Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
585db90
made binning a check box and added option for image format
thusser Feb 7, 2021
fda9fe0
set maximum values for window
thusser Feb 7, 2021
aeda5be
added combo box for setting image format
thusser Feb 7, 2021
1687d52
fetching available binnings from module
thusser Feb 7, 2021
f7c8b35
changed signature of ICameraBinning's list_binnings() to return list …
thusser Feb 8, 2021
622716a
hide controls if not required
thusser Feb 8, 2021
96a357c
added new checkbox to avoid broadcasting new images
thusser Feb 8, 2021
a92a0dc
changed order of setting max and current values
thusser Feb 8, 2021
d9dfc0f
show security question when disabling broadcast
thusser Feb 8, 2021
7b697ee
instead of manually connection signals/slot, use pyqtSlot()
thusser Feb 8, 2021
ebe6f6b
size of page selector
thusser Feb 9, 2021
7629c93
catch exception
thusser Feb 9, 2021
9b59174
sorting page icons
thusser Feb 9, 2021
d427e18
download images in thread
thusser Feb 16, 2021
f320ea1
Moved "images" module to top-level
thusser Feb 19, 2021
9bbf879
allow for negative offsets in dialog
thusser Feb 26, 2021
48df0e4
fixed bug when auto-saving
thusser Mar 3, 2021
1c44280
add warning to logger when GUIs update_func fails
Mar 22, 2021
d564ab0
added combo box for exposure time unit
thusser Mar 24, 2021
ee15fbc
fixed type hints
thusser Apr 9, 2021
eaf9510
fixed types to make mypy happy
thusser Apr 9, 2021
bcd9d94
fixed bug (_update_thread is never None)
thusser Apr 9, 2021
e4af37d
moved ExposureStatus to utils.enums
thusser Apr 14, 2021
109fce9
moved IMotion.Status to utils.enums.MotionStatus
thusser Apr 14, 2021
509a14e
moved IMotion.Status to utils.enums.MotionStatus
thusser Apr 14, 2021
f8662d0
updated docstrings
thusser Apr 16, 2021
43cf0a8
added __module__
thusser Apr 17, 2021
9f3c667
documentation
thusser Apr 18, 2021
7668376
v0.13
thusser Apr 30, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pyobs_gui/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
"""
TODO: write doc
"""
__title__ = 'GUI'

