Esempio n. 1
0
    def create_geog_form(self):
        grid = QGridLayout()
        self.geog_dataset_form = QGroupBox('Add Dataset')
        self.geog_dataset_form.setLayout(grid)
        self.geog_dataset_form.hide()

        group_name_validator = StringValidator(lambda s: s and re.fullmatch(r'[a-zA-Z0-9_]+', s))
        # TODO fix validator if empty
        interp_validator = StringValidator(lambda s: ' ' not in s)

        self.geog_dataset_form_group_name = add_grid_lineedit(grid, 0, 'Group Name',
                                                              validator=group_name_validator, required=True)
        self.geog_dataset_form_dataset = add_grid_combobox(grid, 1, 'Dataset')
        self.geog_dataset_form_variable = add_grid_combobox(grid, 2, 'Variable')
        self.geog_dataset_form_interp = add_grid_combobox(grid, 3, 'Interpolation')
        self.geog_dataset_form_custom_interp = add_grid_lineedit(grid, 4, 'Custom Interpolation',
                                                                 validator=interp_validator, required=False)
        
        self.geog_dataset_form_variable.currentIndexChanged.connect(self.geog_dataset_form_variable_changed)

        btn_add = QPushButton('Add')
        btn_cancel = QPushButton('Cancel')
        btn_add.clicked.connect(self.on_add_geog_dataset_form_button_clicked)
        btn_cancel.clicked.connect(self.on_cancel_geog_dataset_form_button_clicked)

        grid.addWidget(btn_cancel, 5, 0)
        grid.addWidget(btn_add, 5, 1)
Esempio n. 2
0
def create_parent_group_box(name: str,
                            res: float,
                            unit: str,
                            required: bool = False) -> QGroupBox:
    """Returns a 'validator-ready' group box to be used by the parent-domain tab."""
    parent_child_ratio_box = QGridLayout()
    # TODO: This should be a spinbox instead with range [1,5].
    parent_child_ratio = add_grid_lineedit(parent_child_ratio_box,
                                           0,
                                           'Child-to-Parent Ratio',
                                           RATIO_VALIDATOR,
                                           required=required)

    res_label = QLabel(
        HORIZONTAL_RESOLUTION_LABEL.format(resolution=res, unit=unit))

    sub_group_box = QGroupBox("Padding")
    grid = QGridLayout()
    top_label = QLabel('Top')
    top_label.setAlignment(Qt.AlignCenter)
    grid.addWidget(top_label, 0, 1)
    left_label = QLabel('Left')
    left_label.setAlignment(Qt.AlignCenter)
    grid.addWidget(left_label, 2, 0)
    right_label = QLabel('Right')
    right_label.setAlignment(Qt.AlignCenter)
    grid.addWidget(right_label, 2, 2)
    bottom_label = QLabel('Bottom')
    bottom_label.setAlignment(Qt.AlignCenter)
    grid.addWidget(bottom_label, 4, 1)
    top = create_lineedit(DIM_VALIDATOR, required)
    left = create_lineedit(DIM_VALIDATOR, required)
    right = create_lineedit(DIM_VALIDATOR, required)
    bottom = create_lineedit(DIM_VALIDATOR, required)
    grid.addWidget(top, 1, 1)
    grid.addWidget(left, 3, 0)
    grid.addWidget(right, 3, 2)
    grid.addWidget(bottom, 5, 1)
    sub_group_box.setLayout(grid)

    vbox = QVBoxLayout()
    vbox.addLayout(parent_child_ratio_box)
    vbox.addWidget(res_label)
    vbox.addWidget(sub_group_box)
    group_box = QGroupBox(name)
    group_box.setLayout(vbox)
    return {
        'inputs': {
            'ratio': parent_child_ratio,
            'top': top,
            'left': left,
            'right': right,
            'bottom': bottom
        },
        'other': {
            'resolution': res_label
        }
    }, group_box
