~ubuntu-branches/ubuntu/utopic/mysql-workbench/utopic

« back to all changes in this revision

Viewing changes to .pc/prtcl.patch/library/forms/gtk/src/lf_utilities.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2014-05-31 12:03:58 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20140531120358-cjik5ofkmj0fxsn8
Tags: 6.1.6+dfsg-1
* New upstream release [May 2014].
* Dropped "prtcl.patch".
* "debian/clean": better clean-up.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
 * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
3
 
 *
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
7
 
 * License.
8
 
 * 
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.
13
 
 * 
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
17
 
 * 02110-1301  USA
18
 
 */
19
 
 
20
 
//#include "config.h"
21
 
#if defined(HAVE_GNOME_KEYRING) || defined(HAVE_OLD_GNOME_KEYRING)
22
 
extern "C" {
23
 
  #include <gnome-keyring.h>
24
 
};
25
 
  #include <string.h>
26
 
  #define USE_KEYRING 1
27
 
#endif
28
 
 
29
 
#include <glib/gstdio.h>
30
 
#include <sys/prctl.h>
31
 
 
32
 
// this is broken
33
 
//#undef USE_KEYRING
34
 
#include "../lf_mforms.h"
35
 
 
36
 
#include "base/file_functions.h"
37
 
#include "base/file_utilities.h"
38
 
#include "base/log.h"
39
 
#include "base/string_utilities.h"
40
 
#include "../lf_utilities.h"
41
 
#include "gtk_helpers.h"
42
 
#include "mforms.h"
43
 
 
44
 
namespace mforms {
45
 
namespace gtk {
46
 
 
47
 
/**
48
 
  * Get the current active window for this application
49
 
  */
50
 
GtkWindow *get_current_window()
51
 
{
52
 
  GList *window_list = gtk_window_list_toplevels();
53
 
  do
54
 
  {
55
 
    GtkWindow *wnd = (GtkWindow *)window_list->data;
56
 
    
57
 
    if (gtk_window_is_active(wnd))
58
 
      return wnd;
59
 
  } while((window_list = g_list_next(window_list)) != NULL);
60
 
 
61
 
  return NULL;
62
 
}
63
 
 
64
 
/**
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
68
 
 *  scripting shell.
69
 
 *  To find the proper parent window, we're searching for the current active window
70
 
 *  on this application.
71
 
 */
72
 
void set_dialog_transcient(Gtk::MessageDialog &dialog)
73
 
{
74
 
  GtkWindow *parent_window = get_current_window();
75
 
  
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);
80
 
}
81
 
//--------------------------------------------------------------------------------
82
 
  
83
 
 
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)
87
 
{
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);
92
 
  if (!cancel.empty())
93
 
    dlg.add_button(cancel, mforms::ResultCancel);
94
 
  if (!other.empty())
95
 
    dlg.add_button(other, mforms::ResultOther);
96
 
 
97
 
  set_dialog_transcient(dlg);
98
 
 
99
 
  int r= dlg.run();
100
 
  if (r == Gtk::RESPONSE_DELETE_EVENT)
101
 
    return mforms::ResultCancel;
102
 
  return r;
103
 
}
104
 
 
105
 
 
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)
109
 
{
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);
114
 
  if (!cancel.empty())
115
 
    dlg.add_button(cancel, mforms::ResultCancel);
116
 
  if (!other.empty())
117
 
    dlg.add_button(other, mforms::ResultOther);
118
 
 
119
 
  set_dialog_transcient(dlg);
120
 
 
121
 
  int r= dlg.run();
122
 
  if (r == Gtk::RESPONSE_DELETE_EVENT)
123
 
    return mforms::ResultCancel;
124
 
  return r;
125
 
}
126
 
 
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)
130
 
{
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);
135
 
  if (!cancel.empty())
136
 
    dlg.add_button(cancel, mforms::ResultCancel);
137
 
  if (!other.empty())
138
 
    dlg.add_button(other, mforms::ResultOther);
139
 
 
140
 
  set_dialog_transcient(dlg);
141
 
  
142
 
  int r= dlg.run();
