~ubuntu-branches/ubuntu/quantal/mysql-workbench/quantal

« back to all changes in this revision

Viewing changes to frontend/linux/linux_utilities/gtk_helpers.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-03-01 21:57:30 UTC
  • Revision ID: package-import@ubuntu.com-20120301215730-o7y8av8y38n162ro
Tags: upstream-5.2.38+dfsg
ImportĀ upstreamĀ versionĀ 5.2.38+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "gtk_helpers.h"
 
2
#include "image_cache.h"
 
3
 
 
4
#include "config.h"
 
5
 
 
6
#include <gtkmm/image.h>
 
7
#include <gtkmm/filechooserdialog.h>
 
8
#include <gtkmm/stock.h>
 
9
#include <gtkmm/combobox.h>
 
10
#include <gtkmm/comboboxtext.h>
 
11
#include <gtkmm/comboboxentrytext.h>
 
12
#include <gtkmm/menu.h>
 
13
#include <gtkmm/eventbox.h>
 
14
#include <gtkmm/paned.h>
 
15
#include "text_list_columns_model.h"
 
16
 
 
17
#include "treemodel_wrapper.h"
 
18
 
 
19
// This list_model is used for all functions which operate on GTKListStore
 
20
static TextListColumnsModel _wb_list_model;
 
21
 
 
22
Glib::RefPtr<Gtk::ListStore> get_empty_model()
 
23
{
 
24
  static Glib::RefPtr<Gtk::ListStore> empty_list_store;
 
25
  if (!empty_list_store)
 
26
    empty_list_store = Gtk::ListStore::create(_wb_list_model);
 
27
 
 
28
  return empty_list_store;
 
29
}
 
30
 
 
31
//------------------------------------------------------------------------------
 
32
Gtk::HBox &create_icon_label(const std::string &icon, const std::string &text)
 
33
{
 
34
  Gtk::HBox *hbox= Gtk::manage(new Gtk::HBox(false, 0));
 
35
  
 
36
  Gtk::Image *image= Gtk::manage(new Gtk::Image(ImageCache::get_instance()->image_from_filename(icon)));
 
37
  Gtk::Label *label= Gtk::manage(new Gtk::Label(text));
 
38
  
 
39
  label->set_use_markup(true);
 
40
  
 
41
  hbox->pack_start(*image);
 
42
  hbox->pack_start(*label, true, true);
 
43
  
 
44
  hbox->show_all();
 
45
  
 
46
  return *hbox;
 
47
}
 
48
 
 
49
 
 
50
//------------------------------------------------------------------------------
 
51
Glib::RefPtr<Gtk::ListStore> model_from_string_list(const std::vector<std::string>& list, TextListColumnsModel* columns)
 
52
{
 
53
  Glib::RefPtr<Gtk::ListStore> model = Gtk::ListStore::create(*columns);
 
54
  
 
55
  std::vector<std::string>::const_iterator last = list.end();
 
56
  
 
57
  for (std::vector<std::string>::const_iterator iter = list.begin(); iter != last; ++iter)
 
58
    (*model->append())[columns->item] = *iter;
 
59
  
 
60
  return model;
 
61
}
 
62
 
 
63
 
 
64
//------------------------------------------------------------------------------
 
65
Glib::RefPtr<Gtk::ListStore> model_from_string_list(const std::vector<std::string>& list, TextListColumnsModel** columns)
 
66
{
 
67
  if ( columns )
 
68
    *columns = &_wb_list_model;
 
69
 
 
70
  return model_from_string_list(list, &_wb_list_model);
 
71
}
 
72
 
 
73
 
 
74
//------------------------------------------------------------------------------
 
75
Glib::RefPtr<Gtk::ListStore> model_from_string_list(const std::list<std::string>& list, TextListColumnsModel** columns)
 
