1111from AnyQt .QtWidgets import (
1212 QGroupBox , QRadioButton , QPushButton , QHBoxLayout , QGridLayout ,
1313 QVBoxLayout , QStackedWidget , QComboBox ,
14- QButtonGroup , QStyledItemDelegate , QListView , QDoubleSpinBox
15- )
16- from AnyQt .QtCore import Qt , QThread , QModelIndex
14+ QButtonGroup , QStyledItemDelegate , QListView , QDoubleSpinBox , QLabel )
15+ from AnyQt .QtCore import Qt , QThread , QModelIndex , QDateTime , QLocale
1716from AnyQt .QtCore import pyqtSlot as Slot
17+ from AnyQt .QtGui import QDoubleValidator
18+
1819from orangewidget .utils .listview import ListViewSearch
1920
2021import Orange .data
@@ -154,6 +155,8 @@ class Warning(OWWidget.Warning):
154155 _variable_imputation_state = settings .ContextSetting ({}) # type: VariableState
155156
156157 autocommit = settings .Setting (True )
158+ default_numeric = settings .Setting ("" )
159+ default_time = settings .Setting (0 )
157160
158161 want_main_area = False
159162 resizing_enabled = False
@@ -171,11 +174,13 @@ def __init__(self):
171174 main_layout .setContentsMargins (10 , 10 , 10 , 10 )
172175 self .controlArea .layout ().addLayout (main_layout )
173176
174- box = QGroupBox (title = self .tr ("Default Method" ), flat = False )
175- box_layout = QGridLayout (box )
176- box_layout .setContentsMargins (5 , 0 , 0 , 0 )
177+ box = gui .vBox (None , "Default Method" )
177178 main_layout .addWidget (box )
178179
180+ box_layout = QGridLayout (box )
181+ box_layout .setSpacing (8 )
182+ box .layout ().addLayout (box_layout )
183+
179184 button_group = QButtonGroup ()
180185 button_group .buttonClicked [int ].connect (self .set_default_method )
181186
@@ -186,6 +191,41 @@ def __init__(self):
186191 button_group .addButton (button , method )
187192 box_layout .addWidget (button , i % 3 , i // 3 )
188193
194+ def set_to_fixed_value ():
195+ self .set_default_method (Method .Default )
196+
197+ def set_default_time (datetime ):
198+ self .default_time = datetime .toSecsSinceEpoch ()
199+ if self .default_method_index != Method .Default :
200+ set_to_fixed_value ()
201+ else :
202+ self ._invalidate ()
203+
204+ hlayout = QHBoxLayout ()
205+ box .layout ().addLayout (hlayout )
206+ button = QRadioButton ("Fixed values; numeric variables:" )
207+ button_group .addButton (button , Method .Default )
208+ button .setChecked (Method .Default == self .default_method_index )
209+ hlayout .addWidget (button )
210+
211+ locale = QLocale ()
212+ locale .setNumberOptions (locale .NumberOption .RejectGroupSeparator )
213+ validator = QDoubleValidator ()
214+ validator .setLocale (locale )
215+ le = gui .lineEdit (
216+ None , self , "default_numeric" ,
217+ validator = validator , alignment = Qt .AlignRight ,
218+ callback = self ._invalidate , focusInCallback = set_to_fixed_value )
219+ hlayout .addWidget (le )
220+
221+ hlayout .addWidget (QLabel (", time:" ))
222+
223+ self .time_widget = gui .DateTimeEditWCalendarTime (self )
224+ self .time_widget .setContentsMargins (0 , 0 , 0 , 0 )
225+ self .default_time = QDateTime .currentDateTime ().toSecsSinceEpoch ()
226+ self .time_widget .dateTimeChanged .connect (set_default_time )
227+ hlayout .addWidget (self .time_widget )
228+
189229 self .default_button_group = button_group
190230
191231 box = QGroupBox (title = self .tr ("Individual Attribute Settings" ),
@@ -267,6 +307,17 @@ def create_imputer(self, method, *args):
267307 m = AsDefault ()
268308 m .method = default
269309 return m
310+ elif method == Method .Default and not args : # global default values
311+ if self .default_numeric == "" :
312+ default_num = np .nan
313+ else :
314+ default_num , ok = QLocale ().toDouble (self .default_numeric )
315+ if not ok :
316+ default_num = np .nan
317+ return impute .FixedValueByType (
318+ default_continuous = default_num ,
319+ default_time = self .default_time or np .nan
320+ )
270321 else :
271322 return METHODS [method ](* args )
272323
@@ -302,6 +353,8 @@ def set_data(self, data):
302353 if data is not None :
303354 self .varmodel [:] = data .domain .variables
304355 self .openContext (data .domain )
356+ self .time_widget .set_datetime (
357+ QDateTime .fromSecsSinceEpoch (self .default_time ))
305358 # restore per variable imputation state
306359 self ._restore_state (self ._variable_imputation_state )
307360
@@ -660,5 +713,19 @@ def storeSpecificSettings(self):
660713 super ().storeSpecificSettings ()
661714
662715
716+ def __sample_data (): # pragma: no cover
717+ domain = Orange .data .Domain (
718+ [Orange .data .ContinuousVariable (f"c{ i } " ) for i in range (3 )]
719+ + [Orange .data .TimeVariable (f"t{ i } " ) for i in range (3 )],
720+ [])
721+ n = np .nan
722+ x = np .array ([
723+ [1 , 2 , n , 1000 , n , n ],
724+ [2 , n , 1 , n , 2000 , 2000 ]
725+ ])
726+ return Orange .data .Table (domain , x , np .empty ((2 , 0 )))
727+
728+
663729if __name__ == "__main__" : # pragma: no cover
730+ # WidgetPreview(OWImpute).run(__sample_data())
664731 WidgetPreview (OWImpute ).run (Orange .data .Table ("brown-selected" ))
0 commit comments