aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-06-04 15:36:07 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-06-04 15:36:07 +0000
commit1d6f454162b54ada09ead2ab89d379cd1c1b280a (patch)
tree44c841a27f04366b63a7bdcd6994c10de9bec475
parent33bcc6f83dc12269adedcbbbff2a51f58be3743c (diff)
downloadpaludis-1d6f454162b54ada09ead2ab89d379cd1c1b280a.tar.gz
paludis-1d6f454162b54ada09ead2ab89d379cd1c1b280a.tar.xz
r3198@snowflake: ciaranm | 2007-06-04 16:34:55 +0100
Import gtkpaludis
-rw-r--r--configure.ac27
-rw-r--r--src/clients/gtkpaludis/Makefile.am27
-rw-r--r--src/clients/gtkpaludis/gtkpaludis.cc26
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/Makefile.am50
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/categories_list.cc61
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/categories_list.hh29
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/categories_list_model.cc109
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/categories_list_model.hh43
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/main_notebook.cc98
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/main_notebook.hh31
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/main_notebook_page.cc25
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/main_notebook_page.hh22
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/main_window.cc70
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/main_window.hh33
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/markup.cc49
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/markup.hh17
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/messages_page.cc95
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/messages_page.hh32
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/package_buttons.cc91
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/package_buttons.hh34
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_filter.cc78
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_filter.hh26
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_list.cc96
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_list.hh33
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_list_filtered_model.cc91
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_list_filtered_model.hh40
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_list_model.cc276
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_list_model.hh51
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_package_filter.cc60
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_package_filter.hh29
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_model.cc78
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_model.hh39
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_option.hh17
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_page.cc164
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_page.hh51
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter.cc61
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter.hh29
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter_model.cc115
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter_model.hh45
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_text_filter.cc60
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_text_filter.hh29
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source.cc59
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source.hh29
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_model.cc70
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_model.hh39
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_option.hh15
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/query_notebook.cc56
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/query_notebook.hh28
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/query_notebook_page.cc26
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/query_notebook_page.hh23
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/query_window.cc122
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/query_window.hh41
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repositories_list.cc57
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repositories_list.hh29
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repositories_list_model.cc86
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repositories_list_model.hh42
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repositories_page.cc70
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repositories_page.hh30
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repository_buttons.cc69
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repository_buttons.hh30
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repository_info.cc45
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repository_info.hh26
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repository_info_model.cc94
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/repository_info_model.hh49
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/threaded_window.cc181
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/threaded_window.hh46
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/version_info.cc68
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/version_info.hh30
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc146
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/version_info_model.hh47
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/versions_list.cc99
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/versions_list.hh31
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/versions_list_model.cc196
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/versions_list_model.hh51
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/versions_page.cc72
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/versions_page.hh31
-rw-r--r--src/clients/gtkpaludis/vtemm/Makefile.am70
-rw-r--r--src/clients/gtkpaludis/vtemm/converts/Makefile.am9
-rw-r--r--src/clients/gtkpaludis/vtemm/converts/convert.m430
-rw-r--r--src/clients/gtkpaludis/vtemm/converts/convert_base.m469
-rw-r--r--src/clients/gtkpaludis/vtemm/defs/Makefile.am51
-rw-r--r--src/clients/gtkpaludis/vtemm/defs/enum.pl230
-rw-r--r--src/clients/gtkpaludis/vtemm/defs/generate_defs_vte.cc36
-rw-r--r--src/clients/gtkpaludis/vtemm/reaper.ccg65
-rw-r--r--src/clients/gtkpaludis/vtemm/reaper.hg50
-rw-r--r--src/clients/gtkpaludis/vtemm/terminal_widget.ccg159
-rw-r--r--src/clients/gtkpaludis/vtemm/terminal_widget.hg181
87 files changed, 5519 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 8c7ce13..4b6ac95 100644
--- a/configure.ac
+++ b/configure.ac
@@ -337,6 +337,7 @@ need_xml_check=
need_pcrepp_check=
need_syck_check=
need_gem_check=
+need_gtkmm_check=
dnl {{{ we need libebt.
dnl don't use AC_CHECK_HEADER, it does silly things
@@ -916,7 +917,7 @@ AC_DEFINE_UNQUOTED([DEFAULT_DISTRIBUTION], "$DEFAULT_DISTRIBUTION", [Default dis
dnl }}}
dnl {{{ clients
-ALL_CLIENTS="adjutrix contrarius inquisitio paludis qualudis"
+ALL_CLIENTS="adjutrix contrarius gtkpaludis inquisitio paludis qualudis"
DEFAULT_CLIENTS="adjutrix paludis"
if test x"$ENABLE_QA" = "xyes" ; then
DEFAULT_CLIENTS="$DEFAULT_CLIENTS qualudis"
@@ -930,6 +931,7 @@ AC_ARG_WITH([clients],
adjutrix A tool for tree querying
contrarius The cross toolchain creator
+ gtkpaludis GUI client (experimental)
inquisitio A search client
paludis The Paludis console client
qualudis The QA console client],
@@ -944,6 +946,9 @@ AC_SUBST([BUILD_CLIENTS])
if echo $clients | tr ' ' '\n' | grep '^inquisitio$' >/dev/null ; then
need_pcrepp_check=yes
fi
+if echo $clients | tr ' ' '\n' | grep '^gtkpaludis$' >/dev/null ; then
+ need_gtkmm_check=yes
+fi
dnl }}}
dnl {{{ libxml2 check
@@ -994,6 +999,21 @@ if test "x$need_gem_check" = "xyes" ; then
fi
dnl }}}
+dnl {{{ gtkmm check
+if test "x$need_gtkmm_check" = "xyes" ; then
+ PKG_CHECK_MODULES([gtkmm], [gtkmm-2.4 >= 2.8.0])
+ PKG_CHECK_MODULES([gthread], [gthread-2.0 >= 2.12.0])
+ PKG_CHECK_MODULES([vte], [vte >= 0.12.1])
+ PKG_CHECK_MODULES([pygtk], [pygtk-2.0 >= 2.6.0])
+ AC_CHECK_FUNCS([posix_openpt], [], [AC_MSG_ERROR([I need posix_openpt])])
+ GLIBMM_LIBDIR=`pkg-config --variable=libdir glibmm-2.4`
+ GMMPROC_DIR=$GLIBMM_LIBDIR/glibmm-2.4/proc
+ AC_SUBST(GMMPROC_DIR)
+ GMMPROC=$GMMPROC_DIR/gmmproc
+ AC_SUBST(GMMPROC)
+fi
+dnl }}}
+
dnl {{{ is sed gnu sed
AC_MSG_CHECKING([if we need a sed wrapper])
AC_SUBST([NEED_SED_WRAPPER])
@@ -1162,6 +1182,11 @@ AC_OUTPUT(
src/common_args/Makefile
src/clients/Makefile
src/clients/contrarius/Makefile
+ src/clients/gtkpaludis/Makefile
+ src/clients/gtkpaludis/vtemm/Makefile
+ src/clients/gtkpaludis/vtemm/defs/Makefile
+ src/clients/gtkpaludis/vtemm/converts/Makefile
+ src/clients/gtkpaludis/libgtkpaludis/Makefile
src/clients/inquisitio/Makefile
src/clients/paludis/Makefile
src/clients/qualudis/Makefile
diff --git a/src/clients/gtkpaludis/Makefile.am b/src/clients/gtkpaludis/Makefile.am
new file mode 100644
index 0000000..1ac0664
--- /dev/null
+++ b/src/clients/gtkpaludis/Makefile.am
@@ -0,0 +1,27 @@
+CLEANFILES = *~
+MAINTAINERCLEANFILES = Makefile.in
+SUBDIRS = vtemm libgtkpaludis .
+
+AM_CXXFLAGS = -I$(top_srcdir) -I$(top_srcdir)/src/clients/gtkpaludis \
+ @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@ \
+ $(gtkmm_CFLAGS) $(gthread_CFLAGS) \
+ @PALUDIS_CXXFLAGS_NO_WOLD_STYLE_CAST@ @PALUDIS_CXXFLAGS_NO_WREDUNDANT_DECLS@ @PALUDIS_CXXFLAGS_NO_WSHADOW@
+
+bin_PROGRAMS = gtkpaludis
+
+TESTS =
+
+gtkpaludis_SOURCES = \
+ gtkpaludis.cc
+
+gtkpaludis_LDADD = \
+ $(builddir)/libgtkpaludis/libgtkpaludis.a \
+ $(builddir)/vtemm/libvtemm.a \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/libpaludisenvironments.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(gtkmm_LIBS) $(gthread_LIBS) $(vte_LIBS)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/src/clients/gtkpaludis/gtkpaludis.cc b/src/clients/gtkpaludis/gtkpaludis.cc
new file mode 100644
index 0000000..cd311ef
--- /dev/null
+++ b/src/clients/gtkpaludis/gtkpaludis.cc
@@ -0,0 +1,26 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include <paludis/environments/environment_maker.hh>
+#include <paludis/util/log.hh>
+#include <libgtkpaludis/main_window.hh>
+#include <gtkmm.h>
+#include <cstdlib>
+
+using namespace gtkpaludis;
+
+int main(int argc, char *argv[])
+{
+ Glib::thread_init();
+ Gtk::Main kit(argc, argv);
+
+ paludis::Log::get_instance()->set_log_level(paludis::ll_qa);
+ paludis::Log::get_instance()->set_program_name(argv[0]);
+ paludis::tr1::shared_ptr<paludis::Environment> env(
+ paludis::EnvironmentMaker::get_instance()->make_from_spec(""));
+
+ MainWindow main_window(env.get());
+ Gtk::Main::run(main_window);
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/Makefile.am b/src/clients/gtkpaludis/libgtkpaludis/Makefile.am
new file mode 100644
index 0000000..c07e40d
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/Makefile.am
@@ -0,0 +1,50 @@
+CLEANFILES = *~
+MAINTAINERCLEANFILES = Makefile.in
+
+noinst_LIBRARIES = libgtkpaludis.a
+libgtkpaludis_a_SOURCES = \
+ categories_list.cc categories_list.hh \
+ categories_list_model.cc categories_list_model.hh \
+ main_notebook.cc main_notebook.hh \
+ main_notebook_page.cc main_notebook_page.hh \
+ main_window.cc main_window.hh \
+ markup.cc markup.hh \
+ messages_page.cc messages_page.hh \
+ package_buttons.cc package_buttons.hh \
+ packages_filter.cc packages_filter.hh \
+ packages_list.cc packages_list.hh \
+ packages_list_filtered_model.cc packages_list_filtered_model.hh \
+ packages_list_model.cc packages_list_model.hh \
+ packages_page.cc packages_page.hh \
+ packages_package_filter.cc packages_package_filter.hh \
+ packages_package_filter_model.cc packages_package_filter_model.hh \
+ packages_repository_filter.cc packages_repository_filter.hh \
+ packages_repository_filter_model.cc packages_repository_filter_model.hh \
+ packages_text_filter.cc packages_text_filter.hh \
+ packages_text_filter_source.cc packages_text_filter_source.hh \
+ packages_text_filter_source_model.cc packages_text_filter_source_model.hh \
+ query_notebook.cc query_notebook.hh \
+ query_notebook_page.cc query_notebook_page.hh \
+ query_window.cc query_window.hh \
+ repositories_list.cc repositories_list.hh \
+ repositories_list_model.cc repositories_list_model.hh \
+ repositories_page.cc repositories_page.hh \
+ repository_buttons.cc repository_buttons.hh \
+ repository_info.cc repository_info.hh \
+ repository_info_model.cc repository_info_model.hh \
+ threaded_window.cc threaded_window.hh \
+ version_info.cc version_info.hh \
+ version_info_model.cc version_info_model.hh \
+ versions_list.cc versions_list.hh \
+ versions_list_model.cc versions_list_model.hh \
+ versions_page.cc versions_page.hh \
+ packages_package_filter_option.hh \
+ packages_text_filter_source_option.hh
+
+AM_CXXFLAGS = @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@ -I$(top_srcdir)/src/clients/gtkpaludis \
+ $(gtkmm_CFLAGS) $(gthread_CFLAGS) -I$(top_srcdir) \
+ @PALUDIS_CXXFLAGS_NO_WOLD_STYLE_CAST@ @PALUDIS_CXXFLAGS_NO_WREDUNDANT_DECLS@ @PALUDIS_CXXFLAGS_NO_WSHADOW@
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/categories_list.cc b/src/clients/gtkpaludis/libgtkpaludis/categories_list.cc
new file mode 100644
index 0000000..f4687df
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/categories_list.cc
@@ -0,0 +1,61 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "categories_list.hh"
+#include "categories_list_model.hh"
+#include "packages_page.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<CategoriesList>
+ {
+ Glib::RefPtr<CategoriesListModel> model;
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ model(new CategoriesListModel(m, p)),
+ main_window(m),
+ packages_page(p)
+ {
+ }
+ };
+}
+
+CategoriesList::CategoriesList(MainWindow * const m, PackagesPage * const p) :
+ Gtk::TreeView(),
+ PrivateImplementationPattern<CategoriesList>(new Implementation<CategoriesList>(m, p))
+{
+ set_model(_imp->model);
+
+ append_column("Category", _imp->model->columns().col_cat_name);
+
+ signal_cursor_changed().connect(sigc::mem_fun(this, &CategoriesList::handle_signal_cursor_changed));
+}
+
+CategoriesList::~CategoriesList()
+{
+}
+
+void
+CategoriesList::populate()
+{
+ _imp->model->populate();
+}
+
+void
+CategoriesList::handle_signal_cursor_changed()
+{
+ if (get_selection()->get_selected())
+ _imp->packages_page->set_category(paludis::tr1::shared_ptr<CategoryNamePart>(new CategoryNamePart(
+ static_cast<Glib::ustring>((*get_selection()->get_selected())[_imp->model->columns().col_cat_name]).raw())));
+ else
+ _imp->packages_page->set_category(
+ paludis::tr1::shared_ptr<CategoryNamePart>());
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/categories_list.hh b/src/clients/gtkpaludis/libgtkpaludis/categories_list.hh
new file mode 100644
index 0000000..98f62d9
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/categories_list.hh
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_CATEGORIES_LIST_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_CATEGORIES_LIST_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <gtkmm/treeview.h>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class CategoriesList :
+ public Gtk::TreeView,
+ private paludis::PrivateImplementationPattern<CategoriesList>
+ {
+ protected:
+ void handle_signal_cursor_changed();
+
+ public:
+ CategoriesList(MainWindow * const m, PackagesPage * const p);
+ ~CategoriesList();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/categories_list_model.cc b/src/clients/gtkpaludis/libgtkpaludis/categories_list_model.cc
new file mode 100644
index 0000000..c6dac77
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/categories_list_model.cc
@@ -0,0 +1,109 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "categories_list_model.hh"
+#include "main_window.hh"
+#include "packages_page.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<CategoriesListModel>
+ {
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+ CategoriesListModel::Columns columns;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ main_window(m),
+ packages_page(p)
+ {
+ }
+ };
+}
+
+CategoriesListModel::CategoriesListModel(MainWindow * const m, PackagesPage * const p) :
+ PrivateImplementationPattern<CategoriesListModel>(new Implementation<CategoriesListModel>(m, p)),
+ Gtk::ListStore(_imp->columns)
+{
+}
+
+CategoriesListModel::~CategoriesListModel()
+{
+}
+
+void
+CategoriesListModel::populate()
+{
+ _imp->main_window->paludis_thread_action(
+ sigc::mem_fun(this, &CategoriesListModel::populate_in_paludis_thread), "Populating categories list model");
+}
+
+void
+CategoriesListModel::populate_in_paludis_thread()
+{
+ paludis::tr1::shared_ptr<CategoryNamePartCollection> columns(
+ new CategoryNamePartCollection::Concrete);
+
+ paludis::tr1::shared_ptr<RepositoryNameCollection> repos(
+ _imp->packages_page->get_repository_filter()->repositories(*_imp->main_window->environment()));
+
+ if (repos)
+ {
+ for (RepositoryNameCollection::Iterator r(repos->begin()), r_end(repos->end()) ;
+ r != r_end ; ++r)
+ {
+ paludis::tr1::shared_ptr<const CategoryNamePartCollection> cats(
+ _imp->main_window->environment()->package_database()->fetch_repository(*r)->category_names());
+ std::copy(cats->begin(), cats->end(), columns->inserter());
+ }
+ }
+ else
+ {
+ for (IndirectIterator<PackageDatabase::RepositoryIterator>
+ r(indirect_iterator(_imp->main_window->environment()->package_database()->begin_repositories())),
+ r_end(indirect_iterator(_imp->main_window->environment()->package_database()->end_repositories())) ;
+ r != r_end ; ++r)
+ {
+ paludis::tr1::shared_ptr<const CategoryNamePartCollection> cats(r->category_names());
+ std::copy(cats->begin(), cats->end(), columns->inserter());
+ }
+ }
+
+ _imp->main_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &CategoriesListModel::populate_in_gui_thread), columns));
+}
+
+void
+CategoriesListModel::populate_in_gui_thread(paludis::tr1::shared_ptr<const CategoryNamePartCollection> names)
+{
+ clear();
+ for (CategoryNamePartCollection::Iterator n(names->begin()), n_end(names->end()) ;
+ n != n_end ; ++n)
+ (*append())[_imp->columns.col_cat_name] = stringify(*n);
+}
+
+
+CategoriesListModel::Columns::Columns()
+{
+ add(col_cat_name);
+}
+
+CategoriesListModel::Columns::~Columns()
+{
+}
+
+CategoriesListModel::Columns &
+CategoriesListModel::columns()
+{
+ return _imp->columns;
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/categories_list_model.hh b/src/clients/gtkpaludis/libgtkpaludis/categories_list_model.hh
new file mode 100644
index 0000000..1ff1e0e
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/categories_list_model.hh
@@ -0,0 +1,43 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_CATEGORIES_LIST_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_CATEGORIES_LIST_MODEL_HH 1
+
+#include <gtkmm/liststore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class CategoriesListModel :
+ private paludis::PrivateImplementationPattern<CategoriesListModel>,
+ public Gtk::ListStore
+ {
+ protected:
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread(paludis::tr1::shared_ptr<const paludis::CategoryNamePartCollection> names);
+
+ public:
+ CategoriesListModel(MainWindow * const m, PackagesPage * const p);
+ ~CategoriesListModel();
+
+ void populate();
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<Glib::ustring> col_cat_name;
+ };
+
+ Columns & columns();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/main_notebook.cc b/src/clients/gtkpaludis/libgtkpaludis/main_notebook.cc
new file mode 100644
index 0000000..f5e4f79
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/main_notebook.cc
@@ -0,0 +1,98 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "main_notebook.hh"
+#include "main_notebook_page.hh"
+#include "repositories_page.hh"
+#include "packages_page.hh"
+#include "messages_page.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <map>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<MainNotebook>
+ {
+ MainWindow * const main_window;
+
+ PackagesPage packages_page;
+ RepositoriesPage repositories_page;
+
+ MessagesPage messages_page;
+ bool messages_starred;
+
+ std::map<int, MainNotebookPage *> pages_by_index;
+
+ sigc::connection signal_switch_page_connection;
+
+ Implementation(MainWindow * const m, MainNotebook * const n) :
+ main_window(m),
+ packages_page(m),
+ repositories_page(m),
+ messages_page(m, n),
+ messages_starred(false)
+ {
+ }
+ };
+}
+
+MainNotebook::MainNotebook(MainWindow * const m) :
+ Gtk::Notebook(),
+ PrivateImplementationPattern<MainNotebook>(new Implementation<MainNotebook>(m, this))
+{
+ _imp->pages_by_index.insert(std::make_pair(
+ append_page(_imp->packages_page, "Packages"),
+ &_imp->packages_page));
+
+ _imp->pages_by_index.insert(std::make_pair(
+ append_page(_imp->repositories_page, "Repositories"),
+ &_imp->repositories_page));
+
+ _imp->pages_by_index.insert(std::make_pair(
+ append_page(_imp->messages_page, "Messages"),
+ &_imp->messages_page));
+
+ _imp->signal_switch_page_connection = signal_switch_page().connect(
+ sigc::mem_fun(*this, &MainNotebook::handle_switch_page));
+}
+
+MainNotebook::~MainNotebook()
+{
+ _imp->signal_switch_page_connection.disconnect();
+}
+
+void
+MainNotebook::handle_switch_page(GtkNotebookPage *, guint page)
+{
+ std::map<int, MainNotebookPage *>::const_iterator f(_imp->pages_by_index.find(page));
+ if (_imp->pages_by_index.end() != f)
+ {
+ f->second->populate_once();
+ if (f->second == &_imp->messages_page)
+ unmark_messages_page();
+ }
+}
+
+void
+MainNotebook::mark_messages_page()
+{
+ if (! _imp->messages_starred)
+ {
+ _imp->messages_starred = true;
+ set_tab_label_text(_imp->messages_page, "Messages *");
+ }
+}
+
+void
+MainNotebook::unmark_messages_page()
+{
+ if (_imp->messages_starred)
+ {
+ _imp->messages_starred = false;
+ set_tab_label_text(_imp->messages_page, "Messages");
+ }
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/main_notebook.hh b/src/clients/gtkpaludis/libgtkpaludis/main_notebook.hh
new file mode 100644
index 0000000..1d0c4bd
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/main_notebook.hh
@@ -0,0 +1,31 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_GTKPALUDIS_LIBGTKPALUDIS_MAIN_NOTEBOOK_HH
+#define GTKPALUDIS_GUARD_GTKPALUDIS_LIBGTKPALUDIS_MAIN_NOTEBOOK_HH 1
+
+#include <gtkmm/notebook.h>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class MainNotebook :
+ public Gtk::Notebook,
+ private paludis::PrivateImplementationPattern<MainNotebook>
+ {
+ protected:
+ void handle_switch_page(GtkNotebookPage *, guint);
+
+ public:
+ MainNotebook(MainWindow * const);
+ ~MainNotebook();
+
+ void populate();
+
+ void mark_messages_page();
+ void unmark_messages_page();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/main_notebook_page.cc b/src/clients/gtkpaludis/libgtkpaludis/main_notebook_page.cc
new file mode 100644
index 0000000..32adfea
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/main_notebook_page.cc
@@ -0,0 +1,25 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "main_notebook_page.hh"
+
+using namespace gtkpaludis;
+
+MainNotebookPage::MainNotebookPage() :
+ _populated(false)
+{
+}
+
+MainNotebookPage::~MainNotebookPage()
+{
+}
+
+void
+MainNotebookPage::populate_once()
+{
+ if (_populated)
+ return;
+
+ populate();
+ _populated = true;
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/main_notebook_page.hh b/src/clients/gtkpaludis/libgtkpaludis/main_notebook_page.hh
new file mode 100644
index 0000000..8c66476
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/main_notebook_page.hh
@@ -0,0 +1,22 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_MAIN_NOTEBOOK_PAGE_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_MAIN_NOTEBOOK_PAGE_HH 1
+
+namespace gtkpaludis
+{
+ class MainNotebookPage
+ {
+ private:
+ bool _populated;
+
+ public:
+ MainNotebookPage();
+ virtual ~MainNotebookPage() = 0;
+
+ void populate_once();
+ virtual void populate() = 0;
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/main_window.cc b/src/clients/gtkpaludis/libgtkpaludis/main_window.cc
new file mode 100644
index 0000000..0affe10
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/main_window.cc
@@ -0,0 +1,70 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "main_window.hh"
+#include "main_notebook.hh"
+#include <gtkmm/statusbar.h>
+#include <gtkmm/table.h>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<MainWindow>
+ {
+ Gtk::Table main_table;
+ MainNotebook main_notebook;
+ Gtk::Statusbar status_bar;
+
+ Implementation(MainWindow * const m) :
+ main_table(2, 1),
+ main_notebook(m)
+ {
+ }
+ };
+}
+
+MainWindow::MainWindow(Environment * const e) :
+ ThreadedWindow(Gtk::WINDOW_TOPLEVEL, e),
+ PrivateImplementationPattern<MainWindow>(new Implementation<MainWindow>(this)),
+ _imp(PrivateImplementationPattern<MainWindow>::_imp)
+{
+ set_title("gtkPaludis");
+ set_default_size(800, 600);
+ set_border_width(4);
+
+ _imp->main_table.attach(_imp->main_notebook, 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL,
+ Gtk::EXPAND | Gtk::FILL, 4, 4);
+ _imp->main_table.attach(_imp->status_bar, 0, 1, 1, 2, Gtk::EXPAND | Gtk::FILL,
+ Gtk::FILL, 4, 4);
+
+ add(_imp->main_table);
+ show_all();
+
+ _imp->status_bar.set_has_resize_grip(true);
+}
+
+MainWindow::~MainWindow()
+{
+}
+
+void
+MainWindow::push_status_message(const std::string & s)
+{
+ _imp->status_bar.push(s);
+}
+
+void
+MainWindow::pop_status_message()
+{
+ _imp->status_bar.pop();
+}
+
+void
+MainWindow::do_set_sensitive(const bool v)
+{
+ _imp->main_notebook.set_sensitive(v);
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/main_window.hh b/src/clients/gtkpaludis/libgtkpaludis/main_window.hh
new file mode 100644
index 0000000..8e469b6
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/main_window.hh
@@ -0,0 +1,33 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_GTKPALUDIS_MAIN_WINDOW_HH
+#define GTKPALUDIS_GUARD_GTKPALUDIS_MAIN_WINDOW_HH 1
+
+#include <libgtkpaludis/threaded_window.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow :
+ public ThreadedWindow,
+ private paludis::PrivateImplementationPattern<MainWindow>
+ {
+ private:
+ paludis::PrivateImplementationPattern<MainWindow>::ImpPtr & _imp;
+
+ protected:
+ virtual void push_status_message(const std::string &);
+ virtual void pop_status_message();
+
+ virtual void do_set_sensitive(const bool);
+
+ public:
+ MainWindow(paludis::Environment * const);
+ ~MainWindow();
+
+ using ThreadedWindow::sensitise;
+ using ThreadedWindow::desensitise;
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/markup.cc b/src/clients/gtkpaludis/libgtkpaludis/markup.cc
new file mode 100644
index 0000000..4231591
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/markup.cc
@@ -0,0 +1,49 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "markup.hh"
+
+using namespace gtkpaludis;
+
+std::string
+gtkpaludis::markup_escape(const std::string & s)
+{
+ std::string result;
+ for (std::string::size_type p(0) ; p < s.length() ; ++p)
+ {
+ switch (s[p])
+ {
+ case '<':
+ result.append("&lt;");
+ break;
+ case '>':
+ result.append("&gt;");
+ break;
+ case '&':
+ result.append("&amp;");
+ break;
+ default:
+ result.append(1, s[p]);
+ break;
+ }
+ }
+ return result;
+}
+
+std::string
+gtkpaludis::markup_bold(const std::string & s)
+{
+ return "<span weight=\"bold\">" + s + "</span>";
+}
+
+std::string
+gtkpaludis::markup_italic(const std::string & s)
+{
+ return "<span style=\"italic\">" + s + "</span>";
+}
+
+std::string
+gtkpaludis::markup_foreground(const std::string & c, const std::string & s)
+{
+ return "<span foreground=\"" + c + "\">" + s + "</span>";
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/markup.hh b/src/clients/gtkpaludis/libgtkpaludis/markup.hh
new file mode 100644
index 0000000..9b0bc41
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/markup.hh
@@ -0,0 +1,17 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_MARKUP_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_MARKUP_HH 1
+
+#include <string>
+
+namespace gtkpaludis
+{
+ std::string markup_escape(const std::string & s);
+ std::string markup_foreground(const std::string & c, const std::string & s);
+ std::string markup_bold(const std::string & s);
+ std::string markup_italic(const std::string & s);
+}
+
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/messages_page.cc b/src/clients/gtkpaludis/libgtkpaludis/messages_page.cc
new file mode 100644
index 0000000..13478f2
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/messages_page.cc
@@ -0,0 +1,95 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "messages_page.hh"
+#include "main_notebook.hh"
+
+#include <paludis/query.hh>
+#include <paludis/util/fd_output_stream.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/log.hh>
+#include <gtkmm/scrolledwindow.h>
+#include <vtemm/terminal_widget.hh>
+#include <iostream>
+#include <cstdlib>
+#include <fcntl.h>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<MessagesPage>
+ {
+ MainWindow * const main_window;
+ MainNotebook * const main_notebook;
+
+ Gtk::ScrolledWindow terminal_scroll;
+ Vte::Terminal terminal;
+
+ int master_fd, slave_fd;
+
+ paludis::tr1::shared_ptr<FDOutputStream> messages_stream;
+
+ sigc::connection terminal_cursor_moved_connection;
+
+ Implementation(MainWindow * const m, MessagesPage * const, MainNotebook * const n) :
+ main_window(m),
+ main_notebook(n),
+ master_fd(posix_openpt(O_RDWR | O_NOCTTY))
+ {
+ grantpt(master_fd);
+ unlockpt(master_fd);
+ slave_fd = open(ptsname(master_fd), O_RDWR);
+
+ messages_stream.reset(new FDOutputStream(slave_fd));
+ }
+
+ ~Implementation()
+ {
+ close(master_fd);
+ close(slave_fd);
+ }
+ };
+}
+
+MessagesPage::MessagesPage(MainWindow * const m, MainNotebook * const n) :
+ Gtk::Table(1, 1),
+ MainNotebookPage(),
+ PrivateImplementationPattern<MessagesPage>(new Implementation<MessagesPage>(m, this, n))
+{
+ _imp->terminal.set_pty(dup(_imp->master_fd));
+ set_run_command_stdout_fds(_imp->slave_fd, _imp->master_fd);
+ set_run_command_stderr_fds(_imp->slave_fd, _imp->master_fd);
+ PStream::set_stderr_fd(_imp->slave_fd, _imp->master_fd);
+ Log::get_instance()->set_log_stream(_imp->messages_stream.get());
+
+ _imp->terminal.set_scroll_on_output(true);
+
+ _imp->terminal_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
+ _imp->terminal_scroll.add(_imp->terminal);
+ attach(_imp->terminal_scroll, 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 4, 4);
+
+ _imp->terminal_cursor_moved_connection = _imp->terminal.signal_cursor_moved().connect(
+ sigc::mem_fun(this, &MessagesPage::handle_terminal_cursor_moved));
+}
+
+MessagesPage::~MessagesPage()
+{
+ _imp->terminal_cursor_moved_connection.disconnect();
+ Log::get_instance()->set_log_stream(&std::cerr);
+}
+
+void
+MessagesPage::populate()
+{
+}
+
+void
+MessagesPage::handle_terminal_cursor_moved()
+{
+ _imp->main_notebook->mark_messages_page();
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/messages_page.hh b/src/clients/gtkpaludis/libgtkpaludis/messages_page.hh
new file mode 100644
index 0000000..21c8788
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/messages_page.hh
@@ -0,0 +1,32 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_MESSAGES_PAGE_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_MESSAGES_PAGE_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <libgtkpaludis/main_notebook_page.hh>
+#include <gtkmm/table.h>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class MainNotebook;
+
+ class MessagesPage :
+ public Gtk::Table,
+ public MainNotebookPage,
+ private paludis::PrivateImplementationPattern<MessagesPage>
+ {
+ protected:
+ void handle_terminal_cursor_moved();
+
+ public:
+ MessagesPage(MainWindow * const m, MainNotebook * const n);
+ ~MessagesPage();
+
+ void populate();
+ };
+}
+
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/package_buttons.cc b/src/clients/gtkpaludis/libgtkpaludis/package_buttons.cc
new file mode 100644
index 0000000..fbdc7b1
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/package_buttons.cc
@@ -0,0 +1,91 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "package_buttons.hh"
+#include "main_window.hh"
+#include "query_window.hh"
+#include "packages_page.hh"
+#include <gtkmm/button.h>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repository.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackageButtons>
+ {
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+
+ Gtk::Button install_button;
+ Gtk::Button uninstall_button;
+ Gtk::Button query_button;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ main_window(m),
+ packages_page(p),
+ install_button("Install..."),
+ uninstall_button("Uninstall..."),
+ query_button("Query...")
+ {
+ }
+ };
+}
+
+PackageButtons::PackageButtons(MainWindow * const m, PackagesPage * const p) :
+ Gtk::HButtonBox(),
+ PrivateImplementationPattern<PackageButtons>(new Implementation<PackageButtons>(m, p))
+{
+ set_layout(Gtk::BUTTONBOX_END);
+ set_spacing(10);
+
+ _imp->install_button.set_sensitive(false);
+ add(_imp->install_button);
+
+ _imp->uninstall_button.set_sensitive(false);
+ add(_imp->uninstall_button);
+
+ _imp->query_button.set_sensitive(false);
+ _imp->query_button.signal_clicked().connect(sigc::mem_fun(this, &PackageButtons::handle_query_button_clicked));
+ add(_imp->query_button);
+}
+
+PackageButtons::~PackageButtons()
+{
+}
+
+void
+PackageButtons::populate()
+{
+ _imp->main_window->paludis_thread_action(
+ sigc::bind(sigc::mem_fun(this, &PackageButtons::populate_in_paludis_thread),
+ _imp->packages_page->get_qpn()), "Updating package buttons");
+}
+
+void
+PackageButtons::populate_in_paludis_thread(paludis::tr1::shared_ptr<const QualifiedPackageName> q)
+{
+ _imp->main_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &PackageButtons::populate_in_gui_thread),
+ q, false, false));
+}
+
+void
+PackageButtons::populate_in_gui_thread(const bool u, const bool v, const bool w)
+{
+ _imp->query_button.set_sensitive(u);
+ _imp->install_button.set_sensitive(v);
+ _imp->uninstall_button.set_sensitive(w);
+}
+
+void
+PackageButtons::handle_query_button_clicked()
+{
+ QueryWindow * q(new QueryWindow(_imp->main_window, *_imp->packages_page->get_qpn()));
+ q->show_all();
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/package_buttons.hh b/src/clients/gtkpaludis/libgtkpaludis/package_buttons.hh
new file mode 100644
index 0000000..6794206
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/package_buttons.hh
@@ -0,0 +1,34 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGE_BUTTONS_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGE_BUTTONS_HH 1
+
+#include <gtkmm/buttonbox.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackageButtons :
+ public Gtk::HButtonBox,
+ private paludis::PrivateImplementationPattern<PackageButtons>
+ {
+ private:
+ void populate_in_paludis_thread(paludis::tr1::shared_ptr<const paludis::QualifiedPackageName>);
+ void populate_in_gui_thread(const bool, const bool, const bool);
+
+ protected:
+ void handle_query_button_clicked();
+
+ public:
+ PackageButtons(MainWindow * const m, PackagesPage * const p);
+ ~PackageButtons();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_filter.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_filter.cc
new file mode 100644
index 0000000..1eb15cb
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_filter.cc
@@ -0,0 +1,78 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_filter.hh"
+#include "packages_repository_filter.hh"
+#include "packages_package_filter.hh"
+#include "packages_text_filter.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <gtkmm/label.h>
+#include <gtkmm/table.h>
+#include <gtkmm/expander.h>
+#include <gtkmm/box.h>
+#include <gtkmm/checkbutton.h>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesFilter>
+ {
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+ PackagesRepositoryFilter packages_repository_filter;
+ PackagesPackageFilter packages_package_filter;
+ PackagesTextFilter packages_text_filter;
+
+ Gtk::Expander standard_expander;
+ Gtk::Expander extra_expander;
+ Gtk::Table standard_table;
+ Gtk::Table extra_table;
+
+ Gtk::Label extra_label;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ main_window(m),
+ packages_page(p),
+ packages_repository_filter(m, p),
+ packages_package_filter(m, p),
+ packages_text_filter(m, p),
+ standard_expander("Filters:"),
+ extra_expander("More filters:"),
+ standard_table(3, 1),
+ extra_table(1, 1),
+ extra_label("EXTRA STUFF")
+ {
+ }
+ };
+}
+
+PackagesFilter::PackagesFilter(MainWindow * const m, PackagesPage * const p) :
+ Gtk::VBox(),
+ PrivateImplementationPattern<PackagesFilter>(new Implementation<PackagesFilter>(m, p))
+{
+ add(_imp->standard_expander);
+ _imp->standard_expander.add(_imp->standard_table);
+ _imp->standard_expander.set_expanded(true);
+ _imp->standard_table.attach(_imp->packages_repository_filter, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 4, 4);
+ _imp->standard_table.attach(_imp->packages_package_filter, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL, 4, 4);
+ _imp->standard_table.attach(_imp->packages_text_filter, 2, 3, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::FILL, 0, 0);
+
+ add(_imp->extra_expander);
+ _imp->extra_expander.add(_imp->extra_table);
+ _imp->extra_table.attach(_imp->extra_label, 0, 1, 0, 1);
+}
+
+PackagesFilter::~PackagesFilter()
+{
+}
+
+void
+PackagesFilter::populate()
+{
+ _imp->packages_repository_filter.populate();
+ _imp->packages_package_filter.populate();
+ _imp->packages_text_filter.populate();
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_filter.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_filter.hh
new file mode 100644
index 0000000..9fb6d0f
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_filter.hh
@@ -0,0 +1,26 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_FILTER_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_FILTER_HH 1
+
+#include <gtkmm/box.h>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackagesFilter :
+ public Gtk::VBox,
+ private paludis::PrivateImplementationPattern<PackagesFilter>
+ {
+ public:
+ PackagesFilter(MainWindow * const, PackagesPage * const);
+ ~PackagesFilter();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_list.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_list.cc
new file mode 100644
index 0000000..0868bda
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_list.cc
@@ -0,0 +1,96 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_list.hh"
+#include "packages_list_model.hh"
+#include "packages_list_filtered_model.hh"
+#include "packages_page.hh"
+#include "main_window.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesList>
+ {
+ Glib::RefPtr<PackagesListModel> real_model;
+ Glib::RefPtr<PackagesListFilteredModel> filtered_model;
+ MainWindow * const main_window;
+ PackagesPage * const repositories_page;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ real_model(new PackagesListModel(m, p)),
+ filtered_model(new PackagesListFilteredModel(m, p, real_model)),
+ main_window(m),
+ repositories_page(p)
+ {
+ }
+ };
+}
+
+PackagesList::PackagesList(MainWindow * const m, PackagesPage * const p) :
+ Gtk::TreeView(),
+ PrivateImplementationPattern<PackagesList>(new Implementation<PackagesList>(m, p))
+{
+ set_model(_imp->filtered_model);
+
+ append_column("Package", _imp->real_model->columns().col_package);
+
+ Gtk::CellRendererText renderer;
+ int c(append_column("Status", renderer) - 1);
+ get_column(c)->add_attribute(renderer, "markup", _imp->real_model->columns().col_status_markup.index());
+
+ append_column("Description", _imp->real_model->columns().col_description);
+
+ signal_cursor_changed().connect(sigc::mem_fun(this, &PackagesList::handle_signal_cursor_changed));
+}
+
+PackagesList::~PackagesList()
+{
+}
+
+void
+PackagesList::handle_signal_cursor_changed()
+{
+ if (get_selection()->get_selected())
+ _imp->repositories_page->set_qpn(paludis::tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(
+ (*get_selection()->get_selected())[_imp->real_model->columns().col_pde].operator
+ paludis::tr1::shared_ptr<const PackageDatabaseEntry>()->name)));
+ else
+ _imp->repositories_page->set_qpn(paludis::tr1::shared_ptr<QualifiedPackageName>());
+}
+
+void
+PackagesList::populate_real()
+{
+ _imp->real_model->populate();
+ _imp->main_window->paludis_thread_action(
+ sigc::mem_fun(this, &PackagesList::populate_in_paludis_thread), "Populating packages list");
+}
+
+void
+PackagesList::populate_filter()
+{
+ _imp->filtered_model->populate();
+}
+
+void
+PackagesList::populate_in_paludis_thread()
+{
+ _imp->main_window->gui_thread_action(
+ sigc::mem_fun(this, &PackagesList::populate_in_gui_thread));
+}
+
+void
+PackagesList::populate_in_gui_thread()
+{
+ expand_all();
+ columns_autosize();
+
+ if (! get_selection()->get_selected())
+ if (! _imp->filtered_model->children().empty())
+ set_cursor(_imp->filtered_model->get_path(_imp->filtered_model->children().begin()));
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_list.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_list.hh
new file mode 100644
index 0000000..e991f66
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_list.hh
@@ -0,0 +1,33 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_LIST_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_LIST_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <gtkmm/treeview.h>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackagesList :
+ public Gtk::TreeView,
+ private paludis::PrivateImplementationPattern<PackagesList>
+ {
+ protected:
+ void handle_signal_cursor_changed();
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread();
+
+ public:
+ PackagesList(MainWindow * const m, PackagesPage * const p);
+ ~PackagesList();
+
+ void populate_real();
+ void populate_filter();
+ };
+}
+
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_list_filtered_model.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_list_filtered_model.cc
new file mode 100644
index 0000000..32bb7cd
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_list_filtered_model.cc
@@ -0,0 +1,91 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_list_filtered_model.hh"
+#include "packages_list_model.hh"
+#include "packages_page.hh"
+#include <algorithm>
+#include <iterator>
+#include <ctype.h>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesListFilteredModel>
+ {
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+ Glib::RefPtr<PackagesListModel> real_model;
+
+ Implementation(MainWindow * const m, PackagesPage * const p,
+ Glib::RefPtr<PackagesListModel> r) :
+ main_window(m),
+ packages_page(p),
+ real_model(r)
+ {
+ }
+ };
+}
+
+PackagesListFilteredModel::PackagesListFilteredModel(MainWindow * const m,
+ PackagesPage * const p, Glib::RefPtr<PackagesListModel> d) :
+ PrivateImplementationPattern<PackagesListFilteredModel>(new Implementation<PackagesListFilteredModel>(m, p, d)),
+ Gtk::TreeModelFilter(d)
+{
+ set_visible_func(sigc::mem_fun(this, &PackagesListFilteredModel::handle_visible_func));
+}
+
+PackagesListFilteredModel::~PackagesListFilteredModel()
+{
+}
+
+void
+PackagesListFilteredModel::populate()
+{
+ refilter();
+}
+
+bool
+PackagesListFilteredModel::handle_visible_func(const TreeModel::const_iterator & i) const
+{
+ bool result(true);
+
+ if (result)
+ {
+ PackagesPackageFilterOption pfo(_imp->packages_page->get_package_filter());
+ result &= ((*i)[_imp->real_model->columns().col_best_package_filter_option] >= pfo);
+ }
+
+ if (result)
+ {
+ std::string tft(_imp->packages_page->get_text_filter_text());
+ if (! tft.empty())
+ {
+ std::string text;
+ switch (_imp->packages_page->get_text_filter())
+ {
+ case ptfso_name:
+ text = Glib::ustring((*i)[_imp->real_model->columns().col_package]).raw();
+ break;
+
+ case ptfso_description:
+ text = Glib::ustring((*i)[_imp->real_model->columns().col_description]).raw();
+ break;
+ }
+
+ if (! text.empty())
+ {
+ std::string text_lower, tft_lower;
+ std::transform(text.begin(), text.end(), std::back_inserter(text_lower), &::tolower);
+ std::transform(tft.begin(), tft.end(), std::back_inserter(tft_lower), &::tolower);
+ result &= (std::string::npos != text_lower.find(tft_lower));
+ }
+ }
+ }
+
+ return result;
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_list_filtered_model.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_list_filtered_model.hh
new file mode 100644
index 0000000..90d5acc
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_list_filtered_model.hh
@@ -0,0 +1,40 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_LIST_FILTERED_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_LIST_FILTERED_MODEL_HH 1
+
+#include <gtkmm/treemodelfilter.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+#include <paludis/package_database_entry.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackagesListModel;
+
+ class PackagesListFilteredModel :
+ private paludis::PrivateImplementationPattern<PackagesListFilteredModel>,
+ public Gtk::TreeModelFilter
+ {
+ private:
+ bool handle_visible_func(const TreeModel::const_iterator &) const;
+
+ protected:
+ class PopulateData;
+
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread(paludis::tr1::shared_ptr<const PopulateData> names);
+
+ public:
+ PackagesListFilteredModel(MainWindow * const m, PackagesPage * const p,
+ Glib::RefPtr<PackagesListModel>);
+ ~PackagesListFilteredModel();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_list_model.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_list_model.cc
new file mode 100644
index 0000000..eccb8da
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_list_model.cc
@@ -0,0 +1,276 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_list_model.hh"
+#include "main_window.hh"
+#include "packages_page.hh"
+#include "markup.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <list>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesListModel>
+ {
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+ PackagesListModel::Columns columns;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ main_window(m),
+ packages_page(p)
+ {
+ }
+ };
+}
+
+namespace
+{
+ struct PopulateDataSubItem
+ {
+ std::string slot;
+ std::string status;
+ std::string description;
+ PackageDatabaseEntry pde;
+
+ PopulateDataSubItem(const std::string & s, const std::string & t, const std::string & d,
+ const PackageDatabaseEntry p) :
+ slot(s),
+ status(t),
+ description(d),
+ pde(p)
+ {
+ }
+ };
+
+ struct PopulateDataItem
+ {
+ std::string package;
+ PackagesPackageFilterOption best_option;
+ std::list<PopulateDataSubItem> subitems;
+
+ PopulateDataItem(const std::string & p) :
+ package(p),
+ best_option(ppfo_all_packages)
+ {
+ }
+ };
+}
+
+namespace gtkpaludis
+{
+ struct PackagesListModel::PopulateData
+ {
+ std::list<PopulateDataItem> items;
+ };
+}
+
+
+PackagesListModel::PackagesListModel(MainWindow * const m, PackagesPage * const p) :
+ PrivateImplementationPattern<PackagesListModel>(new Implementation<PackagesListModel>(m, p)),
+ Gtk::TreeStore(_imp->columns)
+{
+}
+
+PackagesListModel::~PackagesListModel()
+{
+}
+
+PackagesListModel::Columns::Columns()
+{
+ add(col_package);
+ add(col_status_markup);
+ add(col_description);
+ add(col_pde);
+ add(col_best_package_filter_option);
+}
+
+PackagesListModel::Columns::~Columns()
+{
+}
+
+PackagesListModel::Columns &
+PackagesListModel::columns()
+{
+ return _imp->columns;
+}
+
+void
+PackagesListModel::populate()
+{
+ _imp->main_window->paludis_thread_action(
+ sigc::mem_fun(this, &PackagesListModel::populate_in_paludis_thread), "Populating packages list model");
+}
+
+namespace
+{
+ PopulateDataSubItem make_item(const PackageDatabaseEntry & pde,
+ paludis::tr1::shared_ptr<const VersionMetadata> metadata,
+ const Environment * const environment,
+ PackagesPackageFilterOption * const best_option)
+ {
+ std::string status;
+ paludis::tr1::shared_ptr<const PackageDatabaseEntryCollection> ci(
+ environment->package_database()->query(
+ query::Matches(PackageDepSpec(
+ paludis::tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(pde.name)),
+ paludis::tr1::shared_ptr<CategoryNamePart>(),
+ paludis::tr1::shared_ptr<PackageNamePart>(),
+ paludis::tr1::shared_ptr<VersionRequirements>(),
+ vr_and,
+ paludis::tr1::shared_ptr<SlotName>(new SlotName(metadata->slot)))) &
+ query::InstalledAtRoot(environment->root()),
+ qo_order_by_version));
+
+ paludis::tr1::shared_ptr<const PackageDatabaseEntryCollection> av(
+ environment->package_database()->query(
+ query::Matches(PackageDepSpec(
+ paludis::tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(pde.name)),
+ paludis::tr1::shared_ptr<CategoryNamePart>(),
+ paludis::tr1::shared_ptr<PackageNamePart>(),
+ paludis::tr1::shared_ptr<VersionRequirements>(),
+ vr_and,
+ paludis::tr1::shared_ptr<SlotName>(new SlotName(metadata->slot)))) &
+ query::RepositoryHasInstallableInterface() &
+ query::NotMasked(),
+ qo_order_by_version));
+
+ if (! ci->empty())
+ {
+ status = markup_escape(stringify(ci->last()->version));
+ *best_option = std::max(*best_option, ppfo_installed_packages);
+
+ if (! av->empty())
+ {
+ if (av->last()->version < ci->last()->version)
+ {
+ status.append(markup_bold(markup_escape(" > " + stringify(av->last()->version))));
+ *best_option = std::max(*best_option, ppfo_upgradable_packages);
+ }
+ else if (av->last()->version > ci->last()->version)
+ {
+ status.append(markup_bold(markup_escape(" < " + stringify(av->last()->version))));
+ *best_option = std::max(*best_option, ppfo_upgradable_packages);
+ }
+ }
+ }
+ else
+ {
+ paludis::tr1::shared_ptr<const PackageDatabaseEntryCollection> av(
+ environment->package_database()->query(
+ query::Matches(PackageDepSpec(
+ paludis::tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(pde.name)),
+ paludis::tr1::shared_ptr<CategoryNamePart>(),
+ paludis::tr1::shared_ptr<PackageNamePart>(),
+ paludis::tr1::shared_ptr<VersionRequirements>(),
+ vr_and,
+ paludis::tr1::shared_ptr<SlotName>(new SlotName(metadata->slot)))) &
+ query::RepositoryHasInstallableInterface() &
+ query::NotMasked(),
+ qo_order_by_version));
+ if (av->empty())
+ {
+ status.append(markup_foreground("grey", markup_escape("masked")));
+ *best_option = std::max(*best_option, ppfo_all_packages);
+ }
+ else
+ {
+ status.append(markup_foreground("grey", markup_escape(stringify(av->last()->version))));
+ *best_option = std::max(*best_option, ppfo_visible_packages);
+ }
+ }
+
+ return PopulateDataSubItem(
+ stringify(metadata->slot),
+ status,
+ metadata->description,
+ pde);
+ }
+}
+
+void
+PackagesListModel::populate_in_paludis_thread()
+{
+ paludis::tr1::shared_ptr<PopulateData> data(new PopulateData);
+ paludis::tr1::shared_ptr<const PackageDatabaseEntryCollection> c;
+
+ if (_imp->packages_page->get_category())
+ c = _imp->main_window->environment()->package_database()->query(
+ *_imp->packages_page->get_repository_filter() &
+ query::Category(*_imp->packages_page->get_category()),
+ qo_best_version_in_slot_only);
+ else
+ c.reset(new PackageDatabaseEntryCollection::Concrete);
+
+ QualifiedPackageName old_qpn("OLD/OLD");
+ PackagesPackageFilterOption * best_option(0);
+
+ for (PackageDatabaseEntryCollection::ReverseIterator p(c->rbegin()), p_end(c->rend()) ;
+ p != p_end ; ++p)
+ {
+ paludis::tr1::shared_ptr<const VersionMetadata> metadata(
+ _imp->main_window->environment()->package_database()->fetch_repository(p->repository)->version_metadata(
+ p->name, p->version));
+
+ if (old_qpn != p->name)
+ {
+ best_option = &data->items.insert(data->items.begin(), PopulateDataItem(stringify(p->name.package)))->best_option;
+ data->items.begin()->subitems.push_front(make_item(*p, metadata, _imp->main_window->environment(),
+ best_option));
+ old_qpn = p->name;
+ }
+ else
+ data->items.begin()->subitems.push_front(make_item(*p, metadata, _imp->main_window->environment(),
+ best_option));
+ }
+
+ _imp->main_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &PackagesListModel::populate_in_gui_thread), data));
+}
+
+void
+PackagesListModel::populate_in_gui_thread(paludis::tr1::shared_ptr<const PackagesListModel::PopulateData> names)
+{
+ clear();
+
+ for (std::list<PopulateDataItem>::const_iterator i(names->items.begin()), i_end(names->items.end()) ;
+ i != i_end ; ++i)
+ {
+ if (i->subitems.empty())
+ continue;
+
+ iterator r(append());
+ (*r)[_imp->columns.col_package] = i->package;
+ (*r)[_imp->columns.col_pde] = paludis::tr1::shared_ptr<PackageDatabaseEntry>(
+ new PackageDatabaseEntry(i->subitems.begin()->pde));
+ (*r)[_imp->columns.col_best_package_filter_option] = i->best_option;
+
+ if (next(i->subitems.begin()) == i->subitems.end())
+ {
+ (*r)[_imp->columns.col_status_markup] = i->subitems.begin()->status;
+ (*r)[_imp->columns.col_description] = i->subitems.begin()->description;
+ }
+ else
+ {
+ for (std::list<PopulateDataSubItem>::const_iterator j(i->subitems.begin()), j_end(i->subitems.end()) ;
+ j != j_end ; ++j)
+ {
+ iterator s(append(r->children()));
+ (*s)[_imp->columns.col_package] = ":" + j->slot;
+ (*s)[_imp->columns.col_status_markup] = j->status;
+ (*s)[_imp->columns.col_description] = j->description;
+ (*s)[_imp->columns.col_pde] = paludis::tr1::shared_ptr<PackageDatabaseEntry>(new PackageDatabaseEntry(j->pde));
+ (*s)[_imp->columns.col_best_package_filter_option] = i->best_option;
+ }
+ }
+ }
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_list_model.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_list_model.hh
new file mode 100644
index 0000000..1b2dc4e
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_list_model.hh
@@ -0,0 +1,51 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_LIST_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_LIST_MODEL_HH 1
+
+#include <gtkmm/treestore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+#include <paludis/package_database_entry.hh>
+#include <libgtkpaludis/packages_package_filter_option.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackagesListModel :
+ private paludis::PrivateImplementationPattern<PackagesListModel>,
+ public Gtk::TreeStore
+ {
+ protected:
+ class PopulateData;
+
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread(paludis::tr1::shared_ptr<const PopulateData> names);
+
+ public:
+ PackagesListModel(MainWindow * const m, PackagesPage * const p);
+ ~PackagesListModel();
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<Glib::ustring> col_package;
+ Gtk::TreeModelColumn<Glib::ustring> col_status_markup;
+ Gtk::TreeModelColumn<Glib::ustring> col_description;
+ Gtk::TreeModelColumn<paludis::tr1::shared_ptr<const paludis::PackageDatabaseEntry> > col_pde;
+ Gtk::TreeModelColumn<PackagesPackageFilterOption> col_best_package_filter_option;
+ };
+
+ Columns & columns();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter.cc
new file mode 100644
index 0000000..7bd5863
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter.cc
@@ -0,0 +1,60 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_package_filter.hh"
+#include "packages_package_filter_model.hh"
+#include "packages_page.hh"
+#include <paludis/query.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesPackageFilter>
+ {
+ Glib::RefPtr<PackagesPackageFilterModel> model;
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ model(new PackagesPackageFilterModel(m)),
+ main_window(m),
+ packages_page(p)
+ {
+ }
+ };
+}
+
+PackagesPackageFilter::PackagesPackageFilter(MainWindow * const m, PackagesPage * const p) :
+ PrivateImplementationPattern<PackagesPackageFilter>(new Implementation<PackagesPackageFilter>(m, p)),
+ Gtk::ComboBox()
+{
+ set_model(_imp->model);
+ Gtk::CellRendererText renderer;
+ pack_start(renderer);
+ add_attribute(renderer, "text", _imp->model->columns().col_text.index());
+
+ signal_changed().connect(sigc::mem_fun(this, &PackagesPackageFilter::handle_signal_changed));
+}
+
+PackagesPackageFilter::~PackagesPackageFilter()
+{
+}
+
+void
+PackagesPackageFilter::populate()
+{
+ _imp->model->populate();
+ set_active(0);
+}
+
+void
+PackagesPackageFilter::handle_signal_changed()
+{
+ if (get_active())
+ _imp->packages_page->set_package_filter((*get_active())[_imp->model->columns().col_filter]);
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter.hh
new file mode 100644
index 0000000..5f89152
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter.hh
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_PACKAGE_FILTER_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_PACKAGE_FILTER_HH 1
+
+#include <gtkmm/combobox.h>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackagesPackageFilter :
+ private paludis::PrivateImplementationPattern<PackagesPackageFilter>,
+ public Gtk::ComboBox
+ {
+ protected:
+ void handle_signal_changed();
+
+ public:
+ PackagesPackageFilter(MainWindow * const, PackagesPage * const);
+ ~PackagesPackageFilter();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_model.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_model.cc
new file mode 100644
index 0000000..67c7536
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_model.cc
@@ -0,0 +1,78 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_package_filter_model.hh"
+#include "main_window.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/environment.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/package_database.hh>
+#include <paludis/query.hh>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesPackageFilterModel>
+ {
+ MainWindow * const main_window;
+ PackagesPackageFilterModel::Columns columns;
+
+ Implementation(MainWindow * const m) :
+ main_window(m)
+ {
+ }
+ };
+}
+
+PackagesPackageFilterModel::PackagesPackageFilterModel(MainWindow * const m) :
+ PrivateImplementationPattern<PackagesPackageFilterModel>(new Implementation<PackagesPackageFilterModel>(m)),
+ Gtk::TreeStore(_imp->columns)
+{
+}
+
+PackagesPackageFilterModel::~PackagesPackageFilterModel()
+{
+}
+
+void
+PackagesPackageFilterModel::populate()
+{
+ iterator r;
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "All packages";
+ (*r)[_imp->columns.col_filter] = ppfo_all_packages;
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "Visible packages";
+ (*r)[_imp->columns.col_filter] = ppfo_visible_packages;
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "Installed packages";
+ (*r)[_imp->columns.col_filter] = ppfo_installed_packages;
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "Upgradable packages";
+ (*r)[_imp->columns.col_filter] = ppfo_upgradable_packages;
+}
+
+
+PackagesPackageFilterModel::Columns::Columns()
+{
+ add(col_text);
+ add(col_filter);
+}
+
+PackagesPackageFilterModel::Columns::~Columns()
+{
+}
+
+PackagesPackageFilterModel::Columns &
+PackagesPackageFilterModel::columns()
+{
+ return _imp->columns;
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_model.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_model.hh
new file mode 100644
index 0000000..ead3bed
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_model.hh
@@ -0,0 +1,39 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_PACKAGE_FILTER_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_PACKAGE_FILTER_MODEL_HH 1
+
+#include <gtkmm/treestore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <libgtkpaludis/packages_package_filter_option.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class PackagesPackageFilterModel :
+ private paludis::PrivateImplementationPattern<PackagesPackageFilterModel>,
+ public Gtk::TreeStore
+ {
+ public:
+ PackagesPackageFilterModel(MainWindow * const m);
+ ~PackagesPackageFilterModel();
+
+ void populate();
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<Glib::ustring> col_text;
+ Gtk::TreeModelColumn<PackagesPackageFilterOption> col_filter;
+ };
+
+ Columns & columns();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_option.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_option.hh
new file mode 100644
index 0000000..c43e189
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_package_filter_option.hh
@@ -0,0 +1,17 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_PACKAGE_FILTER_OPTION_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_PACKAGE_FILTER_OPTION_HH 1
+
+namespace gtkpaludis
+{
+ enum PackagesPackageFilterOption
+ {
+ ppfo_all_packages,
+ ppfo_visible_packages,
+ ppfo_installed_packages,
+ ppfo_upgradable_packages
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_page.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_page.cc
new file mode 100644
index 0000000..c7d9276
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_page.cc
@@ -0,0 +1,164 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_page.hh"
+#include "packages_filter.hh"
+#include "categories_list.hh"
+#include "packages_list.hh"
+#include "package_buttons.hh"
+
+#include <paludis/query.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <gtkmm/scrolledwindow.h>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesPage>
+ {
+ MainWindow * const main_window;
+
+ PackagesFilter packages_filter;
+
+ Gtk::ScrolledWindow categories_list_scroll;
+ CategoriesList categories_list;
+
+ Gtk::ScrolledWindow packages_list_scroll;
+ PackagesList packages_list;
+ PackageButtons package_buttons;
+
+ paludis::tr1::shared_ptr<const Query> repository_filter;
+ paludis::tr1::shared_ptr<const CategoryNamePart> category;
+ paludis::tr1::shared_ptr<const QualifiedPackageName> qpn;
+ PackagesPackageFilterOption package_filter;
+ PackagesTextFilterSourceOption text_filter;
+ std::string text_filter_text;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ main_window(m),
+ packages_filter(m, p),
+ categories_list(m, p),
+ packages_list(m, p),
+ package_buttons(m, p),
+ repository_filter(new query::All()),
+ package_filter(ppfo_all_packages),
+ text_filter(ptfso_name)
+ {
+ }
+ };
+}
+
+PackagesPage::PackagesPage(MainWindow * const m) :
+ Gtk::Table(3, 2),
+ MainNotebookPage(),
+ PrivateImplementationPattern<PackagesPage>(new Implementation<PackagesPage>(m, this))
+{
+ attach(_imp->packages_filter, 0, 2, 0, 1, Gtk::FILL, Gtk::FILL, 4, 4);
+
+ _imp->categories_list_scroll.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
+ _imp->categories_list_scroll.add(_imp->categories_list);
+ attach(_imp->categories_list_scroll, 0, 1, 1, 2, Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 4, 4);
+
+ _imp->packages_list_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ _imp->packages_list_scroll.add(_imp->packages_list);
+
+ attach(_imp->packages_list_scroll, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 4, 4);
+ attach(_imp->package_buttons, 0, 2, 2, 3, Gtk::FILL, Gtk::FILL, 4, 4);
+}
+
+PackagesPage::~PackagesPage()
+{
+}
+
+void
+PackagesPage::populate()
+{
+ _imp->categories_list.populate();
+ _imp->packages_filter.populate();
+ _imp->packages_list.populate_real();
+ _imp->package_buttons.populate();
+}
+
+void
+PackagesPage::set_category(paludis::tr1::shared_ptr<const CategoryNamePart> c)
+{
+ _imp->category = c;
+ _imp->packages_list.populate_real();
+ _imp->package_buttons.populate();
+}
+
+paludis::tr1::shared_ptr<const CategoryNamePart>
+PackagesPage::get_category() const
+{
+ return _imp->category;
+}
+
+void
+PackagesPage::set_qpn(paludis::tr1::shared_ptr<const QualifiedPackageName> q)
+{
+ _imp->qpn = q;
+ _imp->package_buttons.populate();
+}
+
+paludis::tr1::shared_ptr<const QualifiedPackageName>
+PackagesPage::get_qpn() const
+{
+ return _imp->qpn;
+}
+
+void
+PackagesPage::set_repository_filter(paludis::tr1::shared_ptr<const Query> q)
+{
+ _imp->repository_filter = q;
+ _imp->categories_list.populate();
+ _imp->packages_list.populate_real();
+ _imp->package_buttons.populate();
+}
+
+paludis::tr1::shared_ptr<const Query>
+PackagesPage::get_repository_filter() const
+{
+ return _imp->repository_filter;
+}
+
+void
+PackagesPage::set_package_filter(const PackagesPackageFilterOption q)
+{
+ _imp->package_filter = q;
+ _imp->packages_list.populate_filter();
+}
+
+PackagesPackageFilterOption
+PackagesPage::get_package_filter() const
+{
+ return _imp->package_filter;
+}
+
+void
+PackagesPage::set_text_filter(const PackagesTextFilterSourceOption q)
+{
+ _imp->text_filter = q;
+ _imp->packages_list.populate_filter();
+}
+
+PackagesTextFilterSourceOption
+PackagesPage::get_text_filter() const
+{
+ return _imp->text_filter;
+}
+
+void
+PackagesPage::set_text_filter_text(const std::string & q)
+{
+ _imp->text_filter_text = q;
+ _imp->packages_list.populate_filter();
+}
+
+std::string
+PackagesPage::get_text_filter_text() const
+{
+ return _imp->text_filter_text;
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_page.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_page.hh
new file mode 100644
index 0000000..d722d43
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_page.hh
@@ -0,0 +1,51 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_PAGE_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_PAGE_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+#include <paludis/query.hh>
+#include <paludis/package_database_entry.hh>
+#include <libgtkpaludis/main_notebook_page.hh>
+#include <libgtkpaludis/packages_package_filter_option.hh>
+#include <libgtkpaludis/packages_text_filter_source_option.hh>
+#include <gtkmm/table.h>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class PackagesPage :
+ public Gtk::Table,
+ public MainNotebookPage,
+ private paludis::PrivateImplementationPattern<PackagesPage>
+ {
+ public:
+ PackagesPage(MainWindow * const m);
+ ~PackagesPage();
+
+ virtual void populate();
+
+ void set_category(paludis::tr1::shared_ptr<const paludis::CategoryNamePart>);
+ paludis::tr1::shared_ptr<const paludis::CategoryNamePart> get_category() const;
+
+ void set_repository_filter(paludis::tr1::shared_ptr<const paludis::Query>);
+ paludis::tr1::shared_ptr<const paludis::Query> get_repository_filter() const;
+
+ void set_package_filter(const PackagesPackageFilterOption);
+ PackagesPackageFilterOption get_package_filter() const;
+
+ void set_text_filter(const PackagesTextFilterSourceOption);
+ PackagesTextFilterSourceOption get_text_filter() const;
+
+ void set_text_filter_text(const std::string &);
+ std::string get_text_filter_text() const;
+
+ void set_qpn(paludis::tr1::shared_ptr<const paludis::QualifiedPackageName>);
+ paludis::tr1::shared_ptr<const paludis::QualifiedPackageName> get_qpn() const;
+
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter.cc
new file mode 100644
index 0000000..b8ca7a1
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter.cc
@@ -0,0 +1,61 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_repository_filter.hh"
+#include "packages_repository_filter_model.hh"
+#include "packages_page.hh"
+#include <paludis/query.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesRepositoryFilter>
+ {
+ Glib::RefPtr<PackagesRepositoryFilterModel> model;
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ model(new PackagesRepositoryFilterModel(m)),
+ main_window(m),
+ packages_page(p)
+ {
+ }
+ };
+}
+
+PackagesRepositoryFilter::PackagesRepositoryFilter(MainWindow * const m, PackagesPage * const p) :
+ PrivateImplementationPattern<PackagesRepositoryFilter>(new Implementation<PackagesRepositoryFilter>(m, p)),
+ Gtk::ComboBox()
+{
+ set_model(_imp->model);
+ Gtk::CellRendererText renderer;
+ pack_start(renderer);
+ add_attribute(renderer, "text", _imp->model->columns().col_text.index());
+ add_attribute(renderer, "sensitive", _imp->model->columns().col_sensitive.index());
+
+ signal_changed().connect(sigc::mem_fun(this, &PackagesRepositoryFilter::handle_signal_changed));
+}
+
+PackagesRepositoryFilter::~PackagesRepositoryFilter()
+{
+}
+
+void
+PackagesRepositoryFilter::populate()
+{
+ _imp->model->populate();
+ set_active(0);
+}
+
+void
+PackagesRepositoryFilter::handle_signal_changed()
+{
+ if (get_active())
+ _imp->packages_page->set_repository_filter((*get_active())[_imp->model->columns().col_query].operator
+ paludis::tr1::shared_ptr<const Query>());
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter.hh
new file mode 100644
index 0000000..3d37eb3
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter.hh
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_REPOSITORY_FILTER_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_REPOSITORY_FILTER_HH 1
+
+#include <gtkmm/combobox.h>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackagesRepositoryFilter :
+ private paludis::PrivateImplementationPattern<PackagesRepositoryFilter>,
+ public Gtk::ComboBox
+ {
+ protected:
+ void handle_signal_changed();
+
+ public:
+ PackagesRepositoryFilter(MainWindow * const, PackagesPage * const);
+ ~PackagesRepositoryFilter();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter_model.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter_model.cc
new file mode 100644
index 0000000..efad8a7
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter_model.cc
@@ -0,0 +1,115 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_repository_filter_model.hh"
+#include "main_window.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/query.hh>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesRepositoryFilterModel>
+ {
+ MainWindow * const main_window;
+ PackagesRepositoryFilterModel::Columns columns;
+
+ Implementation(MainWindow * const m) :
+ main_window(m)
+ {
+ }
+ };
+}
+
+PackagesRepositoryFilterModel::PackagesRepositoryFilterModel(MainWindow * const m) :
+ PrivateImplementationPattern<PackagesRepositoryFilterModel>(new Implementation<PackagesRepositoryFilterModel>(m)),
+ Gtk::TreeStore(_imp->columns)
+{
+}
+
+PackagesRepositoryFilterModel::~PackagesRepositoryFilterModel()
+{
+}
+
+void
+PackagesRepositoryFilterModel::populate()
+{
+ iterator r;
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "All repositories";
+ (*r)[_imp->columns.col_sensitive] = true;
+ (*r)[_imp->columns.col_query] = paludis::tr1::shared_ptr<Query>(new query::All);
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "Installable repositories";
+ (*r)[_imp->columns.col_sensitive] = true;
+ (*r)[_imp->columns.col_query] = paludis::tr1::shared_ptr<Query>(new query::RepositoryHasInstallableInterface);
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "Installed repositories";
+ (*r)[_imp->columns.col_sensitive] = true;
+ (*r)[_imp->columns.col_query] = paludis::tr1::shared_ptr<Query>(new query::RepositoryHasInstalledInterface);
+
+ _imp->main_window->paludis_thread_action(
+ sigc::mem_fun(this, &PackagesRepositoryFilterModel::populate_in_paludis_thread), "Populating repository filter model");
+}
+
+void
+PackagesRepositoryFilterModel::populate_in_paludis_thread()
+{
+ paludis::tr1::shared_ptr<RepositoryNameCollection> columns(
+ new RepositoryNameCollection::Concrete);
+
+ for (IndirectIterator<PackageDatabase::RepositoryIterator>
+ r(indirect_iterator(_imp->main_window->environment()->package_database()->begin_repositories())),
+ r_end(indirect_iterator(_imp->main_window->environment()->package_database()->end_repositories())) ;
+ r != r_end ; ++r)
+ columns->push_back(r->name());
+
+ _imp->main_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &PackagesRepositoryFilterModel::populate_in_gui_thread), columns));
+}
+
+void
+PackagesRepositoryFilterModel::populate_in_gui_thread(paludis::tr1::shared_ptr<const RepositoryNameCollection> names)
+{
+ iterator repositories(append());
+ (*repositories)[_imp->columns.col_text] = "Specific repository";
+ (*repositories)[_imp->columns.col_sensitive] = false;
+
+ for (RepositoryNameCollection::Iterator n(names->begin()), n_end(names->end()) ;
+ n != n_end ; ++n)
+ {
+ iterator r(append(repositories->children()));
+ (*r)[_imp->columns.col_text] = stringify(*n);
+ (*r)[_imp->columns.col_sensitive] = true;
+ (*r)[_imp->columns.col_query] = paludis::tr1::shared_ptr<Query>(new query::Repository(*n));
+ }
+}
+
+
+PackagesRepositoryFilterModel::Columns::Columns()
+{
+ add(col_sensitive);
+ add(col_text);
+ add(col_query);
+}
+
+PackagesRepositoryFilterModel::Columns::~Columns()
+{
+}
+
+PackagesRepositoryFilterModel::Columns &
+PackagesRepositoryFilterModel::columns()
+{
+ return _imp->columns;
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter_model.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter_model.hh
new file mode 100644
index 0000000..6b2f97b
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_repository_filter_model.hh
@@ -0,0 +1,45 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_REPOSITORY_FILTER_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_REPOSITORY_FILTER_MODEL_HH 1
+
+#include <gtkmm/treestore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+#include <paludis/query.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class PackagesRepositoryFilterModel :
+ private paludis::PrivateImplementationPattern<PackagesRepositoryFilterModel>,
+ public Gtk::TreeStore
+ {
+ protected:
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread(paludis::tr1::shared_ptr<const paludis::RepositoryNameCollection> names);
+
+ public:
+ PackagesRepositoryFilterModel(MainWindow * const m);
+ ~PackagesRepositoryFilterModel();
+
+ void populate();
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<bool> col_sensitive;
+ Gtk::TreeModelColumn<Glib::ustring> col_text;
+ Gtk::TreeModelColumn<paludis::tr1::shared_ptr<const paludis::Query> > col_query;
+ };
+
+ Columns & columns();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter.cc
new file mode 100644
index 0000000..eceb07f
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter.cc
@@ -0,0 +1,60 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_text_filter.hh"
+#include "packages_text_filter_source.hh"
+#include "packages_page.hh"
+#include "main_window.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <gtkmm/label.h>
+#include <gtkmm/entry.h>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesTextFilter>
+ {
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+
+ PackagesTextFilterSource packages_text_filter_source;
+ Gtk::Entry filter_entry;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ main_window(m),
+ packages_page(p),
+ packages_text_filter_source(m, p)
+ {
+ }
+ };
+}
+
+PackagesTextFilter::PackagesTextFilter(MainWindow * const m, PackagesPage * const p) :
+ PrivateImplementationPattern<PackagesTextFilter>(new Implementation<PackagesTextFilter>(m, p)),
+ Gtk::Table(2, 1)
+{
+ attach(_imp->packages_text_filter_source, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 4, 4);
+ attach(_imp->filter_entry, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::FILL, 4, 4);
+
+ _imp->filter_entry.signal_changed().connect(
+ sigc::mem_fun(this, &PackagesTextFilter::handle_filter_entry_changed));
+}
+
+PackagesTextFilter::~PackagesTextFilter()
+{
+}
+
+void
+PackagesTextFilter::populate()
+{
+ _imp->packages_text_filter_source.populate();
+}
+
+void
+PackagesTextFilter::handle_filter_entry_changed()
+{
+ _imp->packages_page->set_text_filter_text(_imp->filter_entry.get_text().raw());
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter.hh
new file mode 100644
index 0000000..5d52428
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter.hh
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_TEXT_FILTER_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_TEXT_FILTER_HH 1
+
+#include <gtkmm/table.h>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackagesTextFilter :
+ private paludis::PrivateImplementationPattern<PackagesTextFilter>,
+ public Gtk::Table
+ {
+ private:
+ void handle_filter_entry_changed();
+
+ public:
+ PackagesTextFilter(MainWindow * const m, PackagesPage * const p);
+ ~PackagesTextFilter();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source.cc
new file mode 100644
index 0000000..4785e8a
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source.cc
@@ -0,0 +1,59 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_text_filter_source.hh"
+#include "packages_text_filter_source_model.hh"
+#include "packages_page.hh"
+#include <paludis/query.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesTextFilterSource>
+ {
+ Glib::RefPtr<PackagesTextFilterSourceModel> model;
+ MainWindow * const main_window;
+ PackagesPage * const packages_page;
+
+ Implementation(MainWindow * const m, PackagesPage * const p) :
+ model(new PackagesTextFilterSourceModel(m)),
+ main_window(m),
+ packages_page(p)
+ {
+ }
+ };
+}
+
+PackagesTextFilterSource::PackagesTextFilterSource(MainWindow * const m, PackagesPage * const p) :
+ PrivateImplementationPattern<PackagesTextFilterSource>(new Implementation<PackagesTextFilterSource>(m, p)),
+ Gtk::ComboBox()
+{
+ set_model(_imp->model);
+ Gtk::CellRendererText renderer;
+ pack_start(renderer);
+ add_attribute(renderer, "text", _imp->model->columns().col_text.index());
+
+ signal_changed().connect(sigc::mem_fun(this, &PackagesTextFilterSource::handle_signal_changed));
+}
+
+PackagesTextFilterSource::~PackagesTextFilterSource()
+{
+}
+
+void
+PackagesTextFilterSource::populate()
+{
+ _imp->model->populate();
+ set_active(0);
+}
+
+void
+PackagesTextFilterSource::handle_signal_changed()
+{
+ if (get_active())
+ _imp->packages_page->set_text_filter((*get_active())[_imp->model->columns().col_filter]);
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source.hh
new file mode 100644
index 0000000..3f0f339
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source.hh
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_TEXT_FILTER_SOURCE_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_TEXT_FILTER_SOURCE_HH 1
+
+#include <gtkmm/combobox.h>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class PackagesPage;
+
+ class PackagesTextFilterSource :
+ private paludis::PrivateImplementationPattern<PackagesTextFilterSource>,
+ public Gtk::ComboBox
+ {
+ protected:
+ void handle_signal_changed();
+
+ public:
+ PackagesTextFilterSource(MainWindow * const, PackagesPage * const);
+ ~PackagesTextFilterSource();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_model.cc b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_model.cc
new file mode 100644
index 0000000..cbd8208
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_model.cc
@@ -0,0 +1,70 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "packages_text_filter_source_model.hh"
+#include "main_window.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/query.hh>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<PackagesTextFilterSourceModel>
+ {
+ MainWindow * const main_window;
+ PackagesTextFilterSourceModel::Columns columns;
+
+ Implementation(MainWindow * const m) :
+ main_window(m)
+ {
+ }
+ };
+}
+
+PackagesTextFilterSourceModel::PackagesTextFilterSourceModel(MainWindow * const m) :
+ PrivateImplementationPattern<PackagesTextFilterSourceModel>(new Implementation<PackagesTextFilterSourceModel>(m)),
+ Gtk::TreeStore(_imp->columns)
+{
+}
+
+PackagesTextFilterSourceModel::~PackagesTextFilterSourceModel()
+{
+}
+
+void
+PackagesTextFilterSourceModel::populate()
+{
+ iterator r;
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "Name contains:";
+ (*r)[_imp->columns.col_filter] = ptfso_name;
+
+ r = append();
+ (*r)[_imp->columns.col_text] = "Description contains:";
+ (*r)[_imp->columns.col_filter] = ptfso_description;
+}
+
+
+PackagesTextFilterSourceModel::Columns::Columns()
+{
+ add(col_text);
+ add(col_filter);
+}
+
+PackagesTextFilterSourceModel::Columns::~Columns()
+{
+}
+
+PackagesTextFilterSourceModel::Columns &
+PackagesTextFilterSourceModel::columns()
+{
+ return _imp->columns;
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_model.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_model.hh
new file mode 100644
index 0000000..3383c32
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_model.hh
@@ -0,0 +1,39 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_TEXT_FILTER_SOURCE_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_TEXT_FILTER_SOURCE_MODEL_HH 1
+
+#include <gtkmm/treestore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <libgtkpaludis/packages_text_filter_source_option.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class PackagesTextFilterSourceModel :
+ private paludis::PrivateImplementationPattern<PackagesTextFilterSourceModel>,
+ public Gtk::TreeStore
+ {
+ public:
+ PackagesTextFilterSourceModel(MainWindow * const m);
+ ~PackagesTextFilterSourceModel();
+
+ void populate();
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<Glib::ustring> col_text;
+ Gtk::TreeModelColumn<PackagesTextFilterSourceOption> col_filter;
+ };
+
+ Columns & columns();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_option.hh b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_option.hh
new file mode 100644
index 0000000..1a05982
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/packages_text_filter_source_option.hh
@@ -0,0 +1,15 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_TEXT_FILTER_SOURCE_OPTION_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_PACKAGES_TEXT_FILTER_SOURCE_OPTION_HH 1
+
+namespace gtkpaludis
+{
+ enum PackagesTextFilterSourceOption
+ {
+ ptfso_name,
+ ptfso_description
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/query_notebook.cc b/src/clients/gtkpaludis/libgtkpaludis/query_notebook.cc
new file mode 100644
index 0000000..2682d53
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/query_notebook.cc
@@ -0,0 +1,56 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "query_notebook.hh"
+#include "query_notebook_page.hh"
+#include "versions_page.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <map>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<QueryNotebook>
+ {
+ QueryWindow * const main_window;
+ VersionsPage versions_page;
+
+ std::map<int, QueryNotebookPage *> pages_by_index;
+
+ sigc::connection signal_switch_page_connection;
+
+ Implementation(QueryWindow * const m) :
+ main_window(m),
+ versions_page(m)
+ {
+ }
+ };
+}
+
+QueryNotebook::QueryNotebook(QueryWindow * const m) :
+ Gtk::Notebook(),
+ PrivateImplementationPattern<QueryNotebook>(new Implementation<QueryNotebook>(m))
+{
+ _imp->pages_by_index.insert(std::make_pair(
+ append_page(_imp->versions_page, "Versions"),
+ &_imp->versions_page));
+
+ _imp->signal_switch_page_connection = signal_switch_page().connect(
+ sigc::mem_fun(*this, &QueryNotebook::handle_switch_page));
+}
+
+QueryNotebook::~QueryNotebook()
+{
+ _imp->signal_switch_page_connection.disconnect();
+}
+
+void
+QueryNotebook::handle_switch_page(GtkNotebookPage *, guint page)
+{
+ std::map<int, QueryNotebookPage *>::const_iterator f(_imp->pages_by_index.find(page));
+ if (_imp->pages_by_index.end() != f)
+ f->second->populate_once();
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/query_notebook.hh b/src/clients/gtkpaludis/libgtkpaludis/query_notebook.hh
new file mode 100644
index 0000000..12aacd8
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/query_notebook.hh
@@ -0,0 +1,28 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_QUERY_NOTEBOOK_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_QUERY_NOTEBOOK_HH 1
+
+#include <gtkmm/notebook.h>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace gtkpaludis
+{
+ class QueryWindow;
+
+ class QueryNotebook :
+ public Gtk::Notebook,
+ private paludis::PrivateImplementationPattern<QueryNotebook>
+ {
+ protected:
+ void handle_switch_page(GtkNotebookPage *, guint);
+
+ public:
+ QueryNotebook(QueryWindow * const);
+ ~QueryNotebook();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/query_notebook_page.cc b/src/clients/gtkpaludis/libgtkpaludis/query_notebook_page.cc
new file mode 100644
index 0000000..d4ffd9f
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/query_notebook_page.cc
@@ -0,0 +1,26 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "query_notebook_page.hh"
+
+using namespace gtkpaludis;
+
+QueryNotebookPage::QueryNotebookPage() :
+ _populated(false)
+{
+}
+
+QueryNotebookPage::~QueryNotebookPage()
+{
+}
+
+void
+QueryNotebookPage::populate_once()
+{
+ if (_populated)
+ return;
+
+ populate();
+ _populated = true;
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/query_notebook_page.hh b/src/clients/gtkpaludis/libgtkpaludis/query_notebook_page.hh
new file mode 100644
index 0000000..fad5e78
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/query_notebook_page.hh
@@ -0,0 +1,23 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_QUERY_NOTEBOOK_PAGE_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_QUERY_NOTEBOOK_PAGE_HH 1
+
+namespace gtkpaludis
+{
+ class QueryNotebookPage
+ {
+ private:
+ bool _populated;
+
+ public:
+ QueryNotebookPage();
+ virtual ~QueryNotebookPage() = 0;
+
+ void populate_once();
+ virtual void populate() = 0;
+ };
+}
+
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/query_window.cc b/src/clients/gtkpaludis/libgtkpaludis/query_window.cc
new file mode 100644
index 0000000..ef473b3
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/query_window.cc
@@ -0,0 +1,122 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "query_window.hh"
+#include "query_notebook.hh"
+#include "main_window.hh"
+#include <paludis/name.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <gtkmm/table.h>
+#include <gtkmm/button.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/stock.h>
+#include <gtkmm/statusbar.h>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<QueryWindow>
+ {
+ MainWindow * const main_window;
+
+ Gtk::Table main_table;
+ Gtk::HButtonBox main_button_box;
+ Gtk::Button ok_button;
+ Gtk::Statusbar status_bar;
+
+ QueryNotebook query_notebook;
+ QualifiedPackageName package_name;
+
+ Implementation(MainWindow * const m, QueryWindow * const q, const QualifiedPackageName & n) :
+ main_window(m),
+ main_table(3, 1),
+ ok_button(Gtk::Stock::OK),
+ query_notebook(q),
+ package_name(n)
+ {
+ }
+ };
+}
+
+QueryWindow::QueryWindow(MainWindow * const m, const QualifiedPackageName & q) :
+ ThreadedWindow(Gtk::WINDOW_TOPLEVEL, m->environment()),
+ PrivateImplementationPattern<QueryWindow>(new Implementation<QueryWindow>(m, this, q)),
+ _imp(PrivateImplementationPattern<QueryWindow>::_imp)
+{
+ m->desensitise();
+
+ set_modal(true);
+ set_transient_for(*m);
+ set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
+ set_title("Querying '" + stringify(q) + "'");
+ set_default_size(700, 500);
+ set_border_width(4);
+
+ _imp->ok_button.signal_clicked().connect(sigc::mem_fun(this, &QueryWindow::handle_ok_button_clicked));
+
+ _imp->main_button_box.set_layout(Gtk::BUTTONBOX_END);
+ _imp->main_button_box.set_spacing(10);
+ _imp->main_button_box.add(_imp->ok_button);
+
+ _imp->status_bar.set_has_resize_grip(true);
+
+ _imp->main_table.attach(_imp->query_notebook, 0, 1, 0, 1, Gtk::EXPAND | Gtk::FILL,
+ Gtk::EXPAND | Gtk::FILL, 4, 4);
+ _imp->main_table.attach(_imp->main_button_box, 0, 1, 1, 2, Gtk::EXPAND | Gtk::FILL,
+ Gtk::FILL, 4, 4);
+ _imp->main_table.attach(_imp->status_bar, 0, 1, 2, 3, Gtk::EXPAND | Gtk::FILL,
+ Gtk::FILL, 4, 4);
+
+ add(_imp->main_table);
+
+ show_all();
+}
+
+QueryWindow::~QueryWindow()
+{
+ _imp->main_window->sensitise();
+}
+
+void
+QueryWindow::handle_ok_button_clicked()
+{
+ handle_delete_event(0);
+}
+
+bool
+QueryWindow::handle_delete_event(GdkEventAny * a)
+{
+ ThreadedWindow::handle_delete_event(a);
+ delete this;
+ return false;
+}
+
+const QualifiedPackageName
+QueryWindow::get_package_name() const
+{
+ return _imp->package_name;
+}
+
+void
+QueryWindow::push_status_message(const std::string & s)
+{
+ _imp->status_bar.push(s);
+}
+
+void
+QueryWindow::pop_status_message()
+{
+ _imp->status_bar.pop();
+}
+
+void
+QueryWindow::do_set_sensitive(const bool v)
+{
+ _imp->query_notebook.set_sensitive(v);
+ _imp->main_button_box.set_sensitive(v);
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/query_window.hh b/src/clients/gtkpaludis/libgtkpaludis/query_window.hh
new file mode 100644
index 0000000..1a88733
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/query_window.hh
@@ -0,0 +1,41 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_QUERY_WINDOW_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_QUERY_WINDOW_HH 1
+
+#include <libgtkpaludis/threaded_window.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class QualifiedPackageName;
+}
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class QueryWindow :
+ public ThreadedWindow,
+ private paludis::PrivateImplementationPattern<QueryWindow>
+ {
+ private:
+ paludis::PrivateImplementationPattern<QueryWindow>::ImpPtr & _imp;
+
+ protected:
+ virtual bool handle_delete_event(GdkEventAny *);
+ void handle_ok_button_clicked();
+ virtual void do_set_sensitive(const bool);
+
+ virtual void push_status_message(const std::string &);
+ virtual void pop_status_message();
+
+ public:
+ QueryWindow(MainWindow * const, const paludis::QualifiedPackageName &);
+ ~QueryWindow();
+
+ const paludis::QualifiedPackageName get_package_name() const;
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repositories_list.cc b/src/clients/gtkpaludis/libgtkpaludis/repositories_list.cc
new file mode 100644
index 0000000..917937c
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repositories_list.cc
@@ -0,0 +1,57 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "repositories_list.hh"
+#include "repositories_list_model.hh"
+#include "repositories_page.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<RepositoriesList>
+ {
+ Glib::RefPtr<RepositoriesListModel> model;
+ MainWindow * const main_window;
+ RepositoriesPage * const repositories_page;
+
+ Implementation(MainWindow * const m, RepositoriesPage * const p) :
+ model(new RepositoriesListModel(m)),
+ main_window(m),
+ repositories_page(p)
+ {
+ }
+ };
+}
+
+RepositoriesList::RepositoriesList(MainWindow * const m, RepositoriesPage * const p) :
+ Gtk::TreeView(),
+ PrivateImplementationPattern<RepositoriesList>(new Implementation<RepositoriesList>(m, p))
+{
+ set_model(_imp->model);
+
+ append_column("Repository", _imp->model->columns().col_repo_name);
+
+ signal_cursor_changed().connect(sigc::mem_fun(this, &RepositoriesList::handle_signal_cursor_changed));
+}
+
+RepositoriesList::~RepositoriesList()
+{
+}
+
+void
+RepositoriesList::populate()
+{
+ _imp->model->populate();
+}
+
+void
+RepositoriesList::handle_signal_cursor_changed()
+{
+ if (get_selection()->get_selected())
+ _imp->repositories_page->set_repository(RepositoryName(
+ static_cast<Glib::ustring>((*get_selection()->get_selected())[_imp->model->columns().col_repo_name]).raw()));
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repositories_list.hh b/src/clients/gtkpaludis/libgtkpaludis/repositories_list.hh
new file mode 100644
index 0000000..461d134
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repositories_list.hh
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORIES_LIST_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORIES_LIST_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <gtkmm/treeview.h>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+ class RepositoriesPage;
+
+ class RepositoriesList :
+ public Gtk::TreeView,
+ private paludis::PrivateImplementationPattern<RepositoriesList>
+ {
+ protected:
+ void handle_signal_cursor_changed();
+
+ public:
+ RepositoriesList(MainWindow * const m, RepositoriesPage * const p);
+ ~RepositoriesList();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repositories_list_model.cc b/src/clients/gtkpaludis/libgtkpaludis/repositories_list_model.cc
new file mode 100644
index 0000000..a099b11
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repositories_list_model.cc
@@ -0,0 +1,86 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "repositories_list_model.hh"
+#include "main_window.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<RepositoriesListModel>
+ {
+ MainWindow * const main_window;
+ RepositoriesListModel::Columns columns;
+
+ Implementation(MainWindow * const m) :
+ main_window(m)
+ {
+ }
+ };
+}
+
+RepositoriesListModel::RepositoriesListModel(MainWindow * const m) :
+ PrivateImplementationPattern<RepositoriesListModel>(new Implementation<RepositoriesListModel>(m)),
+ Gtk::ListStore(_imp->columns)
+{
+}
+
+RepositoriesListModel::~RepositoriesListModel()
+{
+}
+
+void
+RepositoriesListModel::populate()
+{
+ _imp->main_window->paludis_thread_action(
+ sigc::mem_fun(this, &RepositoriesListModel::populate_in_paludis_thread), "Populating repositories list model");
+}
+
+void
+RepositoriesListModel::populate_in_paludis_thread()
+{
+ paludis::tr1::shared_ptr<RepositoryNameCollection> columns(
+ new RepositoryNameCollection::Concrete);
+
+ for (IndirectIterator<PackageDatabase::RepositoryIterator>
+ r(indirect_iterator(_imp->main_window->environment()->package_database()->begin_repositories())),
+ r_end(indirect_iterator(_imp->main_window->environment()->package_database()->end_repositories())) ;
+ r != r_end ; ++r)
+ columns->push_back(r->name());
+
+ _imp->main_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &RepositoriesListModel::populate_in_gui_thread), columns));
+}
+
+void
+RepositoriesListModel::populate_in_gui_thread(paludis::tr1::shared_ptr<const RepositoryNameCollection> names)
+{
+ clear();
+ for (RepositoryNameCollection::Iterator n(names->begin()), n_end(names->end()) ;
+ n != n_end ; ++n)
+ (*append())[_imp->columns.col_repo_name] = stringify(*n);
+}
+
+
+RepositoriesListModel::Columns::Columns()
+{
+ add(col_repo_name);
+}
+
+RepositoriesListModel::Columns::~Columns()
+{
+}
+
+RepositoriesListModel::Columns &
+RepositoriesListModel::columns()
+{
+ return _imp->columns;
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repositories_list_model.hh b/src/clients/gtkpaludis/libgtkpaludis/repositories_list_model.hh
new file mode 100644
index 0000000..625c3cc
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repositories_list_model.hh
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORIES_LIST_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORIES_LIST_MODEL_HH 1
+
+#include <gtkmm/liststore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class RepositoriesListModel :
+ private paludis::PrivateImplementationPattern<RepositoriesListModel>,
+ public Gtk::ListStore
+ {
+ protected:
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread(paludis::tr1::shared_ptr<const paludis::RepositoryNameCollection> names);
+
+ public:
+ RepositoriesListModel(MainWindow * const m);
+ ~RepositoriesListModel();
+
+ void populate();
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<Glib::ustring> col_repo_name;
+ };
+
+ Columns & columns();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repositories_page.cc b/src/clients/gtkpaludis/libgtkpaludis/repositories_page.cc
new file mode 100644
index 0000000..683383b
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repositories_page.cc
@@ -0,0 +1,70 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "repositories_page.hh"
+#include "repositories_list.hh"
+#include "repository_info.hh"
+#include "repository_buttons.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <gtkmm/scrolledwindow.h>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<RepositoriesPage>
+ {
+ MainWindow * const main_window;
+
+ Gtk::ScrolledWindow repositories_list_scroll;
+ RepositoriesList repositories_list;
+
+ Gtk::ScrolledWindow repository_info_scroll;
+ RepositoryInfo repository_info;
+
+ RepositoryButtons repository_buttons;
+
+ Implementation(MainWindow * const m, RepositoriesPage * const p) :
+ main_window(m),
+ repositories_list(m, p),
+ repository_info(m),
+ repository_buttons(m)
+ {
+ }
+ };
+}
+
+RepositoriesPage::RepositoriesPage(MainWindow * const m) :
+ Gtk::Table(2, 2),
+ MainNotebookPage(),
+ PrivateImplementationPattern<RepositoriesPage>(new Implementation<RepositoriesPage>(m, this))
+{
+ _imp->repositories_list_scroll.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
+ _imp->repositories_list_scroll.add(_imp->repositories_list);
+ attach(_imp->repositories_list_scroll, 0, 1, 0, 2, Gtk::SHRINK, Gtk::EXPAND | Gtk::FILL, 4, 4);
+
+ _imp->repository_info_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ _imp->repository_info_scroll.add(_imp->repository_info);
+ attach(_imp->repository_info_scroll, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 4, 4);
+
+ attach(_imp->repository_buttons, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL, 4, 4);
+}
+
+RepositoriesPage::~RepositoriesPage()
+{
+}
+
+void
+RepositoriesPage::populate()
+{
+ _imp->repositories_list.populate();
+}
+
+void
+RepositoriesPage::set_repository(const RepositoryName & name)
+{
+ _imp->repository_info.set_repository(name);
+ _imp->repository_buttons.set_repository(name);
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repositories_page.hh b/src/clients/gtkpaludis/libgtkpaludis/repositories_page.hh
new file mode 100644
index 0000000..dc45fc4
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repositories_page.hh
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_GTKPALUDIS_LIBGTKPALUDIS_REPOSITORIES_PAGE_HH
+#define GTKPALUDIS_GUARD_GTKPALUDIS_LIBGTKPALUDIS_REPOSITORIES_PAGE_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+#include <libgtkpaludis/main_notebook_page.hh>
+#include <gtkmm/table.h>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class RepositoriesPage :
+ public Gtk::Table,
+ public MainNotebookPage,
+ private paludis::PrivateImplementationPattern<RepositoriesPage>
+ {
+ public:
+ RepositoriesPage(MainWindow * const m);
+ ~RepositoriesPage();
+
+ virtual void populate();
+
+ void set_repository(const paludis::RepositoryName &);
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repository_buttons.cc b/src/clients/gtkpaludis/libgtkpaludis/repository_buttons.cc
new file mode 100644
index 0000000..9c15763
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repository_buttons.cc
@@ -0,0 +1,69 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "repository_buttons.hh"
+#include "main_window.hh"
+#include <gtkmm/button.h>
+#include <paludis/environment.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repository.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<RepositoryButtons>
+ {
+ MainWindow * const main_window;
+
+ Gtk::Button sync_button;
+ Gtk::Button sync_all_button;
+
+ Implementation(MainWindow * const m) :
+ main_window(m),
+ sync_button("Sync"),
+ sync_all_button("Sync All")
+ {
+ }
+ };
+}
+
+RepositoryButtons::RepositoryButtons(MainWindow * const m) :
+ Gtk::HButtonBox(),
+ PrivateImplementationPattern<RepositoryButtons>(new Implementation<RepositoryButtons>(m))
+{
+ set_layout(Gtk::BUTTONBOX_END);
+ set_spacing(10);
+
+ add(_imp->sync_button);
+ add(_imp->sync_all_button);
+}
+
+RepositoryButtons::~RepositoryButtons()
+{
+}
+
+void
+RepositoryButtons::set_repository(const RepositoryName & name)
+{
+ _imp->main_window->paludis_thread_action(
+ sigc::bind(sigc::mem_fun(this, &RepositoryButtons::set_repository_in_paludis_thread), name),
+ "Preparing repository buttons");
+}
+
+void
+RepositoryButtons::set_repository_in_paludis_thread(const RepositoryName & name)
+{
+ _imp->main_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &RepositoryButtons::set_repository_in_gui_thread),
+ 0 != _imp->main_window->environment()->package_database()->fetch_repository(name)->syncable_interface));
+}
+
+void
+RepositoryButtons::set_repository_in_gui_thread(const bool v)
+{
+ _imp->sync_button.set_sensitive(v);
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repository_buttons.hh b/src/clients/gtkpaludis/libgtkpaludis/repository_buttons.hh
new file mode 100644
index 0000000..fd2a16e
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repository_buttons.hh
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORY_BUTTONS_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORY_BUTTONS_HH 1
+
+#include <gtkmm/buttonbox.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class RepositoryButtons :
+ public Gtk::HButtonBox,
+ private paludis::PrivateImplementationPattern<RepositoryButtons>
+ {
+ private:
+ void set_repository_in_paludis_thread(const paludis::RepositoryName &);
+ void set_repository_in_gui_thread(const bool);
+
+ public:
+ RepositoryButtons(MainWindow * const m);
+ ~RepositoryButtons();
+
+ void set_repository(const paludis::RepositoryName &);
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repository_info.cc b/src/clients/gtkpaludis/libgtkpaludis/repository_info.cc
new file mode 100644
index 0000000..1fec280
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repository_info.cc
@@ -0,0 +1,45 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "repository_info.hh"
+#include "repository_info_model.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<gtkpaludis::RepositoryInfo>
+ {
+ MainWindow * const main_window;
+
+ Glib::RefPtr<RepositoryInfoModel> model;
+
+ Implementation(MainWindow * const m) :
+ main_window(m),
+ model(new RepositoryInfoModel(m))
+ {
+ }
+ };
+}
+
+RepositoryInfo::RepositoryInfo(MainWindow * const m) :
+ Gtk::TreeView(),
+ paludis::PrivateImplementationPattern<RepositoryInfo>(new paludis::Implementation<RepositoryInfo>(m))
+{
+ set_model(_imp->model);
+
+ append_column("Key", _imp->model->columns().col_key);
+ append_column("Value", _imp->model->columns().col_value);
+}
+
+RepositoryInfo::~RepositoryInfo()
+{
+}
+
+void
+RepositoryInfo::set_repository(const paludis::RepositoryName & name)
+{
+ _imp->model->set_repository(name);
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repository_info.hh b/src/clients/gtkpaludis/libgtkpaludis/repository_info.hh
new file mode 100644
index 0000000..d9c26a5
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repository_info.hh
@@ -0,0 +1,26 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORY_INFO_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORY_INFO_HH 1
+
+#include <gtkmm/treeview.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class RepositoryInfo :
+ public Gtk::TreeView,
+ private paludis::PrivateImplementationPattern<RepositoryInfo>
+ {
+ public:
+ RepositoryInfo(MainWindow * const);
+ ~RepositoryInfo();
+
+ void set_repository(const paludis::RepositoryName &);
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repository_info_model.cc b/src/clients/gtkpaludis/libgtkpaludis/repository_info_model.cc
new file mode 100644
index 0000000..d444bf2
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repository_info_model.cc
@@ -0,0 +1,94 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "repository_info_model.hh"
+#include "main_window.hh"
+#include <paludis/repository.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<RepositoryInfoModel>
+ {
+ MainWindow * const main_window;
+ RepositoryInfoModel::Columns columns;
+
+ Implementation(MainWindow * const m) :
+ main_window(m)
+ {
+ }
+ };
+}
+
+RepositoryInfoModel::RepositoryInfoModel(MainWindow * const m) :
+ PrivateImplementationPattern<RepositoryInfoModel>(new Implementation<RepositoryInfoModel>(m)),
+ Gtk::TreeStore(_imp->columns)
+{
+}
+
+RepositoryInfoModel::~RepositoryInfoModel()
+{
+}
+
+void
+RepositoryInfoModel::set_repository(const RepositoryName & name)
+{
+ _imp->main_window->paludis_thread_action(
+ sigc::bind(sigc::mem_fun(this, &RepositoryInfoModel::set_repository_in_paludis_thread), name),
+ "Populating repository information model");
+}
+
+void
+RepositoryInfoModel::set_repository_in_paludis_thread(const RepositoryName & name)
+{
+ paludis::tr1::shared_ptr<const RepositoryInfo> info(
+ _imp->main_window->environment()->package_database()->fetch_repository(name)->info(true));
+
+ _imp->main_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &RepositoryInfoModel::set_repository_in_gui_thread), info));
+}
+
+void
+RepositoryInfoModel::set_repository_in_gui_thread(paludis::tr1::shared_ptr<const RepositoryInfo> info)
+{
+ clear();
+ for (IndirectIterator<RepositoryInfo::SectionIterator>
+ s(indirect_iterator(info->begin_sections())), s_end(indirect_iterator(info->end_sections())) ;
+ s != s_end ; ++s)
+ {
+ iterator i(append());
+ (*i)[_imp->columns.col_key] = s->heading();
+
+ for (RepositoryInfoSection::KeyValueIterator k(s->begin_kvs()), k_end(s->end_kvs()) ;
+ k != k_end ; ++k)
+ {
+ iterator j(append(i->children()));
+ (*j)[_imp->columns.col_key] = k->first;
+ (*j)[_imp->columns.col_value] = k->second;
+ }
+ }
+}
+
+RepositoryInfoModel::Columns::Columns()
+{
+ add(col_key);
+ add(col_value);
+}
+
+RepositoryInfoModel::Columns::~Columns()
+{
+}
+
+RepositoryInfoModel::Columns &
+RepositoryInfoModel::columns()
+{
+ return _imp->columns;
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/repository_info_model.hh b/src/clients/gtkpaludis/libgtkpaludis/repository_info_model.hh
new file mode 100644
index 0000000..2f77bba
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/repository_info_model.hh
@@ -0,0 +1,49 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORY_INFO_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_REPOSITORY_INFO_MODEL_HH 1
+
+#include <gtkmm/treestore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+#include <paludis/util/tr1_memory.hh>
+
+namespace paludis
+{
+ class RepositoryInfo;
+}
+
+namespace gtkpaludis
+{
+ class MainWindow;
+
+ class RepositoryInfoModel :
+ private paludis::PrivateImplementationPattern<RepositoryInfoModel>,
+ public Gtk::TreeStore
+ {
+ private:
+ void set_repository_in_paludis_thread(const paludis::RepositoryName &);
+ void set_repository_in_gui_thread(paludis::tr1::shared_ptr<const paludis::RepositoryInfo>);
+
+ public:
+ RepositoryInfoModel(MainWindow * const);
+ ~RepositoryInfoModel();
+
+ void set_repository(const paludis::RepositoryName &);
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<Glib::ustring> col_key;
+ Gtk::TreeModelColumn<Glib::ustring> col_value;
+ };
+
+ Columns & columns();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/threaded_window.cc b/src/clients/gtkpaludis/libgtkpaludis/threaded_window.cc
new file mode 100644
index 0000000..772f941
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/threaded_window.cc
@@ -0,0 +1,181 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "threaded_window.hh"
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <unistd.h>
+#include <algorithm>
+#include <list>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<ThreadedWindow>
+ {
+ Environment * const environment;
+
+ int sensitivity;
+ Gtk::Widget * saved_focus;
+
+ Glib::Mutex gui_queue_lock;
+ std::list<sigc::slot<void> > gui_queue;
+
+ Glib::Mutex paludis_queue_lock;
+ std::list<sigc::slot<void> > paludis_queue;
+ int paludis_queue_pipe[2];
+
+ bool paludis_queue_exit;
+
+ Glib::Thread * paludis_thread;
+
+ Implementation(Environment * const e) :
+ environment(e),
+ sensitivity(0),
+ saved_focus(0),
+ paludis_queue_exit(false)
+ {
+ if (0 != pipe(paludis_queue_pipe))
+ throw InternalError(PALUDIS_HERE, "pipe() failed");
+ }
+ };
+}
+
+ThreadedWindow::ThreadedWindow(Gtk::WindowType w, Environment * const e) :
+ Gtk::Window(w),
+ PrivateImplementationPattern<ThreadedWindow>(new Implementation<ThreadedWindow>(e))
+{
+ Glib::signal_timeout().connect(sigc::mem_fun(this, &ThreadedWindow::run_gui_queue), 10);
+ _imp->paludis_thread = Glib::Thread::create(sigc::mem_fun(this, &ThreadedWindow::run_paludis_queue), true);
+ signal_delete_event().connect(sigc::mem_fun(this, &ThreadedWindow::handle_delete_event));
+}
+
+ThreadedWindow::~ThreadedWindow()
+{
+}
+
+bool
+ThreadedWindow::handle_delete_event(GdkEventAny *)
+{
+ desensitise();
+
+ _imp->paludis_queue_exit = true;
+ char x('x');
+ write(_imp->paludis_queue_pipe[1], &x, 1);
+ _imp->paludis_thread->join();
+
+ return false;
+}
+
+void
+ThreadedWindow::paludis_thread_action(const sigc::slot<void> & a, const std::string & status_message)
+{
+ desensitise();
+ Glib::Mutex::Lock l(_imp->paludis_queue_lock);
+ _imp->paludis_queue.push_back(sigc::bind(sigc::mem_fun(this, &ThreadedWindow::paludis_thread_action_then_sensitise),
+ a, status_message));
+
+ char x('x');
+ write(_imp->paludis_queue_pipe[1], &x, 1);
+}
+
+void
+ThreadedWindow::paludis_thread_action_then_sensitise(const sigc::slot<void> & a, const std::string & status_message)
+{
+ if (! status_message.empty())
+ gui_thread_action(sigc::bind(sigc::mem_fun(this, &ThreadedWindow::push_status_message), status_message));
+
+ a();
+
+ if (! status_message.empty())
+ gui_thread_action(sigc::mem_fun(this, &ThreadedWindow::pop_status_message));
+
+ gui_thread_action(sigc::mem_fun(this, &ThreadedWindow::sensitise));
+}
+
+void
+ThreadedWindow::gui_thread_action(const sigc::slot<void> & a)
+{
+ Glib::Mutex::Lock l(_imp->gui_queue_lock);
+ _imp->gui_queue.push_back(a);
+}
+
+void
+ThreadedWindow::sensitise()
+{
+ if (0 == --_imp->sensitivity)
+ {
+ do_set_sensitive(true);
+ if (_imp->saved_focus)
+ {
+ set_focus(*_imp->saved_focus);
+ _imp->saved_focus = 0;
+ }
+ }
+}
+
+void
+ThreadedWindow::desensitise()
+{
+ if (0 == _imp->sensitivity++)
+ {
+ _imp->saved_focus = get_focus();
+ do_set_sensitive(false);
+ }
+}
+
+bool
+ThreadedWindow::run_gui_queue()
+{
+ std::list<sigc::slot<void> > local_queue;
+
+ {
+ Glib::Mutex::Lock l(_imp->gui_queue_lock);
+ if (! _imp->gui_queue.empty())
+ local_queue.splice(local_queue.begin(), _imp->gui_queue, _imp->gui_queue.begin(), _imp->gui_queue.end());
+ }
+
+ std::for_each(local_queue.begin(), local_queue.end(), paludis::tr1::mem_fn(&sigc::slot<void>::operator ()));
+
+ return true;
+}
+
+void
+ThreadedWindow::run_paludis_queue()
+{
+ while (! _imp->paludis_queue_exit)
+ {
+ std::list<sigc::slot<void> > local_queue;
+
+ {
+ Glib::Mutex::Lock l(_imp->paludis_queue_lock);
+ if (! _imp->paludis_queue.empty())
+ local_queue.splice(local_queue.begin(), _imp->paludis_queue, _imp->paludis_queue.begin(), _imp->paludis_queue.end());
+ }
+
+ if (local_queue.empty())
+ {
+ char buf[1024];
+ read(_imp->paludis_queue_pipe[0], &buf, 1023);
+ }
+ else
+ std::for_each(local_queue.begin(), local_queue.end(), paludis::tr1::mem_fn(&sigc::slot<void>::operator ()));
+ }
+}
+
+Environment *
+ThreadedWindow::environment()
+{
+ return _imp->environment;
+}
+
+void
+ThreadedWindow::do_set_sensitive(const bool v)
+{
+ set_sensitive(v);
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/threaded_window.hh b/src/clients/gtkpaludis/libgtkpaludis/threaded_window.hh
new file mode 100644
index 0000000..000fd8a
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/threaded_window.hh
@@ -0,0 +1,46 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_THREADED_WINDOW_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_THREADED_WINDOW_HH 1
+
+#include <gtkmm/window.h>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class Environment;
+}
+
+namespace gtkpaludis
+{
+ class ThreadedWindow :
+ public Gtk::Window,
+ private paludis::PrivateImplementationPattern<ThreadedWindow>
+ {
+ protected:
+ virtual bool handle_delete_event(GdkEventAny *);
+
+ void paludis_thread_action_then_sensitise(const sigc::slot<void> &, const std::string & status_message);
+ void desensitise();
+ void sensitise();
+ virtual void do_set_sensitive(const bool);
+
+ bool run_gui_queue();
+ void run_paludis_queue();
+
+ ThreadedWindow(Gtk::WindowType, paludis::Environment * const);
+
+ virtual void push_status_message(const std::string &) = 0;
+ virtual void pop_status_message() = 0;
+
+ public:
+ ~ThreadedWindow();
+
+ void paludis_thread_action(const sigc::slot<void> &, const std::string & status_message);
+ void gui_thread_action(const sigc::slot<void> &);
+
+ paludis::Environment * environment();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/version_info.cc b/src/clients/gtkpaludis/libgtkpaludis/version_info.cc
new file mode 100644
index 0000000..b120a23
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/version_info.cc
@@ -0,0 +1,68 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "version_info.hh"
+#include "version_info_model.hh"
+#include "versions_page.hh"
+#include "query_window.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<VersionInfo>
+ {
+ Glib::RefPtr<VersionInfoModel> model;
+ QueryWindow * const query_window;
+ VersionsPage * const versions_page;
+
+ Implementation(QueryWindow * const m, VersionsPage * const p) :
+ model(new VersionInfoModel(m, p)),
+ query_window(m),
+ versions_page(p)
+ {
+ }
+ };
+}
+
+VersionInfo::VersionInfo(QueryWindow * const m, VersionsPage * const p) :
+ Gtk::TreeView(),
+ PrivateImplementationPattern<VersionInfo>(new Implementation<VersionInfo>(m, p))
+{
+ set_model(_imp->model);
+
+ append_column("Key", _imp->model->columns().col_key);
+
+ Gtk::CellRendererText renderer;
+ int c(append_column("Value", renderer) - 1);
+ get_column(c)->add_attribute(renderer, "markup", _imp->model->columns().col_value_markup.index());
+}
+
+VersionInfo::~VersionInfo()
+{
+}
+
+void
+VersionInfo::populate()
+{
+ _imp->model->populate();
+ _imp->query_window->paludis_thread_action(
+ sigc::mem_fun(this, &VersionInfo::populate_in_paludis_thread), "Populating version information");
+}
+
+void
+VersionInfo::populate_in_paludis_thread()
+{
+ _imp->query_window->gui_thread_action(
+ sigc::mem_fun(this, &VersionInfo::populate_in_gui_thread));
+}
+
+void
+VersionInfo::populate_in_gui_thread()
+{
+ expand_all();
+ columns_autosize();
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/version_info.hh b/src/clients/gtkpaludis/libgtkpaludis/version_info.hh
new file mode 100644
index 0000000..7d587ae
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/version_info.hh
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSION_INFO_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSION_INFO_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <gtkmm/treeview.h>
+
+namespace gtkpaludis
+{
+ class QueryWindow;
+ class VersionsPage;
+
+ class VersionInfo :
+ public Gtk::TreeView,
+ private paludis::PrivateImplementationPattern<VersionInfo>
+ {
+ protected:
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread();
+
+ public:
+ VersionInfo(QueryWindow * const m, VersionsPage * const p);
+ ~VersionInfo();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc b/src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc
new file mode 100644
index 0000000..1005c7b
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc
@@ -0,0 +1,146 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "version_info_model.hh"
+#include "query_window.hh"
+#include "versions_page.hh"
+#include "markup.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/query.hh>
+#include <list>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<VersionInfoModel>
+ {
+ QueryWindow * const query_window;
+ VersionsPage * const versions_page;
+ VersionInfoModel::Columns columns;
+
+ Implementation(QueryWindow * const m, VersionsPage * const p) :
+ query_window(m),
+ versions_page(p)
+ {
+ }
+ };
+}
+
+namespace
+{
+ struct PopulateDataItem
+ {
+ std::string key;
+ std::string value_markup;
+
+ PopulateDataItem(const std::string & k, const std::string & m) :
+ key(k),
+ value_markup(m)
+ {
+ }
+ };
+}
+
+namespace gtkpaludis
+{
+ struct VersionInfoModel::PopulateData
+ {
+ std::list<PopulateDataItem> items;
+ };
+}
+
+
+VersionInfoModel::VersionInfoModel(QueryWindow * const m, VersionsPage * const p) :
+ PrivateImplementationPattern<VersionInfoModel>(new Implementation<VersionInfoModel>(m, p)),
+ Gtk::TreeStore(_imp->columns)
+{
+}
+
+VersionInfoModel::~VersionInfoModel()
+{
+}
+
+VersionInfoModel::Columns::Columns()
+{
+ add(col_key);
+ add(col_value_markup);
+}
+
+VersionInfoModel::Columns::~Columns()
+{
+}
+
+VersionInfoModel::Columns &
+VersionInfoModel::columns()
+{
+ return _imp->columns;
+}
+
+void
+VersionInfoModel::populate()
+{
+ _imp->query_window->paludis_thread_action(
+ sigc::bind(sigc::mem_fun(this, &VersionInfoModel::populate_in_paludis_thread),
+ _imp->versions_page->get_pde()), "Populating version information model");
+}
+
+void
+VersionInfoModel::populate_in_paludis_thread(paludis::tr1::shared_ptr<const PackageDatabaseEntry> p)
+{
+ paludis::tr1::shared_ptr<PopulateData> data(new PopulateData);
+
+ if (p)
+ {
+ paludis::tr1::shared_ptr<const VersionMetadata> metadata(
+ _imp->query_window->environment()->package_database()->fetch_repository(p->repository)->version_metadata(
+ p->name, p->version));
+
+ data->items.push_back(PopulateDataItem("Description", markup_escape(metadata->description)));
+
+ if (metadata->ebuild_interface)
+ {
+ std::string km;
+ paludis::tr1::shared_ptr<const KeywordNameCollection> keywords(metadata->ebuild_interface->keywords());
+ for (KeywordNameCollection::Iterator k(keywords->begin()), k_end(keywords->end()) ;
+ k != k_end ; ++k)
+ {
+ if (! km.empty())
+ km.append(" ");
+
+ paludis::tr1::shared_ptr<KeywordNameCollection> kc(new KeywordNameCollection::Concrete);
+ kc->insert(*k);
+ if (_imp->query_window->environment()->accept_keywords(kc, *p))
+ km.append(markup_bold(markup_escape(stringify(*k))));
+ else
+ km.append(markup_italic(markup_escape(stringify(*k))));
+ }
+
+ data->items.push_back(PopulateDataItem("Keywords", km));
+ }
+ }
+
+ _imp->query_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &VersionInfoModel::populate_in_gui_thread), data));
+}
+
+void
+VersionInfoModel::populate_in_gui_thread(paludis::tr1::shared_ptr<const VersionInfoModel::PopulateData> names)
+{
+ clear();
+
+ for (std::list<PopulateDataItem>::const_iterator i(names->items.begin()), i_end(names->items.end()) ;
+ i != i_end ; ++i)
+ {
+ iterator r(append());
+ (*r)[_imp->columns.col_key] = i->key;
+ (*r)[_imp->columns.col_value_markup] = i->value_markup;
+ }
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/version_info_model.hh b/src/clients/gtkpaludis/libgtkpaludis/version_info_model.hh
new file mode 100644
index 0000000..8a62bc9
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/version_info_model.hh
@@ -0,0 +1,47 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSION_INFO_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSION_INFO_MODEL_HH 1
+
+#include <gtkmm/treestore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+#include <paludis/package_database_entry.hh>
+
+namespace gtkpaludis
+{
+ class QueryWindow;
+ class VersionsPage;
+
+ class VersionInfoModel :
+ private paludis::PrivateImplementationPattern<VersionInfoModel>,
+ public Gtk::TreeStore
+ {
+ protected:
+ class PopulateData;
+
+ void populate_in_paludis_thread(paludis::tr1::shared_ptr<const paludis::PackageDatabaseEntry>);
+ void populate_in_gui_thread(paludis::tr1::shared_ptr<const PopulateData> names);
+
+ public:
+ VersionInfoModel(QueryWindow * const m, VersionsPage * const p);
+ ~VersionInfoModel();
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<Glib::ustring> col_key;
+ Gtk::TreeModelColumn<Glib::ustring> col_value_markup;
+ };
+
+ Columns & columns();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/versions_list.cc b/src/clients/gtkpaludis/libgtkpaludis/versions_list.cc
new file mode 100644
index 0000000..df03572
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/versions_list.cc
@@ -0,0 +1,99 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "versions_list.hh"
+#include "versions_list_model.hh"
+#include "versions_page.hh"
+#include "query_window.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<VersionsList>
+ {
+ Glib::RefPtr<VersionsListModel> model;
+ QueryWindow * const query_window;
+ VersionsPage * const versions_page;
+
+ Implementation(QueryWindow * const m, VersionsPage * const p) :
+ model(new VersionsListModel(m, p)),
+ query_window(m),
+ versions_page(p)
+ {
+ }
+ };
+}
+
+VersionsList::VersionsList(QueryWindow * const m, VersionsPage * const p) :
+ Gtk::TreeView(),
+ PrivateImplementationPattern<VersionsList>(new Implementation<VersionsList>(m, p))
+{
+ set_model(_imp->model);
+
+ append_column("Version", _imp->model->columns().col_version_string);
+ append_column("Repository", _imp->model->columns().col_repo_name);
+ append_column("Slot", _imp->model->columns().col_slot);
+
+ Gtk::CellRendererText renderer;
+ int c(append_column("Masks", renderer) - 1);
+ get_column(c)->add_attribute(renderer, "markup", _imp->model->columns().col_masks_markup.index());
+
+ signal_cursor_changed().connect(sigc::mem_fun(this, &VersionsList::handle_signal_cursor_changed));
+}
+
+VersionsList::~VersionsList()
+{
+}
+
+void
+VersionsList::handle_signal_cursor_changed()
+{
+ if (get_selection()->get_selected())
+ _imp->versions_page->set_pde(paludis::tr1::shared_ptr<PackageDatabaseEntry>(new PackageDatabaseEntry(*
+ (*get_selection()->get_selected())[_imp->model->columns().col_pde].operator
+ paludis::tr1::shared_ptr<const PackageDatabaseEntry> ())));
+ else
+ _imp->versions_page->set_pde(paludis::tr1::shared_ptr<PackageDatabaseEntry>());
+}
+
+void
+VersionsList::populate()
+{
+ _imp->model->populate();
+ _imp->query_window->paludis_thread_action(
+ sigc::mem_fun(this, &VersionsList::populate_in_paludis_thread), "Populating versions list");
+}
+
+void
+VersionsList::populate_in_paludis_thread()
+{
+ _imp->query_window->gui_thread_action(
+ sigc::mem_fun(this, &VersionsList::populate_in_gui_thread));
+}
+
+void
+VersionsList::populate_in_gui_thread()
+{
+ expand_all();
+ columns_autosize();
+
+ if (! get_selection()->get_selected())
+ if (! _imp->model->children().empty())
+ {
+ bool found(false);
+ for (Gtk::TreeModel::iterator i(_imp->model->children().begin()), i_end(_imp->model->children().end()) ;
+ i != i_end && ! found; ++i)
+ if ((*i)[_imp->model->columns().col_prefer_default])
+ {
+ set_cursor(_imp->model->get_path(*i));
+ found = true;
+ }
+
+ if (! found)
+ set_cursor(_imp->model->get_path(_imp->model->children().begin()));
+ }
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/versions_list.hh b/src/clients/gtkpaludis/libgtkpaludis/versions_list.hh
new file mode 100644
index 0000000..d0ccb26
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/versions_list.hh
@@ -0,0 +1,31 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSIONS_LIST_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSIONS_LIST_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <gtkmm/treeview.h>
+
+namespace gtkpaludis
+{
+ class QueryWindow;
+ class VersionsPage;
+
+ class VersionsList :
+ public Gtk::TreeView,
+ private paludis::PrivateImplementationPattern<VersionsList>
+ {
+ protected:
+ void handle_signal_cursor_changed();
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread();
+
+ public:
+ VersionsList(QueryWindow * const m, VersionsPage * const p);
+ ~VersionsList();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/versions_list_model.cc b/src/clients/gtkpaludis/libgtkpaludis/versions_list_model.cc
new file mode 100644
index 0000000..0edfbc8
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/versions_list_model.cc
@@ -0,0 +1,196 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "versions_list_model.hh"
+#include "query_window.hh"
+#include "versions_page.hh"
+#include "markup.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/query.hh>
+#include <list>
+
+using namespace paludis;
+using namespace gtkpaludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<VersionsListModel>
+ {
+ QueryWindow * const query_window;
+ VersionsPage * const versions_page;
+ VersionsListModel::Columns columns;
+
+ Implementation(QueryWindow * const m, VersionsPage * const p) :
+ query_window(m),
+ versions_page(p)
+ {
+ }
+ };
+}
+
+namespace
+{
+ struct PopulateDataItem
+ {
+ PackageDatabaseEntry pde;
+ std::string slot;
+ std::string masks;
+ bool prefer_default;
+
+ PopulateDataItem(const PackageDatabaseEntry & d, const std::string & s,
+ const std::string & m, const bool p) :
+ pde(d),
+ slot(s),
+ masks(m),
+ prefer_default(p)
+ {
+ }
+ };
+}
+
+namespace gtkpaludis
+{
+ struct VersionsListModel::PopulateData
+ {
+ std::list<PopulateDataItem> items;
+ };
+}
+
+
+VersionsListModel::VersionsListModel(QueryWindow * const m, VersionsPage * const p) :
+ PrivateImplementationPattern<VersionsListModel>(new Implementation<VersionsListModel>(m, p)),
+ Gtk::TreeStore(_imp->columns)
+{
+}
+
+VersionsListModel::~VersionsListModel()
+{
+}
+
+VersionsListModel::Columns::Columns()
+{
+ add(col_version_string);
+ add(col_repo_name);
+ add(col_slot);
+ add(col_masks_markup);
+ add(col_pde);
+ add(col_prefer_default);
+}
+
+VersionsListModel::Columns::~Columns()
+{
+}
+
+VersionsListModel::Columns &
+VersionsListModel::columns()
+{
+ return _imp->columns;
+}
+
+void
+VersionsListModel::populate()
+{
+ _imp->query_window->paludis_thread_action(
+ sigc::mem_fun(this, &VersionsListModel::populate_in_paludis_thread),
+ "Populating versions list model");
+}
+
+void
+VersionsListModel::populate_in_paludis_thread()
+{
+ paludis::tr1::shared_ptr<PopulateData> data(new PopulateData);
+ paludis::tr1::shared_ptr<const PackageDatabaseEntryCollection> c(
+ _imp->query_window->environment()->package_database()->query(
+ query::Package(_imp->query_window->get_package_name()),
+ qo_order_by_version));
+
+ for (PackageDatabaseEntryCollection::ReverseIterator p(c->rbegin()), p_end(c->rend()) ;
+ p != p_end ; ++p)
+ {
+ bool prefer_default(true);
+
+ paludis::tr1::shared_ptr<const VersionMetadata> metadata(
+ _imp->query_window->environment()->package_database()->fetch_repository(p->repository)->version_metadata(
+ p->name, p->version));
+
+ MaskReasons mask_reasons(_imp->query_window->environment()->mask_reasons(*p));
+ std::string mr_string;
+
+ for (MaskReason m(MaskReason(0)) ; m < last_mr ;
+ m = MaskReason(static_cast<int>(m) + 1))
+ {
+ if (! mask_reasons[m])
+ continue;
+
+ prefer_default = false;
+ if (! mr_string.empty())
+ mr_string.append(", ");
+
+ switch (m)
+ {
+ case mr_keyword:
+ mr_string.append("keyword");
+ break;
+ case mr_user_mask:
+ mr_string.append("user mask");
+ break;
+ case mr_profile_mask:
+ mr_string.append("profile mask");
+ break;
+ case mr_repository_mask:
+ mr_string.append("repository mask");
+ break;
+ case mr_eapi:
+ mr_string.append("EAPI");
+ break;
+ case mr_license:
+ mr_string.append("licence");
+ break;
+ case mr_by_association:
+ mr_string.append("by association");
+ break;
+ case mr_chost:
+ mr_string.append("wrong CHOST");
+ break;
+ case mr_breaks_portage:
+ mr_string.append("breaks Portage");
+ break;
+ case mr_interactive:
+ mr_string.append("interactive");
+ break;
+
+ case last_mr:
+ break;
+ }
+ }
+
+ data->items.push_back(PopulateDataItem(*p, stringify(metadata->slot), mr_string, prefer_default));
+ }
+
+ _imp->query_window->gui_thread_action(
+ sigc::bind(sigc::mem_fun(this, &VersionsListModel::populate_in_gui_thread), data));
+}
+
+void
+VersionsListModel::populate_in_gui_thread(paludis::tr1::shared_ptr<const VersionsListModel::PopulateData> names)
+{
+ clear();
+
+ for (std::list<PopulateDataItem>::const_iterator i(names->items.begin()), i_end(names->items.end()) ;
+ i != i_end ; ++i)
+ {
+ iterator r(append());
+ (*r)[_imp->columns.col_pde] = paludis::tr1::shared_ptr<PackageDatabaseEntry>(new PackageDatabaseEntry(i->pde));
+ (*r)[_imp->columns.col_repo_name] = stringify(i->pde.repository);
+ (*r)[_imp->columns.col_version_string] = stringify(i->pde.version);
+ (*r)[_imp->columns.col_slot] = i->slot;
+ (*r)[_imp->columns.col_masks_markup] = i->masks;
+ (*r)[_imp->columns.col_prefer_default] = i->prefer_default;
+ }
+}
+
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/versions_list_model.hh b/src/clients/gtkpaludis/libgtkpaludis/versions_list_model.hh
new file mode 100644
index 0000000..82391f3
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/versions_list_model.hh
@@ -0,0 +1,51 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSIONS_LIST_MODEL_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSIONS_LIST_MODEL_HH 1
+
+#include <gtkmm/treestore.h>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/name.hh>
+#include <paludis/package_database_entry.hh>
+
+namespace gtkpaludis
+{
+ class QueryWindow;
+ class VersionsPage;
+
+ class VersionsListModel :
+ private paludis::PrivateImplementationPattern<VersionsListModel>,
+ public Gtk::TreeStore
+ {
+ protected:
+ class PopulateData;
+
+ void populate_in_paludis_thread();
+ void populate_in_gui_thread(paludis::tr1::shared_ptr<const PopulateData> names);
+
+ public:
+ VersionsListModel(QueryWindow * const m, VersionsPage * const p);
+ ~VersionsListModel();
+
+ class Columns :
+ public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Columns();
+ ~Columns();
+
+ Gtk::TreeModelColumn<Glib::ustring> col_version_string;
+ Gtk::TreeModelColumn<Glib::ustring> col_repo_name;
+ Gtk::TreeModelColumn<Glib::ustring> col_slot;
+ Gtk::TreeModelColumn<Glib::ustring> col_masks_markup;
+ Gtk::TreeModelColumn<paludis::tr1::shared_ptr<const paludis::PackageDatabaseEntry> > col_pde;
+ Gtk::TreeModelColumn<bool> col_prefer_default;
+ };
+
+ Columns & columns();
+
+ void populate();
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/libgtkpaludis/versions_page.cc b/src/clients/gtkpaludis/libgtkpaludis/versions_page.cc
new file mode 100644
index 0000000..4e595c8
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/versions_page.cc
@@ -0,0 +1,72 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "versions_page.hh"
+#include "versions_list.hh"
+#include "version_info.hh"
+#include <gtkmm/scrolledwindow.h>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace gtkpaludis;
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<VersionsPage>
+ {
+ QueryWindow * const query_window;
+
+ Gtk::ScrolledWindow versions_list_scroll;
+ VersionsList versions_list;
+
+ Gtk::ScrolledWindow version_info_scroll;
+ VersionInfo version_info;
+
+ paludis::tr1::shared_ptr<const PackageDatabaseEntry> pde;
+
+ Implementation(QueryWindow * const m, VersionsPage * const p) :
+ query_window(m),
+ versions_list(m, p),
+ version_info(m, p)
+ {
+ }
+ };
+}
+
+VersionsPage::VersionsPage(QueryWindow * const m) :
+ Gtk::Table(2, 1),
+ QueryNotebookPage(),
+ PrivateImplementationPattern<VersionsPage>(new Implementation<VersionsPage>(m, this))
+{
+ _imp->versions_list_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
+ _imp->versions_list_scroll.add(_imp->versions_list);
+ attach(_imp->versions_list_scroll, 0, 1, 0, 1, Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 4, 4);
+
+ _imp->version_info_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ _imp->version_info_scroll.add(_imp->version_info);
+ attach(_imp->version_info_scroll, 0, 1, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, 4, 4);
+}
+
+VersionsPage::~VersionsPage()
+{
+}
+
+void
+VersionsPage::populate()
+{
+ _imp->versions_list.populate();
+}
+
+void
+VersionsPage::set_pde(paludis::tr1::shared_ptr<const PackageDatabaseEntry> c)
+{
+ _imp->pde = c;
+ _imp->version_info.populate();
+}
+
+paludis::tr1::shared_ptr<const PackageDatabaseEntry>
+VersionsPage::get_pde() const
+{
+ return _imp->pde;
+}
+
diff --git a/src/clients/gtkpaludis/libgtkpaludis/versions_page.hh b/src/clients/gtkpaludis/libgtkpaludis/versions_page.hh
new file mode 100644
index 0000000..dc50354
--- /dev/null
+++ b/src/clients/gtkpaludis/libgtkpaludis/versions_page.hh
@@ -0,0 +1,31 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#ifndef GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSIONS_PAGE_HH
+#define GTKPALUDIS_GUARD_LIBGTKPALUDIS_VERSIONS_PAGE_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/package_database_entry.hh>
+#include <libgtkpaludis/query_notebook_page.hh>
+#include <gtkmm/table.h>
+
+namespace gtkpaludis
+{
+ class QueryWindow;
+
+ class VersionsPage :
+ public Gtk::Table,
+ public QueryNotebookPage,
+ private paludis::PrivateImplementationPattern<VersionsPage>
+ {
+ public:
+ VersionsPage(QueryWindow * const m);
+ ~VersionsPage();
+
+ virtual void populate();
+
+ void set_pde(paludis::tr1::shared_ptr<const paludis::PackageDatabaseEntry>);
+ paludis::tr1::shared_ptr<const paludis::PackageDatabaseEntry> get_pde() const;
+ };
+}
+
+#endif
diff --git a/src/clients/gtkpaludis/vtemm/Makefile.am b/src/clients/gtkpaludis/vtemm/Makefile.am
new file mode 100644
index 0000000..4079bd1
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/Makefile.am
@@ -0,0 +1,70 @@
+EXTRA_DIST = \
+ terminal_widget.hg terminal_widget.ccg \
+ reaper.hg reaper.ccg
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_NO_WOLD_STYLE_CAST@ \
+ @PALUDIS_CXXFLAGS_NO_WSHADOW@ @PALUDIS_CXXFLAGS_NO_WREDUNDANT_DECLS@
+
+DEFS = \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DGLIBMM_EXCEPTIONS_ENABLED=1
+
+vte_generated_sources = \
+ terminal_widget.cc terminal_widget.hh private/terminal_widget_p.hh \
+ reaper.cc reaper.hh private/reaper_p.hh
+
+SUBDIRS = defs converts .
+
+BUILT_SOURCES = terminal_widget.hh reaper.hh $(vte_generated_sources)
+
+# automake is rather weird on this one...
+automake-deps-hack.tmp :
+ $(MAKE) -C defs
+ touch $@
+
+terminal_widget.hh terminal_widget.cc : terminal_widget.hg terminal_widget.ccg automake-deps-hack.tmp
+ mkdir -p private
+ @GMMPROC@ --unwrapped -I converts --defs defs terminal_widget . .
+ sed -e 's@/\* vim: set @/* vim: set ro @' < ./terminal_widget.h > ./terminal_widget.hh
+ rm terminal_widget.h
+ mv ./terminal_widget.cc ./terminal_widget.cc.tmp
+ sed \
+ -e 's@#include <vtemm/terminal_widget.h>@#include "terminal_widget.hh"@' \
+ -e 's@#include <vtemm/private/terminal_widget_p.h>@#include "private/terminal_widget_p.hh"@' \
+ -e 's@/\* vim: set @/* vim: set ro @' \
+ < ./terminal_widget.cc.tmp > ./terminal_widget.cc
+ rm ./terminal_widget.cc.tmp
+ mv ./private/terminal_widget_p.h ./private/terminal_widget_p.hh
+
+reaper.hh reaper.cc : reaper.hg reaper.ccg automake-deps-hack.tmp
+ mkdir -p private
+ @GMMPROC@ --unwrapped -I converts --defs defs reaper . .
+ sed -e 's@/\* vim: set @/* vim: set ro @' < ./reaper.h > ./reaper.hh
+ rm reaper.h
+ mv ./reaper.cc ./reaper.cc.tmp
+ sed \
+ -e 's@#include <vtemm/reaper.h>@#include "reaper.hh"@' \
+ -e 's@#include <vtemm/private/reaper_p.h>@#include "private/reaper_p.hh"@' \
+ -e 's@/\* vim: set @/* vim: set ro @' \
+ < ./reaper.cc.tmp > ./reaper.cc
+ rm ./reaper.cc.tmp
+ mv ./private/reaper_p.h ./private/reaper_p.hh
+
+noinst_LIBRARIES = libvtemm.a
+
+nodist_libvtemm_a_SOURCES = \
+ $(vte_generated_sources)
+
+INCLUDES = $(gtkmm_CFLAGS) $(vte_CFLAGS)
+
+clean-local :
+ rm -fr private || true
+
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda $(vte_generated_sources) automake-deps-hack.tmp
+MAINTAINERCLEANFILES = Makefile.in
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+
diff --git a/src/clients/gtkpaludis/vtemm/converts/Makefile.am b/src/clients/gtkpaludis/vtemm/converts/Makefile.am
new file mode 100644
index 0000000..ea65efb
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/converts/Makefile.am
@@ -0,0 +1,9 @@
+noinst_DATA = convert.m4 convert_base.m4
+CLEANFILES = *~
+MAINTAINERCLEANFILES = Makefile.in
+EXTRA_DIST = $(noinst_DATA)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+
diff --git a/src/clients/gtkpaludis/vtemm/converts/convert.m4 b/src/clients/gtkpaludis/vtemm/converts/convert.m4
new file mode 100644
index 0000000..319807e
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/converts/convert.m4
@@ -0,0 +1,30 @@
+dnl $Id: convert.m4,v 1.1.1.1 2003/01/21 13:41:24 murrayc Exp $
+
+# Other libraries, such as libgnomeuimm, can provide their own convert.m4 files,
+# Maybe choosing to include the same files as this one.
+
+include(convert_gtkmm.m4)
+
+_CONV_ENUM(Vte,TerminalEraseBinding)
+_CONV_ENUM(Vte,TerminalAntiAlias)
+
+_EQUAL(glong, long)
+_EQUAL(guint, unsigned)
+
+_CONVERSION(int&, int*, &($3))
+_CONVERSION(long&, glong*, &($3))
+_CONVERSION(return-char*, char*, ($3))
+
+# Gtk conversions
+_CONVERSION(const Gtk::MenuShell&, GtkMenuShell*, (const_cast<Gtk::MenuShell&>($3)).gobj())
+
+# Gdk conversions
+_CONVERSION(const Gdk::Color&, const GdkColor*, ($3).gobj())
+_CONVERSION(Gdk::Color&, GdkColor*, ($3).gobj())
+_CONVERSION(Gdk::Cursor&, GdkCursor*, ($3).gobj())
+
+# Pango conversions
+_CONVERSION(const Pango::FontDescription&, const PangoFontDescription*, ($3).gobj())
+_CONVERSION(const PangoFontDescription*, const Pango::FontDescription, Glib::wrap(const_cast<PangoFontDescription*>(($3)), true))
+
+
diff --git a/src/clients/gtkpaludis/vtemm/converts/convert_base.m4 b/src/clients/gtkpaludis/vtemm/converts/convert_base.m4
new file mode 100644
index 0000000..feaf583
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/converts/convert_base.m4
@@ -0,0 +1,69 @@
+dnl $Id: convert_base.m4,v 1.1.1.1 2003/01/21 13:41:24 murrayc Exp $
+
+#
+# Define a hashing for names
+#
+define(`__HASH',`__`'m4_translit(`$*',`ABCDEFGHIJKLMNOPQRSTUVWXYZ<>[]&*, ',`abcdefghijklmnopqrstuvwxyzVBNMRSC_')`'')
+define(`__EQUIV',`m4_ifdef(EV`'__HASH(`$1'),EV`'__HASH(`$1'),`$1')')
+
+define(`__HASH2',`dnl
+pushdef(`__E1',__EQUIV(`$1'))pushdef(`__E2',__EQUIV(`$2'))dnl
+m4_ifelse(__E1,__E2,`__EQ',__HASH(__E1)`'__HASH(__E2))`'dnl
+popdef(`__E1')popdef(`__E2')`'')
+
+define(`CF__EQ',`$3')
+
+#
+# _CONVERT(ctype, cpptype, name, wrap_line)
+# Print the conversion from ctype to cpptype
+define(`_CONVERT',`dnl
+pushdef(`__COV',`CF`'__HASH2(`$1',`$2')')dnl
+m4_ifdef(__COV,`m4_indir(__COV,`$1',`$2',`$3')',`
+m4_errprint(`No conversion from $1 to $2 defined (line: $4, parameter name: $3)
+')
+m4_m4exit(1)
+')`'dnl
+')
+
+
+#
+# Functions for populating the tables.
+#
+define(`_CONVERSION',`
+m4_ifelse(`$3',,,`define(CF`'__HASH2(`$1',`$2'),`$3')')
+')
+
+define(`_EQUAL',`define(EV`'__HASH(`$1'),`$2')')
+
+/*******************************************************************/
+
+
+define(`__ARG3__',`$`'3')
+define(`_CONV_ENUM',`dnl
+_CONVERSION(`$1$2', `$2', (($2)(__ARG3__)))
+_CONVERSION(`$1$2', `$1::$2', (($1::$2)(__ARG3__)))
+_CONVERSION(`$2', `$1$2', (($1$2)(__ARG3__)))
+_CONVERSION(`$1::$2', `$1$2', (($1$2)(__ARG3__)))
+')dnl
+
+# e.g. Glib::RefPtr<Gdk::Something> to GdkSomething*
+define(`__CONVERT_REFPTR_TO_P',`Glib::unwrap($`'3)')
+
+# e.g. Glib::RefPtr<const Gdk::Something> to GdkSomething*
+#define(`__CONVERT_CONST_REFPTR_TO_P',`const_cast<$`'2>($`'3->gobj())')
+define(`__CONVERT_CONST_REFPTR_TO_P',`const_cast<$`'2>(Glib::unwrap($`'3))')
+
+# The Sun Forte compiler doesn't seem to be able to handle these, so we are using the altlernative, __CONVERT_CONST_REFPTR_TO_P_SUN.
+# The Sun compiler gives this error, for instance:
+#  "widget.cc", line 4463: Error: Overloading ambiguity between "Glib::unwrap<Gdk::Window>(const Glib::RefPtr<const Gdk::Window>&)" and
+# "Glib::unwrap<const Gdk::Window>(const Glib::RefPtr<const Gdk::Window>&)".
+#
+define(`__CONVERT_CONST_REFPTR_TO_P_SUN',`const_cast<$`'2>(Glib::unwrap<$1>($`'3))')
+
+
+include(convert_gtk.m4)
+include(convert_pango.m4)
+include(convert_gdk.m4)
+include(convert_atk.m4)
+include(convert_glib.m4)
+
diff --git a/src/clients/gtkpaludis/vtemm/defs/Makefile.am b/src/clients/gtkpaludis/vtemm/defs/Makefile.am
new file mode 100644
index 0000000..958e132
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/defs/Makefile.am
@@ -0,0 +1,51 @@
+vte_defs_included = \
+ vte_methods.defs \
+ vte_vfuncs.defs \
+ vte_enums.defs \
+ vte_signals.defs
+
+vte_defs = \
+ $(vte_defs_included) \
+ vte.defs
+
+noinst_DATA = $(vte_defs)
+noinst_PROGRAMS = force_automake_to_include_cxxcompile
+
+INCLUDES = $(gtkmm_CFLAGS) $(vte_CFLAGS)
+
+force_automake_to_include_cxxcompile_SOURCES = force_automake_to_include_cxxcompile.cc
+
+force_automake_to_include_cxxcompile.cc :
+ echo 'int main(int, char *[]) { }' > $@
+
+generate_defs_vte : generate_defs_vte.cc
+ $(CXXCOMPILE) $(gtkmm_LIBS) $(vte_LIBS) -lglibmm_generate_extra_defs-2.4 -o $@ $<
+
+CLEANFILES = *~ force_automake_to_include_cxxcompile.cc generate_defs_vte
+MAINTAINERCLEANFILES = Makefile.in $(vte_defs)
+
+vte_methods.defs :
+ if ! python `pkg-config --variable=datadir pygtk-2.0`/pygtk/2.0/codegen/h2def.py \
+ `pkg-config --variable=includedir vte`/vte/*.h \
+ > $@ ; then rm $@ ; false ; fi
+
+vte_enums.defs :
+ if ! perl $(srcdir)/enum.pl `pkg-config --variable=includedir vte`/vte/*.h > $@ ; \
+ then rm $@ ; false ; fi
+
+vte_signals.defs : generate_defs_vte
+ ./generate_defs_vte | sed -e 's~const-gchar\*~gchar*~' > $@
+
+vte.defs :
+ echo > $@
+ for a in $(vte_defs_included) ; do echo "(include $${a})" >> $@ ; done
+
+vte_vfuncs.defs :
+ touch $@
+
+EXTRA_DIST = enum.pl generate_defs_vte.cc
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+
diff --git a/src/clients/gtkpaludis/vtemm/defs/enum.pl b/src/clients/gtkpaludis/vtemm/defs/enum.pl
new file mode 100644
index 0000000..df41545
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/defs/enum.pl
@@ -0,0 +1,230 @@
+#! /usr/bin/perl
+
+# The lisp definitions for flags does not include order.
+# thus we must extract it ourselves.
+# Usage: ./enum.pl /gnome/head/cvs/gconf/gconf/*.h > gconf_enums.defs
+
+
+my %token;
+$module="none";
+
+while ($ARGV[0] =~ /^--(\S+)/)
+{
+ shift @ARGV;
+ $module=shift @ARGV if ($1 eq "module");
+ if ($1 eq "help")
+ {
+ print "enum.pl [--module modname] header_files ....\n";
+ exit 0;
+ }
+}
+
+foreach $file (@ARGV)
+{
+ &parse($file);
+}
+
+exit;
+
+
+
+# parse enums from C
+sub parse
+{
+ my ($file)=@_;
+
+ $from=0;
+ open(FILE,$file);
+
+ $enum=0;
+ $deprecated=0;
+ $comment=0;
+
+ while(<FILE>)
+ {
+ if($comment)
+ {
+ # end of multiline comment
+ $comment = 0 if(/\*\//);
+ next;
+ }
+
+ $deprecated = 1 if(s/^#ifndef [A-Z_]+_DISABLE_DEPRECATED//);
+
+ ++$deprecated if($deprecated > 0 && /^#\s*if/);
+ --$deprecated if($deprecated > 0 && /^#\s*endif/);
+
+ next if($deprecated > 0);
+
+ # filter single-line comments
+ s/\/\*.*\*\///g;
+
+ # begin of multiline comment
+ if(/\/\*/)
+ {
+ $comment = 1;
+ next;
+ }
+
+ s/','/\%\%COMMA\%\%/;
+ s/'}'/\%\%RBRACE\%\%/;
+ if (/^typedef enum/ )
+ {
+ print ";; From $file\n\n" if (!$from);
+ $from=1;
+ $enum=1;
+ next;
+ }
+
+ if ($enum && /\}/)
+ {
+ $enum=0;
+ &process($line,$_);
+ $line="";
+ }
+ $line.=$_ if ($enum);
+ }
+}
+
+
+# convert enums to lisp
+sub process
+{
+ my ($line,$def)=@_;
+
+ $def=~s/\s*\}\s*//g;
+ $def=~s/\s*;\s*$//;
+ my $c_name=$def;
+
+ $line=~s/\s+/ /g;
+ $line=~s/\/\*.*\*\///g;
+ $line=~s/\s*{\s*//;
+
+ my $entity = "enum";
+ $c_name =~ /^([A-Z][a-z]*)/;
+ $module = $1;
+ $def =~ s/$module//;
+
+ @c_name=();
+ @name=();
+ @number=();
+
+ $val=0;
+ foreach $i (split(/,/,$line))
+ {
+ $i=~s/^\s+//;
+ $i=~s/\s+$//;
+ if ($i =~ /^\S+$/)
+ {
+ push(@c_name,$i);
+ push(@number,sprintf("%d",$val));
+ $token{$i}=$val;
+ }
+ elsif ($i =~ /^(\S+)\s*=\s*(0x[0-9a-fA-F]+)$/ ||
+ $i =~ /^(\S+)\s*=\s*(-?[0-9]+)$/ ||
+ $i =~ /^(\S+)\s*=\s*(1\s*<<\s*[0-9]+)$/
+ )
+ {
+ my ($tmp1, $tmp2) = ($1, $2);
+ push(@c_name, $tmp1);
+ eval("\$val = $tmp2;");
+ $entity = "flags" if($tmp2 =~ /^1\s*<</ || $tmp2 =~ /^0x/);
+ push(@number, $tmp2);
+ $token{$tmp1} = $tmp2;
+ }
+ elsif ($i =~ /^(\S+)\s*=\s*([ _x0-9a-fA-Z|()~]+)$/)
+ {
+ my ($tmp1, $tmp2) = ($1, $2);
+ push(@c_name, $tmp1);
+ $tmp2 =~ s/([A-Z_]+)/($token{$1})/;
+ eval("\$val = $tmp2;");
+ $val = "#error" if(!$val);
+ $val = sprintf("0x%X", $val) if($entity eq "flags");
+ push(@number, $val);
+ $token{$tmp1} = $val;
+ }
+ elsif ($i =~ /^(\S+)\s*=\s*'(.)'$/)
+ {
+ push(@c_name,$1);
+ push(@number,"\'$2\'");
+ $val=ord($2);
+ $token{$1}=$val;
+ }
+ elsif ($i =~ /^(\S+)\s*=\s*(\%\%[A-Z]+\%\%)$/)
+ {
+ $tmp=$1;
+ $_=$2;
+ s/\%\%COMMA\%\%/,/;
+ s/\%\%RBRACE\%\%/]/;
+ push(@c_name,$tmp);
+ push(@number,"\'$_\'");
+ $val=ord($_);
+ $token{$tmp}=$val;
+ }
+ else
+ {
+ #print STDERR "$i\n";
+ }
+ $val++;
+ }
+
+ # remove the prefix to form names
+ &form_names(\@name,\@c_name);
+
+ my $format = "%d";
+ $format = "0x%X" if($entity eq "flags");
+
+ # evaluate any unevaluated values
+ my $j;
+ for ($j=0;$j<$#number+1;$j++)
+ {
+ if ($number[$j]=~/\$/)
+ {
+ $number[$j]=sprintf($format, eval($number[$j]));
+ }
+ }
+
+ #print ";; Enum $def\n\n";
+ print "(define-$entity-extended $def\n";
+ print " (in-module \"$module\")\n";
+ print " (c-name \"$c_name\")\n";
+
+ print " (values\n";
+ for ($j=0;$j<$#c_name+1;$j++)
+ {
+ print " \'(\"$name[$j]\" \"$c_name[$j]\"";
+ print " \"$number[$j]\"" if ($number[$j] ne "");
+ print ")\n";
+ }
+ print " )\n";
+ print ")\n\n";
+}
+
+
+sub form_names
+{
+ my ($name,$c_name)=@_;
+
+ my $len=length($$c_name[0]) - 1;
+ my $j;
+ for ($j=0;$j<$#c_name;$j++)
+ {
+ while (substr($$c_name[$j],$len-1,1) ne "_" ||
+ substr($$c_name[$j],0,$len) ne substr($$c_name[$j+1],0,$len))
+ {
+ $len--;
+ }
+ #print substr($$c_name[$j],0,$len),"\n";
+ }
+
+ my $prefix=substr($$c_name[0],0,$len);
+
+ for ($j=0;$j<$#c_name+1;$j++)
+ {
+ $_=$$c_name[$j];
+ s/^$prefix//;
+ tr/A-Z_/a-z-/;
+ push(@$name,$_);
+ }
+
+}
diff --git a/src/clients/gtkpaludis/vtemm/defs/generate_defs_vte.cc b/src/clients/gtkpaludis/vtemm/defs/generate_defs_vte.cc
new file mode 100644
index 0000000..20c9b5c
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/defs/generate_defs_vte.cc
@@ -0,0 +1,36 @@
+/* $Id: generate_defs_gtk.cc,v 1.22 2006/05/16 18:03:21 murrayc Exp $ */
+
+/* generate_defs_gtk.cc
+ *
+ * Copyright (C) 2001 The Free Software Foundation
+ *
+ * This library 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 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "glibmm_generate_extra_defs/generate_extra_defs.h"
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <vte/vte.h>
+#include <vte/reaper.h>
+
+int main (int argc, char *argv[])
+{
+ gtk_init(&argc, &argv);
+
+std::cout << get_defs(VTE_TYPE_TERMINAL)
+ << get_defs(VTE_TYPE_REAPER);
+
+ return 0;
+}
diff --git a/src/clients/gtkpaludis/vtemm/reaper.ccg b/src/clients/gtkpaludis/vtemm/reaper.ccg
new file mode 100644
index 0000000..e2f1164
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/reaper.ccg
@@ -0,0 +1,65 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Piotr Rak <piotr.rak@gmail.com>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <vte/reaper.h>
+#include <paludis/util/exception.hh>
+
+namespace
+{
+
+ void Reaper_proxy_signal_child_exited(GObject*, int pid, int status, gpointer data)
+ {
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
+ if (Vte::Reaper::get_instance() == data) //ignore signals connected using c api
+ Vte::Reaper::get_instance()->signal_child_exited().emit(pid, status);
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
+ }
+} /* anonymous namspace */
+
+namespace Vte
+{
+
+ Reaper::Reaper() :
+ Glib::Object(reinterpret_cast<GObject*>(::vte_reaper_get()))
+ {
+ //TODO: looks like vte-0.13.3 has child-exited renamed abi/api breakage??
+ //propably shoud be also unregistred if Reaper will stop be singleton
+ g_signal_connect(G_OBJECT(gobj()), "child-exited", G_CALLBACK(Reaper_proxy_signal_child_exited) , this);
+ }
+
+ int Reaper::add_child(GPid pid)
+ {
+ return vte_reaper_add_child(pid);
+ }
+
+ sigc::signal<void, int, int>& Reaper::signal_child_exited()
+ {
+ return _signal_child_exited;
+ }
+}
+
diff --git a/src/clients/gtkpaludis/vtemm/reaper.hg b/src/clients/gtkpaludis/vtemm/reaper.hg
new file mode 100644
index 0000000..db7b146
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/reaper.hg
@@ -0,0 +1,50 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Piotr Rak <piotr.rak@gmail.com>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sys/types.h>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <glibmm/object.h>
+#include <sigc++/sigc++.h>
+
+_DEFS(vtemm,vte)
+_PINCLUDE(glibmm/private/object_p.h)
+
+namespace Vte
+{
+ class Reaper :
+ public Glib::Object,
+ public paludis::InstantiationPolicy<Reaper, paludis::instantiation_method::SingletonTag>
+
+ {
+ friend class paludis::InstantiationPolicy<Reaper, paludis::instantiation_method::SingletonTag>;
+
+ sigc::signal<void, int, int> _signal_child_exited;
+
+ _CLASS_GOBJECT(Reaper,VteReaper,VTE_REAPER,Glib::Object,GObject)
+
+ Reaper();
+
+ public:
+
+ int add_child(GPid pid);
+ sigc::signal<void, int, int>& signal_child_exited();
+
+ };
+}
diff --git a/src/clients/gtkpaludis/vtemm/terminal_widget.ccg b/src/clients/gtkpaludis/vtemm/terminal_widget.ccg
new file mode 100644
index 0000000..74ff4a9
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/terminal_widget.ccg
@@ -0,0 +1,159 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Piotr Rak <piotr.rak@gmail.com>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <vte/vte.h>
+
+namespace
+{
+
+gboolean proxy_slot_selected_callback(VteTerminal * /* term */ , glong column, glong row, gpointer data)
+{
+ typedef Vte::Terminal::SlotIsSelected SlotType;
+ SlotType& slot(*static_cast<SlotType*>(data));
+
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
+ return slot(column, row);
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
+
+ return 0;
+}
+
+} /* anonymous namespace */
+
+
+namespace Vte
+{
+
+CharAttributes::CharAttributes(VteCharAttributes* obj) :
+ _gobject(new VteCharAttributes(*obj))
+{
+}
+
+CharAttributes::~CharAttributes()
+{
+ delete _gobject;
+}
+
+CharAttributes::CharAttributes(const CharAttributes& rhs) :
+ _gobject(new VteCharAttributes(*rhs._gobject))
+{
+}
+
+CharAttributes& CharAttributes::operator= (const CharAttributes& rhs)
+{
+ if (this != &rhs)
+ {
+ delete _gobject;
+ _gobject = new VteCharAttributes(*rhs._gobject);
+ }
+ return *this;
+}
+
+int CharAttributes::row() const
+{
+ return _gobject->row;
+}
+
+int CharAttributes::column() const
+{
+ return _gobject->column;
+}
+
+Gdk::Color CharAttributes::foreground() const
+{
+ return Gdk::Color(&_gobject->fore, true);
+}
+
+Gdk::Color CharAttributes::background() const
+{
+ return Gdk::Color(&_gobject->back, true);
+}
+
+bool CharAttributes::underline() const
+{
+ return _gobject->underline;
+}
+
+bool CharAttributes::strikethrough() const
+{
+ return _gobject->strikethrough;
+}
+
+char* Terminal::get_text(const Terminal::SlotIsSelected& slot, std::vector<CharAttributes>& attributes)
+{
+ GArray* garray(g_array_new(false, true, sizeof(VteCharAttributes)));
+ Terminal::SlotIsSelected slot_copy(slot);
+
+ char * result(vte_terminal_get_text(gobj(), &proxy_slot_selected_callback, &slot_copy, garray));
+
+ for (size_t i=0; i< garray->len; ++i)
+ {
+ attributes.push_back(new VteCharAttributes(g_array_index(garray, VteCharAttributes, i))); //TODO suboptimal deep copy
+ }
+
+ g_array_free(garray, false);
+
+ return result;
+}
+
+char* Terminal::get_text_include_trailing_spaces(const Terminal::SlotIsSelected& slot, std::vector<CharAttributes>& attributes)
+{
+ GArray* garray(g_array_new(false, true, sizeof(VteCharAttributes)));
+ Terminal::SlotIsSelected slot_copy(slot);
+
+ char * result(vte_terminal_get_text_include_trailing_spaces(gobj(),
+ &proxy_slot_selected_callback, &slot_copy, garray));
+
+ for (size_t i=0; i< garray->len; ++i)
+ {
+ attributes.push_back(new VteCharAttributes(g_array_index(garray, VteCharAttributes, i))); //TODO suboptimal deep copy
+ }
+
+ g_array_free(garray, true);
+
+ return result;
+}
+
+char* Terminal::get_text_range(long start_row, long start_col, long end_row, long end_col, const SlotIsSelected& slot, std::vector<CharAttributes>& attributes)
+{
+ GArray* garray(g_array_new(false, true, sizeof(VteCharAttributes)));
+ Terminal::SlotIsSelected slot_copy(slot);
+
+ char * result(vte_terminal_get_text_range(gobj(),start_row, start_col, end_row, end_col,
+ &proxy_slot_selected_callback, &slot_copy, garray));
+
+ for (size_t i=0; i< garray->len; ++i)
+ {
+ attributes.push_back(new VteCharAttributes(g_array_index(garray, VteCharAttributes, i))); //TODO suboptimal deep copy
+ }
+
+ g_array_free(garray, true);
+
+ return result;
+}
+
+} /* namespace Vte */
diff --git a/src/clients/gtkpaludis/vtemm/terminal_widget.hg b/src/clients/gtkpaludis/vtemm/terminal_widget.hg
new file mode 100644
index 0000000..956a293
--- /dev/null
+++ b/src/clients/gtkpaludis/vtemm/terminal_widget.hg
@@ -0,0 +1,181 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Piotr Rak <piotr.rak@gmail.com>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <gtkmm/widget.h>
+#include <gtkmm/menushell.h>
+#include <gtkmm/adjustment.h>
+#include <gdkmm/cursor.h>
+#include <pangomm/fontdescription.h>
+
+#include <vector>
+
+_DEFS(vtemm,vte)
+_PINCLUDE(gtkmm/private/widget_p.h)
+
+/* we don't want whole vte.h in this file */
+typedef struct _VteCharAttributes VteCharAttributes;
+
+namespace Vte
+{
+
+
+class CharAttributes
+{
+private:
+ VteCharAttributes * _gobject;
+
+public:
+ CharAttributes(VteCharAttributes *obj);
+ CharAttributes(const CharAttributes&);
+
+ ~CharAttributes();
+
+ CharAttributes& operator= (const CharAttributes&);
+
+ int row() const;
+ int column() const;
+ Gdk::Color foreground() const;
+ Gdk::Color background() const;
+ bool underline() const;
+ bool strikethrough() const;
+};
+
+_WRAP_ENUM(TerminalEraseBinding, VteTerminalEraseBinding)
+_WRAP_ENUM(TerminalAntiAlias, VteTerminalAntiAlias)
+
+class Terminal :
+ public Gtk::Widget
+{
+
+_CLASS_GTKOBJECT(Terminal,VteTerminal,VTE_TERMINAL,Gtk::Widget,GtkWidget)
+public:
+
+typedef sigc::slot<bool, long, long> SlotIsSelected;
+
+_CTOR_DEFAULT
+
+_WRAP_METHOD(void im_append_menuitems(const Gtk::MenuShell& menushell), vte_terminal_im_append_menuitems)
+_WRAP_METHOD(pid_t fork_command(const char* command, char** argv, char** envv, const char* directory, bool lastlog, bool utmp, bool wtmp), vte_terminal_fork_command)
+_WRAP_METHOD(pid_t forkpty(char** env, const char* directory, bool lastlog, bool utmp, bool wtmp), vte_terminal_forkpty)
+_WRAP_METHOD(void set_pty(int pty_master), vte_terminal_set_pty)
+_WRAP_METHOD(void feed(const char* data, glong length), vte_terminal_feed)
+_WRAP_METHOD(void feed_child(const char* text, glong length), vte_terminal_feed_child)
+_WRAP_METHOD(void feed_child_binary(const char* data, glong length), vte_terminal_feed_child_binary)
+_WRAP_METHOD(void copy_clipboard(), vte_terminal_copy_clipboard)
+_WRAP_METHOD(void paste_clipboard(), vte_terminal_paste_clipboard)
+_WRAP_METHOD(void copy_primary(), vte_terminal_copy_primary)
+_WRAP_METHOD(void paste_primary(), vte_terminal_paste_primary)
+_WRAP_METHOD(void set_size(glong columns, glong rows), vte_terminal_set_size)
+_WRAP_METHOD(void set_audible_bell(bool is_audible), vte_terminal_set_audible_bell)
+_WRAP_METHOD(bool get_audible_bell(), vte_terminal_get_audible_bell)
+_WRAP_METHOD(void set_visible_bell(bool is_visible), vte_terminal_set_visible_bell)
+_WRAP_METHOD(bool get_visible_bell(), vte_terminal_get_visible_bell)
+_WRAP_METHOD(void set_allow_bold(bool allow_bold), vte_terminal_set_allow_bold)
+_WRAP_METHOD(bool get_allow_bold(), vte_terminal_get_allow_bold)
+_WRAP_METHOD(void set_scroll_on_output(bool scroll), vte_terminal_set_scroll_on_output)
+_WRAP_METHOD(void set_scroll_on_keystroke(bool scroll), vte_terminal_set_scroll_on_keystroke)
+_WRAP_METHOD(void set_color_bold(const Gdk::Color& bold), vte_terminal_set_color_bold )
+_WRAP_METHOD(void set_color_foreground(const Gdk::Color& foreground), vte_terminal_set_color_foreground)
+_WRAP_METHOD(void set_color_background(const Gdk::Color& background), vte_terminal_set_color_background)
+_WRAP_METHOD(void set_color_dim(const Gdk::Color& dim), vte_terminal_set_color_dim)
+_WRAP_METHOD(void set_color_cursor(const Gdk::Color& cursor), vte_terminal_set_color_cursor)
+_WRAP_METHOD(void set_color_highlight(const Gdk::Color& highlight), vte_terminal_set_color_highlight)
+_WRAP_METHOD(void set_colors(const Gdk::Color& foreground, const Gdk::Color& background, const Gdk::Color& palete_size, glong palette_size), vte_terminal_set_colors)
+_WRAP_METHOD(void set_default_colors(), vte_terminal_set_default_colors)
+_WRAP_METHOD(void set_background_image(Glib::RefPtr<Gdk::Pixbuf> pixbuf), vte_terminal_set_background_image)
+_WRAP_METHOD(void set_background_image_file(const char* path), vte_terminal_set_background_image_file)
+_WRAP_METHOD(void set_background_saturation(double saturation), vte_terminal_set_background_saturation)
+_WRAP_METHOD(void set_background_transparent(bool transparent), vte_terminal_set_background_transparent)
+_WRAP_METHOD(void set_background_tint_color(const Gdk::Color& color), vte_terminal_set_background_tint_color)
+_WRAP_METHOD(void set_scroll_background(bool scroll), vte_terminal_set_scroll_background)
+_WRAP_METHOD(void set_cursor_blinks(bool blink), vte_terminal_set_cursor_blinks)
+_WRAP_METHOD(void set_scrollback_lines(long lines), vte_terminal_set_scrollback_lines)
+_WRAP_METHOD(void set_font(const Pango::FontDescription& font_desc), vte_terminal_set_font)
+_WRAP_METHOD(void set_font_from_string(const char* name), vte_terminal_set_font_from_string)
+_WRAP_METHOD(void set_font_from_string_full(const char* name, TerminalAntiAlias antialas), vte_terminal_set_font_from_string_full)
+_WRAP_METHOD(void set_font_full(const Pango::FontDescription& font_desc, TerminalAntiAlias antialas), vte_terminal_set_font_full)
+_WRAP_METHOD(const Pango::FontDescription get_font(), vte_terminal_get_font)
+_WRAP_METHOD(bool get_using_xft(), vte_terminal_get_using_xft)
+_WRAP_METHOD(bool get_has_selection(), vte_terminal_get_has_selection)
+_WRAP_METHOD(void set_word_chars(const char* spec), vte_terminal_set_word_chars)
+_WRAP_METHOD(bool is_word_char(gunichar), vte_terminal_is_word_char)
+_WRAP_METHOD(void set_backspace_binding(TerminalEraseBinding binding), vte_terminal_set_backspace_binding)
+_WRAP_METHOD(void set_delete_binding(TerminalEraseBinding binding), vte_terminal_set_delete_binding)
+_WRAP_METHOD(void set_mouse_autohide(bool setting), vte_terminal_set_mouse_autohide)
+_WRAP_METHOD(bool get_mouse_autohide(), vte_terminal_get_mouse_autohide)
+_WRAP_METHOD(void reset(bool full, bool clear_history), vte_terminal_reset)
+//_WRAP_METHOD(char* get_text(bool (*is_selected) (glong column,glong row,gpointer data), gpointer data, GArray *attributes), vte_terminal_get_text) //Manualy wrapped below
+//_WRAP_METHOD(char* get_text_range(glong start_row, glong start_col, glong end_row, glong end_col, gboolean (*is_selected) (glong column,glong row,gpointer data), gpointer data, GArray *attributes), vte_terminal_get_text_range) //Manualy wrapped bellow
+_WRAP_METHOD(void get_cursor_position(long& column, long& row), vte_terminal_get_cursor_position)
+_WRAP_METHOD(void match_clear_all(), vte_terminal_match_clear_all)
+_WRAP_METHOD(int match_add(const char* match), vte_terminal_match_add)
+_WRAP_METHOD(void match_remove(int tag), vte_terminal_match_remove)
+_WRAP_METHOD(char* match_check(glong column, glong row, int& tag), vte_terminal_match_check)
+_WRAP_METHOD(void match_set_cursor(int tag, Gdk::Cursor& ), vte_terminal_match_set_cursor)
+_WRAP_METHOD(void match_set_cursor_type(int tag, Gdk::CursorType), vte_terminal_match_set_cursor_type)
+_WRAP_METHOD(void set_emulation(const char* emulation), vte_terminal_set_emulation)
+_WRAP_METHOD(const char* get_emulation(), vte_terminal_get_emulation)
+_WRAP_METHOD(const char* get_default_emulation(), vte_terminal_get_default_emulation)
+_WRAP_METHOD(void set_encoding(const char* codeset), vte_terminal_set_encoding)
+_WRAP_METHOD(const char* get_encoding(), vte_terminal_get_encoding)
+_WRAP_METHOD(const char* get_status_line(), vte_terminal_get_status_line)
+_WRAP_METHOD(void get_padding(int& xpad, int& ypad), vte_terminal_get_padding)
+_WRAP_METHOD(Gtk::Adjustment* get_adjustment(), vte_terminal_get_adjustment)
+_WRAP_METHOD(glong get_char_ascent(), vte_terminal_get_char_ascent)
+_WRAP_METHOD(glong get_char_descent(), vte_terminal_get_char_descent)
+_WRAP_METHOD(glong get_char_height(), vte_terminal_get_char_height)
+_WRAP_METHOD(glong get_char_width(), vte_terminal_get_char_width)
+_WRAP_METHOD(glong get_column_count(), vte_terminal_get_column_count)
+_WRAP_METHOD(const char* get_icon_title(), vte_terminal_get_icon_title)
+_WRAP_METHOD(glong get_row_count(), vte_terminal_get_row_count)
+_WRAP_METHOD(const char* get_window_title(), vte_terminal_get_window_title)
+
+_WRAP_SIGNAL(void char_size_changed(unsigned w, unsigned h), "char-size-changed")
+_WRAP_SIGNAL(void child_exited(), "child-exited")
+_WRAP_SIGNAL(void commit(gchar* text, unsigned length), "commit")
+_WRAP_SIGNAL(void contents_changed(), "contents-changed")
+_WRAP_SIGNAL(void cursor_moved(), "cursor-moved")
+_WRAP_SIGNAL(void decrease_font_size(), "decrease-font-size")
+_WRAP_SIGNAL(void deiconify_window(), "deiconify-window")
+_WRAP_SIGNAL(void emulation_changed(), "emulation-changed")
+_WRAP_SIGNAL(void encoding_changed(), "encoding-changed")
+_WRAP_SIGNAL(void eof(), "eof")
+_WRAP_SIGNAL(void icon_title_changed(), "icon-title-changed")
+_WRAP_SIGNAL(void iconify_window(), "iconify-window")
+_WRAP_SIGNAL(void increase_font_size(), "increase-font-size")
+_WRAP_SIGNAL(void lower_window(), "lower-window")
+_WRAP_SIGNAL(void maximize_window(), "maximize-window")
+_WRAP_SIGNAL(void move_window(unsigned x, unsigned y), "move-window")
+_WRAP_SIGNAL(void raise_window(), "raise-window")
+_WRAP_SIGNAL(void refresh_window(), "refresh-window")
+_WRAP_SIGNAL(void resize_window(unsigned w, unsigned h), "resize-window")
+_WRAP_SIGNAL(void restore_window(), "restore-window")
+_WRAP_SIGNAL(void selection_changed(), "selection-changed")
+_WRAP_SIGNAL(void status_line_changed(), "status-line-changed")
+_WRAP_SIGNAL(void text_deleted(), "text-deleted")
+_WRAP_SIGNAL(void text_inserted(), "text-inserted")
+_WRAP_SIGNAL(void text_modified(), "text-modified")
+_WRAP_SIGNAL(void text_scrolled(int arg), "text-scrolled")
+_WRAP_SIGNAL(void window_title_changed(), "window-title-changed")
+ char* get_text(const SlotIsSelected& slot, std::vector<CharAttributes>& attributes);
+ char* get_text_include_trailing_spaces(const SlotIsSelected& slot, std::vector<CharAttributes>& attributes);
+ char* get_text_range(long start_row, long start_col, long end_row, long end_col, const SlotIsSelected& slot, std::vector<CharAttributes>& attributes);
+};
+
+} /* namespace Vte */