OSDN Git Service

Bookmark is implemented.
authorAiwota Programmer <aiwotaprog@tetteke.tk>
Sun, 28 Jun 2009 19:17:20 +0000 (04:17 +0900)
committerAiwota Programmer <aiwotaprog@tetteke.tk>
Sun, 28 Jun 2009 19:17:20 +0000 (04:17 +0900)
src/application_framework.cxx
src/application_framework.hxx
src/bookmark_item.cxx [new file with mode: 0644]
src/bookmark_item.hxx [new file with mode: 0644]
src/bookmark_window.cxx [new file with mode: 0644]
src/bookmark_window.hxx [new file with mode: 0644]

index 36dd67d..abc4f09 100644 (file)
@@ -29,6 +29,7 @@
 #include <gtkmm/uimanager.h>
 #include <gtkmm/actiongroup.h>
 #include <iostream>
+#include "bookmark_window.hxx"
 
 
 namespace dialektos {
@@ -75,6 +76,11 @@ void ApplicationFrameWork::build_menubar() {
   action_group_->add(Gtk::Action::create("ViewStatusbar", "Toggle _Statusbar"),
       sigc::mem_fun(*this, &ApplicationFrameWork::on_action_view_statusbar));
 
+  // Bookmark menu
+  action_group_->add(Gtk::Action::create("MenuBookmark", "_Bookmark"));
+  action_group_->add(Gtk::Action::create("BookmarkShow", "_Show Bookmarks"),
+      sigc::mem_fun(*this, &ApplicationFrameWork::on_action_bookmark_show));
+
   ui_manager_->insert_action_group(action_group_);
   add_accel_group(ui_manager_->get_accel_group());
 
@@ -92,6 +98,9 @@ void ApplicationFrameWork::build_menubar() {
     "      <menuitem action='ViewToolbar'/>"
     "      <menuitem action='ViewStatusbar'/>"
     "    </menu>"
+    "    <menu action='MenuBookmark'>"
+    "      <menuitem action='BookmarkShow'/>"
+    "    </menu>"
     "  </menubar>"
     "  <toolbar name='ToolBar'>"
     "    <toolitem action='ViewRefresh'/>"
@@ -140,6 +149,10 @@ void ApplicationFrameWork::on_action_view_statusbar() {
   if (statusbar_.is_visible()) statusbar_.hide(); else statusbar_.show();
 }
 
+void ApplicationFrameWork::on_action_bookmark_show() {
+  BookmarkWindow::create();
+}
+
 void ApplicationFrameWork::on_child_button_press(GdkEventButton* event) {
   if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
     popupmenu_->popup(event->button, event->time);
index f49774d..4d24a8e 100644 (file)
@@ -48,6 +48,7 @@ protected:
   virtual void on_action_view_menubar();
   virtual void on_action_view_toolbar();
   virtual void on_action_view_statusbar();
+  virtual void on_action_bookmark_show();
 
   virtual void on_child_button_press(GdkEventButton*);
 
diff --git a/src/bookmark_item.cxx b/src/bookmark_item.cxx
new file mode 100644 (file)
index 0000000..00e9628
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 by Aiwota Programmer
+ * aiwotaprog@tetteke.tk
+ *
+ * This file is part of Dialektos.
+ *
+ * Dialektos is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Dialektos is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Dialektos.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "bookmark_item.hxx"
+
+#include <boost/archive/xml_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/xpressive/xpressive.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <sstream>
+#include <fstream>
+#include <vector>
+#include <string>
+#include "convert/cp932.hxx"
+
+
+namespace dialektos {
+
+namespace bookmark {
+
+
+std::vector<Item> from_html(const std::string& html) {
+  using namespace boost::xpressive;
+
+  const sregex regex = as_xpr("<A HREF=")
+    >> (s1=as_xpr("http://") >> +~set[as_xpr('>')|as_xpr(' ')])
+    >> *~as_xpr('>') >> '>'
+    >> (s2=+~as_xpr('<')) >> as_xpr("</A>") >> *_;
+  const sregex regex_category = "<BR><BR><B>"
+    >> (s1=+~as_xpr('<')) >> "</B><BR>" >> *_;
+
+  std::vector<Item> list;
+  std::stringstream ss;
+  ss << html;
+  std::string current_category;
+  std::string line;
+  while (std::getline(ss, line)) {
+    boost::algorithm::trim_right(line);
+    const std::string utf8 = convert::cp932(line);
+
+    if (utf8.empty()) {
+      current_category.clear();
+      continue;
+    }
+
+    smatch what;
+
+    if (regex_match(utf8, what, regex_category)) {
+      current_category = what[1];
+      continue;
+    }
+
+    if (regex_match(utf8, what, regex)) {
+      Item item;
+      item.uri = what[1];
+      item.name = what[2];
+      item.categories.push_back("bbsmenu");
+      if (!current_category.empty())
+        item.categories.push_back(current_category);
+      list.push_back(item);
+    }
+  }
+
+  return list;
+}
+
+std::vector<Item> from_xml(const boost::filesystem::path& xml) {
+  std::vector<Item> items;
+
+  if (!boost::filesystem::exists(xml) || !boost::filesystem::is_regular(xml))
+    return items;
+
+  std::ifstream ifs(xml.file_string().c_str());
+  try {
+    boost::archive::xml_iarchive ia(ifs);
+    ia >> boost::serialization::make_nvp("Bookmarks", items);
+  } catch (const boost::archive::archive_exception& e) {
+    std::cerr << "bookmark::from_xml(): " << e.what() << " "
+    << xml << std::endl;
+  }
+  return items;
+}
+
+void to_xml(const boost::filesystem::path& xml,
+    const std::vector<Item>& items) {
+  std::ofstream ofs(xml.file_string().c_str());
+  try {
+    boost::archive::xml_oarchive oa(ofs);
+    oa << boost::serialization::make_nvp("Bookmarks", items);
+  } catch (const boost::archive::archive_exception& e) {
+    std::cerr << "bookmark::to_xml(): " << e.what() << " " << xml << std::endl;
+  }
+}
+
+
+} // namespace bookmark
+
+} // namespace dialektos
diff --git a/src/bookmark_item.hxx b/src/bookmark_item.hxx
new file mode 100644 (file)
index 0000000..149b2fb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 by Aiwota Programmer
+ * aiwotaprog@tetteke.tk
+ *
+ * This file is part of Dialektos.
+ *
+ * Dialektos is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Dialektos is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Dialektos.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BOOKMARK_ITEM_HXX
+#define BOOKMARK_ITEM_HXX
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/string.hpp>
+#include <boost/filesystem/path.hpp>
+#include <vector>
+#include <string>
+#include <algorithm>
+
+
+namespace dialektos {
+
+namespace bookmark {
+
+
+struct Item {
+  std::string name;
+  std::string uri;
+  std::vector<std::string> categories;
+
+  bool belongs_to(const std::string& category) const {
+    return std::find(categories.begin(), categories.end(), category) !=
+      categories.end();
+  }
+
+private:
+  friend class boost::serialization::access;
+  template <typename ArchiveType>
+  void serialize(ArchiveType& ar, const unsigned int version) {
+    ar & boost::serialization::make_nvp("Name", name);
+    ar & boost::serialization::make_nvp("URI", uri);
+    ar & boost::serialization::make_nvp("Categories", categories);
+  }
+};
+
+std::vector<Item> from_html(const std::string& html);
+std::vector<Item> from_xml(const boost::filesystem::path&);
+void to_xml(const boost::filesystem::path&, const std::vector<Item>&);
+
+} // namespace bookmark
+
+} // namespace dialektos
+
+
+#endif
diff --git a/src/bookmark_window.cxx b/src/bookmark_window.cxx
new file mode 100644 (file)
index 0000000..37fcdb5
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2009 by Aiwota Programmer
+ * aiwotaprog@tetteke.tk
+ *
+ * This file is part of Dialektos.
+ *
+ * Dialektos is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Dialektos is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Dialektos.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "bookmark_window.hxx"
+
+#include <sigc++/functors/mem_fun.h>
+#include <gtkmm/stock.h>
+#include <boost/lambda/lambda.hpp>
+#include <boost/foreach.hpp>
+#include <boost/filesystem/path.hpp>
+#include <iostream>
+#include <vector>
+#include <cstdlib>
+#include "http_get.hxx"
+#include "http_header.hxx"
+#include "http_response.hxx"
+#include "bookmark_item.hxx"
+#include "uri_opener.hxx"
+
+
+namespace dialektos {
+
+
+boost::scoped_ptr<BookmarkWindow> BookmarkWindow::single_window;
+const std::string BookmarkWindow::filename = "bookmarks.xml";
+
+
+void BookmarkWindow::create() {
+  if (single_window) single_window->present();
+  else single_window.reset(new BookmarkWindow);
+}
+
+
+BookmarkWindow::BookmarkWindow() : Gtk::Window(),
+vbox_(), hpaned_(), scrolled1_(), scrolled2_(),
+view_category_(), view_bookmark_(), statusbar_(),
+category_column_record_(), bookmark_column_record_(),
+category_list_store_(Gtk::ListStore::create(category_column_record_)),
+bookmark_list_store_(Gtk::ListStore::create(bookmark_column_record_)),
+ui_manager_(Gtk::UIManager::create()),
+action_group_(Gtk::ActionGroup::create()),
+menubar_(0), toolbar_(0), popupmenu_(0),
+http_getter_(),
+bookmarks_() {
+
+  build_menu();
+
+  set_default_size(250,300);
+
+  add(vbox_);
+  vbox_.pack_start(*menubar_, Gtk::PACK_SHRINK);
+  vbox_.pack_start(*toolbar_, Gtk::PACK_SHRINK);
+  vbox_.pack_start(hpaned_);
+  vbox_.pack_start(statusbar_, Gtk::PACK_SHRINK);
+
+  hpaned_.pack1(scrolled1_, Gtk::SHRINK);
+  hpaned_.pack2(scrolled2_);
+  hpaned_.set_position(100);
+
+  scrolled1_.add(view_category_);
+  scrolled2_.add(view_bookmark_);
+
+  scrolled1_.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+  scrolled2_.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+
+  view_category_.set_model(category_list_store_);
+  view_category_.append_column("Category", category_column_record_.category_);
+
+  view_bookmark_.set_model(bookmark_list_store_);
+  view_bookmark_.append_column("Bookmark", bookmark_column_record_.name_);
+
+  view_category_.signal_cursor_changed().connect(
+      sigc::mem_fun(*this, &BookmarkWindow::on_category_cursor_changed));
+  view_category_.signal_row_activated().connect(
+      sigc::mem_fun(*this, &BookmarkWindow::on_category_row_activated));
+  view_bookmark_.signal_row_activated().connect(
+      sigc::mem_fun(*this, &BookmarkWindow::on_bookmark_row_activated));
+
+  bookmarks_ = bookmark::from_xml(get_xml_path());
+  reconstruct_category();
+
+  show_all();
+}
+
+BookmarkWindow::~BookmarkWindow() {
+}
+
+bool BookmarkWindow::on_delete_event(GdkEventAny*) {
+  single_window.reset();
+  return false;
+}
+
+void BookmarkWindow::build_menu() {
+  // File menu
+  action_group_->add(Gtk::Action::create("MenuFile", "_File"));
+
+  // View menu
+  action_group_->add(Gtk::Action::create("MenuView", "_View"));
+  action_group_->add(Gtk::Action::create("ViewRefresh", Gtk::Stock::REFRESH),
+      sigc::mem_fun(*this, &BookmarkWindow::on_action_view_refresh));
+  action_group_->add(Gtk::Action::create("ViewStop", Gtk::Stock::STOP),
+      sigc::mem_fun(*this, &BookmarkWindow::on_action_view_stop));
+  action_group_->add(Gtk::Action::create("ViewMenubar", "Toggle _Menubar"),
+      sigc::mem_fun(*this, &BookmarkWindow::on_action_view_menubar));
+  action_group_->add(Gtk::Action::create("ViewToolbar", "Toggle _Toolbar"),
+      sigc::mem_fun(*this, &BookmarkWindow::on_action_view_toolbar));
+  action_group_->add(Gtk::Action::create("ViewStatusbar", "Toggle _Statusbar"),
+      sigc::mem_fun(*this, &BookmarkWindow::on_action_view_statusbar));
+
+  ui_manager_->insert_action_group(action_group_);
+  add_accel_group(ui_manager_->get_accel_group());
+
+  Glib::ustring ui_info =
+    "<ui>"
+    "  <menubar name='MenuBar'>"
+    "    <menu action='MenuFile'>"
+    "    </menu>"
+    "    <menu action='MenuView'>"
+    "      <menuitem action='ViewRefresh'/>"
+    "      <menuitem action='ViewStop'/>"
+    "      <separator/>"
+    "      <menuitem action='ViewMenubar'/>"
+    "      <menuitem action='ViewToolbar'/>"
+    "      <menuitem action='ViewStatusbar'/>"
+    "    </menu>"
+    "  </menubar>"
+    "  <toolbar name='ToolBar'>"
+    "    <toolitem action='ViewRefresh'/>"
+    "    <toolitem action='ViewStop'/>"
+    "  </toolbar>"
+    "  <popup name='MenuPopup'>"
+    "    <menuitem action='ViewRefresh'/>"
+    "    <menuitem action='ViewStop'/>"
+    "    <separator/>"
+    "    <menuitem action='ViewMenubar'/>"
+    "  </popup>"
+    "</ui>";
+
+  ui_manager_->add_ui_from_string(ui_info);
+
+  menubar_ = ui_manager_->get_widget("/MenuBar");
+  toolbar_ = ui_manager_->get_widget("/ToolBar");
+  popupmenu_ =
+    dynamic_cast<Gtk::Menu*>(ui_manager_->get_widget("/MenuPopup"));
+}
+
+void BookmarkWindow::on_action_view_refresh() {
+  if (http_getter_) return;
+
+  statusbar_.push("HTTP/1.0 GET...");
+
+  const std::string uri = "http://menu.2ch.net/bbsmenu.html";
+  http::Header request_header;
+  request_header.set_host("menu.2ch.net");
+
+  http_getter_.reset(new http::GetInThread(uri, request_header));
+  http_getter_->signal_end().connect(
+      sigc::mem_fun(*this, &BookmarkWindow::on_http_get_end));
+  http_getter_->run();
+}
+
+void BookmarkWindow::on_action_view_stop() {
+  if (http_getter_) http_getter_->cancel();
+}
+
+void BookmarkWindow::on_action_view_menubar() {
+  if (menubar_->is_visible()) menubar_->hide(); else menubar_->show();
+}
+
+void BookmarkWindow::on_action_view_toolbar() {
+  if (toolbar_->is_visible()) toolbar_->hide(); else toolbar_->show();
+}
+
+void BookmarkWindow::on_action_view_statusbar() {
+  if (statusbar_.is_visible()) statusbar_.hide(); else statusbar_.show();
+}
+
+void BookmarkWindow::on_http_get_end(bool success) {
+  //  const std::string uri = http_getter_->get_uri();
+  //  const http::Header request_header = http_getter_->get_request_header();
+  const http::Response response = http_getter_->get_response();
+  const boost::system::error_code err = http_getter_->get_error();
+  http_getter_.reset(0);
+  if (err) {
+    statusbar_.push(err.message());
+    return;
+  }
+  if (!success) {
+    statusbar_.push("Canceled.");
+    return;
+  }
+
+  statusbar_.push(
+      response.get_status_line().get_line() + " " +
+      response.get_header().get_last_modified());
+
+  const int code = response.get_status_line().get_code();
+  if (code != 200) return;
+
+  bookmarks_ = bookmark::from_html(response.get_content());
+  reconstruct_category();
+
+  save_content();
+}
+
+void BookmarkWindow::on_category_cursor_changed() {
+  Glib::RefPtr<const Gtk::TreeSelection> selection =
+    view_category_.get_selection();
+
+  std::vector<Gtk::TreeModel::Path> paths = selection->get_selected_rows();
+  if (paths.empty()) return;
+
+  on_category_row_activated(paths[0], 0);
+}
+
+void BookmarkWindow::on_category_row_activated(
+    const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) {
+
+  Gtk::TreeRow row = *(category_list_store_->get_iter(path));
+  const std::string category = row[category_column_record_.category_];
+
+  bookmark_list_store_->clear();
+
+  BOOST_FOREACH(const bookmark::Item& item, bookmarks_) {
+    if (item.belongs_to(category)) {
+      Gtk::TreeModel::Row row = *(bookmark_list_store_->append());
+      row[bookmark_column_record_.name_] = item.name;
+      row[bookmark_column_record_.uri_] = item.uri;
+    }
+  }
+}
+
+void BookmarkWindow::on_bookmark_row_activated(const Gtk::TreeModel::Path& path,
+    Gtk::TreeViewColumn*) {
+  Gtk::TreeRow row = *(bookmark_list_store_->get_iter(path));
+  const std::string& uri = row[bookmark_column_record_.uri_];
+  uri_opener::open(uri);
+}
+
+void BookmarkWindow::save_content() {
+  bookmark::to_xml(get_xml_path(), bookmarks_);
+}
+
+void BookmarkWindow::reconstruct_category() {
+  std::vector<std::string> categories;
+
+  BOOST_FOREACH(const bookmark::Item& item, bookmarks_) {
+    BOOST_FOREACH(const std::string& category, item.categories) {
+      if (std::find(categories.begin(), categories.end(), category) ==
+        categories.end())
+        categories.push_back(category);
+    }
+  }
+
+  category_list_store_->clear();
+
+  BOOST_FOREACH(const std::string& category, categories) {
+    Gtk::TreeModel::Row row = *(category_list_store_->append());
+    row[category_column_record_.category_] = category;
+  }
+}
+
+boost::filesystem::path BookmarkWindow::get_xml_path() const {
+  const boost::filesystem::path home(std::getenv("HOME"));
+  return home / ".dialektos" / filename;
+}
+
+
+} // namespace dialektos
diff --git a/src/bookmark_window.hxx b/src/bookmark_window.hxx
new file mode 100644 (file)
index 0000000..02422eb
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2009 by Aiwota Programmer
+ * aiwotaprog@tetteke.tk
+ *
+ * This file is part of Dialektos.
+ *
+ * Dialektos is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Dialektos is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Dialektos.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BOOKMARK_WINDOW_HXX
+#define BOOKMARK_WINDOW_HXX
+
+
+#include <gtkmm/window.h>
+#include <gtkmm/box.h>
+#include <gtkmm/paned.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/statusbar.h>
+#include <gtkmm/widget.h>
+#include <gtkmm/uimanager.h>
+#include <gtkmm/actiongroup.h>
+#include <gtkmm/liststore.h>
+#include <glibmm/refptr.h>
+#include <boost/scoped_ptr.hpp>
+#include <boost/filesystem/path.hpp>
+#include <string>
+#include <vector>
+#include "bookmark_item.hxx"
+
+
+namespace dialektos {
+
+namespace http {
+  struct GetInThread;
+}
+
+
+class BookmarkWindow : public Gtk::Window {
+
+  struct CategoryColumnRecord : public Gtk::TreeModelColumnRecord {
+    CategoryColumnRecord() : Gtk::TreeModelColumnRecord() {
+      add(category_);
+    }
+    Gtk::TreeModelColumn<std::string> category_;
+  };
+
+  struct BookmakrItemColumnRecord : public Gtk::TreeModelColumnRecord {
+    BookmakrItemColumnRecord() : Gtk::TreeModelColumnRecord() {
+      add(name_);
+      add(uri_);
+    }
+    Gtk::TreeModelColumn<std::string> name_;
+    Gtk::TreeModelColumn<std::string> uri_;
+  };
+
+public:
+  static void create();
+  virtual ~BookmarkWindow();
+protected:
+  BookmarkWindow();
+  virtual bool on_delete_event(GdkEventAny*);
+private:
+  void build_menu();
+
+  void on_action_view_refresh();
+  void on_action_view_stop();
+  void on_action_view_menubar();
+  void on_action_view_toolbar();
+  void on_action_view_statusbar();
+
+  void on_http_get_end(bool);
+
+  void on_category_cursor_changed();
+  void on_category_row_activated(const Gtk::TreeModel::Path&,
+      Gtk::TreeViewColumn*);
+  void on_bookmark_row_activated(const Gtk::TreeModel::Path&,
+      Gtk::TreeViewColumn*);
+
+  void save_content();
+
+  void reconstruct_category();
+  boost::filesystem::path get_xml_path() const;
+
+  Gtk::VBox vbox_;
+  Gtk::HPaned hpaned_;
+  Gtk::ScrolledWindow scrolled1_;
+  Gtk::ScrolledWindow scrolled2_;
+  Gtk::TreeView view_category_;
+  Gtk::TreeView view_bookmark_;
+  Gtk::Statusbar statusbar_;
+
+  CategoryColumnRecord category_column_record_;
+  BookmakrItemColumnRecord bookmark_column_record_;
+  Glib::RefPtr<Gtk::ListStore> category_list_store_;
+  Glib::RefPtr<Gtk::ListStore> bookmark_list_store_;
+
+  Glib::RefPtr<Gtk::UIManager> ui_manager_;
+  Glib::RefPtr<Gtk::ActionGroup> action_group_;
+  Gtk::Widget* menubar_;
+  Gtk::Widget* toolbar_;
+  Gtk::Menu* popupmenu_;
+
+  boost::scoped_ptr<http::GetInThread> http_getter_;
+
+  std::vector<bookmark::Item> bookmarks_;
+
+  static boost::scoped_ptr<BookmarkWindow> single_window;
+  static const std::string filename;
+};
+
+}
+
+
+#endif