Prompt for non-existing download directories.

Closes #2120
This commit is contained in:
Panagiotis K 2017-10-11 13:40:53 +03:00
parent abbd69f604
commit 0a753915ff
4 changed files with 67 additions and 4 deletions

View File

@ -27,6 +27,7 @@ import collections
import functools
import pathlib
import tempfile
import errno
import sip
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QObject, QModelIndex,
@ -137,7 +138,8 @@ def create_full_filename(basename, filename):
encoding = sys.getfilesystemencoding()
filename = utils.force_encoding(filename, encoding)
basename = utils.force_encoding(basename, encoding)
if os.path.isabs(filename) and os.path.isdir(filename):
if os.path.isabs(filename) and (os.path.isdir(filename) or
os.path.join(filename, "") == filename):
# We got an absolute directory from the user, so we save it under
# the default filename in that directory.
return os.path.join(filename, basename)
@ -657,11 +659,42 @@ class AbstractDownloadItem(QObject):
self._filename = create_full_filename(self.basename,
os.path.expanduser('~'))
dirname = os.path.dirname(self._filename)
if not os.path.exists(dirname):
txt = ("<b>{}</b> does not exist. Create it?".
format(html.escape(
os.path.join(dirname, ""))))
self._ask_create_parent_question("Create directory?", txt,
force_overwrite,
remember_directory)
else:
self._after_create_parent_question(force_overwrite,
remember_directory)
def _after_create_parent_question(self,
force_overwrite, remember_directory):
"""After asking about parent directory.
Args:
force_overwrite: Force overwriting existing files.
remember_directory: If True, remember the directory for future
downloads.
"""
global last_used_directory
try:
os.makedirs(os.path.dirname(self._filename))
except OSError as e:
# Unlikely, but could be created before
# we get a chance to create it.
if e.errno != errno.EEXIST:
raise
self.basename = os.path.basename(self._filename)
if remember_directory:
last_used_directory = os.path.dirname(self._filename)
log.downloads.debug("Setting filename to {}".format(filename))
log.downloads.debug("Setting filename to {}".format(self._filename))
if force_overwrite:
self._after_set_filename()
elif os.path.isfile(self._filename):

View File

@ -203,6 +203,17 @@ class DownloadItem(downloads.AbstractDownloadItem):
no_action=no_action, cancel_action=no_action,
abort_on=[self.cancelled, self.error])
def _ask_create_parent_question(self, title, msg,
force_overwrite, remember_directory):
no_action = functools.partial(self.cancel, remove_data=False)
message.confirm_async(title=title, text=msg,
yes_action=(lambda:
self._after_create_parent_question(
force_overwrite,
remember_directory)),
no_action=no_action, cancel_action=no_action,
abort_on=[self.cancelled, self.error])
def _set_fileobj(self, fileobj, *, autoclose=True):
""""Set the file object to write the download to.

View File

@ -120,6 +120,22 @@ class DownloadItem(downloads.AbstractDownloadItem):
"state {} (not in requested state)!".format(
filename, self, state_name))
def _ask_create_parent_question(self, title, msg,
force_overwrite, remember_directory):
no_action = functools.partial(self.cancel, remove_data=False)
question = usertypes.Question()
question.title = title
question.text = msg
question.mode = usertypes.PromptMode.yesno
question.answered_yes.connect(lambda:
self._after_create_parent_question(
force_overwrite, remember_directory))
question.answered_no.connect(no_action)
question.cancelled.connect(no_action)
self.cancelled.connect(question.abort)
self.error.connect(question.abort)
message.global_bridge.ask(question, blocking=True)
def _ask_confirm_question(self, title, msg):
no_action = functools.partial(self.cancel, remove_data=False)
question = usertypes.Question()

View File

@ -256,8 +256,11 @@ Feature: Downloading things from a website.
Then the error "Can only download the current page as mhtml." should be shown
Scenario: :download with a directory which doesn't exist
When I run :download --dest (tmpdir)/downloads/somedir/filename http://localhost:(port)/
Then the error "Download error: No such file or directory" should be shown
When I run :download --dest (tmpdir)/downloads/somedir/filename http://localhost:(port)/data/downloads/download.bin
And I wait for "Asking question <qutebrowser.utils.usertypes.Question default=None mode=<PromptMode.yesno: 1> text='<b>*</b> does not exist. Create it?' title='Create directory?'>, *" in the log
And I run :prompt-accept yes
And I wait until the download filename is finished
Then the downloaded file filename should not exist
## mhtml downloads