Skip to content

Commit a34e6d0

Browse files
authored
Merge pull request #15 from pyobs/develop
v0.13
2 parents 0d0bb46 + 7668376 commit a34e6d0

File tree

13 files changed

+482
-208
lines changed

13 files changed

+482
-208
lines changed

pyobs_gui/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1+
"""
2+
TODO: write doc
3+
"""
4+
__title__ = 'GUI'
5+
16
from .gui import GUI

pyobs_gui/basewidget.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import threading
22
import logging
3+
from typing import List, Dict, Tuple, Any
34

45
from PyQt5 import QtWidgets, QtGui, QtCore
56
from PyQt5.QtCore import pyqtSignal
@@ -23,11 +24,11 @@ def __init__(self, update_func=None, update_interval: float = 1, *args, **kwargs
2324
# update thread
2425
self._update_func = update_func
2526
self._update_interval = update_interval
26-
self._update_thread = None
27-
self._update_thread_event = None
27+
self._update_thread = threading.Thread()
28+
self._update_thread_event = threading.Event()
2829

2930
# sidebar
30-
self.sidebar_widgets = []
31+
self.sidebar_widgets: List[BaseWidget] = []
3132
self.sidebar_layout = None
3233

3334
# has it been initialized?
@@ -65,18 +66,17 @@ def hideEvent(self, event: QtGui.QHideEvent) -> None:
6566
self._update_thread_event.set()
6667

6768
# wait for it
68-
if self._update_thread is not None:
69+
if self._update_thread.is_alive():
6970
self._update_thread.join()
70-
self._update_thread = None
71-
self._update_thread_event = None
7271

7372
def _update_loop_thread(self):
7473
while not self._update_thread_event.is_set():
7574
try:
7675
# call update function
7776
self._update_func()
78-
except:
79-
pass
77+
except Exception as e:
78+
log.warning("Exception during GUIs update function: %s",
79+
str(e))
8080

8181
# sleep a little
8282
self._update_thread_event.wait(self._update_interval)
@@ -107,7 +107,7 @@ def show_error(self, message):
107107
def enable_buttons(self, widgets, enable):
108108
[w.setEnabled(enable) for w in widgets]
109109

110-
def get_fits_headers(self, namespaces: list = None, *args, **kwargs) -> dict:
110+
def get_fits_headers(self, namespaces: List[str] = None, *args, **kwargs) -> Dict[str, Tuple[Any, str]]:
111111
"""Returns FITS header for the current status of this module.
112112
113113
Args:

pyobs_gui/gui.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import List, Dict, Tuple, Any
2+
13
from PyQt5 import QtWidgets
24

35
from pyobs.interfaces import IFitsHeaderProvider
@@ -6,6 +8,8 @@
68

79

810
class GUI(Module, IFitsHeaderProvider):
11+
__module__ = 'pyobs_gui'
12+
913
def __init__(self, *args, **kwargs):
1014
Module.__init__(self, *args, **kwargs)
1115
self._window = None
@@ -21,7 +25,7 @@ def main(self):
2125
# run
2226
app.exec()
2327

24-
def get_fits_headers(self, namespaces: list = None, *args, **kwargs) -> dict:
28+
def get_fits_headers(self, namespaces: List[str] = None, *args, **kwargs) -> Dict[str, Tuple[Any, str]]:
2529
"""Returns FITS header for the current status of this module.
2630
2731
Args:

pyobs_gui/mainwindow.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,29 @@
2020
from pyobs_gui.widgetweather import WidgetWeather
2121

2222

23+
class PagesListWidgetItem(QtWidgets.QListWidgetItem):
24+
"""ListWidgetItem for the pages list. Always sorts Shell and Events first"""
25+
def __lt__(self, other):
26+
"""Compare two items."""
27+
28+
# special cases?
29+
if self.text() == 'Shell':
30+
# if self is 'Shell', it always goes first
31+
return True
32+
elif other.text() == 'Shell':
33+
# if other is 'Shell', it always goes later
34+
return False
35+
elif self.text() == 'Events':
36+
# if self is 'Events', it only goes first if other is not 'Shell'
37+
return other.text() != 'Shell'
38+
elif other.text() == 'Events':
39+
# if other is 'Events', self always goes later, since case of 'Shell' as self has always been dealt with
40+
return False
41+
else:
42+
# default case
43+
return QtWidgets.QListWidgetItem.__lt__(self, other)
44+
45+
2346
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
2447
add_log = pyqtSignal(list)
2548
add_command_log = pyqtSignal(str)
@@ -109,12 +132,13 @@ def _add_client(self, client: str, icon: QtGui.QIcon, widget: QtWidgets.QWidget)
109132
"""
110133

111134
# add list item
112-
item = QtWidgets.QListWidgetItem()
135+
item = PagesListWidgetItem()
113136
item.setIcon(icon)
114137
item.setText(client)
115138

116-
# add to list
139+
# add to list and sort
117140
self.listPages.addItem(item)
141+
self.listPages.sortItems()
118142

119143
# add widget
120144
self.stackedWidget.addWidget(widget)

pyobs_gui/qt/mainwindow.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,16 @@ def setupUi(self, MainWindow):
7474
sizePolicy.setVerticalStretch(0)
7575
sizePolicy.setHeightForWidth(self.listPages.sizePolicy().hasHeightForWidth())
7676
self.listPages.setSizePolicy(sizePolicy)
77+
self.listPages.setMinimumSize(QtCore.QSize(100, 0))
7778
self.listPages.setMaximumSize(QtCore.QSize(100, 16777215))
7879
self.listPages.setFrameShape(QtWidgets.QFrame.NoFrame)
80+
self.listPages.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
81+
self.listPages.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
82+
self.listPages.setProperty("showDropIndicator", False)
83+
self.listPages.setDragDropMode(QtWidgets.QAbstractItemView.NoDragDrop)
84+
self.listPages.setDefaultDropAction(QtCore.Qt.IgnoreAction)
7985
self.listPages.setIconSize(QtCore.QSize(64, 64))
86+
self.listPages.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
8087
self.listPages.setViewMode(QtWidgets.QListView.IconMode)
8188
self.listPages.setObjectName("listPages")
8289
self.horizontalLayout.addWidget(self.listPages)

pyobs_gui/qt/mainwindow.ui

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@
153153
<verstretch>0</verstretch>
154154
</sizepolicy>
155155
</property>
156+
<property name="minimumSize">
157+
<size>
158+
<width>100</width>
159+
<height>0</height>
160+
</size>
161+
</property>
156162
<property name="maximumSize">
157163
<size>
158164
<width>100</width>
@@ -162,12 +168,30 @@
162168
<property name="frameShape">
163169
<enum>QFrame::NoFrame</enum>
164170
</property>
171+
<property name="horizontalScrollBarPolicy">
172+
<enum>Qt::ScrollBarAlwaysOff</enum>
173+
</property>
174+
<property name="editTriggers">
175+
<set>QAbstractItemView::NoEditTriggers</set>
176+
</property>
177+
<property name="showDropIndicator" stdset="0">
178+
<bool>false</bool>
179+
</property>
180+
<property name="dragDropMode">
181+
<enum>QAbstractItemView::NoDragDrop</enum>
182+
</property>
183+
<property name="defaultDropAction">
184+
<enum>Qt::IgnoreAction</enum>
185+
</property>
165186
<property name="iconSize">
166187
<size>
167188
<width>64</width>
168189
<height>64</height>
169190
</size>
170191
</property>
192+
<property name="verticalScrollMode">
193+
<enum>QAbstractItemView::ScrollPerPixel</enum>
194+
</property>
171195
<property name="viewMode">
172196
<enum>QListView::IconMode</enum>
173197
</property>

pyobs_gui/qt/widgetcamera.py

Lines changed: 75 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class Ui_WidgetCamera(object):
1414
def setupUi(self, WidgetCamera):
1515
WidgetCamera.setObjectName("WidgetCamera")
16-
WidgetCamera.resize(967, 657)
16+
WidgetCamera.resize(1269, 810)
1717
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(WidgetCamera)
1818
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
1919
self.scrollArea = QtWidgets.QScrollArea(WidgetCamera)
@@ -26,7 +26,7 @@ def setupUi(self, WidgetCamera):
2626
self.scrollArea.setWidgetResizable(True)
2727
self.scrollArea.setObjectName("scrollArea")
2828
self.scrollAreaWidgetContents = QtWidgets.QWidget()
29-
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 183, 641))
29+
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 264, 794))
3030
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
3131
sizePolicy.setHorizontalStretch(0)
3232
sizePolicy.setVerticalStretch(0)
@@ -80,45 +80,30 @@ def setupUi(self, WidgetCamera):
8080
self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBinning)
8181
self.gridLayout_3.setSpacing(0)
8282
self.gridLayout_3.setObjectName("gridLayout_3")
83-
self.spinBinningY = QtWidgets.QSpinBox(self.groupBinning)
84-
self.spinBinningY.setMinimum(1)
85-
self.spinBinningY.setMaximum(3)
86-
self.spinBinningY.setObjectName("spinBinningY")
87-
self.gridLayout_3.addWidget(self.spinBinningY, 1, 1, 1, 1)
88-
self.spinBinningX = QtWidgets.QSpinBox(self.groupBinning)
89-
self.spinBinningX.setMinimum(1)
90-
self.spinBinningX.setMaximum(3)
91-
self.spinBinningX.setObjectName("spinBinningX")
92-
self.gridLayout_3.addWidget(self.spinBinningX, 0, 1, 1, 1)
93-
self.label_6 = QtWidgets.QLabel(self.groupBinning)
94-
self.label_6.setObjectName("label_6")
95-
self.gridLayout_3.addWidget(self.label_6, 1, 0, 1, 1)
9683
self.label_5 = QtWidgets.QLabel(self.groupBinning)
9784
self.label_5.setObjectName("label_5")
9885
self.gridLayout_3.addWidget(self.label_5, 0, 0, 1, 1)
86+
self.comboBinning = QtWidgets.QComboBox(self.groupBinning)
87+
self.comboBinning.setObjectName("comboBinning")
88+
self.gridLayout_3.addWidget(self.comboBinning, 0, 1, 1, 1)
9989
self.verticalLayout.addWidget(self.groupBinning)
90+
self.groupImageFormat = QtWidgets.QGroupBox(self.scrollAreaWidgetContents)
91+
self.groupImageFormat.setObjectName("groupImageFormat")
92+
self.gridLayout_6 = QtWidgets.QGridLayout(self.groupImageFormat)
93+
self.gridLayout_6.setSpacing(0)
94+
self.gridLayout_6.setObjectName("gridLayout_6")
95+
self.label_10 = QtWidgets.QLabel(self.groupImageFormat)
96+
self.label_10.setObjectName("label_10")
97+
self.gridLayout_6.addWidget(self.label_10, 0, 0, 1, 1)
98+
self.comboImageFormat = QtWidgets.QComboBox(self.groupImageFormat)
99+
self.comboImageFormat.setObjectName("comboImageFormat")
100+
self.gridLayout_6.addWidget(self.comboImageFormat, 0, 1, 1, 1)
101+
self.verticalLayout.addWidget(self.groupImageFormat)
100102
self.groupExposure = QtWidgets.QGroupBox(self.scrollAreaWidgetContents)
101103
self.groupExposure.setObjectName("groupExposure")
102104
self.gridLayout_4 = QtWidgets.QGridLayout(self.groupExposure)
103105
self.gridLayout_4.setSpacing(0)
104106
self.gridLayout_4.setObjectName("gridLayout_4")
105-
self.label_7 = QtWidgets.QLabel(self.groupExposure)
106-
self.label_7.setObjectName("label_7")
107-
self.gridLayout_4.addWidget(self.label_7, 1, 0, 1, 1)
108-
self.comboImageType = QtWidgets.QComboBox(self.groupExposure)
109-
self.comboImageType.setObjectName("comboImageType")
110-
self.gridLayout_4.addWidget(self.comboImageType, 0, 1, 1, 1)
111-
self.label_8 = QtWidgets.QLabel(self.groupExposure)
112-
self.label_8.setObjectName("label_8")
113-
self.gridLayout_4.addWidget(self.label_8, 2, 0, 1, 1)
114-
self.spinCount = QtWidgets.QSpinBox(self.groupExposure)
115-
self.spinCount.setMinimum(1)
116-
self.spinCount.setMaximum(9999)
117-
self.spinCount.setObjectName("spinCount")
118-
self.gridLayout_4.addWidget(self.spinCount, 2, 1, 1, 1)
119-
self.label_9 = QtWidgets.QLabel(self.groupExposure)
120-
self.label_9.setObjectName("label_9")
121-
self.gridLayout_4.addWidget(self.label_9, 0, 0, 1, 1)
122107
self.butExpose = QtWidgets.QPushButton(self.groupExposure)
123108
palette = QtGui.QPalette()
124109
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
@@ -267,7 +252,21 @@ def setupUi(self, WidgetCamera):
267252
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush)
268253
self.butExpose.setPalette(palette)
269254
self.butExpose.setObjectName("butExpose")
270-
self.gridLayout_4.addWidget(self.butExpose, 3, 0, 1, 2)
255+
self.gridLayout_4.addWidget(self.butExpose, 4, 0, 1, 2)
256+
self.spinCount = QtWidgets.QSpinBox(self.groupExposure)
257+
self.spinCount.setMinimum(1)
258+
self.spinCount.setMaximum(9999)
259+
self.spinCount.setObjectName("spinCount")
260+
self.gridLayout_4.addWidget(self.spinCount, 2, 1, 1, 1)
261+
self.comboImageType = QtWidgets.QComboBox(self.groupExposure)
262+
self.comboImageType.setObjectName("comboImageType")
263+
self.gridLayout_4.addWidget(self.comboImageType, 0, 1, 1, 1)
264+
self.labelImageType = QtWidgets.QLabel(self.groupExposure)
265+
self.labelImageType.setObjectName("labelImageType")
266+
self.gridLayout_4.addWidget(self.labelImageType, 0, 0, 1, 1)
267+
self.labelExpTime = QtWidgets.QLabel(self.groupExposure)
268+
self.labelExpTime.setObjectName("labelExpTime")
269+
self.gridLayout_4.addWidget(self.labelExpTime, 1, 0, 1, 1)
271270
self.butAbort = QtWidgets.QPushButton(self.groupExposure)
272271
palette = QtGui.QPalette()
273272
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
@@ -416,12 +415,32 @@ def setupUi(self, WidgetCamera):
416415
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush)
417416
self.butAbort.setPalette(palette)
418417
self.butAbort.setObjectName("butAbort")
419-
self.gridLayout_4.addWidget(self.butAbort, 4, 0, 1, 2)
418+
self.gridLayout_4.addWidget(self.butAbort, 5, 0, 1, 2)
419+
self.label_8 = QtWidgets.QLabel(self.groupExposure)
420+
self.label_8.setObjectName("label_8")
421+
self.gridLayout_4.addWidget(self.label_8, 2, 0, 1, 1)
422+
self.checkBroadcast = QtWidgets.QCheckBox(self.groupExposure)
423+
self.checkBroadcast.setChecked(True)
424+
self.checkBroadcast.setObjectName("checkBroadcast")
425+
self.gridLayout_4.addWidget(self.checkBroadcast, 3, 1, 1, 1)
426+
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
427+
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
420428
self.spinExpTime = QtWidgets.QDoubleSpinBox(self.groupExposure)
421-
self.spinExpTime.setMaximum(99999.0)
429+
self.spinExpTime.setSuffix("")
430+
self.spinExpTime.setDecimals(3)
431+
self.spinExpTime.setMaximum(999.0)
422432
self.spinExpTime.setProperty("value", 1.0)
423433
self.spinExpTime.setObjectName("spinExpTime")
424-
self.gridLayout_4.addWidget(self.spinExpTime, 1, 1, 1, 1)
434+
self.horizontalLayout_3.addWidget(self.spinExpTime)
435+
self.comboExpTimeUnit = QtWidgets.QComboBox(self.groupExposure)
436+
self.comboExpTimeUnit.setMinimumContentsLength(2)
437+
self.comboExpTimeUnit.setObjectName("comboExpTimeUnit")
438+
self.comboExpTimeUnit.addItem("")
439+
self.comboExpTimeUnit.addItem("")
440+
self.comboExpTimeUnit.addItem("")
441+
self.horizontalLayout_3.addWidget(self.comboExpTimeUnit)
442+
self.horizontalLayout_3.setStretch(0, 1)
443+
self.gridLayout_4.addLayout(self.horizontalLayout_3, 1, 1, 1, 1)
425444
self.verticalLayout.addWidget(self.groupExposure)
426445
spacerItem = QtWidgets.QSpacerItem(20, 26, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
427446
self.verticalLayout.addItem(spacerItem)
@@ -508,20 +527,20 @@ def setupUi(self, WidgetCamera):
508527
WidgetCamera.setTabOrder(self.spinWindowTop, self.spinWindowWidth)
509528
WidgetCamera.setTabOrder(self.spinWindowWidth, self.spinWindowHeight)
510529
WidgetCamera.setTabOrder(self.spinWindowHeight, self.butFullFrame)
511-
WidgetCamera.setTabOrder(self.butFullFrame, self.spinBinningX)
512-
WidgetCamera.setTabOrder(self.spinBinningX, self.spinBinningY)
513-
WidgetCamera.setTabOrder(self.spinBinningY, self.comboImageType)
514-
WidgetCamera.setTabOrder(self.comboImageType, self.spinExpTime)
515-
WidgetCamera.setTabOrder(self.spinExpTime, self.spinCount)
516-
WidgetCamera.setTabOrder(self.spinCount, self.butExpose)
530+
WidgetCamera.setTabOrder(self.butFullFrame, self.comboBinning)
531+
WidgetCamera.setTabOrder(self.comboBinning, self.comboImageFormat)
532+
WidgetCamera.setTabOrder(self.comboImageFormat, self.comboImageType)
533+
WidgetCamera.setTabOrder(self.comboImageType, self.spinCount)
534+
WidgetCamera.setTabOrder(self.spinCount, self.checkBroadcast)
535+
WidgetCamera.setTabOrder(self.checkBroadcast, self.butExpose)
517536
WidgetCamera.setTabOrder(self.butExpose, self.butAbort)
518-
WidgetCamera.setTabOrder(self.butAbort, self.tabWidget)
519-
WidgetCamera.setTabOrder(self.tabWidget, self.checkAutoUpdate)
537+
WidgetCamera.setTabOrder(self.butAbort, self.checkAutoUpdate)
520538
WidgetCamera.setTabOrder(self.checkAutoUpdate, self.checkAutoSave)
521539
WidgetCamera.setTabOrder(self.checkAutoSave, self.textAutoSavePath)
522540
WidgetCamera.setTabOrder(self.textAutoSavePath, self.butAutoSave)
523541
WidgetCamera.setTabOrder(self.butAutoSave, self.butSaveTo)
524-
WidgetCamera.setTabOrder(self.butSaveTo, self.tableFitsHeader)
542+
WidgetCamera.setTabOrder(self.butSaveTo, self.tabWidget)
543+
WidgetCamera.setTabOrder(self.tabWidget, self.tableFitsHeader)
525544

526545
def retranslateUi(self, WidgetCamera):
527546
_translate = QtCore.QCoreApplication.translate
@@ -532,16 +551,20 @@ def retranslateUi(self, WidgetCamera):
532551
self.label.setText(_translate("WidgetCamera", "Left:"))
533552
self.label_4.setText(_translate("WidgetCamera", "Height:"))
534553
self.butFullFrame.setText(_translate("WidgetCamera", "Full Frame"))
535-
self.groupBinning.setTitle(_translate("WidgetCamera", "Binning:"))
536-
self.label_6.setText(_translate("WidgetCamera", "Y:"))
537-
self.label_5.setText(_translate("WidgetCamera", "X:"))
554+
self.groupBinning.setTitle(_translate("WidgetCamera", "Binning"))
555+
self.label_5.setText(_translate("WidgetCamera", "XxY:"))
556+
self.groupImageFormat.setTitle(_translate("WidgetCamera", "Image format"))
557+
self.label_10.setText(_translate("WidgetCamera", "Format:"))
538558
self.groupExposure.setTitle(_translate("WidgetCamera", "Exposure"))
539-
self.label_7.setText(_translate("WidgetCamera", "ExpTime:"))
540-
self.label_8.setText(_translate("WidgetCamera", "Count:"))
541-
self.label_9.setText(_translate("WidgetCamera", "Type:"))
542559
self.butExpose.setText(_translate("WidgetCamera", "Expose"))
560+
self.labelImageType.setText(_translate("WidgetCamera", "Type:"))
561+
self.labelExpTime.setText(_translate("WidgetCamera", "ExpTime:"))
543562
self.butAbort.setText(_translate("WidgetCamera", "Abort"))
544-
self.spinExpTime.setSuffix(_translate("WidgetCamera", "s"))
563+
self.label_8.setText(_translate("WidgetCamera", "Count:"))
564+
self.checkBroadcast.setText(_translate("WidgetCamera", "Broadcast"))
565+
self.comboExpTimeUnit.setItemText(0, _translate("WidgetCamera", "s"))
566+
self.comboExpTimeUnit.setItemText(1, _translate("WidgetCamera", "ms"))
567+
self.comboExpTimeUnit.setItemText(2, _translate("WidgetCamera", "µs"))
545568
self.labelStatus.setText(_translate("WidgetCamera", "IDLE"))
546569
self.labelExposuresLeft.setText(_translate("WidgetCamera", "IDLE"))
547570
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabImage), _translate("WidgetCamera", "Image"))

0 commit comments

Comments
 (0)