143
 
  if (r == Gtk::RESPONSE_DELETE_EVENT)
144
 
    return mforms::ResultCancel;
145
 
  return r;
146
 
}
147
 
 
148
 
static void handle_click(Gtk::CheckButton* btn, bool* state)
149
 
{
150
 
  *state = btn->get_active();
151
 
}
152
 
 
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)
158
 
{
159
 
  Gtk::MessageDialog dlg("<b>"+title+"</b>", true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true);
160
 
  dlg.set_secondary_text(text);
161
 
 
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));
166
 
 
167
 
  Gtk::Button *ok_btn = Gtk::manage(new Gtk::Button(ok));
168
 
  dlg.add_action_widget(*ok_btn, mforms::ResultOk);
169
 
 
170
 
  if (!cancel.empty())
171
 
    dlg.add_action_widget(*Gtk::manage(new Gtk::Button(cancel)), mforms::ResultCancel);
172
 
  if (!other.empty())
173
 
    dlg.add_action_widget(*Gtk::manage(new Gtk::Button(other)), mforms::ResultOther);
174
 
  dlg.show_all();
175
 
 
176
 
  set_dialog_transcient(dlg);
177
 
 
178
 
  int r= dlg.run();
179
 
  if (r == Gtk::RESPONSE_DELETE_EVENT)
180
 
    return mforms::ResultCancel;
181
 
  return r;
182
 
}
183
 
 
184
 
void UtilitiesImpl::set_clipboard_text(const std::string &text)
185
 
{
186
 
  Gtk::Clipboard::get()->set_text(text);
187
 
}
188
 
 
189
 
std::string UtilitiesImpl::get_clipboard_text()
190
 
{
191
 
  return Gtk::Clipboard::get()->wait_for_text();
192
 
}
193
 
 
194
 
void UtilitiesImpl::open_url(const std::string &url)
195
 
{
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, 
199
 
                                         FALSE);
200
 
 
201
 
  const gchar *argv[] = {
202
 
    "xdg-open",
203
 
    quoted_url,
204
 
    NULL 
205
 
  };
206
 
  GError *error = NULL;
207
 
  gboolean result = g_spawn_async(NULL, (gchar**)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error);
208
 
  
209
 
  free(quoted_url);
210
 
  
211
 
  if (!result)
212
 
  {
213
 
    char *err = g_strdup_printf("Error opening url with xdg-open: %s", error->message);
214
 
    g_error_free(error);
215
 
    std::runtime_error exc(err);
216
 
    g_free(err);
217
 
    throw exc;
218
 
  }
219
 
}
220
 
 
221
 
std::string UtilitiesImpl::get_special_folder(mforms::FolderType type)
222
 
{
223
 
  std::string path;
224
 
  const char *t;
225
 
 
226
 
  switch (type)
227
 
  {
228
 
  case mforms::Documents:
229
 
#if GTK_VERSION_GT(2,10)
230
 
    t = g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS);
231
 
    if (t) path= t;
232
 
#endif
233
 
    break;
234
 
  case mforms::Desktop:
235
 
#if GTK_VERSION_GT(2,10)
236
 
    t = g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP);
237
 
    if (t) path= t;
238
 
#else
239
 
    t = g_strdup_printf("%s/Desktop", g_get_home_dir());
240
 
    path= t;
241
 
    g_free((void*)t);
242
 
#endif
243
 
    break;
244
 
  case mforms::ApplicationData:
245
 
    path = g_get_home_dir();
246
 
    break;
247
 
  case mforms::ApplicationSettings:
248
 
    path = g_get_home_dir();
249
 
    path.append("/.mysql/workbench");
250
 
    break;
251
 
  case WinProgramFiles:
252
 
  case WinProgramFilesX86:
253
 
    path = "/";
254
 
    break;
255
 
  }
256
 
  if (path.empty())
257
 
  {
258
 
    t = g_get_home_dir();
259
 
    if (t) path= t;
260
 
  }
261
 
  return path.empty() ? "~" : path;
262
 
}
263
 
 
264
 
