打开文件

在这一步中,我们使我们的应用程序显示由命令行参数给定的文件的所有内容。

为此,我们向我们的应用程序窗口中添加一个数据成员,此保持一个指向Gtk::Stack的指针。我们通过在应用程序窗口的构造函数中调用Gtk::Builder::get_widget()获得指向该子部件的指针。

现在我们重访对每个命令行参数都会调用的ExampleAppWindow::open_file_view()成员函数,并构造一个Gtk::TextView然后将其作为页面添加到Gtk::Stack中。

最后,我们将Gtk::StackSwitcher添加到UI文件的标题栏区域,并告诉它如何显示Gtk::Stack的相关信息。

堆切换器(StackSwitcher)从其所属的堆(Stack)中获取其所需的关于显示选项卡的相关信息。在这,作为Gtk::Stack::add()方法的最后一个参数,我们为每个显示的文件传递一个标签。

我们的应用程序开始成形:

Figure 29-3打开文件

源代码

File: exampleapplication.h (For use with gtkmm 4)

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

File: exampleappwindow.h (For use with gtkmm 4)

#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: main.cc (For use with gtkmm 4)

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

File: exampleappwindow.cc (For use with gtkmm 4)

#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_stack = m_refBuilder->get_widget<Gtk::Stack>("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");

  auto window = Gtk::Builder::get_widget_derived<ExampleAppWindow>(refBuilder, "app_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 Glib::ustring basename = file->get_basename();

  auto scrolled = Gtk::make_managed<Gtk::ScrolledWindow>();
  scrolled->set_expand(true);
  auto view = Gtk::make_managed<Gtk::TextView>();
  view->set_editable(false);
  view->set_cursor_visible(false);
  scrolled->set_child(*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;
  }
}

File: exampleapplication.cc (For use with gtkmm 4)

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

File: window.ui (For use with gtkmm 4)

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <object class="GtkApplicationWindow" id="app_window">
    <property name="title" translatable="yes">Example Application</property>
    <property name="default-width">600</property>
    <property name="default-height">400</property>
    <property name="hide-on-close">True</property>
    <child type="titlebar">
      <object class="GtkHeaderBar" id="header">
        <child type="title">
          <object class="GtkStackSwitcher" id="tabs">
            <property name="stack">stack</property>
          </object>
        </child>
      </object>
    </child>
    <child>
      <object class="GtkBox" id="content_box">
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkStack" id="stack"/>
        </child>
      </object>
    </child>
  </object>
</interface>