Example #1
0
class TimeEdit(WidgetWithTZinfo):
    def __init__(self, parent=None):
        super(TimeEdit, self).__init__(parent)
        self.initQTimeEdit()
        self.initTZinfoEdit()

    def initQTimeEdit(self):
        self.timeEdit = QDateTimeEdit(self)
        self.timeEdit.setKeyboardTracking(False)
        self.timeEdit.setDisplayFormat("hh:mm:ss.zzz")
        self.layout().addWidget(self.timeEdit)

    def time(self) -> datetime.time:
        time = self.timeEdit.time().toPyTime()
        tzinfo = self.tzinfoEdit.getObj2add()
        time = time.replace(tzinfo=tzinfo)
        return time

    def setTime(self, val: datetime.time):
        if isinstance(val, datetime.time):
            self.timeEdit.setTime(val)
            self.tzinfoEdit.setVal(val.tzinfo)
        else:
            raise TypeError("arg1 must be instance of type datetime.time",
                            type(val))
class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()
        self.datetime_1 = QDateTimeEdit(self)                             # 1
        self.datetime_1.dateChanged.connect(lambda: print('Date Changed!'))
        self.datetime_2 = QDateTimeEdit(QDateTime.currentDateTime(), self)  # 2
        self.datetime_2.setDisplayFormat('yyyy-MM-dd HH:mm:ss')
        self.datetime_2.timeChanged.connect(lambda: print('Time Changed!'))
        print(self.datetime_2.date())
        print(self.datetime_2.time())
        print(self.datetime_2.dateTime())
        self.datetime_3 = QDateTimeEdit(QDateTime.currentDateTime(), self) # 3
        self.datetime_3.dateTimeChanged.connect(lambda: print('DateTimeChanged!'))
        self.datetime_3.setCalendarPopup(True)
        self.datetime_4 = QDateTimeEdit(QDate.currentDate(), self)       # 4
        self.datetime_5 = QDateTimeEdit(QTime.currentTime(), self)
        self.date = QDateEdit(QDate.currentDate(), self)                 # 5
        self.date.setDisplayFormat('yyyy/MM/dd')
        print(self.date.date())
        self.time = QTimeEdit(QTime.currentTime(), self)                 # 6
        self.time.setDisplayFormat('HH:mm:ss')
        print(self.time.time())
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.datetime_1)
        self.v_layout.addWidget(self.datetime_2)
        self.v_layout.addWidget(self.datetime_3)
        self.v_layout.addWidget(self.datetime_4)
        self.v_layout.addWidget(self.datetime_5)
        self.v_layout.addWidget(self.date)
        self.v_layout.addWidget(self.time)
        self.setLayout(self.v_layout)