//------------------------------------------------------------------------------
265
 
static std::map<TimeoutHandle, sigc::connection> timeouts;
266
 
static TimeoutHandle last_timeout_handle = 0;
267
 
static base::Mutex timeout_mutex;
268
 
 
269
 
inline bool run_slot(const boost::function<bool ()> slot, TimeoutHandle handle)
270
 
{
271
 
  {
272
 
    base::MutexLock lock(timeout_mutex);
273
 
    std::map<TimeoutHandle, sigc::connection>::iterator it;
274
 
    if ((it = timeouts.find(handle)) != timeouts.end())
275
 
      timeouts.erase(it);
276
 
  }
277
 
  return slot();
278
 
}
279
 
 
280
 
//------------------------------------------------------------------------------
281
 
TimeoutHandle UtilitiesImpl::add_timeout(float interval, const boost::function<bool ()> &slot)
282
 
{
283
 
  try
284
 
  {
285
 
    if (slot)
286
 
    {
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;
291
 
    }
292
 
  }
293
 
  catch (std::exception &exc)
294
 
  {
295
 
    static const char* const default_log_domain = "Utilities";
296
 
    log_exception("Utilities: exception in add timeout function", exc);
297
 
  }
298
 
  return 0;
299
 
}
300
 
 
301
 
 
302
 
void UtilitiesImpl::cancel_timeout(TimeoutHandle h)
303
 
{
304
 
  base::MutexLock lock(timeout_mutex);
305
 
  std::map<TimeoutHandle, sigc::connection>::iterator it;
306
 
  if ((it = timeouts.find(h)) != timeouts.end())
307
 
  {
308
 
    it->second.disconnect();
309
 
    timeouts.erase(it);
310
 
  }
311
 
}
312
 
 
313
 
 
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)
319
 
{
320
 
  if (getenv("WB_NO_GNOME_KEYRING"))
321
 
  {
322
 
    return;
323
 
  }
324
 
 
325
 
  GnomeKeyringPasswordSchema wb_pwd_schema;
326
 
  memset(&wb_pwd_schema, 0, sizeof(wb_pwd_schema));
327
 
 
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
334
 
 
335
 
  GnomeKeyringResult res = gnome_keyring_store_password_sync(&wb_pwd_schema,
336
 
                                                             NULL, // using default keyring
337
 
                                                             account.c_str(),
338
 
                                                             password.c_str(),
339
 
                                                             "service", service.c_str(),
340
 
                                                             "account", account.c_str(),
341
 
                                                             NULL
342
 
                                                             );
343
 
 
344
 
  if ( res != GNOME_KEYRING_RESULT_OK )
345
 
    throw std::runtime_error(gnome_keyring_result_to_message(res));
346
 
}
347
 
 
348
 
//------------------------------------------------------------------------------
349
 
bool UtilitiesImpl::find_password(const std::string &service, const std::string &account, std::string &password)
350
 
{
351
 
  if (getenv("WB_NO_GNOME_KEYRING"))
352
 
  {
353
 
    return false;
354
 
  }
355
 
 
356
 
  bool ret = false;
357
 
 
358
 
  GnomeKeyringPasswordSchema wb_pwd_schema;
359
 
  memset(&wb_pwd_schema, 0, sizeof(wb_pwd_schema));
360
 
 
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
367
 
 
368
 
  gchar *kpwd = 0;
369
 
 
370
 
  GnomeKeyringResult res = gnome_keyring_find_password_sync(&wb_pwd_schema,
371
 
                                                            &kpwd,
372
 
                                                            "service", service.c_str(),
373
 
                                                            "account", account.c_str(),
374
 
                                                            NULL);
375
 
 
376
 
  if ( res != GNOME_KEYRING_RESULT_OK && res != GNOME_KEYRING_RESULT_NO_MATCH )
377
 
  {
378
 
    if (kpwd)
379
 
      gnome_keyring_free_password(kpwd);
380
 
      kpwd = 0;
381
 
    throw std::runtime_error(gnome_keyring_result_to_message(res));
382
 
  }
383
 
 
384
 
  if (kpwd && res == GNOME_KEYRING_RESULT_OK)
385
 
  {
386
 
    ret = true;
387
 
    password = kpwd;
388
 
    gnome_keyring_free_password(kpwd);
389
 
    kpwd = 0;
390
 
  }
391
 
 
392
 
  return ret;
393
 
}
394
 
 
395
 