Esempio n. 3
0
    def create_interp_input(self) -> None:
        grid = QGridLayout()

        self.interp_vert_selector = add_grid_combobox(grid, 0, 'Vertical Variable')
        self.interp_input = add_grid_lineedit(grid, 1, 'Desired Level', QDoubleValidator(0.0, 10000.0, 50), required=True)       
        self.interp_input.returnPressed.connect(self.on_interp_btn_clicked)

        btn = QPushButton('Interpolate')
        btn.clicked.connect(self.on_interp_btn_clicked)
        grid.addWidget(btn, 2, 1)

        self.interp_container = QGroupBox('Interpolate Vertical Level')
        self.interp_container.setCheckable(True)
        self.interp_container.setChecked(False)
        self.interp_container.toggled.connect(self.on_interp_toggled)
        self.interp_container.setLayout(grid)
        self.interp_container.setHidden(True)
        self.vbox.addWidget(self.interp_container)
Esempio n. 4
0
    def __init__(self, iface: QgisInterface) -> None:
        super().__init__()
        self.iface = iface

        # Import/Export
        ## Import from 'namelist.wps'
        import_from_namelist_button = QPushButton("Import from namelist")
        import_from_namelist_button.setObjectName('import_from_namelist')

        ## Export to namelist
        export_geogrid_namelist_button = QPushButton("Export to namelist")
        export_geogrid_namelist_button.setObjectName(
            'export_geogrid_namelist_button')

        vbox_import_export = QVBoxLayout()
        vbox_import_export.addWidget(import_from_namelist_button)
        vbox_import_export.addWidget(export_geogrid_namelist_button)

        self.gbox_import_export = QGroupBox("Import/Export")
        self.gbox_import_export.setLayout(vbox_import_export)

        # Group: Map Type
        self.group_box_map_type = QGroupBox("Map Type")
        vbox_map_type = QVBoxLayout()
        hbox_map_type = QHBoxLayout()

        self.projection = QComboBox()
        self.projection.setObjectName('projection')
        projs = {
            'undefined':
            '-',  # do not use a default projection - let the user pick the projection.
            'lat-lon': 'Latitude/Longitude',
            'lambert': 'Lambert'
        }
        for proj_id, proj_label in projs.items():
            self.projection.addItem(proj_label, proj_id)

        hbox_map_type.addWidget(QLabel('GCS/Projection:'))
        # TODO: when the user select the type of GCS/Projection
        # we should automatically change the GCS/Projection for the whole
        # project. This will do an on-the-fly remapping of any of the other CRS
        # which are different from the one supported by our tool/WRF.
        # The Project CRS can be accessed in QGIS under the menu `Project` > `Project Properties` > `CRS.`
        # -> This is only really possible for Lat/Lon as this one is a CRS, where the others are projections
        #    that only become a full CRS with the additional parameters like truelat1.
        # TODO: fields should be cleared when the user changes the CRS/Projection.
        hbox_map_type.addWidget(self.projection)
        vbox_map_type.addLayout(hbox_map_type)

        ## Lambert only: show 'True Latitudes' field
        truelat_grid = QGridLayout()
        self.truelat1 = add_grid_lineedit(truelat_grid,
                                          0,
                                          'True Latitude 1',
                                          LAT_VALIDATOR,
                                          unit='°',
                                          required=True)
        self.truelat2 = add_grid_lineedit(truelat_grid,
                                          1,
                                          'True Latitude 2',
                                          LAT_VALIDATOR,
                                          unit='°',
                                          required=True)
        self.widget_true_lats = QWidget()
        self.widget_true_lats.setLayout(truelat_grid)
        vbox_map_type.addWidget(self.widget_true_lats)

        self.domain_pb_set_projection = QPushButton("Set Map CRS")
        self.domain_pb_set_projection.setObjectName('set_projection_button')
        vbox_map_type.addWidget(self.domain_pb_set_projection)
        self.group_box_map_type.setLayout(vbox_map_type)

        # Group: Horizontal Resolution
        self.group_box_resol = QGroupBox("Horizontal Grid Spacing")
        hbox_resol = QHBoxLayout()
        self.resolution = MyLineEdit(required=True)
        self.resolution.setValidator(RESOLUTION_VALIDATOR)
        self.resolution.textChanged.connect(
            lambda _: update_input_validation_style(self.resolution))
        self.resolution.textChanged.emit(self.resolution.text())
        hbox_resol.addWidget(self.resolution)
        self.resolution_label = QLabel()
        hbox_resol.addWidget(self.resolution_label)

        self.group_box_resol.setLayout(hbox_resol)

        # Group: Automatic Domain Generator
        self.group_box_auto_domain = QGroupBox("Grid Extent Calculator")
        vbox_auto_domain = QVBoxLayout()
        hbox_auto_domain = QHBoxLayout()
        domain_pb_set_canvas_extent = QPushButton("Set to Canvas Extent")
        domain_pb_set_canvas_extent.setObjectName('set_canvas_extent_button')
        domain_pb_set_layer_extent = QPushButton("Set to Active Layer Extent")
        domain_pb_set_layer_extent.setObjectName('set_layer_extent_button')
        vbox_auto_domain.addLayout(hbox_auto_domain)
        vbox_auto_domain.addWidget(domain_pb_set_canvas_extent)
        vbox_auto_domain.addWidget(domain_pb_set_layer_extent)
        self.group_box_auto_domain.setLayout(vbox_auto_domain)

        # Group: Manual Domain Configuration

        ## Subgroup: Centre Point
        grid_center_point = QGridLayout()
        self.center_lon = add_grid_lineedit(grid_center_point,
                                            0,
                                            'Longitude',
                                            LON_VALIDATOR,
                                            '°',
                                            required=True)
        self.center_lat = add_grid_lineedit(grid_center_point,
                                            1,
                                            'Latitude',
                                            LAT_VALIDATOR,
                                            '°',
                                            required=True)
        group_box_centre_point = QGroupBox("Center Point")
        group_box_centre_point.setLayout(grid_center_point)

        ## Subgroup: Advanced configuration
        grid_dims = QGridLayout()
        self.cols = add_grid_lineedit(grid_dims,
                                      0,
                                      'Horizontal',
                                      DIM_VALIDATOR,
                                      required=True)
        self.rows = add_grid_lineedit(grid_dims,
                                      1,
                                      'Vertical',
                                      DIM_VALIDATOR,
                                      required=True)
        group_box_dims = QGroupBox("Grid Extent")
        group_box_dims.setLayout(grid_dims)

        vbox_manual_domain = QVBoxLayout()
        vbox_manual_domain.addWidget(group_box_centre_point)
        vbox_manual_domain.addWidget(group_box_dims)

        self.group_box_manual_domain = QGroupBox("Advanced Configuration")
        # TODO: make this section collapsable (default state collapsed)
        # and change the checkbox to arrows like `setArrowType(Qt.RightArrow)`
        # TODO: the style should be disabled when the 'advanced configuration' box is disabled (default).
        self.group_box_manual_domain.setCheckable(True)
        self.group_box_manual_domain.setChecked(False)
        self.group_box_manual_domain.setLayout(vbox_manual_domain)

        for field in [
                self.resolution, self.center_lat, self.center_lon, self.rows,
                self.cols, self.truelat1, self.truelat2
        ]:
            # editingFinished is only emitted on user input, not via programmatic changes.
            # This is important as we want to avoid re-drawing the bbox many times when several
            # fields get changed while using the automatic domain generator.
            field.editingFinished.connect(self.on_change_any_field)

        # Group Box: Parent Domain
        self.group_box_parent_domain = QGroupBox("Enable Parenting")
        self.group_box_parent_domain.setObjectName('group_box_parent_domain')
        self.group_box_parent_domain.setCheckable(True)
        self.group_box_parent_domain.setChecked(False)

        # TODO: As it is for the single domain case the generation of the domain should be automatic.
        # For now leave placeholder values of '3' for Child to Parent Ratio and '2' for padding.
        # use `calc_parent_lonlat_from_child` in `routines.py` to calculate the coordinate of the domain given the child domain coordinate,
        # grid_ratio and padding.
        hbox_parent_num = QHBoxLayout()
        hbox_parent_num.addWidget(QLabel('Number of Parent Domains:'))
        self.parent_spin = QSpinBox()
        self.parent_spin.setObjectName('parent_spin')
        self.parent_spin.setRange(1, MAX_PARENTS)
        hbox_parent_num.addWidget(self.parent_spin)

        self.group_box_parent_domain.setLayout(hbox_parent_num)

        self.parent_domains = []  # type: list
        self.parent_vbox = QVBoxLayout()
        self.parent_vbox.setSizeConstraint(QLayout.SetMinimumSize)

        go_to_data_tab_btn = QPushButton('Continue to Datasets')
        go_to_data_tab_btn.clicked.connect(self.go_to_data_tab)

        # Tabs
        dom_mgr_layout = QVBoxLayout()
        dom_mgr_layout.addWidget(self.gbox_import_export)
        dom_mgr_layout.addWidget(self.group_box_map_type)
        dom_mgr_layout.addWidget(self.group_box_resol)
        dom_mgr_layout.addWidget(self.group_box_auto_domain)
        dom_mgr_layout.addWidget(self.group_box_manual_domain)
        dom_mgr_layout.addWidget(self.group_box_parent_domain)
        dom_mgr_layout.addLayout(self.parent_vbox)
        dom_mgr_layout.addWidget(go_to_data_tab_btn)
        self.setLayout(dom_mgr_layout)

        QMetaObject.connectSlotsByName(self)

        # trigger event for initial layout
        self.projection.currentIndexChanged.emit(
            self.projection.currentIndex())