76
{
 
77
  if ( columns )
 
78
    *columns = &_wb_list_model;
 
79
 
 
80
  Glib::RefPtr<Gtk::ListStore> model = Gtk::ListStore::create(_wb_list_model);
 
81
  
 
82
  std::list<std::string>::const_iterator last = list.end();
 
83
  
 
84
  for (std::list<std::string>::const_iterator iter = list.begin(); iter != last; ++iter)
 
85
    (*model->append())[_wb_list_model.item] = *iter;
 
86
  
 
87
  return model;
 
88
}
 
89
 
 
90
 
 
91
//------------------------------------------------------------------------------
 
92
void recreate_model_from_string_list(Glib::RefPtr<Gtk::ListStore> model, const std::vector<std::string>& list)
 
93
{
 
94
  model->clear();
 
95
  
 
96
  std::vector<std::string>::const_iterator last = list.end();
 
97
  
 
98
  for (std::vector<std::string>::const_iterator iter = list.begin(); iter != last; ++iter)
 
99
    (*model->append())[_wb_list_model.item] = *iter;
 
100
}
 
101
 
 
102
 
 
103
//------------------------------------------------------------------------------
 
104
void setup_combo_for_string_list(Gtk::ComboBox *combo)
 
105
{
 
106
  Gtk::CellRendererText *cell= Gtk::manage(new Gtk::CellRendererText());
 
107
  combo->pack_end(*cell, true);
 
108
  combo->add_attribute(*cell, "text", 0);
 
109
}
 
110
 
 
111
//------------------------------------------------------------------------------
 
112
std::string get_selected_combo_item(Gtk::ComboBox *combo)
 
113
{
 
114
  Gtk::TreeIter iter= combo->get_active();
 
115
  if (iter)
 
116
  {
 
117
    Gtk::TreeRow row= *iter;
 
118
    std::string item= row[_wb_list_model.item];
 
119
    
 
120
    return item;
 
121
  }
 
122
  return "";
 
123
}
 
124
 
 
125
//------------------------------------------------------------------------------
 
126
 
 
127
bool set_selected_combo_item(Gtk::ComboBox *combo, const std::string &value)
 
128
{
 
129
  Glib::RefPtr<Gtk::TreeModel> store(combo->get_model());
 
130
 
 
131
  for (Gtk::TreeIter end = store->children().end(), iter = store->children().begin();
 
132
      iter != end; ++iter)
 
133
  {
 
134
    Gtk::TreeRow row= *iter;
 
135
    std::string item = row[_wb_list_model.item];
 
136
    if (item == value)
 
137
    {
 
138
      combo->set_active(iter);
 
139
      return true;
 
140
    }
 
141
  }
 
142
  return false;
 
143
}
 
144
 
 
145
//------------------------------------------------------------------------------
 
146
void set_glib_string(Glib::ValueBase& value, const std::string& str, bool escape_nuls)
 
147
{
 
148
  GValue *gval = value.gobj();
 
149
 
 
150
  g_value_init(gval, G_TYPE_STRING);
 
151
  if (escape_nuls)
 
152
  {
 
153
    std::string tmp;
 
154
    std::string::size_type p = 0, e;
 
155
    std::string::size_type length = str.length();
 
156
    // skip the \0 bytes so that data is displayed as in OSX
 
157
    while (p < length)
 
158
    {
 
159
       e = str.find('\0', p);
 
160
       if (e == std::string::npos)
 
161
         break;
 
162
       tmp.append(str.data()+p, e-p);
 
163
       p = e+1;
 
164
    }
 
165
    if (p < length)
 
166
      tmp.append(str.data()+p);
 
167
    g_value_set_string(gval, tmp.c_str());
 
168
  }
 
169
  else
 
170
    g_value_set_string(gval, str.c_str());
 
171
}
 
172
 
 
173
//------------------------------------------------------------------------------
 
174
void set_glib_int(Glib::ValueBase& value, const int i)
 
175
{
 
176
  GValue *gval = value.gobj();
 
177
 
 
178
  g_value_init(gval, G_TYPE_INT);
 
179
  g_value_set_int(gval, i);
 
180
}
 
181
 
 
182
//------------------------------------------------------------------------------
 
183
void set_glib_bool(Glib::ValueBase& value, const bool b)
 
184
{
 
185
  GValue *gval = value.gobj();
 
186
 
 
187
  g_value_init(gval, G_TYPE_BOOLEAN);
 
188
  g_value_set_boolean(gval, b);
 
189
}
 
190
 
 
191
//------------------------------------------------------------------------------
 
192
void set_glib_double(Glib::ValueBase& value, const double d)
 
193
{
 
194
  GValue *gval = value.gobj();
 
195
 
 
196
  g_value_init(gval, G_TYPE_DOUBLE);
 
197
  g_value_set_double(gval, d);
 
198
}
 
199
 
 
200
//------------------------------------------------------------------------------
 
201
void fill_combo_from_string_list(Gtk::ComboBox* combo, const std::vector<std::string>& list)
 
202
{
 
203
  std::vector<std::string>::const_iterator it   = list.begin();
 
204
  std::vector<std::string>::const_iterator last = list.end();
 
205
 
 
206
  Glib::RefPtr<Gtk::ListStore> store(Glib::RefPtr<Gtk::ListStore>::cast_dynamic(combo->get_model()));
 
207
  if (!store)
 
208
  {
 
209
    store = get_empty_model();
 
210
    combo->set_model(store);
 
211
  }
 
212
 
 
213
  store->clear();
 
214
 
 
215
  for (; last != it; ++it )
 
216
  {
 
217
    Gtk::TreeIter iter = store->append();
 
218
    Gtk::TreeRow row= *iter;
 
219
    row.set_value(0, *it);
 
220
  }
 
221
}
 
222
 
 
223
//------------------------------------------------------------------------------
 
224
void fill_combo_from_string_list(Gtk::ComboBoxEntryText* combo, const std::vector<std::string>& list)
 
225
{
 
226
  std::vector<std::string>::const_iterator it   = list.begin();
 
227
  std::vector<std::string>::const_iterator last = list.end();
 
228
 
 
229
  for (; last != it; ++it )
 
230
    combo->append_text(*it);
 
231
}
 
232
 
 
233
//------------------------------------------------------------------------------
 
234
static std::string file_chooser_impl(const bool is_for_save, const std::string &filter)
 
235
{
 
236
  std::string filename;
 
237
  Gtk::FileChooserDialog dialog("Please choose a file",
 
238
          is_for_save ? Gtk::FILE_CHOOSER_ACTION_SAVE : Gtk::FILE_CHOOSER_ACTION_OPEN);
 
239
  dialog.set_transient_for(*get_mainwindow());
 
240
 
 
241
  //Add response buttons the the dialog:
 
242
  dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
 
243
  dialog.add_button(is_for_save ? Gtk::Stock::SAVE : Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
 
244
 
 
245
  if (!filter.empty())
 
246
  {
 
247
    Gtk::FileFilter filter_any;
 
248
    //filter_any.set_name("Any files");
 
249
    filter_any.add_pattern(filter);
 
250
    dialog.add_filter(filter_any);
 
251
  }
 
252
  const int result = dialog.run();
 
253
 
 
254
  switch(result)
 
255
  {
 
256
    case(Gtk::RESPONSE_OK):
 
257
    {
 
258
      filename = dialog.get_filename();
 
259
      break;
 
260
    }
 
261
    default:
 
262
      break;
 
263
  }
 
264
  
 
265
  return filename;
 
266
}
 
267
 
 
268
//------------------------------------------------------------------------------
 
269
std::string open_file_chooser(const std::string &filter)
 
270
{
 
271
  return file_chooser_impl(false, filter); // false - is not for save
 
272
}
 
273
 
 
274
std::string save_file_chooser(const std::string &filter)
 
275
{
 
276
  return file_chooser_impl(true, filter); // true - is for save
 
277
}
 
278
 
 
279
//------------------------------------------------------------------------------
 
280
static void expand_node(bec::TreeModel* tm, const bec::NodeId& node, Gtk::TreeView* tv)
 
281
{
 
282
  // Expand the node itself if needed
 
283
  if (tm->is_expandable(node))
 
284
  {
 
285
    if (tm->is_expanded(node))
 
286
    {
 
287
      const int             node_depth = node.depth();
 
288
      Gtk::TreeModel::Path  path;
 
289
 
 
290
      for (int i = 0; i < node_depth; ++i)
 
291
          path.push_back(node[i]);
 
292
 
 
293
      tv->expand_row(path, true);
 
294
    }
 
295
 
 
296
    // Apply the same thing for all node's children
 
297
    const int children_count = tm->count_children(node);
 
298
    if ( children_count > 0 )
 
299
    {
 
300
      for (int i = 0; i < children_count; ++i)
 
301
      {
 
302
        bec::NodeId child = tm->get_child(node, i);
 
303
        expand_node(tm, child, tv);
 
304
      }
 
305
    }
 
306
  }
 
307
}
 
308
 
 
309
//------------------------------------------------------------------------------
 
310
void expand_tree_nodes_as_in_be(const Glib::RefPtr<TreeModelWrapper> &model, Gtk::TreeView *tv)
 
311
{
 
312
  model->block_expand_collapse_signals();
 
313
  //TODO: This vv will work once grt_value_tree.h will have correct support for storing expanded/collapsed states 
 
314
  //bec::TreeModel *tm = static_cast<bec::TreeModel*>(model->get_be_model());
 
315
  //expand_node(tm, tm->get_root(), tv);
 
316
 
 
317
  // The code below is a workaround while we do not have working support for store/retrive expanded state of the node
 
318
  ExpandedRowsStorage* rows = model->expanded_rows_storage();
 
319
  // As: The insert members shall not affect the validity of iterators and references 
 
320
  // to the container, and the erase members shall invalidate only iterators and 
 
321
  // references to the erased elements. We need to have temp vector of values of invalid rows
 
322
  std::vector<ExpandedRowsStorage::key_type> invalid_rows;
 
323
  if ( rows )
 
324
  {
 
325
    ExpandedRowsStorage::const_iterator       row  = rows->begin();
 
326
    const ExpandedRowsStorage::const_iterator last = rows->end();
 
327
    
 
328
    for (; last != row; ++row)
 
329
    {
 
330
      if (!tv->expand_row(Gtk::TreeModel::Path(*row), false))
 
331
        invalid_rows.push_back(*row);
 
332
    }
 
333
    
 
334
    std::vector<ExpandedRowsStorage::key_type>::const_iterator i_row  = invalid_rows.begin();
 
335
    std::vector<ExpandedRowsStorage::key_type>::const_iterator i_last = invalid_rows.end();
 
336
    for(; i_last != i_row; ++i_row)
 
337
      rows->erase(*i_row);
 
338
  }
 
339
  model->unblock_expand_collapse_signals();
 
340
}
 
341
 
 
342
//------------------------------------------------------------------------------
 
343
//std::string run_string_dialog(const std::string& title, const std::string& init_value)
 
344
//{
 
345
//  Gtk::Entry entry;
 
346
//  Gtk::Dialog dlg;
 
347
//  entry.set_text(init_value);
 
348
//  entry.show();
 
349
//  dlg.add_action_widget(entry, 0xff);
 
350
//  dlg.set_title(title);
 
351
//  dlg.set_position(Gtk::WIN_POS_MOUSE);
 
352
//  dlg.set_transient_for(*get_mainwindow());
 
353
//  const int result = dlg.run();
 
354
//
 
355
//  std::string ret = init_value;
 
356
//  switch (result)
 
357
//  {
 
358
//    case 0xff: // for the magic number 0xff see above add_action_widget
 
359
//      ret = entry.get_text();
 
360
//      break;
 
361
//    default: break;
 
362
//  }
 
363
//  
 
364
//  return ret;
 
365
//}
 
366
 
 
367
 
 
368
static void populate_popup_menu(const bec::MenuItemList &items, const int time, 
 
369
                    const sigc::slot<void, std::string> &activate_slot, Gtk::Menu *popup)
 
370
{
 
371
  popup->foreach(sigc::mem_fun(popup, &Gtk::Container::remove));
 
372
 
 
373
        bec::MenuItemList::const_iterator  cur_item  = items.begin();
 
374
  const bec::MenuItemList::const_iterator  last_item = items.end();
 
375
 
 
376
  for ( ; last_item != cur_item; cur_item++ )
 
377
  {
 
378
    Gtk::MenuItem *item = Gtk::manage(new Gtk::MenuItem(bec::replace_string(cur_item->caption, "_", "__"), true));
 
379
    item->set_name(cur_item->name);
 
380
    item->set_sensitive(cur_item->enabled);
 
381
    // not support in Gtk from Ubuntu 8.04
 
382
    //item->set_use_underline(false);
 
383
 
 
384
    //g_message("run_popup: %s", cur_item->caption.c_str());
 
385
 
 
386
    switch ( cur_item->type )
 
387
    {
 
388
      case bec::MenuAction:
 
389
      case bec::MenuUnavailable:
 
390
      {
 
391
        if ( item )
 
392
          item->signal_activate().connect(sigc::bind(activate_slot, cur_item->name));
 
393
        break;
 
394
      }
 
395
      case bec::MenuCascade:
 
396
      {
 
397
        Gtk::Menu *submenu= Gtk::manage(new Gtk::Menu());
 
398
        item->set_submenu(*submenu);
 
399
        populate_popup_menu(cur_item->subitems, time, activate_slot, submenu);
 
400
        break;
 
401
      }
 
402
      case bec::MenuRadio:
 
403
      {
 
404
        //g_message("%s: fake impl of menuradioitem", __FUNCTION__);
 
405
      }
 
406
      case bec::MenuCheck:
 
407
      {
 
408
        Gtk::CheckMenuItem* citem = Gtk::manage(new Gtk::CheckMenuItem(cur_item->caption, true));
 
409
        item = citem;
 
410
        citem->set_active(cur_item->checked);
 
411
        citem->signal_activate().connect(sigc::bind(activate_slot, cur_item->name));
 
412
        break;
 
413
      }
 
414
      case bec::MenuSeparator:
 
415
      {
 
416
        delete item;
 
417
        item = Gtk::manage(new Gtk::SeparatorMenuItem());
 
418
        break;
 
419
      }
 
420
      default:
 
421
      {
 
422
        g_message("%s: WARNING! unhandled menuitem type %i, '%s'", __FUNCTION__, cur_item->type, cur_item->name.c_str());
 
423
        break;
 
424
      }
 
425
    }
 
426
    
 
427
    popup->append(*item);
 
428
    item->show();
 
429
  }
 
430
 
 
431
  popup->show(); 
 
432
}
 
433
 
 
434
 
 
435
void run_popup_menu(const bec::MenuItemList &items, const int time, 
 
436
                    const sigc::slot<void, std::string> &activate_slot, Gtk::Menu *popup)
 
437
{
 
438
  populate_popup_menu(items, time, activate_slot, popup);
 
439
 
 
440
  popup->popup(3, time);
 
441
}
 
442
 
 
443
//--------------------------------------------------------------------------------
 
444
/*
 
445
Gtk::Widget *create_closeable_tab(const Glib::ustring &title,
 
446
                                  const sigc::slot<void> &close_callback,
 
447
                                  Gtk::Label **title_label)
 
448
{
 
449
  Gtk::HBox *hbox= Gtk::manage(new Gtk::HBox(false, 1));
 
450
  Gtk::Label *label= Gtk::manage(new Gtk::Label("\342\234\225"));
 
451
  Gtk::EventBox *evbox= Gtk::manage(new Gtk::EventBox());
 
452
  Gtk::Label *text_label= Gtk::manage(new Gtk::Label(title));
 
453
 
 
454
  evbox->add(*label);
 
455
  label->show();
 
456
  hbox->pack_start(*text_label);
 
457
  hbox->pack_start(*evbox);
 
458
 
 
459
  hbox->show_all();
 
460
  
 
461
  if (title_label)
 
462
    *title_label = text_label;
 
463
 
 
464
  return hbox;
 
465
}
 
466
*/
 
467
 
 
468
//--------------------------------------------------------------------------------
 
469
 
 
470
void swap_panned_children(Gtk::Paned *paned, bool fixed_size_1)
 
471
{
 
472
  Gtk::Widget *w1 = paned->get_child1();
 
473
  Gtk::Widget *w2 = paned->get_child2();
 
474
    
 
475
  w1->reference();
 
476
  w2->reference();
 
477
  
 
478
  paned->remove(*w1);
 
479
  paned->remove(*w2);
 
480
  
 
481
  paned->pack1(*w2, true, fixed_size_1);
 
482
  paned->pack2(*w1, true, !fixed_size_1);
 
483
  
 
484
  w1->unreference();
 
485
  w2->unreference();
 
486
}
 
487
 
 
488
//--------------------------------------------------------------------------------
 
489
 
 
490
 
 
491
static bool disallow_select(const Glib::RefPtr<Gtk::TreeModel> &model, const Gtk::TreeModel::Path &path, bool selected)
 
492
{
 
493
  return false;
 
494
}
 
495
 
 
496
static bool allow_select(const Glib::RefPtr<Gtk::TreeModel> &model, const Gtk::TreeModel::Path &path, bool selected)
 
497
{
 
498
  return true;
 
499
}
 
500
 
 
501
static void handle_button_press(GdkEventButton *event, Gtk::TreeView *tree)
 
502
{
 
503
  Gtk::TreeModel::Path path;
 
504
  Gtk::TreeViewColumn *column;
 
505
  int cx, cy;
 
506
 
 
507
  if (tree->get_path_at_pos(event->x, event->y, path, column, cx, cy))
 
508
  {
 
509
    if (tree->get_selection()->is_selected(path) && (event->state & 0xff) == 0)
 
510
    {
 
511
      tree->get_selection()->set_select_function(sigc::ptr_fun(disallow_select));
 
512
    }
 
513
  }
 
514
}
 
515
 
 
516
 
 
517
static void handle_button_release(GdkEventButton *event, Gtk::TreeView *tree)
 
518
{
 
519
  tree->get_selection()->set_select_function(sigc::ptr_fun(allow_select));
 
520
}
 
521
 
 
522
 
 
523
void fix_broken_gtk_selection_handling(Gtk::TreeView *tree)
 
524
{
 
525
  tree->signal_button_press_event().connect_notify(sigc::bind(sigc::ptr_fun(handle_button_press), tree));
 
526
  tree->signal_button_release_event().connect_notify(sigc::bind(sigc::ptr_fun(handle_button_release), tree));
 
527
}
 
528
 
 
529
//------------------------------------------------------------------------------
 
530
void gtk_paned_set_pos_ratio(Gtk::Paned* paned, const float ratio)
 
531
{
 
532
  const int min_pos = paned->property_min_position();
 
533
  const int max_pos = paned->property_max_position();
 
534
  const int diff = (max_pos - min_pos) * ratio;
 
535
  if (ratio >= 1.0)
 
536
    paned->set_position(max_pos);
 
537
  else
 
538
    paned->set_position(min_pos + diff);
 
539
}
 
540
 
 
541
//------------------------------------------------------------------------------
 
542
float gtk_paned_get_pos_ratio(Gtk::Paned* paned)
 
543
{
 
544
  const float min_pos = paned->property_min_position();
 
545
  const float max_pos = paned->property_max_position();
 
546
 
 
547
  return (paned->get_position() - min_pos) / (max_pos - min_pos);
 
548
}