Logo Search packages:      
Sourcecode: uget version File versions  Download package

ug_download_dialog.c

/*
 *
 *   Copyright (C) 2005-2009 by Raymond Huang
 *   plushuang at users.sourceforge.net
 *
 *  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.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU Lesser General Public License in all respects
 *  for all of the code used other than OpenSSL.  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so.  If you
 *  do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#include <gdk/gdkkeysyms.h>    // for GDK_key...

#include <ug_category.h>
#include <ug_data_app.h>
#include <ug_download_dialog.h>
#include <ug_list_view.h>
#include <ug_utils.h>
#include <ug_url.h>

#include <glib/gi18n.h>

static gboolean   on_key_press_event      (GtkWidget* widget, GdkEventKey *event, UgDownloadDialog* ddialog);
static void       on_message_dialog_response (GtkDialog* dlg, gint response, UgDownloadDialog* ddialog);
static void       on_dialog_show    (GtkWidget *widget, UgDownloadDialog* dialog);
static void       on_cursor_changed (GtkTreeView* treeview, UgDownloadDialog* dialog);
static void       on_url_entry_changed    (GtkWidget* widget, UgDownloadDialog* dialog);
static void       on_batch_entry_changed  (GtkWidget* widget, UgDownloadDialog* dialog);

static void       ug_download_dialog_init_content     (UgDownloadDialog* dialog, GtkWindow* parent)
{
      gtk_dialog_add_button (dialog->self, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
      gtk_dialog_add_button (dialog->self, GTK_STOCK_OK, GTK_RESPONSE_OK);
      gtk_dialog_set_default_response (dialog->self, GTK_RESPONSE_OK);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_OK, FALSE);
      gtk_dialog_set_has_separator (dialog->self, FALSE);
      gtk_window_set_modal ((GtkWindow*) dialog->self, FALSE);
      gtk_window_set_resizable ((GtkWindow*) dialog->self, FALSE);
      gtk_window_set_destroy_with_parent ((GtkWindow*) dialog->self, TRUE);
      gtk_window_set_transient_for ((GtkWindow*) dialog->self, parent);
      g_signal_connect (dialog->self, "show", G_CALLBACK(on_dialog_show), dialog);

      ug_proxy_widget_init (&dialog->proxy, TRUE);
      ug_download_widget_init (&dialog->download, &dialog->proxy, (GtkWindow*) dialog->self);
      g_signal_connect (GTK_EDITABLE (dialog->download.url_entry), "changed", G_CALLBACK(on_url_entry_changed), dialog);
      g_signal_connect (dialog->download.url_entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);
      g_signal_connect (dialog->download.file_entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);
      g_signal_connect (dialog->download.folder_entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);
      g_signal_connect (dialog->download.referer_entry, "key-press-event",G_CALLBACK (on_key_press_event), dialog);
      g_signal_connect (dialog->download.username_entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);
      g_signal_connect (dialog->download.password_entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);
      g_signal_connect (dialog->proxy.host_entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);
      g_signal_connect (dialog->proxy.username_entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);
      g_signal_connect (dialog->proxy.password_entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);

      // for ug_download_dialog_set_category_list()
      dialog->hbox = (GtkBox*) gtk_hbox_new (FALSE, 2);
      gtk_box_pack_start (GTK_BOX (dialog->self->vbox), (GtkWidget*) dialog->hbox, TRUE, TRUE, 0);
      gtk_widget_show ((GtkWidget*) dialog->hbox);
}

UgDownloadDialog* ug_download_dialog_new (const gchar* title, GtkWindow* parent)
{
      UgDownloadDialog* dialog;

      dialog = g_malloc0 (sizeof (UgDownloadDialog));
      dialog->self = (GtkDialog*) gtk_dialog_new ();

      ug_download_dialog_init_content (dialog, parent);
      gtk_window_set_title ((GtkWindow*) dialog->self, title);

      dialog->current_page = (GtkWidget*) dialog->download.self;
      gtk_box_pack_end (dialog->hbox, (GtkWidget*) dialog->download.self, TRUE, TRUE, 1);
      return dialog;
}

UgDownloadDialog* ug_download_dialog_new_selector (const gchar* title, GtkWindow* parent)
{
      UgDownloadDialog* dialog;
      GtkRequisition          requisition;

      dialog = g_malloc0 (sizeof (UgDownloadDialog));
      dialog->self = (GtkDialog*) gtk_dialog_new ();
      gtk_dialog_add_button (dialog->self, GTK_STOCK_GO_BACK, GTK_RESPONSE_REJECT);
      gtk_dialog_add_button (dialog->self, GTK_STOCK_GO_FORWARD, GTK_RESPONSE_ACCEPT);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_REJECT, FALSE);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_ACCEPT, TRUE);

      gtk_window_set_title ((GtkWindow*) dialog->self, title);
      ug_download_dialog_init_content (dialog, parent);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_OK, TRUE);
      ug_download_widget_set_multiple (&dialog->download, TRUE);
      gtk_widget_size_request (dialog->download.self, &requisition);

      ug_selector_init (&dialog->selector, (GtkWindow*) dialog->self);
      gtk_widget_set_size_request (dialog->selector.self, requisition.width, requisition.height);
      dialog->first_page   = (GtkWidget*) dialog->selector.self;
      dialog->current_page = (GtkWidget*) dialog->selector.self;
      gtk_box_pack_end (dialog->hbox, (GtkWidget*) dialog->selector.self, TRUE, TRUE, 1);
      return dialog;
}

UgDownloadDialog* ug_download_dialog_new_batch (GtkWindow* parent)
{
      UgDownloadDialog* dialog;
      GtkRequisition          requisition;
      gchar*      title;

      dialog = g_malloc0 (sizeof (UgDownloadDialog));
      dialog->self = (GtkDialog*) gtk_dialog_new ();
      gtk_dialog_add_button (dialog->self, GTK_STOCK_GO_BACK, GTK_RESPONSE_REJECT);
      gtk_dialog_add_button (dialog->self, GTK_STOCK_GO_FORWARD, GTK_RESPONSE_ACCEPT);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_REJECT, FALSE);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_ACCEPT, FALSE);

      title = g_strconcat ("Uget - ", _("New Batch Download"), NULL);
      gtk_window_set_title ((GtkWindow*) dialog->self, title);
      g_free (title);
      ug_download_dialog_init_content (dialog, parent);
      ug_download_widget_set_multiple (&dialog->download, TRUE);
      gtk_widget_size_request (dialog->download.self, &requisition);

      ug_batch_widget_init (&dialog->batch);
      gtk_widget_set_size_request (dialog->batch.self, requisition.width, requisition.height);
      dialog->first_page   = (GtkWidget*) dialog->batch.self;
      dialog->current_page = (GtkWidget*) dialog->batch.self;
      gtk_box_pack_end (dialog->hbox, (GtkWidget*) dialog->batch.self, TRUE, TRUE, 1);
      g_signal_connect (GTK_EDITABLE (dialog->batch.entry), "changed", G_CALLBACK(on_batch_entry_changed), dialog);
      g_signal_connect (dialog->batch.entry, "key-press-event", G_CALLBACK (on_key_press_event), dialog);
      return dialog;
}

void  ug_download_dialog_destroy (UgDownloadDialog* dialog)
{
      g_object_ref (dialog->current_page);
      gtk_container_remove ((GtkContainer*) dialog->hbox, dialog->current_page);
      // destroy widget
      if (dialog->batch.self)
            gtk_widget_destroy (dialog->batch.self);
      if (dialog->download.self)
            gtk_widget_destroy (dialog->download.self);
      if (dialog->selector.self) {
            ug_selector_finalize (&dialog->selector);
            gtk_widget_destroy (dialog->selector.self);
      }
      // destroy dialog
      gtk_widget_destroy ((GtkWidget*) dialog->self);

      // user
      if (dialog->dataset)
            ug_data_free (dialog->dataset);
      g_free (dialog);
}

gboolean    ug_download_dialog_response (UgDownloadDialog* dialog, gint response_id)
{
      GtkTreePath*      path;
      GtkWidget*        msg_dialog;
      gchar*                  title;

      switch (response_id) {
      case GTK_RESPONSE_ACCEPT:
            if (dialog->current_page == dialog->selector.self) {
                  if (ug_selector_show_error (&dialog->selector))
                        return TRUE;
            }
            g_object_ref (dialog->current_page);
            gtk_container_remove ((GtkContainer*) dialog->hbox, dialog->current_page);
            gtk_box_pack_end (dialog->hbox, (GtkWidget*) dialog->download.self, TRUE, TRUE, 1);
            dialog->current_page = dialog->download.self;
            gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_ACCEPT, FALSE);
            gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_REJECT, TRUE);
            return TRUE;

      case GTK_RESPONSE_REJECT:
            g_object_ref (dialog->current_page);
            gtk_container_remove ((GtkContainer*) dialog->hbox, dialog->current_page);
            gtk_box_pack_end (dialog->hbox, (GtkWidget*) dialog->first_page, TRUE, TRUE, 1);
            dialog->current_page = dialog->first_page;
            gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_ACCEPT, TRUE);
            gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_REJECT, FALSE);
            return TRUE;

      case GTK_RESPONSE_OK:
            if (dialog->current_page == dialog->selector.self) {
                  if (ug_selector_show_error (&dialog->selector))
                        return TRUE;
            }
            if (dialog->category_view) {
                  gtk_tree_view_get_cursor (dialog->category_view, &path, NULL);
                  if (path == NULL) {
                        msg_dialog = gtk_message_dialog_new ((GtkWindow*) dialog->self,
                                             GTK_DIALOG_DESTROY_WITH_PARENT,
                                             GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
                                             _("No category selected."));
                        title = g_strconcat ("Uget - ", _("Error"), NULL);
                        gtk_window_set_title ((GtkWindow*) msg_dialog, title);
                        g_free (title);
                        gtk_window_set_transient_for ((GtkWindow*) msg_dialog, (GtkWindow*) dialog->self);
                        // set sensitive TRUE in on_message_dialog_response()
                        gtk_widget_set_sensitive ((GtkWidget*) dialog->self, FALSE);
                        g_signal_connect (msg_dialog, "response", G_CALLBACK (on_message_dialog_response), dialog);
                        if (gtk_window_get_modal ((GtkWindow*) dialog->self))
                              gtk_dialog_run ((GtkDialog*) msg_dialog);
                        else
                              gtk_widget_show ((GtkWidget*) msg_dialog);
                        return TRUE;
                  }
                  gtk_tree_path_free (path);
            }
            break;
      }

      return FALSE;
}

void  ug_download_dialog_get (UgDownloadDialog* dialog, UgDataset* dataset)
{
      ug_proxy_widget_get (&dialog->proxy, dataset);
      ug_download_widget_get (&dialog->download, dataset);
}

void  ug_download_dialog_set (UgDownloadDialog* dialog, UgDataset* dataset)
{
      ug_proxy_widget_set (&dialog->proxy, dataset);
      ug_download_widget_set (&dialog->download, dataset);
}

void  ug_download_dialog_set_category_list (UgDownloadDialog* dialog, GtkListStore* category_list)
{
      GtkWidget*  scrolled;
      GtkBox*           vbox;

      dialog->category_view = ug_category_view_new ();
      gtk_tree_view_set_model (dialog->category_view, (GtkTreeModel*) category_list);
      gtk_widget_set_size_request ((GtkWidget*) dialog->category_view, 165, 100);
      g_signal_connect (dialog->category_view, "cursor-changed", G_CALLBACK (on_cursor_changed), dialog);
      // scrolled window
      scrolled = gtk_scrolled_window_new (NULL, NULL);
      gtk_widget_show (scrolled);
      gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
                                      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
      gtk_container_add (GTK_CONTAINER (scrolled), GTK_WIDGET(dialog->category_view));
      // pack vbox
      vbox = (GtkBox*) gtk_vbox_new (FALSE, 2);
      gtk_box_pack_start (vbox, gtk_label_new (_("Category")), FALSE, FALSE, 0);
      gtk_box_pack_start (vbox, (GtkWidget*) scrolled, TRUE, TRUE, 0);
      gtk_widget_show_all ((GtkWidget*) vbox);
      // pack hbox
      gtk_box_pack_start (dialog->hbox, (GtkWidget*) vbox, TRUE, TRUE, 1);
}

void  ug_download_dialog_select_category (UgDownloadDialog* dialog, UgCategory* category)
{
      UgCategory*       temp;
      GtkTreeModel*     model;
      GtkTreePath*      path;
      GtkTreeIter       iter;
      gboolean          valid;

      if (dialog->category_view == NULL)
            return;
      model = gtk_tree_view_get_model (dialog->category_view);
      valid = gtk_tree_model_get_iter_first (model, &iter);
      while (valid) {
            gtk_tree_model_get (model, &iter, 0, &temp, -1);
            if (temp == category) {
                  path = gtk_tree_model_get_path (model, &iter);
                  gtk_tree_view_set_cursor (dialog->category_view, path, NULL, FALSE);
                  gtk_tree_path_free (path);
                  break;
            }
            valid = gtk_tree_model_iter_next (model, &iter);
      }
}

UgCategory* ug_download_dialog_get_category (UgDownloadDialog* dialog)
{
      UgCategory*       category;
      GtkTreeModel*     model;
      GtkTreePath*      path;
      GtkTreeIter       iter;

      gtk_tree_view_get_cursor (dialog->category_view, &path, NULL);
      model = gtk_tree_view_get_model (dialog->category_view);
      if (path == NULL) {
            if (gtk_tree_model_get_iter_first (model, &iter)) {
                  gtk_tree_model_get (model, &iter, 0, &category, -1);
                  return category;
            }
            return NULL;
      }
      gtk_tree_model_get_iter (model, &iter, path);
      gtk_tree_path_free (path);
      gtk_tree_model_get (model, &iter, 0, &category, -1);
      return category;
}

UgDataset*  ug_download_dialog_get_download_list (UgDownloadDialog* dialog)
{
      UgDataset*        dataset;
      UgDataset*        result;
      UgDataCommon*     common;
      UgUrlPart*        urlpart;
      GList*                  list;
      GList*                  link;

      if (dialog->batch.self)
            list = ug_batch_widget_get_list (&dialog->batch, FALSE);
      else if (dialog->selector.self)
            list = ug_selector_get_marked (&dialog->selector);
      else {
            if (dialog->dataset) {
                  dataset = dialog->dataset;
                  dialog->dataset = NULL;
            }
            else
                  dataset = ug_dataset_new_app ();
            ug_download_dialog_get (dialog, dataset);
            return dataset;
      }

      urlpart = g_malloc (sizeof (UgUrlPart));
      result = NULL;
      for (link = list;  link;  link = link->next) {
            dataset = ug_dataset_new_app ();
            ug_download_dialog_get (dialog, dataset);
            common = UG_DATASET_COMMON (dataset);
            ug_url_part (urlpart, link->data, -1);
            ug_str_set (&common->url, link->data, -1);
            if (urlpart->file_len)
                  common->file = ug_url_unescape_to_utf8 (urlpart->file, urlpart->file_len);
            else
                  ug_str_set (&common->file, "index.html", -1);
            result  = ug_data_list_prepend (result, dataset);
      }
      g_free (urlpart);

      g_list_foreach (list, (GFunc) g_free, NULL);
      g_list_free (list);
      return result;
}

// ----------------------------------------------------------------------------
//    signal handler
static void       on_message_dialog_response (GtkDialog* dlg, gint response, UgDownloadDialog* ddialog)
{
      gtk_widget_set_sensitive ((GtkWidget*) ddialog->self, TRUE);      // set sensitive FALSE in ug_download_dialog_response()
      gtk_widget_destroy ((GtkWidget*) dlg);
}

static void       on_dialog_show (GtkWidget *widget, UgDownloadDialog* dialog)
{
      if (dialog->first_page == NULL) {
            if (dialog->download.multiple) {
                  gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_OK, TRUE);
                  dialog->response_ok = TRUE;
                  gtk_window_set_focus ((GtkWindow*) dialog->self, (GtkWidget*) dialog->download.folder_entry);
            }
            else
                  gtk_window_set_focus ((GtkWindow*) dialog->self, (GtkWidget*) dialog->download.url_entry);
      }
      else if (dialog->first_page == dialog->batch.self)
            gtk_window_set_focus ((GtkWindow*) dialog->self, dialog->batch.entry);
      else if (dialog->first_page == dialog->selector.self)
            gtk_window_set_focus ((GtkWindow*) dialog->self, (GtkWidget*) dialog->selector.notebook);
}

static gboolean on_key_press_event (GtkWidget* widget, GdkEventKey *event, UgDownloadDialog* dialog)
{
      int keyval = event->keyval;

      if ((keyval == GDK_Return || keyval == GDK_KP_Enter) && dialog->response_ok) {
            gtk_dialog_response (dialog->self, GTK_RESPONSE_OK);
            return TRUE;
      }
      return FALSE;
}

static void       on_cursor_changed (GtkTreeView* treeview, UgDownloadDialog* dialog)
{
      GtkTreeModel*     model;
      GtkTreePath*      path;
      GtkTreeIter       iter;
      UgCategory*       category;

      model = gtk_tree_view_get_model (treeview);
      gtk_tree_view_get_cursor (treeview, &path, NULL);
      gtk_tree_model_get_iter (model, &iter, path);
      gtk_tree_path_free (path);
      gtk_tree_model_get (model, &iter, 0, &category, -1);
      if (category->download_default) {
            ug_download_widget_apply (&dialog->download, category->download_default);
            ug_proxy_widget_set (&dialog->proxy, category->download_default);
      }
}

static void       on_batch_entry_changed  (GtkWidget* widget, UgDownloadDialog* dialog)
{
      gboolean    valid;

      valid = ug_batch_widget_update_preview (&dialog->batch);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_OK,     valid);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_ACCEPT, valid);
      dialog->response_ok = valid;
}

static void       on_url_entry_changed    (GtkWidget* widget, UgDownloadDialog* dialog)
{
      gboolean    valid;

      valid = ug_download_widget_complete_entry (&dialog->download);
      gtk_dialog_set_response_sensitive (dialog->self, GTK_RESPONSE_OK, valid);
      dialog->response_ok = valid;
}


Generated by  Doxygen 1.6.0   Back to index