### BEGIN LICENSE
# Copyright (C) 2010 Stuart Langridge stuart.langridge@canonical.com
# Copyright (C) 2012 Rick Spencer rick.spencer@canonical.com
#This program is free software: you can redistribute it and/or modify it 
#under the terms of the GNU General Public License version 3, as published 
#by the Free Software Foundation.
#
#This program is distributed in the hope that it will be useful, but 
#WITHOUT ANY WARRANTY; without even the implied warranties of 
#MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
#PURPOSE.  See the GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License along 
#with this program.  If not, see <http://www.gnu.org/licenses/>.
### END LICENSE

try:
    from gi.repository import GObject
    from gi.repository import Gtk
    from gi.repository import Gio
    from gi.repository import GLib
    import gettext
    from gettext import gettext as _
    gettext.textdomain('quickly-widgets')
except:
    print "couldn't load dependencies"


class UrlFetchProgressBox(Gtk.HBox):
    """UrlFetchProgressBox: encapsulates a pulsating progressbar, a cancel
    button, and a URL that needs fetching. Use a UrlFetchProgressBox when you 
    need to fetch a URL; the box will show while the URL is being fetched 
    without blocking the UI for the user.
    By default, the box will automatically destroy itself once the URL is
    fetched; suppress this by passing destroy_after_fetching=False.
    Fires a "downloaded" signal once download is complete, passing the contents
    of the URL.
    Cancelling fires the "downloaded" signal with a value of None.
    """

    __gsignals__ = {'downloaded' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, 
            (GObject.TYPE_PYOBJECT,)),
        'download-error' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, 
            (GObject.TYPE_PYOBJECT,))}

    def __init__(self, url, destroy_after_fetching=True, cancelable=True):
        """Create an UrlFetchProgressBox

        Keyword arguments:
        url -- the URL to fetch
        destroy_after_fetching -- should this widget destroy itself once the URL
          is fetched? Defaults to True.
        cancelable -- whether to show cancel button. Defaults to True.
        """
        Gtk.HBox.__init__( self, False, 2)
        self.progressbar = Gtk.ProgressBar()
        GObject.timeout_add(10, self.__tick)
        self.running = True
        parts = [x for x in url.split("/") if x]
        self.progressbar.set_text(_("Downloading %s") % parts[-1])
        self.progressbar.show()
        self.pack_start(self.progressbar, True, True, 0)
        self.destroy_after_fetching = destroy_after_fetching
        self.cancel_button = Gtk.Button(stock=Gtk.STOCK_CANCEL)
        if cancelable:
            self.cancel_button.show()
        self.cancel_button.set_sensitive(False)
        self.cancel_button.connect("clicked",self.__cancel)
        self.pack_end(self.cancel_button, False, False, 0)
        self.cancel_button.set_sensitive(True)
        self.__canceller = Gio.Cancellable()
        self.stream = Gio.file_new_for_uri(url)
        self.stream.load_contents_async(self.__canceller, self.__download_finished, None)
    

    def __tick(self):
        self.progressbar.pulse()
        return self.running
    
    def __download_finished(self, gdaemonfile, result, data=None):
        try:
            #GIO documentation says that the file is [0] in the tuple
            #but it is realy [1]
            content = self.stream.load_contents_finish(result)[1]
        except Exception, e:
            self.emit("download-error",e)
        else:
            self.emit("downloaded", content)
        self.__maybe_destroy()
    
    def __cancel(self, btn):
        self.__canceller.cancel()
        self.__maybe_destroy()
    
    def __maybe_destroy(self):
        self.running = False
        if self.destroy_after_fetching: self.destroy()

class TestWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_title("UrlFetchProgressBox test")
        self.vbox = Gtk.VBox()
        btn = Gtk.Button(stock=Gtk.STOCK_EXECUTE)
        btn.connect("clicked", self.start_download)
        self.vbox.pack_end(btn, True, True, 0)
        self.add(self.vbox)
        self.set_size_request(300,200)
        self.connect("destroy", Gtk.main_quit)
    
    def start_download(self, btn):
        prog = UrlFetchProgressBox("http://www.ubuntu.com/desktop/get-ubuntu/download")
        
        prog.connect("downloaded", self.downloaded)
        prog.connect("download-error", self.errored)
        self.vbox.pack_start(prog, False, False, 0)
        prog.show()

    def errored(self, widget, e):
        print "encountered error: %s " % e.message

    def downloaded(self, widget, content):
        print "downloaded %s bytes of content" % len(content)

if __name__ == "__main__":
    w = TestWindow()
    w.show_all()
    Gtk.main()

