Skip to content

Commit

Permalink
finalize the FileDialogEx widget
Browse files Browse the repository at this point in the history
  • Loading branch information
sccolbert committed Jun 19, 2013
1 parent 15de3ee commit 390868c
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 42 deletions.
145 changes: 123 additions & 22 deletions enaml/qt/qt_file_dialog_ex.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,23 @@
from .qt_toolkit_dialog import QtToolkitDialog


ACCEPT_MODE = {
'open': QFileDialog.AcceptOpen,
'save': QFileDialog.AcceptSave,
}


FILE_MODE = {
'any_file': QFileDialog.AnyFile,
'existing_file': QFileDialog.ExistingFile,
'existing_files': QFileDialog.ExistingFiles,
'directory': QFileDialog.Directory,
}


# Guard flags
FILTER_GUARD = 0x1
PATH_GUARD = 0x1
FILTER_GUARD = 0x2


class QtFileDialogEx(QtToolkitDialog, ProxyFileDialogEx):
Expand All @@ -38,51 +53,137 @@ def init_widget(self):
"""
super(QtFileDialogEx, self).init_widget()
d = self.declaration
self.set_accept_mode(d.accept_mode)
self.set_file_mode(d.file_mode)
self.set_show_dirs_only(d.show_dirs_only)
self.set_current_path(d.current_path)
self.set_name_filters(d.name_filters)
self.set_selected_name_filter(d.selected_name_filter)
widget = self.widget
widget.currentChanged.connect(self.on_current_changed)
widget.filesSelected.connect(self.on_files_selected)
widget.filterSelected.connect(self.on_filter_selected)

#--------------------------------------------------------------------------
# Utility Methods
#--------------------------------------------------------------------------
def get_default_title(self):
""" Get the default window title for the file dialog.
"""
widget = self.widget
if widget.acceptMode() == QFileDialog.AcceptOpen:
if widget.fileMode() == QFileDialog.Directory:
return 'Find Directory'
return 'Open'
return 'Save As'

#--------------------------------------------------------------------------
# Signal Handlers
#--------------------------------------------------------------------------
def on_current_changed(self, path):
""" Handle the 'currentChanged' signal from the dialog.
"""
d = self.declaration
if d is not None:
self._guard |= PATH_GUARD
try:
d.current_path = path
finally:
self._guard &= ~PATH_GUARD

def on_files_selected(self, paths):
""" Handle the 'filesSelected' signal from the dialog.
"""
d = self.declaration
if d is not None:
d.selected_paths = paths

def on_filter_selected(self, selected):
""" Handle the 'filterSelected' signal from the dialog.
"""
d = self.declaration
if d is not None:
self._guard |= FILTER_GUARD
try:
d.selected_name_filter = selected
finally:
self._guard &= ~FILTER_GUARD

#--------------------------------------------------------------------------
# ProxyFileDialogEx API
#--------------------------------------------------------------------------
def set_accept_mode(self, mode):
""" Set the accept mode of the underlying widget.
"""
self.widget.setAcceptMode(ACCEPT_MODE[mode])

def set_file_mode(self, mode):
""" Set the file mode of the underlying widget.
"""
self.widget.setFileMode(FILE_MODE[mode])

def set_show_dirs_only(self, show):
""" Set the show dirs only state of the underlying widget.
"""
self.widget.setOption(QFileDialog.ShowDirsOnly, show)

def set_current_path(self, path):
pass
""" Set the current path for the underlying widget.
"""
if not self._guard & PATH_GUARD:
self.widget.selectFile(path)

def set_name_filters(self, filters):
pass
""" Set the name filters on the underlying widget.
"""
self.widget.setNameFilters(filters)

def set_selected_name_filter(self, selected):
pass
""" Set the selected name filter on the underlying widget.
"""
if not self._guard & FILTER_GUARD:
self.widget.selectNameFilter(selected)

def exec_native(self):
""" Exec a native file dialog for the declaration state.
"""
d = self.declaration
path = d.path
path = d.current_path
caption = d.title
filters = ';;'.join(d.filters)
selected_filter = d.selected_filter
if d.mode == 'open_file':
path, selected_filter = QFileDialog.getOpenFileNameAndFilter(
self.parent_widget(), caption, path, filters, selected_filter
)
filters = ';;'.join(d.name_filters)
selected_filter = d.selected_name_filter
parent = self.parent_widget()
if d.file_mode == 'directory':
path = QFileDialog.getExistingDirectory(parent, caption, path)
paths = [path] if path else []
elif d.mode == 'open_files':
paths, selected_filter = QFileDialog.getOpenFileNamesAndFilter(
self.parent_widget(), caption, path, filters, selected_filter
)
elif d.mode == 'save_file':
elif d.accept_mode == 'save':
path, selected_filter = QFileDialog.getSaveFileNameAndFilter(
self.parent_widget(), caption, path, filters, selected_filter
parent, caption, path, filters, selected_filter
)
paths = [path] if path else []
elif d.file_mode == 'existing_files':
paths, selected_filter = QFileDialog.getOpenFileNamesAndFilter(
parent, caption, path, filters, selected_filter
)
else:
path = QFileDialog.getExistingDirectory(
self.parent_widget(), caption, path
path, selected_filter = QFileDialog.getOpenFileNameAndFilter(
parent, caption, path, filters, selected_filter
)
paths = [path] if path else []
result = 'accepted' if paths else 'rejected'
d._handle_close(result, paths, selected_filter)

if paths:
self.on_current_changed(paths[0])
self.on_filter_selected(selected_filter)
self.on_files_selected(paths)
d._proxy_finished(bool(paths))
62 changes: 42 additions & 20 deletions enaml/widgets/file_dialog_ex.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#
# The full license is in the file COPYING.txt, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import Enum, List, Unicode, Typed, ForwardTyped, observe
from atom.api import Bool, Enum, List, Unicode, Typed, ForwardTyped, observe

from enaml.core.declarative import d_

Expand All @@ -19,6 +19,15 @@ class ProxyFileDialogEx(ProxyToolkitDialog):
#: A reference to the FileDialog declaration.
declaration = ForwardTyped(lambda: FileDialogEx)

def set_accept_mode(self, accept_mode):
raise NotImplementedError

def set_file_mode(self, file_mode):
raise NotImplementedError

def set_show_dirs_only(self, show):
raise NotImplementedError

def set_current_path(self, path):
raise NotImplementedError

Expand All @@ -39,10 +48,18 @@ class FileDialogEx(ToolkitDialog):
use this dialog in lieu of the older version.
"""
#: The mode of the dialog. This must be set before opening.
mode = d_(Enum('open_file', 'open_files', 'save_file', 'directory'))
#: The accept mode of the dialog.
accept_mode = d_(Enum('open', 'save'))

