c++qtqtreewidgetitem

Editing QTreeWidgetItem while retaining file extension


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?


Solution

  • 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();
    }