def __init__(self, parent: QWidget, variable: ContinuousVariable, min_value: float, max_value: float, callback: Callable): super().__init__(parent, callback) if np.isnan(min_value) or np.isnan(max_value): raise ValueError("Min/Max cannot be NaN.") n_decimals = variable.number_of_decimals abs_max = max(abs(min_value), max_value) if abs_max * 10**n_decimals > self.MAX_FLOAT: n_decimals = int(np.log10(self.MAX_FLOAT / abs_max)) self._value: float = min_value self._n_decimals: int = n_decimals self._min_value: float = self.__round_value(min_value) self._max_value: float = self.__round_value(max_value) sp_spin = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sp_spin.setHorizontalStretch(1) sp_slider = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sp_slider.setHorizontalStretch(5) sp_edit = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sp_edit.setHorizontalStretch(1) class DoubleSpinBox(QDoubleSpinBox): def sizeHint(self) -> QSize: size: QSize = super().sizeHint() return QSize(size.width(), size.height() + 2) self._spin = DoubleSpinBox( parent, value=self._min_value, minimum=-np.inf, maximum=np.inf, singleStep=10**(-self._n_decimals), decimals=self._n_decimals, minimumWidth=70, sizePolicy=sp_spin, ) self._slider = QSlider( parent, minimum=self.__map_to_slider(self._min_value), maximum=self.__map_to_slider(self._max_value), singleStep=1, orientation=Qt.Horizontal, sizePolicy=sp_slider, ) self._label_min = QLabel( parent, text=variable.repr_val(min_value), alignment=Qt.AlignRight, minimumWidth=60, sizePolicy=sp_edit, ) self._label_max = QLabel( parent, text=variable.repr_val(max_value), alignment=Qt.AlignLeft, minimumWidth=60, sizePolicy=sp_edit, ) self._slider.valueChanged.connect(self._apply_slider_value) self._spin.valueChanged.connect(self._apply_spin_value) self.layout().addWidget(self._spin) self.layout().addWidget(self._label_min) self.layout().addWidget(self._slider) self.layout().addWidget(self._label_max) self.setFocusProxy(self._spin) def deselect(): self._spin.lineEdit().deselect() try: self._spin.lineEdit().selectionChanged.disconnect(deselect) except TypeError: pass # Invoking self.setFocusProxy(self._spin), causes the # self._spin.lineEdit()s to have selected texts (focus is set to # provide keyboard functionality, i.e.: pressing ESC after changing # spinbox value). Since the spin text is selected only after the # delegate draws it, it cannot be deselected during initialization. # Therefore connect the deselect() function to # self._spin.lineEdit().selectionChanged only for editor creation. self._spin.lineEdit().selectionChanged.connect(deselect) self._slider.installEventFilter(self) self._spin.installEventFilter(self)
def __init__(self): super().__init__() whole_box = gui.widgetBox(self.controlArea, "", orientation=False) left_box = gui.widgetBox(whole_box, "") right_box = gui.widgetBox(whole_box, "") info_box = gui.widgetBox(left_box, "Info") self.info = gui.widgetLabel( info_box, 'Input: no reporters, no partners, no commodities/services') size_policy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Minimum) top_box = gui.widgetBox(left_box, "Type of output") gui.radioButtonsInBox(top_box, self, 'profiles_or_time_series', ['Profiles', 'Time series'], orientation=False, sizePolicy=size_policy, callback=self.clear_messages) reporter_partner_years_box = gui.widgetBox(left_box, "", orientation=False) size_policy.setHorizontalStretch(2) reporters_box = gui.widgetBox(reporter_partner_years_box, "Reporters", sizePolicy=size_policy) gui.lineEdit(reporters_box, self, 'reporter_filter', 'Filter ', callback=(lambda: self.filter(self.list_model_reporter[1], self.reporter_filter)), callbackOnType=True, orientation=False) self.list_model_reporter = self.make_continent_view( 'rep', self.on_continent_item_changed, reporters_box) size_policy.setHorizontalStretch(2) partners_box = gui.widgetBox(reporter_partner_years_box, "Partners", sizePolicy=size_policy) gui.lineEdit(partners_box, self, 'partner_filter', 'Filter ', callback=(lambda: self.filter(self.list_model_partner[1], self.partner_filter)), callbackOnType=True, orientation=False) self.list_model_partner = self.make_continent_view( 'par', self.on_continent_item_changed, partners_box) size_policy.setHorizontalStretch(1) years_box = gui.widgetBox(reporter_partner_years_box, "Years", sizePolicy=size_policy) gui.lineEdit(years_box, self, 'years_filter', 'Filter ', callback=(lambda: self.filter(self.list_model_years[1], self.years_filter)), callbackOnType=True, orientation=False) self.list_model_years = self.make_list_view(self.on_item_changed, years_box) trade_flows_box = gui.widgetBox(left_box, "Trade", orientation=False) gui.checkBox(trade_flows_box, self, 'tf_import', 'Import', callback=self.on_item_changed) exp = gui.checkBox(trade_flows_box, self, 'tf_export', 'Export', callback=self.on_item_changed) exp.setCheckState(Qt.Checked) gui.checkBox(trade_flows_box, self, 'tf_re_import', 'Re-import', callback=self.on_item_changed) gui.checkBox(trade_flows_box, self, 'tf_re_export', 'Re-export', callback=self.on_item_changed) commodities_services_box = gui.widgetBox(right_box, "Exchange Type") gui.radioButtonsInBox( commodities_services_box, self, 'commodities_or_services', ['Commodities', 'Services'], orientation=False, sizePolicy=size_policy, callback=(lambda: self.change_tree_view(commodities_services_box))) gui.lineEdit(commodities_services_box, self, 'comm_ser_filter', 'Filter ', callback=(lambda: self.filter(self.tree_model_cs[1], self. comm_ser_filter)), callbackOnType=True, orientation=False) self.tree_model_cs = self.make_tree_view('comm', self.on_item_changed, commodities_services_box) button_box = gui.widgetBox(left_box, "") self.commit_button = gui.button(button_box, self, "Commit", callback=self.commit) self.commit_button.setEnabled(False) # activate filters self.filter(self.list_model_reporter[1], self.reporter_filter) self.filter(self.list_model_partner[1], self.partner_filter) self.filter(self.list_model_years[1], self.years_filter) self.filter(self.tree_model_cs[1], self.comm_ser_filter)