PDA

View Full Version : checkComboBox , how to do?



qiank128
24th August 2006, 11:43
someone can help me?

jpn
24th August 2006, 11:55
If you mean something like this (http://www.codeproject.com/combobox/checkcombo.asp), it really shouldn't bee too hard since QComboBox allows you to use your own model (and view, which you probably don't event need..). You need to make the combobox non-editable and make the model to return Qt::ItemIsUserCheckable for all indexes QAbstractItemModel::flags(). I think all you need to do by hand is the filling of the line edit of the combobox.

Edit: Oh, and about the model. In my opinion, QStandardItemModel could be a good choice to start with, as QStringListModel doesn't support storing of check states..

qiank128
24th August 2006, 12:44
Can you give me a example?

or some code

this is my code , but it doesnt work.

// CheckComboBox.h
#ifndef CHECKCOMBOBOX_H
#define CHECKCOMBOBOX_H

#include <QComboBox.h>
#include <QStandardItemModel>

class CheckModel : public QStandardItemModel
{
public:
CheckModel();

Qt::ItemFlags flags(const QModelIndex & index);

};

class CheckComboBox : public QComboBox
{
public:
CheckComboBox( QWidget * parent = 0 );

private:
};

#endif


// CheckComboBox.cpp
#include "CheckComboBox.h"

CheckModel::CheckModel() : QStandardItemModel()
{
}

Qt::ItemFlags CheckModel::flags(const QModelIndex & index)
{
return Qt::ItemIsUserCheckable;
}

CheckComboBox::CheckComboBox (QWidget * parent) : QComboBox(parent)
{
setEditable(false);
CheckModel *pModel = new CheckModel();
this->setModel(pModel);
}

jpn
24th August 2006, 13:06
At least you need to insert a single column to your model:


CheckModel::CheckModel() : QStandardItemModel()
{
insertColumn(0); // important
}


You might also want to return a bit more flags (the base class implementation returns a combination of ItemIsEnabled and ItemIsSelectable):


Qt::ItemFlags flags(const QModelIndex & index)
{
return QStandardItemModel::flags(index) | Qt::ItemIsUserCheckable;
};


Also, when adding your items, you might need to initialize the check state:


comboBox->setItemData(idx, Qt::Unchecked, Qt::CheckStateRole);

qiank128
24th August 2006, 14:33
how to capture the QComboBox popup view clicked event?


CheckComboBox::CheckComboBox (QWidget * parent) : QComboBox(parent)
{
setEditable(false);
CheckModel *pModel = new CheckModel();
this->setModel(pModel);
this->setMinimumWidth(100);

// why this signal(clicked) can not be capture?

connect((const QObject *)QComboBox::view(), SIGNAL(clicked ( const QModelIndex & )), this, SLOT(_itemCB(const QModelIndex &)));
}


void CheckComboBox::_itemCB(const QModelIndex &index)
{
QMessageBox::warning( this, "clicked", "clicked" );
}

jpn
24th August 2006, 15:27
Ahh, sorry. I didn't think of it that the view should remain visible when (un)checking items, or is that what you want?

Seems to be a bit complicated. At least much more complicated than I thought.. ;)

QComboBox installs an event filter on the view, which prevents the view from behaving normally in some situations. For example it filters all mouse release events and therefore the view never gets them and neither emits any clicked() signal..

I did a small example for you. The implementation is in a single file because I was so lazy.. :p All you have left is filling the combo's line edit correctly.

qiank128
25th August 2006, 02:42
// i have a mistake,

/*******why i can not capture the "MouseButtonRelease" event?

/*******can you?

/*******but i can use "MouseButtonPress" replace it,

/*******how to let the popup view always show , when i checked an item?

// view->installEventFilter(view); // <--- !!!
// view->viewport()->installEventFilter(view); // <--- !!!
// must behind the setView(view);
setEditable(false);
CheckModel* model = new CheckModel(this);
CheckView* view = new CheckView(this);
setModel(model);
setView(view);
// these 2 lines below are important and must be
// applied AFTER QComboBox::setView() because
// QComboBox installs it's own filter on the view
view->installEventFilter(view); // <--- !!!
view->viewport()->installEventFilter(view); // <--- !!!

qiank128
25th August 2006, 06:56
The attached file is CheckComboBox source code.

thanks jpn

eduardhc
20th July 2009, 11:37
Hi,
Just found this code by googling around a bit for a Qt combobox with check box support. I've been trying it and seems to work fine. I've just added the following override to CheckView, so now it also works properly when space bar is used to check / uncheck the items inside the dropped list:



virtual void keyPressEvent(QKeyEvent * event)
{
QListView::keyPressEvent(event);

if (event->key() == Qt::Key_Space)
{
emit clicked(currentIndex());
}
}


Just wanted to share it, in case someone finds it useful...
Anyway, thanks for the code to the original author.

Best regards,
Eduard

samofweb
26th August 2010, 03:07
Hi,
Just found this code by googling around a bit for a Qt combobox with check box support. I've been trying it and seems to work fine. I've just added the following override to CheckView, so now it also works properly when space bar is used to check / uncheck the items inside the dropped list:



virtual void keyPressEvent(QKeyEvent * event)
{
QListView::keyPressEvent(event);

if (event->key() == Qt::Key_Space)
{
emit clicked(currentIndex());
}
}


Just wanted to share it, in case someone finds it useful...
Anyway, thanks for the code to the original author.

Best regards,
Eduard

That is really good! Thanks a lot!

pat726627
10th January 2011, 23:34
;) Awesome! This is just perfect ;)

colin207
27th January 2011, 06:41
Hi

Tried this looks great BUT I find it sizes the combo incorrectly.

e.g this code which sticks a CheckComboBox in a toolbar:
CheckComboBox * px = new CheckComboBox;
px->addItem("eggs", false);
px->addItem("bananas", true);
px->addItem("a somewhat longer option", false);
pToolBar->addWidget(px);


... then when popped up the last, longest item has its text displayed as "a somewhat longer o..." even though the combo box has obviously tried to size itself to the correct width to show all the items (I know that for certain; if I stick in a much longer text item it tries to size itself to that, but is still slightly too short). My guess is that whereever the code is that sizes the conbo, it isnt taking into account the extra width needed for the checkbox.

Any ideas/solutions anyone?

Thx

pinkiP
6th July 2012, 08:43
Hi,

I like to edit the lineedit of the checkcombobox while my program is running. So I set setEditable(true). Now, the problem is that the lineedit ignores the keyEvent. I tried to define a keyEvent, but it doesn't work. Has anyone an idea?

pinkiP
21st August 2012, 08:01
I got it. So here is my code. You have to promote this to a QComboBox.



/* mycombobox.h */
#ifndef MYCOMBOBOX_H
#define MYCOMBOBOX_H

