RedPanda-CPP/RedPandaIDE/widgets/filenameeditdelegate.cpp

101 lines
3.5 KiB
C++

/* by XY0797 2024.2.21 */
#include "filenameeditdelegate.h"
#include <QLineEdit>
#include <qapplication.h>
// 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);
}