//------------------------------------------------------------------------------
396
 
void UtilitiesImpl::forget_password(const std::string &service, const std::string &account)
397
 
{
398
 
  if (getenv("WB_NO_GNOME_KEYRING"))
399
 
  {
400
 
    return;
401
 
  }
402
 
 
403
 
  GnomeKeyringPasswordSchema wb_pwd_schema;
404
 
  memset(&wb_pwd_schema, 0, sizeof(wb_pwd_schema));
405
 
 
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
412
 
 
413
 
  GnomeKeyringResult res = gnome_keyring_delete_password_sync(&wb_pwd_schema,
414
 
                                                            "service", service.c_str(),
415
 
                                                            "account", account.c_str(),
416
 
                                                            NULL);
417
 
 
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));
420
 
}
421
 
 
422
 
#elif defined(HAVE_OLD_GNOME_KEYRING)
423
 
 
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",
435
 
                                             ""
436
 
                                            };
437
 
 
438
 
//------------------------------------------------------------------------------
439
 
static const char* gnome_keyring_result_to_message(const GnomeKeyringResult result)
440
 
{
441
 
  const char* message = gnome_keyring_results[Gnome_keyring_results_size - 1];
442
 
 
443
 
  if (result >= 0 && result < (GnomeKeyringResult)Gnome_keyring_results_size)
444
 
    message = gnome_keyring_results[result];
445
 
 
446
 
  return message;
447
 
}
448
 
 
449
 
//------------------------------------------------------------------------------
450
 
void UtilitiesImpl::store_password(const std::string &service, const std::string &account, const std::string &password)
451
 
{
452
 
  if (getenv("WB_NO_GNOME_KEYRING"))
453
 
  {
454
 
    return;
455
 
  }
456
 
 
457
 
  GnomeKeyringAttributeList *attrs = gnome_keyring_attribute_list_new();
458
 
  guint32 item_id = 0;
459
 
 
460
 
  gnome_keyring_attribute_list_append_string(attrs, "service", service.c_str());
461
 
  gnome_keyring_attribute_list_append_string(attrs, "account", account.c_str());
462
 
 
463
 
  const GnomeKeyringResult result = gnome_keyring_item_create_sync(NULL,
464
 
                                                                  GNOME_KEYRING_ITEM_GENERIC_SECRET,
465
 
                                                                  account.c_str(),
466
 
                                                                  attrs,
467
 
                                                                  password.c_str(),
468
 
                                                                  true,
469
 
                                                                  &item_id);
470
 
 
471
 
  gnome_keyring_attribute_list_free(attrs);
472
 
 
473
 
  if ( result != GNOME_KEYRING_RESULT_OK )
474
 
    throw std::runtime_error(gnome_keyring_result_to_message(result));
475
 
}
476
 
 
477
 
//------------------------------------------------------------------------------
478
 
static guint32 find_password_and_id(const std::string &service, const std::string &account, std::string &password)
479
 
{
480
 
  guint32 ret = 0;
481
 
 
482
 
  GnomeKeyringAttributeList *attrs = gnome_keyring_attribute_list_new();
483
 
 
484
 
  gnome_keyring_attribute_list_append_string(attrs, "service", service.c_str());
485
 
  gnome_keyring_attribute_list_append_string(attrs, "account", account.c_str());
486
 
 
487
 
  GList* found_items = 0;
488
 
 
489
 
  const GnomeKeyringResult result = gnome_keyring_find_items_sync(GNOME_KEYRING_ITEM_GENERIC_SECRET,
490
 
                                                                  attrs,
491
 
                                                                  &found_items);
492
 
 
493
 
  if (result != GNOME_KEYRING_RESULT_OK)
494
 
  {
495
 
    if (found_items)
496
 
      gnome_keyring_found_list_free(found_items);
497
 
    throw std::runtime_error(gnome_keyring_result_to_message(result));
498
 
  }
499
 
 
500
 
  if (g_list_length(found_items) > 0)
501
 
  {
502
 
    GnomeKeyringFound* item = (GnomeKeyringFound*)g_list_first(found_items);
503
 
    password = item->secret;
504
 
    ret = item->item_id;
505
 
  }
506
 
 
507
 
  if (found_items)
508
 
    gnome_keyring_found_list_free(found_items);
509
 
 
510
 
  return ret;
511
 
}
512
 
 
513
 
