LINUX.ORG.RU

Кастомный делегат и завершение редактирования

 , ,


0

2

Привет, всем! Столкнулся с проблемой, которую мне пока не получается решить. Прошу помочь. У меня есть виджет для редактирования пути к файлу. Его я использую в делегате table view (скриншот). Проблема с ним в том, что если я передаю фокус в lineedit, то делегат не хочет самостоятельно закрываться переходя на другую вкладку, либо по нажатию run. Это приводит к тому, что данные не передаются в модель и в диалог, который этими данными интересуется. Поискал на форумах, как люди решают эту проблему. В основном рекомендуют применять setFocusProxy и eventFilter. Но я не смог разобраться, как их применить к моему случаю. Есть ещё такое ограничение: в редакторе присутствуют кнопки выбора файла и редактирования файла. Желательно по их нажатию не закрывать делегат. Проект с проблемой на github Целевая платформа windows

Я когда-то смотрел эти делегаты. Так они там через жопу сделаны. Проще дьяволу душу продать, чем нормально запилить кастомный виджет в таблицу. С фокусом постоянно проблемы. Используй qml.

ox55ff ★★ ()
QWidget *Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    FilePathEditor* editor = new FilePathEditor(parent, index);
    
    //< You should commit the data when it's changed.
    QSignalMapper * mapper = new QSignalMapper(editor);
    mapper->setMapping(editor,editor);
    QObject::connect(editor,SIGNAL(getValidPath()), mapper, SLOT(map()));
    QObject::connect(mapper, SIGNAL(mapped(QWidget *)), this, SIGNAL(commitData(QWidget *)));
    
    return editor;
}
anonymous ()
class FilePathEditor : public QWidget
{
    Q_OBJECT

public:
    explicit FilePathEditor(QWidget *parent, const QModelIndex &modelIndex);
    ~FilePathEditor() override;

    void setPath(const QString &path);
    QString path() const;

    void setupDialog();
    void executeNotepad();
signals:
    void pathChanged(QWidget* widget);
    void editionFinished(QWidget* widget,QAbstractItemDelegate::EndEditHint hint = QAbstractItemDelegate::NoHint);

private:
    Ui::FilePathEditor *ui;
    QStringList filters_;
    QFileDialog::AcceptMode acceptMode_;
    QFileDialog::FileMode fileMode_;
    QModelIndex modelIndex_;
void FilePathEditor::setPath(const QString &path) {
    ui->pathEdit->setText(QDir::toNativeSeparators(path));
    emit pathChanged(this);
    if(!path.isEmpty())
    {
        emit editionFinished(this);
    }
}
QWidget *Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    FilePathEditor* editor = new FilePathEditor(parent, index);
    connect(editor,&FilePathEditor::pathChanged,this,&QStyledItemDelegate::commitData);
    connect(editor,&FilePathEditor::editionFinished,this,&QStyledItemDelegate::closeEditor);
    return editor;
}
anonymous ()

В итоге просканировал, какие QEvent прилетают в стандартных делегатах и посмотрел, каких не хватает в моём. Прикостылил postEvent на фокус:

bool FilePathEditor::eventFilter(QObject *watched, QEvent *event) {
    if (watched == ui->pathEdit && event->type() == QEvent::FocusOut) {
        QApplication::postEvent(this, new QFocusEvent(QEvent::FocusOut));
    }
    return QWidget::eventFilter(watched, event);
}

Кнопки почему-то фокус у line edit не отбирают.

Диалогу выбора файла назначил родителя класс делегата, чтобы не было use-after-free. Надеюсь не отвалится.

heaven__12 ()