@@ -147,8 +147,11 @@ class Warning(widget.OWWidget.Warning):
147147 class Error (widget .OWWidget .Error ):
148148 file_not_found = Msg ("File not found." )
149149 missing_reader = Msg ("Missing reader." )
150+ select_file_type = Msg ("Select file type." )
150151 sheet_error = Msg ("Error listing available sheets." )
151152 unknown = Msg ("Read error:\n {}" )
153+ unknown_select = Msg (
154+ "Read error, possibly due to incorrect choice of file type:\n {}" )
152155
153156 UserAdviceMessages = [
154157 widget .Message (
@@ -264,7 +267,7 @@ def package(w):
264267 self .reader_combo = QComboBox (self )
265268 self .reader_combo .setSizePolicy (Policy .Expanding , Policy .Fixed )
266269 self .reader_combo .setMinimumSize (QSize (100 , 1 ))
267- self .reader_combo .activated [int ].connect (self .select_reader )
270+ self .reader_combo .activated [int ].connect (self .on_reader_change )
268271
269272 box .layout ().addWidget (self .reader_combo )
270273 layout .addWidget (box , 0 , 1 )
@@ -327,6 +330,10 @@ def select_sheet(self):
327330 self .recent_paths [0 ].sheet = self .sheet_combo .currentText ()
328331 self .load_data ()
329332
333+ def on_reader_change (self , n ):
334+ self .select_reader (n )
335+ self .load_data ()
336+
330337 def select_reader (self , n ):
331338 if self .source != self .LOCAL_FILE :
332339 return # ignore for URL's
@@ -335,14 +342,11 @@ def select_reader(self, n):
335342 path = self .recent_paths [0 ]
336343 if n == 0 : # default
337344 path .file_format = None
338- self .load_data ()
339345 elif n <= len (self .available_readers ):
340346 reader = self .available_readers [n - 1 ]
341347 path .file_format = reader .qualified_name ()
342- self .load_data ()
343348 else : # the rest include just qualified names
344349 path .file_format = self .reader_combo .itemText (n )
345- self .load_data ()
346350
347351 def _url_set (self ):
348352 index = self .url_combo .currentIndex ()
@@ -373,7 +377,9 @@ def browse_file(self, in_demos=False):
373377 else :
374378 start_file = self .last_path () or os .path .expanduser ("~/" )
375379
376- filename , reader , _ = open_filename_dialog (start_file , None , self .available_readers )
380+ filename , reader , _ = open_filename_dialog (
381+ start_file , None , self .available_readers ,
382+ add_all = "*" )
377383 if not filename :
378384 return
379385 self .add_path (filename )
@@ -415,20 +421,20 @@ def _try_load(self):
415421 if not url :
416422 return self .Information .no_file_selected
417423
418- def mark_problematic_reader ():
419- self .reader_combo .setItemData (self .reader_combo .currentIndex (),
420- QBrush (Qt .red ), Qt .ForegroundRole )
421-
422424 try :
423425 self .reader = self ._get_reader () # also sets current reader index
424426 assert self .reader is not None
425427 except MissingReaderException :
426- mark_problematic_reader ()
427- return self .Error .missing_reader
428+ if self .reader_combo .currentIndex () > 0 :
429+ return self .Error .missing_reader
430+ else :
431+ return self .Error .select_file_type
428432 except Exception as ex :
429- mark_problematic_reader ()
430433 log .exception (ex )
431- return lambda x = ex : self .Error .unknown (str (x ))
434+ if self .reader_combo .currentIndex () > 0 :
435+ return lambda x = ex : self .Error .unknown (str (x ))
436+ else :
437+ return lambda x = ex : self .Error .unknown_select (str (x ))
432438
433439 try :
434440 self ._update_sheet_combo ()
@@ -439,7 +445,6 @@ def mark_problematic_reader():
439445 try :
440446 data = self .reader .read ()
441447 except Exception as ex :
442- mark_problematic_reader ()
443448 log .exception (ex )
444449 return lambda x = ex : self .Error .unknown (str (x ))
445450 if warnings :
@@ -455,9 +460,25 @@ def mark_problematic_reader():
455460 return None
456461
457462 def _get_reader (self ) -> FileFormat :
463+ """
464+ Get the reader for the current file.
465+
466+ For local files, this also observes the stored settings and the reader
467+ combo, as follows:
468+
469+ 1. If the file format is known (from stored settings), use it and set
470+ the reader combo to the corresponding index (as in settings)
471+ 2. Otherwise, detect it from the extension and set the combo to
472+ Auto detect, overriding any previous user-set choice
473+ 3. Otherwise, use the current combo state.
474+
475+ Returns:
476+ FileFormat: reader instance
477+ """
458478 if self .source == self .LOCAL_FILE :
459479 path = self .last_path ()
460480 self .reader_combo .setEnabled (True )
481+
461482 if self .recent_paths and self .recent_paths [0 ].file_format :
462483 qname = self .recent_paths [0 ].file_format
463484 qname_index = {r .qualified_name (): i for i , r in enumerate (self .available_readers )}
@@ -471,11 +492,22 @@ def _get_reader(self) -> FileFormat:
471492 try :
472493 reader_class = class_from_qualified_name (qname )
473494 except Exception as ex :
474- raise MissingReaderException (f'Can not find reader "{ qname } "' ) from ex
495+ raise MissingReaderException (f'Can not fdind reader "{ qname } "' ) from ex
475496 reader = reader_class (path )
497+
476498 else :
477- self .reader_combo .setCurrentIndex (0 )
478- reader = FileFormat .get_reader (path )
499+ old_idx = self .reader_combo .currentIndex ()
500+ try :
501+ self .reader_combo .setCurrentIndex (0 )
502+ reader = FileFormat .get_reader (path )
503+ except MissingReaderException :
504+ if old_idx == 0 :
505+ raise
506+ # Set the path for the current file format,
507+ # and repeat the call to return the corresponding reader
508+ self .select_reader (old_idx )
509+ return self ._get_reader ()
510+
479511 if self .recent_paths and self .recent_paths [0 ].sheet :
480512 reader .select_sheet (self .recent_paths [0 ].sheet )
481513 return reader
@@ -504,12 +536,21 @@ def _select_active_sheet(self):
504536 self .sheet_combo .setCurrentIndex (0 )
505537
506538 def _initialize_reader_combo (self ):
507- self .reader_combo .clear ()
508- filters = [format_filter (f ) for f in self .available_readers ]
509- self .reader_combo .addItems ([DEFAULT_READER_TEXT ] + filters )
510- self .reader_combo .setCurrentIndex (0 )
511- self .reader_combo .setDisabled (True )
512- # additional readers may be added in self._get_reader()
539+ # Reset to initial state without losing the current index or
540+ # emitting any signals.
541+ combo = self .reader_combo
542+ if not combo .count ():
543+ filters = [format_filter (f ) for f in self .available_readers ]
544+ combo .addItems ([DEFAULT_READER_TEXT ] + filters )
545+ combo .setCurrentIndex (0 )
546+ else :
547+ # additional readers may be added in self._get_reader()
548+ n = len (self .available_readers ) + 1
549+ if combo .currentIndex () >= n :
550+ combo .setCurrentIndex (0 )
551+ while combo .count () > n :
552+ combo .removeItem (combo .count () - 1 )
553+ combo .setDisabled (True )
513554
514555 @staticmethod
515556 def _describe (table ):
0 commit comments