class Controller(QtGui.QWidget, View): def __init__(self, parent = None): QtGui.QWidget.__init__(self, parent) self.setupUi(self) self.title = "Combinatorics - Обчислення комбінацій та перестановок" self.currentTabText = self.tabComb.tabText(self.tabComb.currentIndex()) self.currentTab = self.tabComb.currentWidget() self.setWindowTitle(self.title + " - " + self.currentTabText) self.m = ModelMetadata() #self.v = self self.timer = MyTimer(self) self.thread = MyThread(self) self.status = "stoped" self.handleEvents() self.MetaTableReset() self.metaRows["result"].setText(os.path.abspath(self.m.file.name)) self.tableMetadata.resizeColumnsToContents() self.show() def run(self): sys.exit(app.exec_()) def closeEvent(self, event): # clean garbage if self.status in ["started", "paused"]: self.handleStop() # stop thread del self.m # close file event.accept() def handleEvents(self): # enable/disable spinBox or plainTextEdit self.connect(self.radioN, QtCore.SIGNAL("toggled(bool)"), self.spinN.setEnabled) self.connect(self.radioNCustom, QtCore.SIGNAL("toggled(bool)"), self.plainNCustom.setEnabled) self.tabComb.currentChanged.connect(self.handleChangeTab) # link in QLabel leads to other Tab within QTabWidget self.label.linkActivated.connect(lambda link: self.tabComb.setCurrentIndex(int(link[4:]))) # prevent setting K larger than N # self.spinN.valueChanged.connect(lambda value: self.spinK.setMaximum(value)) self.spinColumns.valueChanged["int"].connect(lambda val: setattr(self.m, "columns", val)) self.tabComb.currentChanged.connect(self.handleChange) self.plainNCustom.textChanged.connect(self.handleChange) self.spinN.valueChanged.connect(self.handleChange) self.spinK.valueChanged.connect(self.handleChange) self.radioN.clicked.connect(self.handleChange) self.radioNCustom.clicked.connect(self.handleChange) self.btnStart.clicked.connect(self.handleStart) self.btnStop.clicked.connect(self.handleStop) self.btnResultPath.clicked.connect(self.handleChangePath) self.metaRows["btnClear"].clicked.connect(self.handleClearResult) self.tableMetadata.cellDoubleClicked.connect(self.openResult) self.connect(self.timer, QtCore.SIGNAL("upd_prog_bar(int)"), self.metaRows["progressBar"], QtCore.SLOT("setValue(int)")) self.thread.finished.connect(self.handleStop) def handleChange(self): if self.plainNCustom.isEnabled(): self.m.seq = self.plainNCustom.toPlainText().split() if not self.m.seq: return #self.spinK.setMaximum(len(self.m.seq)) # if k can't be larger than N else: self.m.seq = range(1, self.spinN.value() + 1) self.m.K = self.spinK.value() self.MetaAllUpdate() def handleChangeTab(self, index): self.currentTabText = self.tabComb.tabText(index) self.currentTab = self.tabComb.widget(index) self.setWindowTitle(self.title + " - " + self.currentTabText) self.spinK.setDisabled(index==4) # Permutation doesn't require K, only N self.MetaTableReset() def disabledWhenStart(self, flag): # list of elements that gonna be disabled when Calc. starts (and enabled when stops) disableList = [self.tabComb, self.groupInput, self.checkMetadata, self.checkShowResult, self.spinColumns, self.btnResultPath, self.metaRows["btnClear"]] self.btnStop.setEnabled(flag) for w in disableList: w.setDisabled(flag) def handleStart(self): if self.status in ["stoped", "paused"]: if self.status == "stoped": self.writeMetaData() self.status = "started" self.disabledWhenStart(True) self.btnStart.setText("Призупинити") self.btnStart.setIcon(QtGui.QIcon(QtGui.QPixmap(":/icons/pause.png"))) self.timer.start(1000) self.thread.func = self.currentTab.coreGenerator self.thread.start() elif self.status == "started": self.status = "paused" self.btnStart.setText("Продовжити") self.btnStart.setIcon(QtGui.QIcon(QtGui.QPixmap(":/icons/play.png"))) self.handlePause() def handlePause(self): self.timer.stop() if self.checkShowResult.isChecked(): self.openResult() def handleStop(self): self.status = "stoped" self.disabledWhenStart(False) self.btnStart.setText("Старт обчислень") self.btnStart.setIcon(QtGui.QIcon(QtGui.QPixmap(":/icons/play.png"))) if self.timer.isActive(): self.timer.stop() self.MetaTimeUpdate() # adjustment meta data self.flushResult() if self.checkShowResult.isChecked(): self.openResult() self.m.reset() def handleChangePath(self): path = QtGui.QFileDialog.getSaveFileName(parent=self, caption="Виберіть новий файл, для збереження результату", directory=QtCore.QDir.currentPath(), filter="Text files (*.txt)") if path[0]: self.m.filename = path[0] self.m.file.close() self.m.file = open(os.path.normpath(self.m.filename), "w+", encoding="utf8") self.metaRows["result"].setText(os.path.abspath(self.m.file.name)) self.tableMetadata.resizeColumnsToContents() def handleClearResult(self): self.m.file.close() self.m.file = open(self.m.filename, "w+", encoding="utf-8") self.metaRows["labelSize"].setText("0 байт") # periodically write data from result list to file def flushResult(self): i=0 columns = self.m.columns result = "" while i<len(self.m.result): result += "\t".join(self.m.result[i : (i+columns)]) + "\n" i += columns self.m.file.write(result) self.m.file.flush() self.MetaFileSizeUpdate() self.m.result = [] def openResult(self, row=6, col=0): # row and col here recieves from table's cell dblClick signal if row==6 and col==0: os.startfile(os.path.abspath(self.m.file.name)) # os.popen("notepad " + os.path.abspath(self.m.file.name)) # could be that variant as well def writeMetaData(self): if self.checkMetadata.isChecked(): meta = "{0}\n{0}\n\nТип: {1}\nВхідні дані: N={2}{3}\nВсього комбінацій: {4}\n{0}\n".format( "-"*40, self.currentTabText, len(self.m.seq), ", k=%s" % self.spinK.value() if self.tabComb.currentIndex != 4 else "", self.m.All ) self.m.file.write(meta) self.m.file.flush() def MetaTableReset(self): self.metaRows["name"].setText(self.currentTabText) self.metaRows["all"].setText("1") self.metaRows["complete"].setText("0") self.metaRows["progressBar"].setValue(0) self.metaRows["time"].setText("") self.metaRows["left"].setText("") self.tableMetadata.resizeColumnsToContents() def MetaAllUpdate(self): try: self.m.All = self.currentTab.coreNumber(self.m.seq, self.m.K) except ValueError: self.m.All = 0 self.metaRows["all"].setText( str(self.m.All) ) self.tableMetadata.resizeColumnsToContents() def MetaTimeUpdate(self): self.metaRows["time"].setText( self.m.time ) self.metaRows["left"].setText( self.m.left ) self.metaRows["complete"].setText( str(self.m.complete) ) if self.m.complete == self.m.All: self.metaRows["progressBar"].setValue(100) self.tableMetadata.resizeColumnsToContents() def MetaFileSizeUpdate(self): size = os.stat(os.path.abspath(self.m.filename)).st_size # get size of the file in bytes l_size = list(str(size)) for i in range(len(l_size)-3, 0, -3): # insert space in each 3rd position from the end l_size.insert(i, " ") # 12345678 -> 12 345 678 self.metaRows["labelSize"].setText("".join(l_size) + " байт" )