//------------------------------------------------------------------------------
514
 
bool UtilitiesImpl::find_password(const std::string &service, const std::string &account, std::string &password)
515
 
{
516
 
  if (getenv("WB_NO_GNOME_KEYRING"))
517
 
  {
518
 
    return false;
519
 
  }
520
 
 
521
 
  return find_password_and_id(service, account, password);
522
 
}
523
 
 
524
 
//------------------------------------------------------------------------------
525
 
void UtilitiesImpl::forget_password(const std::string &service, const std::string &account)
526
 
{
527
 
  if (getenv("WB_NO_GNOME_KEYRING"))
528
 
  {
529
 
    return;
530
 
  }
531
 
 
532
 
  std::string password;
533
 
  const guint32 item_id = find_password_and_id(service, account, password);
534
 
 
535
 
  GnomeKeyringResult res = GNOME_KEYRING_RESULT_BAD_ARGUMENTS;
536
 
  if (item_id)
537
 
    res = gnome_keyring_item_delete_sync(NULL, item_id);
538
 
 
539
 
  if ( res != GNOME_KEYRING_RESULT_OK )
540
 
    throw std::runtime_error(gnome_keyring_result_to_message(res));
541
 
}
542
 
#else
543
 
 
544
 
void UtilitiesImpl::store_password(const std::string &service, const std::string &account, const std::string &password)
545
 
{
546
 
}
547
 
 
548
 
bool UtilitiesImpl::find_password(const std::string &service, const std::string &account, std::string &password)
549
 
{
550
 
  g_message("no gnome keyring support");
551
 
  return false;
552
 
}
553
 
 
554
 
void UtilitiesImpl::forget_password(const std::string &service, const std::string &account)
555
 
{
556
 
}
557
 
 
558
 
#endif // !USE_KEYRING
559
 
 
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
565
 
 
566
 
#define MESSAGE_WINDOW_WIDTH 450
567
 
#define MESSAGE_WINDOW_HEIGHT 220
568
 
  
569
 
#ifdef USE_TRANSPARENT_MESSAGE
570
 
//==============================================================================
571
 
//
572
 
//==============================================================================
573
 
class TransparentMessage : public Gtk::Window
574
 
{
575
 
  public:
576
 
    TransparentMessage();
577
 
    void show_message(const std::string& title, const std::string& text, const sigc::slot<bool> &cancel_slot=sigc::slot<bool>());
578
 
    void run();
579
 
    void stop();
580
 
    bool response;
581
 
    bool running_modal;
582
 
  private:
583
 
    Gtk::Button *cancel_button;
584
 
    sigc::slot<bool> cancel_slot;
585
 
    Glib::Mutex mutex;
586
 
    bool _is_runing;
587
 
 
588
 
    virtual bool on_button_release_event(GdkEventButton* ev);
589
 
    void cancel_clicked();
590
 
};
591
 
 
592
 
//------------------------------------------------------------------------------
593
 
TransparentMessage::TransparentMessage()
594
 
  : response(false), _is_runing(false)
595
 
{
596
 
  Gtk::Window *owner = get_mainwindow();
597
 
  if (owner)
598
 
  {
599
 
    set_transient_for(*owner);
600
 
    set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
601
 
  }
602
 
  else
603
 
    set_position(Gtk::WIN_POS_CENTER);
604
 
 
605
 
 
606
 
  property_skip_taskbar_hint() = true;
607
 
  property_skip_pager_hint() = true;
608
 
  property_decorated() = false;
609
 
 
610
 
  set_size_request(MESSAGE_WINDOW_WIDTH, MESSAGE_WINDOW_HEIGHT);
611
 
  
612
 
  set_style(get_style()->copy());
613
 
 
614
 
  {
615
 
    Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(false, 0));
616
 
    vbox->set_border_width(20);
617
 
    add(*vbox);
618
 
 
619
 
    Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, 12));
