QTreeview : How to change the defalut position of the text item - qt

Could you please let me know how to chage the position of the item in QTreeView.By default the item displayed at Left most and in the center of the item box.But how should i change it so that it will display in top

Using a Qt built-in item model
If you are using e.g. QFileSystemModel you have to inherit from it and override the data() behaviour:
class MyFileSystemModel : public QFileSystemModel {
public:
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const {
if (role == Qt::TextAlignmentRole)
return Qt::AlignTop; //maybe different result depending on column/row
else
return QFileSystemModel::data(index, role);
}
and then use that class instead.
Using own item model
If you implemented your own item model all you have to do is handle Qt::TextAlignmentRole in data():
QVariant MyTreeModel::data (const QModelIndex &index, int role) const {
if (role == Qt::TextAlignmentRole)
return Qt::AlignTop; //maybe different result depending on column/row
//handle other roles
return QVariant();
}
The tree view should now automatically align the items to the top.
If you want to customize the appearance even further, here are the roles that are used by QTreeView. For more customization I think you have to implement your own QTreeView subclass.
Using QStandardItemModel
If you did not implement your own model but used QStandardItemModel you have to call
setTextAlignment(Qt::Alignment alignment) with Qt::AlignTop on your standard items before adding them to the model.

Related

How to disable or shorten the tooltip delay in QTableView?

We are using a QTableView with a custom QAbstractTableModel. Some data is too long to display in the cells directly or we would like to show additional information.
In the model we use the following code:
QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole) {
return "Short Content";
}
if (role == Qt::ToolTipRole) {
return "Super long content which contains line\nbreaks, tabs\t and more.";
}
return QVariant();
}
This works and when hovering the cells the tooltip is displayed. However, this takes a few seconds for the tooltip to appear and sometimes some mouse-wiggling.
Is there a built-in way in Qt 5 to disable the timeout and always display the tooltip?
As they point out in the Qt forum the delay depends on the style and is returned through SH_ToolTip_WakeUpDelay which is 700 ms by default.
Considering the above, a possible solution is to use the QProxyStyle method override:
class ProxyStyle : public QProxyStyle
{
public:
using QProxyStyle::QProxyStyle;
int styleHint(StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override
{
if (hint == QStyle::SH_ToolTip_WakeUpDelay)
return 0;
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
};
tableview->setStyle(new ProxyStyle(tableview->style()));

Hide QStandardItemModel row in data member function

How can I hide / exclude entire rows from a QStandardItemModel without removing them physically from the model?
Rational: I want to not display entities which are shown in another view. I already have a working highlight logic for that in the data function. Could I turn it(easily) in a "not display logic", so such rows are skipped?
QVariant CMyModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::BackgroundRole) { return CModelBase::data(index, role); }
.......
if (model.hasSomeCondition())
{
static const QBrush b(Qt::green);
return b;
}
return QVariant();
}

QTableView - set the first column as "read only"

I have a QTableView based on a QStandardItemModel.
I want to set the first column as "read only" and all the others columns editable.
I'm not an expert of QT and OOP, i searched around the web and in the QT-documentation and I've understand that I need to reimplement the flags(const QModelIndex &index) function of my model, but I don't know how and where do the re-implementation.
Thanks in advance!
You should create a new class inherited from QStandardItemModel, reimplement method flags and use your new class instead of the standard one.
class MyModel : public QStandardItemModel
{
public:
virtual Qt::ItemFlags flags(const QModelIndex& index) const override
{
Qt::ItemFlags result = QStandardItemModel::flags(index);
if (index.column() == 0) //0 is the first column!
{
result &= ~Qt::ItemIsEditable;
}
return result;
}
}
Another way to do the same:
- create a new class inherited from QStandardItem,
- reimplement flags in the same way
- call QStandardItemModel::setItemPrototype with an instance of the new class
This way is a little bit more complicated because you will need to reimplement method QStandardItem::clone as well.

emit dataChanged(createIndex(1,1),createIndex(1,1)) results in many ::data invocations

