diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 8439cd22..f1fecf1b 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -203,6 +203,7 @@ SOURCES += \ widgets/custommakefileinfodialog.cpp \ widgets/darkfusionstyle.cpp \ widgets/editorstabwidget.cpp \ + widgets/filenameeditdelegate.cpp \ widgets/filepropertiesdialog.cpp \ widgets/functiontooltipwidget.cpp \ widgets/headercompletionpopup.cpp \ @@ -330,6 +331,7 @@ HEADERS += \ widgets/custommakefileinfodialog.h \ widgets/darkfusionstyle.h \ widgets/editorstabwidget.h \ + widgets/filenameeditdelegate.h \ widgets/filepropertiesdialog.h \ widgets/functiontooltipwidget.h \ widgets/headercompletionpopup.h \ diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 401a7d63..a584bcf7 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -24,6 +24,7 @@ #include "debugger.h" #include "widgets/cpudialog.h" #include "widgets/filepropertiesdialog.h" +#include "widgets/filenameeditdelegate.h" #include "project.h" #include "projecttemplate.h" #include "widgets/newprojectdialog.h" @@ -400,6 +401,8 @@ MainWindow::MainWindow(QWidget *parent) for (int i=1;itreeFiles->hideColumn(i); } + FilenameEditDelegate *filenameEditDelegate = new FilenameEditDelegate(ui->treeFiles); + ui->treeFiles->setItemDelegate(filenameEditDelegate); connect(ui->cbFilesPath->lineEdit(),&QLineEdit::returnPressed, this,&MainWindow::onFilesViewPathChanged); connect(ui->cbFilesPath, QOverload::of(&QComboBox::currentIndexChanged), diff --git a/RedPandaIDE/widgets/filenameeditdelegate.cpp b/RedPandaIDE/widgets/filenameeditdelegate.cpp new file mode 100644 index 00000000..667e9e6c --- /dev/null +++ b/RedPandaIDE/widgets/filenameeditdelegate.cpp @@ -0,0 +1,100 @@ +/* by XY0797 2024.2.21 */ + +#include "filenameeditdelegate.h" +#include +#include + +// Custom edit box control. This is necessary because the default behavior of a QLineEdit when it gains focus is to select all its text, and if a selection is set before gaining focus, it will be overridden by the select-all action upon focusing. +class FilenameLineEdit : public QLineEdit +{ +public: + explicit FilenameLineEdit(QWidget *parent = nullptr) : QLineEdit(parent) {} + + // Add a custom method to set the selection on focus gain. + void setFocusSelectState(int index, int length) + { + m_focusSelectionStart = index; + m_focusSelectionLength = length; + } + +protected: + int m_focusSelectionStart = -1; + int m_focusSelectionLength = -1; + + // Override the focus-in event, resetting the selection before executing the default operation. + void focusInEvent(QFocusEvent *event) override + { + if (m_focusSelectionStart != -1 && m_focusSelectionLength > 0) + { + deselect(); + setSelection(m_focusSelectionStart, m_focusSelectionLength); + } + QLineEdit::focusInEvent(event); + } +}; + +// Return the last occurrence index of '.' in the string; if not found, return the length of the string. +int findDotPosition(const QString &fileName) +{ + int dotPosition = fileName.lastIndexOf('.'); + if (dotPosition != -1) + { + return dotPosition; + } + else + { + return fileName.length(); + } +} + +// Below follows the implementation of the delegate class. + +FilenameEditDelegate::FilenameEditDelegate(QObject *parent) : QStyledItemDelegate(parent) {} + +// Use our custom component when creating the editor. +QWidget *FilenameEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + FilenameLineEdit *editor = new FilenameLineEdit(parent); + return editor; +} + +// Set the content, and if the item is a file, set the selection on focus gain to exclude the file extension. +void FilenameEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + FilenameLineEdit *lineEdit = (FilenameLineEdit *)editor; + if (!lineEdit) { return; } + + QString fileName = index.data().toString(); + lineEdit->setText(fileName); + // Determine whether the currently edited item is a directory or a file; if it's a directory, there's no need to set a selection. + Qt::ItemFlags flags = index.flags(); + if (flags & Qt::ItemNeverHasChildren) { + lineEdit->setFocusSelectState(0, findDotPosition(fileName)); + } +} + +// Return the edited data back to the QTreeView. +void FilenameEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + FilenameLineEdit *lineEdit = (FilenameLineEdit *)editor; + if (!lineEdit) { return; } + + model->setData(index, lineEdit->text()); +} + +// Override the method for updating the editor's position. +void FilenameEditDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + FilenameLineEdit *lineEdit = (FilenameLineEdit *)editor; + if (!lineEdit) { return; } + + const QWidget *widget = option.widget; + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + opt.showDecorationSelected = true; + + QStyle *style = widget ? widget->style() : QApplication::style(); + QRect geom = style->subElementRect(QStyle::SE_ItemViewItemText, &opt, widget); + + lineEdit->setGeometry(geom); +} diff --git a/RedPandaIDE/widgets/filenameeditdelegate.h b/RedPandaIDE/widgets/filenameeditdelegate.h new file mode 100644 index 00000000..c46dbf6d --- /dev/null +++ b/RedPandaIDE/widgets/filenameeditdelegate.h @@ -0,0 +1,20 @@ +#ifndef FILENAMEEDITDELEGATE_H +#define FILENAMEEDITDELEGATE_H + +#include + +class FilenameEditDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + FilenameEditDelegate(QObject *parent = nullptr); + + int mIconWidth = 20; + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + void setEditorData(QWidget *editor, const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; +}; + +#endif // FILENAMEEDITDELEGATE_H diff --git a/RedPandaIDE/xmake.lua b/RedPandaIDE/xmake.lua index edc5c852..c9115584 100644 --- a/RedPandaIDE/xmake.lua +++ b/RedPandaIDE/xmake.lua @@ -91,6 +91,7 @@ target("RedPandaIDE") "widgets/customfilesystemmodel", "widgets/darkfusionstyle", "widgets/editorstabwidget", + "widgets/filenameeditdelegate", "widgets/functiontooltipwidget", "widgets/headercompletionpopup", "widgets/issuestable",