620
 
    vbox->pack_end(*hbox, false, false);
621
 
 
622
 
    cancel_button = Gtk::manage(new Gtk::Button("Cancel"));
623
 
    hbox->pack_end(*cancel_button, false, true);
624
 
    vbox->show_all();
625
 
 
626
 
    cancel_button->signal_clicked().connect(sigc::mem_fun(this, &TransparentMessage::cancel_clicked));
627
 
  }
628
 
}
629
 
 
630
 
//------------------------------------------------------------------------------
631
 
void TransparentMessage::show_message(const std::string& title, const std::string& text, const sigc::slot<bool> &cancel_slot)
632
 
{
633
 
  this->cancel_slot = cancel_slot;
634
 
  if (cancel_slot)
635
 
    cancel_button->show();
636
 
  else
637
 
  {
638
 
    cancel_button->hide();
639
 
    add_events(Gdk::BUTTON_RELEASE_MASK);
640
 
  }
641
 
 
642
 
  realize();
643
 
 
644
 
  Gdk::Color black("black"), white("white");
645
 
  black.rgb_find_color(get_colormap());
646
 
  white.rgb_find_color(get_colormap());
647
 
  
648
 
  Glib::RefPtr<Gdk::Pixmap> pixmap = Gdk::Pixmap::create(get_window(),
649
 
                                                         MESSAGE_WINDOW_WIDTH, MESSAGE_WINDOW_HEIGHT,
650
 
                                                         get_window()->get_depth());
651
 
 
652
 
  Glib::RefPtr<Gdk::GC> gc = Gdk::GC::create(pixmap);
653
 
    
654
 
  gc->set_foreground(white);
655
 
  pixmap->draw_rectangle(gc, false, 0, 0, MESSAGE_WINDOW_WIDTH-1, MESSAGE_WINDOW_HEIGHT-1);
656
 
 
657
 
  gc->set_foreground(black);
658
 
  pixmap->draw_rectangle(gc, true, 2, 2, MESSAGE_WINDOW_WIDTH-3, MESSAGE_WINDOW_HEIGHT-3);
659
 
 
660
 
  
661
 
  Glib::RefPtr<Gdk::Pixbuf> icon = Gdk::Pixbuf::create_from_file(App::get()->get_resource_path("message_wb_wait.png"));
662
 
    
663
 
  pixmap->draw_pixbuf(gc, icon, 0, 0, 20, 20, icon->get_width(), icon->get_height(),
664
 
                      Gdk::RGB_DITHER_NORMAL, 0, 0);
665
 
 
666
 
  Glib::RefPtr<Pango::Layout> layout = create_pango_layout(title);
667
 
  
668
 
  gc->set_foreground(white);
669
 
 
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);
673
 
 
674
 
  
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);
679
 
 
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);
684
 
#endif
685
 
  window->process_updates(true);
686
 
  show_all();
687
 
}
688
 
 
689
 
void TransparentMessage::run()
690
 
{
691
 
  _is_runing = true;
692
 
  Gtk::Main::run();
693
 
}
694
 
 
695
 
//------------------------------------------------------------------------------
696
 
void TransparentMessage::stop()
697
 
{
698
 
  Glib::Mutex::Lock lock(mutex);
699
 
  if (running_modal)
700
 
  {
701
 
    unrealize();
702
 
    running_modal = false;
703
 
    if (_is_runing)
704
 
    {
705
 
      Gtk::Main::quit();
706
 
      _is_runing = false;
707
 
    }
708
 
  }
709
 
  response= true;
710
 
}
711
 
 
712
 
 
713
 
void TransparentMessage::cancel_clicked()
714
 
