| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <gdk/gdk.h> |
| 6 #include <gdk/gdkx.h> |
| 5 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 6 #include <map> | 8 #include <map> |
| 7 #include <set> | 9 #include <set> |
| 8 #include <vector> | 10 #include <vector> |
| 9 | 11 |
| 12 // Xlib defines RootWindow |
| 13 #undef RootWindow |
| 14 |
| 10 #include "base/file_util.h" | 15 #include "base/file_util.h" |
| 11 #include "base/logging.h" | 16 #include "base/logging.h" |
| 12 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
| 13 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 14 #include "base/sys_string_conversions.h" | 19 #include "base/sys_string_conversions.h" |
| 15 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
| 16 #include "base/threading/thread_restrictions.h" | 21 #include "base/threading/thread_restrictions.h" |
| 17 #include "base/utf_string_conversions.h" | 22 #include "base/utf_string_conversions.h" |
| 18 //#include "chrome/browser/ui/gtk/select_file_dialog_impl.h" | 23 #include "chrome/browser/ui/libgtk2ui/gtk2_signal.h" |
| 19 #include "chrome/browser/ui/select_file_dialog.h" | 24 #include "chrome/browser/ui/libgtk2ui/select_file_dialog_impl.h" |
| 20 #include "grit/generated_resources.h" | 25 #include "grit/ui_strings.h" |
| 21 //#include "ui/base/gtk/gtk_signal.h" | 26 #include "ui/aura/root_window.h" |
| 27 #include "ui/aura/window_observer.h" |
| 28 #include "ui/base/dialogs/select_file_dialog.h" |
| 22 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
| 23 | 30 |
| 31 namespace { |
| 32 |
| 33 const char kAuraTransientParent[] = "aura-transient-parent"; |
| 34 |
| 35 // Set |dialog| as transient for |parent|, which will keep it on top and center |
| 36 // it above |parent|. |
| 37 void SetGtkTransientForAura(GtkWidget* dialog, aura::Window* parent) { |
| 38 gtk_widget_realize(dialog); |
| 39 GdkWindow* gdk_window = gtk_widget_get_window(dialog); |
| 40 |
| 41 // TODO(erg): Check to make sure we're using X11 if wayland or some other |
| 42 // display server ever happens. Otherwise, this will crash. |
| 43 XSetTransientForHint(GDK_WINDOW_XDISPLAY(gdk_window), |
| 44 GDK_WINDOW_XID(gdk_window), |
| 45 parent->GetRootWindow()->GetAcceleratedWidget()); |
| 46 |
| 47 // We also set the |parent| as a property of |dialog|, so that we can unlink |
| 48 // the two later. |
| 49 g_object_set_data(G_OBJECT(dialog), kAuraTransientParent, parent); |
| 50 } |
| 51 |
| 52 } // namespace |
| 53 |
| 54 namespace libgtk2ui { |
| 55 |
| 24 // Implementation of SelectFileDialog that shows a Gtk common dialog for | 56 // Implementation of SelectFileDialog that shows a Gtk common dialog for |
| 25 // choosing a file or folder. This acts as a modal dialog. | 57 // choosing a file or folder. This acts as a modal dialog. |
| 26 class SelectFileDialogImplGTK : public SelectFileDialogImpl { | 58 class SelectFileDialogImplGTK : public SelectFileDialogImpl, |
| 59 public aura::WindowObserver { |
| 27 public: | 60 public: |
| 28 explicit SelectFileDialogImplGTK(Listener* listener, | 61 explicit SelectFileDialogImplGTK(Listener* listener, |
| 29 ui::SelectFilePolicy* policy); | 62 ui::SelectFilePolicy* policy); |
| 30 | 63 |
| 31 protected: | 64 protected: |
| 32 virtual ~SelectFileDialogImplGTK(); | 65 virtual ~SelectFileDialogImplGTK(); |
| 33 | 66 |
| 34 // SelectFileDialog implementation. | 67 // SelectFileDialog implementation. |
| 35 // |params| is user data we pass back via the Listener interface. | 68 // |params| is user data we pass back via the Listener interface. |
| 36 virtual void SelectFileImpl(Type type, | 69 virtual void SelectFileImpl(Type type, |
| 37 const string16& title, | 70 const string16& title, |
| 38 const FilePath& default_path, | 71 const FilePath& default_path, |
| 39 const FileTypeInfo* file_types, | 72 const FileTypeInfo* file_types, |
| 40 int file_type_index, | 73 int file_type_index, |
| 41 const FilePath::StringType& default_extension, | 74 const FilePath::StringType& default_extension, |
| 42 gfx::NativeWindow owning_window, | 75 gfx::NativeWindow owning_window, |
| 43 void* params) OVERRIDE; | 76 void* params) OVERRIDE; |
| 44 | 77 |
| 45 private: | 78 private: |
| 46 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; | 79 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; |
| 47 | 80 |
| 81 // Overridden from aura::WindowObserver: |
| 82 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; |
| 83 |
| 48 // Add the filters from |file_types_| to |chooser|. | 84 // Add the filters from |file_types_| to |chooser|. |
| 49 void AddFilters(GtkFileChooser* chooser); | 85 void AddFilters(GtkFileChooser* chooser); |
| 50 | 86 |
| 51 // Notifies the listener that a single file was chosen. | 87 // Notifies the listener that a single file was chosen. |
| 52 void FileSelected(GtkWidget* dialog, const FilePath& path); | 88 void FileSelected(GtkWidget* dialog, const FilePath& path); |
| 53 | 89 |
| 54 // Notifies the listener that multiple files were chosen. | 90 // Notifies the listener that multiple files were chosen. |
| 55 void MultiFilesSelected(GtkWidget* dialog, | 91 void MultiFilesSelected(GtkWidget* dialog, |
| 56 const std::vector<FilePath>& files); | 92 const std::vector<FilePath>& files); |
| 57 | 93 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 SelectFileDialogImplGTK::~SelectFileDialogImplGTK() { | 182 SelectFileDialogImplGTK::~SelectFileDialogImplGTK() { |
| 147 while (dialogs_.begin() != dialogs_.end()) { | 183 while (dialogs_.begin() != dialogs_.end()) { |
| 148 gtk_widget_destroy(*(dialogs_.begin())); | 184 gtk_widget_destroy(*(dialogs_.begin())); |
| 149 } | 185 } |
| 150 } | 186 } |
| 151 | 187 |
| 152 bool SelectFileDialogImplGTK::HasMultipleFileTypeChoicesImpl() { | 188 bool SelectFileDialogImplGTK::HasMultipleFileTypeChoicesImpl() { |
| 153 return file_types_.extensions.size() > 1; | 189 return file_types_.extensions.size() > 1; |
| 154 } | 190 } |
| 155 | 191 |
| 192 void SelectFileDialogImplGTK::OnWindowDestroying(aura::Window* window) { |
| 193 std::set<aura::Window*>::iterator iter = parents_.find(window); |
| 194 if (iter != parents_.end()) { |
| 195 (*iter)->RemoveObserver(this); |
| 196 parents_.erase(iter); |
| 197 } |
| 198 } |
| 199 |
| 156 // We ignore |default_extension|. | 200 // We ignore |default_extension|. |
| 157 void SelectFileDialogImplGTK::SelectFileImpl( | 201 void SelectFileDialogImplGTK::SelectFileImpl( |
| 158 Type type, | 202 Type type, |
| 159 const string16& title, | 203 const string16& title, |
| 160 const FilePath& default_path, | 204 const FilePath& default_path, |
| 161 const FileTypeInfo* file_types, | 205 const FileTypeInfo* file_types, |
| 162 int file_type_index, | 206 int file_type_index, |
| 163 const FilePath::StringType& default_extension, | 207 const FilePath::StringType& default_extension, |
| 164 gfx::NativeWindow owning_window, | 208 gfx::NativeWindow owning_window, |
| 165 void* params) { | 209 void* params) { |
| 166 type_ = type; | 210 type_ = type; |
| 167 // |owning_window| can be null when user right-clicks on a downloadable item | 211 // |owning_window| can be null when user right-clicks on a downloadable item |
| 168 // and chooses 'Open Link in New Tab' when 'Ask where to save each file | 212 // and chooses 'Open Link in New Tab' when 'Ask where to save each file |
| 169 // before downloading.' preference is turned on. (http://crbug.com/29213) | 213 // before downloading.' preference is turned on. (http://crbug.com/29213) |
| 170 if (owning_window) | 214 if (owning_window) { |
| 215 owning_window->AddObserver(this); |
| 171 parents_.insert(owning_window); | 216 parents_.insert(owning_window); |
| 217 } |
| 172 | 218 |
| 173 std::string title_string = UTF16ToUTF8(title); | 219 std::string title_string = UTF16ToUTF8(title); |
| 174 | 220 |
| 175 file_type_index_ = file_type_index; | 221 file_type_index_ = file_type_index; |
| 176 if (file_types) | 222 if (file_types) |
| 177 file_types_ = *file_types; | 223 file_types_ = *file_types; |
| 178 else | 224 else |
| 179 file_types_.include_all_files = true; | 225 file_types_.include_all_files = true; |
| 180 | 226 |
| 181 GtkWidget* dialog = NULL; | 227 GtkWidget* dialog = NULL; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 204 | 250 |
| 205 preview_ = gtk_image_new(); | 251 preview_ = gtk_image_new(); |
| 206 g_signal_connect(dialog, "destroy", | 252 g_signal_connect(dialog, "destroy", |
| 207 G_CALLBACK(OnFileChooserDestroyThunk), this); | 253 G_CALLBACK(OnFileChooserDestroyThunk), this); |
| 208 g_signal_connect(dialog, "update-preview", | 254 g_signal_connect(dialog, "update-preview", |
| 209 G_CALLBACK(OnUpdatePreviewThunk), this); | 255 G_CALLBACK(OnUpdatePreviewThunk), this); |
| 210 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); | 256 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); |
| 211 | 257 |
| 212 params_map_[dialog] = params; | 258 params_map_[dialog] = params; |
| 213 | 259 |
| 214 // Set window-to-parent modality by adding the dialog to the same window | 260 // TODO(erg): Figure out how to fake GTK window-to-parent modality without |
| 215 // group as the parent. | 261 // having the parent be a real GtkWindow. |
| 216 gtk_window_group_add_window(gtk_window_get_group(owning_window), | |
| 217 GTK_WINDOW(dialog)); | |
| 218 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); | 262 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); |
| 219 | 263 |
| 220 gtk_widget_show_all(dialog); | 264 gtk_widget_show_all(dialog); |
| 221 } | 265 } |
| 222 | 266 |
| 223 void SelectFileDialogImplGTK::AddFilters(GtkFileChooser* chooser) { | 267 void SelectFileDialogImplGTK::AddFilters(GtkFileChooser* chooser) { |
| 224 for (size_t i = 0; i < file_types_.extensions.size(); ++i) { | 268 for (size_t i = 0; i < file_types_.extensions.size(); ++i) { |
| 225 GtkFileFilter* filter = NULL; | 269 GtkFileFilter* filter = NULL; |
| 226 std::set<std::string> fallback_labels; | 270 std::set<std::string> fallback_labels; |
| 227 | 271 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 if (listener_) | 347 if (listener_) |
| 304 listener_->FileSelectionCanceled(params); | 348 listener_->FileSelectionCanceled(params); |
| 305 gtk_widget_destroy(dialog); | 349 gtk_widget_destroy(dialog); |
| 306 } | 350 } |
| 307 | 351 |
| 308 GtkWidget* SelectFileDialogImplGTK::CreateFileOpenHelper( | 352 GtkWidget* SelectFileDialogImplGTK::CreateFileOpenHelper( |
| 309 const std::string& title, | 353 const std::string& title, |
| 310 const FilePath& default_path, | 354 const FilePath& default_path, |
| 311 gfx::NativeWindow parent) { | 355 gfx::NativeWindow parent) { |
| 312 GtkWidget* dialog = | 356 GtkWidget* dialog = |
| 313 gtk_file_chooser_dialog_new(title.c_str(), parent, | 357 gtk_file_chooser_dialog_new(title.c_str(), NULL, |
| 314 GTK_FILE_CHOOSER_ACTION_OPEN, | 358 GTK_FILE_CHOOSER_ACTION_OPEN, |
| 315 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | 359 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| 316 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | 360 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
| 317 NULL); | 361 NULL); |
| 362 SetGtkTransientForAura(dialog, parent); |
| 318 AddFilters(GTK_FILE_CHOOSER(dialog)); | 363 AddFilters(GTK_FILE_CHOOSER(dialog)); |
| 319 | 364 |
| 320 if (!default_path.empty()) { | 365 if (!default_path.empty()) { |
| 321 if (CallDirectoryExistsOnUIThread(default_path)) { | 366 if (CallDirectoryExistsOnUIThread(default_path)) { |
| 322 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 367 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
| 323 default_path.value().c_str()); | 368 default_path.value().c_str()); |
| 324 } else { | 369 } else { |
| 325 // If the file doesn't exist, this will just switch to the correct | 370 // If the file doesn't exist, this will just switch to the correct |
| 326 // directory. That's good enough. | 371 // directory. That's good enough. |
| 327 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), | 372 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), |
| 328 default_path.value().c_str()); | 373 default_path.value().c_str()); |
| 329 } | 374 } |
| 330 } else if (!last_opened_path_->empty()) { | 375 } else if (!last_opened_path_->empty()) { |
| 331 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 376 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
| 332 last_opened_path_->value().c_str()); | 377 last_opened_path_->value().c_str()); |
| 333 } | 378 } |
| 334 return dialog; | 379 return dialog; |
| 335 } | 380 } |
| 336 | 381 |
| 337 GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog( | 382 GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog( |
| 338 const std::string& title, | 383 const std::string& title, |
| 339 const FilePath& default_path, | 384 const FilePath& default_path, |
| 340 gfx::NativeWindow parent) { | 385 gfx::NativeWindow parent) { |
| 341 std::string title_string = !title.empty() ? title : | 386 std::string title_string = !title.empty() ? title : |
| 342 l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); | 387 l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); |
| 343 | 388 |
| 344 GtkWidget* dialog = | 389 GtkWidget* dialog = |
| 345 gtk_file_chooser_dialog_new(title_string.c_str(), parent, | 390 gtk_file_chooser_dialog_new(title_string.c_str(), NULL, |
| 346 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, | 391 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, |
| 347 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | 392 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| 348 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | 393 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
| 349 NULL); | 394 NULL); |
| 395 SetGtkTransientForAura(dialog, parent); |
| 350 | 396 |
| 351 if (!default_path.empty()) { | 397 if (!default_path.empty()) { |
| 352 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), | 398 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), |
| 353 default_path.value().c_str()); | 399 default_path.value().c_str()); |
| 354 } else if (!last_opened_path_->empty()) { | 400 } else if (!last_opened_path_->empty()) { |
| 355 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 401 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
| 356 last_opened_path_->value().c_str()); | 402 last_opened_path_->value().c_str()); |
| 357 } | 403 } |
| 358 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); | 404 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); |
| 359 g_signal_connect(dialog, "response", | 405 g_signal_connect(dialog, "response", |
| (...skipping 28 matching lines...) Expand all Loading... |
| 388 G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this); | 434 G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this); |
| 389 return dialog; | 435 return dialog; |
| 390 } | 436 } |
| 391 | 437 |
| 392 GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog(const std::string& title, | 438 GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog(const std::string& title, |
| 393 const FilePath& default_path, gfx::NativeWindow parent) { | 439 const FilePath& default_path, gfx::NativeWindow parent) { |
| 394 std::string title_string = !title.empty() ? title : | 440 std::string title_string = !title.empty() ? title : |
| 395 l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE); | 441 l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE); |
| 396 | 442 |
| 397 GtkWidget* dialog = | 443 GtkWidget* dialog = |
| 398 gtk_file_chooser_dialog_new(title_string.c_str(), parent, | 444 gtk_file_chooser_dialog_new(title_string.c_str(), NULL, |
| 399 GTK_FILE_CHOOSER_ACTION_SAVE, | 445 GTK_FILE_CHOOSER_ACTION_SAVE, |
| 400 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | 446 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| 401 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, | 447 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, |
| 402 NULL); | 448 NULL); |
| 449 SetGtkTransientForAura(dialog, parent); |
| 403 | 450 |
| 404 AddFilters(GTK_FILE_CHOOSER(dialog)); | 451 AddFilters(GTK_FILE_CHOOSER(dialog)); |
| 405 if (!default_path.empty()) { | 452 if (!default_path.empty()) { |
| 406 // Since the file may not already exist, we use | 453 // Since the file may not already exist, we use |
| 407 // set_current_folder() followed by set_current_name(), as per the | 454 // set_current_folder() followed by set_current_name(), as per the |
| 408 // recommendation of the GTK docs. | 455 // recommendation of the GTK docs. |
| 409 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 456 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
| 410 default_path.DirName().value().c_str()); | 457 default_path.DirName().value().c_str()); |
| 411 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), | 458 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), |
| 412 default_path.BaseName().value().c_str()); | 459 default_path.BaseName().value().c_str()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 431 } | 478 } |
| 432 | 479 |
| 433 void SelectFileDialogImplGTK::FileDialogDestroyed(GtkWidget* dialog) { | 480 void SelectFileDialogImplGTK::FileDialogDestroyed(GtkWidget* dialog) { |
| 434 dialogs_.erase(dialog); | 481 dialogs_.erase(dialog); |
| 435 | 482 |
| 436 // Parent may be NULL in a few cases: 1) on shutdown when | 483 // Parent may be NULL in a few cases: 1) on shutdown when |
| 437 // AllBrowsersClosed() trigger this handler after all the browser | 484 // AllBrowsersClosed() trigger this handler after all the browser |
| 438 // windows got destroyed, or 2) when the parent tab has been opened by | 485 // windows got destroyed, or 2) when the parent tab has been opened by |
| 439 // 'Open Link in New Tab' context menu on a downloadable item and | 486 // 'Open Link in New Tab' context menu on a downloadable item and |
| 440 // the tab has no content (see the comment in SelectFile as well). | 487 // the tab has no content (see the comment in SelectFile as well). |
| 441 GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(dialog)); | 488 aura::Window* parent = reinterpret_cast<aura::Window*>( |
| 489 g_object_get_data(G_OBJECT(dialog), kAuraTransientParent)); |
| 442 if (!parent) | 490 if (!parent) |
| 443 return; | 491 return; |
| 444 std::set<GtkWindow*>::iterator iter = parents_.find(parent); | 492 std::set<aura::Window*>::iterator iter = parents_.find(parent); |
| 445 if (iter != parents_.end()) | 493 if (iter != parents_.end()) { |
| 494 (*iter)->RemoveObserver(this); |
| 446 parents_.erase(iter); | 495 parents_.erase(iter); |
| 447 else | 496 } else { |
| 448 NOTREACHED(); | 497 NOTREACHED(); |
| 498 } |
| 449 } | 499 } |
| 450 | 500 |
| 451 bool SelectFileDialogImplGTK::IsCancelResponse(gint response_id) { | 501 bool SelectFileDialogImplGTK::IsCancelResponse(gint response_id) { |
| 452 bool is_cancel = response_id == GTK_RESPONSE_CANCEL || | 502 bool is_cancel = response_id == GTK_RESPONSE_CANCEL || |
| 453 response_id == GTK_RESPONSE_DELETE_EVENT; | 503 response_id == GTK_RESPONSE_DELETE_EVENT; |
| 454 if (is_cancel) | 504 if (is_cancel) |
| 455 return true; | 505 return true; |
| 456 | 506 |
| 457 DCHECK(response_id == GTK_RESPONSE_ACCEPT); | 507 DCHECK(response_id == GTK_RESPONSE_ACCEPT); |
| 458 return false; | 508 return false; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, | 589 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, |
| 540 kPreviewHeight, NULL); | 590 kPreviewHeight, NULL); |
| 541 g_free(filename); | 591 g_free(filename); |
| 542 if (pixbuf) { | 592 if (pixbuf) { |
| 543 gtk_image_set_from_pixbuf(GTK_IMAGE(preview_), pixbuf); | 593 gtk_image_set_from_pixbuf(GTK_IMAGE(preview_), pixbuf); |
| 544 g_object_unref(pixbuf); | 594 g_object_unref(pixbuf); |
| 545 } | 595 } |
| 546 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), | 596 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), |
| 547 pixbuf ? TRUE : FALSE); | 597 pixbuf ? TRUE : FALSE); |
| 548 } | 598 } |
| 599 |
| 600 } // namespace libgtk2ui |
| OLD | NEW |