55
66import numpy as np
77from AnyQt .QtWidgets import \
8- QStyle , QComboBox , QMessageBox , QFileDialog , QGridLayout , QLabel , \
8+ QStyle , QComboBox , QMessageBox , QGridLayout , QLabel , \
99 QLineEdit , QSizePolicy as Policy
1010from AnyQt .QtCore import Qt , QTimer , QSize
1111
1212from Orange .canvas .gui .utils import OSX_NSURL_toLocalFile
13- from Orange .data import StringVariable
1413from Orange .data .table import Table , get_sample_datasets_dir
15- from Orange .data .io import FileFormat , UrlReader
14+ from Orange .data .io import FileFormat , UrlReader , class_from_qualified_name
1615from Orange .widgets import widget , gui
1716from Orange .widgets .settings import Setting , ContextSetting , \
1817 PerfectDomainContextHandler , SettingProvider
1918from Orange .widgets .utils .domaineditor import DomainEditor
2019from Orange .widgets .utils .itemmodels import PyListModel
21- from Orange .widgets .utils .filedialogs import RecentPathsWComboMixin , dialog_formats
20+ from Orange .widgets .utils .filedialogs import RecentPathsWComboMixin , \
21+ open_filename_dialog
2222from Orange .widgets .widget import Output
2323
2424# Backward compatibility: class RecentPath used to be defined in this module,
@@ -40,7 +40,7 @@ def add_origin(examples, filename):
4040 return
4141 vars = examples .domain .variables + examples .domain .metas
4242 strings = [var for var in vars if var .is_string ]
43- dir_name , basename = os .path .split (filename )
43+ dir_name , _ = os .path .split (filename )
4444 for var in strings :
4545 if "type" in var .attributes and "origin" not in var .attributes :
4646 var .attributes ["origin" ] = dir_name
@@ -112,9 +112,13 @@ class Outputs:
112112 class Warning (widget .OWWidget .Warning ):
113113 file_too_big = widget .Msg ("The file is too large to load automatically."
114114 " Press Reload to load." )
115+ load_warning = widget .Msg ("Read warning:\n {}" )
115116
116117 class Error (widget .OWWidget .Error ):
117118 file_not_found = widget .Msg ("File not found." )
119+ missing_reader = widget .Msg ("Missing reader." )
120+ sheet_error = widget .Msg ("Error listing available sheets." )
121+ unknown = widget .Msg ("Read error:\n {}" )
118122
119123 def __init__ (self ):
120124 super ().__init__ ()
@@ -264,58 +268,60 @@ def browse_file(self, in_demos=False):
264268 else :
265269 start_file = self .last_path () or os .path .expanduser ("~/" )
266270
267- filename , _ = QFileDialog .getOpenFileName (
268- self , 'Open Orange Data File' , start_file , dialog_formats ())
271+ readers = [f for f in FileFormat .formats
272+ if getattr (f , 'read' , None ) and getattr (f , "EXTENSIONS" , None )]
273+ filename , reader , _ = open_filename_dialog (start_file , None , readers )
269274 if not filename :
270275 return
271276 self .add_path (filename )
277+ if reader is not None :
278+ self .recent_paths [0 ].file_format = reader .qualified_name ()
279+
272280 self .source = self .LOCAL_FILE
273281 self .load_data ()
274282
275283 # Open a file, create data from it and send it over the data channel
276284 def load_data (self ):
277285 # We need to catch any exception type since anything can happen in
278286 # file readers
279- # pylint: disable=broad-except
280287 self .closeContext ()
281288 self .domain_editor .set_domain (None )
282289 self .apply_button .setEnabled (False )
283290 self .clear_messages ()
284291 self .set_file_list ()
285- if self .last_path () and not os .path .exists (self .last_path ()):
286- self .Error .file_not_found ()
292+
293+ error = self ._try_load ()
294+ if error :
295+ error ()
296+ self .data = None
297+ self .sheet_box .hide ()
287298 self .Outputs .data .send (None )
288299 self .info .setText ("No data." )
289- return
290300
291- error = None
301+ def _try_load (self ):
302+ # pylint: disable=broad-except
303+ if self .last_path () and not os .path .exists (self .last_path ()):
304+ return self .Error .file_not_found
305+
292306 try :
293307 self .reader = self ._get_reader ()
294- if self .reader is None :
295- self .data = None
296- self .Outputs .data .send (None )
297- self .info .setText ("No data." )
298- self .sheet_box .hide ()
299- return
300- except Exception as ex :
301- error = ex
308+ assert self .reader is not None
309+ except Exception :
310+ return self .Error .missing_reader
302311
303- if not error :
312+ try :
304313 self ._update_sheet_combo ()
305- with catch_warnings (record = True ) as warnings :
306- try :
307- data = self .reader .read ()
308- except Exception as ex :
309- log .exception (ex )
310- error = ex
311- self .warning (warnings [- 1 ].message .args [0 ] if warnings else '' )
314+ except Exception :
315+ return self .Error .sheet_error
312316
313- if error :
314- self .data = None
315- self .Outputs .data .send (None )
316- self .info .setText ("An error occurred:\n {}" .format (error ))
317- self .sheet_box .hide ()
318- return
317+ with catch_warnings (record = True ) as warnings :
318+ try :
319+ data = self .reader .read ()
320+ except Exception as ex :
321+ log .exception (ex )
322+ return lambda x = ex : self .Error .unknown (str (x ))
323+ if warnings :
324+ self .Warning .load_warning (warnings [- 1 ].message .args [0 ])
319325
320326 self .info .setText (self ._describe (data ))
321327
@@ -333,7 +339,13 @@ def _get_reader(self):
333339 FileFormat
334340 """
335341 if self .source == self .LOCAL_FILE :
336- reader = FileFormat .get_reader (self .last_path ())
342+ path = self .last_path ()
343+ if self .recent_paths and self .recent_paths [0 ].file_format :
344+ qname = self .recent_paths [0 ].file_format
345+ reader_class = class_from_qualified_name (qname )
346+ reader = reader_class (path )
347+ else :
348+ reader = FileFormat .get_reader (path )
337349 if self .recent_paths and self .recent_paths [0 ].sheet :
338350 reader .select_sheet (self .recent_paths [0 ].sheet )
339351 return reader
0 commit comments