/*
 *  There is a problem when using TreeModelFiltered with editable columns (added
 *  using append_column_editable()): when row X in the filtered data set is 
 *  edited, the data in row X of the unfiltered data set is updated, which is
 *  usually a different row.
 *
 * To demonstrate the bug:
 * - click the 'show only rows > 5' toggle button
 * - click on the check mark in front of 6: this should result in 6 being 
 *   unchecked, but it does not
 * - click again on the toggle button
 * - instead of 6, 0 was unchecked
 *   */

#include <gtkmm.h>

class MainWindow : public Gtk::Window
{
  public:
    MainWindow();
    virtual ~MainWindow() {};

  protected:
    virtual bool on_filter_row_visible(const Gtk::TreeModel::const_iterator& iter);
    virtual void on_filter();

  private:
    class ModelColumns : public Gtk::TreeModel::ColumnRecord
    {
      public:
	ModelColumns()
	{ 
	  add(m_field1); 
	  add(m_field2); 
	};
	Gtk::TreeModelColumn<bool> m_field1;
	Gtk::TreeModelColumn<int>  m_field2;
    };

    Gtk::TreeView                  m_treeview;
    ModelColumns                   m_columns;
    Glib::RefPtr<Gtk::ListStore>   m_reftreemodel;
    Glib::RefPtr<Gtk::TreeModelFilter> m_reftreemodelfilter;
    bool m_filtered;
};

MainWindow::MainWindow() : m_filtered(false)
{
  set_title("Test");
  // add vbox
  Gtk::VBox* box = Gtk::manage(new Gtk::VBox);
  add(*box);
  // add button
  Gtk::ToggleButton* button = Gtk::manage(new Gtk::ToggleButton("show only rows > 5"));
  button->signal_toggled().connect(sigc::mem_fun(*this, &MainWindow::on_filter));
  box->pack_start(*button, Gtk::PACK_SHRINK);
  // create treeview
  m_reftreemodel = Gtk::ListStore::create(m_columns);
  m_reftreemodelfilter = Gtk::TreeModelFilter::create(m_reftreemodel);
  m_reftreemodelfilter->set_visible_func( sigc::mem_fun(*this, &MainWindow::on_filter_row_visible) );
  m_treeview.set_model(m_reftreemodelfilter);
  m_treeview.append_column_editable("Field1", m_columns.m_field1);
  m_treeview.append_column("Field2", m_columns.m_field2);
  // add treeview
  box->pack_start(m_treeview);
  // finished
  show_all_children();
  // generate example data
  for (int i = 0; i <10; i++)
  {
    Gtk::TreeModel::iterator iter = m_reftreemodel->append();
    Gtk::TreeModel::Row row = *iter;
    row[m_columns.m_field1] = true;
    row[m_columns.m_field2] = i;
  }
}

bool MainWindow::on_filter_row_visible(const Gtk::TreeModel::const_iterator& iter)
{
  if (m_filtered && iter)
    return (iter->get_value(m_columns.m_field2) > 5);
  return true;
}

void MainWindow::on_filter()
{ 
  m_filtered = !m_filtered;
  m_reftreemodelfilter->refilter();
}


// ===================== MAIN ======================
int main(int argc, char** argv)
{
  Gtk::Main kit(argc, argv);
  MainWindow window;
  Gtk::Main::run(window);
  return 0;
}

