| OLD | NEW | 
|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <gtk/gtk.h> | 5 #include <gtk/gtk.h> | 
| 6 #include <map> | 6 #include <map> | 
| 7 #include <set> | 7 #include <set> | 
| 8 | 8 | 
| 9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" | 
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" | 
| 11 #include "base/logging.h" | 11 #include "base/logging.h" | 
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" | 
| 13 #include "base/mime_util.h" | 13 #include "base/mime_util.h" | 
| 14 #include "base/thread.h" |  | 
| 15 #include "base/string_util.h" | 14 #include "base/string_util.h" | 
| 16 #include "base/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" | 
|  | 16 #include "base/thread.h" | 
| 17 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" | 
| 18 #include "chrome/browser/chrome_thread.h" | 18 #include "chrome/browser/chrome_thread.h" | 
| 19 #include "chrome/browser/shell_dialogs.h" | 19 #include "chrome/browser/shell_dialogs.h" | 
| 20 #include "grit/generated_resources.h" | 20 #include "grit/generated_resources.h" | 
| 21 | 21 | 
| 22 // The size of the preview we display for selected image files. We set height | 22 // The size of the preview we display for selected image files. We set height | 
| 23 // larger than width because generally there is more free space vertically | 23 // larger than width because generally there is more free space vertically | 
| 24 // than horiztonally (setting the preview image will alway expand the width of | 24 // than horiztonally (setting the preview image will alway expand the width of | 
| 25 // the dialog, but usually not the height). The image's aspect ratio will always | 25 // the dialog, but usually not the height). The image's aspect ratio will always | 
| 26 // be preserved. | 26 // be preserved. | 
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 74   GtkWidget* CreateMultiFileOpenDialog(const std::string& title, | 74   GtkWidget* CreateMultiFileOpenDialog(const std::string& title, | 
| 75       const FilePath& default_path, gfx::NativeWindow parent); | 75       const FilePath& default_path, gfx::NativeWindow parent); | 
| 76 | 76 | 
| 77   GtkWidget* CreateSaveAsDialog(const std::string& title, | 77   GtkWidget* CreateSaveAsDialog(const std::string& title, | 
| 78       const FilePath& default_path, gfx::NativeWindow parent); | 78       const FilePath& default_path, gfx::NativeWindow parent); | 
| 79 | 79 | 
| 80   // Removes and returns the |params| associated with |dialog| from | 80   // Removes and returns the |params| associated with |dialog| from | 
| 81   // |params_map_|. | 81   // |params_map_|. | 
| 82   void* PopParamsForDialog(GtkWidget* dialog); | 82   void* PopParamsForDialog(GtkWidget* dialog); | 
| 83 | 83 | 
| 84   // Removes and returns the parent associated with |dialog| from |parents_|. | 84   // Take care of internal data structures when a file dialog is destroyed. | 
| 85   void RemoveParentForDialog(GtkWidget* dialog); | 85   void FileDialogDestroyed(GtkWidget* dialog); | 
| 86 | 86 | 
| 87   // Check whether response_id corresponds to the user cancelling/closing the | 87   // Check whether response_id corresponds to the user cancelling/closing the | 
| 88   // dialog. Used as a helper for the below callbacks. | 88   // dialog. Used as a helper for the below callbacks. | 
| 89   static bool IsCancelResponse(gint response_id); | 89   static bool IsCancelResponse(gint response_id); | 
| 90 | 90 | 
| 91   // Common function for OnSelectSingleFileDialogResponse and | 91   // Common function for OnSelectSingleFileDialogResponse and | 
| 92   // OnSelectSingleFolderDialogResponse. | 92   // OnSelectSingleFolderDialogResponse. | 
| 93   static void SelectSingleFileHelper(GtkWidget* dialog, | 93   static void SelectSingleFileHelper(GtkWidget* dialog, | 
| 94                                      gint response_id, | 94                                      gint response_id, | 
| 95                                      SelectFileDialogImpl* dialog_impl, | 95                                      SelectFileDialogImpl* dialog_impl, | 
| 96                                      bool allow_folder); | 96                                      bool allow_folder); | 
| 97 | 97 | 
| 98   // Callback for when the user responds to a Save As or Open File dialog. | 98   // Callback for when the user responds to a Save As or Open File dialog. | 
| 99   static void OnSelectSingleFileDialogResponse( | 99   static void OnSelectSingleFileDialogResponse( | 
| 100       GtkWidget* dialog, gint response_id, SelectFileDialogImpl* dialog_impl); | 100       GtkWidget* dialog, gint response_id, SelectFileDialogImpl* dialog_impl); | 
| 101 | 101 | 
| 102   // Callback for when the user responds to a Select Folder dialog. | 102   // Callback for when the user responds to a Select Folder dialog. | 
| 103   static void OnSelectSingleFolderDialogResponse( | 103   static void OnSelectSingleFolderDialogResponse( | 
| 104       GtkWidget* dialog, gint response_id, SelectFileDialogImpl* dialog_impl); | 104       GtkWidget* dialog, gint response_id, SelectFileDialogImpl* dialog_impl); | 
| 105 | 105 | 
| 106   // Callback for when the user responds to a Open Multiple Files dialog. | 106   // Callback for when the user responds to a Open Multiple Files dialog. | 
| 107   static void OnSelectMultiFileDialogResponse( | 107   static void OnSelectMultiFileDialogResponse( | 
| 108       GtkWidget* dialog, gint response_id, SelectFileDialogImpl* dialog_impl); | 108       GtkWidget* dialog, gint response_id, SelectFileDialogImpl* dialog_impl); | 
| 109 | 109 | 
|  | 110   // Callback for when the file chooser gets destroyed. | 
|  | 111   static void OnFileChooserDestroy(GtkWidget* dialog, | 
|  | 112                                    SelectFileDialogImpl* dialog_impl); | 
|  | 113 | 
| 110   // Callback for when we update the preview for the selection. | 114   // Callback for when we update the preview for the selection. | 
| 111   static void OnUpdatePreview(GtkFileChooser* chooser, | 115   static void OnUpdatePreview(GtkFileChooser* chooser, | 
| 112                               SelectFileDialogImpl* dialog); | 116                               SelectFileDialogImpl* dialog); | 
| 113 | 117 | 
| 114   // The listener to be notified of selection completion. | 118   // The listener to be notified of selection completion. | 
| 115   Listener* listener_; | 119   Listener* listener_; | 
| 116 | 120 | 
| 117   // A map from dialog windows to the |params| user data associated with them. | 121   // A map from dialog windows to the |params| user data associated with them. | 
| 118   std::map<GtkWidget*, void*> params_map_; | 122   std::map<GtkWidget*, void*> params_map_; | 
| 119 | 123 | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 156 | 160 | 
| 157 SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) | 161 SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) | 
| 158     : listener_(listener) { | 162     : listener_(listener) { | 
| 159   if (!last_saved_path_) { | 163   if (!last_saved_path_) { | 
| 160     last_saved_path_ = new FilePath(); | 164     last_saved_path_ = new FilePath(); | 
| 161     last_opened_path_ = new FilePath(); | 165     last_opened_path_ = new FilePath(); | 
| 162   } | 166   } | 
| 163 } | 167 } | 
| 164 | 168 | 
| 165 SelectFileDialogImpl::~SelectFileDialogImpl() { | 169 SelectFileDialogImpl::~SelectFileDialogImpl() { | 
| 166   for (std::set<GtkWidget*>::iterator iter = dialogs_.begin(); | 170   while (dialogs_.begin() != dialogs_.end()) { | 
| 167        iter != dialogs_.end(); ++iter) { | 171     gtk_widget_destroy(*(dialogs_.begin())); | 
| 168     gtk_widget_destroy(*iter); |  | 
| 169   } | 172   } | 
| 170 } | 173 } | 
| 171 | 174 | 
| 172 bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const { | 175 bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const { | 
| 173   return parents_.find(parent_window) != parents_.end(); | 176   return parents_.find(parent_window) != parents_.end(); | 
| 174 } | 177 } | 
| 175 | 178 | 
| 176 void SelectFileDialogImpl::ListenerDestroyed() { | 179 void SelectFileDialogImpl::ListenerDestroyed() { | 
| 177   listener_ = NULL; | 180   listener_ = NULL; | 
| 178 } | 181 } | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 217     case SELECT_SAVEAS_FILE: | 220     case SELECT_SAVEAS_FILE: | 
| 218       dialog = CreateSaveAsDialog(title_string, default_path, owning_window); | 221       dialog = CreateSaveAsDialog(title_string, default_path, owning_window); | 
| 219       break; | 222       break; | 
| 220     default: | 223     default: | 
| 221       NOTREACHED(); | 224       NOTREACHED(); | 
| 222       return; | 225       return; | 
| 223   } | 226   } | 
| 224   dialogs_.insert(dialog); | 227   dialogs_.insert(dialog); | 
| 225 | 228 | 
| 226   preview_ = gtk_image_new(); | 229   preview_ = gtk_image_new(); | 
|  | 230   g_signal_connect(dialog, "destroy", G_CALLBACK(OnFileChooserDestroy), this); | 
| 227   g_signal_connect(dialog, "update-preview", G_CALLBACK(OnUpdatePreview), this); | 231   g_signal_connect(dialog, "update-preview", G_CALLBACK(OnUpdatePreview), this); | 
| 228   gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); | 232   gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); | 
| 229 | 233 | 
| 230   params_map_[dialog] = params; | 234   params_map_[dialog] = params; | 
| 231 | 235 | 
| 232   // Set window-to-parent modality by adding the dialog to the same window | 236   // Set window-to-parent modality by adding the dialog to the same window | 
| 233   // group as the parent. | 237   // group as the parent. | 
| 234   gtk_window_group_add_window(gtk_window_get_group(owning_window), | 238   gtk_window_group_add_window(gtk_window_get_group(owning_window), | 
| 235                               GTK_WINDOW(dialog)); | 239                               GTK_WINDOW(dialog)); | 
| 236   gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); | 240   gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 295     NOTREACHED(); | 299     NOTREACHED(); | 
| 296 | 300 | 
| 297   if (listener_) { | 301   if (listener_) { | 
| 298     GtkFileFilter* selected_filter = | 302     GtkFileFilter* selected_filter = | 
| 299         gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog)); | 303         gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog)); | 
| 300     GSList* filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog)); | 304     GSList* filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog)); | 
| 301     int idx = g_slist_index(filters, selected_filter); | 305     int idx = g_slist_index(filters, selected_filter); | 
| 302     g_slist_free(filters); | 306     g_slist_free(filters); | 
| 303     listener_->FileSelected(path, idx + 1, PopParamsForDialog(dialog)); | 307     listener_->FileSelected(path, idx + 1, PopParamsForDialog(dialog)); | 
| 304   } | 308   } | 
| 305   RemoveParentForDialog(dialog); |  | 
| 306   gtk_widget_destroy(dialog); | 309   gtk_widget_destroy(dialog); | 
| 307   dialogs_.erase(dialog); |  | 
| 308 } | 310 } | 
| 309 | 311 | 
| 310 void SelectFileDialogImpl::MultiFilesSelected(GtkWidget* dialog, | 312 void SelectFileDialogImpl::MultiFilesSelected(GtkWidget* dialog, | 
| 311     const std::vector<FilePath>& files) { | 313     const std::vector<FilePath>& files) { | 
| 312   *last_opened_path_ = files[0].DirName(); | 314   *last_opened_path_ = files[0].DirName(); | 
| 313 | 315 | 
| 314   if (listener_) | 316   if (listener_) | 
| 315     listener_->MultiFilesSelected(files, PopParamsForDialog(dialog)); | 317     listener_->MultiFilesSelected(files, PopParamsForDialog(dialog)); | 
| 316   RemoveParentForDialog(dialog); |  | 
| 317   gtk_widget_destroy(dialog); | 318   gtk_widget_destroy(dialog); | 
| 318   dialogs_.erase(dialog); |  | 
| 319 } | 319 } | 
| 320 | 320 | 
| 321 void SelectFileDialogImpl::FileNotSelected(GtkWidget* dialog) { | 321 void SelectFileDialogImpl::FileNotSelected(GtkWidget* dialog) { | 
| 322   void* params = PopParamsForDialog(dialog); | 322   void* params = PopParamsForDialog(dialog); | 
| 323   if (listener_) | 323   if (listener_) | 
| 324     listener_->FileSelectionCanceled(params); | 324     listener_->FileSelectionCanceled(params); | 
| 325   RemoveParentForDialog(dialog); |  | 
| 326   gtk_widget_destroy(dialog); | 325   gtk_widget_destroy(dialog); | 
| 327   dialogs_.erase(dialog); |  | 
| 328 } | 326 } | 
| 329 | 327 | 
| 330 GtkWidget* SelectFileDialogImpl::CreateSelectFolderDialog( | 328 GtkWidget* SelectFileDialogImpl::CreateSelectFolderDialog( | 
| 331     const std::string& title, | 329     const std::string& title, | 
| 332     const FilePath& default_path, | 330     const FilePath& default_path, | 
| 333     gfx::NativeWindow parent) { | 331     gfx::NativeWindow parent) { | 
| 334   std::string title_string = !title.empty() ? title : | 332   std::string title_string = !title.empty() ? title : | 
| 335         l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); | 333         l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); | 
| 336 | 334 | 
| 337   GtkWidget* dialog = | 335   GtkWidget* dialog = | 
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 444 } | 442 } | 
| 445 | 443 | 
| 446 void* SelectFileDialogImpl::PopParamsForDialog(GtkWidget* dialog) { | 444 void* SelectFileDialogImpl::PopParamsForDialog(GtkWidget* dialog) { | 
| 447   std::map<GtkWidget*, void*>::iterator iter = params_map_.find(dialog); | 445   std::map<GtkWidget*, void*>::iterator iter = params_map_.find(dialog); | 
| 448   DCHECK(iter != params_map_.end()); | 446   DCHECK(iter != params_map_.end()); | 
| 449   void* params = iter->second; | 447   void* params = iter->second; | 
| 450   params_map_.erase(iter); | 448   params_map_.erase(iter); | 
| 451   return params; | 449   return params; | 
| 452 } | 450 } | 
| 453 | 451 | 
| 454 void SelectFileDialogImpl::RemoveParentForDialog(GtkWidget* dialog) { | 452 void SelectFileDialogImpl::FileDialogDestroyed(GtkWidget* dialog) { | 
|  | 453   dialogs_.erase(dialog); | 
|  | 454 | 
|  | 455   // Parent may be NULL on shutdown when AllBrowsersClosed() trigger this | 
|  | 456   // handler after all the browser windows got destroyed. | 
| 455   GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(dialog)); | 457   GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(dialog)); | 
| 456   DCHECK(parent); | 458   if (!parent) | 
|  | 459     return; | 
| 457   std::set<GtkWindow*>::iterator iter = parents_.find(parent); | 460   std::set<GtkWindow*>::iterator iter = parents_.find(parent); | 
| 458   if (iter != parents_.end()) | 461   if (iter != parents_.end()) | 
| 459     parents_.erase(iter); | 462     parents_.erase(iter); | 
| 460   else | 463   else | 
| 461     NOTREACHED(); | 464     NOTREACHED(); | 
| 462 } | 465 } | 
| 463 | 466 | 
| 464 // static | 467 // static | 
| 465 bool SelectFileDialogImpl::IsCancelResponse(gint response_id) { | 468 bool SelectFileDialogImpl::IsCancelResponse(gint response_id) { | 
| 466   bool is_cancel = response_id == GTK_RESPONSE_CANCEL || | 469   bool is_cancel = response_id == GTK_RESPONSE_CANCEL || | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 545   g_slist_free(filenames); | 548   g_slist_free(filenames); | 
| 546 | 549 | 
| 547   if (filenames_fp.empty()) { | 550   if (filenames_fp.empty()) { | 
| 548     dialog_impl->FileNotSelected(dialog); | 551     dialog_impl->FileNotSelected(dialog); | 
| 549     return; | 552     return; | 
| 550   } | 553   } | 
| 551   dialog_impl->MultiFilesSelected(dialog, filenames_fp); | 554   dialog_impl->MultiFilesSelected(dialog, filenames_fp); | 
| 552 } | 555 } | 
| 553 | 556 | 
| 554 // static | 557 // static | 
|  | 558 void SelectFileDialogImpl::OnFileChooserDestroy(GtkWidget* dialog, | 
|  | 559     SelectFileDialogImpl* dialog_impl) { | 
|  | 560   dialog_impl->FileDialogDestroyed(dialog); | 
|  | 561 } | 
|  | 562 | 
|  | 563 // static | 
| 555 void SelectFileDialogImpl::OnUpdatePreview(GtkFileChooser* chooser, | 564 void SelectFileDialogImpl::OnUpdatePreview(GtkFileChooser* chooser, | 
| 556                                            SelectFileDialogImpl* dialog) { | 565                                            SelectFileDialogImpl* dialog) { | 
| 557   gchar* filename = gtk_file_chooser_get_preview_filename(chooser); | 566   gchar* filename = gtk_file_chooser_get_preview_filename(chooser); | 
| 558   if (!filename) | 567   if (!filename) | 
| 559     return; | 568     return; | 
| 560   // This will preserve the image's aspect ratio. | 569   // This will preserve the image's aspect ratio. | 
| 561   GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, | 570   GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, | 
| 562                                                        kPreviewHeight, NULL); | 571                                                        kPreviewHeight, NULL); | 
| 563   g_free(filename); | 572   g_free(filename); | 
| 564   if (pixbuf) { | 573   if (pixbuf) { | 
| 565     gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->preview_), pixbuf); | 574     gtk_image_set_from_pixbuf(GTK_IMAGE(dialog->preview_), pixbuf); | 
| 566     g_object_unref(pixbuf); | 575     g_object_unref(pixbuf); | 
| 567   } | 576   } | 
| 568   gtk_file_chooser_set_preview_widget_active(chooser, pixbuf ? TRUE : FALSE); | 577   gtk_file_chooser_set_preview_widget_active(chooser, pixbuf ? TRUE : FALSE); | 
| 569 } | 578 } | 
| OLD | NEW | 
|---|