У меня есть две отдельные темы.
Первый поток для GUI, а второй для данных приложения.
Изначально я хотел использовать QUndoStack и QUndoView.
Но возникла проблема — это представление работает напрямую со стеком:
В этом случае я получил состояние гонки.
Чтобы решить эту проблему, я написал собственный myUndoView, используя QListView и QAbstractListModel.
Теперь все мои слоты используют соединения с очередями, и я храню облегченную копию «реального» стека отмены в модели пользовательского представления.
Это тот же самый размер и тот же порядок «настоящих» элементов стека отмены.
Облегченный элемент содержит только тип команды отмены и текст.
Теперь у меня есть другая проблема. Я не виноват в этом))
У меня есть QLineEdit, который излучает сигнал при изменении значения, когда я нажимаю клавишу ввода или теряю фокус.
Это значение в свою очередь отправляется объекту (модели приложения) с «реальным» стеком отмены. Оно работает.
Но это не работает, когда я взаимодействую с видом отмены тоже.
Повторяю, я не виноват в этом. QUndoView имеет такое же поведение.
Шаг за шагом:
Упс .. currentIndexChanged () сигнал от просмотра отмены может быть отправлен первым,
или сигнал от QLineEdit может быть отправлен первым.
Это всегда отличается ..
Если сигнал от QLineEdit был послан первым — он работает правильно.
История изменений не пропала.
Я хочу сделать ввод / размытие и другие изменения (не в виде истории) всегда вызывается первым. Вероятно, я могу использовать QTimer :: singleShot () для задержки сигналов отмена отката. Но не curentIndexChanged (), потому что этот сигнал испускается при взаимодействии с пользователем и при отмене стека обновляется программно. Мы не можем определить, кто вносит изменения — пользователь или приложение.
Что я пробовал?
Перехватывать щелчки мыши:
myUndoView::mousePressEvent(QMouseEvent *event)
{
event->ignore();
qDebug() << "catched!";
}
Но иногда он теряет щелчки.
В нижней части элемента списка (под буквами) находится область, в которой щелчок передается на элемент.
Это может быть ошибка Qt, найденная в моей среде: Debian, Mate, GTK + Qt-style.
Я думаю, я могу разместить другой прозрачный виджет над списком, получить координаты клика и использовать его:
http://doc.qt.io/qt-5/qabstractitemview.html#indexAt
чтобы получить выбранный индекс.
Или я все делаю неправильно?
Может быть, есть более простой способ?
Как сделать это правильно?
я бы попробовал блокировка списка модельных сигналов в то время как редактирование линии сосредоточено.
Давайте создадим фильтр событий, подобный этому:
class EventFilter : public QObject
{
Q_OBJECT
public:
EventFilter(QObject * model) : _model(model){}
bool eventFilter(QObject *watched, QEvent *event);
private:
QObject * _model;
};
который сохраняет частную ссылку на модель списка в качестве указателя на QObject
, переданный в аргументе конструктора.
Реализация фильтра:
bool EventFilter::eventFilter(QObject *watched, QEvent *event)
{
if(event->type() == QEvent::FocusIn)
{
_model->blockSignals(true);
}
return false;
}
Сохранить ссылку на экземпляр фильтра в классе окна (Form
в моем примере) вместе со ссылкой на экземпляр модели списка:
private:
EventFilter * filter;
QAbstractListModel * model;
Фильтр должен быть создан и установлен в редакторе строк, в Form
конструктор (не забудьте удалить его в деструкторе):
filter = new EventFilter(model); //the model is passed to the filter in construction
ui->lineEdit->installEventFilter(filter);
На этом этапе события модели будут заблокированы, когда редактирование линии получит фокус. Чтобы разблокировать их, используйте строку редактирования editingFinished
слот:
void Form::on_lineEdit_editingFinished()
{
model->blockSignals(false);
}
Других решений пока нет …