Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Side by Side Diff: chrome/browser/gtk/dialogs_gtk.cc

Issue 339096: Keep track of when file dialogs are destroyed. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698