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