from .gui import GUI
18 changes: 9 additions & 9 deletions pyobs_gui/basewidget.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import threading
import logging
from typing import List, Dict, Tuple, Any

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import pyqtSignal
Expand All @@ -23,11 +24,11 @@ def __init__(self, update_func=None, update_interval: float = 1, *args, **kwargs
# update thread
self._update_func = update_func
self._update_interval = update_interval
self._update_thread = None
self._update_thread_event = None
self._update_thread = threading.Thread()
self._update_thread_event = threading.Event()

# sidebar
self.sidebar_widgets = []
self.sidebar_widgets: List[BaseWidget] = []
self.sidebar_layout = None

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

# wait for it
if self._update_thread is not None:
if self._update_thread.is_alive():
self._update_thread.join()
self._update_thread = None
self._update_thread_event = None

def _update_loop_thread(self):
while not self._update_thread_event.is_set():
try:
# call update function
self._update_func()
except:
pass
except Exception as e:
log.warning("Exception during GUIs update function: %s",
str(e))

# sleep a little
self._update_thread_event.wait(self._update_interval)
Expand Down Expand Up @@ -107,7 +107,7 @@ def show_error(self, message):
def enable_buttons(self, widgets, enable):
[w.setEnabled(enable) for w in widgets]

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

Args:
Expand Down
6 changes: 5 additions & 1 deletion pyobs_gui/gui.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import List, Dict, Tuple, Any

from PyQt5 import QtWidgets

from pyobs.interfaces import IFitsHeaderProvider
Expand All @@ -6,6 +8,8 @@


class GUI(Module, IFitsHeaderProvider):
__module__ = 'pyobs_gui'

def __init__(self, *args, **kwargs):
Module.__init__(self, *args, **kwargs)
self._window = None
Expand All @@ -21,7 +25,7 @@ def main(self):
# run
app.exec()

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

Args:
Expand Down
28 changes: 26 additions & 2 deletions pyobs_gui/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,29 @@
from pyobs_gui.widgetweather import WidgetWeather


class PagesListWidgetItem(QtWidgets.QListWidgetItem):
"""ListWidgetItem for the pages list. Always sorts Shell and Events first"""
def __lt__(self, other):
"""Compare two items."""

# special cases?
if self.text() == 'Shell':
# if self is 'Shell', it always goes first
return True
elif other.text() == 'Shell':
# if other is 'Shell', it always goes later
return False
elif self.text() == 'Events':
# if self is 'Events', it only goes first if other is not 'Shell'
return other.text() != 'Shell'
elif other.text() == 'Events':
# if other is 'Events', self always goes later, since case of 'Shell' as self has always been dealt with
return False
else:
# default case
return QtWidgets.QListWidgetItem.__lt__(self, other)


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
add_log = pyqtSignal(list)
add_command_log = pyqtSignal(str)
Expand Down Expand Up @@ -109,12 +132,13 @@ def _add_client(self, client: str, icon: QtGui.QIcon, widget: QtWidgets.QWidget)
"""

# add list item
item = QtWidgets.QListWidgetItem()
item = PagesListWidgetItem()
item.setIcon(icon)
item.setText(client)

# add to list
# add to list and sort
self.listPages.addItem(item)
self.listPages.sortItems()

# add widget
self.stackedWidget.addWidget(widget)
Expand Down
7 changes: 7 additions & 0 deletions pyobs_gui/qt/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,16 @@ def setupUi(self, MainWindow):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.listPages.sizePolicy().hasHeightForWidth())
self.listPages.setSizePolicy(sizePolicy)
self.listPages.setMinimumSize(QtCore.QSize(100, 0))
self.listPages.setMaximumSize(QtCore.QSize(100, 16777215))
self.listPages.setFrameShape(QtWidgets.QFrame.NoFrame)
self.listPages.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listPages.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.listPages.setProperty("showDropIndicator", False)
self.listPages.setDragDropMode(QtWidgets.QAbstractItemView.NoDragDrop)
self.listPages.setDefaultDropAction(QtCore.Qt.IgnoreAction)
self.listPages.setIconSize(QtCore.QSize(64, 64))
self.listPages.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
self.listPages.setViewMode(QtWidgets.QListView.IconMode)
self.listPages.setObjectName("listPages")
self.horizontalLayout.addWidget(self.listPages)
Expand Down
24 changes: 24 additions & 0 deletions pyobs_gui/qt/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
Expand All @@ -162,12 +168,30 @@
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::NoDragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::IgnoreAction</enum>
</property>
<property name="iconSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
Expand Down
127 changes: 75 additions & 52 deletions pyobs_gui/qt/widgetcamera.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
class Ui_WidgetCamera(object):
def setupUi(self, WidgetCamera):
WidgetCamera.setObjectName("WidgetCamera")
WidgetCamera.resize(967, 657)
WidgetCamera.resize(1269, 810)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(WidgetCamera)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.scrollArea = QtWidgets.QScrollArea(WidgetCamera)
Expand All @@ -26,7 +26,7 @@ def setupUi(self, WidgetCamera):
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 183, 641))
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 264, 794))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
Expand Down Expand Up @@ -80,45 +80,30 @@ def setupUi(self, WidgetCamera):
self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBinning)
self.gridLayout_3.setSpacing(0)
self.gridLayout_3.setObjectName("gridLayout_3")
self.spinBinningY = QtWidgets.QSpinBox(self.groupBinning)
self.spinBinningY.setMinimum(1)
self.spinBinningY.setMaximum(3)
self.spinBinningY.setObjectName("spinBinningY")
self.gridLayout_3.addWidget(self.spinBinningY, 1, 1, 1, 1)
self.spinBinningX = QtWidgets.QSpinBox(self.groupBinning)
self.spinBinningX.setMinimum(1)
self.spinBinningX.setMaximum(3)
self.spinBinningX.setObjectName("spinBinningX")
self.gridLayout_3.addWidget(self.spinBinningX, 0, 1, 1, 1)
self.label_6 = QtWidgets.QLabel(self.groupBinning)
self.label_6.setObjectName("label_6")
self.gridLayout_3.addWidget(self.label_6, 1, 0, 1, 1)
self.label_5 = QtWidgets.QLabel(self.groupBinning)
self.label_5.setObjectName("label_5")
self.gridLayout_3.addWidget(self.label_5, 0, 0, 1, 1)
self.comboBinning = QtWidgets.QComboBox(self.groupBinning)
self.comboBinning.setObjectName("comboBinning")
self.gridLayout_3.addWidget(self.comboBinning, 0, 1, 1, 1)
self.verticalLayout.addWidget(self.groupBinning)
self.groupImageFormat = QtWidgets.QGroupBox(self.scrollAreaWidgetContents)
self.groupImageFormat.setObjectName("groupImageFormat")
self.gridLayout_6 = QtWidgets.QGridLayout(self.groupImageFormat)
self.gridLayout_6.setSpacing(0)
self.gridLayout_6.setObjectName("gridLayout_6")
self.label_10 = QtWidgets.QLabel(self.groupImageFormat)
self.label_10.setObjectName("label_10")
self.gridLayout_6.addWidget(self.label_10, 0, 0, 1, 1)
self.comboImageFormat = QtWidgets.QComboBox(self.groupImageFormat)
self.comboImageFormat.setObjectName("comboImageFormat")
self.gridLayout_6.addWidget(self.comboImageFormat, 0, 1, 1, 1)
self.verticalLayout.addWidget(self.groupImageFormat)
self.groupExposure = QtWidgets.QGroupBox(self.scrollAreaWidgetContents)
self.groupExposure.setObjectName("groupExposure")
self.gridLayout_4 = QtWidgets.QGridLayout(self.groupExposure)
self.gridLayout_4.setSpacing(0)
self.gridLayout_4.setObjectName("gridLayout_4")
self.label_7 = QtWidgets.QLabel(self.groupExposure)
self.label_7.setObjectName("label_7")
self.gridLayout_4.addWidget(self.label_7, 1, 0, 1, 1)
self.comboImageType = QtWidgets.QComboBox(self.groupExposure)
self.comboImageType.setObjectName("comboImageType")
self.gridLayout_4.addWidget(self.comboImageType, 0, 1, 1, 1)
self.label_8 = QtWidgets.QLabel(self.groupExposure)
self.label_8.setObjectName("label_8")
self.gridLayout_4.addWidget(self.label_8, 2, 0, 1, 1)
self.spinCount = QtWidgets.QSpinBox(self.groupExposure)
self.spinCount.setMinimum(1)
self.spinCount.setMaximum(9999)
self.spinCount.setObjectName("spinCount")
self.gridLayout_4.addWidget(self.spinCount, 2, 1, 1, 1)
self.label_9 = QtWidgets.QLabel(self.groupExposure)
self.label_9.setObjectName("label_9")
self.gridLayout_4.addWidget(self.label_9, 0, 0, 1, 1)
self.butExpose = QtWidgets.QPushButton(self.groupExposure)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
Expand Down Expand Up @@ -267,7 +252,21 @@ def setupUi(self, WidgetCamera):
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush)
self.butExpose.setPalette(palette)
self.butExpose.setObjectName("butExpose")
self.gridLayout_4.addWidget(self.butExpose, 3, 0, 1, 2)
self.gridLayout_4.addWidget(self.butExpose, 4, 0, 1, 2)
self.spinCount = QtWidgets.QSpinBox(self.groupExposure)
self.spinCount.setMinimum(1)
self.spinCount.setMaximum(9999)
self.spinCount.setObjectName("spinCount")
self.gridLayout_4.addWidget(self.spinCount, 2, 1, 1, 1)
self.comboImageType = QtWidgets.QComboBox(self.groupExposure)
self.comboImageType.setObjectName("comboImageType")
self.gridLayout_4.addWidget(self.comboImageType, 0, 1, 1, 1)
self.labelImageType = QtWidgets.QLabel(self.groupExposure)
self.labelImageType.setObjectName("labelImageType")
self.gridLayout_4.addWidget(self.labelImageType, 0, 0, 1, 1)
self.labelExpTime = QtWidgets.QLabel(self.groupExposure)
self.labelExpTime.setObjectName("labelExpTime")
self.gridLayout_4.addWidget(self.labelExpTime, 1, 0, 1, 1)
self.butAbort = QtWidgets.QPushButton(self.groupExposure)
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
Expand Down Expand Up @@ -416,12 +415,32 @@ def setupUi(self, WidgetCamera):
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush)
self.butAbort.setPalette(palette)
self.butAbort.setObjectName("butAbort")
self.gridLayout_4.addWidget(self.butAbort, 4, 0, 1, 2)
self.gridLayout_4.addWidget(self.butAbort, 5, 0, 1, 2)
self.label_8 = QtWidgets.QLabel(self.groupExposure)
self.label_8.setObjectName("label_8")
self.gridLayout_4.addWidget(self.label_8, 2, 0, 1, 1)
self.checkBroadcast = QtWidgets.QCheckBox(self.groupExposure)
self.checkBroadcast.setChecked(True)
self.checkBroadcast.setObjectName("checkBroadcast")
self.gridLayout_4.addWidget(self.checkBroadcast, 3, 1, 1, 1)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.spinExpTime = QtWidgets.QDoubleSpinBox(self.groupExposure)
self.spinExpTime.setMaximum(99999.0)
self.spinExpTime.setSuffix("")
self.spinExpTime.setDecimals(3)
self.spinExpTime.setMaximum(999.0)
self.spinExpTime.setProperty("value", 1.0)
self.spinExpTime.setObjectName("spinExpTime")
self.gridLayout_4.addWidget(self.spinExpTime, 1, 1, 1, 1)
self.horizontalLayout_3.addWidget(self.spinExpTime)
self.comboExpTimeUnit = QtWidgets.QComboBox(self.groupExposure)
self.comboExpTimeUnit.setMinimumContentsLength(2)
self.comboExpTimeUnit.setObjectName("comboExpTimeUnit")
self.comboExpTimeUnit.addItem("")
self.comboExpTimeUnit.addItem("")
self.comboExpTimeUnit.addItem("")
self.horizontalLayout_3.addWidget(self.comboExpTimeUnit)
self.horizontalLayout_3.setStretch(0, 1)
self.gridLayout_4.addLayout(self.horizontalLayout_3, 1, 1, 1, 1)
self.verticalLayout.addWidget(self.groupExposure)
spacerItem = QtWidgets.QSpacerItem(20, 26, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
Expand Down Expand Up @@ -508,20 +527,20 @@ def setupUi(self, WidgetCamera):
WidgetCamera.setTabOrder(self.spinWindowTop, self.spinWindowWidth)
WidgetCamera.setTabOrder(self.spinWindowWidth, self.spinWindowHeight)
WidgetCamera.setTabOrder(self.spinWindowHeight, self.butFullFrame)
WidgetCamera.setTabOrder(self.butFullFrame, self.spinBinningX)
WidgetCamera.setTabOrder(self.spinBinningX, self.spinBinningY)
WidgetCamera.setTabOrder(self.spinBinningY, self.comboImageType)
WidgetCamera.setTabOrder(self.comboImageType, self.spinExpTime)
WidgetCamera.setTabOrder(self.spinExpTime, self.spinCount)
WidgetCamera.setTabOrder(self.spinCount, self.butExpose)
WidgetCamera.setTabOrder(self.butFullFrame, self.comboBinning)
WidgetCamera.setTabOrder(self.comboBinning, self.comboImageFormat)
WidgetCamera.setTabOrder(self.comboImageFormat, self.comboImageType)
WidgetCamera.setTabOrder(self.comboImageType, self.spinCount)
WidgetCamera.setTabOrder(self.spinCount, self.checkBroadcast)
WidgetCamera.setTabOrder(self.checkBroadcast, self.butExpose)
WidgetCamera.setTabOrder(self.butExpose, self.butAbort)
WidgetCamera.setTabOrder(self.butAbort, self.tabWidget)
WidgetCamera.setTabOrder(self.tabWidget, self.checkAutoUpdate)
WidgetCamera.setTabOrder(self.butAbort, self.checkAutoUpdate)
WidgetCamera.setTabOrder(self.checkAutoUpdate, self.checkAutoSave)
WidgetCamera.setTabOrder(self.checkAutoSave, self.textAutoSavePath)
WidgetCamera.setTabOrder(self.textAutoSavePath, self.butAutoSave)
WidgetCamera.setTabOrder(self.butAutoSave, self.butSaveTo)
WidgetCamera.setTabOrder(self.butSaveTo, self.tableFitsHeader)
WidgetCamera.setTabOrder(self.butSaveTo, self.tabWidget)
WidgetCamera.setTabOrder(self.tabWidget, self.tableFitsHeader)

def retranslateUi(self, WidgetCamera):
_translate = QtCore.QCoreApplication.translate
Expand All @@ -532,16 +551,20 @@ def retranslateUi(self, WidgetCamera):
self.label.setText(_translate("WidgetCamera", "Left:"))
self.label_4.setText(_translate("WidgetCamera", "Height:"))
self.butFullFrame.setText(_translate("WidgetCamera", "Full Frame"))
self.groupBinning.setTitle(_translate("WidgetCamera", "Binning:"))
self.label_6.setText(_translate("WidgetCamera", "Y:"))
self.label_5.setText(_translate("WidgetCamera", "X:"))
self.groupBinning.setTitle(_translate("WidgetCamera", "Binning"))
self.label_5.setText(_translate("WidgetCamera", "XxY:"))
self.groupImageFormat.setTitle(_translate("WidgetCamera", "Image format"))
self.label_10.setText(_translate("WidgetCamera", "Format:"))
self.groupExposure.setTitle(_translate("WidgetCamera", "Exposure"))
self.label_7.setText(_translate("WidgetCamera", "ExpTime:"))
self.label_8.setText(_translate("WidgetCamera", "Count:"))
self.label_9.setText(_translate("WidgetCamera", "Type:"))
self.butExpose.setText(_translate("WidgetCamera", "Expose"))
self.labelImageType.setText(_translate("WidgetCamera", "Type:"))
self.labelExpTime.setText(_translate("WidgetCamera", "ExpTime:"))
self.butAbort.setText(_translate("WidgetCamera", "Abort"))
self.spinExpTime.setSuffix(_translate("WidgetCamera", "s"))
self.label_8.setText(_translate("WidgetCamera", "Count:"))
self.checkBroadcast.setText(_translate("WidgetCamera", "Broadcast"))
self.comboExpTimeUnit.setItemText(0, _translate("WidgetCamera", "s"))
self.comboExpTimeUnit.setItemText(1, _translate("WidgetCamera", "ms"))
self.comboExpTimeUnit.setItemText(2, _translate("WidgetCamera", "µs"))
self.labelStatus.setText(_translate("WidgetCamera", "IDLE"))
self.labelExposuresLeft.setText(_translate("WidgetCamera", "IDLE"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabImage), _translate("WidgetCamera", "Image"))
Expand Down
Loading