1# Copyright (c) 2017-2021 Cedric Bellegarde <cedric.bellegarde@adishatz.org> 2# This program is free software: you can redistribute it and/or modify 3# it under the terms of the GNU General Public License as published by 4# the Free Software Foundation, either version 3 of the License, or 5# (at your option) any later version. 6# This program is distributed in the hope that it will be useful, 7# but WITHOUT ANY WARRANTY; without even the implied warranty of 8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9# GNU General Public License for more details. 10# You should have received a copy of the GNU General Public License 11# along with this program. If not, see <http://www.gnu.org/licenses/>. 12 13from gi.repository import GObject, GLib, Gio, Gtk 14 15from time import time 16 17from eolie.define import App 18from eolie.utils import emit_signal 19 20 21class DownloadManager(GObject.GObject): 22 """ 23 Downloads Manager 24 """ 25 __gsignals__ = { 26 "download-start": (GObject.SignalFlags.RUN_FIRST, None, (str,)), 27 "download-finish": (GObject.SignalFlags.RUN_FIRST, None, ()) 28 } 29 30 def __init__(self): 31 """ 32 Init download manager 33 """ 34 GObject.GObject.__init__(self) 35 self.__downloads = [] 36 self.__finished = [] 37 38 def add(self, download, filename=None): 39 """ 40 Add a download 41 @param download as WebKit2.Download 42 @param filename as str/None 43 """ 44 if download not in self.__downloads: 45 self.__downloads.append(download) 46 download.connect('finished', self.__on_finished) 47 download.connect('failed', self.__on_failed) 48 download.connect('decide-destination', 49 self.__on_decide_destination, filename) 50 51 def remove(self, download): 52 """ 53 Remove download 54 @param download as WebKit2.Download 55 """ 56 if download in self.__downloads: 57 self.__downloads.remove(download) 58 if download in self.__finished: 59 self.__finished.remove(download) 60 61 def get(self): 62 """ 63 Get running downloads 64 @return [WebKit2.Download] 65 """ 66 return self.__downloads 67 68 def get_finished(self): 69 """ 70 Get finished download 71 @return [WebKit2.Download] 72 """ 73 return self.__finished 74 75 def cancel(self): 76 """ 77 Cancel all downloads 78 """ 79 for download in self.__downloads: 80 download.cancel() 81 82 @property 83 def active(self): 84 """ 85 Is download active 86 @return bool 87 """ 88 for download in self.__downloads: 89 if download.get_estimated_progress() != 1.0: 90 return True 91 92####################### 93# PRIVATE # 94####################### 95 def __on_decide_destination(self, download, filename, wanted_filename): 96 """ 97 Modify destination if needed 98 @param download as WebKit2.Download 99 @param filename as str 100 @param wanted_filename as str 101 """ 102 filename = filename.replace("/", "_") 103 extension = filename.split(".")[-1] 104 if wanted_filename: 105 # FIXME We should find a way to pass good extension, 106 # fallback to avi 107 if extension == filename: 108 extension = "avi" 109 filename = wanted_filename + "." + extension 110 directory_uri = App().settings.get_value('download-uri').get_string() 111 if not directory_uri: 112 directory = GLib.get_user_special_dir( 113 GLib.UserDirectory.DIRECTORY_DOWNLOAD) 114 directory_uri = GLib.filename_to_uri(directory, None) 115 destination_uri = "%s/%s" % (directory_uri, 116 GLib.uri_escape_string(filename, 117 None, 118 False)) 119 not_ok = True 120 i = 1 121 try: 122 while not_ok: 123 f = Gio.File.new_for_uri(destination_uri) 124 if f.query_exists(): 125 extension_less = filename.replace(".%s" % extension, "") 126 new_filename = "%s_%s.%s" % (extension_less, i, extension) 127 destination_uri = "%s/%s" % (directory_uri, 128 GLib.uri_escape_string( 129 new_filename, 130 None, 131 False)) 132 else: 133 not_ok = False 134 i += 1 135 except: 136 # Fallback to be sure 137 destination_uri = "%s/@@%s" % (directory_uri, 138 GLib.uri_escape_string( 139 filename, 140 None, 141 False)) 142 143 webkit_uri = GLib.uri_unescape_string(destination_uri, None) 144 download.set_destination(webkit_uri) 145 emit_signal(self, "download-start", str(download)) 146 # Notify user about download 147 window = App().active_window 148 if window is not None: 149 window.toolbar.end.show_download(download) 150 151 def __on_finished(self, download): 152 """ 153 @param download as WebKit2.Download 154 """ 155 self.remove(download) 156 self.__finished.append(download) 157 emit_signal(self, "download-finish") 158 if App().settings.get_value("open-downloads"): 159 destination = download.get_destination() 160 f = Gio.File.new_for_uri(destination) 161 if f.query_exists(): 162 Gtk.show_uri(None, destination, int(time())) 163 164 def __on_failed(self, download, error): 165 """ 166 @param download as WebKit2.Download 167 @param error as GLib.Error 168 """ 169 self.remove(download) 170 self.__finished.append(download) 171