class MainWindow(QDialog): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.stopSign = 0 self.ws = 0 self.comment = '' self.clipboard = QApplication.clipboard() self.setWindowTitle(u'勤務表') self.setWindowIcon(QIcon('./img/tray.png')) self.systemTrayIcon = QSystemTrayIcon(self) self.systemTrayIcon.setIcon(QIcon('./img/tray.png')) self.systemTrayIcon.setVisible(True) self.systemTrayIcon.show() self.systemTrayIcon.activated.connect(self.on_systemTrayIcon_activated) self.tableLabel = QLabel('select *.xls file') self.pathText = QLineEdit() self.triggerBtn = QPushButton(u'檢查 / 開始') self.browseBtn = QPushButton(u' 瀏覽 ') self.stopBtn = QPushButton(u'停止') self.table = QTableWidget(26,0,self) self.setUpTable() self.hbox1 = QHBoxLayout() self.hbox2 = QHBoxLayout() self.hbox3 = QHBoxLayout() self.hbox4 = QHBoxLayout() self.hbox1.addWidget(self.pathText) self.hbox1.addWidget(self.browseBtn) self.hbox1.addWidget(self.triggerBtn) self.browseBtn.clicked.connect(self.OpenFile) self.triggerBtn.clicked.connect(self.setupTypeThread) self.stopBtn.clicked.connect(self.threadStop) self.status = QTreeWidget(self) self.status.setHeaderHidden(True) self.hbox2.addWidget(self.status) self.hbox3.addWidget(self.table) self.hbox4.addWidget(self.stopBtn) self.setGeometry(200, 200, 700, 400) self.status.setFixedHeight (80) self.layout = QVBoxLayout() self.layout.addWidget(self.tableLabel) self.layout.addLayout(self.hbox1) self.layout.addLayout(self.hbox2) self.layout.addLayout(self.hbox3) self.layout.addLayout(self.hbox4) self.setLayout(self.layout) self.stopBtn.setEnabled(False) def setUpTable(self): self.table.horizontalHeader().setVisible(False) for i in xrange(0, 26, 1): self.vhfont = QFont('Times', pointSize = 10, weight=QFont.Bold) timePos = i+6 if i == 0: item = QTableWidgetItem(u'[標題]') elif i == 1: item = QTableWidgetItem(u'[設定]') elif 2 < timePos < 24: item = QTableWidgetItem(('{0}~{1}').format(timePos, timePos+1)) else: item = QTableWidgetItem(('{0}~{1}').format(timePos-24, timePos-23)) item.setFont(self.vhfont) item.setTextAlignment(Qt.AlignCenter) self.table.setVerticalHeaderItem(i, item) def on_systemTrayIcon_activated(self, reason): if reason == QSystemTrayIcon.DoubleClick: if self.isHidden(): try: self.typeThread self.threadStop() except: pass self.show() else: self.hide() def setupTypeThread(self): self.clipboard.setText('') det = self.loadDetec() self.ws, vaild = self.checkTableValidation(det, self.table) ws = [] for col in self.ws: ws.append(col[0]) self.addStatus( u' 狀態: 檢查勤務表狀態....', 0) errStat = self.check(ws) if vaild != True and self.table.columnCount()!=0: self.addStatus( vaild, 1) elif self.table.columnCount() ==0: self.addStatus( u' 錯誤: 請載入勤務表', 1) self.typeThread = startType(self.ws) self.typeThread.threadDone.connect(self.showDoneMsg, Qt.QueuedConnection) self.typeThread.toTray.connect(self.toTray, Qt.QueuedConnection) self.typeThread.toCilpboard.connect(self.toCilpboard, Qt.QueuedConnection) self.typeThread.enableButtons.connect(self.enableButtons, Qt.QueuedConnection) self.typeThread.showErrMsg.connect(self.showErrMsg, Qt.QueuedConnection) self.typeThread.addStatus.connect(self.addStatus, Qt.QueuedConnection) if not self.typeThread.isRunning() and vaild == True and errStat == True: self.addStatus( u' 狀態: 檢查通過,開始進行登打作業....', -1) self.browseBtn.setEnabled(False) self.triggerBtn.setEnabled(False) self.stopBtn.setEnabled(True) self.typeThread.start() def toTray(self, state): if state: pass self.hide() self.systemTrayIcon.showMessage(u'輸入中',u'勤務表背景輸入中....\n\n雙擊圖示可暫停程序', msecs=1000000) else: self.show() def toCilpboard(self, text): self.clipboard.setText(text) def threadStop(self): self.typeThread.stopSign = 1 if self.typeThread.isRunning(): self.browseBtn.setEnabled(True) self.triggerBtn.setEnabled(True) self.stopBtn.setEnabled(False) def addStatus(self, text, err): subTreeItem = QTreeWidgetItem(self.status) subTreeItem.setText(0, text) self.activateWindow() if err == 1: font = QFont('Serif', 10, QFont.Bold) subTreeItem.setFont(0, font) subTreeItem.setForeground(0, QBrush(Qt.white)) subTreeItem.setBackground(0, QBrush(QColor(150,0,0))) elif err == 0: font = QFont('Serif', 10, QFont.Bold) subTreeItem.setFont(0, font) subTreeItem.setForeground(0, QBrush(Qt.black)) subTreeItem.setBackground(0, QBrush(Qt.white)) else: font = QFont('Serif', 10, QFont.Bold) subTreeItem.setFont(0, font) subTreeItem.setForeground(0, QBrush(Qt.white)) subTreeItem.setBackground(0, QBrush(QColor(0,150,0))) self.status.scrollToItem(subTreeItem, QAbstractItemView.PositionAtCenter) def showErrMsg(self, title, msg): self.addStatus( u'錯誤: ' + msg, 1) QMessageBox.warning(self, title, msg, QMessageBox.Ok) def showDoneMsg(self): self.addStatus( u'完成: 完成!', 1) QMessageBox.warning(self, u'完成!', u'完成!', QMessageBox.Ok) def enableButtons(self): self.clipboard.setText(self.comment) self.browseBtn.setEnabled(True) self.triggerBtn.setEnabled(True) self.stopBtn.setEnabled(False) self.show() def OpenFile(self): fileName = QFileDialog.getOpenFileName(self, "Open File.", "/home") self.comment = '' ext = fileName[0].split('.')[-1] if ext == 'xls' or ext == 'xlsx': self.pathText.setText(fileName[0]) sheet = open_workbook(fileName[0]).sheets()[0] self.setFixedHeight(550) self.addStatus( u' 狀態: 載入勤務表: [' + fileName[0] + ']', -1) for col in xrange(self.table.columnCount()-1,-1,-1): self.table.removeColumn(col) ws, header, headerNum = self.loadWS(sheet) self.appendTable(header, ws) self.check(ws) self.comment += self.yieldcomment(sheet) self.ws = ws else: self.showErrMsg(u'錯誤',u'選取檔案不是EXCEL檔') self.ws = 0 def checkTableValidation(self, detCol, table): # .[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ws = [[], [], [], [], [], [], [], [], [], []] errStat = True if len(detCol) == 0 or (0 in detCol): errStat = u' 狀態: 勤務表標頭錯誤,點選 [ --請選擇-- ] 選取有效標頭' for i in xrange(len(detCol)-1): if sorted(detCol)[i] == sorted(detCol)[i+1]: errStat = u' 狀態: 勤務表標頭重複' print detCol for c in xrange(table.columnCount()): col = [] colNum = detCol[c] for r in xrange(2, 26, 1): col.append(table.item(r,c).text()) ws[colNum-1].append(col) for i in xrange(len(ws)): if len(ws[i]) == 0: ws[i].append(['','','','','','','','','','','','','','','','','','','','','','','','']) return (ws), errStat def loadWS(self, sheet): header, headerNum, ws= [],[],[] for c in xrange(3, 26 ,1): title = (sheet.cell_value(3, c)) if len(title) != 0 and len(header) <6: header.append(title) col = [] for m in xrange(7, 31, 1): try: col.append(str(sheet.cell_value(m, c)).strip('()').replace('.0', '').replace('.', ',')) except: col.append(u'error') ws.append(col) return ws, header, headerNum def appendTable(self, header, ws): try: font = QFont('TypeWriter', pointSize = 10, weight=QFont.Bold) for text in header: self.table.insertColumn(0) for c in xrange(len(header)): det = self.determine(header[c]) item = QTableWidgetItem(header[c]) if det == 0: item.setBackground(QBrush(QColor('#FF8D00'))) else: item.setBackground(QBrush(QColor('#005588'))) item.setFont(font) item.setTextAlignment(Qt.AlignCenter) self.table.setItem(0, c, item) nComboBox = self.newCombo() nComboBox.setCurrentIndex(det) self.table.setCellWidget(1, c, (nComboBox)) for r in xrange(2,26,1): item = QTableWidgetItem(ws[c][r-2]) item.setFont(font) item.setTextAlignment(Qt.AlignCenter) self.table.setItem(r, c, item) self.addStatus( u' 狀態: 勤務表預覽成功', -1) return 0 except: self.addStatus( u' 狀態: 勤務表預覽失敗', 1) return 'error' def loadDetec(self): det = [] for col in xrange(self.table.columnCount()): det.append( self.table.cellWidget(1, col).currentIndex()) return det def newCombo(self): taskList = [u'--請選擇--', u'值班', u'救護勤務', u'備勤', u'待命服勤', u'水源查察', u'消防查察', u'宣導勤務', u'訓(演)練', u'專案勤務', u'南山救護站'] nComboBox = QComboBox() nComboBox.addItems(taskList) for i in xrange(len(taskList)): if i == 0: nComboBox.setItemData(i, QColor('#550000'), Qt.BackgroundColorRole) nComboBox.setItemData(i, Qt.AlignCenter, Qt.TextAlignmentRole) nComboBox.setStyleSheet("text-align: right; font: bold 13px;") return nComboBox def setTableErr(self, row, state): if state == 'illegal' : color = '#CC0033' elif state == 'repeated' : color = '#FF8D00' elif state == 'legal' : color = '#201F1F' for col in xrange(self.table.columnCount()): self.table.item(row,col).setBackground(QBrush(QColor(color))) def check(self, ws): errStat = True for m in xrange(2,26): self.setTableErr(m, 'legal') for i in xrange(24): ary = [] for j in xrange(len(ws)): for each in ws[j][i].replace(' ', '').split(','): try: if each == "A": ary.append(-1) elif each == '' : pass else: each == ary.append(int(each)) except: errStat = False timePos = i+8 rptErrMSG = u" 錯誤: 於 {0} ~ {1} 時 數字: {2} --不合法, 請修正" self.setTableErr(i+2, 'illegal') print timePos if timePos < 23: print 'a' self.addStatus(rptErrMSG.format(timePos, timePos+1, each), 1) else: self.addStatus(rptErrMSG.format(timePos-24, timePos-23, each), 1) ary = sorted(ary) for idx in xrange(len(ary)-1): if ary[idx] == ary[idx+1]: errStat = False timePos = i+8 rptErrMSG = u" 錯誤: 於 {0} ~ {1} 時 數字: {2} --番號重複, 請修正" self.setTableErr(i+2, 'repeated') if timePos < 23: self.addStatus(rptErrMSG.format(timePos, timePos+1, str(ary[idx]).replace('-1', 'A')), 1) else: self.addStatus(rptErrMSG.format(timePos-24, timePos-23, str(ary[idx]).replace('-1', 'A')), 1) return errStat def determine(self, title): cmpfactor = 0 smp = [u'值班', u'救護分隊務', u'備', u'待命服', u'水源', u'消防', u'宣導', u'訓演練', u'專案其它', u'南山站'] for index, each in zip(xrange(len(smp)),smp): for text in each: for elem in title: cmpfactor += ( elem == text ) if cmpfactor > 0: return index+1 return 0 def yieldcomment(self, sheet): comment0, comment1 = '', '' # for i,j in [[24,27], [27,27], [29,27], [29,35]]: # try: # comment0 += (smart_str(sheet.cell_value(i, j)) + '\n') # except: # pass for i,j in [[31,3], [32,3], [33,3], [34,3]]: try: comment1 += (sheet.cell_value(i, j) + '\n') except: pass return comment1