Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

content_settings_window_gtk.cc

// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/gtk/options/content_settings_window_gtk.h"

#include <string>

#include "app/l10n_util.h"
#include "base/command_line.h"
#include "base/message_loop.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/gtk/accessible_widget_helper_gtk.h"
#include "chrome/browser/gtk/browser_window_gtk.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/gtk/gtk_tree.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/content_settings_types.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

namespace {

// The singleton options window object.
ContentSettingsWindowGtk* settings_window = NULL;

}  // namespace

// static
void ContentSettingsWindowGtk::Show(GtkWindow* parent,
                                    ContentSettingsType page,
                                    Profile* profile) {
  DCHECK(profile);

  if (!settings_window) {
    // Creating and initializing a bunch of controls generates a bunch of
    // spurious events as control values change. Temporarily suppress
    // accessibility events until the window is created.
    profile->PauseAccessibilityEvents();

    // Create the options window.
    settings_window = new ContentSettingsWindowGtk(parent, profile);

    // Resume accessibility events.
    profile->ResumeAccessibilityEvents();
  }
  settings_window->ShowContentSettingsTab(page);
}

ContentSettingsWindowGtk::ContentSettingsWindowGtk(GtkWindow* parent,
                                                   Profile* profile)
    : profile_(profile),
      cookie_page_(profile),
      image_page_(profile, CONTENT_SETTINGS_TYPE_IMAGES),
      javascript_page_(profile, CONTENT_SETTINGS_TYPE_JAVASCRIPT),
      plugin_page_(profile, CONTENT_SETTINGS_TYPE_PLUGINS),
      popup_page_(profile, CONTENT_SETTINGS_TYPE_POPUPS),
      geolocation_page_(profile, CONTENT_SETTINGS_TYPE_GEOLOCATION),
      notifications_page_(profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
  const struct {
    int message_id;
    GtkWidget* widget;
  } kNotebookPages[] = {
    { IDS_COOKIES_TAB_LABEL, cookie_page_.get_page_widget() },
    { IDS_IMAGES_TAB_LABEL, image_page_.get_page_widget() },
    { IDS_JAVASCRIPT_TAB_LABEL, javascript_page_.get_page_widget() },
    { IDS_PLUGIN_TAB_LABEL, plugin_page_.get_page_widget() },
    { IDS_POPUP_TAB_LABEL, popup_page_.get_page_widget() },
    { IDS_GEOLOCATION_TAB_LABEL, geolocation_page_.get_page_widget() },
    { IDS_NOTIFICATIONS_TAB_LABEL, notifications_page_.get_page_widget() },
  };

  // We don't need to observe changes in this value.
  last_selected_page_.Init(prefs::kContentSettingsWindowLastTabIndex,
                           profile->GetPrefs(), NULL);

  std::string dialog_name = l10n_util::GetStringUTF8(
      IDS_CONTENT_SETTINGS_TITLE);
  dialog_ = gtk_dialog_new_with_buttons(
      dialog_name.c_str(),
      parent,
      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
      GTK_STOCK_CLOSE,
      GTK_RESPONSE_CLOSE,
      NULL);
  gtk_window_set_policy(GTK_WINDOW(dialog_), FALSE, FALSE, TRUE);

  accessible_widget_helper_.reset(new AccessibleWidgetHelper(
      dialog_, profile_));
  accessible_widget_helper_->SendOpenWindowNotification(dialog_name);

  gtk_window_set_default_size(GTK_WINDOW(dialog_), 500, -1);
  // Allow browser windows to go in front of the options dialog in metacity.
  gtk_window_set_type_hint(GTK_WINDOW(dialog_), GDK_WINDOW_TYPE_HINT_NORMAL);
  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
                      gtk_util::kContentAreaSpacing);
  gtk_util::SetWindowIcon(GTK_WINDOW(dialog_));

  // Create hbox with list view and notebook.
  GtkWidget* hbox = gtk_hbox_new(FALSE, gtk_util::kContentAreaSpacing);

  list_ = gtk_tree_view_new();
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list_), FALSE);

  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
      "List Item", renderer, "text", 0, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(list_), column);

  const int kColumnCount = 1;
  GtkListStore* store = gtk_list_store_new(kColumnCount, G_TYPE_STRING);
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNotebookPages); ++i) {
    GtkTreeIter iter;
    gtk_list_store_append(store, &iter);
    std::string label = l10n_util::GetStringUTF8(kNotebookPages[i].message_id);
    gtk_list_store_set(store, &iter, 0, label.c_str(), -1);
  }
  gtk_tree_view_set_model(GTK_TREE_VIEW(list_), GTK_TREE_MODEL(store));
  g_object_unref(store);

  // Needs to happen after the model is all set up.
  GtkTreeSelection* selection = gtk_tree_view_get_selection(
      GTK_TREE_VIEW(list_));
  gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);

  // Wrap the list widget in a scrolled window in order to have a frame.
  GtkWidget* scrolled = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
                                      GTK_SHADOW_ETCHED_IN);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
                                 GTK_POLICY_NEVER, GTK_POLICY_NEVER);
  gtk_container_add(GTK_CONTAINER(scrolled), list_);
  gtk_box_pack_start(GTK_BOX(hbox), scrolled, FALSE, FALSE, 0);

  notebook_ = gtk_notebook_new();
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNotebookPages); ++i) {
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook_),
                             kNotebookPages[i].widget,
                             NULL);
  }
  gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook_), FALSE);
  gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook_), FALSE);
  gtk_box_pack_start(GTK_BOX(hbox), notebook_, FALSE, FALSE, 0);
  DCHECK_EQ(gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)),
            CONTENT_SETTINGS_NUM_TYPES);

  // Create vbox with "Features:" text and hbox below.
  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  GtkWidget* label = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_CONTENT_SETTINGS_FEATURES_LABEL).c_str());
  gtk_misc_set_alignment(GTK_MISC(label), 0, .5);
  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), vbox);

  // Need to show the notebook before connecting switch-page signal, otherwise
  // we'll immediately get a signal switching to page 0 and overwrite our
  // last_selected_page_ value.
  gtk_util::ShowDialogWithLocalizedSize(dialog_, -1, -1, true);

  g_signal_connect(notebook_, "switch-page",
                   G_CALLBACK(OnSwitchPageThunk), this);
  g_signal_connect(selection, "changed",
                   G_CALLBACK(OnListSelectionChangedThunk), this);

  // We only have one button and don't do any special handling, so just hook it
  // directly to gtk_widget_destroy.
  g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL);

  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
}

