How can I create a QTableWidgetItem right-justified with long text, with the ellipses on the left?

Viewed 1089

Suppose I have a QTableWidget. Then, I create items for it

QString pathname="C:\\Directory1\\Directory2\\Directory3\\example.txt";
QTableWidgetItem*item=new QTableWidgetItem(pathname);
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignRight);
ui->myTable->setItem(row, 1, item);

If the column is more narrow than the pathname, then I get something like:

"C:\Directory1\Dir ..."

However, the column display would be much more useful, IMHO, if it were truly right-aligned, in that the end part of the pathname were to be aligned with the right part of the cell, and the part that didn't fit, because the cell was too narrow, was represented by an ellipsis (i.e. the "...") on the left, e.g.

"... ectory3\example.txt"

That way, if there were a lot of files in the same directory, the displayed text might show the full filename, providing it wasn't too long; instead of showing a lot of entries with only the left part of the path being displayed, with the result that they all displayed identically.

I realize I could do a call to find out how big a text string would be displayed at the current font, pitch, weight etc. Then, I might iterate until I found the maximum letters that would fit; and set it in the above code to only as much as would fit.

However, I'd rather use a QStyledItemDelegate and use setItemDelegateForColumn(), do something something similar; or use a stylesheet; such that the underlying data would be the full and correct pathname, but for it to display it being truly right-justified - even when the column is too narrow for the underlying text.

2 Answers

Ok guys, I found an even simpler solution. Just one method to override; and I don't have to do it for each item. Thanks for the help, tho.

After some searching, and reading the code of qitemdelegate.cpp, I knew there was a setOptions method of QStyledItemDelegate. I just couldn't figure out how the options it was using might be being set or used (in a way useful to this ?). Then, I tried a different search, and came across:

Elide modes for QTreeView ,QStandardItemModel

The reply by wysota turned out to be one good answer (although I dislike his homogenizing motto - you'd think he worked for M$). From that, I came up with:

class elideLeftItemC : public QStyledItemDelegate
{
    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
      const QModelIndex &index) const
    {
        QStyleOptionViewItem opt = option;
        opt.textElideMode=Qt::ElideLeft;
        QStyledItemDelegate::paint(painter, opt, index);
    }
} elideLeftItem;

Then, I can just reused with any suitable data type, any time I need elided left text, like:

ui->twMyTable->setItemDelegateForColumn(0, &elideLeftItem);

There may be a way to assign it even farther upstream, but this isn't bad. I might also have tested on column numbers, as in wysota's answer, but I like how it documents which columns have modified delegates and which do not this way. Doing it this way, you don't have to use as much code for each instance where you needed left-elided text. Dat be eet.

For the ellipsis on the left, you can use QFontMetrics on your path name, and you elide it on the left with Qt::ElideLeft.

QTableWidgetItem *item = new QTableWidgetItem();
// your metric
QFontMetrics metrics(item->font());
// your path
QString pathname = "C:\\Directory1\\Directory2\\Directory3\\example.txt";
// your elided path
QString elidedPathname = metrics.elidedText(pathname, Qt::ElideLeft, item->sizeHint().width());
// setting your new string in your item
item->setText(elidedPathname);
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignRight);
ui->myTable->setItem(row, 1, item);
Related