2
* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; version 2 of the
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21
#if defined(HAVE_GNOME_KEYRING) || defined(HAVE_OLD_GNOME_KEYRING)
23
#include <gnome-keyring.h>
29
#include <glib/gstdio.h>
30
#include <sys/prctl.h>
34
#include "../lf_mforms.h"
36
#include "base/file_functions.h"
37
#include "base/file_utilities.h"
39
#include "base/string_utilities.h"
40
#include "../lf_utilities.h"
41
#include "gtk_helpers.h"
48
* Get the current active window for this application
50
GtkWindow *get_current_window()
52
GList *window_list = gtk_window_list_toplevels();
55
GtkWindow *wnd = (GtkWindow *)window_list->data;
57
if (gtk_window_is_active(wnd))
59
} while((window_list = g_list_next(window_list)) != NULL);
65
* Try to set this dialog as transcient to the parent window. Setting this
66
* to the main window could stick this dialog to the wrong window (leaving
67
* a window in between them in the cases like popping a dialog in the
69
* To find the proper parent window, we're searching for the current active window
70
* on this application.
72
void set_dialog_transcient(Gtk::MessageDialog &dialog)
74
GtkWindow *parent_window = get_current_window();
76
// Check if a parent was found and only set transcient if it was. Passing
77
// a NULL parent would remove the transcient flag.
78
if (get_current_window() != NULL)
79
gtk_window_set_transient_for(((Gtk::Window *)&dialog)->gobj(), parent_window);
81
//--------------------------------------------------------------------------------
84
int UtilitiesImpl::show_message(const std::string &title, const std::string &text,
85
const std::string &ok, const std::string &cancel,
86
const std::string &other)
88
Gtk::MessageDialog dlg("<b>"+title+"</b>", true,
89
Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE, true);
90
dlg.set_secondary_text(text);
91
dlg.add_button(ok, mforms::ResultOk);
93
dlg.add_button(cancel, mforms::ResultCancel);
95
dlg.add_button(other, mforms::ResultOther);
97
set_dialog_transcient(dlg);
100
if (r == Gtk::RESPONSE_DELETE_EVENT)
101
return mforms::ResultCancel;
106
int UtilitiesImpl::show_error(const std::string &title, const std::string &text,
107
const std::string &ok, const std::string &cancel,
108
const std::string &other)
110
Gtk::MessageDialog dlg("<b>"+title+"</b>", true,
111
Gtk::MESSAGE_ERROR, Gtk::BUTTONS_NONE, true);
112
dlg.set_secondary_text(text);
113
dlg.add_button(ok, mforms::ResultOk);
115
dlg.add_button(cancel, mforms::ResultCancel);
117
dlg.add_button(other, mforms::ResultOther);
119
set_dialog_transcient(dlg);
122
if (r == Gtk::RESPONSE_DELETE_EVENT)
123
return mforms::ResultCancel;
127
int UtilitiesImpl::show_warning(const std::string &title, const std::string &text,
128
const std::string &ok, const std::string &cancel,
129
const std::string &other)
131
Gtk::MessageDialog dlg("<b>"+title+"</b>", true,
132
Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE, true);
133
dlg.set_secondary_text(text);
134
dlg.add_button(ok, mforms::ResultOk);
136
dlg.add_button(cancel, mforms::ResultCancel);
138
dlg.add_button(other, mforms::ResultOther);
140
set_dialog_transcient(dlg);
143
if (r == Gtk::RESPONSE_DELETE_EVENT)
144
return mforms::ResultCancel;
148
static void handle_click(Gtk::CheckButton* btn, bool* state)
150
*state = btn->get_active();
153
int UtilitiesImpl::show_message_with_checkbox(const std::string &title, const std::string &text,
154
const std::string &ok, const std::string &cancel,
155
const std::string &other,
156
const std::string &checkbox_text, // empty text = default "Don't show this message again" text
157
bool &remember_checked)
159
Gtk::MessageDialog dlg("<b>"+title+"</b>", true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true);
160
dlg.set_secondary_text(text);
162
Gtk::CheckButton* btn = Gtk::manage(new Gtk::CheckButton(checkbox_text.empty() ? "Don't show this message again" : checkbox_text));
163
dlg.get_vbox()->pack_start(*btn, false, true);
164
btn->set_active(remember_checked);
165
btn->signal_clicked().connect(sigc::bind(sigc::ptr_fun(handle_click), btn, &remember_checked));
167
Gtk::Button *ok_btn = Gtk::manage(new Gtk::Button(ok));
168
dlg.add_action_widget(*ok_btn, mforms::ResultOk);
171
dlg.add_action_widget(*Gtk::manage(new Gtk::Button(cancel)), mforms::ResultCancel);
173
dlg.add_action_widget(*Gtk::manage(new Gtk::Button(other)), mforms::ResultOther);
176
set_dialog_transcient(dlg);
179
if (r == Gtk::RESPONSE_DELETE_EVENT)
180
return mforms::ResultCancel;
184
void UtilitiesImpl::set_clipboard_text(const std::string &text)
186
Gtk::Clipboard::get()->set_text(text);
189
std::string UtilitiesImpl::get_clipboard_text()
191
return Gtk::Clipboard::get()->wait_for_text();
194
void UtilitiesImpl::open_url(const std::string &url)
196
char *quoted_url = g_uri_escape_string(url.c_str(),
197
G_URI_RESERVED_CHARS_GENERIC_DELIMITERS
198
G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS,
201
const gchar *argv[] = {
206
GError *error = NULL;
207
gboolean result = g_spawn_async(NULL, (gchar**)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error);
213
char *err = g_strdup_printf("Error opening url with xdg-open: %s", error->message);
215
std::runtime_error exc(err);
221
std::string UtilitiesImpl::get_special_folder(mforms::FolderType type)
228
case mforms::Documents:
229
#if GTK_VERSION_GT(2,10)
230
t = g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS);
234
case mforms::Desktop:
235
#if GTK_VERSION_GT(2,10)
236
t = g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP);
239
t = g_strdup_printf("%s/Desktop", g_get_home_dir());
244
case mforms::ApplicationData:
245
path = g_get_home_dir();
247
case mforms::ApplicationSettings:
248
path = g_get_home_dir();
249
path.append("/.mysql/workbench");
251
case WinProgramFiles:
252
case WinProgramFilesX86:
258
t = g_get_home_dir();
261
return path.empty() ? "~" : path;
264
//------------------------------------------------------------------------------
265
static std::map<TimeoutHandle, sigc::connection> timeouts;
266
static TimeoutHandle last_timeout_handle = 0;
267
static base::Mutex timeout_mutex;
269
inline bool run_slot(const boost::function<bool ()> slot, TimeoutHandle handle)
272
base::MutexLock lock(timeout_mutex);
273
std::map<TimeoutHandle, sigc::connection>::iterator it;
274
if ((it = timeouts.find(handle)) != timeouts.end())
280
//------------------------------------------------------------------------------
281
TimeoutHandle UtilitiesImpl::add_timeout(float interval, const boost::function<bool ()> &slot)
287
base::MutexLock lock(timeout_mutex);
288
++last_timeout_handle;
289
timeouts[last_timeout_handle] = Glib::signal_timeout().connect(sigc::bind(sigc::ptr_fun(run_slot), slot, last_timeout_handle), interval*1000);
290
return last_timeout_handle;
293
catch (std::exception &exc)
295
static const char* const default_log_domain = "Utilities";
296
log_exception("Utilities: exception in add timeout function", exc);
302
void UtilitiesImpl::cancel_timeout(TimeoutHandle h)
304
base::MutexLock lock(timeout_mutex);
305
std::map<TimeoutHandle, sigc::connection>::iterator it;
306
if ((it = timeouts.find(h)) != timeouts.end())
308
it->second.disconnect();
314
//------------------------------------------------------------------------------
315
// GNOME KEYRING passwords section
316
#ifdef HAVE_GNOME_KEYRING
317
//------------------------------------------------------------------------------
318
void UtilitiesImpl::store_password(const std::string &service, const std::string &account, const std::string &password)
320
if (getenv("WB_NO_GNOME_KEYRING"))
325
GnomeKeyringPasswordSchema wb_pwd_schema;
326
memset(&wb_pwd_schema, 0, sizeof(wb_pwd_schema));
328
wb_pwd_schema.item_type = GNOME_KEYRING_ITEM_GENERIC_SECRET;
329
wb_pwd_schema.attributes[0].name = "service";
330
wb_pwd_schema.attributes[0].type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
331
wb_pwd_schema.attributes[1].name = "account";
332
wb_pwd_schema.attributes[1].type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
333
// attributes list must be terminated by a pair {0,0}, since we zeroed the whole struct we're safe here
335
GnomeKeyringResult res = gnome_keyring_store_password_sync(&wb_pwd_schema,
336
NULL, // using default keyring
339
"service", service.c_str(),
340
"account", account.c_str(),
344
if ( res != GNOME_KEYRING_RESULT_OK )
345
throw std::runtime_error(gnome_keyring_result_to_message(res));
348
//------------------------------------------------------------------------------
349
bool UtilitiesImpl::find_password(const std::string &service, const std::string &account, std::string &password)
351
if (getenv("WB_NO_GNOME_KEYRING"))
358
GnomeKeyringPasswordSchema wb_pwd_schema;
359
memset(&wb_pwd_schema, 0, sizeof(wb_pwd_schema));
361
wb_pwd_schema.item_type = GNOME_KEYRING_ITEM_GENERIC_SECRET;
362
wb_pwd_schema.attributes[0].name = "service";
363
wb_pwd_schema.attributes[0].type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
364
wb_pwd_schema.attributes[1].name = "account";
365
wb_pwd_schema.attributes[1].type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
366
// attributes list must be terminated by a pair {0,0}, since we zeroed the whole struct we're safe here
370
GnomeKeyringResult res = gnome_keyring_find_password_sync(&wb_pwd_schema,
372
"service", service.c_str(),
373
"account", account.c_str(),
376
if ( res != GNOME_KEYRING_RESULT_OK && res != GNOME_KEYRING_RESULT_NO_MATCH )
379
gnome_keyring_free_password(kpwd);
381
throw std::runtime_error(gnome_keyring_result_to_message(res));
384
if (kpwd && res == GNOME_KEYRING_RESULT_OK)
388
gnome_keyring_free_password(kpwd);
395
//------------------------------------------------------------------------------
396
void UtilitiesImpl::forget_password(const std::string &service, const std::string &account)
398
if (getenv("WB_NO_GNOME_KEYRING"))
403
GnomeKeyringPasswordSchema wb_pwd_schema;
404
memset(&wb_pwd_schema, 0, sizeof(wb_pwd_schema));
406
wb_pwd_schema.item_type = GNOME_KEYRING_ITEM_GENERIC_SECRET;
407
wb_pwd_schema.attributes[0].name = "service";
408
wb_pwd_schema.attributes[0].type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
409
wb_pwd_schema.attributes[1].name = "account";
410
wb_pwd_schema.attributes[1].type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
411
// attributes list must be terminated by a pair {0,0}, since we zeroed the whole struct we're safe here
413
GnomeKeyringResult res = gnome_keyring_delete_password_sync(&wb_pwd_schema,
414
"service", service.c_str(),
415
"account", account.c_str(),
418
if ( res != GNOME_KEYRING_RESULT_OK && res != GNOME_KEYRING_RESULT_NO_MATCH)
419
throw std::runtime_error(std::string("forget_password ") + gnome_keyring_result_to_message(res));
422
#elif defined(HAVE_OLD_GNOME_KEYRING)
424
//------------------------------------------------------------------------------
425
enum {Gnome_keyring_results_size = 10};
426
static const char* gnome_keyring_results[Gnome_keyring_results_size] = {"OK",
427
"GNOME_KEYRING_RESULT_DENIED",
428
"GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON",
429
"GNOME_KEYRING_RESULT_ALREADY_UNLOCKED",
430
"GNOME_KEYRING_RESULT_NO_SUCH_KEYRING",
431
"GNOME_KEYRING_RESULT_BAD_ARGUMENTS",
432
"GNOME_KEYRING_RESULT_IO_ERROR",
433
"GNOME_KEYRING_RESULT_CANCELLED",
434
"GNOME_KEYRING_RESULT_ALREADY_EXISTS",
438
//------------------------------------------------------------------------------
439
static const char* gnome_keyring_result_to_message(const GnomeKeyringResult result)
441
const char* message = gnome_keyring_results[Gnome_keyring_results_size - 1];
443
if (result >= 0 && result < (GnomeKeyringResult)Gnome_keyring_results_size)
444
message = gnome_keyring_results[result];
449
//------------------------------------------------------------------------------
450
void UtilitiesImpl::store_password(const std::string &service, const std::string &account, const std::string &password)
452
if (getenv("WB_NO_GNOME_KEYRING"))
457
GnomeKeyringAttributeList *attrs = gnome_keyring_attribute_list_new();
460
gnome_keyring_attribute_list_append_string(attrs, "service", service.c_str());
461
gnome_keyring_attribute_list_append_string(attrs, "account", account.c_str());
463
const GnomeKeyringResult result = gnome_keyring_item_create_sync(NULL,
464
GNOME_KEYRING_ITEM_GENERIC_SECRET,
471
gnome_keyring_attribute_list_free(attrs);
473
if ( result != GNOME_KEYRING_RESULT_OK )
474
throw std::runtime_error(gnome_keyring_result_to_message(result));
477
//------------------------------------------------------------------------------
478
static guint32 find_password_and_id(const std::string &service, const std::string &account, std::string &password)
482
GnomeKeyringAttributeList *attrs = gnome_keyring_attribute_list_new();
484
gnome_keyring_attribute_list_append_string(attrs, "service", service.c_str());
485
gnome_keyring_attribute_list_append_string(attrs, "account", account.c_str());
487
GList* found_items = 0;
489
const GnomeKeyringResult result = gnome_keyring_find_items_sync(GNOME_KEYRING_ITEM_GENERIC_SECRET,
493
if (result != GNOME_KEYRING_RESULT_OK)
496
gnome_keyring_found_list_free(found_items);
497
throw std::runtime_error(gnome_keyring_result_to_message(result));
500
if (g_list_length(found_items) > 0)
502
GnomeKeyringFound* item = (GnomeKeyringFound*)g_list_first(found_items);
503
password = item->secret;
508
gnome_keyring_found_list_free(found_items);
513
//------------------------------------------------------------------------------
514
bool UtilitiesImpl::find_password(const std::string &service, const std::string &account, std::string &password)
516
if (getenv("WB_NO_GNOME_KEYRING"))
521
return find_password_and_id(service, account, password);
524
//------------------------------------------------------------------------------
525
void UtilitiesImpl::forget_password(const std::string &service, const std::string &account)
527
if (getenv("WB_NO_GNOME_KEYRING"))
532
std::string password;
533
const guint32 item_id = find_password_and_id(service, account, password);
535
GnomeKeyringResult res = GNOME_KEYRING_RESULT_BAD_ARGUMENTS;
537
res = gnome_keyring_item_delete_sync(NULL, item_id);
539
if ( res != GNOME_KEYRING_RESULT_OK )
540
throw std::runtime_error(gnome_keyring_result_to_message(res));
544
void UtilitiesImpl::store_password(const std::string &service, const std::string &account, const std::string &password)
548
bool UtilitiesImpl::find_password(const std::string &service, const std::string &account, std::string &password)
550
g_message("no gnome keyring support");
554
void UtilitiesImpl::forget_password(const std::string &service, const std::string &account)
558
#endif // !USE_KEYRING
560
// Disabled in linux, as it useless here due to weird popup times
561
// It may not appear at all, or may appear at the end of WBA start
562
// or it may be displayed at the beginning of WBA start and get overlapped
563
// by password request dialog
564
#define USE_TRANSPARENT_MESSAGE
566
#define MESSAGE_WINDOW_WIDTH 450
567
#define MESSAGE_WINDOW_HEIGHT 220
569
#ifdef USE_TRANSPARENT_MESSAGE
570
//==============================================================================
572
//==============================================================================
573
class TransparentMessage : public Gtk::Window
576
TransparentMessage();
577
void show_message(const std::string& title, const std::string& text, const sigc::slot<bool> &cancel_slot=sigc::slot<bool>());
583
Gtk::Button *cancel_button;
584
sigc::slot<bool> cancel_slot;
588
virtual bool on_button_release_event(GdkEventButton* ev);
589
void cancel_clicked();
592
//------------------------------------------------------------------------------
593
TransparentMessage::TransparentMessage()
594
: response(false), _is_runing(false)
596
Gtk::Window *owner = get_mainwindow();
599
set_transient_for(*owner);
600
set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
603
set_position(Gtk::WIN_POS_CENTER);
606
property_skip_taskbar_hint() = true;
607
property_skip_pager_hint() = true;
608
property_decorated() = false;
610
set_size_request(MESSAGE_WINDOW_WIDTH, MESSAGE_WINDOW_HEIGHT);
612
set_style(get_style()->copy());
615
Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(false, 0));
616
vbox->set_border_width(20);
619
Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, 12));
620
vbox->pack_end(*hbox, false, false);
622
cancel_button = Gtk::manage(new Gtk::Button("Cancel"));
623
hbox->pack_end(*cancel_button, false, true);
626
cancel_button->signal_clicked().connect(sigc::mem_fun(this, &TransparentMessage::cancel_clicked));
630
//------------------------------------------------------------------------------
631
void TransparentMessage::show_message(const std::string& title, const std::string& text, const sigc::slot<bool> &cancel_slot)
633
this->cancel_slot = cancel_slot;
635
cancel_button->show();
638
cancel_button->hide();
639
add_events(Gdk::BUTTON_RELEASE_MASK);
644
Gdk::Color black("black"), white("white");
645
black.rgb_find_color(get_colormap());
646
white.rgb_find_color(get_colormap());
648
Glib::RefPtr<Gdk::Pixmap> pixmap = Gdk::Pixmap::create(get_window(),
649
MESSAGE_WINDOW_WIDTH, MESSAGE_WINDOW_HEIGHT,
650
get_window()->get_depth());
652
Glib::RefPtr<Gdk::GC> gc = Gdk::GC::create(pixmap);
654
gc->set_foreground(white);
655
pixmap->draw_rectangle(gc, false, 0, 0, MESSAGE_WINDOW_WIDTH-1, MESSAGE_WINDOW_HEIGHT-1);
657
gc->set_foreground(black);
658
pixmap->draw_rectangle(gc, true, 2, 2, MESSAGE_WINDOW_WIDTH-3, MESSAGE_WINDOW_HEIGHT-3);
661
Glib::RefPtr<Gdk::Pixbuf> icon = Gdk::Pixbuf::create_from_file(App::get()->get_resource_path("message_wb_wait.png"));
663
pixmap->draw_pixbuf(gc, icon, 0, 0, 20, 20, icon->get_width(), icon->get_height(),
664
Gdk::RGB_DITHER_NORMAL, 0, 0);
666
Glib::RefPtr<Pango::Layout> layout = create_pango_layout(title);
668
gc->set_foreground(white);
670
layout->set_font_description(Pango::FontDescription("Bitstream Vera Sans,Helvetica, bold 14"));
671
layout->set_width((MESSAGE_WINDOW_WIDTH-icon->get_width()-30-20)*Pango::SCALE);
672
pixmap->draw_layout(gc, icon->get_width()+30, 40, layout);
675
layout = create_pango_layout(text);
676
layout->set_font_description(Pango::FontDescription("Bitstream Vera Sans,Helvetica, 9"));
677
layout->set_width((MESSAGE_WINDOW_WIDTH-icon->get_width()-30-20)*Pango::SCALE);
678
pixmap->draw_layout(gc, icon->get_width()+30, 90, layout);
680
get_style()->set_bg_pixmap(Gtk::STATE_NORMAL, pixmap);
681
Glib::RefPtr<Gdk::Window> window = get_window();
682
#if GTK_VERSION_GE(2,12)
683
window->set_opacity(0.85);
685
window->process_updates(true);
689
void TransparentMessage::run()
695
//------------------------------------------------------------------------------
696
void TransparentMessage::stop()
698
Glib::Mutex::Lock lock(mutex);
702
running_modal = false;
713
void TransparentMessage::cancel_clicked()
715
Glib::Mutex::Lock lock(mutex);
716
if (cancel_slot && cancel_slot())
721
running_modal = false;
733
//------------------------------------------------------------------------------
734
bool TransparentMessage::on_button_release_event(GdkEventButton* ev)
740
static TransparentMessage *tm = 0;
741
static TransparentMessage *tmc = 0;
744
//------------------------------------------------------------------------------
745
void UtilitiesImpl::show_wait_message(const std::string &title, const std::string &text)
747
#ifdef USE_TRANSPARENT_MESSAGE
749
tm = new TransparentMessage();
752
tm->show_message(title, text);
756
//------------------------------------------------------------------------------
757
bool UtilitiesImpl::hide_wait_message()
759
#ifdef USE_TRANSPARENT_MESSAGE
771
//-------------------------------------------------------------------------------
773
bool UtilitiesImpl::move_to_trash(const std::string &path)
775
// trash in linux is chaos, just delete it
776
if (g_file_test(path.c_str(), G_FILE_TEST_IS_DIR))
777
base_rmdir_recursively(path.c_str());
779
g_remove(path.c_str());
784
//------------------------------------------------------------------------------
785
void UtilitiesImpl::reveal_file(const std::string &path)
787
const gchar *argv[] = {
789
base::dirname(path).c_str(),
792
GError *error = NULL;
793
if (!g_spawn_async(NULL, (gchar**)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error))
795
char *err = g_strdup_printf("Error opening folder with xdg-open: %s", error->message);
797
std::runtime_error exc(err);
805
void UtilitiesImpl::set_thread_name(const std::string &name)
808
prctl(PR_SET_NAME, name.c_str(),0,0,0);
811
//------------------------------------------------------------------------------
814
bool UtilitiesImpl::run_cancelable_wait_message(const std::string &title, const std::string &text,
815
const boost::function<void ()> &start_task, const boost::function<bool ()> &cancel_task)
818
throw std::invalid_argument("start_task param cannot be empty");
821
tmc = new TransparentMessage();
824
tmc->show_message(title, text, sigc::mem_fun(&cancel_task,&boost::function<bool ()>::operator()));
825
tmc->running_modal = true;
827
Glib::signal_idle().connect(sigc::bind_return(start_task, false));
830
bool response = tmc->response;
840
void UtilitiesImpl::stop_cancelable_wait_message()
844
if (Utilities::in_main_thread())
847
Utilities::perform_from_main_thread(sigc::bind_return(sigc::mem_fun(tmc, &TransparentMessage::stop), (void*)NULL));
852
Glib::RefPtr<Gdk::Pixbuf> UtilitiesImpl::get_cached_icon(const std::string &icon)
854
std::map<std::string, Glib::RefPtr<Gdk::Pixbuf> > cache;
856
if (cache.find(icon) != cache.end())
859
if (icon == "folder")
861
Glib::RefPtr<Gdk::Pixbuf> pix = get_mainwindow()->render_icon(Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU);
867
std::string path = mforms::App::get()->get_resource_path(icon);
868
if (!path.empty() && g_file_test(path.c_str(), G_FILE_TEST_IS_REGULAR))
870
cache[icon] = Gdk::Pixbuf::create_from_file(path);
874
g_warning("Can't find icon %s", icon.c_str());
876
return Glib::RefPtr<Gdk::Pixbuf>();
880
//------------------------------------------------------------------------------
882
void UtilitiesImpl::init()
884
::mforms::ControlFactory *f = ::mforms::ControlFactory::get_instance();
886
f->_utilities_impl.show_message= &UtilitiesImpl::show_message;
887
f->_utilities_impl.show_error= &UtilitiesImpl::show_error;
888
f->_utilities_impl.show_warning= &UtilitiesImpl::show_warning;
889
f->_utilities_impl.show_message_with_checkbox= &UtilitiesImpl::show_message_with_checkbox;
890
f->_utilities_impl.show_wait_message= &UtilitiesImpl::show_wait_message;
891
f->_utilities_impl.hide_wait_message= &UtilitiesImpl::hide_wait_message;
892
f->_utilities_impl.run_cancelable_wait_message= &UtilitiesImpl::run_cancelable_wait_message;
893
f->_utilities_impl.stop_cancelable_wait_message= &UtilitiesImpl::stop_cancelable_wait_message;
895
f->_utilities_impl.set_clipboard_text= &UtilitiesImpl::set_clipboard_text;
896
f->_utilities_impl.get_clipboard_text= &UtilitiesImpl::get_clipboard_text;
897
f->_utilities_impl.open_url= &UtilitiesImpl::open_url;
898
f->_utilities_impl.add_timeout= &UtilitiesImpl::add_timeout;
899
f->_utilities_impl.cancel_timeout= &UtilitiesImpl::cancel_timeout;
900
f->_utilities_impl.get_special_folder= &UtilitiesImpl::get_special_folder;
901
f->_utilities_impl.store_password= &UtilitiesImpl::store_password;
902
f->_utilities_impl.find_password= &UtilitiesImpl::find_password;
903
f->_utilities_impl.forget_password= &UtilitiesImpl::forget_password;
904
f->_utilities_impl.move_to_trash= &UtilitiesImpl::move_to_trash;
905
f->_utilities_impl.reveal_file= &UtilitiesImpl::reveal_file;
906
f->_utilities_impl.perform_from_main_thread = &MainThreadRequestQueue::perform;
907
f->_utilities_impl.set_thread_name = &UtilitiesImpl::set_thread_name;
909
MainThreadRequestQueue::get(); // init from main thread
913
//---------------------------------------------------------------------------------
915
void MainThreadRequestQueue::from_main_thread()
917
boost::shared_ptr<Request> req;
919
Glib::Mutex::Lock lock(_mutex);
922
req = _queue.front();
925
req->result = req->slot();
927
Glib::Mutex::Lock lock(req->mutex);
933
MainThreadRequestQueue::MainThreadRequestQueue()
935
_disp.connect(sigc::mem_fun(this, &MainThreadRequestQueue::from_main_thread));
939
MainThreadRequestQueue *MainThreadRequestQueue::get()
941
static MainThreadRequestQueue *q = new MainThreadRequestQueue();
945
void *MainThreadRequestQueue::perform(const boost::function<void* ()> &slot, bool wait)
947
if (Utilities::in_main_thread())
951
MainThreadRequestQueue *self = MainThreadRequestQueue::get();
953
boost::shared_ptr<Request> req(new Request());
958
Glib::Mutex::Lock lock(self->_mutex);
959
self->_queue.push_back(req);
965
Glib::Mutex::Lock lock(req->mutex);
967
req->cond.wait(req->mutex);