Editing QTreeWidgetItem while retaining file extension

Viewed 39

I have a QListWidget that contains filenames. Right-clicking on an item brings up a menu which contains a Rename... item. Clicking on Rename... lets the user edit the filename. So far so good.

But in the Qt Creator Projects window, right-clicking on (say) foo.cpp and selecting Rename... presents the user with a field in which foo is selected, and .cpp isn't. So the default action is to rename the foo part without changing the .cpp extension.

This is exactly what I need, but I don't see a way to achieve it using Qt's public API. What do I have to do? Custom delegates, I suppose; but this is surely a common requirement, so I wondered if anybody had some ready-to-use C++ code that I could snarf?

1 Answers

A possible solution is to create a QObject that intercepts the editor's show event and then change the selection:

#include <QtWidgets>

class Helper: public QObject{
public:
    Helper(QLineEdit *le): QObject(le), m_le(le){
        m_le->installEventFilter(this);
    }
    bool eventFilter(QObject *watched, QEvent *event){
        if(watched == m_le && event->type() == QEvent::Show){
            QString filename = m_le->text();
            QFileInfo fi(filename);
            QString base = fi.baseName();
            m_le->setSelection(0, base.length());
        }
        return QObject::eventFilter(watched, event);
    }
private:
    QLineEdit* m_le;
};

class StyledItemDelegate: public QStyledItemDelegate{
public:
    using QStyledItemDelegate::QStyledItemDelegate;
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem & option, const QModelIndex &index) const{
        QWidget *editor = QStyledItemDelegate::createEditor(parent, option, index);
        if(QLineEdit *le = qobject_cast<QLineEdit *>(editor)){
            new Helper(le);
        }
        return editor;
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTreeWidget w;
    w.setItemDelegate(new StyledItemDelegate);
    for(const QString & filename: {"foo.txt", "foo.tar.gz", "foo.cpp"}){
        auto item = new QTreeWidgetItem({filename});
        item->setFlags(item->flags() | Qt::ItemIsEditable);
        w.addTopLevelItem(item);
    }
    w.show();
    return a.exec();
}
Related