PDA

View Full Version : Unable to catch QHeaderView signals



mule
26th January 2012, 20:08
I have a Qt Application, class name Secretary, base class QMainWindow.



int main( int argc,
char * argv [] )
{
int exitCode;

QApplication app( argc, argv );

Secretary * mainWindow = new Secretary;
mainWindow->move( 0, 0 );
mainWindow->show();

app.connect( & app, SIGNAL( lastWindowClosed() ),
& app, SLOT( quit() ) );
exitCode = app.exec();

return exitCode;
}


class Secretary : public QMainWindow
{
Q_OBJECT

public:
Secretary( QWidget * parent = 0,
Qt::WFlags flags = 0 );
~Secretary();

private:
Ui::SecretaryClass ui;
Secretary_tabMain * tabMain;

private slots:
void on_tableThings_clicked( const QModelIndex & item );
void on_tableThings_sectionClicked( int logicalIndex );
};


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

tabMain = new Secretary_tabMain( & ui, this );

#if 0 //at run time
QObject::connect( ui.tableThings, SIGNAL( sectionClicked( int ) ),
this, SLOT( on_tableThings_sectionClicked( int ) ) );
#endif //at run time
}


Secretary::~Secretary()
{
;
}


void Secretary::on_tableThings_clicked( const QModelIndex & item )
{
QMessageBox::information( 0, "tableThings", "clicked()" );
}


void Secretary::on_tableThings_sectionClicked( int logicalIndex )
{
QMessageBox::information( 0, "tableThings", "sectionClicked()" );
}


On the UI (in Secretary.ui), one of the widgets on the central widget is a QTabWidget, object name tabMain.



class Secretary_tabMain : public QObject
{
Q_OBJECT

public:
Secretary_tabMain( Ui::SecretaryClass * UI,
QObject * parent = 0 );
~Secretary_tabMain();

private:
Ui::SecretaryClass * pUI;
Secretary_tabMainThings * tabMainThings;
};


Secretary_tabMain::Secretary_tabMain( Ui::SecretaryClass * UI,
QObject * parent )
: QObject( parent ),
pUI( UI )
{
tabMainThings = new Secretary_tabMainThings( pUI, this );
}


Secretary_tabMain::~Secretary_tabMain()
{
;
}


The tab widget has several tabs, the tab of interest is a QWidget, object name tabMainThings.



class Secretary_tabMainThings : public QObject
{
Q_OBJECT

public:
Secretary_tabMainThings( Ui::SecretaryClass * UI,
QObject * parent = 0 );
~Secretary_tabMainThings();

private:
Ui::SecretaryClass * pUI;
TableViewModel0 * thingsModel;
};


Secretary_tabMainThings::Secretary_tabMainThings( Ui::SecretaryClass * UI,
QObject * parent )
: QObject( parent ),
pUI( UI )
{
thingsModel = new TableViewModel0;
thingsModel->initView( pUI->tableThings, thingsModel );
}


Secretary_tabMainThings::~Secretary_tabMainThings( )
{
;
}


The tab of interest has many widgets, the widget of interest is a QTableView, object name tableThings.

QAbstractTableModel has been subclassed to create table model TableViewModel0.



class TableViewModel0 : public QAbstractTableModel
{
Q_OBJECT

public :
TableViewModel0( QObject * parent = 0 );
~TableViewModel0();
void initView( QTableView * view,
TableViewModel0 * model );
};


TableViewModel0::TableViewModel0( QObject * parent )
: QAbstractTableModel( parent )
{
;
}


TableViewModel0::~TableViewModel0()
{
;
}


void TableViewModel0::initView( QTableView * view,
TableViewModel0 * model )
{
view->setModel( model );

view->setTabKeyNavigation( false );
view->setSortingEnabled( false );
view->setSelectionMode( QAbstractItemView::SingleSelection );
view->setSelectionBehavior( QAbstractItemView::SelectRows );

view->horizontalHeader()->setClickable( true );
view->horizontalHeader()->setResizeMode( QHeaderView::ResizeToContents );
view->horizontalHeader()->setHighlightSections( false );
view->horizontalHeader()->setSortIndicatorShown( true );

view->verticalHeader()->hide();
view->verticalHeader()->setResizeMode( QHeaderView::ResizeToContents );
}


