def _createUi(self): self.mainLayout = QtGui.QVBoxLayout() label = QtGui.QLabel("<b><font size=\"5\" color='black'>Orca Information</font></b>") self.mainLayout.addWidget(label) self.mainLayout.addSpacing(5) # Layout for the connection controls layoutConnection = QtGui.QHBoxLayout() self.mainLayout.addLayout(layoutConnection) # Connect button self.bConnect = QtGui.QPushButton("Connect") self.bConnect.clicked.connect(self._onbConnectClicked) layoutConnection.addWidget(self.bConnect) layoutConnection.addSpacing(120) # ComboBox for the com ports self.cbComPort = QtGui.QComboBox() for comPort in self.comPorts: self.cbComPort.addItem(comPort) self.cbComPort.currentIndexChanged.connect(self._onComPortChanged) if len(self.comPorts) > 0: self.boardController.set_serial_port(self.comPorts[0]) layoutConnection.addWidget(self.cbComPort) self.mainLayout.addSpacing(20) label = QtGui.QLabel("<b><font color='black'>System.Status</font></b>") self.mainLayout.addWidget(label) # System status label self.systemStatus = StatusLabel() self.mainLayout.addWidget(self.systemStatus) label = QtGui.QLabel("<b><font color='black'>System.Message</font></b>") self.mainLayout.addWidget(label) # System message label self.systemMessage = StatusLabel() self.mainLayout.addWidget(self.systemMessage) # UAV status overview self.uavStatusGadget = UavStatusGadget() self.uavStatusGadget.setMinimumWidth(300) self.uavStatusGadget.setMinimumHeight(250) self.uavStatusGadget.setLinkStatus(False) self.mainLayout.addWidget(self.uavStatusGadget) self.mainLayout.addStretch() self.setLayout(self.mainLayout)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): ''' ShotList MainWindow ''' APPNAME = "shotlist" APPID = "com.LespaceVision.ShotList" __version__ = "1.1.3" # ShotList Column Name define NO = 'No.' THUMB_S = 'Start Frame' THUMB_C = 'Center Frame' THUMB_E = 'End Frame' FILENAME = 'FileName' SCENE = 'Scene' CUT = 'Cut' TAKE = 'Take' COMMENT = 'Comment' CONTAINER = 'Container' CODEC = 'Codec' PIXSIZE = 'Resolution' FILESIZE_GB = 'filesize(GB)' FILESIZE_MB = 'filesize(MB)' REEL = 'Reel' FPS = 'fps' SENSORFPS = 'SensorFps' LENGTH = 'Duration' TC = 'StartTC' BIT = 'bit' ALPHA = 'alpha' COLORSPACE = 'colorspace' GAMMA = 'gamma' AUDIOCH = 'Audio ch' AUDIOSRATE = 'Audio rate' AUDIOCODEC = 'Audio codec' AUDIOBRATE = 'Audio bitrate' CREATETIME = 'Create Time' FULLPATH = 'fullpath' RELPATH = 'relpath' CHECKSUM = 'checksum' CHECKSUM_XXHASH = 'checksum(xxHash)' CHECKSUM_MD5 = 'checksum(MD5)' CHECKSUM_SHA1 = 'checksum(SHA1)' EXINFO = 'Exinfo' # hidden data DIRPATH_HIDDEN = 'base_hidden' FILENAME_HIDDEN = 'name_hidden' SEQPATH_HIDDEN = 'seq_hidden' SEQ_HIDDEN_S = 'seq_hidden_s' SEQ_HIDDEN_C = 'seq_hidden_c' SEQ_HIDDEN_E = 'seq_hidden_e' CHECK_ALGO_SHA1 = "(SHA1)" # RapidCopy cfg.usemd5=0 CHECK_ALGO_MD5 = "(MD5)" # RapidCopy cfg.usemd5=1 CHECK_ALGO_XXHASH = "(xxHash)" # RapidCopy cfg.usemd5=2 #Specification follows RapidCopy.See RapdiCopy source cfg.usemd5... CHECK_ALGO_DICT = { 0: CHECK_ALGO_SHA1, 1: CHECK_ALGO_MD5, 2: CHECK_ALGO_XXHASH } SeqRole = QtCore.Qt.UserRole + 1 #ShotList Column list def_columnlist = [ NO, THUMB_S, THUMB_C, THUMB_E, FILENAME, SCENE, CUT, TAKE, COMMENT, CONTAINER, CODEC, PIXSIZE, FILESIZE_GB, FILESIZE_MB, REEL, FPS, SENSORFPS, LENGTH, TC, BIT, ALPHA, COLORSPACE, GAMMA, AUDIOCH, AUDIOSRATE, AUDIOCODEC, AUDIOBRATE, CREATETIME, FULLPATH, RELPATH, CHECKSUM, EXINFO ] #ShotList no default Column list def_nodefaultlist = [THUMB_S, THUMB_E, CHECKSUM, FILESIZE_MB, SENSORFPS] #ShotList Column defaults data # key=Column name # value = column propetry list # [0]:itemrole method(int) 0:DisplayRole,1:DecorationRole,2:NoRole # [1]:dataset method(int) 0:item.setText,1:item.setData, # [2]:itemflags Qt::ItemFlags(int) 33:select&enable 35:33+edit def_columnpropdict = { NO: [Qt.DisplayRole, 1, 35], THUMB_S: [Qt.DecorationRole, 1, 33], THUMB_C: [Qt.DecorationRole, 1, 33], THUMB_E: [Qt.DecorationRole, 1, 33], FILENAME: [Qt.DisplayRole, 0, 33], SCENE: [Qt.DisplayRole, 0, 35], CUT: [Qt.DisplayRole, 0, 35], TAKE: [Qt.DisplayRole, 0, 35], COMMENT: [Qt.DisplayRole, 0, 35], CONTAINER: [Qt.DisplayRole, 0, 33], CODEC: [Qt.DisplayRole, 0, 33], PIXSIZE: [Qt.DisplayRole, 0, 33], FILESIZE_GB: [Qt.DisplayRole, 0, 33], FILESIZE_MB: [Qt.DisplayRole, 0, 33], REEL: [Qt.DisplayRole, 0, 33], FPS: [Qt.DisplayRole, 0, 33], SENSORFPS: [Qt.DisplayRole, 0, 33], LENGTH: [Qt.DisplayRole, 0, 33], TC: [Qt.DisplayRole, 0, 33], BIT: [Qt.DisplayRole, 0, 33], ALPHA: [Qt.DisplayRole, 0, 33], COLORSPACE: [Qt.DisplayRole, 0, 33], GAMMA: [Qt.DisplayRole, 0, 33], AUDIOCH: [Qt.DisplayRole, 0, 33], AUDIOSRATE: [Qt.DisplayRole, 0, 33], AUDIOCODEC: [Qt.DisplayRole, 0, 33], AUDIOBRATE: [Qt.DisplayRole, 0, 33], CREATETIME: [Qt.DisplayRole, 0, 33], FULLPATH: [Qt.DisplayRole, 0, 33], RELPATH: [Qt.DisplayRole, 0, 33], CHECKSUM: [Qt.DisplayRole, 0, 33], CHECKSUM_XXHASH: [Qt.DisplayRole, 0, 33], CHECKSUM_MD5: [Qt.DisplayRole, 0, 33], CHECKSUM_SHA1: [Qt.DisplayRole, 0, 33], EXINFO: [Qt.DisplayRole, 0, 33], } def_thumb_group = [THUMB_S, THUMB_C, THUMB_E] def_checksum_group = [CHECK_ALGO_MD5, CHECK_ALGO_SHA1, CHECK_ALGO_XXHASH] CORP_INFO = 'LespaceVision' Logdir = "Log" DebugDir = "Debug" msgBox = "" # OPT VALUE OPT_COLUMNLIST = 'SELECTCOLUMNS' OPT_THUMB_X = "THUMB_X" OPT_THUMB_Y = "THUMB_Y" OPT_THUMB_BRIGHT = "THUMB_BRIGHTNESS" OPT_THUMB_OFF_S = "THUMB_OFF_S" OPT_THUMB_OFF_C = "THUMB_OFF_C" OPT_THUMB_OFF_E = "THUMB_OFF_E" OPT_DISABLESEQ = "DISABLE_SEQ" OPT_STAFPS = "STA_FPS" OPT_CHECK_ALGO = "CHECK_ALGO" OPT_EYECATCH = "EYECATCH_PATH" OPT_XLSXOUTTYPE = "XLSX_OTYPE" OPT_XLSXMAXROWS = "XLSX_ROWS" OPT_LCID = "LCID" # OPT DEFAULT THUMB_DEFAULT_X = 176 # Thumbnail X default(16:9) THUMB_DEFAULT_Y = 99 # Thumbnail Y default(16:9) THUMB_DEFALUT_BRIGHT = 1.0 THUMB_DEFAULT_OFF = 0.0 THUMB_DEFAULT_OFF_E = 0.0 / -1 # for "-0.0" DISABLESEQ_DEFAULT = False STAFPS_DEFAULT = 30.0 XLSXOUTTYPE_DEFAULT = 2 # 0=book,1=sheet,2=all XLSXMAXROWS_DEFAULT = 100 LCID_DEFAULT = int(QtCore.QLocale.system().language()) def __init__(self, app): super(MainWindow, self).__init__() self.framegrab = FrameGrabber(self) self.selectedframe = None self.shot = ShotList(self, framegrab=self.framegrab) self.dochome = os.path.join( QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation), self.APPNAME) self.shot.setdochome(self.dochome) if not os.path.exists(self.dochome): os.mkdir(self.dochome) if not os.path.exists(os.path.join(self.dochome, self.Logdir)): os.mkdir(os.path.join(self.dochome, self.Logdir)) self.columnlist = [] self.thumbnail_x = 0 self.thumbnail_y = 0 self.thumbnail_bright = 1.0 self.startoffset = 0.0 self.centeroffset = 0.0 self.endoffset = 0.0 self.stafps = 0.0 self.disableseq = None self.checksumalgo = self.CHECK_ALGO_XXHASH self.eyecatch = "" self.xlsxmaxrows = 0 self.lcid = 0 self.finderpath = None self.previewitem = None self.__readsettings() if (self.lcid == int(QtCore.QLocale.Japanese)): translator = QtCore.QTranslator() translator.load(":/qm/ShotList_ja_JP.qm") app.installTranslator(translator) self.setupUi(self) self.mainToolBar.hide() self.msgBox = QtWidgets.QMessageBox() self.msgBox.setWindowTitle(self.APPNAME) self.msgBox.setIcon(QtWidgets.QMessageBox.Critical) self.timerid = 0 self.dot_count = 0 self.status_label = StatusLabel("") self.main_processing = False self.haserror = False QtCore.QCoreApplication.setOrganizationName(self.CORP_INFO) verstr = "{0} v{1}".format(self.APPNAME, self.__version__) self.setWindowTitle(verstr) QtCore.QCoreApplication.setApplicationName(self.APPNAME) # make temporary directory(PySide2 bug? https://bugreports.qt.io/browse/PYSIDE-884 tempdir = QStandardPaths.writableLocation(QStandardPaths.TempLocation) tempdir = os.path.join(tempdir, self.APPID) if not os.path.isdir(tempdir): os.mkdir(tempdir) self.__initEv() self.lineEdit_SourceDir.setPlaceholderText( self.tr("input Folder path by D&D or src dialog")) def __initEv(self): self.tableWidget_shotlist.setRowCount(0) self.tableWidget_shotlist.setColumnCount(len(self.columnlist)) self.tableWidget_shotlist.setHorizontalHeaderLabels(self.columnlist) self.statusBar.setLayoutDirection(QtCore.Qt.LeftToRight) self.setAcceptDrops(True) self.lineEdit_SourceDir.setAcceptDrops(False) self.tableWidget_shotlist.setShowGrid(True) self.tableWidget_shotlist.setStyleSheet( "QTableWidget::item { padding: 0px }") self.tableWidget_shotlist.setMouseTracking(True) self.tableWidget_shotlist.cellEntered.connect(self.cell_entered) self.pushButton_xlsout.clicked.connect(self.xlsout_clicked) self.pushButton_Input.clicked.connect(self.input_clicked) self.pushButton_import.clicked.connect(self.import_clicked) self.pushButton_shotclear.clicked.connect(self.shotclear_clicked) self.pushButton_reindex.clicked.connect(self.reindex_clicked) self.shot.finished.connect(self.finishThread) self.tableWidget_shotlist.itemClicked.connect(self.item_clicked) self.tableWidget_shotlist.itemDoubleClicked.connect( self.item_doubleclicked) self.tableWidget_shotlist.customContextMenuRequested.connect( self.__menu_opened) # mainSettings connect self.settingdialog = mainSettingDialog(parent=self) self.actionSettings.triggered.connect(self.__mainsetting_triggered) # about connect self.aboutdialog = aboutDialog(parent=self) self.actionAbout_ShotList.triggered.connect(self.__about_triggered) #Thumbnail menu and actions self.thumb_menu = QtWidgets.QMenu() self.action_preview = self.thumb_menu.addAction( self.tr("Select Thumbnail(preview)")) self.action_finder = self.thumb_menu.addAction( self.tr("Open with Finder")) self.action_reindex = self.thumb_menu.addAction( self.tr("Reassign 'No.'")) self.showerrror_area(False) self.pushButton_reindex.setVisible(False) self.dummylabel = QtWidgets.QLabel(" ") self.prog_hlay = QtWidgets.QHBoxLayout(self.progressBar_import) self.prog_hlay.addWidget(self.status_label) self.prog_hlay.setContentsMargins(0, 0, 0, 0) self.progressBar_import.setAlignment(QtCore.Qt.AlignLeft) self.statusBar.addPermanentWidget(self.dummylabel) self.statusBar.addPermanentWidget(self.progressBar_import, 2) self.progressBar_import.setStyleSheet( "QProgressBar::chunk {background-color: paleturquoise;}") self.progressBar_import.setTextVisible(False) return def __readsettings(self): self.cfg = QSettings(self.dochome + "/" + self.APPNAME + ".ini", QSettings.IniFormat) default_columns = self.def_columnlist[:] default_columns.remove(self.THUMB_S) default_columns.remove(self.THUMB_E) default_columns.remove(self.CHECKSUM) default_columns.remove(self.FILESIZE_MB) default_columns.remove(self.SENSORFPS) self.columnlist = self.cfg.value(self.OPT_COLUMNLIST, default_columns) self.thumbnail_x = int( self.cfg.value(self.OPT_THUMB_X, self.THUMB_DEFAULT_X)) self.thumbnail_y = int( self.cfg.value(self.OPT_THUMB_Y, self.THUMB_DEFAULT_Y)) self.thumbnail_bright = float( self.cfg.value(self.OPT_THUMB_BRIGHT, self.THUMB_DEFALUT_BRIGHT)) self.startoffset = float( self.cfg.value(self.OPT_THUMB_OFF_S, self.THUMB_DEFAULT_OFF)) self.centeroffset = float( self.cfg.value(self.OPT_THUMB_OFF_C, self.THUMB_DEFAULT_OFF)) self.endoffset = float( self.cfg.value(self.OPT_THUMB_OFF_E, self.THUMB_DEFAULT_OFF_E)) self.disableseq = self.cfg.value(self.OPT_DISABLESEQ, self.DISABLESEQ_DEFAULT) self.stafps = float( self.cfg.value(self.OPT_STAFPS, self.STAFPS_DEFAULT)) self.checksumalgo = str( self.cfg.value(self.OPT_CHECK_ALGO, self.CHECK_ALGO_XXHASH)) self.eyecatch = str(self.cfg.value(self.OPT_EYECATCH, "")) self.xlsxouttype = int( self.cfg.value(self.OPT_XLSXOUTTYPE, self.XLSXOUTTYPE_DEFAULT)) self.xlsxmaxrows = int( self.cfg.value(self.OPT_XLSXMAXROWS, self.XLSXMAXROWS_DEFAULT)) self.lcid = int(self.cfg.value(self.OPT_LCID, self.LCID_DEFAULT)) return def __writesettings(self): pass def __makelistfromqcombo(self, combobox): itemlist = [] for i in range(combobox.count()): itemlist.append(combobox.itemText(i)) itemlist.reverse() return itemlist def input_clicked(self): dir_path = QFileDialog.getExistingDirectory(self) if not dir_path: return else: self.lineEdit_SourceDir.setText(dir_path) return def import_clicked(self): if self.shot.isRunning(): msgBox = QtWidgets.QMessageBox() msgBox.setIcon(QtWidgets.QMessageBox.Question) msgBox.setText(self.tr("Cancel import?")) msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) self.shot.reqsuspend(True) if (msgBox.exec_() == QtWidgets.QMessageBox.Yes): self.shot.reqcancel(True) self.shot.reqsuspend(False) return elif self.main_processing: self.main_processing = False return ipath = self.lineEdit_SourceDir.text() if not ipath or not os.path.isdir(ipath): msgBox = QtWidgets.QMessageBox() msgBox.setIcon(QtWidgets.QMessageBox.Question) msgBox.setText(self.tr("Please input folder path.")) msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok) msgBox.exec_() return self.textEdit_Result.clear() self.showerrror_area(False) self.tableWidget_shotlist.setSortingEnabled(False) self.tableWidget_shotlist.clearContents() self.tableWidget_shotlist.setColumnCount(len(self.columnlist)) self.tableWidget_shotlist.setHorizontalHeaderLabels(self.columnlist) self.checkedcount = 0 self.shot.reset() self.__setEnabled(False) self.pushButton_xlsout.setEnabled(False) self.shot.setOpt(self.shot.RUNMODE, self.shot.RUNMODE_IMPORT_IMAGES) self.shot.setOpt(self.shot.INPUT_PATH, ipath) self.beginTimer() self.haserror = False self.shot.start() self.progressBar_import.setStyleSheet( "QProgressBar::chunk {background-color: paleturquoise;}") self.pushButton_import.setText(self.tr("Cancel..")) def xlsout_clicked(self): if self.tableWidget_shotlist.rowCount() == 0: return if self.shot.isRunning(): msgBox = QtWidgets.QMessageBox() msgBox.setIcon(QtWidgets.QMessageBox.Question) msgBox.setWindowIcon(QtGui.QIcon(":/ico/" + self.APPNAME + ".ico")) msgBox.setText(self.tr("Cancel xlsxout?")) msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) self.shot.reqsuspend(True) if (msgBox.exec_() == QtWidgets.QMessageBox.Yes): self.shot.reqcancel(True) self.shot.reqsuspend(False) return suffix_name = "" deskpath = QStandardPaths.writableLocation( QStandardPaths.DesktopLocation) writablepath = deskpath + os.sep if self.shot.optdict[self.shot.INPUT_PATH]: # print(os.path.split(self.shot.optdict[self.shot.INPUT_PATH])[1]) suffix_name = os.path.split( self.shot.optdict[self.shot.INPUT_PATH])[1] + "_" # call multi xlsx files output if self.xlsxouttype == 0: dstpaths = [] # prepare "all" xlsx filename # damn sandbox file output security.... # defaultfilename = suffix_name + ".xlsx" rowcount = self.tableWidget_shotlist.rowCount() prev_index = 1 if rowcount < self.xlsxmaxrows: next_index = rowcount else: next_index = self.xlsxmaxrows if rowcount % self.xlsxmaxrows == 0: total_fileno = rowcount / self.xlsxmaxrows else: total_fileno = math.ceil(rowcount / self.xlsxmaxrows) cur_fileno = 1 for i in range(rowcount): if i != 0 and (i + 1) % self.xlsxmaxrows == 0: filename = suffix_name + "{0}_{1}".format( prev_index, next_index) + ".xlsx" writablepath = writablepath + filename dstpath = QFileDialog.getSaveFileName( self, self.tr("Save xlsx({0}/{1})").format( cur_fileno, total_fileno), writablepath)[0] if dstpath: dstpaths.append(dstpath) else: return cur_fileno += 1 prev_index = prev_index + self.xlsxmaxrows if next_index + self.xlsxmaxrows < rowcount: next_index = next_index + self.xlsxmaxrows else: next_index = rowcount writablepath = os.path.split(dstpath)[0] + os.sep elif i == rowcount - 1: filename = suffix_name + "{0}_{1}".format( prev_index, next_index) + ".xlsx" writablepath = writablepath + filename dstpath = QFileDialog.getSaveFileName( self, self.tr("Save xlsx({0}/{1})").format( cur_fileno, total_fileno), writablepath)[0] if dstpath: dstpaths.append(dstpath) else: return else: defaultfilename = suffix_name + ".xlsx" savedialog = QFileDialog() writablepath = writablepath + defaultfilename dstpaths = QFileDialog.getSaveFileName(self, self.tr("Save xlsx"), writablepath)[0] # cancel if not dstpaths: return self.progressBar_import.setStyleSheet( "QProgressBar::chunk {background-color: paleturquoise;}") self.__prepare_xlsxout(dstpaths) self.__setEnabled(False) self.pushButton_import.setEnabled(False) self.beginTimer() self.haserror = False self.shot.start() self.pushButton_xlsout.setText(self.tr("Cancel..")) def shotclear_clicked(self): self.textEdit_Result.clear() def reindex_clicked(self): if self.tableWidget_shotlist.rowCount() == 0: return elif self.shot.isRunning(): return msgBox = QtWidgets.QMessageBox() msgBox.setIcon(QtWidgets.QMessageBox.Question) msgBox.setText( self.tr("'No.' columns value will reassign. Are you sure?")) msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if (msgBox.exec_() == QtWidgets.QMessageBox.No): return for j in range(self.tableWidget_shotlist.columnCount()): if self.tableWidget_shotlist.horizontalHeaderItem( j).text() == self.NO: for i in range(self.tableWidget_shotlist.rowCount()): item = self.tableWidget_shotlist.takeItem(i, j) item.setData(QtCore.Qt.DisplayRole, i + 1) self.tableWidget_shotlist.setItem(i, j, item) # print(item.data(QtCore.Qt.DisplayRole)) msgBox.setIcon(QtWidgets.QMessageBox.Information) msgBox.setText(self.tr("'No.' columns reassigned complete.")) msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes) msgBox.exec_() def cell_entered(self, x, y): item = self.tableWidget_shotlist.item(x, y) datadict = item.data(Qt.UserRole) if datadict: self.finderpath = datadict[self.DIRPATH_HIDDEN] self.previewitem = item else: self.finderpath = None self.previewitem = None def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): url = event.mimeData().urls()[0] path = url.toLocalFile() if (path[-1:] == "/"): path = path[:-1] if not os.path.isdir(path): self.status_label.setText( self.tr("Error:path is file. Plz input folder. path={0}"). format(path)) return self.lineEdit_SourceDir.setText(path) def closeEvent(self, cevent): if not self.shot.isRunning() or self.shot.isFinished(): cevent.accept() else: msgBox = QtWidgets.QMessageBox() msgBox.setIcon(QtWidgets.QMessageBox.Warning) msgBox.setWindowIcon(QtGui.QIcon(":/ico/" + self.APPNAME + ".ico")) msgBox.setText(self.tr("ShotList is running")) msgBox.setInformativeText( self.tr("Can't close ShotList while current task.")) msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok) msgBox.exec_() cevent.ignore() def timerEvent(self, tevent): if (tevent.timerId() == self.timerid and self.shot.message): self.progressBar_import.setMaximum(self.shot.totalseqno) self.progressBar_import.setValue(self.shot.currentseqno) replstr = self.shot.message dotstr = "" for i in range(0, self.dot_count): dotstr += "." self.status_label.setText(replstr + dotstr) self.dot_count += 1 if (self.dot_count == 4): self.dot_count = 0 # did not take Lock but maybe no problem. if len((self.shot.errmessages)): self.showerrror_area(True) self.progressBar_import.setStyleSheet( "QProgressBar::chunk {background-color: orange;}") self.haserror = True for i in range(len(self.shot.errmessages)): self.textEdit_Result.append(self.shot.errmessages[i]) self.shot.errmessages.clear() def beginTimer(self): self.timerid = QObject.startTimer(self, 1000) # @QtCore.Slot() def stopTimer(self): self.status_label.clear() QObject.killTimer(self, self.timerid) @QtCore.Slot() def beginTimer(self): self.timerid = QObject.startTimer(self, 1000) @QtCore.Slot() def stopTimer(self): QObject.killTimer(self, self.timerid) @QtCore.Slot(str) def finishThread(self): self.main_processing = True self.stopTimer() # Output error message when exists if len((self.shot.errmessages)): self.showerrror_area(True) for i in range(len(self.shot.errmessages)): self.textEdit_Result.append(self.shot.errmessages[i]) # Import image if self.shot.optdict[ self.shot.RUNMODE] == self.shot.RUNMODE_IMPORT_IMAGES: if self.shot.req_cancel: self.status_label.setText(self.tr("import canceled.")) self.tableWidget_shotlist.clearContents() self.tableWidget_shotlist.setRowCount(0) else: if len(self.shot.inputresultlist): self.__setrecord(self.shot.inputresultlist) self.fitcolumns() else: errstr = self.tr("No shot(s).") self.textEdit_Result.append(errstr) self.msgBox.setText(errstr) self.msgBox.setIcon(QtWidgets.QMessageBox.Information) self.msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok) self.msgBox.exec_() self.label_preview.setText(self.tr("No shot(s).")) self.status_label.setText(self.tr("Import finished")) if self.haserror: self.progressBar_import.setStyleSheet( "QProgressBar::chunk {background-color: orange;}") else: self.progressBar_import.setStyleSheet( "QProgressBar::chunk {background-color: lightgreen;}") # xlsx output else: if self.shot.req_cancel: # xlsx output canceled. self.status_label.setText(self.tr("xlsx out canceled")) else: # xlsx output finished self.status_label.setText(self.tr("xlsx out finished")) self.textEdit_Result.append( self.tr("xlsx out finished. out path = {0}".format( self.shot.optdict[self.shot.OUTPUT_PATH]))) self.msgBox.setText(self.tr("xlsx out finished.")) if self.xlsxouttype == 0: self.msgBox.setInformativeText( self.tr("xlsx out finished.")) else: self.msgBox.setInformativeText( self.tr("xlsx out finished. out path = {0}".format( self.shot.optdict[self.shot.OUTPUT_PATH]))) self.msgBox.setIcon(QtWidgets.QMessageBox.Information) self.msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok) self.msgBox.exec_() self.progressBar_import.setStyleSheet( "QProgressBar::chunk {background-color: lightgreen;}") self.progressBar_import.setValue(self.progressBar_import.maximum()) # enable mainwindows buttons. self.__setEnabled(True) self.pushButton_import.setEnabled(True) self.pushButton_xlsout.setEnabled(True) self.main_processing = False self.pushButton_import.setText(self.tr("Import")) self.pushButton_xlsout.setText(self.tr("xlsx output")) self.shot.reqsuspend(False) self.shot.reqcancel(False) self.msgBox.setInformativeText("") @QtCore.Slot() def item_clicked(self, item): pass @QtCore.Slot() def item_doubleclicked(self, item): columnname = self.tableWidget_shotlist.horizontalHeaderItem( item.column()).text() if (columnname in self.def_thumb_group): itemdict = self.tableWidget_shotlist.item( item.row(), item.column()).data(Qt.UserRole) ext = os.path.splitext(itemdict[self.FILENAME_HIDDEN])[1].lower() if ext in self.shot.SUPPORT_MOVIMAGES: # QtWidgets.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(fullpath)) fullpath = os.path.join(itemdict[self.DIRPATH_HIDDEN], itemdict[self.FILENAME_HIDDEN]) previewdialog = VideoPlayerDialog(parent=self, path=fullpath) if columnname == self.THUMB_C: previewdialog.set_slider(1) elif columnname == self.THUMB_E: previewdialog.set_slider(2) else: pass elif ext in self.shot.SUPPORT_STAIMAGES: filelist = [] # save memory usage. reconstruct fullpath... for filename in itemdict[self.SEQPATH_HIDDEN]: filelist.append( os.path.join(itemdict[self.DIRPATH_HIDDEN], filename)) seq = pyseq.Sequence(filelist) previewdialog = SequencePlayerDialog(parent=self, seq=seq) end = seq.end() start = seq.start() length = seq.end() - seq.start() if columnname == self.THUMB_S: previewdialog.slider_changed(start) elif columnname == self.THUMB_C: previewdialog.slider_changed(start + (length / 2)) elif columnname == self.THUMB_E: previewdialog.slider_changed(end) else: pass else: return if previewdialog.exec_() == QtWidgets.QDialog.Accepted: xy = self.shot.resize_xandy(self.selectedframe.width(), self.selectedframe.height()) self.selectedframe = self.selectedframe.scaled( xy[0], xy[1], Qt.KeepAspectRatio, Qt.SmoothTransformation) item.setData(QtCore.Qt.DecorationRole, self.selectedframe) @QtCore.Slot() def __mainsetting_triggered(self): if self.settingdialog.exec_() == QtWidgets.QDialog.Accepted: self.fitcolumns() @QtCore.Slot() def __about_triggered(self): self.aboutdialog.exec_() def __menu_opened(self, position): action = self.thumb_menu.exec_( self.tableWidget_shotlist.mapToGlobal(position)) if action == self.action_finder: # self.finderpath set by cell_entered SLOT if self.finderpath: QDesktopServices.openUrl("file:///" + self.finderpath) elif action == self.action_preview: if self.previewitem: self.item_doubleclicked(self.previewitem) elif action == self.action_reindex: self.reindex_clicked() else: pass def __setrecord(self, resultlist): self.tableWidget_shotlist.setRowCount(len(resultlist)) for i, rec in enumerate(resultlist): self.status_label.setText( self.tr("Setting Rows({0}/{1})").format(i, len(resultlist))) # check cancel if self.shot.req_cancel or self.main_processing is False: self.status_label.setText(self.tr("import canceled.")) self.tableWidget_shotlist.clearContents() self.tableWidget_shotlist.setRowCount(0) return False else: self.status_label.setText( self.tr("set record {0}/{1}".format(i, len(resultlist)))) for j in range(self.tableWidget_shotlist.columnCount()): columnname = self.tableWidget_shotlist.horizontalHeaderItem( j).text() item = QtWidgets.QTableWidgetItem() declist = self.def_columnpropdict[columnname] if declist[1]: if columnname in self.def_thumb_group: if isinstance(rec[columnname], str): item.setText(rec[columnname]) else: qimage = QtGui.QPixmap.fromImage(rec[columnname]) item.setData(declist[0], qimage) self.tableWidget_shotlist.setRowHeight( i, qimage.height() + 5) itemdict = {} itemdict[self.DIRPATH_HIDDEN] = rec[ self.DIRPATH_HIDDEN] itemdict[self.FILENAME_HIDDEN] = rec[ self.FILENAME_HIDDEN] if rec[self.SEQPATH_HIDDEN]: itemdict[self.SEQPATH_HIDDEN] = rec[ self.SEQPATH_HIDDEN] if columnname == self.THUMB_S and rec[ self.SEQ_HIDDEN_S]: item.setData(self.SeqRole, rec[self.SEQ_HIDDEN_S]) elif columnname == self.THUMB_C and rec[ self.SEQ_HIDDEN_C]: item.setData(self.SeqRole, rec[self.SEQ_HIDDEN_C]) elif columnname == self.THUMB_E and rec[ self.SEQ_HIDDEN_E]: item.setData(self.SeqRole, rec[self.SEQ_HIDDEN_E]) else: pass else: pass item.setData(Qt.UserRole, itemdict) else: item.setData(declist[0], rec[columnname]) else: item.setText(str(rec[columnname])) if declist[2] == 33: item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) elif declist[2] == 35: item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsEnabled) else: pass # item.setFlags(declist[2]) self.tableWidget_shotlist.setItem(i, j, item) for j in range(self.tableWidget_shotlist.columnCount()): if self.tableWidget_shotlist.horizontalHeaderItem( j).text() == self.CHECKSUM: checksum_item = self.tableWidget_shotlist.horizontalHeaderItem( j) checksum_item.setText(checksum_item.text() + self.checksumalgo) self.label_preview.setText( self.tr("{0} shots total".format(len(resultlist)))) return True def __setEnabled(self, req_bool): self.pushButton_Input.setEnabled(req_bool) self.tableWidget_shotlist.setEnabled(req_bool) self.pushButton_reindex.setEnabled(req_bool) def __setColortoRow(self, table, rowIndex, color): for j in range(table.columnCount()): table.item(rowIndex, j).setBackground(color) # output process running on execute thread,so prepare for xlsx output. def __prepare_xlsxout(self, outpaths): # We do what we can only operate on the main thread. # Throw real out to a thread if not self.tableWidget_shotlist.rowCount: return tablelist = [] for i in range(self.tableWidget_shotlist.rowCount()): self.status_label.setText( self.tr("xlsx preparing Rows({0}/{1})").format( i, self.tableWidget_shotlist.rowCount())) row_list_rec = [] for j in range(self.tableWidget_shotlist.columnCount()): if self.tableWidget_shotlist.horizontalHeaderItem(j).text() in self.def_thumb_group\ and self.tableWidget_shotlist.item(i,j).data(QtCore.Qt.DecorationRole): row_list_rec.append( self.tableWidget_shotlist.item(i, j).data( QtCore.Qt.DecorationRole)) else: row_list_rec.append( self.tableWidget_shotlist.item(i, j).text()) tablelist.append(row_list_rec) # checksum type string add. for i, columnname in enumerate(self.columnlist): if columnname == self.CHECKSUM: self.columnlist[i] = self.columnlist[i] + self.checksumalgo self.shot.setOpt(self.shot.OUTPUT_COLUMNS, self.columnlist) self.shot.setOpt(self.shot.OUTPUT_ROWS, tablelist) # xlsx output path set self.shot.setOpt(self.shot.RUNMODE, self.shot.RUNMODE_OUT_XLSX) self.shot.setOpt(self.shot.OPT_XLSXOUTTYPE, self.xlsxouttype) self.shot.setOpt(self.shot.OPT_XLSXMAXROWS, self.xlsxmaxrows) self.shot.setOpt(self.shot.OUTPUT_PATH, outpaths) def fitcolumns(self): self.tableWidget_shotlist.resizeColumnToContents(0) self.tableWidget_shotlist.resizeColumnsToContents() self.tableWidget_shotlist.setSortingEnabled(True) self.tableWidget_shotlist.sortByColumn(0, QtCore.Qt.AscendingOrder) self.tableWidget_shotlist.clearSelection() #self.tableWidget_shotlist.resizeRowsToContents() def showerrror_area(self, isvisible): self.label_log.setVisible(isvisible) self.textEdit_Result.setVisible(isvisible) self.pushButton_shotclear.setVisible(isvisible)
def __init__(self, app): super(MainWindow, self).__init__() self.framegrab = FrameGrabber(self) self.selectedframe = None self.shot = ShotList(self, framegrab=self.framegrab) self.dochome = os.path.join( QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation), self.APPNAME) self.shot.setdochome(self.dochome) if not os.path.exists(self.dochome): os.mkdir(self.dochome) if not os.path.exists(os.path.join(self.dochome, self.Logdir)): os.mkdir(os.path.join(self.dochome, self.Logdir)) self.columnlist = [] self.thumbnail_x = 0 self.thumbnail_y = 0 self.thumbnail_bright = 1.0 self.startoffset = 0.0 self.centeroffset = 0.0 self.endoffset = 0.0 self.stafps = 0.0 self.disableseq = None self.checksumalgo = self.CHECK_ALGO_XXHASH self.eyecatch = "" self.xlsxmaxrows = 0 self.lcid = 0 self.finderpath = None self.previewitem = None self.__readsettings() if (self.lcid == int(QtCore.QLocale.Japanese)): translator = QtCore.QTranslator() translator.load(":/qm/ShotList_ja_JP.qm") app.installTranslator(translator) self.setupUi(self) self.mainToolBar.hide() self.msgBox = QtWidgets.QMessageBox() self.msgBox.setWindowTitle(self.APPNAME) self.msgBox.setIcon(QtWidgets.QMessageBox.Critical) self.timerid = 0 self.dot_count = 0 self.status_label = StatusLabel("") self.main_processing = False self.haserror = False QtCore.QCoreApplication.setOrganizationName(self.CORP_INFO) verstr = "{0} v{1}".format(self.APPNAME, self.__version__) self.setWindowTitle(verstr) QtCore.QCoreApplication.setApplicationName(self.APPNAME) # make temporary directory(PySide2 bug? https://bugreports.qt.io/browse/PYSIDE-884 tempdir = QStandardPaths.writableLocation(QStandardPaths.TempLocation) tempdir = os.path.join(tempdir, self.APPID) if not os.path.isdir(tempdir): os.mkdir(tempdir) self.__initEv() self.lineEdit_SourceDir.setPlaceholderText( self.tr("input Folder path by D&D or src dialog"))
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.mainToolBar.hide() #self.rpack = RapidPack(self) self.appname = 'DeadlineCalc' self.calc = DeadLineCalc(self) self.msgBox = QtGui.QMessageBox() self.msgBox.setWindowTitle(self.appname) self.msgBox.setIcon(QtGui.QMessageBox.Critical) self.checkedcount = 0 #ジョブリスト中のチェックされてるジョブの数 if not self.calc.connectServer(): # QMessageBoxかなんか出してやるかあ # print("Can't Connect Deadline Server.") errstr = "Can't Connect Deadline Server." self.msgBox.setText(errstr) self.msgBox.setInformativeText(self.calc.errmessage) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() sys.exit(-1) # 先にユーザ一覧取得しちゃおうかなー。 # if not self.calc.getUserandProject(): # print("getUserandProject()") errstr = "Error: getUserandProject() Failed." self.msgBox.setText(errstr) self.msgBox.setInformativeText(self.calc.errmessage) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() sys.exit(-1) #self.aboutdialog.__init__("aaa") QSettings.setDefaultFormat(QSettings.NativeFormat) QtCore.QCoreApplication.setOrganizationName(self.CORP_INFO) self.timerid = 0 self.dot_count = 0 self.status_label = StatusLabel("") self.early_subdate = 0 # calc期間のもっとも早い送信日時 self.late_enddate = 0 # calc期間のもっとも遅い終了日時 #面倒だから内部ver表記でいいやあ verstr = "{0} v{1}".format(self.appname,self.__version__) self.setWindowTitle(verstr) QtCore.QCoreApplication.setApplicationName(self.appname) # Log保存用フォルダ作成 # if (sysisWindows): # # try: # self.dochome = os.path.join(get_path(FOLDERID.Documents, user_handle=None), self.appname) # # except PathNotFoundException as patherr: # # # os.sys.exit(-1) # # print(self.dochome) # else: # self.dochome = os.path.join(os.path.expanduser('~/Documents'), self.appname) # if not os.path.exists(self.dochome): # os.mkdir(self.dochome) # # if not os.path.exists(os.path.join(self.dochome,self.Logdir)): # os.mkdir(os.path.join(self.dochome,self.Logdir)) # # #self.rpack.setdochome(self.dochome) # # #self.cfg = QSettings() # self.cfg = QSettings(self.dochome + "/" + self.appname + ".ini",QSettings.IniFormat) #self.plainTextEdit_jobID self.__initEv() self.__readsettings()
class MainWindow(QtGui.QMainWindow,Ui_MainWindow): ''' deadlinecalc メインウインドウ ''' __version__ = "1.1.3" CORP_INFO = 'LespaceVision' OPT_PRJLASTHIST = 'lastprj' # 最後に使用した案件名文字列 OPT_PRJHIST = 'histprj' # 直近10個くらいまでの案件名文字列 OPT_LOGMODE = 'logmode' # True=Log取得する,False=Log取得しない OPT_DEBUGMODE = 'debugmode' # True=デバッグログ取得する,False=デバッグログ取得しない Logdir = "Log" DebugDir = "Debug" msgBox = "" def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.mainToolBar.hide() #self.rpack = RapidPack(self) self.appname = 'DeadlineCalc' self.calc = DeadLineCalc(self) self.msgBox = QtGui.QMessageBox() self.msgBox.setWindowTitle(self.appname) self.msgBox.setIcon(QtGui.QMessageBox.Critical) self.checkedcount = 0 #ジョブリスト中のチェックされてるジョブの数 if not self.calc.connectServer(): # QMessageBoxかなんか出してやるかあ # print("Can't Connect Deadline Server.") errstr = "Can't Connect Deadline Server." self.msgBox.setText(errstr) self.msgBox.setInformativeText(self.calc.errmessage) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() sys.exit(-1) # 先にユーザ一覧取得しちゃおうかなー。 # if not self.calc.getUserandProject(): # print("getUserandProject()") errstr = "Error: getUserandProject() Failed." self.msgBox.setText(errstr) self.msgBox.setInformativeText(self.calc.errmessage) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() sys.exit(-1) #self.aboutdialog.__init__("aaa") QSettings.setDefaultFormat(QSettings.NativeFormat) QtCore.QCoreApplication.setOrganizationName(self.CORP_INFO) self.timerid = 0 self.dot_count = 0 self.status_label = StatusLabel("") self.early_subdate = 0 # calc期間のもっとも早い送信日時 self.late_enddate = 0 # calc期間のもっとも遅い終了日時 #面倒だから内部ver表記でいいやあ verstr = "{0} v{1}".format(self.appname,self.__version__) self.setWindowTitle(verstr) QtCore.QCoreApplication.setApplicationName(self.appname) # Log保存用フォルダ作成 # if (sysisWindows): # # try: # self.dochome = os.path.join(get_path(FOLDERID.Documents, user_handle=None), self.appname) # # except PathNotFoundException as patherr: # # # os.sys.exit(-1) # # print(self.dochome) # else: # self.dochome = os.path.join(os.path.expanduser('~/Documents'), self.appname) # if not os.path.exists(self.dochome): # os.mkdir(self.dochome) # # if not os.path.exists(os.path.join(self.dochome,self.Logdir)): # os.mkdir(os.path.join(self.dochome,self.Logdir)) # # #self.rpack.setdochome(self.dochome) # # #self.cfg = QSettings() # self.cfg = QSettings(self.dochome + "/" + self.appname + ".ini",QSettings.IniFormat) #self.plainTextEdit_jobID self.__initEv() self.__readsettings() def __initEv(self): self.statusBar.setLayoutDirection(QtCore.Qt.RightToLeft) self.statusBar.setSizeGripEnabled(False) self.statusBar.addPermanentWidget(self.status_label) # comboboxのプルダウンリストのmaxを増やすよん self.comboBox_UserName.setMaxVisibleItems(50) self.comboBox_ProjectName.setMaxVisibleItems(50) self.pushButton_Search.clicked.connect(self.search_clicked) self.pushButton_Calc.clicked.connect(self.calc_clicked) self.pushButton_Reloaduser.clicked.connect(self.reload_clicked) self.pushButton_calcclear.clicked.connect(self.calcclear_clicked) self.pushButton_csvout.clicked.connect(self.csvout_clicked) self.calc.finished.connect(self.finishThread) self.tableWidget_jobList.clearContents() self.tableWidget_jobList.itemClicked.connect(self.job_clicked) self.tableWidget_jobList.itemDoubleClicked.connect(self.job_doubleclicked) return def __readsettings(self): # 検索範囲時刻の初期値設定 # とりあえず直近1カ月範囲? # 開始時刻は現在時刻より1カ月前 defaultstartdate = QDateTime.currentDateTime() lastmonth = defaultstartdate.addMonths(-1) self.dateTimeEdit_start.setDateTime(lastmonth) #終了時刻はなう self.dateTimeEdit_end.setDateTime(defaultstartdate) self.reload_clicked() # iniから前回設定読み出して自動選択とかをこの辺にそのうち # とりあえず空にしとくか self.comboBox_UserName.clearEditText() self.comboBox_ProjectName.clearEditText() self.tableWidget_jobList.setRowCount(0) # Commentとか直接使用しない列もあるから、列増えるたびに要調整。。 self.tableWidget_jobList.setColumnCount(16) #QDateTime to ISODate String.... #print(defaultstartdate.toString(QtCore.Qt.ISODate)) return def __writesettings(self): pass def __makelistfromqcombo(self,combobox): itemlist = [] for i in range(combobox.count()): itemlist.append(combobox.itemText(i)) itemlist.reverse() return itemlist # jobサーチ開始 def search_clicked(self): #print("search_clicked") # if self.dateTimeEdit_start # if self.dateTimeEdit_end # 増えてきたら何がしかリセット関数にまとめないとダメかもなあ。 self.tableWidget_jobList.setSortingEnabled(False) self.tableWidget_jobList.clearContents() self.checkedcount = 0 self.calc.reset() #beforedate #QDateTime -> ISO8601String -> python datetime beforedate = dateutil.parser.parse(self.dateTimeEdit_start.dateTime().toString(QtCore.Qt.ISODate)) enddate = dateutil.parser.parse(self.dateTimeEdit_end.dateTime().toString(QtCore.Qt.ISODate)) # チェック範囲矛盾? if(beforedate > enddate): #エラー処理はそのうち良い感じに errstr = "Invalid date.\nbefore = " + str(beforedate) + "\nend = " + str(enddate) self.msgBox.setText(errstr) #self.msgBox.setInformativeText(self.calc.errmessage) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() return self.__setEnabled(False) self.calc.setOpt(self.calc.STARTDATE,beforedate) self.calc.setOpt(self.calc.ENDDATE,enddate) if self.tabWidget_Comannds.currentIndex(): # ジョブID指定モードだね self.calc.setOpt(self.calc.RUNMODE, self.calc.RUNMODE_SEARCH_JOBID) #idlist = str(self.plainTextEdit_jobID.toPlainText()).split(u'2029') idlist = str(self.plainTextEdit_jobID.toPlainText()).split('\n') #pp.pprint(idlist) self.calc.setOpt(self.calc.JOBIDS, idlist) else: self.calc.setOpt(self.calc.RUNMODE, self.calc.RUNMODE_SEARCH_INQ) if self.comboBox_UserName.currentText(): self.calc.setOpt(self.calc.USER_NAME,str(self.comboBox_UserName.currentText())) # else: # self.calc.setOpt(self.calc.USER_NAME,u"") if self.comboBox_ProjectName.currentText(): self.calc.setOpt(self.calc.PROJ_NAME,str(self.comboBox_ProjectName.currentText())) self.beginTimer() self.calc.start() return # 単価計算開始 def calc_clicked(self): #print("calc_clicked") if self.tableWidget_jobList.rowCount() == 0: return # 係数値を拾うよん。未入力=1として扱う。 if self.lineEdit_keisuu.text(): try: keisuu = float(self.lineEdit_keisuu.text()) except Exception as ex: errstr = "Error:Invalid Value.\n" + str(ex) self.msgBox.setText(errstr) # self.msgBox.setInformativeText(self.calc.errmessage) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() return self.calc.setOpt(self.calc.CALC_KEISUU, keisuu) # 実働時間算出用の日時情報をリセット self.early_subdate = datetime.datetime(2100,12,31,23,59,59) self.late_enddate = datetime.datetime(1970,1,1) calc_list = [] # (jobid,コンカレントタスク数,チャンク数)のタプルのリスト userdict = {} # プロジェクト名指定検索の時、関連するユーザを出力するための辞書 for i in range(self.tableWidget_jobList.rowCount()): item = self.tableWidget_jobList.item(i,0) if item.checkState() == QtCore.Qt.Checked: jobid = self.tableWidget_jobList.item(i, 1).text() conc_task = int(self.tableWidget_jobList.item(i, 11).text()) chunk = int(self.tableWidget_jobList.item(i,12).text()) # プロジェクト範囲抽出を受けた時に関連ユーザ出すためにユーザ名だけこっそり抽出しておく username = str(self.tableWidget_jobList.item(i, 2).text()).split('_')[0] userdict[username] = username #key重複は上書き # print(item.text()) wk_tuple = (jobid, conc_task, chunk) calc_list.append(wk_tuple) #v110 実働時間算出のため、すべての選択済みジョブの送信日時の一番早い時刻と終了時刻の一番遅い時刻を決定する wk_subdate = dateutil.parser.parse(self.tableWidget_jobList.item(i,5).text()).replace(tzinfo=None) if self.early_subdate > wk_subdate: self.early_subdate = wk_subdate wk_enddate = dateutil.parser.parse(self.tableWidget_jobList.item(i,6).text()).replace(tzinfo=None) if self.late_enddate < wk_enddate: self.late_enddate = wk_enddate # else: # print("no check is " + str(self.tableWidget_jobList.item(i,0).text())) self.calc.setOpt(self.calc.JOBID_CONTASKS,calc_list) # サーチする時にプロジェクト名指定でサーチした? if self.calc.optdict.get(self.calc.PROJ_NAME): # 関連ユーザ抽出用に最終出力結果にユーザ一覧辞書を渡しておく self.calc.setOpt(self.calc.CALC_PROJUSER,userdict) self.calc.setOpt(self.calc.RUNMODE, self.calc.RUNMODE_CALC) #pp.pprint(wk_list) self.__setEnabled(False) self.beginTimer() self.calc.start() return def reload_clicked(self): # 通信失敗? if not self.calc.getUserandProject(): #reload諦めよっと errstr = "Error: getUserandProject() Failed." self.msgBox.setText(errstr) self.msgBox.setInformativeText(self.calc.errmessage) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() sys.exit(-1) # 一回全部中身クリアする self.comboBox_UserName.clear() self.comboBox_ProjectName.clear() # ユーザ名とプロジェクト名一覧を設定 # ユーザ名 wk_list = [] for key in self.calc.userdict: wk_list.append(key) # ABCそーとしよっと wk_list.sort() # ABCそーと順でコンボボックスに追加しよっと for user in wk_list: self.comboBox_UserName.addItem(user) wk_list[:] = [] # プロジェクト名 for key in self.calc.projdict: wk_list.append(key) # ABCそーとしよっと wk_list.sort() for project in wk_list: self.comboBox_ProjectName.addItem(project) self.comboBox_ProjectName.clearEditText() self.comboBox_UserName.clearEditText() self.status_label.setText("User and Project Reloaded.") # def closeEvent(self,cevent): # # if not self.rpack.isRunning() or self.rpack.isFinished(): # self.__writesettings() # cevent.accept() # else: # msgBox = QtGui.QMessageBox() # msgBox.setIcon(QtGui.QMessageBox.Warning) # msgBox.setWindowIcon(QtGui.QIcon(":/ico/" + self.appname + ".ico")) # msgBox.setText(self.tr("RapidPack is running")) # msgBox.setInformativeText(self.tr("Can't close RapidPack while pack end.")) # msgBox.setStandardButtons(QtGui.QMessageBox.Ok) # msgBox.exec_() # cevent.ignore() def calcclear_clicked(self): self.textEdit_Result.clear() def csvout_clicked(self): if self.tableWidget_jobList.rowCount() == 0: return dstdialog = QtGui.QFileDialog(self) dstdialog.setFileMode(QtGui.QFileDialog.AnyFile) dstdialog.setAcceptMode(QtGui.QFileDialog.AcceptSave) dt = QDateTime.currentDateTime() # prefix_name = self.appname # prefix_name += "_" prefix_name = dt.toString("yyyyMMddhhmmss") prefix_name += ".csv" writablepath = os.path.expanduser('~') + os.sep writablepath += prefix_name # print(writablepath) dststr = dstdialog.getSaveFileName( self, self.tr("input output filename."), writablepath ) if not dststr[0]: return #print(dststr) self.__csvout(dststr) infostr = "CSV output finished." self.msgBox.setText(infostr) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.setIcon(QtGui.QMessageBox.Information) self.msgBox.exec_() self.msgBox.setIcon(QtGui.QMessageBox.Warning) def timerEvent(self,tevent): #print("timer! tevent = {0} selftimerid = {1}".format(tevent.timerId(),) if(tevent.timerId() == self.timerid and self.calc.message): replstr = self.calc.message dotstr = "" for i in range(0,self.dot_count): dotstr += "." self.status_label.setText(replstr + dotstr) if self.calc.errmessage: self.textEdit_Result.append(self.calc.errmessage) self.calc.errmessage = "" self.dot_count += 1 if(self.dot_count == 4): self.dot_count = 0 # def eventFilter(self,widget,event): # if(event.type() == QtCore.QEvent.KeyPress): # if(widget is self.comboBox_SourceDir): # #print("source combo ignore") # return True # elif(widget is self.comboBox_OutputPath): # #print("output combo ignore") # return True # elif(widget is self.textEdit_ignorefolders): # #print("ignore folders ignore") # return True # # return super(MainWindow,self).eventFilter(widget,event) # @QtCore.Slot() def beginTimer(self): self.timerid = QObject.startTimer(self,1000) # print("begin timerid = {0}".format(self.timerid)) # @QtCore.Slot() def stopTimer(self): # print("stop timerid = {0}".format(self.timerid)) self.status_label.clear() QObject.killTimer(self,self.timerid) @QtCore.Slot() def beginTimer(self): self.timerid = QObject.startTimer(self,1000) # print("begin timerid = {0}".format(self.timerid)) @QtCore.Slot() def stopTimer(self): # print("stop timerid = {0}".format(self.timerid)) QObject.killTimer(self,self.timerid) @QtCore.Slot(str) def finishThread(self): self.stopTimer() # なんかエラーっぽいメッセージあったらとりあえず出力 if self.calc.errmessage: self.textEdit_Result.append(self.calc.errmessage) self.calc.errmessage = "" # 処理内容ごとにあちこち振り分けかなー # レコードサーチの場合 if self.calc.optdict[self.calc.RUNMODE] == self.calc.RUNMODE_SEARCH_INQ \ or self.calc.optdict[self.calc.RUNMODE] == self.calc.RUNMODE_SEARCH_JOBID: # なんか1レコードでもあった? if len(self.calc.searchresultlist): self.__setrecord(self.calc.searchresultlist) self.__fitcolumns() else: # レコード0の時はメッセージ出したろかな。。 errstr = "There are no jobs." self.msgBox.setText(errstr) self.msgBox.setIcon(QtGui.QMessageBox.Information) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() self.msgBox.setIcon(QtGui.QMessageBox.Warning) # self.label_job.setText("There are no jobs.") self.label_jobs.setText("There are no jobs.") self.status_label.setText('Search finished.') else: # 計算modeの場合は結果を出力 # 各ジョブごとの金額をリストに反映 for i in range(self.tableWidget_jobList.rowCount()): checkitem = self.tableWidget_jobList.item(i,0) jobid = self.tableWidget_jobList.item(i,1).text() # print(str(self.tableWidget_jobList.columnCount())) # 計算対象かつ、指定ジョブIDがキーとして存在するか if checkitem.checkState() == QtCore.Qt.Checked and \ jobid in self.calc.calcjobresultdict: # item = QtGui.QTableWidgetItem(str(int(self.calc.calcjobresultdict[jobid]))) item = self.tableWidget_jobList.item(i, self.tableWidget_jobList.columnCount() - 2) item.setText(self.calc.calcjobresultdict[jobid]['TotalTaskTime']) item = self.tableWidget_jobList.item(i,self.tableWidget_jobList.columnCount() - 1) item.setText(str(int(self.calc.calcjobresultdict[jobid]['JobPrice']))) # self.tableWidget_jobList.setItem(i,self.tableWidget_jobList.columnCount() - 1,item) self.textEdit_Result.append("/-----------------------------------------------------/\n") earlysub_str = self.early_subdate.strftime("%Y/%m/%d %H:%M:%S") late_enddate_str = self.late_enddate.strftime("%Y/%m/%d %H:%M:%S") workdate = self.late_enddate - self.early_subdate self.textEdit_Result.append("WorkStartDate: %s\nWorkEndDate: %s" % (earlysub_str,late_enddate_str)) self.textEdit_Result.append("Workingdays: %s\n" % self.calc.time_f(workdate.total_seconds())) #️ self.textEdit_Result.append("Workingdays: %s\n\n" % workdate) self.textEdit_Result.append(self.calc.calcresult) self.textEdit_Result.append("/-----------------------------------------------------/\n") self.calc.calcresult = "" self.status_label.setText('Calc finished.') self.__fitcolumns() # button類のロックを解除 self.__setEnabled(True) # msgBox = QtGui.QMessageBox() # msgBox.setIcon(QtGui.QMessageBox.Warning) # msgBox.setWindowTitle(self.appname) # msgBox.setStandardButtons(QtGui.QMessageBox.Ok) @QtCore.Slot() def job_clicked(self,item): # print(item.checkState()) # JobNameへのクリックにしか反応しないよ if item.column() == 0: if item.checkState() == QtCore.Qt.CheckState.Checked: self.checkedcount += 1 else: self.checkedcount -= 1 self.label_jobs.setText('%d total, %d checked' % (self.tableWidget_jobList.rowCount(), self.checkedcount)) @QtCore.Slot() def job_doubleclicked(self,item): if item.column() == 13: outpathlist = item.text().split(',') for i in range(len(outpathlist)): if os.path.exists(outpathlist[i]): QtGui.QDesktopServices.openUrl(outpathlist[i]) else: errstr = "warn:" + outpathlist[i] + " can't access.\n" self.textEdit_Result.append(errstr) def __setrecord(self,resultlist): self.tableWidget_jobList.setRowCount(len(resultlist)) # レコード数分降順でループ # deadline APIが必ずdate昇順でしか返してこないのを逆利用 for i,rec in enumerate(reversed(resultlist)): #print(i) item = QtGui.QTableWidgetItem(rec['JobName']) # 先頭だけはちぇっかぶる # flags = QtCore.Qt.ItemIsUserCheckable # flags |= QtCore.Qt.ItemIsEnabled # print(int(item.flags())) # print(flags) item.setFlags(49) # (int)QtCore.Qt.ItemIsUserCheckable + (int)QtCore.Qt.ItemIsEnabled) # checkedの設定するよ if rec['Checked']: item.setCheckState(QtCore.Qt.Checked) self.checkedcount += 1 else: item.setCheckState(QtCore.Qt.Unchecked) qfont = item.font() qfont.setPointSize(qfont.pointSize() + 1) qfont.setBold(True) item.setFont(qfont) self.tableWidget_jobList.setItem(i, 0,item) # JobID item = QtGui.QTableWidgetItem(rec['JobID']) qfont = item.font() qfont.setPointSize(qfont.pointSize() - 1) item.setFont(qfont) self.tableWidget_jobList.setItem(i, 1,item) # UserName item = QtGui.QTableWidgetItem(rec['UserName']) self.tableWidget_jobList.setItem(i, 2, item) # Status item = QtGui.QTableWidgetItem(rec['Status']) self.tableWidget_jobList.setItem(i, 3, item) # SubMachine item = QtGui.QTableWidgetItem(rec['SubMachine']) self.tableWidget_jobList.setItem(i, 4, item) # SubDate # item = QtGui.QTableWidgetItem(rec['SubDate'].isoformat()) item = QtGui.QTableWidgetItem(rec['SubDate'].strftime("%Y/%m/%d %H:%M:%S")) self.tableWidget_jobList.setItem(i, 5, item) # FinDateとJobRenderTimeは'Failed'時は入れられないよん # print(rec['FinDate']) if rec['FinDate']: # FinDate item = QtGui.QTableWidgetItem(rec['FinDate'].strftime("%Y/%m/%d %H:%M:%S")) self.tableWidget_jobList.setItem(i, 6, item) else: item = QtGui.QTableWidgetItem("None") self.tableWidget_jobList.setItem(i, 6, item) # FramesList item = QtGui.QTableWidgetItem(rec['FramesList']) self.tableWidget_jobList.setItem(i, 7, item) # Framesそのうちparseしてそれっぽく処理しないといけないなー item = QtGui.QTableWidgetItem(rec['Frames']) self.tableWidget_jobList.setItem(i, 8, item) # Plugin item = QtGui.QTableWidgetItem(rec['Plugin']) self.tableWidget_jobList.setItem(i, 9, item) item = QtGui.QTableWidgetItem(rec['Comment']) self.tableWidget_jobList.setItem(i, 10, item) # Concurent_tasks item = QtGui.QTableWidgetItem(rec['ConcTasks']) self.tableWidget_jobList.setItem(i, 11, item) # Chunk item = QtGui.QTableWidgetItem(rec['Chunk']) self.tableWidget_jobList.setItem(i, 12, item) # OutDir item = QtGui.QTableWidgetItem(rec['OutDir']) self.tableWidget_jobList.setItem(i, 13, item) # TotalTaskTime item = QtGui.QTableWidgetItem("None") self.tableWidget_jobList.setItem(i, 14, item) # JobPrice item = QtGui.QTableWidgetItem("") self.tableWidget_jobList.setItem(i, 15, item) # 完全な正常終了以外はすべて色変更 if rec['Status'] != 'Completed': # JobNameも色表示変更しておこかな # self.tableWidget_jobList.item(i, 0).setBackground(QtGui.QColor(255, 88, 71)) # if rec['Status'] == 'Failed': # item.setBackground(QtGui.QColor(255, 88, 71)) self.__setColortoRow(self.tableWidget_jobList, i, QtGui.QColor(255, 160, 122)) # とりあえず出力した結果を表示 self.label_jobs.setText('%d total, %d selected' % (len(resultlist),self.checkedcount)) # 1.0.4 self.tableWidget_jobList.sortItems(5,QtCore.Qt.DescendingOrder) def __setEnabled(self,req_bool): self.pushButton_Search.setEnabled(req_bool) self.pushButton_Calc.setEnabled(req_bool) self.tableWidget_jobList.setEnabled(req_bool) def __setColortoRow(self,table,rowIndex,color): for j in range(table.columnCount()): table.item(rowIndex,j).setBackground(color) # self.tableWidget_jobList.item(rowIndex, j). def __csvout(self,outpath): # print(outpath) # ファイルオープン try: ofd = codecs.open(str(outpath[0]), 'w',encoding="shift_jis") for i in range(self.tableWidget_jobList.columnCount()): # print(self.tableWidget_jobList.horizontalHeaderItem(i).text()) itemtext = "\"" + self.tableWidget_jobList.horizontalHeaderItem(i).text() + "\"," ofd.write(itemtext) ofd.write("\n") for i in range(self.tableWidget_jobList.rowCount()): for j in range(self.tableWidget_jobList.columnCount()): itemtext = "\"" + self.tableWidget_jobList.item(i, j).text() + "\"" # outpath情報には表示上の都合で','を除去 if(j == 13): itemtext = itemtext.replace(',','') if(j != self.tableWidget_jobList.columnCount() - 1): itemtext += "," else: itemtext += "\n" ofd.write(str(itemtext)) except (IOError, OSError) as err: errstr = "Can't open " + outpath self.msgBox.setText(errstr) self.msgBox.setStandardButtons(QtGui.QMessageBox.Ok) self.msgBox.exec_() return ofd.close() def __fitcolumns(self): for i in range(self.tableWidget_jobList.columnCount()): # Commentは長くなることあるからそれ以外を表示しよっと。。 if i == 10: pass if i == 13: self.tableWidget_jobList.setColumnWidth(i,120) else: self.tableWidget_jobList.resizeColumnToContents(i) self.tableWidget_jobList.setSortingEnabled(True)
class InfoPanel(QtGui.QWidget): def __init__(self, comPorts, boardController): super(InfoPanel, self).__init__() self.comPorts = comPorts self.boardController = boardController self.setMinimumWidth(320) self.setMaximumWidth(320) # Create the UI self._createUi() self.systemStatus.setText("-") self.systemMessage.setText("-") def _createUi(self): self.mainLayout = QtGui.QVBoxLayout() label = QtGui.QLabel("<b><font size=\"5\" color='black'>Orca Information</font></b>") self.mainLayout.addWidget(label) self.mainLayout.addSpacing(5) # Layout for the connection controls layoutConnection = QtGui.QHBoxLayout() self.mainLayout.addLayout(layoutConnection) # Connect button self.bConnect = QtGui.QPushButton("Connect") self.bConnect.clicked.connect(self._onbConnectClicked) layoutConnection.addWidget(self.bConnect) layoutConnection.addSpacing(120) # ComboBox for the com ports self.cbComPort = QtGui.QComboBox() for comPort in self.comPorts: self.cbComPort.addItem(comPort) self.cbComPort.currentIndexChanged.connect(self._onComPortChanged) if len(self.comPorts) > 0: self.boardController.set_serial_port(self.comPorts[0]) layoutConnection.addWidget(self.cbComPort) self.mainLayout.addSpacing(20) label = QtGui.QLabel("<b><font color='black'>System.Status</font></b>") self.mainLayout.addWidget(label) # System status label self.systemStatus = StatusLabel() self.mainLayout.addWidget(self.systemStatus) label = QtGui.QLabel("<b><font color='black'>System.Message</font></b>") self.mainLayout.addWidget(label) # System message label self.systemMessage = StatusLabel() self.mainLayout.addWidget(self.systemMessage) # UAV status overview self.uavStatusGadget = UavStatusGadget() self.uavStatusGadget.setMinimumWidth(300) self.uavStatusGadget.setMinimumHeight(250) self.uavStatusGadget.setLinkStatus(False) self.mainLayout.addWidget(self.uavStatusGadget) self.mainLayout.addStretch() self.setLayout(self.mainLayout) def _onComPortChanged(self): self.boardController.set_serial_port(self.comPorts[self.cbComPort.currentIndex()]) def _onbConnectClicked(self): if not self.boardController.connected(): self.cbComPort.setEnabled(False) self.uavStatusGadget.setLinkStatus(True) self.bConnect.setText("Disconnect") else: self.cbComPort.setEnabled(True) self.uavStatusGadget.setLinkStatus(False) self.bConnect.setText("Connect") def paintEvent(self, e): qp = QtGui.QPainter() qp.begin(self) self._drawBackground(qp) qp.end() def _drawBackground(self, qp): size = self.size() width = size.width() height = size.height() # Draw the background qp.setBrush(QtGui.QColor("#878486")) qp.drawRect(1, 1, width, height) # Draw frame qp.setPen(QtGui.QColor(0, 0, 0)) #qp.setBrush(QtGui.QColor(0, 0, 0)) qp.drawRect(0,0,width-1,height-1) def setSystemStatus(self, text): self.systemStatus.setText(text) def setSystemMessage(self, text): self.systemMessage.setText(text)