Opening files

In this step, we make our application show the contents of all the files that it is given on the commandline.

To this end, we add a data member to our application window and keep a pointer to the Gtk::Stack there. We get the pointer with a call to Gtk::Builder::get_widget() in the application window's constructor.

Now we revisit the ExampleAppWindow::open_file_view() method that is called for each commandline argument, and construct a Gtk::TextView that we then add as a page to the stack.

Note that we do not have to touch the stack switcher at all. It gets all its information from the stack that it belongs to. Here, we are passing the label to show for each file as the last argument to the Gtk::Stack::add() method.

Our application is beginning to take shape:

Figure 31.3. Opening files

Opening files

Source Code

File: exampleappwindow.h (For use with gtkmm 3, not gtkmm 2)

#ifndef GTKMM_EXAMPLEAPPWINDOW_H_
#define GTKMM_EXAMPLEAPPWINDOW_H_

#include <gtkmm.h>

class ExampleAppWindow : public Gtk::ApplicationWindow
{
public:
  ExampleAppWindow(BaseObjectType* cobject,
    const Glib::RefPtr<Gtk::Builder>& refBuilder);

  static ExampleAppWindow* create();

  void open_file_view(const Glib::RefPtr<Gio::File>& file);

protected:
  Glib::RefPtr<Gtk::Builder> m_refBuilder;
  Gtk::Stack* m_stack;
};

#endif /* GTKMM_EXAMPLEAPPWINDOW_H */

File: exampleapplication.h (For use with gtkmm 3, not gtkmm 2)

#include "../step1/exampleapplication.h"
// Equal to the corresponding file in step1

File: exampleapplication.cc (For use with gtkmm 3, not gtkmm 2)

#include "../step2/exampleapplication.cc"
// Equal to the corresponding file in step2

File: main.cc (For use with gtkmm 3, not gtkmm 2)

#include "../step1/main.cc"
// Equal to the corresponding file in step1

File: exampleappwindow.cc (For use with gtkmm 3, not gtkmm 2)

#include "exampleappwindow.h"
#include <iostream>
#include <stdexcept>

ExampleAppWindow::ExampleAppWindow(BaseObjectType* cobject,
  const Glib::RefPtr<Gtk::Builder>& refBuilder)
: Gtk::ApplicationWindow(cobject),
  m_refBuilder(refBuilder),
  m_stack(nullptr)
{
  m_refBuilder->get_widget("stack", m_stack);
  if (!m_stack)
    throw std::runtime_error("No \"stack\" object in window.ui");
}

//static
ExampleAppWindow* ExampleAppWindow::create()
{
  // Load the Builder file and instantiate its widgets.
  auto refBuilder = Gtk::Builder::create_from_resource("/org/gtkmm/exampleapp/window.ui");

  ExampleAppWindow* window = nullptr;
  refBuilder->get_widget_derived("app_window", window);
  if (!window)
    throw std::runtime_error("No \"app_window\" object in window.ui");

  return window;
}

void ExampleAppWindow::open_file_view(const Glib::RefPtr<Gio::File>& file)
{
  const auto basename = file->get_basename();

  auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
  scrolled->set_hexpand(true);
  scrolled->set_vexpand(true);
  scrolled->show();
  auto view = Gtk::make_managed<Gtk::TextView>();
  view->set_editable(false);
  view->set_cursor_visible(false);
  view->show();
  scrolled->add(*view);
  m_stack->add(*scrolled, basename, basename);

  try
  {
    char* contents = nullptr;
    gsize length = 0;
    
    file->load_contents(contents, length);
    view->get_buffer()->set_text(contents, contents+length);
    g_free(contents);
  }
  catch (const Glib::Error& ex)
  {
    std::cout << "ExampleAppWindow::open_file_view(\"" << file->get_parse_name()
      << "\"):\n  " << ex.what() << std::endl;
  }
}