<commit_before>/*
   Copyright (C) 2009-2013 <NAME> <<EMAIL>>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   See the file COPYING for the full license text.
*/

namespace Gtk {
    extern static void widget_size_request (Gtk.Widget widget, out Gtk.Requisition requisition);
}

namespace Sokoke {
    extern static void widget_get_text_size (Gtk.Widget widget, string sample, out int width, out int height);
}

namespace Transfers {
    private class Transfer : GLib.Object {
        internal WebKit.Download download;

        internal signal void changed ();
        internal signal void remove ();
        internal signal void removed ();

        internal int action { get {
            return Midori.Download.get_type (download);
        } }
        internal double progress { get {
            return Midori.Download.get_progress (download);
        } }
#if HAVE_WEBKIT2
        public bool succeeded { get; protected set; default = false; }
        public bool finished { get; protected set; default = false; }
        internal string destination { get {
            return download.destination;
        } }
#else
        internal bool succeeded { get {
            return download.status == WebKit.DownloadStatus.FINISHED;
        } }
        internal bool finished { get {
            return Midori.Download.is_finished (download);
        } }
        internal string destination { get {
            return download.destination_uri;
        } }
#endif

        internal Transfer (WebKit.Download download) {
            this.download = download;
            #if HAVE_WEBKIT2
            download.notify["estimated-progress"].connect (transfer_changed);
            download.finished.connect (() => {
                succeeded = finished = true;
                changed ();
            });
            download.failed.connect (() => {
                succeeded = false;
                finished = true;
                changed ();
            });
            #else
            download.notify["status"].connect (transfer_changed);
            download.notify["progress"].connect (transfer_changed);
            #endif
        }

        void transfer_changed (GLib.ParamSpec pspec) {
            changed ();
        }
    }

    static bool pending_transfers (Katze.Array array) {
        foreach (GLib.Object item in array.get_items ()) {
            var transfer = item as Transfer;
            if (!transfer.finished)
                return true;
        }
        return false;
    }

    private class Sidebar : Gtk.VBox, Midori.Viewable {
        Gtk.Toolbar? toolbar = null;
        Gtk.ToolButton clear;
        Gtk.ListStore store = new Gtk.ListStore (1, typeof (Transfer));
        Gtk.TreeView treeview;
        Katze.Array array;

        public unowned string get_stock_id () {
            return Midori.Stock.TRANSFER;
        }

        public unowned string get_label () {
            return _("Transfers");
        }

        public Gtk.Widget get_toolbar () {
            if (toolbar == null) {
                toolbar = new Gtk.Toolbar ();
                toolbar.set_icon_size (Gtk.IconSize.BUTTON);
                toolbar.insert (new Gtk.ToolItem (), -1);
                var separator = new Gtk.SeparatorToolItem ();
                separator.draw = false;
                separator.set_expand (true);
                toolbar.insert (separator, -1);
                clear = new Gtk.ToolButton.from_stock (Gtk.STOCK_CLEAR);
                clear.label = _("Clear All");
                clear.is_important = true;
                clear.clicked.connect (clear_clicked);
                clear.sensitive = !array.is_empty ();
                toolbar.insert (clear, -1);
                toolbar.show_all ();
            }
            return toolbar;
        }

        void clear_clicked () {
            foreach (GLib.Object item in array.get_items ()) {
                var transfer = item as Transfer;
                if (transfer.finished)
                    transfer.remove ();
            }
        }

        public Sidebar (Katze.Array array) {
            Gtk.TreeViewColumn column;

            treeview = new Gtk.TreeView.with_model (store);
            treeview.headers_visible = false;

            store.set_sort_column_id (0, Gtk.SortType.ASCENDING);
            store.set_sort_func (0, tree_sort_func);

            column = new Gtk.TreeViewColumn ();
            Gtk.CellRendererPixbuf renderer_icon = new Gtk.CellRendererPixbuf ();
            column.pack_start (renderer_icon, false);
            column.set_cell_data_func (renderer_icon, on_render_icon);
            treeview.append_column (column);

            column = new Gtk.TreeViewColumn ();
            column.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE);
            Gtk.CellRendererProgress renderer_progress = new Gtk.CellRendererProgress ();
            column.pack_start (renderer_progress, true);
            column.set_expand (true);
            column.set_cell_data_func (renderer_progress, on_render_text);
            treeview.append_column (column);

