PDA

View Full Version : ActiveX and QComboBox delegate



klaarx
14th August 2012, 09:27
Hi !

I'm developping an ActiveX component using a QTableWidget with QComboBox delegates.
The QTableWidget works perfectly when I use it in a QMainWindow directly but its behaviour changes once embedded in an ActiveX.
When I select a choice in one of the QComboBox, the focus is not set on the widget and the event itemChanged is not called on QTableWidget when I select an other cell of the table. When I force the focus on the QComboBox by right clicking on it, the event is called when I select an other cell.

I found a solution by connecting the signal currentIndexChanged(int) to a slot which emit the signals commitData() and closeEditor(). It solves the problem when using the mouse to select the choice but not when using the keyboard. The focus is lost whenever I press the down arrow.

I'd like to know if it is a known bug of Qt or if I missed something and if there is a good solution to solve it.
I made a simple project on VS2008 which reproduce this problem.
https://rapidshare.com/files/551753355/UITest_ActiveX.zip
The top QTableWidget is in an ActiveX and has the problem. The bottom QTableWidget is in a frame and works as I want.

Don't hesitate to test it and ask me more details.
Thanks.

Here is my source code :

main.cpp


#include "uitest_activex.h"
#include <QtGui/QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
UITest_ActiveX w;
w.show();
return a.exec();
}



uitest_activex.h


#ifndef UITEST_ACTIVEX_H
#define UITEST_ACTIVEX_H

#include <QtGui/QMainWindow>
#include "ui_uitest_activex.h"

class UITest_ActiveX : public QMainWindow
{
public:
UITest_ActiveX(QWidget *parent = 0, Qt::WFlags flags = 0);
~UITest_ActiveX();

private:
Ui::UITest_ActiveXClass ui;
};

#endif // UITEST_ACTIVEX_H


uitest_activex.cpp


#include "uitest_activex.h"
#include <QtGui/QVBoxLayout>
#include <ActiveQt/QAxWidget>

#include <QTGui/QTableWidget>
#include "..\UITest_AxComponent\comboboxdelegate.h"

UITest_ActiveX::UITest_ActiveX(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);

QFrame* inv_frame = new QFrame();
inv_frame->resize(1200, 1200);
inv_frame->setMinimumSize(QSize(800, 600));

QVBoxLayout* lnv_vertical_layout = new QVBoxLayout(inv_frame);

//TEST1 : in an ActiveX Component
QAxWidget* inv_ax_helpdesk = new QAxWidget(inv_frame) ;
inv_ax_helpdesk->setControl( "{5E3FC5ED-FBA6-47AE-B1A3-31567AF9C2F3}" ) ;
inv_ax_helpdesk->setObjectName( QString::fromUtf8( "inv_ax_helpdesk" ) ) ;
inv_ax_helpdesk->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
lnv_vertical_layout->addWidget(inv_ax_helpdesk);
//END TEST 1

//TEST2 : not in an ActiveX Component
QTableWidget* lnv_table_widget = new QTableWidget();
lnv_table_widget->setRowCount(10);
lnv_table_widget->setColumnCount(2);
lnv_vertical_layout->addWidget( lnv_table_widget );

for(int li_column = 0; li_column < 2; ++li_column)
{
for(int li_row = 0; li_row < 10; ++li_row)
{
lnv_table_widget->setItem(li_row, li_column, new QTableWidgetItem(0));
lnv_table_widget->item(li_row, li_column)->setData(Qt::DisplayRole, 1);
}
}

lnv_table_widget->setItemDelegateForColumn(0, new ComboBoxDelegate());

for(int li_index = 0; li_index < 30; ++li_index)
{
lnv_table_widget->openPersistentEditor(lnv_table_widget->item(li_index, 0));
}
//END TEST 2

this->setCentralWidget(inv_frame);
}

UITest_ActiveX::~UITest_ActiveX()
{
}


comboboxdelegate.h


#ifndef COMBOBOXDELEGATE_H
#define COMBOBOXDELEGATE_H

#include <QtGui/QStyledItemDelegate.h>
#include <QtGui/QComboBox>
#include "defines.h"

class UITEST_AXCOMPONENT_EXPORT ComboBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT

private:
QComboBox* inv_combobox;

public:
ComboBoxDelegate(QObject* anv_parent = 0);
~ComboBoxDelegate();

QWidget* createEditor(QWidget* auo_parent, const QStyleOptionViewItem& anv_option, const QModelIndex& anv_modelIndex) const;
void setEditorData(QWidget* auo_editor, const QModelIndex& anv_modelIndex) const;
void setModelData(QWidget* auo_editor, QAbstractItemModel* anv_model, const QModelIndex& anv_modelIndex) const;

private slots:
void commitAndCloseEditor();
};

#endif


ocomboboxdelegate.cpp


#include <QtGui/QtGui>