{
715
 
  Glib::Mutex::Lock lock(mutex);
716
 
  if (cancel_slot && cancel_slot())
717
 
  {
718
 
    if (running_modal)
719
 
    {
720
 
      unrealize();
721
 
      running_modal = false;
722
 
      if (_is_runing)
723
 
      {
724
 
        Gtk::Main::quit();
725
 
        hide();
726
 
        _is_runing = false;
727
 
      }
728
 
    }
729
 
    response = false;
730
 
  }
731
 
}
732
 
 
733
 
//------------------------------------------------------------------------------
734
 
bool TransparentMessage::on_button_release_event(GdkEventButton* ev)
735
 
{
736
 
  hide();
737
 
  return false;
738
 
}
739
 
 
740
 
static TransparentMessage *tm = 0;
741
 
static TransparentMessage *tmc = 0;
742
 
#endif
743
 
 
744
 
//------------------------------------------------------------------------------
745
 
void UtilitiesImpl::show_wait_message(const std::string &title, const std::string &text)
746
 
{
747
 
  #ifdef USE_TRANSPARENT_MESSAGE
748
 
  if (!tm)
749
 
    tm = new TransparentMessage();
750
 
 
751
 
  if (tm)
752
 
    tm->show_message(title, text);
753
 
  #endif
754
 
}
755
 
 
756
 
//------------------------------------------------------------------------------
757
 
bool UtilitiesImpl::hide_wait_message()
758
 
{
759
 
  #ifdef USE_TRANSPARENT_MESSAGE
760
 
  if (tm)
761
 
  {
762
 
    tm->hide();
763
 
    delete tm;
764
 
    tm = 0;
765
 
  }
766
 
  #endif
767
 
  return false;
768
 
}
769
 
 
770
 
 
771
 
//-------------------------------------------------------------------------------
772
 
 
773
 
bool UtilitiesImpl::move_to_trash(const std::string &path)
774
 
{
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());
778
 
  else
779
 
    g_remove(path.c_str());
780
 
  return true;
781
 
}
782
 
 
783
 
 
784
 
//------------------------------------------------------------------------------
785
 
void UtilitiesImpl::reveal_file(const std::string &path)
786
 
{
787
 
  const gchar *argv[] = {
788
 
    "xdg-open",
789
 
    base::dirname(path).c_str(),
790
 
    NULL 
791
 
  };
792
 
  GError *error = NULL;
793
 
  if (!g_spawn_async(NULL, (gchar**)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error))
794
 
  {
795
 
    char *err = g_strdup_printf("Error opening folder with xdg-open: %s", error->message);
796
 
    g_error_free(error);
797
 
    std::runtime_error exc(err);
798
 
    g_free(err);
799
 
    throw exc;
800
 
  }
801
 
 
802
 
}
803
 
 
804
 
 
805
 
void UtilitiesImpl::set_thread_name(const std::string &name)
806
 
{
807
 
  if (!name.empty())
808
 
    prctl(PR_SET_NAME, name.c_str(),0,0,0);
809
 
}
810
 
 
811
 
//------------------------------------------------------------------------------
812
 
 
813
 
 
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)
816
 
{
817
 
  if (!start_task)
818
 
    throw std::invalid_argument("start_task param cannot be empty");
819
 
 
820
 
  if (!tmc)
821
 
    tmc = new TransparentMessage();
822
 
  if (tmc)
823
 
  {
824
 
    tmc->show_message(title, text, sigc::mem_fun(&cancel_task,&boost::function<bool ()>::operator()));
825
 
    tmc->running_modal = true;
826
 
 
827
 
    Glib::signal_idle().connect(sigc::bind_return(start_task, false));
828
 
 
829
 
    tmc->run();
830
 
    bool response = tmc->response;
831
 
    delete tmc;
832
 
    tmc = 0;
833
 
    return response;
834
 
  }
835
 
 
836
 
  return false;
837
 
}
838
 
 
839
 
 
840
 
void UtilitiesImpl::stop_cancelable_wait_message()
841
 
