1
/**************************************************************************
3
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
4
License: See LICENSE_gsmartcontrol.txt
5
***************************************************************************/
7
#ifndef GSC_TEXT_WINDOW_H
8
#define GSC_TEXT_WINDOW_H
10
#include <gtkmm/window.h>
11
#include <gtkmm/button.h>
12
#include <gtkmm/accelgroup.h>
13
#include <gtkmm/textview.h>
14
#include <gtkmm/filechooserdialog.h>
15
#include <gdk/gdkkeysyms.h> // GDK_Escape
18
#include "hz/fs_file.h"
20
#include "applib/app_ui_res_utils.h"
24
struct SmartctlOutputInstance { static const bool multi_instance = true; };
28
// use create() / destroy() with this class instead of new / delete!
31
// InstanceSwitch: e.g. supply 3 different classes to use 3 different single-instance windows.
32
template<class InstanceSwitch>
33
class GscTextWindow : public AppUIResWidget<GscTextWindow<InstanceSwitch>, InstanceSwitch::multi_instance> {
37
// name of glade/ui file without a .glade/.ui extension and quotes
38
APP_UI_RES_DATA_INIT(gsc_text_window);
40
// needed for glade, not inherited from parent because of templates
41
typedef GscTextWindow<InstanceSwitch> self_type;
44
// glade/gtkbuilder needs this constructor
45
GscTextWindow(typename Gtk::Window::BaseObjectType* gtkcobj, const app_ui_res_ref_t& ref_ui)
46
: AppUIResWidget<GscTextWindow<InstanceSwitch>, InstanceSwitch::multi_instance>(gtkcobj, ref_ui)
50
APP_GTKMM_CONNECT_VIRTUAL(delete_event); // make sure the event handler is called
52
Gtk::Button* save_as_button = 0;
53
APP_UI_RES_AUTO_CONNECT(save_as_button, clicked);
55
Gtk::Button* close_window_button = 0;
56
APP_UI_RES_AUTO_CONNECT(close_window_button, clicked);
61
Glib::RefPtr<Gtk::AccelGroup> accel_group = this->get_accel_group();
62
if (close_window_button) {
63
close_window_button->add_accelerator("clicked", accel_group, GDK_Escape,
64
Gdk::ModifierType(0), Gtk::AccelFlags(0));
70
// show(); // better show later, after set_text().
72
default_title_ = this->get_title();
76
virtual ~GscTextWindow()
80
void set_text(const Glib::ustring& title, const Glib::ustring& contents,
81
bool save_visible = false, bool use_monospace = false)
83
this->set_title(title + " - " + default_title_); // something - gsmartcontrol
85
this->contents_ = contents; // we save it to prevent its mangling through the widget
87
Gtk::TextView* textview = this->template lookup_widget<Gtk::TextView*>("main_textview");
89
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
90
buffer->set_text(contents);
93
Glib::RefPtr<Gtk::TextTag> tag = buffer->create_tag();
94
tag->property_family() = "Monospace";
95
buffer->apply_tag(tag, buffer->begin(), buffer->end());
99
Gtk::Button* save_as_button = this->template lookup_widget<Gtk::Button*>("save_as_button");
100
if (save_as_button) {
102
save_as_button->set_sensitive(true);
103
save_as_button->show();
105
save_as_button->hide();
106
save_as_button->set_sensitive(false); // disable accelerators
112
void set_save_filename(const std::string& filename)
114
save_filename_ = filename;
121
// -------------------- Callbacks
124
// ---------- override virtual methods
126
// by default, delete_event calls hide().
127
bool on_delete_event_before(GdkEventAny* e)
129
destroy(this); // deletes this object and nullifies instance
130
return true; // event handled, don't call default virtual handler
134
// ---------- other callbacks
136
void on_save_as_button_clicked()
138
static std::string last_dir;
140
Gtk::FileChooserDialog dialog(*this, "Save Data As...",
141
Gtk::FILE_CHOOSER_ACTION_SAVE);
143
// Add response buttons the the dialog
144
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
145
dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
147
#if APP_GTKMM_CHECK_VERSION(2, 8, 0)
148
dialog.set_do_overwrite_confirmation(true); // since gtkmm 2.8
151
if (!last_dir.empty())
152
dialog.set_current_folder(last_dir);
154
if (!save_filename_.empty())
155
dialog.set_current_name(save_filename_);
157
// Show the dialog and wait for a user response
158
int result = dialog.run(); // the main cycle blocks here
160
// Handle the response
162
case Gtk::RESPONSE_ACCEPT:
164
last_dir = dialog.get_current_folder(); // safe for the future
166
std::string file = dialog.get_filename();
168
if (!f.put_contents(this->contents_)) { // this will send to debug_ too.
169
gui_show_error_dialog("Cannot save data to file", f.get_error_utf8(), this);
174
case Gtk::RESPONSE_CANCEL: case Gtk::RESPONSE_DELETE_EVENT:
175
// nothing, the dialog is closed already
179
debug_out_error("app", DBG_FUNC_MSG << "Unknown dialog response code: " << result << ".\n");
185
void on_close_window_button_clicked()
192
Glib::ustring default_title_;
193
Glib::ustring contents_;
194
std::string save_filename_;