PDA

View Full Version : TreeView as view for ComboBox



niko
24th January 2008, 19:44
Hello,

is this supported?


int main(int argc, char **argv)
{
QApplication app(argc,argv);
QDirModel* model = new QDirModel();
QTreeView* view = new QTreeView();
view->setModel(model);
QComboBox* combo = new QComboBox();
combo->setView(view);
combo->setModel(model);
combo->show();
app.exec();
}


If so - what do I make wrong?
(The view isn't rendered correctly - only 10px height, selecting a file doesn't work)

thanks,
niko

jpn
4th February 2008, 15:51
Here's something you can start with. ;)

niko
4th February 2008, 19:10
I'm getting the same result as before; see attached screenshot.

Does it work better for you?

(Qt version 4.3.3)

jpn
4th February 2008, 20:10
What if you change in showPopup():

setRootModelIndex(QModelIndex());
to

setRootModelIndex(static_cast<QDirModel*>(model())->index(QDir::rootPath()));
?

niko
5th February 2008, 06:56
great! that works now!!

Why did you add the eventFilter and the skipNextHide? I disabled it and it still worked for me.

thanks,
niko

jpn
5th February 2008, 07:02
Why did you add the eventFilter and the skipNextHide? I disabled it and it still worked for me.
Otherwise you can't expand/collapse branches without the popup view getting hid...

niko
5th February 2008, 07:22
aah, i see :D

many thanks!!

niko
30th March 2008, 17:57
I have to bring this topic up again, because the solution is not really working for me.
The problem is that QComboBox calculates the height of the popup by counting the root-items.
Jpn suggested using another root, so that there are more items. But in my case this doesn't work - as it can happen that there is only one item.

My modified testcase:


#include <QtGui>

class TreeComboBox : public QComboBox
{
public:
TreeComboBox(QWidget* parent = 0) : QComboBox(parent), skipNextHide(false)
{
QTreeView* v = new QTreeView(this);
setView(v);
v->header()->hide();
v->viewport()->installEventFilter(this);
}

bool eventFilter(QObject* object, QEvent* event)
{
if (event->type() == QEvent::MouseButtonPress && object == view()->viewport())
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
QModelIndex index = view()->indexAt(mouseEvent->pos());
if (!view()->visualRect(index).contains(mouseEvent->pos()))
skipNextHide = true;
}
return false;
}

virtual void showPopup()
{
setRootModelIndex(QModelIndex());
QComboBox::showPopup();
}

virtual void hidePopup()
{
setRootModelIndex(view()->currentIndex().parent());
setCurrentIndex(view()->currentIndex().row());
if (skipNextHide)
skipNextHide = false;
else
QComboBox::hidePopup();
}

private:
bool skipNextHide;
};

int main(int argc, char* argv[])
{
QApplication app(argc, argv);
TreeComboBox combo;
QStandardItemModel model;
model.appendRow(new QStandardItem("Test1"));
model.item(0)->appendRow(new QStandardItem("Test1.1"));
model.item(0)->appendRow(new QStandardItem("Test1.2"));
model.item(0)->appendRow(new QStandardItem("Test1.3"));
combo.setModel(&model);
combo.show();
app.exec();
}

jpn
31st March 2008, 07:38
I can't think of any better solution than faking the amount of top level items:


class Model : public QStandardItemModel
{
public:
int rowCount(const QModelIndex& index = QModelIndex()) const
{
int count = QStandardItemModel::rowCount(index);
return !index.isValid() ? qMax(10, count) : count; // at least 10 when top-level
}
};

This will, however, give false branches whilst expanding the tree. I guess one could get rid of them with a hackish reimplementation of QTreeView::drawBranches().

niko
5th April 2008, 20:57
That dind't help - because for those non-existing items the TreeView returned a height of 0 in the visualRect function.

My solution was to re-implement visualRect for the TreeView - and modify the height of the last top-level row.

see attached source.

However I still have a problem:
steps to reproduce (with attached application):
* open popup
* select 1.2
* open popup again
* close branch
* Test 1 gets the new root?!

oscar
21st September 2008, 17:10
Setting minimum size helped me avoiding the height problem, although it's not perfect:


comboBox->view()->setMinimumHeight(comboBox->count()*10);

Regards,
Oscar

mugabe
12th May 2009, 07:47
However I still have a problem:
steps to reproduce (with attached application):
* open popup
* select 1.2
* open popup again
* close branch
* Test 1 gets the new root?!

Does anyone know how to solve this?

removing lines
setRootModelIndex(view()->currentIndex().parent());
setCurrentIndex(view()->currentIndex().row());
will solve this problem partially.

If ComboBox is non-editable it work correct, but if it is editable bug comes back.