Sorry this is a long posting.
main.cpp
Code:
#include "MainWindow.h"
#include <gtkmm/main.h>
#include <iostream>
int main(int argc, char *argv[]) {
Gnome::Gda::init();
Gtk::Main kit(argc, argv);
Glib::RefPtr<Gtk::Builder> refBuilder = Gtk::Builder::create_from_file("MainWindow.glade");
MainWindow *window;
refBuilder->get_widget_derived("window1", window);
//Shows the window and returns when it is closed.
Gtk::Main::run(*window);
return 0;
}
MainWindow.cpp
Code:
#include "MainWindow.h"
#include <libgdamm.h>
#include <gtkmm.h>
#include <iostream>
#include <memory>
#include "DBUtil.h"
#include "FormDialog.h"
MainWindow::MainWindow(BaseObjectType* cobject, Glib::RefPtr<Gtk::Builder> refBuilder) :
Gtk::Window(cobject),
m_refBuilder(refBuilder) {
DBUtil dbUtil;
// Creacion conexion DB
std::string db("SQLite");
std::string options("DB_DIR=.;DB_NAME=example_db");
cnc = dbUtil.create_connection(db, options);
// Creacion parser SQL
parser = cnc->create_parser();
if (!parser) /* @cnc doe snot provide its own parser => use default one */
parser = Gnome::Gda::SqlParser::create();
// Inicializacion db (si no está inicializada!)
dbUtil.create_table(cnc, parser);
// Tomar elementos de glade y asociarlos a objetos
m_refBuilder->get_widget("scrolledwindow1", m_ScrolledWindow);
m_refBuilder->get_widget("button1", m_Button_New);
m_refBuilder->get_widget("button2", m_Button_Delete);
m_ScrolledWindow->add(m_Treeview);
m_Treeview.mostrar_contenido_pacientes(cnc);
// Asociar manejadores de eventos a los botones
if (m_Button_New) {
m_Button_New->signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::on_button_new));
}
if (m_Button_Delete) {
m_Button_Delete->signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::on_button_delete));
}
show_all_children();
}
MainWindow::~MainWindow() {
}
void MainWindow::on_button_new() {
std::cout << " Pulsado boton nuevo " << std::endl;
FormDialog *dialog;
Glib::RefPtr<Gtk::Builder> refBuilder = Gtk::Builder::create_from_file("FormDialog.glade");
refBuilder->get_widget_derived("dialog1", dialog);
dialog->setConnectionData(cnc, parser);
dialog->run();
m_Treeview.mostrar_contenido_pacientes(cnc);
delete dialog;
}
void MainWindow::on_button_delete() {
int id = m_Treeview.getSelectedId();
}
FormDialog.cpp
Code:
/*
* File: FormDialog.cpp
* Author: noelia
*
* Created on July 7, 2011, 6:45 PM
*/
#include "FormDialog.h"
#include <gtkmm.h>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "DBUtil.h"
FormDialog::FormDialog(BaseObjectType* cobject, Glib::RefPtr<Gtk::Builder> refBuilder) :
Gtk::Dialog(cobject),
m_refBuilder(refBuilder) {
ayuda_win = 0;
image = 0;
visor_win = 0;
m_refBuilder->get_widget("button1", button1); //Add
m_refBuilder->get_widget("button2", button2); //Salir
m_refBuilder->get_widget("button3", button3);
m_refBuilder->get_widget("entry1", entry1);
m_refBuilder->get_widget("entry2", entry2);
m_refBuilder->get_widget("entry3", entry3);
if (button1) {
button1->signal_clicked().connect(sigc::mem_fun(*this, &FormDialog::on_button_add));
}
if (button2) {
button2->signal_clicked().connect(sigc::mem_fun(*this, &FormDialog::on_button_quit));
}
if (button3) {
button3->signal_clicked().connect(sigc::mem_fun(*this, &FormDialog::on_button_sel));
}
show_all_children();
}
FormDialog::~FormDialog() {
delete ayuda_win;
delete visor_win;
}
void FormDialog::setConnectionData(const Glib::RefPtr<Gnome::Gda::Connection>& cnc, Glib::RefPtr<Gnome::Gda::SqlParser> &parser) {
_cnc = cnc;
_parser = parser;
}
int FormDialog::check_file(const char * path){
if (strstr(path, ".jpg") || strstr(path, ".jpeg")) {
return 1;
}
// ayuda_win should now be defined in the class of FormDialog
if (ayuda_win) {
// We already have the window, so just show it
ayuda_win->present();
} else {
Glib::ustring us("\n Help! \n");
ayuda_win = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);
ayuda_win->set_title ("Ayuda");
ayuda_win->move(15,55);
ayuda_win(add(Gtk::manage(new Gtk::Label(us, false)));
ayuda_win->show_all();
}
return 0;
}
int FormDialog::copyF(const char *origS, const char *destS)
{
int c;
FILE *orig = fopen(origS, "r");
if (!orig) {
fprintf(stderr,"%s: No such file or directory\n",origS);
return 0;
}
FILE *dest = fopen(destS, "w");
if (!dest) {
fprintf(stderr,"%s: No such file or directory\n",destS);
fclose(orig);
return 0;
}
while ((c = getc(orig)) != EOF)
putc(c, dest);
fclose(orig);
fclose(dest);
return 1;
}
void FormDialog::on_button_sel() {
Gtk::FileChooserDialog dialog("Selecciona la imagen a procesar",
Gtk::FILE_CHOOSER_ACTION_OPEN);
dialog.add_button (Gtk::Stock::OPEN,
Gtk::RESPONSE_ACCEPT);
dialog.add_button (Gtk::Stock::CANCEL,
Gtk::RESPONSE_CANCEL);
switch (dialog.run())
{
case Gtk::RESPONSE_ACCEPT:
{
if (check_file(dialog.get_filename().c_str())) {
Glib::RefPtr<Gdk::Pixbuf> pb = Gdk::Pixbuf::create_from_file(dialog.get_filename());
pb = pb->scale_simple(800, 600,Gdk::INTERP_BILINEAR);
if (!visor_win) {
// No window so create it
visor_win = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);
Gtk::HBox *box = Gtk::manage(new Gtk::HBox());
box->set_spaceing(5);
image = Gtk::manage(new Gtk::Image());
box->pack_start(*image, true, true);
visor_win->add(*box);
}
image->set(pb);
visor_win->move(315, 50);
visor_win->set_title(Glib::filename_to_utf8(dialog.get_filename()));
visor_win->show_all();
visor_win->present();
const char * auxpath = dialog.get_filename().c_str();
path = std::string(auxpath);
// std::cout << "pathImagen = " << path << std::endl;
}
break;
}
default:
break;
}
// dialog.hide(); -- Do not need this as it will be destroyed once out of scope
// we will be out of scope on the next line :)
}
void FormDialog::on_button_add() {
if (!path.empty()) {
// Falta comprobar errores!!!
// Cajas de entradas.
Glib::ustring p1(entry1->get_text());
Glib::ustring p2(entry2->get_text());
Glib::ustring p3(entry3->get_text());
DBUtil dbutil;
const Glib::ustring sql = "SELECT max(ref) FROM Pacientes";
Glib::RefPtr<Gnome::Gda::DataModel> data_model = dbutil.run_sql_select(_cnc, sql);
Glib::RefPtr<Gnome::Gda::DataModelIter> iter = data_model->create_iter();
int id = -1;
Gtk::TreeModel::Row row;
while (iter->move_next()) {
int i = 0;
id = iter->get_value_at(i++).get_int();
}
id++;
Glib::ustring str = Glib::ustring::format(id);
Glib::ustring query = "INSERT INTO Pacientes VALUES ("
+ str + "," + p1 + ",'" + p2 + "','" + p3 + "','" + path + "',0)";
mkdir(p1.c_str(),0777);
std::string pathF = std::string("./");
pathF.append(p1.c_str());
pathF.append("/");
std::string aux = "/";
int ultimoSlash = 0;
int nImagen = 0;
int contador = 0;
char slash = aux.at(0);
for (size_t i=0; i < path.length(); i++) {
if (path.at(i) == slash) {
ultimoSlash = contador;
nImagen = 0;
} else
nImagen++;
contador++;
}
pathF.append(path.substr(ultimoSlash+1,nImagen));
copyF(path.c_str(), pathF.c_str());
path.clear();
dbutil.run_sql_non_select(_cnc, _parser, query);
}
else check_file("");
}
void FormDialog::on_button_quit() {
path.clear();
hide();
}
In the method FormDialog::copyF(const char *origS,const char *destS) If fopen(origS, "r"); succeds but fopen(destS, "w"); fails it will exit leaving the first file still open. Also orig==NULL and !orig do the same thing, with the latter being the perfered usage.
In the method void FormDialog::setConnectionData(const Glib::RefPtr<Gnome::Gda::Connection>& cnc, Glib::RefPtr<Gnome::Gda::SqlParser> &parser) { You are using objects start start with an underscore. These are reserved for the compiler and you should not be using them in your own code. I have not changed this, but leave it to you to choose a name.
In the method int FormDialog::check_file(const char * path), the objects "us", "ayuda_win" and "etiqueta" are lost. I changed the way "us" is used, so that it will be automatically deallocated when out of scope. Make "ayuda_win" a member of the FormDialog class and delete it in the destructor. Also introduce a way of reusing the object. Set the Gtk::Label object to be managed by the top level window "ayuda_win", so it is deallocated when the window "ayuda_win" is destroyed.
In the method void FormDialog::on_button_sel(), the objects "visor_win", "box", "image" were lost track of. Here the objects "visor_win" and "image" should be placed into the FormDialog class. This way we can delete the window when FormDialog is deleted. Again we set the box and image objects to be managed by the top level window (visor_win). I also used Glib::filename_to_utf8() to convert the file name into a displayable UTF8 form. This is used as the way the filename is stored on the file system may not be in UTF8 and GTK expects all displayed strings to be in UTF8.
In method void FormDialog::on_button_add(), the object "str" is never freed, so this is a memory leak. By using a stack based Glib::ustring str, it will be automatically freed when out of scope. To do the string conversion I used Glib::ustring::format(). Note that this is safe from memory over runs and is totally type safe. Just so that you know, you can use '+' to append strings together when using Glib::ustring. It can make code look clearer instead of using append. But both do the same thing.
Here I have not used any smart pointers. I prefer to use smart pointers to keep track of windows, as it can take care of automatic deallocation of objects. There are many implementations such as the one in Glibmm, Boost and in the new C++ standard.
Note that I have not tested any of this code.
Note there is the book at
http://developer.gnome.org/gtkmm-tutorial/stable/ which gives a very good tutorial for the use of gtkmm.