PDA

View Full Version : how i can chagne Qtableview horizontal header text as well as remove Indexes vHeader



advseo32
15th July 2013, 18:49
Hi every one

i'm using qsqlquerymodel to get data from sqlite database and Qtableview widget to retrive data

i want to custimize ( vertical header and horizontal header in Qtableview )

vertical header ---> remove indexes numbers but vertical header still shown and place icon when the entier row is selected
horizontal header ---> change the text of caption



her what i code




// for horizontal header
ProduitModel->setHeaderData(0,Qt::Horizontal, "Id");
ProduitModel->setHeaderData(1,Qt::Horizontal, "Designation");
ProduitModel->setHeaderData(2,Qt::Horizontal, "Famille");
ProduitModel->setHeaderData(3,Qt::Horizontal, "Qte Maximum");
ProduitModel->setHeaderData(4,Qt::Horizontal, "Qte Minimum");
ProduitModel->setHeaderData(5,Qt::Horizontal, "Prix");
ProduitModel->setHeaderData(6,Qt::Horizontal, "Prix vente");
// form vertical header
ProduitView->verticalHeader()->setStyleSheet("QHeaderView::section:checked {"
" background-color: black; }"
" background-image: url(imgs/arrow.png)"
);



Her's image that explain what i mean

9291

Santosh Reddy
15th July 2013, 19:46
Write a proxy model derived from QIdentityProxyModel, and implement the QIdentityProxyModel::headerData() function and return what ever data is required in in header.

In Qt::Vertical header, return nothing for Qt::ItemDataRole and return icon for Qt::DecorationRole
In Qt::Horizontal header return the desired label in Qt::ItemDataRole

advseo32
15th July 2013, 21:22
thank's Santosh but really, i havn't any idea how to do it

can you give an example OR some hints to start coding ??

Santosh Reddy
15th July 2013, 21:55
Here is fully functional code with usage example


class HeaderModel : public QIdentityProxyModel
{
public:
explicit HeaderModel(QObject * parent = 0)
: QIdentityProxyModel(parent)
{ }

QVariant headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Horizontal)
{
if(role == Qt::DisplayRole)
switch(section)
{
case 0: return "Id"; break;
case 1: return "Designation"; break;
case 2: return "Famille"; break;
case 3: return "Qte Maximum"; break;
case 4: return "Qte Minimum"; break;
case 5: return "Prix"; break;
case 6: return "Prix vente"; break;
default:
return QString("Column %1").arg(section + 1);
break;
}
}
else if(orientation == Qt::Vertical)
{
if(role == Qt::DecorationRole)
return QIcon("imgs/arrow.png");
}

return QVariant();
}
};

//usage
{
QSqlQueryModel sqlQueryModel;
...

HeaderModel headerModel;

QTableView tableView;

headerModel.setSourceModel(&sqlQueryModel);

tableView.setModel(&headerModel);

tableView.show();
}

advseo32
16th July 2013, 07:09
Here is fully functional code with usage example


class HeaderModel : public QIdentityProxyModel
{
public:
explicit HeaderModel(QObject * parent = 0)
: QIdentityProxyModel(parent)
{ }

QVariant headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Horizontal)
{
if(role == Qt::DisplayRole)
switch(section)
{
case 0: return "Id"; break;
case 1: return "Designation"; break;
case 2: return "Famille"; break;
case 3: return "Qte Maximum"; break;
case 4: return "Qte Minimum"; break;
case 5: return "Prix"; break;
case 6: return "Prix vente"; break;
default:
return QString("Column %1").arg(section + 1);
break;
}
}
else if(orientation == Qt::Vertical)
{
if(role == Qt::DecorationRole)
return QIcon("imgs/arrow.png");
}

return QVariant();
}
};

//usage
{
QSqlQueryModel sqlQueryModel;
...

HeaderModel headerModel;

QTableView tableView;

headerModel.setSourceModel(&sqlQueryModel);

tableView.setModel(&headerModel);

tableView.show();
}

Wow Reddy,
Your code Work perfectly, but i have Qt 4.7 witch mean that QIdentityProxyModel is not supported. So, i have used QSortFilterProxyModel
the horziontal header changed with my text , and vertical header to arrow instead of numbers
i need the vertical header show arrow.png only when the user select the row , what's the Role that allow me to do this ?

Santosh Reddy
16th July 2013, 07:40
Oops... Sorry I din't see that you using Qt4, anyway you have figured out a way.

For icon use Qt::DecorationRole

advseo32
16th July 2013, 07:57
Oops... Sorry I din't see that you using Qt4, anyway you have figured out a way.