{
842
 
  if (tmc)
843
 
  {
844
 
    if (Utilities::in_main_thread())
845
 
      tmc->stop();
846
 
    else
847
 
      Utilities::perform_from_main_thread(sigc::bind_return(sigc::mem_fun(tmc, &TransparentMessage::stop), (void*)NULL));
848
 
  }
849
 
}
850
 
 
851
 
   
852
 
Glib::RefPtr<Gdk::Pixbuf> UtilitiesImpl::get_cached_icon(const std::string &icon)
853
 
{
854
 
  std::map<std::string, Glib::RefPtr<Gdk::Pixbuf> > cache;
855
 
 
856
 
  if (cache.find(icon) != cache.end())
857
 
    return cache[icon];
858
 
 
859
 
  if (icon == "folder")
860
 
  {
861
 
    Glib::RefPtr<Gdk::Pixbuf> pix = get_mainwindow()->render_icon(Gtk::Stock::DIRECTORY, Gtk::ICON_SIZE_MENU);
862
 
    cache[icon] = pix;
863
 
    return pix;
864
 
  }
865
 
  else
866
 
  {
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))
869
 
    {
870
 
      cache[icon] = Gdk::Pixbuf::create_from_file(path);
871
 
      return cache[icon];
872
 
    }
873
 
    else
874
 
      g_warning("Can't find icon %s", icon.c_str());
875
 
  }
876
 
  return Glib::RefPtr<Gdk::Pixbuf>();
877
 
}
878
 
 
879
 
 
880
 
//------------------------------------------------------------------------------
881
 
 
882
 
void UtilitiesImpl::init()
883
 
{
884
 
  ::mforms::ControlFactory *f = ::mforms::ControlFactory::get_instance();
885
 
 
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;
894
 
 
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;
908
 
 
909
 
  MainThreadRequestQueue::get(); // init from main thread
910
 
}
911
 
 
912
 
 
913
 
//---------------------------------------------------------------------------------
914
 
 
915
 
void MainThreadRequestQueue::from_main_thread()
916
 
{
917
 
  boost::shared_ptr<Request> req;
918
 
  {
919
 
    Glib::Mutex::Lock lock(_mutex);
920
 
    if (_queue.empty())
921
 
      return;
922
 
    req = _queue.front();
923
 
    _queue.pop_front();
924
 
  }
925
 
  req->result = req->slot();
926
 
 
927
 
  Glib::Mutex::Lock lock(req->mutex);
928
 
  req->done = true;
929
 
  req->cond.signal();
930
 
}
931
 
 
932
 
 
933
 
MainThreadRequestQueue::MainThreadRequestQueue()
934
 
{
935
 
  _disp.connect(sigc::mem_fun(this, &MainThreadRequestQueue::from_main_thread));
936
 
}
937
 
 
938
 
 
939
 
MainThreadRequestQueue *MainThreadRequestQueue::get()
940
 
{
941
 
  static MainThreadRequestQueue *q = new MainThreadRequestQueue();
942
 
  return q;
943
 
}
944
 
 
945
 
void *MainThreadRequestQueue::perform(const boost::function<void* ()> &slot, bool wait)
946
 
{
947
 
  if (Utilities::in_main_thread())
948
 
    return slot();
949
 
  else
950
 
  {
951
 
    MainThreadRequestQueue *self = MainThreadRequestQueue::get();
952
 
 
953
 
    boost::shared_ptr<Request> req(new Request());
954
 
    req->slot = slot;
955
 
    req->done = false;
956
 
    req->result = 0;
957
 
    {
958
 
      Glib::Mutex::Lock lock(self->_mutex);
959
 
      self->_queue.push_back(req);
960
 
    }
961
 
    self->_disp.emit();
962
 
 
963
 
    if (wait)
964
 
    {
965
 
      Glib::Mutex::Lock lock(req->mutex);
966
 
      while (!req->done)
967
 
        req->cond.wait(req->mutex);
968
 
 
969
 
      return req->result;
970
 
    }
971
 
    return NULL;
972
 
  }
973
 
}
974
 
 
975
 
 
976
 
   
977
 
   
978
 
};
979
 
};