            column = new Gtk.TreeViewColumn ();
            Gtk.CellRendererPixbuf renderer_button = new Gtk.CellRendererPixbuf ();
            column.pack_start (renderer_button, false);
            column.set_cell_data_func (renderer_button, on_render_button);
            treeview.append_column (column);

            treeview.row_activated.connect (row_activated);
            treeview.button_release_event.connect (button_released);
            treeview.popup_menu.connect (menu_popup);
            treeview.show ();
            pack_start (treeview, true, true, 0);

            this.array = array;
            array.add_item.connect (transfer_added);
            array.remove_item.connect_after (transfer_removed);
            foreach (GLib.Object item in array.get_items ())
                transfer_added (item);
        }

        void row_activated (Gtk.TreePath path, Gtk.TreeViewColumn column) {
            Gtk.TreeIter iter;
            if (store.get_iter (out iter, path)) {
                Transfer transfer;
                store.get (iter, 0, out transfer);

                try {
                    if (Midori.Download.action_clear (transfer.download, treeview))
                        transfer.remove ();
                } catch (Error error) {
                    // Failure to open is the only known possibility here
                    GLib.warning (_("Failed to open download: %s"), error.message);
                }
            }
        }

        bool button_released (Gdk.EventButton event) {
            if (event.button == 3)
                return show_popup_menu (event);
            return false;
        }

        bool menu_popup () {
            return show_popup_menu (null);
        }

        bool show_popup_menu (Gdk.EventButton? event) {
            Gtk.TreeIter iter;
            if (treeview.get_selection ().get_selected (null, out iter)) {
                Transfer transfer;
                store.get (iter, 0, out transfer);

                var menu = new Gtk.Menu ();
                var menuitem = new Gtk.ImageMenuItem.from_stock (Gtk.STOCK_OPEN, null);
                menuitem.activate.connect (() => {
                    try {
                        Midori.Download.open (transfer.download, treeview);
                    } catch (Error error_open) {
                        GLib.warning (_("Failed to open download: %s"), error_open.message);
                    }
                });
                menuitem.sensitive = transfer.succeeded;
                menu.append (menuitem);
                menuitem = new Gtk.ImageMenuItem.with_mnemonic (_("Open Destination _Folder"));
                menuitem.image = new Gtk.Image.from_stock (Gtk.STOCK_DIRECTORY, Gtk.IconSize.MENU);
                menuitem.activate.connect (() => {
                    var folder = GLib.File.new_for_uri (transfer.destination);
                    (Midori.Browser.get_for_widget (this).tab as Midori.Tab).open_uri (folder.get_parent ().get_uri ());
                });
                menu.append (menuitem);
                menuitem = new Gtk.ImageMenuItem.with_mnemonic (_("Copy Link Loc_ation"));
                menuitem.activate.connect (() => {
                    string uri = transfer.destination;
                    get_clipboard (Gdk.SELECTION_PRIMARY).set_text (uri, -1);
                    get_clipboard (Gdk.SELECTION_CLIPBOARD).set_text (uri, -1);
                });
                menuitem.image = new Gtk.Image.from_stock (Gtk.STOCK_COPY, Gtk.IconSize.MENU);
                menu.append (menuitem);
                menu.show_all ();
                Katze.widget_popup (treeview, menu, null, Katze.MenuPos.CURSOR);

                return true;
            }
            return false;
        }

        int tree_sort_func (Gtk.TreeModel model, Gtk.TreeIter a, Gtk.TreeIter b) {
            Transfer transfer1, transfer2;
            model.get (a, 0, out transfer1);
            model.get (b, 0, out transfer2);
            return (transfer1.finished ? 1 : 0) - (transfer2.finished ? 1 : 0);
        }

        void transfer_changed () {
            treeview.queue_draw ();
        }