#: The file mode of the dialog.
file_mode = d_(Enum(
'any_file', 'existing_file', 'existing_files', 'directory'))

#: Whether or not to only show directories. This is only valid when
#: the file_mode is set to 'directory'.
show_dirs_only = d_(Bool(False))

#: The current path in the dialog.
#: The currently selected path in the dialog.
current_path = d_(Unicode())

#: The paths selected by the user when the dialog is accepted.
Expand Down Expand Up @@ -77,11 +94,13 @@ def get_existing_directory(parent=None, **kwargs):
string if no directory was selected.
"""
kwargs['mode'] = 'directory'
kwargs['accept_mode'] = 'open'
kwargs['file_mode'] = 'directory'
kwargs['show_dirs_only'] = True
dialog = FileDialogEx(parent, **kwargs)
dialog.exec_native()
if dialog.result and dialog.selected_paths:
return dialog.selected_paths[0]
if dialog.exec_native():
if dialog.selected_paths:
return dialog.selected_paths[0]
return u''

@staticmethod
Expand All @@ -103,11 +122,12 @@ def get_open_file_name(parent=None, **kwargs):
string if no file name was selected.
"""
kwargs['mode'] = 'open_file'
kwargs['accept_mode'] = 'open'
kwargs['file_mode'] = 'existing_file'
dialog = FileDialogEx(parent, **kwargs)
dialog.exec_native()
if dialog.result and dialog.selected_paths:
return dialog.selected_paths[0]
if dialog.exec_native():
if dialog.selected_paths:
return dialog.selected_paths[0]
return u''

@staticmethod
Expand All @@ -129,10 +149,10 @@ def get_open_file_names(parent=None, **kwargs):
list if no file names were selected.
"""
kwargs['mode'] = 'open_files'
kwargs['accept_mode'] = 'open'
kwargs['file_mode'] = 'existing_files'
dialog = FileDialogEx(parent, **kwargs)
dialog.exec_native()
if dialog.result:
if dialog.exec_native():
return dialog.selected_paths
return []

Expand All @@ -155,11 +175,12 @@ def get_save_file_name(parent=None, **kwargs):
string if no file name was selected.
"""
kwargs['mode'] = 'save_file'
kwargs['accept_mode'] = 'save'
kwargs['file_mode'] = 'any_file'
dialog = FileDialogEx(parent, **kwargs)
dialog.exec_native()
if dialog.result and dialog.selected_paths:
return dialog.selected_paths[0]
if dialog.exec_native():
if dialog.selected_paths:
return dialog.selected_paths[0]
return u''

def exec_native(self):
Expand All @@ -182,7 +203,8 @@ def exec_native(self):
#--------------------------------------------------------------------------
# Observers
#--------------------------------------------------------------------------
@observe(('mode', 'current_path', 'name_filters', 'selected_name_filter'))
@observe(('accept_mode', 'file_mode', 'show_dirs_only', 'current_path',
'name_filters', 'selected_name_filter'))
def _update_proxy(self, change):
""" An observer which updates the proxy when the data changes.
Expand Down

0 comments on commit 390868c

Please sign in to comment.