I have a QTableView and a corresponding instance of a child of QAbtractTableModel.
I was surprised to see that if my table model instance emits a dataChanged naming a single cell, the Qt framework will then issue a large number of calls to my table model's ::data() member function. The row/column range of those calls appears to cover the entire range of what is on the screen + some extra.
This is more than I expected. I would have thought that a dataChanged() that names a single cell would only result in ::data() calls requesting data for that cell. After all, that's the only cell that my table model said was changed. But the Qt framework appears to be very gregarious and inquires about all the cells.
I clearly have a broken understanding of the intent of the dataChanged() signal.
Is there a way to tell the QTableView to update one cell and one cell only without all the extra chatter sent to my table model?
UPDATE: Including code sample
The example here is a header, source, and a chunk of code to create the table. For me, the table displays with 12 columns and 29 rows. After the "issueEmit" invocation at the end, ::data will be invoked 1044 times all because of a dataChanged() signal for a single cell.
// Declaration
#include <QAbstractTableModel>
class SimpleModel : public QAbstractTableModel
{
Q_OBJECT
private:
bool _post_emit;
public:
explicit SimpleModel(QObject *parent=0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void issueEmit();
};
// Implementation
#include <stdlib.h>
#include <stdio.h>
#include "simplemodel.h"
SimpleModel::SimpleModel(QObject *parent) : QAbstractTableModel(parent), _post_emit(false) { }
int SimpleModel::rowCount(const QModelIndex &parent) const {
return 100;
}
int SimpleModel::columnCount(const QModelIndex &parent) const {
return 100;
}
QVariant SimpleModel::data(const QModelIndex &index, int role) const {
if (role==Qt::DisplayRole) {
if (_post_emit) {
static unsigned s_calls=0;
s_calls++;
printf("Data calls: %d\n",s_calls);
}
return ((rand()%10000)/1000.00);
}
return QVariant();
}
void SimpleModel::issueEmit() {
_post_emit=true;
emit dataChanged(createIndex(1,1),createIndex(1,1));
}
// Usage
QTableView *table=new QTableView;
table->setMinimumSize(1200,900);
SimpleModel *model=new SimpleModel;
table->setModel(model);
table->show();
model->issueEmit();
QVariant QStandardItem::data ( int role = Qt::UserRole + 1 ) const [virtual]
Returns the item's data for the given role, or an invalid QVariant if there is no data for the role.
The argument is really the interesting thing here. Each item in a model holds a number of QVariants, these QVariants maintain different information about the item.
These Variants are all assigned roles. Any time you emit that data has changed the model must redraw the item. To redraw the item it must look at many different pieces of data (small excerpt included below)
Roles describing appearance and meta data (with associated types):
Constant Value Description
Qt::FontRole 6 The font used for items rendered with the default delegate. (QFont)
Qt::TextAlignmentRole 7 The alignment of the text for items rendered with the default delegate. (Qt::AlignmentFlag)
Qt::BackgroundRole 8 The background brush used for items rendered with the default delegate. (QBrush)

QComboBox with NULL support

I'm using QComboBox to select unit (an arbitrary property of the object) from Units table. The problem is that object in my data model can have no unit (NULL in the table), in which case QComboBox shows value happened on top of the list. Select 'none' is not possible.
What do you suggest to add NULL support? I have few versions:
Insert special record in Units table named '--' or 'N/A'. Not exactly NULL - will have its own id.
Set items in QComboBox and update model manually. Possible but tedious - goodbye automatic update of unit list.
What else is possible - subclassing QComboBox (overriding what)? I don't see anything similar to setEditorData/setModelData like in QAbstractItemDelegate to control items.
You can subclass the model, so that data will return a special value for NULL and then setData will check for the special value and substitute a NULL.
Example sketch of code:
class MyModel : public QSqlTableModel
{
Q_OBJECT
public:
MyModel();
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
};
QVariant MyModel::data(const QModelIndex& idx, int role)
{
QVariant var = QSqlTableModel::data(idx, role);
if (var.isNull())
var = QVariant(QString("NULL"));
return var;
}
bool MyModel::setData(const QModelIndex& idx, const QVariant& value, int role)
{
QVariant var(value);
if (var == QString("NULL"))
var == QVariant(record().field(idx.column()).type());
return QSqlTableModel::setData(idx, var, role);
}

Resources