Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make win filechooser use modern windows browser and fix small issues. #535

Merged
merged 1 commit into from
Jan 23, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 35 additions & 22 deletions plyer/platforms/win/filechooser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
from plyer.facades import FileChooser
from win32com.shell.shell import (
SHBrowseForFolder as browse,
SHGetPathFromIDList as get_path
SHGetPathFromIDList as get_path, SHILCreateFromPath
)
from win32com.shell import shellcon
import win32gui
import win32con
import pywintypes
from os.path import dirname, splitext, join
import pathlib
from os.path import dirname, splitext, join, isdir


class Win32FileChooser(object):
Expand Down Expand Up @@ -64,10 +66,13 @@ def run(self):
args = {}

if self.path:
args["InitialDir"] = dirname(self.path)
_, ext = splitext(self.path)
args["File"] = self.path
args["DefExt"] = ext
if isdir(self.path):
args["InitialDir"] = self.path
else:
args["InitialDir"] = dirname(self.path)
_, ext = splitext(self.path)
args["File"] = self.path
args["DefExt"] = ext and ext[1:] # no period

args["Title"] = self.title if self.title else "Pick a file..."
args["CustomFilter"] = 'Other file types\x00*.*\x00'
Expand All @@ -82,8 +87,8 @@ def run(self):
filters += f[0] + "\x00" + ";".join(f[1:]) + "\x00"
args["Filter"] = filters

flags = win32con.OFN_EXTENSIONDIFFERENT
flags |= win32con.OFN_OVERWRITEPROMPT
flags = win32con.OFN_OVERWRITEPROMPT
flags |= win32con.OFN_HIDEREADONLY

if self.multiple:
flags |= win32con.OFN_ALLOWMULTISELECT
Expand All @@ -93,40 +98,48 @@ def run(self):

args["Flags"] = flags

# GetOpenFileNameW, GetSaveFileNameW will raise
# pywintypes.error: (0, '...', 'No error message is available')
# which is most likely due to incorrect type handling from the
# win32gui side; return empty list in that case after exception
if self.mode == "open":
self.fname, _, _ = win32gui.GetOpenFileNameW(**args)
elif self.mode == "save":
self.fname, _, _ = win32gui.GetSaveFileNameW(**args)
try:
if self.mode == "open":
self.fname, _, _ = win32gui.GetOpenFileNameW(**args)
elif self.mode == "save":
self.fname, _, _ = win32gui.GetSaveFileNameW(**args)
except pywintypes.error as e:
# if canceled, it's not really an error
if not e.winerror:
self._handle_selection(self.selection)
return self.selection
raise

if self.fname:
if self.multiple:
seq = str(self.fname).split("\x00")
dir_n, base_n = seq[0], seq[1:]
self.selection = [
join(dir_n, i) for i in base_n
]
if len(seq) > 1:
dir_n, base_n = seq[0], seq[1:]
self.selection = [
join(dir_n, i) for i in base_n
]
else:
self.selection = seq
else:
self.selection = str(self.fname).split("\x00")

else: # dir mode
BIF_EDITBOX = shellcon.BIF_EDITBOX
BIF_NEWDIALOGSTYLE = 0x00000040
# From http://goo.gl/UDqCqo
pidl, name, images = browse( # pylint: disable=unused-variable
win32gui.GetDesktopWindow(),
None,
self.title if self.title else "Pick a folder...",
0, None, None
BIF_NEWDIALOGSTYLE | BIF_EDITBOX, None, None
)

# pidl is None when nothing is selected
# and e.g. the dialog is closed afterwards with Cancel
if pidl:
self.selection = [str(get_path(pidl).decode('utf-8'))]

except (RuntimeError, pywintypes.error):
except (RuntimeError, pywintypes.error, Exception):
# ALWAYS! let user know what happened
import traceback
traceback.print_exc()
Expand Down