Skip to content
Snippets Groups Projects
Commit 657d4212 authored by djarosz's avatar djarosz :robot:
Browse files

Add a settings page that allows user to specify refresh cylce and perform...

Add a settings page that allows user to specify refresh cylce and perform refresh cycle according to setting. Closes #11
parent 2119f1f1
No related branches found
No related tags found
No related merge requests found
...@@ -4,13 +4,15 @@ from __future__ import print_function ...@@ -4,13 +4,15 @@ from __future__ import print_function
import sys import sys
import os import os
from PyQt4.QtGui import QMainWindow, QStackedLayout, QApplication, QWidget, QTabWidget, QSplashScreen, QPixmap, QMenu, QAction, QCursor, QMessageBox, QAbstractButton from PyQt4.QtGui import QMainWindow, QStackedLayout, QApplication, QWidget, QTabWidget, QSplashScreen, QPixmap, QMenu, \
QAction, QCursor, QMessageBox, QAbstractButton, QIcon
from PyQt4.QtCore import Qt, QTimer from PyQt4.QtCore import Qt, QTimer
from time import sleep, time from time import sleep, time
import smtplib import smtplib
from email.mime.text import MIMEText from email.mime.text import MIMEText
from traceback import format_tb from traceback import format_tb
from dm.aps_beamline_tools.gui.settingsTab import SettingsTab
from dm.common.constants import dmStatus from dm.common.constants import dmStatus
from dm.common.exceptions.dmException import DmException from dm.common.exceptions.dmException import DmException
from dm.common.exceptions.configurationError import ConfigurationError from dm.common.exceptions.configurationError import ConfigurationError
...@@ -104,6 +106,7 @@ class DmStationUi(QMainWindow): ...@@ -104,6 +106,7 @@ class DmStationUi(QMainWindow):
self.fileTab = FileTab(self.stationName, self) self.fileTab = FileTab(self.stationName, self)
self.workflowTab = WorkflowTab(self.stationName, self) self.workflowTab = WorkflowTab(self.stationName, self)
self.processingJobsTab = ProcessingJobsTab(self.stationName, self) self.processingJobsTab = ProcessingJobsTab(self.stationName, self)
self.settingsTab = SettingsTab(self)
# Add the windows to the stack. # Add the windows to the stack.
self.stackedLayout.addWidget(self.experimentsTab) self.stackedLayout.addWidget(self.experimentsTab)
...@@ -124,6 +127,19 @@ class DmStationUi(QMainWindow): ...@@ -124,6 +127,19 @@ class DmStationUi(QMainWindow):
# Hide until ready for release # Hide until ready for release
self.tabs.addTab(self.workflowTab, "Workflows") self.tabs.addTab(self.workflowTab, "Workflows")
self.tabs.addTab(self.processingJobsTab, "Processing Jobs") self.tabs.addTab(self.processingJobsTab, "Processing Jobs")
homeDir = os.path.dirname(sys.argv[0])
settingsIcon = QIcon(homeDir + '/images/settings.svg')
self.tabs.addTab(self.settingsTab, settingsIcon, "Settings")
self.refreshDaqsTimer = QTimer()
self.refreshDaqsTimer.timeout.connect(self.refreshDaqs)
self.refreshUploadsTimer = QTimer()
self.refreshUploadsTimer.timeout.connect(self.refreshUploads)
self.refreshExperimentsTimer = QTimer()
self.refreshExperimentsTimer.timeout.connect(self.refreshExperiments)
self.refreshJobsTimer = QTimer()
self.refreshJobsTimer.timeout.connect(self.refreshJobs)
self.setUpRefreshTimers()
# Set a central widget to hold everything # Set a central widget to hold everything
self.setCentralWidget(self.tabs) self.setCentralWidget(self.tabs)
...@@ -204,6 +220,34 @@ class DmStationUi(QMainWindow): ...@@ -204,6 +220,34 @@ class DmStationUi(QMainWindow):
def clearSelection(self, table): def clearSelection(self, table):
table.clearSelection() table.clearSelection()
def setUpRefreshTimers(self):
self.refreshDaqsTimer.stop()
self.refreshExperimentsTimer.stop()
self.refreshUploadsTimer.stop()
self._startRefreshTimer(self.refreshDaqsTimer, self.settingsTab.fetchRefCycleDaqs())
self._startRefreshTimer(self.refreshUploadsTimer, self.settingsTab.fetchRefCycleUploads())
self._startRefreshTimer(self.refreshExperimentsTimer, self.settingsTab.fetchRefCycleExperiments())
self._startRefreshTimer(self.refreshJobsTimer, self.settingsTab.fetchRefCycleJobs())
def _startRefreshTimer(self, timer, seconds):
# 0 means that no refresh cycle will occur
if seconds != 0:
interval = seconds * 1000
timer.start(interval)
def refreshExperiments(self):
self.experimentsTab.updateList()
def refreshDaqs(self):
self.daqsTab.updateList()
def refreshUploads(self):
self.uploadsTab.updateList()
def refreshJobs(self):
self.processingJobsTab.updateList()
# Refreshes the experiments, DAQ, and Uploads tables. # Refreshes the experiments, DAQ, and Uploads tables.
def refreshTables(self): def refreshTables(self):
self.experimentsTab.updateList() self.experimentsTab.updateList()
...@@ -292,10 +336,6 @@ if __name__ == "__main__": ...@@ -292,10 +336,6 @@ if __name__ == "__main__":
sleep(0.001) sleep(0.001)
app.processEvents() app.processEvents()
window = DmStationUi() window = DmStationUi()
# Calls refreshTables every minute
timer = QTimer()
timer.timeout.connect(window.refreshTables)
timer.start(60000)
splashScreen.finish(window) splashScreen.finish(window)
window.show() window.show()
window.raise_() window.raise_()
......
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 478.703 478.703" style="enable-background:new 0 0 478.703 478.703;" xml:space="preserve">
<g>
<g>
<path d="M454.2,189.101l-33.6-5.7c-3.5-11.3-8-22.2-13.5-32.6l19.8-27.7c8.4-11.8,7.1-27.9-3.2-38.1l-29.8-29.8
c-5.6-5.6-13-8.7-20.9-8.7c-6.2,0-12.1,1.9-17.1,5.5l-27.8,19.8c-10.8-5.7-22.1-10.4-33.8-13.9l-5.6-33.2
c-2.4-14.3-14.7-24.7-29.2-24.7h-42.1c-14.5,0-26.8,10.4-29.2,24.7l-5.8,34c-11.2,3.5-22.1,8.1-32.5,13.7l-27.5-19.8
c-5-3.6-11-5.5-17.2-5.5c-7.9,0-15.4,3.1-20.9,8.7l-29.9,29.8c-10.2,10.2-11.6,26.3-3.2,38.1l20,28.1
c-5.5,10.5-9.9,21.4-13.3,32.7l-33.2,5.6c-14.3,2.4-24.7,14.7-24.7,29.2v42.1c0,14.5,10.4,26.8,24.7,29.2l34,5.8
c3.5,11.2,8.1,22.1,13.7,32.5l-19.7,27.4c-8.4,11.8-7.1,27.9,3.2,38.1l29.8,29.8c5.6,5.6,13,8.7,20.9,8.7c6.2,0,12.1-1.9,17.1-5.5
l28.1-20c10.1,5.3,20.7,9.6,31.6,13l5.6,33.6c2.4,14.3,14.7,24.7,29.2,24.7h42.2c14.5,0,26.8-10.4,29.2-24.7l5.7-33.6
c11.3-3.5,22.2-8,32.6-13.5l27.7,19.8c5,3.6,11,5.5,17.2,5.5l0,0c7.9,0,15.3-3.1,20.9-8.7l29.8-29.8c10.2-10.2,11.6-26.3,3.2-38.1
l-19.8-27.8c5.5-10.5,10.1-21.4,13.5-32.6l33.6-5.6c14.3-2.4,24.7-14.7,24.7-29.2v-42.1
C478.9,203.801,468.5,191.501,454.2,189.101z M451.9,260.401c0,1.3-0.9,2.4-2.2,2.6l-42,7c-5.3,0.9-9.5,4.8-10.8,9.9
c-3.8,14.7-9.6,28.8-17.4,41.9c-2.7,4.6-2.5,10.3,0.6,14.7l24.7,34.8c0.7,1,0.6,2.5-0.3,3.4l-29.8,29.8c-0.7,0.7-1.4,0.8-1.9,0.8
c-0.6,0-1.1-0.2-1.5-0.5l-34.7-24.7c-4.3-3.1-10.1-3.3-14.7-0.6c-13.1,7.8-27.2,13.6-41.9,17.4c-5.2,1.3-9.1,5.6-9.9,10.8l-7.1,42
c-0.2,1.3-1.3,2.2-2.6,2.2h-42.1c-1.3,0-2.4-0.9-2.6-2.2l-7-42c-0.9-5.3-4.8-9.5-9.9-10.8c-14.3-3.7-28.1-9.4-41-16.8
c-2.1-1.2-4.5-1.8-6.8-1.8c-2.7,0-5.5,0.8-7.8,2.5l-35,24.9c-0.5,0.3-1,0.5-1.5,0.5c-0.4,0-1.2-0.1-1.9-0.8l-29.8-29.8
c-0.9-0.9-1-2.3-0.3-3.4l24.6-34.5c3.1-4.4,3.3-10.2,0.6-14.8c-7.8-13-13.8-27.1-17.6-41.8c-1.4-5.1-5.6-9-10.8-9.9l-42.3-7.2
c-1.3-0.2-2.2-1.3-2.2-2.6v-42.1c0-1.3,0.9-2.4,2.2-2.6l41.7-7c5.3-0.9,9.6-4.8,10.9-10c3.7-14.7,9.4-28.9,17.1-42
c2.7-4.6,2.4-10.3-0.7-14.6l-24.9-35c-0.7-1-0.6-2.5,0.3-3.4l29.8-29.8c0.7-0.7,1.4-0.8,1.9-0.8c0.6,0,1.1,0.2,1.5,0.5l34.5,24.6
c4.4,3.1,10.2,3.3,14.8,0.6c13-7.8,27.1-13.8,41.8-17.6c5.1-1.4,9-5.6,9.9-10.8l7.2-42.3c0.2-1.3,1.3-2.2,2.6-2.2h42.1
c1.3,0,2.4,0.9,2.6,2.2l7,41.7c0.9,5.3,4.8,9.6,10,10.9c15.1,3.8,29.5,9.7,42.9,17.6c4.6,2.7,10.3,2.5,14.7-0.6l34.5-24.8
c0.5-0.3,1-0.5,1.5-0.5c0.4,0,1.2,0.1,1.9,0.8l29.8,29.8c0.9,0.9,1,2.3,0.3,3.4l-24.7,34.7c-3.1,4.3-3.3,10.1-0.6,14.7
c7.8,13.1,13.6,27.2,17.4,41.9c1.3,5.2,5.6,9.1,10.8,9.9l42,7.1c1.3,0.2,2.2,1.3,2.2,2.6v42.1H451.9z"/>
<path d="M239.4,136.001c-57,0-103.3,46.3-103.3,103.3s46.3,103.3,103.3,103.3s103.3-46.3,103.3-103.3S296.4,136.001,239.4,136.001
z M239.4,315.601c-42.1,0-76.3-34.2-76.3-76.3s34.2-76.3,76.3-76.3s76.3,34.2,76.3,76.3S281.5,315.601,239.4,315.601z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
#!/usr/bin/env python
from PyQt4.QtGui import QGridLayout, QSpacerItem, QSizePolicy, QPushButton, QWidget, \
QFont, QLabel, QTableWidget, QTableWidgetItem, QColor, QAbstractItemView, QHBoxLayout, QPalette, QFormLayout, \
QGroupBox, QLineEdit, QDoubleValidator, QIntValidator
from PyQt4.QtCore import Qt, QSettings, QString
from dm.aps_beamline_tools.gui.apiFactory import ApiFactory
from .subclasses import customSelectionModel, customStyledDelegate
# Define the Processing Jobs tab content:
class SettingsTab(QWidget):
ORG_NAME="UChicagoArgonneLLC"
APP_NAME="dmStationUi"
REF_CYCLE_EXPERIMENTS = "experimentsRefreshCycle"
REF_CYCLE_DAQS = "daqsRefreshCycle"
REF_CYCLE_UPLOADS = "uploadsRefreshCycle"
REF_CYCLE_JOBS = "processingJobsRefreshCycle"
DEFAULT_INTERVAL = 60
def __init__(self, parent):
super(SettingsTab, self).__init__(parent)
self.parent = parent
self.settingsLayout()
self.settings = QSettings(SettingsTab.ORG_NAME, SettingsTab.APP_NAME, self)
self.loadSettings()
# GUI layout where each block is a row on the grid
def settingsLayout(self):
grid = QGridLayout()
labelFont = QFont('Arial', 18, QFont.Bold)
lbl = QLabel('Settings', self)
lbl.setAlignment(Qt.AlignCenter)
lbl.setFont(labelFont)
grid.addWidget(lbl, 0, 0)
refIntervalGroup = QGroupBox()
refIntervalGroup.setAlignment(Qt.AlignCenter)
refIntervalGroup.setTitle("Refresh Intervals (seconds)")
refIntervalsFormLayout = QFormLayout()
self.experimentsRefInternvalVal = self._createIntInput(refIntervalsFormLayout, "Experiments", "Specify the interval in seconds for experiments refresh cycle (0 for no refresh)")
self.daqsRefInternvalVal = self._createIntInput(refIntervalsFormLayout, "Daqs", "Specify the interval in seconds for daqs refresh cycle (0 for no refresh)")
self.uploadsRefInternvalVal = self._createIntInput(refIntervalsFormLayout, "Uploads", "Specify the interval in seconds for uploads refresh cycle (0 for no refresh)")
self.jobsRefInternvalVal = self._createIntInput(refIntervalsFormLayout, "Processing Jobs",
"Specify the interval in seconds for processing jobs refresh cycle (0 for no refresh)")
refIntervalGroup.setLayout(refIntervalsFormLayout)
grid.addWidget(refIntervalGroup, 2, 0)
saveBtn = QPushButton('Save', self)
saveBtn.clicked.connect(self.saveSettings)
grid.addWidget(saveBtn, 3, 0, Qt.AlignCenter)
self.setLayout(grid)
def _createIntInput(self, formLayout, promptText, tooltip, min=0, max=1000):
minMaxText = " (" +str(min) + "-" + str(max)+")"
promptTextLabel = QLabel(promptText + minMaxText)
inputObject = QLineEdit()
inputObject.setValidator(QIntValidator(min, max, self))
inputObject.setToolTip(tooltip)
formLayout.addRow(promptTextLabel, inputObject)
return inputObject
def loadSettings(self):
self._loadIntervalSettings(SettingsTab.REF_CYCLE_UPLOADS, self.uploadsRefInternvalVal)
self._loadIntervalSettings(SettingsTab.REF_CYCLE_DAQS, self.daqsRefInternvalVal)
self._loadIntervalSettings(SettingsTab.REF_CYCLE_EXPERIMENTS, self.experimentsRefInternvalVal)
self._loadIntervalSettings(SettingsTab.REF_CYCLE_JOBS, self.jobsRefInternvalVal)
def _loadIntervalSettings(self, key, settingInputWidget):
refCycle = self.settings.value(key, SettingsTab.DEFAULT_INTERVAL).toString()
if (refCycle == ""):
refCycle = QString(str(SettingsTab.DEFAULT_INTERVAL))
settingInputWidget.setText(refCycle)
def saveSettings(self):
self.settings.setValue(SettingsTab.REF_CYCLE_DAQS, self.daqsRefInternvalVal.text())
self.settings.setValue(SettingsTab.REF_CYCLE_EXPERIMENTS, self.experimentsRefInternvalVal.text())
self.settings.setValue(SettingsTab.REF_CYCLE_UPLOADS, self.uploadsRefInternvalVal.text())
self.settings.setValue(SettingsTab.REF_CYCLE_JOBS, self.jobsRefInternvalVal.text())
self.loadSettings()
# Reload with the new values
self.parent.setUpRefreshTimers()
def fetchRefCycleExperiments(self):
return int(self.experimentsRefInternvalVal.text())
def fetchRefCycleDaqs(self):
return int(self.daqsRefInternvalVal.text())
def fetchRefCycleUploads(self):
return int(self.uploadsRefInternvalVal.text())
def fetchRefCycleJobs(self):
return int(self.jobsRefInternvalVal.text())
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment