3
* Copyright (C) 2001-2004 Murray Cumming
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of the
8
* License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* General Public License for more details.
15
* You should have received a copy of the GNU General Public
16
* License along with this program; if not, write to the
17
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, USA.
21
#include <config.h> // For GLOM_ENABLE_MAEMO
23
#include <glom/utils_ui.h>
24
#include <libglom/connectionpool.h>
25
#include <libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
26
#include <libglom/data_structure/glomconversions.h>
28
#include <libglom/data_structure/layout/layoutitem_image.h> // For GLOM_IMAGE_FORMAT
29
#include <gdkmm/pixbufloader.h>
30
#include <libgda/gda-blob-op.h> // For gda_blob_op_read_all()
32
#include <gtkmm/messagedialog.h>
36
#ifdef GLOM_ENABLE_MAEMO
37
#include <hildonmm/note.h>
40
#include <glibmm/i18n.h>
42
#include <string.h> // for strchr
43
#include <sstream> //For stringstream
48
#include <locale> // for locale, time_put
49
#include <ctime> // for struct tm
50
#include <iostream> // for cout, endl
58
// Basically copied from libgnome (gnome-help.c, Copyright (C) 2001 Sid Vicious
59
// Copyright (C) 2001 Jonathan Blandford <jrb@alum.mit.edu>), but C++ified
60
std::string locate_help_file(const std::string& path, const std::string& doc_name)
62
// g_get_language_names seems not to be wrapped by glibmm
63
const char* const* lang_list = g_get_language_names ();
65
for(unsigned int j = 0; lang_list[j] != NULL; ++j)
67
const char* lang = lang_list[j];
69
/* This has to be a valid language AND a language with
70
* no encoding postfix. The language will come up without
72
if(lang == NULL || strchr(lang, '.') != NULL)
75
const char* exts[] = { "", ".xml", ".docbook", ".sgml", ".html", NULL };
76
for(unsigned i = 0; exts[i] != NULL; ++i)
78
std::string name = doc_name + exts[i];
79
std::string full = Glib::build_filename(path, Glib::build_filename(lang, name));
81
if(Glib::file_test(full, Glib::FILE_TEST_EXISTS))
89
} //anonymous namespace
94
// Run dialog and response on Help if appropriate.
95
int Utils::dialog_run_with_help(Gtk::Dialog* dialog, const Glib::ustring& id)
97
int result = dialog->run();
99
//Maemo has no help system since Maemo 5,
100
//so we hide the buttons in anyway.
101
#ifndef GLOM_ENABLE_MAEMO
102
while (result == Gtk::RESPONSE_HELP)
105
result = dialog->run();
107
#endif //GLOM_ENABLE_MAEMO
114
* Help::show_help(const std::string& id)
116
* Launch a help browser with the glom help and load the given id if given
117
* If the help cannot be found an error dialog will be shown
120
// Maemo has no help system since Maemo 5 (Fremantle).
121
#ifndef GLOM_ENABLE_MAEMO
122
void Utils::show_help(const Glib::ustring& id)
137
const char *const path = GLOM_DATADIR G_DIR_SEPARATOR_S "gnome"
138
G_DIR_SEPARATOR_S "help"
139
G_DIR_SEPARATOR_S "glom";
140
std::string help_file = locate_help_file(path, "glom.xml");
141
if(help_file.empty())
143
throw std::runtime_error(_("No help file available"));
147
std::string uri = "ghelp:" + help_file;
148
if(pId) { uri += "?"; uri += pId; }
150
// g_app_info_launch_default_for_uri seems not to be wrapped by giomm
151
if(!g_app_info_launch_default_for_uri(uri.c_str(), NULL, &err))
153
std::string message(err->message);
155
throw std::runtime_error(message);
159
catch(const std::exception& ex)
161
const Glib::ustring message = _("Could not display help: ") + Glib::ustring(ex.what());
162
Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR);
166
#endif //GLOM_ENABLE_MAEMO
168
void Utils::show_ok_dialog(const Glib::ustring& title, const Glib::ustring& message, Gtk::Window* parent, Gtk::MessageType message_type)
170
#undef GLOM_ENABLE_MAEMO
171
#ifdef GLOM_ENABLE_MAEMO
172
// TODO_maemo: Map message_type to a sensible stock_id?
173
Hildon::Note dialog(Hildon::NOTE_TYPE_INFORMATION, parent, message);
175
Gtk::MessageDialog dialog("<b>" + title + "</b>", true /* markup */, message_type, Gtk::BUTTONS_OK);
176
dialog.set_secondary_text(message);
178
dialog.set_transient_for(*parent);
184
void Utils::show_ok_dialog(const Glib::ustring& title, const Glib::ustring& message, Gtk::Window& parent, Gtk::MessageType message_type)
186
show_ok_dialog(title, message, &parent, message_type);
192
static void on_window_hide(Glib::RefPtr<Glib::MainLoop> main_loop, sigc::connection handler_connection)
194
handler_connection.disconnect(); //This should release a main_loop reference.
197
//main_loop should be destroyed soon, because nothing else is using it.
200
} //anonymous namespace.
202
void Utils::show_window_until_hide(Gtk::Window* window)
207
Glib::RefPtr<Glib::MainLoop> main_loop = Glib::MainLoop::create(false /* not running */);
209
//Stop the main_loop when the window is hidden:
210
sigc::connection handler_connection; //TODO: There seems to be a crash if this is on the same line.
211
handler_connection = window->signal_hide().connect(
213
sigc::ptr_fun(&on_window_hide),
214
main_loop, handler_connection
218
main_loop->run(); //Run and block until it is stopped by the hide signal handler.
221
Glib::ustring Utils::bold_message(const Glib::ustring& message)
223
return "<b>" + message + "</b>";
227
Glib::RefPtr<Gdk::Pixbuf> Utils::get_pixbuf_for_gda_value(const Gnome::Gda::Value& value)
229
Glib::RefPtr<Gdk::Pixbuf> result;
231
if(value.get_value_type() == GDA_TYPE_BINARY || value.get_value_type() == GDA_TYPE_BLOB)
233
glong buffer_binary_length;
234
gconstpointer buffer_binary;
235
if(value.get_value_type() == GDA_TYPE_BLOB)
237
const GdaBlob* blob = value.get_blob();
238
if(gda_blob_op_read_all(blob->op, const_cast<GdaBlob*>(blob)))
240
buffer_binary_length = blob->data.binary_length;
241
buffer_binary = blob->data.data;
245
buffer_binary_length = 0;
246
buffer_binary = NULL;
247
g_warning("Conversions::get_pixbuf_for_gda_value(): Failed to read BLOB data");
252
buffer_binary = value.get_binary(buffer_binary_length);
255
/* Note that this is regular binary data, not escaped text representing the binary data: */
256
if(buffer_binary && buffer_binary_length)
258
//typedef std::list<Gdk::PixbufFormat> type_list_formats;
259
//const type_list_formats formats = Gdk::Pixbuf::get_formats();
260
//std::cout << "Debug: Supported pixbuf formats:" << std::endl;
261
//for(type_list_formats::const_iterator iter = formats.begin(); iter != formats.end(); ++iter)
263
// std::cout << " name=" << iter->get_name() << ", writable=" << iter->is_writable() << std::endl;
266
Glib::RefPtr<Gdk::PixbufLoader> refPixbufLoader;
269
refPixbufLoader = Gdk::PixbufLoader::create();
271
catch(const Gdk::PixbufError& ex)
273
refPixbufLoader.reset();
274
#ifdef GLIBMM_EXCEPTIONS_ENABLED
275
std::cerr << "PixbufLoader::create failed: " << ex.what() << std::endl;
281
guint8* puiData = (guint8*)buffer_binary;
282
#ifdef GLIBMM_EXCEPTIONS_ENABLED
286
//g_warning("ImageGlom::set_value(): debug: from db: ");
287
//for(int i = 0; i < 10; ++i)
288
// g_warning("%02X (%c), ", (guint8)puiData[i], (char)puiData[i]);
290
refPixbufLoader->write(puiData, (glong)buffer_binary_length);
291
result = refPixbufLoader->get_pixbuf();
293
refPixbufLoader->close(); //This throws if write() threw, so it must be inside the try block.
296
std::auto_ptr<Glib::Error> error;
297
refPixbufLoader->write(puiData, (glong)buffer_binary_length, error);
298
if(error.get() == NULL)
300
result = refPixbufLoader->get_pixbuf();
301
refPixbufLoader->close(error);
305
#ifdef GLIBMM_EXCEPTIONS_ENABLED
306
catch(const Glib::Exception& ex)
309
if(error.get() != NULL)
311
const Glib::Exception& ex = *error.get();
313
g_warning("Conversions::get_pixbuf_for_gda_value(): PixbufLoader::write() failed: %s", ex.what().c_str());
317
//TODO: load the image, using the mime type stored elsewhere.
318
//pixbuf = Gdk::Pixbuf::create_from_data(
326
int Utils::get_suitable_field_width_for_widget(Gtk::Widget& widget, const sharedptr<const LayoutItem_Field>& field_layout)
330
const Field::glom_field_type field_type = field_layout->get_glom_type();
332
Glib::ustring example_text;
335
case(Field::TYPE_DATE):
337
Glib::Date date(31, Glib::Date::Month(12), 2000);
338
example_text = Conversions::get_text_for_gda_value(field_type, Gnome::Gda::Value(date));
341
case(Field::TYPE_TIME):
343
Gnome::Gda::Time time = {0, 0, 0, 0, 0};
347
example_text = Conversions::get_text_for_gda_value(field_type, Gnome::Gda::Value(time));
350
case(Field::TYPE_NUMERIC):
352
#ifdef GLOM_ENABLE_MAEMO
353
//Maemo's screen is not so big, so don't be so generous:
354
example_text = "EUR 9999999";
356
example_text = "EUR 9999999999";
360
case(Field::TYPE_TEXT):
361
case(Field::TYPE_IMAGE): //Give images the same width as text fields, so they will often line up.
363
//if(!field_layout->get_text_format_multiline()) //Use the full width for multi-line text.
364
#ifdef GLOM_ENABLE_MAEMO
365
//Maemo's screen is not so big, so don't be so generous:
366
example_text = "AAAAAAAAAAAAAAAA";
368
example_text = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
379
if(!example_text.empty())
381
//Get the width required for this string in the current font:
382
Glib::RefPtr<Pango::Layout> refLayout = widget.create_pango_layout(example_text);
385
refLayout->get_pixel_size(width, height);
396
std::string Utils::get_filepath_with_extension(const std::string& filepath, const std::string& extension)
398
std::string result = filepath;
400
bool add_ext = false;
401
const std::string str_ext = "." + extension;
403
if(result.size() < str_ext.size()) //It can't have the ext already if it's not long enough.
405
add_ext = true; //It isn't there already.
409
const Glib::ustring strEnd = result.substr(result.size() - str_ext.size());
410
if(strEnd != str_ext) //If it doesn't already have the extension
414
//Add extension if necessay.
418
//TODO: Do not replace existing extensions, so it could be e.g. 'something.blah.theext'