        void transfer_added (GLib.Object item) {
            var transfer = item as Transfer;
            Gtk.TreeIter iter;
            store.append (out iter);
            store.set (iter, 0, transfer);
            transfer.changed.connect (transfer_changed);
            clear.sensitive = true;
        }

        void transfer_removed (GLib.Object item) {
            var transfer = item as Transfer;
            transfer.changed.disconnect (transfer_changed);
            Gtk.TreeIter iter;
            if (store.iter_children (out iter, null)) {
                do {
                    Transfer found;
                    store.get (iter, 0, out found);
                    if (transfer == found) {
                        store.remove (iter);
                        break;
                    }
                } while (store.iter_next (ref iter));
            }
            if (array.is_empty ())
                clear.sensitive = false;
        }

        void on_render_icon (Gtk.CellLayout column, Gtk.CellRenderer renderer,
            Gtk.TreeModel model, Gtk.TreeIter iter) {

            Transfer transfer;
            model.get (iter, 0, out transfer);
            string content_type = Midori.Download.get_content_type (transfer.download, null);
            var icon = GLib.ContentType.get_icon (content_type) as ThemedIcon;
            icon.append_name ("text-html");
            renderer.set ("gicon", icon,
                          "stock-size", Gtk.IconSize.DND,
                          "xpad", 1, "ypad", 12);
        }

