def __init__(self, parent, main, cs_callback, get_csstate): super(FeeSelectionDialog, self).__init__(parent, main) #Button Label self.lblButtonFee = QLabelButton("") #get default values flatFee = self.main.getSettingOrSetDefault("Default_Fee", MIN_TX_FEE) flatFee = coin2str(flatFee, maxZeros=1).strip() fee_byte = str(self.main.getSettingOrSetDefault("Default_FeeByte", MIN_FEE_BYTE)) blocksToConfirm = self.main.getSettingOrSetDefault(\ "Default_FeeByte_BlocksToConfirm", NBLOCKS_TO_CONFIRM) self.coinSelectionCallback = cs_callback self.getCoinSelectionState = get_csstate self.validAutoFee = True try: autoFee_byte = str(estimateFee(blocksToConfirm) / 1000.0) except: autoFee_byte = "N/A" self.validAutoFee = False defaultCheckState = \ self.main.getSettingOrSetDefault("FeeOption", DEFAULT_FEE_TYPE) #flat free def setFlatFee(): def callbck(): return self.selectType('FlatFee') return callbck def updateLbl(): self.updateCoinSelection() self.radioFlatFee = QRadioButton(self.tr("Flat Fee (BTC)")) self.edtFeeAmt = QLineEdit(flatFee) self.edtFeeAmt.setFont(GETFONT('Fixed')) self.edtFeeAmt.setMinimumWidth(tightSizeNChar(self.edtFeeAmt, 6)[0]) self.edtFeeAmt.setMaximumWidth(tightSizeNChar(self.edtFeeAmt, 12)[0]) self.connect(self.radioFlatFee, SIGNAL('clicked()'), setFlatFee()) self.connect(self.edtFeeAmt, SIGNAL('textChanged(QString)'), updateLbl) frmFlatFee = QFrame() frmFlatFee.setFrameStyle(STYLE_RAISED) layoutFlatFee = QGridLayout() layoutFlatFee.addWidget(self.radioFlatFee, 0, 0, 1, 1) layoutFlatFee.addWidget(self.edtFeeAmt, 0, 1, 1, 1) frmFlatFee.setLayout(layoutFlatFee) #fee/byte def setFeeByte(): def callbck(): return self.selectType('FeeByte') return callbck self.radioFeeByte = QRadioButton(self.tr("Fee/Byte (Satoshi/Byte)")) self.edtFeeByte = QLineEdit(fee_byte) self.edtFeeByte.setFont(GETFONT('Fixed')) self.edtFeeByte.setMinimumWidth(tightSizeNChar(self.edtFeeByte, 6)[0]) self.edtFeeByte.setMaximumWidth(tightSizeNChar(self.edtFeeByte, 12)[0]) self.connect(self.radioFeeByte, SIGNAL('clicked()'), setFeeByte()) self.connect(self.edtFeeByte, SIGNAL('textChanged(QString)'), updateLbl) frmFeeByte = QFrame() frmFeeByte.setFrameStyle(STYLE_RAISED) layoutFeeByte = QGridLayout() layoutFeeByte.addWidget(self.radioFeeByte, 0, 0, 1, 1) layoutFeeByte.addWidget(self.edtFeeByte, 0, 1, 1, 1) frmFeeByte.setLayout(layoutFeeByte) #auto fee/byte def setAutoFeeByte(): def callbck(): return self.selectType('Auto') return callbck radioButtonTxt = self.tr("Fee rate from node (sat/Byte): ") if not self.validAutoFee: radioButtonTxt = self.tr("Failed to fetch fee/byte from node") self.radioAutoFeeByte = QRadioButton(radioButtonTxt) self.lblAutoFeeByte = QLabel(autoFee_byte) self.lblAutoFeeByte.setFont(GETFONT('Fixed')) self.lblAutoFeeByte.setMinimumWidth(tightSizeNChar(self.lblAutoFeeByte, 6)[0]) self.lblAutoFeeByte.setMaximumWidth(tightSizeNChar(self.lblAutoFeeByte, 12)[0]) self.sliderAutoFeeByte = QSlider(Qt.Horizontal, self) self.sliderAutoFeeByte.setMinimum(2) self.sliderAutoFeeByte.setMaximum(6) self.sliderAutoFeeByte.setValue(blocksToConfirm) self.lblSlider = QLabel() def getSliderLabelTxt(): return self.tr("Blocks to confirm: %1").arg(\ unicode(self.sliderAutoFeeByte.value())) def updateAutoFeeByte(): blocksToConfirm = self.sliderAutoFeeByte.value() try: autoFee_byte = str(estimateFee(blocksToConfirm) / 1000.0) except: autoFee_byte = "N/A" self.lblSlider.setText(getSliderLabelTxt()) self.lblAutoFeeByte.setText(autoFee_byte) updateLbl() self.lblSlider.setText(getSliderLabelTxt()) self.connect(self.radioAutoFeeByte, SIGNAL('clicked()'), setAutoFeeByte()) self.sliderAutoFeeByte.valueChanged.connect(updateAutoFeeByte) self.sliderAutoFeeByte.setEnabled(False) frmAutoFeeByte = QFrame() frmAutoFeeByte.setFrameStyle(STYLE_RAISED) layoutAutoFeeByte = QGridLayout() layoutAutoFeeByte.addWidget(self.radioAutoFeeByte, 0, 0, 1, 1) layoutAutoFeeByte.addWidget(self.lblAutoFeeByte, 0, 1, 1, 1) layoutAutoFeeByte.addWidget(self.lblSlider, 1, 0, 1, 2) layoutAutoFeeByte.addWidget(self.sliderAutoFeeByte, 2, 0, 1, 2) frmAutoFeeByte.setLayout(layoutAutoFeeByte) if not self.validAutoFee: frmAutoFeeByte.setEnabled(False) #adjust and close self.btnClose = QPushButton(self.tr('Close')) self.connect(self.btnClose, SIGNAL('clicked()'), self.accept) self.checkBoxAdjust = QCheckBox(self.tr('Adjust fee/byte for privacy')) self.checkBoxAdjust.setChecked(\ self.main.getSettingOrSetDefault('AdjustFee', True)) self.connect(self.checkBoxAdjust, SIGNAL('clicked()'), updateLbl) frmClose = makeHorizFrame(\ [self.checkBoxAdjust, 'Stretch', self.btnClose], STYLE_NONE) #main layout layout = QGridLayout() layout.addWidget(frmAutoFeeByte, 0, 0, 1, 4) layout.addWidget(frmFeeByte, 2, 0, 1, 4) layout.addWidget(frmFlatFee, 4, 0, 1, 4) layout.addWidget(frmClose, 5, 0, 1, 4) self.setLayout(layout) self.setWindowTitle(self.tr('Select Fee Type')) self.selectType(defaultCheckState) self.setFocus()
class WTestManager(QWidget, Logger.ClassLogger): """ Widget to display all tests in the scheduler """ def __init__(self, parent): """ Constructs WTestManager widget @param parent: @type parent: """ QWidget.__init__(self, parent) self.parent = parent self.name = self.tr("Task Manager") self.ascendingOrder = False self.ascendingOrderHistory = False self.ascendingOrderWaiting = False self.itemCurrent = None self.projects = [] self.createWidgets() self.createActions() self.createConnections() self.createActions() self.createToolbar() self.deactivate() def createWidgets (self): """ QtWidgets creation QTreeWidget (Id, Name, Init at, Sched at, Start at, Stop at, User, Duration) _______________ | QToolBar | |---------------| _______________ | | |---------------| | | | | |_______________| """ #self.mainTab = QTabWidget() layout = QVBoxLayout() topLayout = QHBoxLayout() # waiting tree widget self.tabWaiting = QTabWidget() #self.waitingBox = QGroupBox("Waiting") self.waitingBox = QFrame(self) self.testWaiting = QTreeWidget(self) self.testWaiting.setSelectionMode(QAbstractItemView.ExtendedSelection) self.waitingToolbar = QToolBar(self) self.labelsWaiting = [ self.tr("No.") , self.tr("Group"), self.tr("Schedulation Type"), self.tr("Project"), self.tr("Name") , self.tr("Next run"), self.tr("Repeat"), self.tr("Probes"), self.tr("Notifications") , self.tr("Tests result"), self.tr("Author") ] self.testWaiting.setHeaderLabels(self.labelsWaiting) self.testWaiting.setIndentation(10) self.testWaiting.setContextMenuPolicy(Qt.CustomContextMenu) layoutWaiting = QVBoxLayout() layoutWaiting.addWidget(self.waitingToolbar) layoutWaiting.addWidget(self.testWaiting) self.waitingBox.setLayout(layoutWaiting) self.tabWaiting.addTab( self.waitingBox, "Scheduled" ) self.enqueuedBox = QFrame(self) layoutEnqueued = QVBoxLayout() self.testEnqueued = QTreeWidget(self) self.labelsEnqueued = [ self.tr("Group of tests") ] self.testEnqueued.setHeaderLabels(self.labelsEnqueued) self.testEnqueued.setIndentation(10) layoutEnqueued.addWidget(self.testEnqueued) self.enqueuedBox.setLayout(layoutEnqueued) self.tabWaiting.addTab( self.enqueuedBox, "Waiting" ) # current tree widget self.currentBox = QGroupBox("Running") self.testManager = QTreeWidget(self) self.testManager.setSelectionMode(QAbstractItemView.ExtendedSelection) self.dockToolbar = QToolBar(self) self.labels = [ self.tr("No."), self.tr("Project"), self.tr("Name"), self.tr("Started at"), self.tr("Author"), self.tr("Recursive") ] self.testManager.setHeaderLabels(self.labels) self.testManager.setIndentation(10) self.testManager.setContextMenuPolicy(Qt.CustomContextMenu) layoutCurrent = QVBoxLayout() layoutCurrent.addWidget(self.dockToolbar) layoutCurrent.addWidget(self.testManager) self.currentBox.setLayout(layoutCurrent) v_splitter = QSplitter(self) v_splitter.addWidget( self.tabWaiting ) v_splitter.addWidget( self.currentBox ) topLayout.addWidget(v_splitter) # history tree widget self.historyBox = QGroupBox("History") self.testHistory = QTreeWidget(self) self.historyToolbar = QToolBar(self) self.labels2 = [ self.tr("Id"), self.tr("Schedulation Type"), self.tr("Project") , self.tr("Name"), self.tr("Sched at"), self.tr("Run start"), self.tr("Run end"), self.tr("Author"), self.tr("Duration (in sec.)"), self.tr("Run Result") ] self.testHistory.setHeaderLabels(self.labels2) self.statsBox = QGroupBox("Summary") self.nbRunningLabel = QLabel("0") self.nbWaitingLabel = QLabel("0") self.nbHistoryLabel = QLabel("0") self.nbCompleteHistoryLabel = QLabel("0") self.nbErrorHistoryLabel = QLabel("0") self.nbKilledHistoryLabel = QLabel("0") self.nbCancelledHistoryLabel = QLabel("0") layout2 = QFormLayout() layout2.addRow(QLabel("Running"), self.nbRunningLabel ) layout2.addRow(QLabel("Waiting"), self.nbWaitingLabel ) layout2.addRow( QLabel(""), QLabel("") ) layout2.addRow(QLabel("History"), self.nbHistoryLabel ) layout2.addRow(QLabel(" - COMPLETE"), self.nbCompleteHistoryLabel ) layout2.addRow(QLabel(" - ERROR"), self.nbErrorHistoryLabel ) layout2.addRow(QLabel(" - KILLED"), self.nbKilledHistoryLabel ) layout2.addRow(QLabel(" - CANCELLED"), self.nbCancelledHistoryLabel ) self.statsBox.setLayout(layout2) layoutHistory = QVBoxLayout() layoutHistory.addWidget(self.historyToolbar) layoutHistory.addWidget(self.testHistory) self.historyBox.setLayout(layoutHistory) subLayout = QHBoxLayout() subLayout.addWidget(self.historyBox) subLayout.addWidget(self.statsBox) frame_left = QFrame(self) frame_left.setFrameShape(QFrame.NoFrame) frame_left.setLayout(topLayout) frame_right = QFrame(self) frame_right.setFrameShape(QFrame.NoFrame) frame_right.setLayout(subLayout) topLayout.setContentsMargins(0,0,0,0) subLayout.setContentsMargins(0,0,0,0) splitter1 = QSplitter(Qt.Vertical) splitter1.addWidget(frame_left) splitter1.addWidget(frame_right) layout.addWidget(splitter1) self.setLayout(layout) def createConnections(self): """ Create Qt Connections """ self.testWaiting.customContextMenuRequested.connect(self.onPopupMenuWaiting) self.testWaiting.currentItemChanged.connect(self.onCurrentWaitingItemChanged) self.testManager.customContextMenuRequested.connect(self.onPopupMenu) self.testManager.currentItemChanged.connect(self.onCurrentItemChanged) self.testWaiting.itemDoubleClicked.connect(self.onItemDoubleClicked) def createActions (self): """ Actions defined: * sort running task * sort waiting task * sort history task * kill one task * kill all tasks * cancel one task * cancel all task * clear the history * edit a waiting task * refresh waiting tasks * refresh running tasks * partial refresh of the history * complete refresh of the history * disable a waiting task * enable a waiting task """ self.sortAction = QtHelper.createAction(self, "Ascending Order", self.toggleSort, toggled = True, icon = QIcon(":/ascending.png") ) self.sortHistoryAction = QtHelper.createAction(self, "Ascending Order", self.toggleSortHistory, toggled = True, icon = QIcon(":/ascending.png") ) self.sortWaitingAction = QtHelper.createAction(self, "Ascending Order", self.toggleSortWaiting, toggled = True, icon = QIcon(":/ascending.png") ) self.killAction = QtHelper.createAction(self, "&Kill", self.killTask, tip = 'Kill selected test', icon = QIcon(":/process-kill.png") ) self.killAllAction = QtHelper.createAction(self, "&Kill All", self.killAllTasks, tip = 'Kill all running tests', icon = QIcon(":/process-killall.png") ) self.cancelAction = QtHelper.createAction(self, "&Cancel", self.cancelTask, tip = 'Cancel selected test', icon = QIcon(":/process-cancel.png") ) self.cancelAllAction = QtHelper.createAction(self, "&Cancel All", self.cancelAllTasks, tip = 'Cancel all waiting tests', icon = QIcon(":/processes-cancelall.png") ) self.clearHistoryAction = QtHelper.createAction(self, "&Clear history", self.clearHistory, tip = 'Clear history', icon = QIcon(":/trash.png")) self.editWaitingAction = QtHelper.createAction(self, "&Edit", self.editWaiting, tip = 'Edit the selected task', icon = QIcon(":/reschedule.png")) self.refreshWaitingAction = QtHelper.createAction(self, "Waiting tasks", self.refreshWaitingList, icon = QIcon(":/act-refresh.png"), tip="Refresh waiting tasks" ) self.refreshRunningAction = QtHelper.createAction(self, "Running tasks", self.refreshRunningList, icon = QIcon(":/act-refresh.png"), tip="Refresh running tasks" ) self.partialRefreshHistoryAction = QtHelper.createAction(self, "Partial history", self.partialRefreshHistoryList, icon = QIcon(":/act-half-refresh.png"), tip="Refresh partial history" ) self.refreshHistoryAction = QtHelper.createAction(self, "Full history", self.refreshHistoryList, icon = QIcon(":/act-refresh.png"), tip="Refresh full history" ) self.disableAction = QtHelper.createAction(self, "&Disable", self.disableTask, tip = 'Disable task', icon = QIcon(":/process-pause-icon.png") ) self.enableAction = QtHelper.createAction(self, "&Enable", self.enableTask, tip = 'Enable task', icon = None) def createToolbar(self): """ Toolbar creation ||----------|| || Kill all || ||----------|| """ self.dockToolbar.setObjectName("Test Manager toolbar") self.dockToolbar.addAction(self.sortAction) self.dockToolbar.addAction(self.refreshRunningAction) self.dockToolbar.addSeparator() self.dockToolbar.addAction(self.killAction) self.dockToolbar.addAction(self.killAllAction) self.dockToolbar.addSeparator() self.dockToolbar.setIconSize(QSize(16, 16)) # self.historyToolbar.setObjectName("Test Manager History toolbar") self.historyToolbar.addAction(self.sortHistoryAction) self.historyToolbar.addAction(self.partialRefreshHistoryAction) self.historyToolbar.addAction(self.refreshHistoryAction) self.historyToolbar.addSeparator() self.historyToolbar.addAction(self.clearHistoryAction) self.historyToolbar.setIconSize(QSize(16, 16)) # self.waitingToolbar.setObjectName("Test Manager Waiting toolbar") self.waitingToolbar.addAction(self.sortWaitingAction) self.waitingToolbar.addAction(self.refreshWaitingAction) self.waitingToolbar.addSeparator() self.waitingToolbar.addAction(self.editWaitingAction) self.waitingToolbar.addAction(self.disableAction) self.waitingToolbar.addAction(self.cancelAction) self.waitingToolbar.addAction(self.cancelAllAction) self.waitingToolbar.addSeparator() self.waitingToolbar.setIconSize(QSize(16, 16)) def onItemDoubleClicked(self, item): """ On item double clicked in waiting task """ if item.taskEventType in [ UCI.SCHED_QUEUE_AT, UCI.SCHED_QUEUE ]: pass else: self.editWaiting() def getProjectName(self, prjId): """ Return the project name """ pname = "UNKNOWN" if prjId == 0: return "UNDEFINED" for p in self.projects: if int(p['project_id']) == int(prjId): pname = p['name'] break return pname def refreshWaitingList(self): """ Refresh the waiting task list """ RCI.instance().waitingTasks() def refreshRunningList(self): """ Refresh the running task list """ RCI.instance().runningTasks() def partialRefreshHistoryList(self): """ Partial refresh of the history task list """ RCI.instance().historyTasks() def refreshHistoryList(self): """ Refresh the history task list """ RCI.instance().historyTasksAll() def onCurrentItemChanged(self, witem1, witem2): """ On current item changed @param witem1: @type witem1: @param witem2: @type witem2: """ # kill task available just for admin and tester if UCI.RIGHTS_ADMIN in RCI.instance().userRights or UCI.RIGHTS_TESTER in RCI.instance().userRights : if witem1 is not None: if witem1.taskState == STATE_RUNNING : self.itemCurrent = witem1 self.killAction.setEnabled(True) else: self.killAction.setEnabled(False) def onCurrentWaitingItemChanged(self, witem1, witem2): """ On current waiting task item changed @param witem1: @type witem1: @param witem2: @type witem2: """ # kill task available just for admin and tester if UCI.RIGHTS_ADMIN in RCI.instance().userRights or UCI.RIGHTS_TESTER in RCI.instance().userRights : if witem1 is not None: self.itemCurrent = witem1 self.cancelAction.setEnabled(True) self.editWaitingAction.setEnabled(True) self.disableAction.setEnabled(True) else: self.cancelAction.setEnabled(False) self.editWaitingAction.setEnabled(False) self.disableAction.setEnabled(False) def disableTask(self): """ Disable a waiting task """ # if self.itemCurrent is not None: for currentItem in self.testWaiting.selectedItems(): RCI.instance().rescheduleTask(taskId=currentItem.taskId, taskEnabled=False, scheduleType=currentItem.taskEventType, scheduleAt=currentItem.taskEventArgs, scheduleRepeat=currentItem.taskEventNb, probesEnabled=currentItem.taskWithoutProbes, notificationsEnabled=currentItem.taskWithoutNotif, debugEnabled=False, logsEnabled=currentItem.taskNoKeepTr, fromTime=currentItem.taskEventFrom, toTime=currentItem.taskEventTo ) def enableTask(self): """ Enable a waiting task """ # if self.itemCurrent is not None: for currentItem in self.testWaiting.selectedItems(): RCI.instance().rescheduleTask(taskId=currentItem.taskId, taskEnabled=True, scheduleType=currentItem.taskEventType, scheduleAt=currentItem.taskEventArgs, scheduleRepeat=currentItem.taskEventNb, probesEnabled=currentItem.taskWithoutProbes, notificationsEnabled=currentItem.taskWithoutNotif, debugEnabled=False, logsEnabled=currentItem.taskNoKeepTr, fromTime=currentItem.taskEventFrom, toTime=currentItem.taskEventTo ) def editWaiting(self): """ Edit a waiting task """ if self.itemCurrent is not None: if self.itemCurrent.taskEventType in [ UCI.SCHED_QUEUE_AT, UCI.SCHED_QUEUE ]: pass else: dSched = ScheduleDialog.SchedDialog( self ) dSched.fillFields( schedType=self.itemCurrent.taskEventType, schedArgs=self.itemCurrent.taskEventArgs, taskName=self.itemCurrent.taskEventName, taskId=self.itemCurrent.taskId, schedNb=self.itemCurrent.taskEventNb, withoutProbes=self.itemCurrent.taskWithoutProbes, enabled=self.itemCurrent.taskEventEnabled, withoutNotifs=self.itemCurrent.taskWithoutNotif, noKeepTr=self.itemCurrent.taskNoKeepTr, schedFrom=self.itemCurrent.taskEventFrom, schedTo=self.itemCurrent.taskEventTo ) if dSched.exec_() == QDialog.Accepted: runAt, runType, runNb, withoutProbes, runEnabled, noTr, withoutNotifs, runFrom, runTo = dSched.getSchedtime() RCI.instance().rescheduleTask(taskId=self.itemCurrent.taskId, taskEnabled=runEnabled, scheduleType=runType, scheduleAt=runAt, scheduleRepeat=runNb, probesEnabled=withoutProbes, notificationsEnabled=withoutNotifs, debugEnabled=False, logsEnabled=noTr, fromTime=runFrom, toTime=runTo ) def clearHistory(self): """ Call the server to clear the history """ reply = QMessageBox.question(self, "Clear tasks history", "Are you sure ?", QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.Yes: RCI.instance().clearHistory() def testKilled(self): """ Test kiled """ self.itemCurrent = None self.killAction.setEnabled(False) def testCancelled(self): """ Test cancelled """ self.itemCurrent = None self.cancelAction.setEnabled(False) def active (self): """ Enables QTreeWidget """ self.waitingBox.setEnabled(True) self.currentBox.setEnabled(True) self.historyBox.setEnabled(True) self.statsBox.setEnabled(True) # self.testManager.setEnabled(True) self.testHistory.setEnabled(True) self.testWaiting.setEnabled(True) # self.sortAction.setEnabled(True) self.sortHistoryAction.setEnabled(True) self.sortWaitingAction.setEnabled(True) self.refreshWaitingAction.setEnabled(True) self.refreshRunningAction.setEnabled(True) self.refreshHistoryAction.setEnabled(True) self.partialRefreshHistoryAction.setEnabled(True) self.killAction.setEnabled(False) self.cancelAction.setEnabled(False) self.editWaitingAction.setEnabled(False) if UCI.RIGHTS_ADMIN in RCI.instance().userRights: self.killAllAction.setEnabled(True) self.cancelAllAction.setEnabled(True) self.clearHistoryAction.setEnabled(True) self.disableAction.setEnabled(False) self.enableAction.setEnabled(True) def deactivate (self): """ Clears QTreeWidget and disables it """ self.waitingBox.setEnabled(False) self.currentBox.setEnabled(False) self.historyBox.setEnabled(False) self.statsBox.setEnabled(False) self.testWaiting.clear() self.testWaiting.setEnabled(False) self.testManager.clear() self.testManager.setEnabled(False) self.testHistory.clear() self.testHistory.setEnabled(False) self.testEnqueued.clear() self.testHistory.setEnabled(False) self.nbRunningLabel.setText("0") self.nbWaitingLabel.setText("0") self.nbHistoryLabel.setText("0") self.nbCompleteHistoryLabel.setText("0") self.nbErrorHistoryLabel.setText("0") self.nbKilledHistoryLabel.setText("0") self.nbCancelledHistoryLabel.setText("0") self.itemCurrent = None self.setDefaultActionsValues() def setDefaultActionsValues (self): """ Set default values for qt actions """ self.sortAction.setEnabled(False) self.sortHistoryAction.setEnabled(False) self.sortWaitingAction.setEnabled(False) self.killAction.setEnabled(False) self.killAllAction.setEnabled(False) self.cancelAction.setEnabled(False) self.cancelAllAction.setEnabled(False) self.editWaitingAction.setEnabled(False) self.clearHistoryAction.setEnabled(False) self.refreshWaitingAction.setEnabled(False) self.refreshRunningAction.setEnabled(False) self.refreshHistoryAction.setEnabled(False) self.partialRefreshHistoryAction.setEnabled(False) self.disableAction.setEnabled(False) self.enableAction.setEnabled(False) def loadProjects(self, data): """ Load all projects """ self.projects = data def loadRunning (self, data): """ Loads running tasks @param data: @type data: dict """ self.nbRunningLabel.setText( str( len(data) ) ) for task in data: if self.getProjectName(task['project-id']) == "UNKNOWN": continue taskItem = TaskRunningItem( task = task, parent= self.testManager ) # resize cols for i in xrange(len(self.labels2) - 1): self.testManager.resizeColumnToContents(i) # change sort order if self.ascendingOrder: self.testWaiting.sortItems(2, Qt.AscendingOrder) # sort by sched time self.testManager.sortItems(2, Qt.DescendingOrder) def updateRunning(self, data): """ Update running tasks @param data: @type data: """ self.testManager.clear() self.loadRunning( data=data ) def loadWaiting (self, data): """ Loads waiting tasks @param data: @type data: dict """ self.nbWaitingLabel.setText( str(len(data)) ) for task in data: eventid, eventtype, eventargs, eventtime, eventname, author, realruntime, duration, result, eventnb, \ eventnbcur, eventenabled, withoutprobes, withoutnotif, nokeeptr, userid, projectid, eventfrom, eventto, groupid = task if self.getProjectName(projectid) == "UNKNOWN": continue taskItem = TaskWaitingItem( task = task, parent= self.testWaiting ) # resize cols for i in xrange(len(self.labels2) - 1): self.testWaiting.resizeColumnToContents(i) # change sort order if self.ascendingOrderHistory: self.testWaiting.sortItems(3, Qt.AscendingOrder) self.testWaiting.sortItems(3, Qt.DescendingOrder) def updateWaiting(self, data): """ Update waiting tasks @param data: @type data: """ self.testWaiting.clear() self.loadWaiting( data=data ) def loadEnqueued (self, data): """ Loads enqueued tasks @param data: @type data: dict """ for (groupId, groupData) in data.items(): groupName, groupsTests = groupData pluriel = '' if len(groupsTests) > 1: pluriel = '' groupTask = TaskEnqueuedItem( parent=self.testEnqueued, text="%s - %s - (%s test%s)" % (groupId, groupName, len(groupsTests), pluriel) ) groupTask.setExpanded(True) for gTest in groupsTests: tDict = eval(gTest) tst = "%s:%s.%s" % ( self.getProjectName(tDict['prj-id']), tDict['test-path'], tDict['test-extension']) # set the icon according to the type of test if tDict['test-extension'] == 'tux': testIcon = QIcon(":/tux.png") if tDict['test-extension'] == 'tax': testIcon = QIcon(":/tax.png") if tDict['test-extension'] == 'tsx': testIcon = QIcon(":/tsx.png") if tDict['test-extension'] == 'tpx': testIcon = QIcon(":/tpx.png") if tDict['test-extension'] == 'tgx': testIcon = QIcon(":/tgx.png") subTask = TaskEnqueuedItem(parent=groupTask, text=tst, icon=testIcon) def updateEnqueued(self, data): """ Update enqueued tasks @param data: @type data: """ self.testEnqueued.clear() self.loadEnqueued( data=data ) def loadHistory (self, data): """ Loads history tasks @param data: @type data: dict """ # Init counters nbComplete = int(self.nbCompleteHistoryLabel.text()) nbError = int(self.nbErrorHistoryLabel.text()) nbKilled = int(self.nbKilledHistoryLabel.text()) nbCancelled = int(self.nbCancelledHistoryLabel.text()) for task in data: dbid, eventtype, eventargs, eventtime, eventname, author, realruntime, duration, result, projectid = task if self.getProjectName(projectid) == "UNKNOWN": continue taskItem = TaskHistoryItem( task = task, parent= self.testHistory ) if taskItem.taskEventResult == STATE_COMPLETE: nbComplete += 1 if taskItem.taskEventResult == STATE_ERROR: nbError += 1 if taskItem.taskEventResult == STATE_KILLED: nbKilled += 1 if taskItem.taskEventResult == STATE_CANCELLED: nbCancelled += 1 # resize cols for i in xrange(len(self.labels2) - 1): self.testHistory.resizeColumnToContents(i) # change sort order by sched at if self.ascendingOrderHistory: self.testHistory.sortItems(0, Qt.AscendingOrder) self.testHistory.sortItems(0, Qt.DescendingOrder) # Update summary nbHistory = int(self.nbHistoryLabel.text()) self.nbHistoryLabel.setText( str( len(data) + nbHistory ) ) self.nbCompleteHistoryLabel.setText( str(nbComplete) ) self.nbErrorHistoryLabel.setText( str(nbError) ) self.nbKilledHistoryLabel.setText( str(nbKilled) ) self.nbCancelledHistoryLabel.setText( str(nbCancelled) ) def updateHistory(self, data): """ Update history tasks @param data: @type data: """ # reset counters self.nbHistoryLabel.setText("0") self.nbCompleteHistoryLabel.setText("0") self.nbErrorHistoryLabel.setText("0") self.nbKilledHistoryLabel.setText("0") self.nbCancelledHistoryLabel.setText("0") # self.testHistory.clear() self.loadHistory( data=data ) def refreshRunningTask(self, data, action): """ Refresh running task @param data: @type data: @param action: @type action: """ if action == "add": self.loadRunning(data=data) elif action == "update": self.updateRunning(data=data) else: pass # error def refreshWaitingTask(self, data, action): """ Refresh waiting task @param data: @type data: @param action: @type action: """ if action == "update": self.updateWaiting(data=data) else: pass # error def refreshEnqueuedTask(self, data, action): """ Refresh enqueued task @param data: @type data: @param action: @type action: """ if action == "update": self.updateEnqueued(data=data) else: pass # error def refreshHistoryTask(self, data, action): """ Refresh history task @param data: @type data: @param action: @type action: """ if action == "add": self.loadHistory(data=data) elif action == "update": self.updateHistory(data=data) else: pass # error def onPopupMenu(self, pos): """ Display menu on right click @param pos: @type pos: """ self.menu = QMenu() item = self.testManager.itemAt(pos) if item: self.itemCurrent = item # kill task available just for admin and tester if UCI.RIGHTS_ADMIN in RCI.instance().userRights or UCI.RIGHTS_TESTER in RCI.instance().userRights : if item.taskState == STATE_RUNNING : self.menu.addAction( self.killAction ) self.menu.popup(self.testManager.mapToGlobal(pos)) def onPopupMenuWaiting(self, pos): """ Display menu on right click @param pos: @type pos: """ self.menu = QMenu() item = self.testWaiting.itemAt(pos) if item: self.itemCurrent = item # kill task available just for admin and tester if UCI.RIGHTS_ADMIN in RCI.instance().userRights or UCI.RIGHTS_TESTER in RCI.instance().userRights : self.menu.addAction( self.editWaitingAction ) self.menu.addAction( self.cancelAction ) self.menu.addSeparator() self.menu.addAction( self.disableAction ) self.menu.addAction( self.enableAction ) self.menu.popup(self.testWaiting.mapToGlobal(pos)) def cancelTask(self): """ Cancel the selected task """ items = self.testWaiting.selectedItems() taskIds = [] for itm in items: taskIds.append( itm.taskId ) reply = QMessageBox.question(self, "Cancel test(s)", "Are you sure ?", QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.Yes: RCI.instance().cancelTasks(taskIds=taskIds) def cancelAllTasks(self): """ Cancel all tasks """ reply = QMessageBox.question(self, "Cancel all tests", "Are you sure ?", QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.Yes: RCI.instance().cancelTasksAll() def killTask(self): """ Kill the selected task """ items = self.testManager.selectedItems() taskIds = [] for itm in items: taskIds.append( itm.taskId ) reply = QMessageBox.question(self, "Kill test", "Are you sure ?", QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.Yes: RCI.instance().killTasks(taskIds=taskIds) def killAllTasks(self): """ Kill all tasks """ reply = QMessageBox.question(self, "Kill all tests", "Are you sure ?", QMessageBox.Yes | QMessageBox.No ) if reply == QMessageBox.Yes: RCI.instance().killTasksAll() def toggleSort(self): """ Toggle sort of running task """ if not self.ascendingOrder: self.testManager.sortItems(2, Qt.AscendingOrder) self.ascendingOrder = True else: self.testManager.sortItems(2, Qt.DescendingOrder) self.ascendingOrder = False def toggleSortHistory(self): """ Toggle sort of the history """ if not self.ascendingOrderHistory: self.testHistory.sortItems(0, Qt.AscendingOrder) self.ascendingOrderHistory = True else: self.testHistory.sortItems(0, Qt.DescendingOrder) self.ascendingOrderHistory = False def toggleSortWaiting(self): """ Toggle sort of the waiting """ if not self.ascendingOrderWaiting: self.testWaiting.sortItems(3, Qt.AscendingOrder) self.ascendingOrderWaiting = True else: self.testWaiting.sortItems(3, Qt.DescendingOrder) self.ascendingOrderWaiting = False
def setupSmartAutoFeeByteUI(self, feeEstimate, blocksToConfirm, strat): def setAutoFeeByte(): def callbck(): return self.selectType('Auto') return callbck stratList = [FEEBYTE_CONSERVATIVE, FEEBYTE_ECONOMICAL] def updateLbl(): self.updateCoinSelection() def getStrategyString(): try: cbIndex = self.comboStrat.currentIndex() return stratList[cbIndex] except: return FEEBYTE_CONSERVATIVE def feeByteToStr(feeByte): try: self.feeByte = feeByte return "<u>%.1f</u>" % feeByte except: self.feeByte = -1 if isinstance(feeByte, str): return feeByte else: return "N/A" radioButtonTxt = self.tr("Fee rate from node (sat/Byte): ") if not self.validAutoFee: radioButtonTxt = self.tr("Failed to fetch fee/byte from node") self.radioAutoFeeByte = QRadioButton(radioButtonTxt) self.lblAutoFeeByte = QLabel(feeByteToStr(feeEstimate)) self.lblAutoFeeByte.setFont(GETFONT('Fixed')) self.lblAutoFeeByte.setMinimumWidth( tightSizeNChar(self.lblAutoFeeByte, 6)[0]) self.lblAutoFeeByte.setMaximumWidth( tightSizeNChar(self.lblAutoFeeByte, 12)[0]) self.sliderAutoFeeByte = QSlider(Qt.Horizontal, self) self.sliderAutoFeeByte.setMinimum(2) self.sliderAutoFeeByte.setMaximum(100) self.sliderAutoFeeByte.setValue(blocksToConfirm) self.lblSlider = QLabel() self.lblStrat = QLabel(self.tr("Profile:")) self.ttStart = self.main.createToolTipWidget( self.tr(''' <u>Fee Estimation Profiles:</u><br><br> <b>CONSERVATIVE:</b> Short term estimate. More reactive to current changes in the mempool. Use this estimate if you want a high probability of getting your transaction mined quickly. <br><br> <b>ECONOMICAL:</b> Long term estimate. Ignores short term changes to the mempool. Use this profile if you want low fees and can tolerate swings in the projected confirmation window. <br><br> The estimate profiles may not diverge until your node has gathered enough data from the network to refine its predictions. Refer to the \"estimatesmartfee\" section in the Bitcoin Core 0.15 changelog for more informations. ''')) self.comboStrat = QComboBox() currentIndex = 0 for i in range(len(stratList)): self.comboStrat.addItem(stratList[i]) if stratList[i] == strat: currentIndex = i self.comboStrat.setCurrentIndex(currentIndex) def getSliderLabelTxt(): return self.tr("Blocks to confirm: %1").arg(\ unicode(self.sliderAutoFeeByte.value())) def updateAutoFeeByte(): blocksToConfirm = self.sliderAutoFeeByte.value() strategy = getStrategyString() try: feeEstimate, version, err = \ self.getFeeByteFromNode(blocksToConfirm, strategy) except: feeEstimate = "N/A" self.lblSlider.setText(getSliderLabelTxt()) self.lblAutoFeeByte.setText(feeByteToStr(feeEstimate)) updateLbl() def stratComboChange(): updateAutoFeeByte() self.lblSlider.setText(getSliderLabelTxt()) self.connect(self.radioAutoFeeByte, SIGNAL('clicked()'), setAutoFeeByte()) self.sliderAutoFeeByte.valueChanged.connect(updateAutoFeeByte) self.sliderAutoFeeByte.setEnabled(False) self.connect(self.comboStrat, SIGNAL('currentIndexChanged(int)'), stratComboChange) frmAutoFeeByte = QFrame() frmAutoFeeByte.setFrameStyle(STYLE_RAISED) layoutAutoFeeByte = QGridLayout() layoutAutoFeeByte.addWidget(self.radioAutoFeeByte, 0, 0, 1, 2) layoutAutoFeeByte.addWidget(self.lblAutoFeeByte, 0, 2, 1, 2) layoutAutoFeeByte.addWidget(self.lblSlider, 1, 0, 1, 1) layoutAutoFeeByte.addWidget(self.sliderAutoFeeByte, 2, 0, 1, 4) layoutAutoFeeByte.addWidget(self.lblStrat, 3, 0, 1, 1) layoutAutoFeeByte.addWidget(self.comboStrat, 3, 1, 1, 2) layoutAutoFeeByte.addWidget(self.ttStart, 3, 3, 1, 1) frmAutoFeeByte.setLayout(layoutAutoFeeByte) if not self.validAutoFee: frmAutoFeeByte.setEnabled(False) return frmAutoFeeByte
def setupLegacyAutoFeeByteUI(self, feeEstimate, blocksToConfirm): def setAutoFeeByte(): def callbck(): return self.selectType('Auto') return callbck def updateLbl(): self.updateCoinSelection() def feeByteToStr(feeByte): try: self.feeByte = feeByte return "<u>%.1f</u>" % feeByte except: self.feeByte = -1 if isinstance(feeByte, str): return feeByte else: return "N/A" radioButtonTxt = self.tr("Fee rate from node (sat/Byte): ") if not self.validAutoFee: radioButtonTxt = self.tr("Failed to fetch fee/byte from node") self.radioAutoFeeByte = QRadioButton(radioButtonTxt) self.lblAutoFeeByte = QLabel(feeByteToStr(feeEstimate)) self.lblAutoFeeByte.setFont(GETFONT('Fixed')) self.lblAutoFeeByte.setMinimumWidth( tightSizeNChar(self.lblAutoFeeByte, 6)[0]) self.lblAutoFeeByte.setMaximumWidth( tightSizeNChar(self.lblAutoFeeByte, 12)[0]) self.sliderAutoFeeByte = QSlider(Qt.Horizontal, self) self.sliderAutoFeeByte.setMinimum(2) self.sliderAutoFeeByte.setMaximum(6) self.sliderAutoFeeByte.setValue(blocksToConfirm) self.lblSlider = QLabel() def getSliderLabelTxt(): return self.tr("Blocks to confirm: %1").arg(\ unicode(self.sliderAutoFeeByte.value())) def updateAutoFeeByte(): blocksToConfirm = self.sliderAutoFeeByte.value() try: feeEstimate, version, err = \ self.getFeeByteFromNode(blocksToConfirm, FEEBYTE_CONSERVATIVE) except: feeEstimate = "N/A" self.lblSlider.setText(getSliderLabelTxt()) self.lblAutoFeeByte.setText(feeByteToStr(feeEstimate)) updateLbl() self.lblSlider.setText(getSliderLabelTxt()) self.connect(self.radioAutoFeeByte, SIGNAL('clicked()'), setAutoFeeByte()) self.sliderAutoFeeByte.valueChanged.connect(updateAutoFeeByte) self.sliderAutoFeeByte.setEnabled(False) frmAutoFeeByte = QFrame() frmAutoFeeByte.setFrameStyle(STYLE_RAISED) layoutAutoFeeByte = QGridLayout() layoutAutoFeeByte.addWidget(self.radioAutoFeeByte, 0, 0, 1, 1) layoutAutoFeeByte.addWidget(self.lblAutoFeeByte, 0, 1, 1, 1) layoutAutoFeeByte.addWidget(self.lblSlider, 1, 0, 1, 2) layoutAutoFeeByte.addWidget(self.sliderAutoFeeByte, 2, 0, 1, 2) frmAutoFeeByte.setLayout(layoutAutoFeeByte) if not self.validAutoFee: frmAutoFeeByte.setEnabled(False) return frmAutoFeeByte
def setupSmartAutoFeeByteUI(self, feeEstimate, blocksToConfirm, strat): def setAutoFeeByte(): def callbck(): return self.selectType('Auto') return callbck stratList = [FEEBYTE_CONSERVATIVE, FEEBYTE_ECONOMICAL] def updateLbl(): self.updateCoinSelection() def getStrategyString(): try: cbIndex = self.comboStrat.currentIndex() return stratList[cbIndex] except: return FEEBYTE_CONSERVATIVE def feeByteToStr(feeByte): try: self.feeByte = feeByte return "<u>%.1f</u>" % feeByte except: self.feeByte = -1 if isinstance(feeByte, str): return feeByte else: return "N/A" radioButtonTxt = self.tr("Fee rate from node (sat/Byte): ") if not self.validAutoFee: radioButtonTxt = self.tr("Failed to fetch fee/byte from node") self.radioAutoFeeByte = QRadioButton(radioButtonTxt) self.lblAutoFeeByte = QLabel(feeByteToStr(feeEstimate)) self.lblAutoFeeByte.setFont(GETFONT('Fixed')) self.lblAutoFeeByte.setMinimumWidth(tightSizeNChar(self.lblAutoFeeByte, 6)[0]) self.lblAutoFeeByte.setMaximumWidth(tightSizeNChar(self.lblAutoFeeByte, 12)[0]) self.sliderAutoFeeByte = QSlider(Qt.Horizontal, self) self.sliderAutoFeeByte.setMinimum(2) self.sliderAutoFeeByte.setMaximum(100) self.sliderAutoFeeByte.setValue(blocksToConfirm) self.lblSlider = QLabel() self.lblStrat = QLabel(self.tr("Profile:")) self.ttStart = self.main.createToolTipWidget(self.tr( ''' <u>Fee Estimation Profiles:</u><br><br> <b>CONSERVATIVE:</b> Short term estimate. More reactive to current changes in the mempool. Use this estimate if you want a high probability of getting your transaction mined quickly. <br><br> <b>ECONOMICAL:</b> Long term estimate. Ignores short term changes to the mempool. Use this profile if you want low fees and can tolerate swings in the projected confirmation window. <br><br> The estimate profiles may not diverge until your node has gathered enough data from the network to refine its predictions. Refer to the \"estimatesmartfee\" section in the Bitcoin Core 0.15 changelog for more informations. ''')) self.comboStrat = QComboBox() currentIndex = 0 for i in range(len(stratList)): self.comboStrat.addItem(stratList[i]) if stratList[i] == strat: currentIndex = i self.comboStrat.setCurrentIndex(currentIndex) def getSliderLabelTxt(): return self.tr("Blocks to confirm: %1").arg(\ unicode(self.sliderAutoFeeByte.value())) def updateAutoFeeByte(): blocksToConfirm = self.sliderAutoFeeByte.value() strategy = getStrategyString() try: feeEstimate, version, err = \ self.getFeeByteFromNode(blocksToConfirm, strategy) except: feeEstimate = "N/A" self.lblSlider.setText(getSliderLabelTxt()) self.lblAutoFeeByte.setText(feeByteToStr(feeEstimate)) updateLbl() def stratComboChange(): updateAutoFeeByte() self.lblSlider.setText(getSliderLabelTxt()) self.connect(self.radioAutoFeeByte, SIGNAL('clicked()'), setAutoFeeByte()) self.sliderAutoFeeByte.valueChanged.connect(updateAutoFeeByte) self.sliderAutoFeeByte.setEnabled(False) self.connect(self.comboStrat, SIGNAL('currentIndexChanged(int)'), stratComboChange) frmAutoFeeByte = QFrame() frmAutoFeeByte.setFrameStyle(STYLE_RAISED) layoutAutoFeeByte = QGridLayout() layoutAutoFeeByte.addWidget(self.radioAutoFeeByte, 0, 0, 1, 2) layoutAutoFeeByte.addWidget(self.lblAutoFeeByte, 0, 2, 1, 2) layoutAutoFeeByte.addWidget(self.lblSlider, 1, 0, 1, 1) layoutAutoFeeByte.addWidget(self.sliderAutoFeeByte, 2, 0, 1, 4) layoutAutoFeeByte.addWidget(self.lblStrat, 3, 0, 1, 1) layoutAutoFeeByte.addWidget(self.comboStrat, 3, 1, 1, 2) layoutAutoFeeByte.addWidget(self.ttStart, 3, 3, 1, 1) frmAutoFeeByte.setLayout(layoutAutoFeeByte) if not self.validAutoFee: frmAutoFeeByte.setEnabled(False) return frmAutoFeeByte
def setupLegacyAutoFeeByteUI(self, feeEstimate, blocksToConfirm): def setAutoFeeByte(): def callbck(): return self.selectType('Auto') return callbck def updateLbl(): self.updateCoinSelection() def feeByteToStr(feeByte): try: self.feeByte = feeByte return "<u>%.1f</u>" % feeByte except: self.feeByte = -1 if isinstance(feeByte, str): return feeByte else: return "N/A" radioButtonTxt = self.tr("Fee rate from node (sat/Byte): ") if not self.validAutoFee: radioButtonTxt = self.tr("Failed to fetch fee/byte from node") self.radioAutoFeeByte = QRadioButton(radioButtonTxt) self.lblAutoFeeByte = QLabel(feeByteToStr(feeEstimate)) self.lblAutoFeeByte.setFont(GETFONT('Fixed')) self.lblAutoFeeByte.setMinimumWidth(tightSizeNChar(self.lblAutoFeeByte, 6)[0]) self.lblAutoFeeByte.setMaximumWidth(tightSizeNChar(self.lblAutoFeeByte, 12)[0]) self.sliderAutoFeeByte = QSlider(Qt.Horizontal, self) self.sliderAutoFeeByte.setMinimum(2) self.sliderAutoFeeByte.setMaximum(6) self.sliderAutoFeeByte.setValue(blocksToConfirm) self.lblSlider = QLabel() def getSliderLabelTxt(): return self.tr("Blocks to confirm: %1").arg(\ unicode(self.sliderAutoFeeByte.value())) def updateAutoFeeByte(): blocksToConfirm = self.sliderAutoFeeByte.value() try: feeEstimate, version, err = \ self.getFeeByteFromNode(blocksToConfirm, FEEBYTE_CONSERVATIVE) except: feeEstimate = "N/A" self.lblSlider.setText(getSliderLabelTxt()) self.lblAutoFeeByte.setText(feeByteToStr(feeEstimate)) updateLbl() self.lblSlider.setText(getSliderLabelTxt()) self.connect(self.radioAutoFeeByte, SIGNAL('clicked()'), setAutoFeeByte()) self.sliderAutoFeeByte.valueChanged.connect(updateAutoFeeByte) self.sliderAutoFeeByte.setEnabled(False) frmAutoFeeByte = QFrame() frmAutoFeeByte.setFrameStyle(STYLE_RAISED) layoutAutoFeeByte = QGridLayout() layoutAutoFeeByte.addWidget(self.radioAutoFeeByte, 0, 0, 1, 1) layoutAutoFeeByte.addWidget(self.lblAutoFeeByte, 0, 1, 1, 1) layoutAutoFeeByte.addWidget(self.lblSlider, 1, 0, 1, 2) layoutAutoFeeByte.addWidget(self.sliderAutoFeeByte, 2, 0, 1, 2) frmAutoFeeByte.setLayout(layoutAutoFeeByte) if not self.validAutoFee: frmAutoFeeByte.setEnabled(False) return frmAutoFeeByte