GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Fri Apr 18, 2014 3:24 am

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Gtk::Window* cannot be closed
PostPosted: Mon Dec 05, 2011 11:30 pm 
Offline
Familiar Face

Joined: Tue Nov 29, 2011 6:19 pm
Posts: 9
Why could be the causes of a window cannot be closed?

I got a couple of misfuntion windows, they cannot be closed while the dialog whose create is opened.
In another version of the application i was creating the windows in the same way and now they cannot be closed.

The main window is created in the main:
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;
}


the dialog is created in the main window:
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();
}


And finally the two windows whose cannot be closed are in **** and ++++
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) {


    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() {
}

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")!=NULL  || strstr(path, ".jpeg")!=NULL) {
        return 1;
}
else {

   Glib::ustring* us = new Glib::ustring("\n  Help!   \n");

****   Gtk::Window* ayuda_win = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);
   ayuda_win->set_title ("Ayuda");
   ayuda_win->move(15,55);
   Gtk::Label* etiqueta = new Gtk::Label(*us,false);

       ayuda_win->add(*etiqueta);
**** ayuda_win->show_all();

  return 0; }

}

int FormDialog::copyF(const char *origS,const char *destS)
{
  int c;
  FILE *orig,*dest;
  orig = fopen(origS, "r");
  dest = fopen(destS, "w");

  if(orig==NULL || !orig) {
      fprintf(stderr,"%s: No such file or directory\n",origS);
      return 0;
  }

  else if(dest==NULL || !dest) {
      fprintf(stderr,"%s: No such file or directory\n",destS);
      return 0;
  }

  while((c=getc(orig))!=EOF)
    putc(c,dest);

   fclose(orig);
   fclose(dest);
   return 1;

}



void FormDialog::on_button_sel() {
   +++++Gtk::Window* visor_win = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);

   Gtk::HBox* box = new Gtk::HBox();
   box->set_spacing(5);


   Gtk::Image* image = new Gtk::Image();

   box->pack_start (*image, true, true);

   visor_win->add(*box);

   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);
      image->set(pb);

         visor_win->move(315,50);
      visor_win->set_title (dialog.get_filename().c_str());
   +++++visor_win->show_all();
      
      const char * auxpath = dialog.get_filename().c_str();

         path = std::string(auxpath);
//      std::cout << "pathImagen = " << path << std::endl;
}
       break;
    }
      default:
         break;
   }
   dialog.hide();
}

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++;
    char *str = new char[30];
    sprintf(str,"%i",id);

    Glib::ustring query("INSERT INTO Pacientes VALUES (");
    query.append(str);
    query.append(",");
    query.append(p1);
    query.append(",'");
    query.append(p2);
    query.append("','");
    query.append(p3);
    query.append("','");
    query.append(path);   
    query.append("',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();
}


Top
 Profile  
 
 Post subject: Re: Gtk::Window* cannot be closed
PostPosted: Tue Dec 06, 2011 9:22 am 
Offline
Familiar Face

Joined: Tue Nov 29, 2011 6:19 pm
Posts: 9
Any hint/clue/fix would be appreciate! When the dialog whose opened that windows is closed, them can be closed normally ... is a strage behaviour

Also i'm doing a bump ... cause this bots not only start new threads ... the try to answer questions! Not the best answers btw, but .... 'It's something.jpg' :P


Top
 Profile  
 
 Post subject: Re: Gtk::Window* cannot be closed
PostPosted: Thu Dec 08, 2011 11:19 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 709
Location: UK
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.

_________________
E.


Top
 Profile  
 
 Post subject: Re: Gtk::Window* cannot be closed
PostPosted: Sat Dec 10, 2011 7:45 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 709
Location: UK
Just one bit that was missed out. Here we will over ride the on_hide() of the FormDialog class. When the FormDialog is hidden the signal handler void FormDialog::on_hide() is called which then hides the windows that the class owns.

Code:
// Add to FormDialog class in the protected section
//   virtual void on_hide();
//
// Hide then other windows when our FormDialog window is hidden.

void FormDialog::on_hide()
{
    if (ayuda_win) ayuda_win->hide();
    if (visor_win) visor_win->hide();
}

_________________
E.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group