ContentSettingsWindowGtk::~ContentSettingsWindowGtk() {
}

void ContentSettingsWindowGtk::ShowContentSettingsTab(
    ContentSettingsType page) {
  // Bring options window to front if it already existed and isn't already
  // in front
  gtk_util::PresentWindow(dialog_,  gtk_get_current_event_time());

  if (page == CONTENT_SETTINGS_TYPE_DEFAULT) {
    // Remember the last visited page from local state.
    page = static_cast<ContentSettingsType>(last_selected_page_.GetValue());
    if (page == CONTENT_SETTINGS_TYPE_DEFAULT)
      page = CONTENT_SETTINGS_TYPE_COOKIES;
  }
  // If the page number is out of bounds, reset to the first tab.
  if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)))
    page = CONTENT_SETTINGS_TYPE_COOKIES;

  gtk_tree::SelectAndFocusRowNum(page, GTK_TREE_VIEW(list_));
}

void ContentSettingsWindowGtk::OnSwitchPage(
    GtkWidget* notebook,
    GtkNotebookPage* page,
    guint page_num) {
  int index = page_num;
  DCHECK(index > CONTENT_SETTINGS_TYPE_DEFAULT &&
         index < CONTENT_SETTINGS_NUM_TYPES);

  // Keep list in sync.
  GtkTreeModel* model;
  GtkTreeIter iter;
  if (gtk_tree_selection_get_selected(
      gtk_tree_view_get_selection(GTK_TREE_VIEW(list_)), &model, &iter)) {
    gint row_index = gtk_tree::GetRowNumForIter(model, &iter);
    if (row_index == index)
      return;
  }
  gtk_tree::SelectAndFocusRowNum(index, GTK_TREE_VIEW(list_));
}

void ContentSettingsWindowGtk::OnWindowDestroy(GtkWidget* widget) {
  settings_window = NULL;
  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}

void ContentSettingsWindowGtk::OnListSelectionChanged(
    GtkTreeSelection* selection) {
  GtkTreeModel* model;
  GtkTreeIter iter;
  if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
    NOTREACHED();
    return;
  }
  gint row_index = gtk_tree::GetRowNumForIter(model, &iter);
  DCHECK(row_index > CONTENT_SETTINGS_TYPE_DEFAULT &&
         row_index < CONTENT_SETTINGS_NUM_TYPES);

  last_selected_page_.SetValue(row_index);

  if (row_index != gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_)))
    gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), row_index);
}

Generated by  Doxygen 1.6.0   Back to index