#include "comboboxdelegate.h"

ComboBoxDelegate::ComboBoxDelegate(QObject* anv_parent) :
QStyledItemDelegate(anv_parent)
{
inv_combobox = 0;
}

ComboBoxDelegate::~ComboBoxDelegate()
{
if(inv_combobox != 0)
{
delete inv_combobox;
}
}

QWidget* ComboBoxDelegate::createEditor(QWidget* anv_parent, const QStyleOptionViewItem& anv_option , const QModelIndex& anv_model_index) const
{
QComboBox* lw_new_editor = new QComboBox(anv_parent);
lw_new_editor->autoFillBackground();

lw_new_editor->addItem("Choice0", 0);
lw_new_editor->addItem("Choice1", 1);
lw_new_editor->addItem("Choice2", 2);

//QObject::connect(lw_new_editor, SIGNAL(currentIndexChanged(int)), this, SLOT(commitAndCloseEditor()) );

return lw_new_editor;
}

void ComboBoxDelegate::setEditorData(QWidget* anv_editor, const QModelIndex& anv_model_index) const
{
QComboBox* lnv_combobox = static_cast<QComboBox*>(anv_editor);
QVariant lv_data = anv_model_index.model()->data(anv_model_index, Qt::DisplayRole);

int li_index = lnv_combobox->findData(lv_data, Qt::UserRole);
lnv_combobox->setCurrentIndex(li_index);
}

void ComboBoxDelegate::setModelData(QWidget* anv_editor, QAbstractItemModel* anv_model, const QModelIndex& anv_model_index) const
{
QComboBox* lnv_combobox = static_cast<QComboBox*>(anv_editor);
int li_index = lnv_combobox->currentIndex();

//récupération des data dans la ComboBox
QVariant lnv_data = lnv_combobox->itemData(li_index, Qt::UserRole);

//recopie des data dans le modèle de données
anv_model->setData(anv_model_index, lnv_data, Qt::DisplayRole);

QModelIndex lnv_model_index = anv_model->index(anv_model_index.row(), anv_model_index.column() + 1);
anv_model->setData(lnv_model_index, lnv_data, Qt::DisplayRole);
}

void ComboBoxDelegate::commitAndCloseEditor()
{
qDebug() << "ComboBoxDelegate::commitAndCloseEditor";
QComboBox* editor = qobject_cast<QComboBox*>(sender());

emit commitData(editor);
emit closeEditor(editor);
}


uitest_axcomponent.h


#ifndef UITEST_AXCOMPONENT_H
#define UITEST_AXCOMPONENT_H

#include <QtGui/QWidget>
#include <ActiveQt/QAxBindable>

#include "ui_uitest_axcomponent.h"

class UITest_AxComponent : public QWidget, public QAxBindable
{
Q_OBJECT

public:
UITest_AxComponent(QWidget *parent = 0);

private:
Ui::UITest_AxComponentClass ui;
};

#endif // UITEST_AXCOMPONENT_H



uitest_axcomponent.cpp


#include "uitest_axcomponent.h"

#include <ActiveQt/QAxFactory>
#include <QtGui/QTableWidget>
#include <QtGui/QVBoxLayout>

#include "comboboxdelegate.h"

UITest_AxComponent::UITest_AxComponent(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);

QVBoxLayout* lnv_vertical_layout = new QVBoxLayout(this);

QTableWidget* lnv_table_widget = new QTableWidget();
lnv_table_widget->setRowCount(10);
lnv_table_widget->setColumnCount(2);
lnv_vertical_layout->addWidget( lnv_table_widget );

for(int li_column = 0; li_column < 2; ++li_column)
{
for(int li_row = 0; li_row < 10; ++li_row)
{
lnv_table_widget->setItem(li_row, li_column, new QTableWidgetItem(0));
lnv_table_widget->item(li_row, li_column)->setData(Qt::DisplayRole, 1);
}
}

lnv_table_widget->setItemDelegateForColumn(0, new ComboBoxDelegate());

for(int li_index = 0; li_index < 30; ++li_index)
{
lnv_table_widget->openPersistentEditor(lnv_table_widget->item(li_index, 0));
}
}

QAXFACTORY_DEFAULT(UITest_AxComponent,
"{5E3FC5ED-FBA6-47AE-B1A3-31567AF9C2F3}",
"{129C2AEF-95FF-41CD-933A-BB6797C15EA7}",
"{D649E3DF-8A75-4760-BE24-C95099DA12E3}",
"{95A80282-D524-472A-893B-34362AB50097}",
"{5925E413-B343-47BA-9C8A-9D63E0F06F2C}")

klaarx
16th August 2012, 09:23
nobody has an idea ?

klaarx
17th August 2012, 15:45
should I report it as a bug ?

klaarx
20th August 2012, 17:08
Please, I still need help !