#include <QtGui>

class MyComboBox : public QComboBox
{
Q_OBJECT
public:
MyComboBox(QWidget *parent = 0) : QComboBox(parent)
{
setEditable(true);
model = new QStandardItemModel;
displayedit = "";
itemcount = model->rowCount();
updateText();
}

void showPopup()
{
temp = new QStandardItemModel;
temp = model;

/*
if the user write somthing into the edit line, the new number of rows will be greater than the old number of rows:
the new items has to be set as checkable items and every item should be only one time in the list
*/
if(itemcount <temp->rowCount())
{
for (int row = 0; row<model->rowCount(); row++) //for every item in the model set the new model
{
if(row == itemcount)
{
/*
Tests if more than one new item are added at the same time
*/
QString string = this->itemText(row);
QString pattern("; ");
QStringList datalist = string.split(pattern);

/*
if only one item was add:
set the item checked and add it to the model
*/
if (datalist.count() == 1)
{
QStandardItem *newItem = new QStandardItem;
newItem->setText(datalist.at(0));
newItem->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled);
newItem->setData(Qt::Checked,Qt::CheckStateRole);
model->setItem(row,0,newItem);
row++;
}

/*
if more than one item was written in the edit line:
test for similarity with the items in the current list
and add every new item as new single item to the model and will be checked
*/
else{
for (int size = 0; size<datalist.count(); size++ )
{
QList<QStandardItem*> list = temp->findItems(datalist.at(size)); //check for similarity
if(list.empty() == true)
{

QStandardItem *newItem = new QStandardItem;
newItem->setText(datalist.at(size));
newItem->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled);
newItem->setData(Qt::Checked,Qt::CheckStateRole);
model->setItem(row,0,newItem);
row++;
}

}
}
}

/*
in case, that only the current available items were checked
*/
else {
QStandardItem *newItem = new QStandardItem;
newItem->setText(this->itemText(row));
newItem->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled);
if(temp->item(row,0)->checkState() == Qt::Checked)
{
newItem->setData(Qt::Checked,Qt::CheckStateRole);
qDebug()<<"blubb";
}
else newItem->setData(Qt::Unchecked,Qt::CheckStateRole);
model->setItem(row,0,newItem);
}
}
}

// set the model of the combobox
this->setModel(model);

QComboBox::showPopup();

// set the current number of items
itemcount = model->rowCount();

}
void hidePopup()
{
displayedit = "";
for(int i = 0; i<model->rowCount(); i++)
{
if(model->item(i,0)->checkState() == Qt::Checked)
{
displayedit = displayedit + model->item(i,0)->text() +"; ";
}

}
QComboBox::hidePopup();
QTimer::singleShot(0, this, SLOT(updateText()));
this->setToolTip(displayedit);
}

void addItem(const QString &text/*, const QVariant &userData*/)
{
int row = model->rowCount();
item = new QStandardItem;
item->setText(text);
item->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled);
item->setData(Qt::Unchecked,Qt::CheckStateRole);
model->setItem(row,0,item);
this->setModel(model);
itemcount = model->rowCount();
}

void addItems(const QStringList &texts){

for (int i = 0; i <texts.count();i++)
{
int row = model->rowCount();
item = new QStandardItem;
item->setText(texts.at(i));
item->setFlags(Qt::ItemIsUserCheckable| Qt::ItemIsEnabled);
item->setData(Qt::Unchecked,Qt::CheckStateRole);
model->setItem(row,0,item);
this->setModel(model);
}
itemcount = model->rowCount();
}

public slots:
void updateText()
{
lineEdit()->setText(displayedit);
}

private:
QString str;
QStandardItemModel *model;
QStandardItemModel *temp;
QStandardItem *item;
QString displayedit;
QStringList list;
int itemcount;
bool check;
};

#endif // MYCOMBOBOX_H