Esempio n. 5
0
    def __init__(self, iface) -> None:
        super().__init__()

        self.iface = iface
        self.options = get_options()
        self.msg_bar = MessageBar(iface)

        vbox = QVBoxLayout()
        self.setLayout(vbox)

        hbox = QHBoxLayout()
        vbox.addLayout(hbox)

        hbox.addWidget(QLabel('Dataset: '))
        self.cbox_dataset = QComboBox()
        self.cbox_dataset.addItem('-')
        for index, (dataset_name,
                    dataset_label) in enumerate(met_datasets.items()):
            self.cbox_dataset.addItem(dataset_name, dataset_name)
            self.cbox_dataset.setItemData(index + 1, dataset_label,
                                          Qt.ToolTipRole)
        self.cbox_dataset.currentIndexChanged.connect(self.on_dataset_changed)
        hbox.addWidget(self.cbox_dataset)

        hbox_product_name = QHBoxLayout()
        vbox.addLayout(hbox_product_name)
        hbox_product_name.addWidget(QLabel('Product: '))
        self.cbox_product = QComboBox()
        self.cbox_product.currentIndexChanged.connect(self.on_product_changed)
        hbox_product_name.addWidget(self.cbox_product)

        hbox_start_datetime = QHBoxLayout()
        vbox.addLayout(hbox_start_datetime)
        self.dedit_start_date = QDateTimeEdit()
        self.dedit_start_date.setCalendarPopup(True)
        hbox_start_datetime.addWidget(QLabel('Start: '))
        hbox_start_datetime.addWidget(self.dedit_start_date)

        hbox_end_datetime = QHBoxLayout()
        vbox.addLayout(hbox_end_datetime)
        self.dedit_end_date = QDateTimeEdit()
        self.dedit_end_date.setCalendarPopup(True)
        hbox_end_datetime.addWidget(QLabel('End: '))
        hbox_end_datetime.addWidget(self.dedit_end_date)

        gbox_extent = QGroupBox('Extent')
        vbox.addWidget(gbox_extent)
        vbox_extent = QVBoxLayout()
        gbox_extent.setLayout(vbox_extent)

        hbox_extent = QHBoxLayout()
        vbox_extent.addLayout(hbox_extent)
        self.radio_global = QRadioButton('Global')
        self.radio_global.toggled.connect(self.on_extent_radio_button_clicked)
        hbox_extent.addWidget(self.radio_global)
        self.radio_subset = QRadioButton('Subset')
        self.radio_subset.toggled.connect(self.on_extent_radio_button_clicked)
        hbox_extent.addWidget(self.radio_subset)

        self.widget_extent = QWidget()
        vbox_extent.addWidget(self.widget_extent)
        grid_extent = QGridLayout()
        self.widget_extent.setLayout(grid_extent)
        self.widget_extent.hide()
        self.top = add_grid_lineedit(grid_extent,
                                     0,
                                     'North Latitude',
                                     LAT_VALIDATOR,
                                     '°',
                                     required=True)
        self.right = add_grid_lineedit(grid_extent,
                                       1,
                                       'East Longitude',
                                       LON_VALIDATOR,
                                       '°',
                                       required=True)
        self.left = add_grid_lineedit(grid_extent,
                                      2,
                                      'West Longitude',
                                      LON_VALIDATOR,
                                      '°',
                                      required=True)
        self.bottom = add_grid_lineedit(grid_extent,
                                        3,
                                        'South Latitude',
                                        LAT_VALIDATOR,
                                        '°',
                                        required=True)
        self.extent_from_active_layer = QPushButton('Set from Active Layer')
        grid_extent.addWidget(self.extent_from_active_layer, 4, 1)
        self.extent_from_active_layer.clicked.connect(
            self.on_extent_from_active_layer_button_clicked)
        self.radio_global.setChecked(True)

        self.tree = QListWidget()
        vbox_tree = QVBoxLayout()
        vbox.addLayout(vbox_tree)
        vbox_tree.addWidget(self.tree)

        self.btn_download = QPushButton('Download')
        self.btn_download.clicked.connect(self.on_download_button_clicked)
        vbox.addWidget(self.btn_download)

        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, PROGRESS_BAR_MAX)
        self.progress_bar.setTextVisible(False)
        self.progress_bar.hide()
        vbox.addWidget(self.progress_bar)
    def __init__(self, vtable_dir: str, spec: Optional[dict] = None) -> None:
        super().__init__()

        self.vtable_dir = vtable_dir
        self.paths = set()  # type: Set[Path]

        geom = QGuiApplication.primaryScreen().geometry()
        w, h = geom.width(), geom.height()
        self.setWindowTitle("Custom Meteorological Dataset")
        self.setMinimumSize(w * 0.25, h * 0.35)

        layout = QVBoxLayout()

        # button to open folder/files dialog
        hbox = QHBoxLayout()
        layout.addLayout(hbox)
        add_folder_btn = QPushButton('Add folder')
        add_files_btn = QPushButton('Add files')
        remove_selected_btn = QPushButton('Remove selected')
        hbox.addWidget(add_folder_btn)
        hbox.addWidget(add_files_btn)
        hbox.addWidget(remove_selected_btn)
        add_folder_btn.clicked.connect(self.on_add_folder_btn_clicked)
        add_files_btn.clicked.connect(self.on_add_files_btn_clicked)
        remove_selected_btn.clicked.connect(
            self.on_remove_selected_btn_clicked)

        # show added files in a list
        self.paths_list = QListWidget()
        self.paths_list.setSelectionMode(QAbstractItemView.ContiguousSelection)
        layout.addWidget(self.paths_list)

        grid = QGridLayout()
        layout.addLayout(grid)

        # date/time start/end
        self.start_date_input = QDateTimeEdit()
        self.start_date_input.setCalendarPopup(True)

        self.end_date_input = QDateTimeEdit()
        self.end_date_input.setCalendarPopup(True)

        add_grid_labeled_widget(grid, 0, 'Start Date/Time',
                                self.start_date_input)
        add_grid_labeled_widget(grid, 1, 'End Date/Time', self.end_date_input)

        # interval in seconds
        interval_validator = QIntValidator()
        interval_validator.setBottom(1)
        self.interval_input = add_grid_lineedit(grid,
                                                2,
                                                'Interval in seconds',
                                                interval_validator,
                                                required=True)

        # vtable file input
        self.vtable_input, vtable_hbox = create_file_input(
            dialog_caption='Select VTable file',
            is_folder=False,
            start_folder=vtable_dir)
        add_grid_labeled_widget(grid, 3, 'VTable', vtable_hbox)

        btn_box = QDialogButtonBox(QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)
        btn_box.accepted.connect(self.on_ok_clicked)
        btn_box.rejected.connect(self.reject)
        layout.addWidget(btn_box)

        self.setLayout(layout)

        if spec:
            self.paths = set(map(Path, spec['paths']))
            self.base_folder = spec['base_folder']
            self.update_file_list()

            start_date, end_date = spec['time_range']
            for date_input, date in [(self.start_date_input, start_date),
                                     (self.end_date_input, end_date)]:
                date_input.setDateTime(
                    QDateTime(QDate(date.year, date.month, date.day),
                              QTime(date.hour, date.minute)))

            self.interval_input.set_value(spec['interval_seconds'])

            self.vtable_input.setText(spec['vtable'])