Commit d47124d7 authored by Murray Cumming's avatar Murray Cumming
Browse files

Image fields: Add Open, Open With, and Save context menu items.

* glom/utility_widgets/dialog_image_save_progress.[h|cc]:
* ui/operator/dialog_image_save_progress.glade:
Added a progress dialog to do image saving, though it does not yet do
async saving so the dialog is never shown.
* Makefile.am:
* Makefile_glom.am:
* po/POTFILES.in: Mention the new files.
  * glom/utility_widgets/imageglom.[h|cc]: Add the new context menu items,
  using a temporary file for the Open and Open With features.
  Open With uses AppChooserDialog to offer a choice to the user.
  Bug #630057
parent 029b4ed8
2011-07-12 Murray Cumming <murrayc@murrayc.com>
Image fields: Add Open, Open With, and Save context menu items.
* glom/utility_widgets/dialog_image_save_progress.[h|cc]:
* ui/operator/dialog_image_save_progress.glade:
Added a progress dialog to do image saving, though it does not yet do
async saving so the dialog is never shown.
* Makefile.am:
* Makefile_glom.am:
* po/POTFILES.in: Mention the new files.
* glom/utility_widgets/imageglom.[h|cc]: Add the new context menu items,
using a temporary file for the Open and Open With features.
Open With uses AppChooserDialog to offer a choice to the user.
Bug #630057
2011-07-11 Murray Cumming <murrayc@murrayc.com>
Rename Dialog_Image_Progress to DialogImageLoadProgress
......
......@@ -90,6 +90,7 @@ dist_glade_operator_DATA = \
ui/operator/dialog_existing_or_new.glade \
ui/operator/dialog_find_id.glade \
ui/operator/dialog_image_load_progress.glade \
ui/operator/dialog_image_save_progress.glade \
ui/operator/dialog_import_csv.glade \
ui/operator/dialog_import_csv_progress.glade \
ui/operator/window_main.glade \
......
......@@ -190,6 +190,8 @@ glom_source_files = \
glom/utility_widgets/dialog_flowtable.h \
glom/utility_widgets/dialog_image_load_progress.cc \
glom/utility_widgets/dialog_image_load_progress.h \
glom/utility_widgets/dialog_image_save_progress.cc \
glom/utility_widgets/dialog_image_save_progress.h \
glom/utility_widgets/dialog_properties.cc \
glom/utility_widgets/dialog_properties.h \
glom/utility_widgets/flowtable.cc \
......
......@@ -40,7 +40,7 @@ const bool DialogImageLoadProgress::glade_developer(false);
DialogImageLoadProgress::DialogImageLoadProgress(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder)
: Gtk::Dialog(cobject)
{
builder->get_widget("image_loading_progress_bar", m_progress_bar);
builder->get_widget("progress_bar", m_progress_bar);
if(!m_progress_bar)
throw std::runtime_error("Missing widgets from glade file for DialogImageLoadProgress");
......@@ -50,6 +50,7 @@ DialogImageLoadProgress::~DialogImageLoadProgress()
{
if(m_data.get())
g_free(m_data->data);
if(m_loader)
{
try
......
......@@ -61,7 +61,6 @@ private:
Glib::RefPtr<Gio::File> m_file;
Glib::RefPtr<Gio::FileInputStream> m_stream;
unsigned int m_stream_size;
};
} //namespace Glom
......
/* Glom
*
* Copyright (C) 2001-2004 Murray Cumming
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "dialog_image_save_progress.h"
#include <gtkmm/messagedialog.h>
#include <iostream>
#include <glibmm/i18n.h>
namespace Glom
{
const char* DialogImageSaveProgress::glade_id("dialog_image_save_progress");
const bool DialogImageSaveProgress::glade_developer(false);
DialogImageSaveProgress::DialogImageSaveProgress(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder)
: Gtk::Dialog(cobject)
{
builder->get_widget("progress_bar", m_progress_bar);
if(!m_progress_bar)
throw std::runtime_error("Missing widgets from glade file for DialogImageSaveProgress");
}
DialogImageSaveProgress::~DialogImageSaveProgress()
{
}
void DialogImageSaveProgress::save(const Glib::ustring& uri)
{
//TODO: Support non-local URIs when we do this properly, using Gio::File.
const std::string filepath = Glib::filename_from_uri(uri);
m_progress_bar->set_text(Glib::ustring::compose("Saving %1...",
Glib::filename_display_basename(filepath)));
try
{
// Open the file for reading:
m_pixbuf->save(filepath, GLOM_IMAGE_FORMAT);
}
catch(const Glib::Error& ex)
{
error(ex.what());
}
//response(Gtk::RESPONSE_ACCEPT);
}
void DialogImageSaveProgress::error(const Glib::ustring& error_message)
{
Gtk::MessageDialog dialog(*this, _("Error Saving"), Gtk::MESSAGE_ERROR);
dialog.set_title(_("Error saving image"));
dialog.set_secondary_text(error_message);
dialog.run();
response(Gtk::RESPONSE_REJECT);
}
void DialogImageSaveProgress::set_pixbuf(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf)
{
m_pixbuf = pixbuf;
}
} // namespace Glom
/* Glom
*
* Copyright (C) 2001-2004 Murray Cumming
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef GLOM_UTILITY_WIDGETS_DIALOG_IMAGE_SAVE_PROGRESS_H
#define GLOM_UTILITY_WIDGETS_DIALOG_IMAGE_SAVE_PROGRESS_H
#include <gtkmm/dialog.h>
#include <gtkmm/builder.h>
#include <gtkmm/progressbar.h>
#include <libglom/data_structure/layout/layoutitem_image.h> //For the file formats.
//#include <memory>
namespace Glom
{
class DialogImageSaveProgress : public Gtk::Dialog
{
public:
static const char* glade_id;
static const bool glade_developer;
DialogImageSaveProgress(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder);
virtual ~DialogImageSaveProgress();
void save(const Glib::ustring& uri);
void set_pixbuf(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf);
private:
void error(const Glib::ustring& error_message);
Glib::RefPtr<Gdk::Pixbuf> m_pixbuf;
Gtk::ProgressBar* m_progress_bar;
};
} //namespace Glom
#endif // GLOM_UTILITY_WIDGETS_DIALOG_IMAGE_SAVE_PROGRESS_H
......@@ -24,7 +24,8 @@
#include <glom/utils_ui.h>
#include <glom/glade_utils.h>
#include <libglom/data_structure/glomconversions.h>
//#include <sstream> //For stringstream
#include <glom/utility_widgets/dialog_image_load_progress.h>
#include <glom/utility_widgets/dialog_image_save_progress.h>
#include <iostream> // for cout, endl
......@@ -310,19 +311,147 @@ void ImageGlom::scale()
// g_warning("ImageGlom::scale(): attempt to scale a null pixbuf.");
}
void ImageGlom::on_menupopup_activate_select_file()
void ImageGlom::on_menupopup_activate_open_file()
{
if(m_read_only)
open_with();
}
void ImageGlom::on_menupopup_activate_open_file_with()
{
Application* pApp = get_application();
//Offer the user a choice of suitable applications:
Gtk::AppChooserDialog dialog(GLOM_IMAGE_FORMAT_MIME_TYPE);
if(pApp)
dialog.set_transient_for(*pApp);
if(dialog.run() != Gtk::RESPONSE_OK)
return;
Glib::RefPtr<Gio::AppInfo> app_info = dialog.get_app_info();
if(!app_info)
{
std::cerr << G_STRFUNC << ": app_info was null." << std::endl;
}
open_with(app_info);
}
//TODO: Use Hildon::FileChooser for Maemo.
Gtk::FileChooserDialog dialog(_("Choose Image"), Gtk::FILE_CHOOSER_ACTION_OPEN);
void ImageGlom::open_with(const Glib::RefPtr<Gio::AppInfo>& app_info)
{
//Get a temporary file path:
std::string filepath;
const int filehandle = Glib::file_open_tmp(filepath);
::close(filehandle);
if(filepath.empty())
{
std::cerr << G_STRFUNC << ": Glib::file_open_tmp() returned an empty filepath" << std::endl;
return;
}
const Glib::ustring uri = Glib::filename_to_uri(filepath);
if(!save_file(uri))
return;
if(app_info)
{
std::vector<std::string> vec_uris;
vec_uris.push_back(uri);
std::cout << "app_info: " << app_info->get_name() << ", uri=" << uri << std::endl;
app_info->launch_uris(vec_uris, 0); //TODO: Get a GdkAppLaunchContext?
}
else
{
//TODO: Avoid duplication in xsl_utils.cc, by moving this into a utility function:
#ifdef G_OS_WIN32
// gtk_show_uri doesn't seem to work on Win32, at least not for local files
// We use Windows API instead.
// TODO: Check it again and file a bug if necessary.
ShellExecute(0, "open", uri.c_str(), 0, 0, SW_SHOW);
#else
//Use the GNOME browser:
GError* gerror = 0;
if(!gtk_show_uri(0 /* screen */, uri.c_str(), GDK_CURRENT_TIME, &gerror))
{
std::cerr << G_STRFUNC << ": " << gerror->message << std::endl;
g_error_free(gerror);
}
#endif //G_OS_WIN32
}
}
static Glib::RefPtr<Gtk::FileFilter> get_file_filter_images()
{
//Get image formats only:
Glib::RefPtr<Gtk::FileFilter> filter = Gtk::FileFilter::create();
filter->set_name(_("Images"));
filter->add_pixbuf_formats();
dialog.add_filter(filter);
return filter;
}
void ImageGlom::on_menupopup_activate_save_file()
{
Application* pApp = get_application();
Gtk::FileChooserDialog dialog(_("Save Image"), Gtk::FILE_CHOOSER_ACTION_SAVE);
if(pApp)
dialog.set_transient_for(*pApp);
dialog.add_filter( get_file_filter_images() );
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
const int response = dialog.run();
dialog.hide();
if(response != Gtk::RESPONSE_OK)
return;
const Glib::ustring uri = dialog.get_uri();
if(uri.empty())
return;
save_file(uri);
}
bool ImageGlom::save_file(const Glib::ustring& uri)
{
DialogImageSaveProgress* dialog_save = 0;
Utils::get_glade_widget_derived_with_warning(dialog_save);
if(!dialog_save)
return false;
// Automatically delete the dialog when we no longer need it:
std::auto_ptr<Gtk::Dialog> dialog_keeper(dialog_save);
Application* pApp = get_application();
if(pApp)
dialog_save->set_transient_for(*pApp);
dialog_save->set_pixbuf(m_pixbuf_original);
dialog_save->save(uri);
//TODO: Use this when we do async saving:
//dialog_save->run();
return true;
}
void ImageGlom::on_menupopup_activate_select_file()
{
if(m_read_only)
return;
Application* pApp = get_application();
//TODO: Use Hildon::FileChooser for Maemo.
Gtk::FileChooserDialog dialog(_("Choose Image"), Gtk::FILE_CHOOSER_ACTION_OPEN);
if(pApp)
dialog.set_transient_for(*pApp);
dialog.add_filter( get_file_filter_images() );
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
dialog.add_button(_("Select"), Gtk::RESPONSE_OK);
......@@ -341,7 +470,6 @@ void ImageGlom::on_menupopup_activate_select_file()
// Automatically delete the dialog when we no longer need it:
std::auto_ptr<Gtk::Dialog> dialog_keeper(dialog);
Application* pApp = get_application();
if(pApp)
dialog->set_transient_for(*pApp);
......@@ -459,11 +587,24 @@ void ImageGlom::setup_menu_usermode()
m_refActionGroup_UserModePopup = Gtk::ActionGroup::create();
m_refActionGroup_UserModePopup->add(Gtk::Action::create("ContextMenu_UserMode", "Context Menu") );
m_refActionOpenFile = Gtk::Action::create("ContextOpenFile", Gtk::Stock::OPEN);
m_refActionOpenFileWith = Gtk::Action::create("ContextOpenFileWith", Gtk::Stock::OPEN, _("Open With"));
m_refActionSaveFile = Gtk::Action::create("ContextSaveFile", Gtk::Stock::SAVE);
m_refActionSelectFile = Gtk::Action::create("ContextSelectFile", Gtk::Stock::EDIT, _("Choose File"));
m_refActionCopy = Gtk::Action::create("ContextCopy", Gtk::Stock::COPY);
m_refActionPaste = Gtk::Action::create("ContextPaste", Gtk::Stock::PASTE);
m_refActionClear = Gtk::Action::create("ContextClear", Gtk::Stock::CLEAR);
m_refActionGroup_UserModePopup->add(m_refActionOpenFile,
sigc::mem_fun(*this, &ImageGlom::on_menupopup_activate_open_file) );
m_refActionGroup_UserModePopup->add(m_refActionOpenFileWith,
sigc::mem_fun(*this, &ImageGlom::on_menupopup_activate_open_file_with) );
m_refActionGroup_UserModePopup->add(m_refActionSaveFile,
sigc::mem_fun(*this, &ImageGlom::on_menupopup_activate_save_file) );
m_refActionGroup_UserModePopup->add(m_refActionSelectFile,
sigc::mem_fun(*this, &ImageGlom::on_menupopup_activate_select_file) );
......@@ -487,6 +628,9 @@ void ImageGlom::setup_menu_usermode()
Glib::ustring ui_info =
"<ui>"
" <popup name='ContextMenu_UserMode'>"
" <menuitem action='ContextOpenFile'/>"
" <menuitem action='ContextOpenFileWith'/>"
" <menuitem action='ContextSaveFile'/>"
" <menuitem action='ContextSelectFile'/>"
" <menuitem action='ContextCopy'/>"
" <menuitem action='ContextPaste'/>"
......
......@@ -24,7 +24,6 @@
#include <gtkmm.h>
#include <libglom/data_structure/field.h>
#include "layoutwidgetfield.h"
#include "dialog_image_load_progress.h"
#include <gtkmm/builder.h>
namespace Glom
......@@ -59,12 +58,13 @@ public:
private:
void init();
// Note that these are normal signal handlers when glibmm was compiled
// without default signal handler API.
virtual bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
virtual bool on_button_press_event(GdkEventButton *event);
void on_menupopup_activate_open_file();
void on_menupopup_activate_open_file_with();
void on_menupopup_activate_save_file();
void on_menupopup_activate_select_file();
void on_menupopup_activate_copy();
void on_menupopup_activate_paste();
......@@ -78,7 +78,8 @@ private:
void setup_menu_usermode();
void scale();
bool save_file(const Glib::ustring& uri);
void open_with(const Glib::RefPtr<Gio::AppInfo>& app_info = Glib::RefPtr<Gio::AppInfo>());
Gtk::Image m_image;
Gtk::Frame m_frame;
......@@ -89,7 +90,8 @@ private:
Gtk::Menu* m_pMenuPopup_UserMode;
Glib::RefPtr<Gtk::ActionGroup> m_refActionGroup_UserModePopup;
Glib::RefPtr<Gtk::UIManager> m_refUIManager_UserModePopup;
Glib::RefPtr<Gtk::Action> m_refActionSelectFile, m_refActionCopy, m_refActionPaste, m_refActionClear;
Glib::RefPtr<Gtk::Action> m_refActionOpenFile, m_refActionOpenFileWith,
m_refActionSaveFile, m_refActionSelectFile, m_refActionCopy, m_refActionPaste, m_refActionClear;
bool m_read_only;
};
......
......@@ -72,7 +72,8 @@ void GlomXslUtils::transform_and_open(const xmlpp::Document& xml_document, const
std::cout << "After xslt: " << result << std::endl;
//Save it to a temporary file and show it in a browser:
const Glib::ustring temp_path = Glib::get_tmp_dir() + "/glom_printout.html";
const Glib::ustring temp_path = Glib::build_filename(
Glib::get_tmp_dir(), "glom_printout.html");
//std::cout << "temp_path=" << temp_path << std::endl;
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(temp_path);
......
2011-07-11 Murray Cumming <murrayc@murrayc-desktop>
reviewed by: <delete if not using a buddy>
* POTFILES.in:
2010-09-08 Murray Cumming <murrayc@murrayc-desktop>
reviewed by: <delete if not using a buddy>
......
......@@ -121,6 +121,7 @@ glom/mode_data/datawidget/datawidget.cc
glom/mode_data/db_adddel/db_adddel.cc
glom/mode_data/datawidget/dialog_choose_id.cc
glom/utility_widgets/dialog_image_load_progress.cc
glom/utility_widgets/dialog_image_save_progress.cc
glom/mode_data/datawidget/entry.cc
glom/utility_widgets/eggspreadtable/eggspreadtable.c
glom/utility_widgets/filechooserdialog_saveextras.cc
......@@ -139,6 +140,7 @@ ui/operator/dialog_data_invalid_format.glade
ui/operator/dialog_existing_or_new.glade
ui/operator/dialog_find_id.glade
ui/operator/dialog_image_load_progress.glade
ui/operator/dialog_image_save_progress.glade
ui/operator/dialog_import_csv.glade
ui/operator/dialog_import_csv_progress.glade
ui/operator/window_main.glade
......
......@@ -15,6 +15,7 @@
#include <glom/mode_data/datawidget/dialog_choose_id.h>
#include <glom/utility_widgets/dialog_flowtable.h>
#include <glom/utility_widgets/dialog_image_load_progress.h>
#include <glom/utility_widgets/dialog_image_save_progress.h>
#include <glom/mode_design/layout/dialog_choose_field.h>
#include <glom/mode_design/dialog_add_related_table.h>
#include <glom/mode_design/layout/layout_item_dialogs/dialog_buttonscript.h>
......@@ -88,6 +89,7 @@ int main(int argc, char *argv[])
instantiate_widget<DataWidgetChildren::Dialog_ChooseDate>();
instantiate_widget<Dialog_InvalidData>();
instantiate_widget<DialogImageLoadProgress>();
instantiate_widget<DialogImageSaveProgress>();
instantiate_widget<Dialog_ProgressCreating>();
//Developer mode UI:
......
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<object class="GtkDialog" id="dialog_image_progress">
<object class="GtkDialog" id="dialog_image_load_progress">
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="title" translatable="yes">Loading image</property>
......@@ -48,7 +48,7 @@
<property name="can_focus">False</property>
<property name="border_width">6</property>
<child>
<object class="GtkProgressBar" id="image_loading_progress_bar">
<object class="GtkProgressBar" id="progress_bar">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
......
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkDialog" id="dialog_image_save_progress">
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="title" translatable="yes">Saving Image</property>
<property name="window_position">center-on-parent</property>
<property name="default_width">640</property>
<property name="type_hint">normal</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button2">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">6</property>
<child>
<object class="GtkProgressBar" id="progress_bar">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-6">button2</action-widget>
</action-widgets>
</object>
</interface>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment