Re: DND in TreeView



On Thu, Mar 19, 2009 at 10:46:33PM -0400, José Alburquerque wrote:
> On Fri, 2009-03-20 at 07:48 +0800, Deng Xiyue wrote: 
> > José Alburquerque <jaalburquerque cox net> writes:
> > 
> > > On Fri, 2009-03-20 at 00:17 +0800, Deng Xiyue wrote:
> > >> Sorry for the delay in preparing a testcase for being busy in the past
> > >> weeks.  The test program is based on one of the examples with callbacks
> > >> connected to the aforementioned signals, cout the deleted and inserted
> > >> rows to stdout.  By DND from and to the last row the abnormal behavior
> > >> will be observed.  As the implementation of TreeView in GTKMM, I guess
> > >> the same behavior is expected with pure GTK+ code.  But I still like to
> > >> know whether this is the way to handle DND within TreeView before filing
> > >> bug report.  Thanks.
> > >
> > > Is it a lot of C++ code?  Maybe you can post the code and it can be
> > > tested to get a sense of what's happening.
> > >
> > 
> > I have attached the code in my last post, maybe it get stripped from
> > your INBOX?  It can be seen on the mailing list archive[1] though.
> 
> Sorry.  Just began using evolution and honestly did not notice the
> attachment.
> 
> As far as I can tell, the signals are called.  I've attached your source
> with some output statements in your signal handlers so you can confirm.
> Maybe something you're trying do is not quite working the way you
> expect.  Maybe ensure that the methods you're calling do what they're
> supposed to and that your logic is right.  HTH.
> 

I've refined the testcase with output from both insert and delete signal
handlers, so that you can see that the delete signal is never called
when dragging the last row away.

Still I'd like to know whether it is the supposed way to handle DND in
TreeView.

Regards,
Deng Xiyue
#include <iostream>
#include <gtkmm.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:
  //Signal handlers:
  virtual void on_button_quit();
  virtual void on_row_deleted(Gtk::TreeModel::Path const& path);
  virtual void on_row_inserted(Gtk::TreePath const&, Gtk::TreeIter const&);

  //Tree model columns:
  class ModelColumns : public Gtk::TreeModel::ColumnRecord
  {
  public:

    ModelColumns()
    { add(m_col_id); }

    Gtk::TreeModelColumn<unsigned int> m_col_id;
  };

  ModelColumns m_Columns;

  //Child widgets:
  Gtk::VBox m_VBox;

  Gtk::ScrolledWindow m_ScrolledWindow;
  Gtk::TreeView m_TreeView;
  Glib::RefPtr<Gtk::ListStore> m_refTreeModel;

  Gtk::HButtonBox m_ButtonBox;
  Gtk::Button m_Button_Quit;

  int inserted_pos_;
};

ExampleWindow::ExampleWindow()
  : m_Button_Quit("Quit")
{
  set_title("TreeView DND bug test");
  set_border_width(5);
  set_default_size(400, 200);

  add(m_VBox);

  //Add the TreeView, inside a ScrolledWindow, with the button underneath:
  m_ScrolledWindow.add(m_TreeView);

  //Only show the scrollbars when they are necessary:
  m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);

  m_VBox.pack_start(m_ScrolledWindow);
  m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);

  m_ButtonBox.pack_start(m_Button_Quit, Gtk::PACK_SHRINK);
  m_ButtonBox.set_border_width(5);
  m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
  m_Button_Quit.signal_clicked().connect( sigc::mem_fun(*this,
                                                        &ExampleWindow::on_button_quit) );

  //Create the Tree model:
  m_refTreeModel = Gtk::ListStore::create(m_Columns);
  m_TreeView.set_model(m_refTreeModel);
  m_TreeView.set_reorderable(true);

  //Fill the TreeView's model
  Gtk::TreeModel::Row row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 1;

  row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 2;

  row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 3;

  row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 4;

  //Add the TreeView's view columns:
  //This number will be shown with the default numeric formatting.
  m_TreeView.append_column("ID", m_Columns.m_col_id);

  m_refTreeModel->signal_row_inserted().connect
    (sigc::mem_fun(*this, &ExampleWindow::on_row_inserted));
  m_refTreeModel->signal_row_deleted().connect
    (sigc::mem_fun(*this, &ExampleWindow::on_row_deleted));
  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_button_quit()
{
  hide();
}

void ExampleWindow::on_row_deleted(Gtk::TreeModel::Path const& path)
{
  Gtk::TreeModel::iterator iter_deleted =
    m_refTreeModel->get_iter(path);
  if (iter_deleted)
    {
      Gtk::TreeModel::Row row = *iter_deleted;
      int deleted_pos = row[m_Columns.m_col_id] - 1;

      if (deleted_pos < inserted_pos_)
        {
          --inserted_pos_;
        }

      if (deleted_pos != inserted_pos_)
        {
          std::cout << "Deleted row: " << deleted_pos << std::endl;
        }
    }
}

void ExampleWindow::on_row_inserted(Gtk::TreeModel::Path const& path,
                                              Gtk::TreeModel::iterator const& iter)
{
  Gtk::TreeModel::iterator iter_inserted =
    m_refTreeModel->get_iter(path);
  if (iter_inserted)
    {
      Gtk::TreeModel::Row row = *(++iter_inserted);
      inserted_pos_ = row[m_Columns.m_col_id];
      std::cout << "Inserted row: " << inserted_pos_ << std::endl;
    }
}

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  ExampleWindow window;
  //Shows the window and returns when it is closed.
  Gtk::Main::run(window);

  return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]