I have a static method which shows a list (Items) and return an array of selected object in Items. I would like to add a checkbox to reload the list along some parameters. We are using QT 3.3.
//// Static
int CMSUI_InputDialog::FittingList(QWidget* parent,
const CString& Title,
const CStringArray& Items,
bool IsMultiSelect,
int DefaultItem,
bool OkIsDefault,
CArray<int, int>& Selecteds)
{
int ret = 0;
Selecteds.RemoveAll();
/// Create grid
QDialog dialog(parent, 0, true);
dialog.setCaption(QString(Title));
QGridLayout* pLayoutGrid = Init(&dialog, OkIsDefault);
//Create checkBox
QCheckBox* pCheckBox = new QCheckBox(&dialog, "m_pApply_Filter");
pCheckBox->setText("Norm Filter");
pLayoutGrid->addWidget(pCheckBox, 0, 0);
QObject::connect(pCheckBox, SIGNAL(stateChanged(int)), &dialog, SLOT(checkboxClicked()));
/// Create ListBox
QListBox* pList = new QListBox(&dialog);
pList->setMinimumSize(QSize(370, 90));
pList->setSelectionMode(QListBox::Extended);
// Load the list
int Count = Items.GetSize();
for (int i = 0; i < Count; i++)
{
QString QS(Items[i]);
pList->insertItem(QS);
}
if (DefaultItem >= 0 && DefaultItem < Count)
pList->setSelected(DefaultItem, true);
pLayoutGrid->addWidget(pList, 1, 0);
// Connect double clic on QDialog accept
QObject::connect(pList, SIGNAL(doubleClicked(QListBoxItem*)), &dialog, SLOT(accept()));
if (dialog.exec() == QDialog::Accepted)
{
for (int i = 0; i < Count; i++)
{
if (pList->isSelected(i))
Selecteds.Add(i);
}
ret = 1;
}
return ret;
}
void CMSUI_InputDialog::checkboxClicked()
{
//To do
}
checkboxClicked() is declared in CMSUI_InputDialog.h as slot
class CMSUI_InputDialog
{
protected :
static QGridLayout* Init(QWidget* pParent, bool OkIsDefault);
public slots:
void checkboxClicked();
public:
/// CheckBox + ListBox for fittings
static int FittingList(QWidget* parent,
const CString& Title,
const CStringArray& Items,
bool IsMultiSelect,
int DefaultItem,
bool OkIsDefault,
CArray<int, int>& Selecteds);
};
I tried many things but I'm stupid with QT and didn't got any success to catch the action on the checkbox
There's little Qt-specific here as far as the primary problem goes: it's all understandable in plain C++, no need for Qt knowledge.
You're not checking the result returned by the connect
method: it returns false
when it fails. The connect
fails in your case, so there's no point in going any further than that. The slot will not be called. The reason for that: dialog
is just a QDialog
, not CMSUI_InputDialog
. You can't add any slots to an existing Qt class.
Slots must be methods in QObject
s. The class where you added the "slot" is not derived from QObject
. You'd need to create such a class (to replace the QDialog
that you're using).
slots
is a macro that is empty (expands to nothing) and thus has no effect on the compilation. It has a purpose, though: the moc
(meta object compiler) that processes the header file will notice that macro and process the subsequent methods as slots. It won't do that unless you also have the Q_OBJECT
macro within the class.
First, you'd want to factor out the options for that dialog into a FittingOptions
struct, to make the code manageable.
struct FittingOptions {
const CStringArray& items,
bool isMultiSelect,
int defaultItem,
bool okIsDefault,
};
The dialog should become a new class, where your slot would go:
class FittingList : public QDialog {
Q_OBJECT
FittingOptions opt;
CArray<int, int>* selecteds;
public:
FittingList(QWidget *parent, const FittingOptions &options) :
QDialog(parent), opt(options), selecteds(0)
{
// TODO: initialization code that creates widgets etc.
}
void setSelecteds(CArray<int, int> &selecteds)
{
this->selecteds = &selecteds;
}
// ...
public slots:
void checkboxChanged() { /* TODO */ }
};
And then, put the initialization code from the FittingList
method into the constructor. Change that method into:
int CMSUI_InputDialog::FittingList(QWidget* parent,
const CString& title,
const CStringArray& items,
bool isMultiSelect,
int defaultItem,
bool okIsDefault,
CArray<int, int>& selecteds)
{
const FittingOptions options = {
items, isMultiSelect, defaultItem, okIsDefault
};
::FittingList dialog(parent, options);
dialog.setCaption(QString(title));
dialog.setSelecteds(selecteds);
if (dialog.exec() != QDialog::Accepted) return 0;
return 1;
}
Look at other examples within your project to see how they went about such problems. This code is quite stale by today's standards, but it's a maintenance job as far as I understand, so you got to do more of the same - since I imagine you're not upgrading the Qt version.
Note: this is obviously something that concerns the original author(s) of the code, not you. You haven't written this stuff. Even in Qt 3's times this code would have been considered crusty - the seemingly pervasive use of globals/singletons is cringe-worthy. I always wonder why people who work on such presumably large scale projects won't look into the code they paid for and is available to them: Qt 3 includes full source code to Qt Designer, and that's where one might have looked for inspiration/tutoring. These days, Qt Creator is a much bigger code base than Designer (by more than an order of magnitude) and is fairly decently architected, so large-scale projects might take inspiration from there.