For icon use Qt::DecorationRole

Sorry, i don't noticed that i'm using Qt 4.7

any way Qt::DecorationRole get all vertical index filled by arrow.png icon , i want the icon only shown when the user select the entier row

Santosh Reddy
16th July 2013, 09:53
Looks like it is not supported to change the icon/image on the header only when the row/column is selected. Only thing that works is backgroud color using stylesheets

tableView.setStyleSheet("QHeaderView::section:checked { background-color: red; }");

advseo32
16th July 2013, 11:25
Maybe , but i have an application use this action


9299

Santosh Reddy
16th July 2013, 12:46
Ok I can think of a way to do this. We can create and install a custom QHeaderView on QTableView's verticalheader. Here a revised solution.



// Handles Horizontal header
class HeaderModel : public QSortFilterProxyModel
{
Q_OBJECT

public:
explicit HeaderModel(QObject * parent = 0)
: QSortFilterProxyModel(parent)
{ }

QVariant headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Horizontal)
{
if(role == Qt::DisplayRole)
switch(section)
{
case 0: return "Id"; break;
case 1: return "Designation"; break;
case 2: return "Famille"; break;
case 3: return "Qte Maximum"; break;
case 4: return "Qte Minimum"; break;
case 5: return "Prix"; break;
case 6: return "Prix vente"; break;
default:
return QString("Column %1").arg(section + 1);
break;
}
}

return QVariant();
}
};

// Handles Vertical header
class Header : public QHeaderView
{
public:
explicit Header(QWidget * parent)
: QHeaderView(Qt::Vertical, parent)
, mSelectedIndex(-1)
{
setMinimumWidth(QImage("imgs/arrow.png").width());
}

protected:
void mousePressEvent(QMouseEvent * event)
{
QHeaderView::mousePressEvent(event);

int section = logicalIndexAt(event->pos());

if(mSelectedIndex != section)
{
emit sectionClicked(section);
emit sectionPressed(section);
emit sectionEntered(section);

mSelectedIndex = section;
update();
}
}

void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
if(mSelectedIndex > -1)
{
if(mSelectedIndex == logicalIndex)
if(!isSectionHidden(logicalIndex))
painter->drawImage(rect, QImage("imgs/arrow.png"));
}
painter->restore();
}

private:
int mSelectedIndex;
};

//Usage
QSqlQueryModel model;

QTableView tableView;

HeaderModel headerModel;
headerModel.setSourceModel(&model); //<<<< Horizontal Header

tableView.setVerticalHeader(new Header(&tableView)); //<<<< Vertial Header
tableView.setModel(&headerModel);
tableView.show();

advseo32
16th July 2013, 17:55
thank's it's nearly what i need ,
how i can handle when the user use up and down keyboard keys

with keyPressEvent ???

advseo32
17th July 2013, 13:10
how i can handle this , only one the user use Key_Up and Key_Down

advseo32
18th July 2013, 08:41
what should i learn to be able to custimise Qtableview completly

rockdemon
18th July 2013, 09:41
try this book http://www.amazon.com/Programming-Edition-Prentice-Software-Development/dp/0132354160

advseo32
18th July 2013, 11:48
try this book http://www.amazon.com/Programming-Edition-Prentice-Software-Development/dp/0132354160

thanks, this is a great book

Added after 12 minutes:

any body can help me ??

rockdemon
18th July 2013, 11:59
something like? http://qt.developpez.com/doc/4.7/modelview/

They're not all great - but there are some examples on t'internet if you google :)

The book above does have the best walkthrough i've found for model view in Qt.

advseo32
18th July 2013, 19:36
something like? http://qt.developpez.com/doc/4.7/modelview/

They're not all great - but there are some examples on t'internet if you google :)

The book above does have the best walkthrough i've found for model view in Qt.
thanks i will read page by page

Added after 13 minutes:

Her is detailled description for my problem

i use Qsqlquerymodel with sqlite3 DBMS

to retrieve data from database i use two Qtableview widgets

i want to the user to be able to work like so:

the user uses only keyboard(no mouse )

when the data grabed from database and showed in the Qtableview via Qsqlquerymodel the first row in the table must be selected by default

the user uses arrow keys ( key_Down and Key_Up) to move between rows with "arrow.png" icon shown in verticalheader of Qtableview

when the user clics Entrer_Key, the row selected will be appened in the second Qtableview


plz help me , i have read model/view many times , and i figured out what really mean , but i still have a porbleme with customizing mytable view to work with


Qkeymouse events, currentrowchanged signal

advseo32
19th July 2013, 17:30
no body can help me ??

advseo32
21st July 2013, 07:46
plz help me, i need the soulution

Santosh Reddy
3rd August 2013, 12:01
Here you go, keyboard only operation



// Handles Horizontal header
class HeaderModel : public QSortFilterProxyModel
{
Q_OBJECT

public:
explicit HeaderModel(QObject * parent = 0)
: QSortFilterProxyModel(parent)
{ }

QVariant headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Horizontal)
{
if(role == Qt::DisplayRole)
switch(section)
{
case 0: return "Id"; break;
case 1: return "Designation"; break;
case 2: return "Famille"; break;
case 3: return "Qte Maximum"; break;
case 4: return "Qte Minimum"; break;
case 5: return "Prix"; break;
case 6: return "Prix vente"; break;
default:
return QString("Column %1").arg(section + 1);
break;
}
}

return QVariant();
}
};

// Handles Vertical header
class Header : public QHeaderView
{
Q_OBJECT
public:
explicit Header(QWidget * parent)
: QHeaderView(Qt::Vertical, parent)
, mSelectedIndex(-1)
{
setMinimumWidth(QImage("imgs/arrow.png").width());
}

public slots:
void changeCurrent(const QModelIndex & current, const QModelIndex & previous)
{
int section = current.row();

if(mSelectedIndex != section)
{
mSelectedIndex = section;
viewport()->update();
}
}

protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
if(mSelectedIndex > -1)
{
if(mSelectedIndex == logicalIndex)
if(!isSectionHidden(logicalIndex))
painter->drawImage(rect, QImage("imgs/arrow.png"));
}
painter->restore();
}

private:
int mSelectedIndex;
};

//Usage
QSqlQueryModel model;

HeaderModel headerModel;
headerModel.setSourceModel(&model);

QTableView tableView;
Header * header = new Header(&tableView);
tableView.setModel(&headerModel);
tableView.connect(tableView.selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), header, SLOT(changeCurrent(QModelIndex,QModelIndex)));
tableView.setVerticalHeader(header);
tableView.setSelectionMode(QAbstractItemView::Sing leSelection);
tableView.setSelectionBehavior(QAbstractItemView:: SelectRows);
tableView.show();

advseo32
3rd August 2013, 18:24
Here you go, keyboard only operation



// Handles Horizontal header
class HeaderModel : public QSortFilterProxyModel
{
Q_OBJECT

public:
explicit HeaderModel(QObject * parent = 0)
: QSortFilterProxyModel(parent)
{ }

QVariant headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Horizontal)
{
if(role == Qt::DisplayRole)
switch(section)
{
case 0: return "Id"; break;
case 1: return "Designation"; break;
case 2: return "Famille"; break;
case 3: return "Qte Maximum"; break;
case 4: return "Qte Minimum"; break;
case 5: return "Prix"; break;
case 6: return "Prix vente"; break;
default:
return QString("Column %1").arg(section + 1);
break;
}
}

return QVariant();
}
};

// Handles Vertical header
class Header : public QHeaderView
{
Q_OBJECT
public:
explicit Header(QWidget * parent)
: QHeaderView(Qt::Vertical, parent)
, mSelectedIndex(-1)
{
setMinimumWidth(QImage("imgs/arrow.png").width());
}

public slots:
void changeCurrent(const QModelIndex & current, const QModelIndex & previous)
{
int section = current.row();

if(mSelectedIndex != section)
{
mSelectedIndex = section;
viewport()->update();
}
}

protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
if(mSelectedIndex > -1)
{
if(mSelectedIndex == logicalIndex)
if(!isSectionHidden(logicalIndex))
painter->drawImage(rect, QImage("imgs/arrow.png"));
}
painter->restore();
}

private:
int mSelectedIndex;
};

//Usage
QSqlQueryModel model;

HeaderModel headerModel;
headerModel.setSourceModel(&model);

QTableView tableView;
Header * header = new Header(&tableView);
tableView.setModel(&headerModel);
tableView.connect(tableView.selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), header, SLOT(changeCurrent(QModelIndex,QModelIndex)));
tableView.setVerticalHeader(header);
tableView.setSelectionMode(QAbstractItemView::Sing leSelection);
tableView.setSelectionBehavior(QAbstractItemView:: SelectRows);
tableView.show();


Yes this is working perfectly, but i get hard to resize the icon ,

i tried setFixedWidth() and setFixedHigh() but the icon becomes broken
i want like QtableWidget when we set an icon it resizes automatically

thanks Santosh Reddy :)

Santosh Reddy
13th August 2013, 12:38
Then set the minimum size of the icon, that will allow it to increase it's size when required.