class CountdownWidget(QWidget):
    """Define custom widget as countdown control panel."""
    def __init__(self, ctrl, parent=None):
        """Init completer."""
        super().__init__(parent)
        self.controller = ctrl
        self.createLayout()
        self.loadSettings()
        self.connect()

    def createLayout(self):
        """Create widget to control the countdown browser source."""
        layout = QGridLayout()
        self.rb_static = QRadioButton(_("Static Countdown to date:"), self)
        layout.addWidget(self.rb_static, 0, 0)
        self.rb_dynamic = QRadioButton(_("Dynamic Countdown duration:"), self)
        self.rb_dynamic.setChecked(True)
        self.rb_dynamic.toggled.connect(self.toggleRadio)
        layout.addWidget(self.rb_dynamic, 1, 0)
        self.te_datetime = QDateTimeEdit()
        self.te_datetime.setCalendarPopup(True)
        self.te_datetime.setContextMenuPolicy(Qt.CustomContextMenu)
        self.te_datetime.customContextMenuRequested.connect(
            self.openDateTimeMenu)
        layout.addWidget(self.te_datetime, 0, 1)
        self.te_duration = QTimeEdit()
        self.te_duration.setDisplayFormat("HH 'h' mm 'm' ss 's'")
        self.te_duration.setContextMenuPolicy(Qt.CustomContextMenu)
        self.te_duration.customContextMenuRequested.connect(
            self.openDurationMenu)
        layout.addWidget(self.te_duration, 1, 1)
        self.event_label = QLabel(' ' + _('Event description:'))
        layout.addWidget(self.event_label, 0, 2)
        self.le_desc = QLineEdit()
        self.le_desc.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.le_desc, 0, 3, 1, 2)
        self.cb_restart = QCheckBox(
            _('Restart countdown when source becomes active'))
        layout.addWidget(self.cb_restart, 1, 2, 1, 2)
        self.pb_start = QPushButton(" " + _('Start Countdown') + " ")
        layout.addWidget(self.pb_start, 1, 4)
        layout.setColumnStretch(2, 1)
        layout.setColumnStretch(3, 2)
        self.setLayout(layout)

    def openDateTimeMenu(self, position):
        """Open menu to set date to today."""
        menu = QMenu()
        act1 = QAction(_("Set Today"))
        act1.triggered.connect(self.setToday)
        menu.addAction(act1)
        menu.exec_(QCursor.pos())

    def openDurationMenu(self, position):
        """Open menu to set the duration."""
        menu = QMenu()
        for duration in [15, 10, 5, 3, 1]:
            act = QAction(_("Set {} min").format(duration), menu)
            act.triggered.connect(
                lambda x, duration=duration: self.setDuration(duration))
            menu.addAction(act)
        menu.exec_(QCursor.pos())

    def setToday(self):
        """Set date to today."""
        today = QDateTime.currentDateTime()
        today.setTime(self.te_datetime.time())
        self.te_datetime.setDateTime(today)

    def setFromTimestamp(self, timestamp):
        """Set time and date based on timestamp."""
        self.te_datetime.setDateTime(QDateTime.fromTime_t(int(timestamp)))

    def setDuration(self, duration):
        """Set the duration."""
        self.te_duration.setTime(QTime(0, duration, 0))

    def toggleRadio(self):
        """Toggle radio buttion."""
        static = self.rb_static.isChecked()
        self.te_datetime.setEnabled(static)
        self.te_duration.setEnabled(not static)
        self.cb_restart.setEnabled(not static)
        self.pb_start.setEnabled(not static)

    def loadSettings(self):
        """Load data from settings."""
        static = scctool.settings.config.parser.getboolean(
            "Countdown", "static")
        if static:
            self.rb_static.setChecked(True)
        else:
            self.rb_dynamic.setChecked(True)
        description = scctool.settings.config.parser.get(
            'Countdown', 'description')
        self.le_desc.setText(description.strip())
        restart = scctool.settings.config.parser.getboolean(
            "Countdown", "restart")
        self.cb_restart.setChecked(restart)

        duration = QTime()
        string = scctool.settings.config.parser.get('Countdown',
                                                    'duration').strip()
        duration = QTime.fromString(string, 'HH:mm:ss')
        self.te_duration.setTime(duration)

        string = scctool.settings.config.parser.get('Countdown',
                                                    'datetime').strip()
        datetime = QDateTime.fromString(string, 'yyyy-MM-dd HH:mm')
        self.te_datetime.setDateTime(datetime)

    def connect(self):
        """Connect all form elements."""
        self.le_desc.textChanged.connect(self.changed_description)
        self.cb_restart.toggled.connect(self.changed_restart)
        self.te_datetime.dateTimeChanged.connect(self.changed_datetime)
        self.te_duration.timeChanged.connect(self.changed_duration)
        self.rb_static.toggled.connect(self.changed_static)
        self.pb_start.pressed.connect(self.start_pressed)

    def changed_description(self):
        """Change the description."""
        desc = self.le_desc.text().strip()
        scctool.settings.config.parser.set('Countdown', 'description', desc)
        self.controller.websocketThread.sendData2Path('countdown', "DESC",
                                                      desc)

    def changed_restart(self):
        """Handle change of restart option."""
        restart = self.cb_restart.isChecked()
        scctool.settings.config.parser.set('Countdown', 'restart',
                                           str(restart))
        self.controller.websocketThread.sendData2Path('countdown', "RESTART",
                                                      restart)

    def changed_datetime(self, time):
        """Handle change of datetime."""
        datetime = time.toString('yyyy-MM-dd HH:mm')
        scctool.settings.config.parser.set('Countdown', 'datetime', datetime)
        self.sendData()

    def changed_duration(self, time):
        """Handle change of duration."""
        duration = time.toString('HH:mm:ss')
        scctool.settings.config.parser.set('Countdown', 'duration', duration)
        self.sendData()

    def changed_static(self):
        """Handle change of static/dynamic."""
        static = self.rb_static.isChecked()
        scctool.settings.config.parser.set('Countdown', 'static', str(static))
        self.sendData()

    def start_pressed(self):
        """Handle press of the start button."""
        self.controller.websocketThread.sendData2Path('countdown', 'START')

    def sendData(self):
        """Send the data to the websocket."""
        self.controller.websocketThread.sendData2Path(
            'countdown', "DATA",
            self.controller.websocketThread.getCountdownData())
