Allow directories to be entered as destination

The filename will then default to 'page title.mht'
This commit is contained in:
Daniel 2015-10-19 20:08:37 +02:00
parent ae8a9b8798
commit a780325a3a
2 changed files with 63 additions and 41 deletions

View File

@ -49,7 +49,7 @@ ModelRole = usertypes.enum('ModelRole', ['item'], start=Qt.UserRole,
RetryInfo = collections.namedtuple('RetryInfo', ['request', 'manager'])
# Remember the last used directory
_last_used_directory = None
last_used_directory = None
# All REFRESH_INTERVAL milliseconds, speeds will be recalculated and downloads
@ -57,13 +57,13 @@ _last_used_directory = None
REFRESH_INTERVAL = 500
def _download_dir():
def download_dir():
"""Get the download directory to use."""
directory = config.get('storage', 'download-directory')
remember_dir = config.get('storage', 'remember-download-directory')
if remember_dir and _last_used_directory is not None:
return _last_used_directory
if remember_dir and last_used_directory is not None:
return last_used_directory
elif directory is None:
return standarddir.download()
else:
@ -79,15 +79,36 @@ def path_suggestion(filename):
suggestion = config.get('completion', 'download-path-suggestion')
if suggestion == 'path':
# add trailing '/' if not present
return os.path.join(_download_dir(), '')
return os.path.join(download_dir(), '')
elif suggestion == 'filename':
return filename
elif suggestion == 'both':
return os.path.join(_download_dir(), filename)
return os.path.join(download_dir(), filename)
else:
raise ValueError("Invalid suggestion value {}!".format(suggestion))
def create_full_filename(basename, filename):
"""Create a full filename based on the given basename and filename.
Args:
basename: The basename to use if filename is a directory.
filename: The path to a folder or file where you want to save.
Return:
The full absolute path, or None if filename creation was not possible.
"""
if os.path.isabs(filename) and os.path.isdir(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)
elif os.path.isabs(filename):
# We got an absolute filename from the user, so we save it under
# that filename.
return filename
return None
class DownloadItemStats(QObject):
"""Statistics (bytes done, total bytes, time, etc.) about a download.
@ -447,7 +468,7 @@ class DownloadItem(QObject):
filename: The full filename to save the download to.
None: special value to stop the download.
"""
global _last_used_directory
global last_used_directory
if self.fileobj is not None:
raise ValueError("fileobj was already set! filename: {}, "
"existing: {}, fileobj {}".format(
@ -457,13 +478,16 @@ class DownloadItem(QObject):
# See https://github.com/The-Compiler/qutebrowser/issues/427
encoding = sys.getfilesystemencoding()
filename = utils.force_encoding(filename, encoding)
if not self._create_full_filename(filename):
self._filename = create_full_filename(self.basename, filename)
if self._filename is None:
# We only got a filename (without directory) or a relative path
# from the user, so we append that to the default directory and
# try again.
self._create_full_filename(os.path.join(_download_dir(), filename))
self._filename = create_full_filename(
self.basename, os.path.join(download_dir(), filename))
_last_used_directory = os.path.dirname(self._filename)
self.basename = os.path.basename(self._filename)
last_used_directory = os.path.dirname(self._filename)
log.downloads.debug("Setting filename to {}".format(filename))
if os.path.isfile(self._filename):
@ -480,25 +504,6 @@ class DownloadItem(QObject):
else:
self._create_fileobj()
def _create_full_filename(self, filename):
"""Try to create the full filename.
Return:
True if the full filename was created, False otherwise.
"""
if os.path.isabs(filename) and os.path.isdir(filename):
# We got an absolute directory from the user, so we save it under
# the default filename in that directory.
self._filename = os.path.join(filename, self.basename)
return True
elif os.path.isabs(filename):
# We got an absolute filename from the user, so we save it under
# that filename.
self._filename = filename
self.basename = os.path.basename(self._filename)
return True
return False
def set_fileobj(self, fileobj):
""""Set the file object to write the download to.

View File

@ -23,6 +23,7 @@ import functools
import io
import os
import re
import sys
import collections
import uuid
import email.policy
@ -32,7 +33,7 @@ import email.mime.multipart
from PyQt5.QtCore import QUrl
from qutebrowser.browser import webelem
from qutebrowser.browser import webelem, downloads
from qutebrowser.utils import log, objreg, message, usertypes, utils, urlutils
try:
@ -373,7 +374,7 @@ class _Downloader():
log.downloads.debug("Oops! Download already gone: %s", item)
return
item.fileobj.actual_close()
self.writer.add_file(ulrutils.encoded_url(url), b'')
self.writer.add_file(urlutils.encoded_url(url), b'')
if self.pending_downloads:
return
self.finish_file()
@ -428,12 +429,11 @@ def _start_download(dest, win_id, tab_id):
dest: The filename where the resulting file should be saved.
win_id, tab_id: Specify the tab whose page should be loaded.
"""
dest = os.path.expanduser(dest)
web_view = objreg.get('webview', scope='tab', window=win_id, tab=tab_id)
loader = _Downloader(web_view, dest)
loader.run()
def start_download_checked(dest, win_id, tab_id):
"""First check if dest is already a file, then start the download.
@ -441,20 +441,37 @@ def start_download_checked(dest, win_id, tab_id):
dest: The filename where the resulting file should be saved.
win_id, tab_id: Specify the tab whose page should be loaded.
"""
# start_download will call os.path.expanduser on dest too, so no need to
# overwrite dest. We just want to make sure that we're checking
# the right path here. This also means that the user question will show the
# original path, not the expanded.
if not os.path.isfile(os.path.expanduser(dest)):
_start_download(dest, win_id=win_id, tab_id=tab_id)
# The default name is 'page title.mht'
title = (objreg.get('webview', scope='tab', window=win_id, tab=tab_id)
.title())
default_name = title + '.mht'
# Remove characters which cannot be expressed in the file system encoding
encoding = sys.getfilesystemencoding()
default_name = utils.force_encoding(default_name, encoding)
dest = utils.force_encoding(dest, encoding)
dest = os.path.expanduser(dest)
# See if we already have an absolute path
path = downloads.create_full_filename(default_name, dest)
if path is None:
# We still only have a relative path, prepend download_dir and
# try again.
path = downloads.create_full_filename(
default_name, os.path.join(downloads.download_dir(), dest))
downloads.last_used_directory = os.path.dirname(path)
if not os.path.isfile(path):
_start_download(path, win_id=win_id, tab_id=tab_id)
return
q = usertypes.Question()
q.mode = usertypes.PromptMode.yesno
q.text = "{} exists. Overwrite?".format(dest)
q.text = "{} exists. Overwrite?".format(path)
q.completed.connect(q.deleteLater)
q.answered_yes.connect(functools.partial(
_start_download, dest, win_id=win_id, tab_id=tab_id))
_start_download, path, win_id=win_id, tab_id=tab_id))
message_bridge = objreg.get('message-bridge', scope='window',
window=win_id)
message_bridge.ask(q, blocking=False)