        void on_render_text (Gtk.CellLayout column, Gtk.CellRenderer renderer,
            Gtk.TreeModel model, Gtk.TreeIter iter) {

            Transfer transfer;
            model.get (iter, 0, out transfer);
            string tooltip = Midori.Download.get_tooltip (transfer.download);<commit_msg>Fix rendering logic for transfers sidebar<commit_after>/*
   Copyright (C) 2009-2013 <NAME> <<EMAIL>>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   See the file COPYING for the full license text.
*/

namespace Gtk {
    extern static void widget_size_request (Gtk.Widget widget, out Gtk.Requisition requisition);
}

namespace Sokoke {
    extern static void widget_get_text_size (Gtk.Widget widget, string sample, out int width, out int height);
}

namespace Transfers {
    private class Transfer : GLib.Object {
        internal WebKit.Download download;

        internal signal void changed ();
        internal signal void remove ();
        internal signal void removed ();

        internal int action { get {
            return Midori.Download.get_type (download);
        } }
        internal double progress { get {
            return Midori.Download.get_progress (download);
        } }
#if HAVE_WEBKIT2
        public bool succeeded { get; protected set; default = false; }
        public bool finished { get; protected set; default = false; }
        internal string destination { get {
            return download.destination;
        } }
#else
        internal bool succeeded { get {
            return download.status == WebKit.DownloadStatus.FINISHED;
        } }
        internal bool finished { get {
            return Midori.Download.is_finished (download);
        } }
        internal string destination { get {
            return download.destination_uri;
        } }
#endif

        internal Transfer (WebKit.Download download) {
            this.download = download;
            #if HAVE_WEBKIT2
            download.notify["estimated-progress"].connect (transfer_changed);
            download.finished.connect (() => {
                succeeded = finished = true;
                changed ();
            });
            download.failed.connect (() => {
                succeeded = false;
                finished = true;
                changed ();
            });
            #else
            download.notify["status"].connect (transfer_changed);
            download.notify["progress"].connect (transfer_changed);
            #endif
        }

        void transfer_changed (GLib.ParamSpec pspec) {
            changed ();
        }
    }

    static bool pending_transfers (Katze.Array array) {
        foreach (GLib.Object item in array.get_items ()) {
            var transfer = item as Transfer;
            if (!transfer.finished)
                return true;
        }
        return false;
    }

    private class Sidebar : Gtk.VBox, Midori.Viewable {
        Gtk.Toolbar? toolbar = null;
        Gtk.ToolButton clear;
        Gtk.ListStore store = new Gtk.ListStore (2, typeof (Transfer), typeof (string));
        Gtk.TreeView treeview;
        Katze.Array array;

        public unowned string get_stock_id () {
            return Midori.Stock.TRANSFER;
        }

        public unowned string get_label () {
            return _("Transfers");
        }

        public Gtk.Widget get_toolbar () {
            if (toolbar == null) {
                toolbar = new Gtk.Toolbar ();
                toolbar.set_icon_size (Gtk.IconSize.BUTTON);
                toolbar.insert (new Gtk.ToolItem (), -1);
                var separator = new Gtk.SeparatorToolItem ();
                separator.draw = false;
                separator.set_expand (true);
                toolbar.insert (separator, -1);
                clear = new Gtk.ToolButton.from_stock (Gtk.STOCK_CLEAR);
                clear.label = _("Clear All");
                clear.is_important = true;
                clear.clicked.connect (clear_clicked);
                clear.sensitive = !array.is_empty ();
                toolbar.insert (clear, -1);
                toolbar.show_all ();
            }
            return toolbar;
        }

        void clear_clicked () {
            foreach (GLib.Object item in array.get_items ()) {
                var transfer = item as Transfer;
                if (transfer.finished)
                    transfer.remove ();
            }
        }

        public Sidebar (Katze.Array array) {
            Gtk.TreeViewColumn column;

            treeview = new Gtk.TreeView.with_model (store);
            treeview.headers_visible = false;

            store.set_sort_column_id (0, Gtk.SortType.ASCENDING);
            store.set_sort_func (0, tree_sort_func);

            column = new Gtk.TreeViewColumn ();
            Gtk.CellRendererPixbuf renderer_icon = new Gtk.CellRendererPixbuf ();
            column.pack_start (renderer_icon, false);
            column.set_cell_data_func (renderer_icon, on_render_icon);
            treeview.append_column (column);

            column = new Gtk.TreeViewColumn ();
            column.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE);
            Gtk.CellRendererProgress renderer_progress = new Gtk.CellRendererProgress ();
            column.pack_start (renderer_progress, true);
            column.set_expand (true);
            column.set_cell_data_func (renderer_progress, on_render_text);
            treeview.append_column (column);

            column = new Gtk.TreeViewColumn ();
            Gtk.CellRendererPixbuf renderer_button = new Gtk.CellRendererPixbuf ();
            column.pack_start (renderer_button, false);
            column.set_cell_data_func (renderer_button, on_render_button);
            treeview.append_column (column);

            treeview.row_activated.connect (row_activated);
            treeview.button_release_event.connect (button_released);
            treeview.popup_menu.connect (menu_popup);
            treeview.show ();
            pack_start (treeview, true, true, 0);

            this.array = array;
            array.add_item.connect (transfer_added);
            array.remove_item.connect_after (transfer_removed);
            foreach (GLib.Object item in array.get_items ())
                transfer_added (item);
        }

        void row_activated (Gtk.TreePath path, Gtk.TreeViewColumn column) {
            Gtk.TreeIter iter;
            if (store.get_iter (out iter, path)) {
                Transfer transfer;
                store.get (iter, 0, out transfer);

                try {
                    if (Midori.Download.action_clear (transfer.download, treeview))
                        transfer.remove ();
                } catch (Error error) {
                    // Failure to open is the only known possibility here
                    GLib.warning (_("Failed to open download: %s"), error.message);
                }
            }
        }

        bool button_released (Gdk.EventButton event) {
            if (event.button == 3)
                return show_popup_menu (event);
            return false;
        }

        bool menu_popup () {
            return show_popup_menu (null);
        }

        bool show_popup_menu (Gdk.EventButton? event) {
            Gtk.TreeIter iter;
            if (treeview.get_selection ().get_selected (null, out iter)) {
                Transfer transfer;
                store.get (iter, 0, out transfer);

                var menu = new Gtk.Menu ();
                var menuitem = new Gtk.ImageMenuItem.from_stock (Gtk.STOCK_OPEN, null);
                menuitem.activate.connect (() => {
                    try {
                        Midori.Download.open (transfer.download, treeview);
                    } catch (Error error_open) {
                        GLib.warning (_("Failed to open download: %s"), error_open.message);
                    }
                });
                menuitem.sensitive = transfer.succeeded;
                menu.append (menuitem);
                menuitem = new Gtk.ImageMenuItem.with_mnemonic (_("Open Destination _Folder"));
                menuitem.image = new Gtk.Image.from_stock (Gtk.STOCK_DIRECTORY, Gtk.IconSize.MENU);
                menuitem.activate.connect (() => {
                    var folder = GLib.File.new_for_uri (transfer.destination);
                    (Midori.Browser.get_for_widget (this).tab as Midori.Tab).open_uri (folder.get_parent ().get_uri ());
                });
                menu.append (menuitem);
                menuitem = new Gtk.ImageMenuItem.with_mnemonic (_("Copy Link Loc_ation"));
                menuitem.activate.connect (() => {
                    string uri = transfer.destination;
                    get_clipboard (Gdk.SELECTION_PRIMARY).set_text (uri, -1);
                    get_clipboard (Gdk.SELECTION_CLIPBOARD).set_text (uri, -1);
                });
                menuitem.image = new Gtk.Image.from_stock (Gtk.STOCK_COPY, Gtk.IconSize.MENU);
                menu.append (menuitem);
                menu.show_all ();
                Katze.widget_popup (treeview, menu, null, Katze.MenuPos.CURSOR);

                return true;
            }
            return false;
        }

        int tree_sort_func (Gtk.TreeModel model, Gtk.TreeIter a, Gtk.TreeIter b) {
            Transfer transfer1, transfer2;
            model.get (a, 0, out transfer1);
            model.get (b, 0, out transfer2);
            return (transfer1.finished ? 1 : 0) - (transfer2.finished ? 1 : 0);
        }

        void transfer_changed (GLib.Object item) {
            var transfer = item as Transfer;
            Gtk.TreeIter iter;
            if (store.iter_children (out iter, null)) {
                do {
                    Transfer at;
                    store.get (iter, 0, out at);
                    if (transfer == at) {
                        string tooltip = Midori.Download.get_tooltip (transfer.download);
                        store.set (iter, 1, tooltip);
                        break;
                    }
                } while (store.iter_next (ref iter));
            }
            treeview.queue_draw ();
        }

        void transfer_added (GLib.Object item) {
            var transfer = item as Transfer;
            Gtk.TreeIter iter;
            store.append (out iter);
            store.set (iter, 0, transfer);
            transfer.changed.connect (() => transfer_changed(transfer));
            clear.sensitive = true;
        }

        void transfer_removed (GLib.Object item) {
            var transfer = item as Transfer;
            transfer.changed.disconnect (transfer_changed);
            Gtk.TreeIter iter;
            if (store.iter_children (out iter, null)) {
                do {
                    Transfer found;
                    store.get (iter, 0, out found);
                    if (transfer == found) {
                        store.remove (iter);
                        break;
                    }
                } while (store.iter_next (ref iter));
            }
            if (array.is_empty ())
                clear.sensitive = false;
        }

        void on_render_icon (Gtk.CellLayout column, Gtk.CellRenderer renderer,
            Gtk.TreeModel model, Gtk.TreeIter iter) {

            Transfer transfer;
            model.get (iter, 0, out transfer);
            string content_type = Midori.Download.get_content_type (transfer.download, null);
            var icon = GLib.ContentType.get_icon (content_type) as ThemedIcon;
            icon.append_name ("text-html");
            renderer.set ("gicon", icon,
                          "stock-size", Gtk.IconSize.DND,
                          "xpad", 1, "ypad", 12);
        }

        void on_render_text (Gtk.CellLayout column, Gtk.CellRenderer renderer,
            Gtk.TreeModel model, Gtk.TreeIter iter) {

            Transfer transfer;
            string tooltip;
            model.get (iter, 0, out transfer);
            model.get (iter, 1, out tooltip);
{'fraction_non_alphanumeric': 0.09213308591895741, 'fraction_numerical': 0.0038406766495490442, 'mean_word_length': 1.6433215467092506, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 62, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5752169', 'n_tokens_mistral': 6258, 'n_tokens_neox': 5943, 'n_words': 1497}