At run time, clicking on an item in table tableThings will call slot Secretary:: on_tableThings_clicked() and display "tableThings ... clicked()".

However, AND THIS IS THE PROBLEM, clicking on a header section of table tableThings will NOT call slot Secretary:: on_tableThings_sectionClicked().

sectionClicked() is a signal from QHeaderView.

The default headers for QTableView are used; that is, no (new) widgets are set to be used for the QTableView headers.

*** NOTE ***
My first attempt, which was unsuccessful, relied on automatic connections being made by UIC. I then realized that the problem could possibly be that the specific view does not exist at compile time and, therefore, the automatic connections could not be made at compile time.

So, my second attempt was to make the connection explictly at runtime using the code within the #if in the Secretary class constructor. This, too, was unsuccessful.

I have tried many minor variations on these themes, all without success.

Insight?
Suggestions?
What do I have wrong? or don't understand?

All assistance greatly appreciated.

Thanks,
mule

norobro
27th January 2012, 02:24
sectionClicked() is a signal from QHeaderView
That's correct.

You should be getting a warning on the command line: "Object::connect: No such signal tableThings::sectionClicked(int)". Try using QTableView::horizontalHeader() (http://doc.qt.nokia.com/4.7-snapshot/qtableview.html#horizontalHeader) in your connect() statement.

wysota
28th January 2012, 03:37
My first attempt, which was unsuccessful, relied on automatic connections being made by UIC. I then realized that the problem could possibly be that the specific view does not exist at compile time and, therefore, the automatic connections could not be made at compile time.
Automatic connections are made at run time.

mule
30th January 2012, 19:30
(Sorry for the silence ... forced off the grid all weekend.)

norobro, - - -

QObject::connect( ui.tableThings, SIGNAL( sectionClicked( int ) ), this, SLOT( on_tableThings_sectionClicked( int ) ) );
does compile, because tableThings is defined at compile time because it is an actual QTableView object. It just doesn't catch the signal.

Where did you think the reference to horizontalHeader() should be? This:
QObject::connect( ui.tableThings->horizontalHeader(), SIGNAL( sectionClicked( int ) ), this, SLOT( on_tableThings_sectionClicked( int ) ) );
also compiles, but still does not catch the signal.


wysota, - - -

I understand that automatic connections are actually made at run time. My statement intended to convey my (possibly incorrect) understanding that the connection table is created at compile time, and therefore the automatic connection would not even be attempted to be made at run time.

wysota
30th January 2012, 22:02
I understand that automatic connections are actually made at run time. My statement intended to convey my (possibly incorrect) understanding that the connection table is created at compile time, and therefore the automatic connection would not even be attempted to be made at run time.

You are contradicting yourself.


Where did you think the reference to horizontalHeader() should be? This:
QObject::connect( ui.tableThings->horizontalHeader(), SIGNAL( sectionClicked( int ) ), this, SLOT( on_tableThings_sectionClicked( int ) ) );
also compiles, but still does not catch the signal.
It should have worked (provided that on_tableThings_sectionClicked is declared as a slot). Do you get any warnings about signals on the console at run time?

mule
1st February 2012, 14:28
norobro,

You were correct! Adding horizontalHeader() ...

QObject::connect( ui.tableThings->horizontalHeader(), SIGNAL( sectionClicked( int ) ), this, SLOT( on_tableThings_sectionClicked( int ) ) );
... DOES work.

When I initially tried this, I still had one of my "many minor variations" edits of the slot function name, so it couldn't connect.

Looked at it too many times - Wasn't seeing what I thought I was seeing.
Too many projects, not enough sleep.

Thank you.