Example #4
0
class App(QMainWindow):
    switch_window = QtCore.pyqtSignal()

    def __init__(self):
        super().__init__()
        self.title = "To-Do List"  # set title..
        self.left = 70  # x-pos when you open application..
        self.top = 60  # y-pos when you open application..
        self.width = 500  # width of the application..
        self.height = 500  # height of the application..
        self.fName = 'To-Do List File.txt'  # set file name when you save your file..
        self.uncompletedTaskFile, self.completedTaskFile = 'UncompletedTask.txt', 'CompletedTask.txt'
        self.initUI()  # initialize the UI of the application..

    def makeLabel(self, x, y, text):  # make label method...
        self.taskLabel = QLabel(self)
        self.taskLabel.setText(text)
        self.taskLabel.move(x, y)

    def createTaskFile(self):
        if not os.path.exists(self.uncompletedTaskFile) and not os.path.exists(
                self.completedTaskFile):
            with open(self.uncompletedTaskFile, 'w') as f:
                f.close()
            with open(self.completedTaskFile, 'w') as g:
                g.close()

    def setMenuBarAction(self):  # add Action to the menu bar...
        self.saveAction = QAction('Save', self)  # save Action..
        self.saveAction.setStatusTip('Sae The To-Do')
        self.saveAction.setShortcut("Ctrl+S")
        self.saveAction.triggered.connect(self.saveFile)

        self.saveAllAction = QAction('Save All', self)  # save All Action..
        self.saveAllAction.setStatusTip('Save All To-Do')
        self.saveAllAction.triggered.connect(self.saveAllFile)

        self.exitAction = QAction('Exit', self)  # Exit Action..
        self.exitAction.setStatusTip('Exit')
        self.exitAction.triggered.connect(self.exitApp)

        self.aboutToDo = QAction('About To-Do List', self)  # About Action..
        self.aboutToDo.triggered.connect(self.aboutInfo)

    def appMenuBar(self):
        menuBar = self.menuBar()  # Create Menu Bar..

        self.setMenuBarAction()  # Set Action for Menu Bar..

        self.homeMenu = menuBar.addMenu(
            'File')  # Set File Menu to The MenuBar..
        self.helpMenu = menuBar.addMenu(
            'Help')  # Set Help Menu to The MenuBar..

        self.homeMenu.addAction(
            self.saveAction)  # Save Action Added to File Menu..
        self.homeMenu.addAction(
            self.saveAllAction)  # Save All Action Added to File Menu..
        self.homeMenu.addAction(
            self.exitAction)  # Exit Action Added to File Menu..

        self.helpMenu.addAction(
            self.aboutToDo)  # Abouut Action Added to Help Menu..

    def initUI(self):
        self.setWindowTitle(self.title)  # Set title for the Application..
        self.setWindowIcon(QIcon("./logo.png"))  # set Icon for the Application
        self.setGeometry(self.left, self.top, self.width,
                         self.height)  # set app size..
        self.setMaximumSize(QtCore.QSize(
            self.width,
            self.height))  # disabling Application Maximize button..

        self.appMenuBar()  # Set application MenuBar..
        self.createTaskFile()  # creating Task File for application..

        # Task Text Input..
        self.taskText = QLineEdit(self)
        self.taskText.move(10, 45)
        self.taskText.resize(self.width // 2 - 20, 50)
        self.taskText.setPlaceholderText('Enter Task Here..')

        # setting up uncompleted task text Area...
        self.textArea = QTextEdit(self)
        self.textArea.setReadOnly(True)  # readonly text area..
        self.textArea.move(self.width // 2, 45)
        self.textArea.resize(self.width // 2 - 2, self.height - 50)
        self.textArea.setLineWrapMode(QTextEdit.NoWrap)
        self.textArea.setTextColor(QColor(180, 0,
                                          0))  # give font color to red..
        self.textArea.setFontPointSize(10)  # font size = 10..

        # make Labels.....
        self.makeLabel(10, 21, 'Add Task Here')
        self.makeLabel(self.width // 2, 20, 'Uncompleted Task')
        self.makeLabel(5, self.height // 2 - 15, 'Completed Task List')
        self.makeLabel(10, 95, 'Set Reminder')

        # setting up completed task text Area..
        self.completedtextArea = QTextEdit(self)
        self.completedtextArea.setReadOnly(True)  # readonly text area..
        self.completedtextArea.move(5, self.height // 2 + 10)
        self.completedtextArea.resize(self.width // 2 - 13,
                                      self.height // 2 - 15)
        self.completedtextArea.setLineWrapMode(QTextEdit.NoWrap)
        self.completedtextArea.setTextColor(QColor(
            0, 180, 0))  # give font color to green..
        self.completedtextArea.setFontPointSize(10)  # font size = 10..

        self.dateTimeBox = QDateTimeEdit(self)
        self.dateTimeBox.setGeometry(10, 125, 140, 25)

        self.loadTask()  # loading preveiously stord To-Do Task..

        self.Buttons()  # make all the buttons for the Application..

        self.show()  # display the application..a

    def Buttons(self):
        # Add To-Do Button
        self.addButton = QPushButton("Add To-Do", self)
        self.addButton.move(15, 164)

        # Add Clear All Button
        self.clearAllButton = QPushButton("Clear All", self)
        self.clearAllButton.move(130, 164)

        # Adding Mark All Completed Button..
        self.completedButton = QPushButton("Mark All Completed", self)
        self.completedButton.move(58, 203)
        self.completedButton.resize(140, 30)

        # Button events..
        self.addButton.clicked.connect(self.onClick)
        self.clearAllButton.clicked.connect(self.clearAll)
        self.completedButton.clicked.connect(self.completeTask)

    def loadTask(self):
        if os.path.exists(self.uncompletedTaskFile):
            with open(self.uncompletedTaskFile, 'r') as f:
                text = f.read()
                if text != '':
                    self.textArea.append(text)
        if os.path.exists(self.completedTaskFile):
            with open(self.completedTaskFile, 'r') as g:
                texts = g.read().split('\n')
                for text in texts:
                    if text != '':
                        self.completedtextArea.append(text)

    @pyqtSlot()
    def saveFile(self):
        file = self.textArea.toPlainText()
        try:
            fHandle = open(self.fName, 'a')
            fHandle.write(file)
        except:
            with open(self.fName, 'w') as f:
                f.write(file)
        fHandle.close()

    @pyqtSlot()
    def saveAllFile(self):
        uncompletedToDOText = self.textArea.toPlainText()
        completedToDOText = self.completedtextArea.toPlainText()
        if uncompletedToDOText == '':  # if there is no task in uncompleted task list then skip it..
            with open(self.fName, 'w') as f:
                f.write('Completed To-Do Task:\n\n')
                f.write(completedToDOText)
        elif completedToDOText == '':  # if there is no task in completed task list then skip it..
            with open(self.fName, 'w') as f:
                f.write('Uncompleted To-Do Task:\n\n')
                f.write(uncompletedToDOText + '\n\n')
        else:
            with open(self.fName, 'w') as f:  # both..
                f.write('Uncompleted To-Do Task:\n\n')
                f.write(uncompletedToDOText + '\n\n')
                f.write('Completed To-Do Task:\n\n')
                f.write(completedToDOText)

    @pyqtSlot()
    def aboutInfo(self):

        msg = QMessageBox()
        msg.setWindowTitle('To-Do List')
        msg.setGeometry(280, 190, 500, 420)
        msg.setWindowIcon(QIcon('logo.png'))
        msg.setText(
            '''Add Your Daily To-Do Task \n   Bulid With Python & PyQt5.
			        ''')
        msg.exec_()

    @pyqtSlot()
    def exitApp(self):
        sys.exit()  # exit from the App..

    @pyqtSlot()
    def onClick(self):
        textvalue = self.taskText.text()
        date = self.dateTimeBox.date()
        time = self.dateTimeBox.time()
        text = f'{textvalue}  Date: {date.toPyDate()} Time: {time.toPyTime()}\n'  # convert to string..
        if textvalue == '':  # If textvalue in taskText is blank then return don't update textArea..
            return
        else:
            if os.path.exists(self.uncompletedTaskFile):
                with open(self.uncompletedTaskFile, 'a') as f:
                    f.write(text)
            else:
                with open(self.uncompletedTaskFile, 'w') as f:
                    f.write(text)
            self.textArea.append(text)  # else update textArea..
            self.taskText.setText('')  #clear taskText..

    @pyqtSlot()
    def clearAll(self):
        self.textArea.setText('')  # clear uncompleted task list textArea..
        self.completedtextArea.setText(
            '')  # clear completed task list textArea..
        with open(self.uncompletedTaskFile,
                  'w') as f, open(self.completedTaskFile, 'w') as g:
            f.close()
            g.close()

    @pyqtSlot()
    def completeTask(self):
        textValue = self.textArea.toPlainText(
        )  # get uncompleted task list text..
        with open(self.uncompletedTaskFile, 'r+') as g:
            dataFile = g.read().split('\n')
            texts = textValue.split('\n')
            for text in texts:
                for data in dataFile:
                    if data.startswith(text):
                        g.truncate(0)
        if textValue == '':
            return
        else:
            if os.path.exists(self.completedTaskFile):
                with open(self.completedTaskFile, 'a') as f:
                    texts = textValue.split('\n')
                    for text in texts:
                        if text != '':
                            f.write(textValue)
            else:
                with open(self.completedTaskFile, 'w') as f:
                    texts = textValue.split('\n')
                    for text in texts:
                        if text != '':
                            f.write(textValue)
            texts = textValue.split('\n')
            for text in texts:
                if text != '':
                    self.completedtextArea.append(
                        text)  # append to completed task list section..
            self.textArea.setText('')
Example #5
0
class BRFManager(myqt.QFrameLayout):
    sig_brfperiod_changed = QSignal(list)

    def __init__(self, wldset=None, parent=None):
        super(BRFManager, self).__init__(parent)

        self.viewer = BRFViewer(wldset, parent)
        self.kgs_brf_installer = None
        self.__initGUI__()

    def __initGUI__(self):
        self.setContentsMargins(10, 10, 10, 10)

        # ---- Detrend and Correct Options
        self.baro_spinbox = myqt.QDoubleSpinBox(100, 0, show_buttons=True)
        self.baro_spinbox.setRange(0, 9999)
        self.baro_spinbox.setKeyboardTracking(True)

        self.earthtides_spinbox = myqt.QDoubleSpinBox(100,
                                                      0,
                                                      show_buttons=True)
        self.earthtides_spinbox.setRange(0, 9999)
        self.earthtides_spinbox.setKeyboardTracking(True)

        self.earthtides_cbox = QCheckBox('Nbr of ET lags :')
        self.earthtides_cbox.setChecked(True)
        self.earthtides_cbox.stateChanged.connect(
            lambda: self.earthtides_spinbox.setEnabled(self.earthtides_cbox.
                                                       isChecked()))

        self.detrend_waterlevels_cbox = QCheckBox('Detrend water levels')
        self.detrend_waterlevels_cbox.setChecked(True)

        # Setup options layout.
        options_layout = QGridLayout()
        options_layout.addWidget(QLabel('Nbr of BP lags :'), 0, 0)
        options_layout.addWidget(self.baro_spinbox, 0, 2)
        options_layout.addWidget(self.earthtides_cbox, 1, 0)
        options_layout.addWidget(self.earthtides_spinbox, 1, 2)
        options_layout.addWidget(self.detrend_waterlevels_cbox, 2, 0, 1, 3)
        options_layout.setColumnStretch(1, 100)
        options_layout.setContentsMargins(0, 0, 0, 0)

        # ---- BRF date range
        self.date_start_edit = QDateTimeEdit()
        self.date_start_edit.setCalendarPopup(True)
        self.date_start_edit.setDisplayFormat('dd/MM/yyyy hh:mm')
        self.date_start_edit.dateChanged.connect(
            lambda: self.sig_brfperiod_changed.emit(self.get_brfperiod()))
        self.date_start_edit.dateChanged.connect(
            lambda: self.wldset.save_brfperiod(self.get_brfperiod()))

        self.date_end_edit = QDateTimeEdit()
        self.date_end_edit.setCalendarPopup(True)
        self.date_end_edit.setDisplayFormat('dd/MM/yyyy hh:mm')
        self.date_end_edit.dateChanged.connect(
            lambda: self.sig_brfperiod_changed.emit(self.get_brfperiod()))
        self.date_end_edit.dateChanged.connect(
            lambda: self.wldset.save_brfperiod(self.get_brfperiod()))

        self.btn_seldata = OnOffToolButton('select_range', size='small')
        self.btn_seldata.setToolTip("Select a BRF calculation period with "
                                    "the mouse cursor on the graph.")

        # Setup BRF date range layout.
        daterange_layout = QGridLayout()
        daterange_layout.addWidget(QLabel('BRF Start :'), 0, 0)
        daterange_layout.addWidget(self.date_start_edit, 0, 2)
        daterange_layout.addWidget(QLabel('BRF End :'), 1, 0)
        daterange_layout.addWidget(self.date_end_edit, 1, 2)
        daterange_layout.setColumnStretch(1, 100)
        daterange_layout.setContentsMargins(0, 0, 0, 0)

        seldata_layout = QGridLayout()
        seldata_layout.addWidget(self.btn_seldata, 0, 0)
        seldata_layout.setRowStretch(1, 100)
        seldata_layout.setContentsMargins(0, 0, 0, 0)

        # ---- Toolbar
        btn_comp = QPushButton('Compute BRF')
        btn_comp.clicked.connect(self.calc_brf)
        btn_comp.setFocusPolicy(Qt.NoFocus)

        self.btn_show = QToolButtonSmall(icons.get_icon('search'))
        self.btn_show.clicked.connect(self.viewer.show)

        # ---- Main Layout
        self.addLayout(daterange_layout, 0, 0)
        self.addLayout(seldata_layout, 0, 1)
        self.setRowMinimumHeight(1, 15)
        self.addLayout(options_layout, 2, 0)
        self.setRowMinimumHeight(3, 15)
        self.setRowStretch(3, 100)
        self.addWidget(btn_comp, 4, 0)
        self.addWidget(self.btn_show, 4, 1)
        self.setColumnStretch(0, 100)

        # ---- Install Panel
        if not KGSBRFInstaller().kgsbrf_is_installed():
            self.__install_kgs_brf_installer()

    # ---- Properties

    @property
    def nlag_baro(self):
        """Return the number of lags to use for barometric correction."""
        return self.baro_spinbox.value()

    @property
    def nlag_earthtides(self):
        """Return the number of lags to use for Earth tides correction."""
        return (self.earthtides_spinbox.value()
                if self.earthtides_cbox.isChecked() else -1)

    @property
    def detrend_waterlevels(self):
        return self.detrend_waterlevels_cbox.isChecked()

    @property
    def correct_waterlevels(self):
        return True

    def get_brfperiod(self):
        """
        Get the period over which the BRF would be evaluated as a list of
        two numerical Excel date values.
        """
        year, month, day = self.date_start_edit.date().getDate()
        hour = self.date_start_edit.time().hour()
        minute = self.date_start_edit.time().minute()
        dstart = xldate_from_datetime_tuple(
            (year, month, day, hour, minute, 0), 0)

        year, month, day = self.date_end_edit.date().getDate()
        hour = self.date_end_edit.time().hour()
        minute = self.date_end_edit.time().minute()
        dend = xldate_from_datetime_tuple((year, month, day, hour, minute, 0),
                                          0)

        return [dstart, dend]

    def set_brfperiod(self, period):
        """
        Set the value of the date_start_edit and date_end_edit widgets used to
        define the period over which the BRF is evaluated. Also save the
        period to the waterlevel dataset.
        """
        period = np.sort(period).tolist()
        widgets = (self.date_start_edit, self.date_end_edit)
        for xldate, widget in zip(period, widgets):
            if xldate is not None:
                widget.blockSignals(True)
                widget.setDateTime(qdatetime_from_xldate(xldate))
                widget.blockSignals(False)
        self.wldset.save_brfperiod(period)

    # ---- KGS BRF installer
    def __install_kgs_brf_installer(self):
        """
        Installs a KGSBRFInstaller that overlays the whole brf tool
        layout until the KGS_BRF program is installed correctly.
        """
        self.kgs_brf_installer = KGSBRFInstaller()
        self.kgs_brf_installer.sig_kgs_brf_installed.connect(
            self.__uninstall_kgs_brf_installer)
        self.addWidget(self.kgs_brf_installer, 0, 0, self.rowCount(),
                       self.columnCount())

    def __uninstall_kgs_brf_installer(self):
        """
        Uninstall the KGSBRFInstaller after the KGS_BRF program has been
        installed properly.
        """
        self.kgs_brf_installer.sig_kgs_brf_installed.disconnect()
        self.kgs_brf_installer = None

    def set_wldset(self, wldset):
        """Set the namespace for the wldset in the widget."""
        self.wldset = wldset
        self.viewer.set_wldset(wldset)
        self.btn_seldata.setAutoRaise(True)
        self.setEnabled(wldset is not None)
        if wldset is not None:
            xldates = self.wldset.xldates
            self.set_daterange((xldates[0], xldates[-1]))

            # Set the period over which the BRF would be evaluated.
            saved_brfperiod = wldset.get_brfperiod()
            self.set_brfperiod(
                (saved_brfperiod[0] or np.floor(xldates[0]), saved_brfperiod[1]
                 or np.floor(xldates[-1])))

    def set_daterange(self, daterange):
        """
        Set the minimum and maximum value of date_start_edit and date_end_edit
        widgets from the specified list of Excel numeric dates.
        """
        for widget in (self.date_start_edit, self.date_end_edit):
            widget.blockSignals(True)
            widget.setMinimumDateTime(qdatetime_from_xldate(daterange[0]))
            widget.setMaximumDateTime(qdatetime_from_xldate(daterange[1]))
            widget.blockSignals(False)

    def calc_brf(self):
        """Prepare the data, calcul the brf, and save and plot the results."""

        # Prepare the datasets.
        well = self.wldset['Well']

        brfperiod = self.get_brfperiod()
        t1 = min(brfperiod)
        i1 = np.where(self.wldset.xldates >= t1)[0][0]
        t2 = max(brfperiod)
        i2 = np.where(self.wldset.xldates <= t2)[0][-1]

        time = np.copy(self.wldset.xldates[i1:i2 + 1])
        wl = np.copy(self.wldset['WL'][i1:i2 + 1])
        bp = np.copy(self.wldset['BP'][i1:i2 + 1])
        if len(bp) == 0:
            msg = ("The barometric response function cannot be computed"
                   " because the currently selected water level dataset does"
                   " not contain any barometric data for the selected period.")
            QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok)
            return
        et = np.copy(self.wldset['ET'][i1:i2 + 1])
        if len(et) == 0:
            et = np.zeros(len(wl))

        # Fill the gaps in the waterlevel data.
        dt = np.min(np.diff(time))
        tc = np.arange(t1, t2 + dt / 2, dt)
        if len(tc) != len(time) or np.any(np.isnan(wl)):
            print('Filling gaps in data with linear interpolation.')
            indx = np.where(~np.isnan(wl))[0]
            wl = np.interp(tc, time[indx], wl[indx])

            indx = np.where(~np.isnan(bp))[0]
            bp = np.interp(tc, time[indx], bp[indx])

            indx = np.where(~np.isnan(et))[0]
            et = np.interp(tc, time[indx], et[indx])

            time = tc

        QApplication.setOverrideCursor(Qt.WaitCursor)
        print('calculating the BRF')

        bm.produce_BRFInputtxt(well, time, wl, bp, et)
        msg = ("Not enough data. Try enlarging the selected period "
               "or reduce the number of BP lags.")
        if self.nlag_baro >= len(time) or self.nlag_earthtides >= len(time):
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok)
            return

        bm.produce_par_file(self.nlag_baro, self.nlag_earthtides,
                            self.detrend_waterlevels, self.correct_waterlevels)
        bm.run_kgsbrf()

        try:
            dataf = bm.read_brf_output()
            date_start, date_end = (xldate_as_datetime(xldate, 0)
                                    for xldate in self.get_brfperiod())
            self.wldset.save_brf(dataf, date_start, date_end,
                                 self.detrend_waterlevels)
            self.viewer.new_brf_added()
            self.viewer.show()
            QApplication.restoreOverrideCursor()
        except Exception:
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok)
            return
Example #6
0
class BRFManager(myqt.QFrameLayout):
    sig_brfperiod_changed = QSignal(list)

    def __init__(self, wldset=None, parent=None):
        super(BRFManager, self).__init__(parent)

        self.viewer = BRFViewer(wldset, parent)
        self.kgs_brf_installer = None
        self.__initGUI__()

    def __initGUI__(self):
        self.setContentsMargins(10, 10, 10, 10)

        # ---- Detrend and Correct Options
        self.baro_spinbox = myqt.QDoubleSpinBox(100, 0, show_buttons=True)
        self.baro_spinbox.setRange(0, 9999)
        self.baro_spinbox.setKeyboardTracking(True)

        self.earthtides_spinbox = myqt.QDoubleSpinBox(
            100, 0, show_buttons=True)
        self.earthtides_spinbox.setRange(0, 9999)
        self.earthtides_spinbox.setKeyboardTracking(True)

        self.earthtides_cbox = QCheckBox('Nbr of ET lags :')
        self.earthtides_cbox.setChecked(True)
        self.earthtides_cbox.stateChanged.connect(
            lambda: self.earthtides_spinbox.setEnabled(
                self.earthtides_cbox.isChecked()))

        self.detrend_waterlevels_cbox = QCheckBox('Detrend water levels')
        self.detrend_waterlevels_cbox.setChecked(True)

        # Setup options layout.
        options_layout = QGridLayout()
        options_layout.addWidget(QLabel('Nbr of BP lags :'), 0, 0)
        options_layout.addWidget(self.baro_spinbox, 0, 2)
        options_layout.addWidget(self.earthtides_cbox, 1, 0)
        options_layout.addWidget(self.earthtides_spinbox, 1, 2)
        options_layout.addWidget(self.detrend_waterlevels_cbox, 2, 0, 1, 3)
        options_layout.setColumnStretch(1, 100)
        options_layout.setContentsMargins(0, 0, 0, 0)

        # ---- BRF date range
        self.date_start_edit = QDateTimeEdit()
        self.date_start_edit.setCalendarPopup(True)
        self.date_start_edit.setDisplayFormat('dd/MM/yyyy hh:mm')
        self.date_start_edit.dateChanged.connect(
            lambda: self.sig_brfperiod_changed.emit(self.get_brfperiod()))
        self.date_start_edit.dateChanged.connect(
            lambda: self.wldset.save_brfperiod(self.get_brfperiod()))

        self.date_end_edit = QDateTimeEdit()
        self.date_end_edit.setCalendarPopup(True)
        self.date_end_edit.setDisplayFormat('dd/MM/yyyy hh:mm')
        self.date_end_edit.dateChanged.connect(
            lambda: self.sig_brfperiod_changed.emit(self.get_brfperiod()))
        self.date_end_edit.dateChanged.connect(
            lambda: self.wldset.save_brfperiod(self.get_brfperiod()))

        self.btn_seldata = OnOffToolButton('select_range', size='small')
        self.btn_seldata.setToolTip("Select a BRF calculation period with "
                                    "the mouse cursor on the graph.")

        # Setup BRF date range layout.
        daterange_layout = QGridLayout()
        daterange_layout.addWidget(QLabel('BRF Start :'), 0, 0)
        daterange_layout.addWidget(self.date_start_edit, 0, 2)
        daterange_layout.addWidget(QLabel('BRF End :'), 1, 0)
        daterange_layout.addWidget(self.date_end_edit, 1, 2)
        daterange_layout.setColumnStretch(1, 100)
        daterange_layout.setContentsMargins(0, 0, 0, 0)

        seldata_layout = QGridLayout()
        seldata_layout.addWidget(self.btn_seldata, 0, 0)
        seldata_layout.setRowStretch(1, 100)
        seldata_layout.setContentsMargins(0, 0, 0, 0)

        # ---- Toolbar
        btn_comp = QPushButton('Compute BRF')
        btn_comp.clicked.connect(self.calc_brf)
        btn_comp.setFocusPolicy(Qt.NoFocus)

        self.btn_show = QToolButtonSmall(icons.get_icon('search'))
        self.btn_show.clicked.connect(self.viewer.show)

        # ---- Main Layout
        self.addLayout(daterange_layout, 0, 0)
        self.addLayout(seldata_layout, 0, 1)
        self.setRowMinimumHeight(1, 15)
        self.addLayout(options_layout, 2, 0)
        self.setRowMinimumHeight(3, 15)
        self.setRowStretch(3, 100)
        self.addWidget(btn_comp, 4, 0)
        self.addWidget(self.btn_show, 4, 1)
        self.setColumnStretch(0, 100)

        # ---- Install Panel
        if not KGSBRFInstaller().kgsbrf_is_installed():
            self.__install_kgs_brf_installer()

    # ---- Properties

    @property
    def nlag_baro(self):
        """Return the number of lags to use for barometric correction."""
        return self.baro_spinbox.value()

    @property
    def nlag_earthtides(self):
        """Return the number of lags to use for Earth tides correction."""
        return (self.earthtides_spinbox.value() if
                self.earthtides_cbox.isChecked() else -1)

    @property
    def detrend_waterlevels(self):
        return self.detrend_waterlevels_cbox.isChecked()

    @property
    def correct_waterlevels(self):
        return True

    def get_brfperiod(self):
        """
        Get the period over which the BRF would be evaluated as a list of
        two numerical Excel date values.
        """
        year, month, day = self.date_start_edit.date().getDate()
        hour = self.date_start_edit.time().hour()
        minute = self.date_start_edit.time().minute()
        dstart = xldate_from_datetime_tuple(
            (year, month, day, hour, minute, 0), 0)

        year, month, day = self.date_end_edit.date().getDate()
        hour = self.date_end_edit.time().hour()
        minute = self.date_end_edit.time().minute()
        dend = xldate_from_datetime_tuple(
            (year, month, day, hour, minute, 0), 0)

        return [dstart, dend]

    def set_brfperiod(self, period):
        """
        Set the value of the date_start_edit and date_end_edit widgets used to
        define the period over which the BRF is evaluated. Also save the
        period to the waterlevel dataset.
        """
        period = np.sort(period).tolist()
        widgets = (self.date_start_edit, self.date_end_edit)
        for xldate, widget in zip(period, widgets):
            if xldate is not None:
                widget.blockSignals(True)
                widget.setDateTime(qdatetime_from_xldate(xldate))
                widget.blockSignals(False)
        self.wldset.save_brfperiod(period)

    # ---- KGS BRF installer
    def __install_kgs_brf_installer(self):
        """
        Installs a KGSBRFInstaller that overlays the whole brf tool
        layout until the KGS_BRF program is installed correctly.
        """
        self.kgs_brf_installer = KGSBRFInstaller()
        self.kgs_brf_installer.sig_kgs_brf_installed.connect(
                self.__uninstall_kgs_brf_installer)
        self.addWidget(self.kgs_brf_installer, 0, 0,
                       self.rowCount(), self.columnCount())

    def __uninstall_kgs_brf_installer(self):
        """
        Uninstall the KGSBRFInstaller after the KGS_BRF program has been
        installed properly.
        """
        self.kgs_brf_installer.sig_kgs_brf_installed.disconnect()
        self.kgs_brf_installer = None

    def set_wldset(self, wldset):
        """Set the namespace for the wldset in the widget."""
        self.wldset = wldset
        self.viewer.set_wldset(wldset)
        self.btn_seldata.setAutoRaise(True)
        self.setEnabled(wldset is not None)
        if wldset is not None:
            xldates = self.wldset.xldates
            self.set_daterange((xldates[0], xldates[-1]))

            # Set the period over which the BRF would be evaluated.
            saved_brfperiod = wldset.get_brfperiod()
            self.set_brfperiod((saved_brfperiod[0] or np.floor(xldates[0]),
                                saved_brfperiod[1] or np.floor(xldates[-1])))

    def set_daterange(self, daterange):
        """
        Set the minimum and maximum value of date_start_edit and date_end_edit
        widgets from the specified list of Excel numeric dates.
        """
        for widget in (self.date_start_edit, self.date_end_edit):
            widget.blockSignals(True)
            widget.setMinimumDateTime(qdatetime_from_xldate(daterange[0]))
            widget.setMaximumDateTime(qdatetime_from_xldate(daterange[1]))
            widget.blockSignals(False)

    def calc_brf(self):
        """Prepare the data, calcul the brf, and save and plot the results."""

        # Prepare the datasets.
        well = self.wldset['Well']

        brfperiod = self.get_brfperiod()
        t1 = min(brfperiod)
        i1 = np.where(self.wldset.xldates >= t1)[0][0]
        t2 = max(brfperiod)
        i2 = np.where(self.wldset.xldates <= t2)[0][-1]

        time = np.copy(self.wldset.xldates[i1:i2+1])
        wl = np.copy(self.wldset['WL'][i1:i2+1])
        bp = np.copy(self.wldset['BP'][i1:i2+1])
        if len(bp) == 0:
            msg = ("The barometric response function cannot be computed"
                   " because the currently selected water level dataset does"
                   " not contain any barometric data for the selected period.")
            QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok)
            return
        et = np.copy(self.wldset['ET'][i1:i2+1])
        if len(et) == 0:
            et = np.zeros(len(wl))

        # Fill the gaps in the waterlevel data.
        dt = np.min(np.diff(time))
        tc = np.arange(t1, t2+dt/2, dt)
        if len(tc) != len(time) or np.any(np.isnan(wl)):
            print('Filling gaps in data with linear interpolation.')
            indx = np.where(~np.isnan(wl))[0]
            wl = np.interp(tc, time[indx], wl[indx])

            indx = np.where(~np.isnan(bp))[0]
            bp = np.interp(tc, time[indx], bp[indx])

            indx = np.where(~np.isnan(et))[0]
            et = np.interp(tc, time[indx], et[indx])

            time = tc

        QApplication.setOverrideCursor(Qt.WaitCursor)
        print('calculating the BRF')

        bm.produce_BRFInputtxt(well, time, wl, bp, et)
        msg = ("Not enough data. Try enlarging the selected period "
               "or reduce the number of BP lags.")
        if self.nlag_baro >= len(time) or self.nlag_earthtides >= len(time):
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok)
            return

        bm.produce_par_file(
            self.nlag_baro, self.nlag_earthtides, self.detrend_waterlevels,
            self.correct_waterlevels)
        bm.run_kgsbrf()

        try:
            dataf = bm.read_brf_output()
            date_start, date_end = (xldate_as_datetime(xldate, 0) for
                                    xldate in self.get_brfperiod())
            self.wldset.save_brf(dataf, date_start, date_end,
                                 self.detrend_waterlevels)
            self.viewer.new_brf_added()
            self.viewer.show()
            QApplication.restoreOverrideCursor()
        except Exception:
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok)
            return