Get rid of dirty BufferView pointer

Now that there is a signal to inform the controller when the buffer view has
changed, it is no longer necessary to store a perishable pointer to a buffer
view in the dialog view. (Indeed, it was only really useful for checking whether
the new buffer view pointer was different from the old one.)

TODO: other dialogs should be audited for similar hazards.
This commit is contained in:
Guillaume Munch 2016-10-10 00:36:26 +02:00
parent de19b8fc2d
commit e0e765f6a9
2 changed files with 77 additions and 79 deletions

View File

@ -47,10 +47,10 @@ using namespace std;
namespace lyx { namespace lyx {
namespace frontend { namespace frontend {
ViewSourceWidget::ViewSourceWidget() ViewSourceWidget::ViewSourceWidget(QWidget * parent)
: bv_(0), document_(new QTextDocument(this)), : QWidget(parent),
highlighter_(new LaTeXHighlighter(document_)), document_(new QTextDocument(this)),
update_timer_(new QTimer(this)) highlighter_(new LaTeXHighlighter(document_))
{ {
setupUi(this); setupUi(this);
@ -63,16 +63,9 @@ ViewSourceWidget::ViewSourceWidget()
connect(masterPerspectiveCB, SIGNAL(toggled(bool)), connect(masterPerspectiveCB, SIGNAL(toggled(bool)),
this, SLOT(contentsChanged())); this, SLOT(contentsChanged()));
connect(updatePB, SIGNAL(clicked()), connect(updatePB, SIGNAL(clicked()),
this, SLOT(updateViewNow())); this, SIGNAL(needUpdate()));
connect(outputFormatCO, SIGNAL(activated(int)), connect(outputFormatCO, SIGNAL(activated(int)),
this, SLOT(setViewFormat(int))); this, SLOT(setViewFormat(int)));
connect(outputFormatCO, SIGNAL(activated(int)),
this, SLOT(contentsChanged()));
// setting the update timer
update_timer_->setSingleShot(true);
connect(update_timer_, SIGNAL(timeout()),
this, SLOT(realUpdateView()));
// setting a document at this point trigger an assertion in Qt // setting a document at this point trigger an assertion in Qt
// so we disable the signals here: // so we disable the signals here:
@ -93,7 +86,7 @@ ViewSourceWidget::ViewSourceWidget()
} }
void ViewSourceWidget::getContent(BufferView const * view, void ViewSourceWidget::getContent(BufferView const & view,
Buffer::OutputWhat output, docstring & str, string const & format, Buffer::OutputWhat output, docstring & str, string const & format,
bool master) bool master)
{ {
@ -102,33 +95,23 @@ void ViewSourceWidget::getContent(BufferView const * view,
pit_type par_begin; pit_type par_begin;
pit_type par_end; pit_type par_end;
if (!view->cursor().selection()) { if (!view.cursor().selection()) {
par_begin = view->cursor().bottom().pit(); par_begin = view.cursor().bottom().pit();
par_end = par_begin; par_end = par_begin;
} else { } else {
par_begin = view->cursor().selectionBegin().bottom().pit(); par_begin = view.cursor().selectionBegin().bottom().pit();
par_end = view->cursor().selectionEnd().bottom().pit(); par_end = view.cursor().selectionEnd().bottom().pit();
} }
if (par_begin > par_end) if (par_begin > par_end)
swap(par_begin, par_end); swap(par_begin, par_end);
odocstringstream ostr; odocstringstream ostr;
texrow_ = view->buffer() texrow_ = view.buffer()
.getSourceCode(ostr, format, par_begin, par_end + 1, output, master); .getSourceCode(ostr, format, par_begin, par_end + 1, output, master);
//ensure that the last line can always be selected in its full width //ensure that the last line can always be selected in its full width
str = ostr.str() + "\n"; str = ostr.str() + "\n";
} }
void ViewSourceWidget::setBufferView(BufferView const * bv)
{
if (bv_ != bv) {
setText();
bv_ = bv;
}
setEnabled(bv ? true : false);
}
bool ViewSourceWidget::setText(QString const & qstr) bool ViewSourceWidget::setText(QString const & qstr)
{ {
bool const changed = document_->toPlainText() != qstr; bool const changed = document_->toPlainText() != qstr;
@ -142,7 +125,7 @@ bool ViewSourceWidget::setText(QString const & qstr)
void ViewSourceWidget::contentsChanged() void ViewSourceWidget::contentsChanged()
{ {
if (autoUpdateCB->isChecked()) if (autoUpdateCB->isChecked())
updateViewNow(); Q_EMIT needUpdate();
} }
@ -152,31 +135,42 @@ void ViewSourceWidget::setViewFormat(int const index)
string format = fromqstr(outputFormatCO->itemData(index).toString()); string format = fromqstr(outputFormatCO->itemData(index).toString());
if (view_format_ != format) { if (view_format_ != format) {
view_format_ = format; view_format_ = format;
// emit signal Q_EMIT needUpdate();
formatChanged();
} }
} }
void ViewSourceWidget::updateView() int ViewSourceWidget::updateDelay() const
{ {
const int long_delay = 400; const int long_delay = 400;
const int short_delay = 60; const int short_delay = 60;
// a shorter delay if just the current paragraph is shown // a shorter delay if just the current paragraph is shown
update_timer_->start((contentsCO->currentIndex() == 0) ? return (contentsCO->currentIndex() == 0) ? short_delay : long_delay;
short_delay : long_delay);
} }
void ViewSourceWidget::updateViewNow() void GuiViewSource::scheduleUpdate()
{
update_timer_->start(widget_->updateDelay());
}
void GuiViewSource::scheduleUpdateNow()
{ {
update_timer_->start(0); update_timer_->start(0);
} }
void ViewSourceWidget::realUpdateView() void GuiViewSource::realUpdateView()
{ {
if (!bv_) { widget_->updateView(bufferview());
updateTitle();
}
void ViewSourceWidget::updateView(BufferView const * bv)
{
if (!bv) {
setText(); setText();
setEnabled(false); setEnabled(false);
return; return;
@ -199,7 +193,7 @@ void ViewSourceWidget::realUpdateView()
output = Buffer::OnlyBody; output = Buffer::OnlyBody;
docstring content; docstring content;
getContent(bv_, output, content, view_format_, getContent(*bv, output, content, view_format_,
masterPerspectiveCB->isChecked()); masterPerspectiveCB->isChecked());
QString old = document_->toPlainText(); QString old = document_->toPlainText();
QString qcontent = toqstr(content); QString qcontent = toqstr(content);
@ -218,7 +212,7 @@ void ViewSourceWidget::realUpdateView()
} }
#endif #endif
// prevent gotoCursor() // prevent gotoCursor()
viewSourceTV->blockSignals(true); QSignalBlocker blocker(viewSourceTV);
bool const changed = setText(qcontent); bool const changed = setText(qcontent);
if (changed && !texrow_) { if (changed && !texrow_) {
@ -254,7 +248,7 @@ void ViewSourceWidget::realUpdateView()
} else if (texrow_) { } else if (texrow_) {
// Use the available position-to-row conversion to highlight // Use the available position-to-row conversion to highlight
// the current selection in the source // the current selection in the source
std::pair<int,int> rows = texrow_->rowFromCursor(bv_->cursor()); std::pair<int,int> rows = texrow_->rowFromCursor(bv->cursor());
int const beg_row = rows.first; int const beg_row = rows.first;
int const end_row = rows.second; int const end_row = rows.second;
@ -306,7 +300,6 @@ void ViewSourceWidget::realUpdateView()
viewSourceTV->setTextCursor(c); viewSourceTV->setTextCursor(c);
viewSourceTV->horizontalScrollBar()->setValue(h_scroll); viewSourceTV->horizontalScrollBar()->setValue(h_scroll);
} // else if (texrow) } // else if (texrow)
viewSourceTV->blockSignals(false);
} }
@ -342,18 +335,15 @@ void ViewSourceWidget::goToCursor() const
void ViewSourceWidget::updateDefaultFormat() void ViewSourceWidget::updateDefaultFormat(BufferView const & bv)
{ {
if (!bv_) QSignalBlocker blocker(outputFormatCO);
return;
outputFormatCO->blockSignals(true);
outputFormatCO->clear(); outputFormatCO->clear();
outputFormatCO->addItem(qt_("Default"), outputFormatCO->addItem(qt_("Default"),
QVariant(QString("default"))); QVariant(QString("default")));
int index = 0; int index = 0;
vector<string> tmp = bv_->buffer().params().backends(); vector<string> tmp = bv.buffer().params().backends();
vector<string>::const_iterator it = tmp.begin(); vector<string>::const_iterator it = tmp.begin();
vector<string>::const_iterator en = tmp.end(); vector<string>::const_iterator en = tmp.end();
for (; it != en; ++it) { for (; it != en; ++it) {
@ -370,8 +360,6 @@ void ViewSourceWidget::updateDefaultFormat()
index = outputFormatCO->count() -1; index = outputFormatCO->count() -1;
} }
setViewFormat(index); setViewFormat(index);
outputFormatCO->blockSignals(false);
} }
@ -414,31 +402,39 @@ void ViewSourceWidget::restoreSession(QString const & session_key)
.toBool(); .toBool();
autoUpdateCB->setChecked(checked); autoUpdateCB->setChecked(checked);
if (checked) if (checked)
updateView(); Q_EMIT needUpdate();
} }
GuiViewSource::GuiViewSource(GuiView & parent, GuiViewSource::GuiViewSource(GuiView & parent,
Qt::DockWidgetArea area, Qt::WindowFlags flags) Qt::DockWidgetArea area, Qt::WindowFlags flags)
: DockView(parent, "view-source", qt_("Code Preview"), area, flags) : DockView(parent, "view-source", qt_("Code Preview"), area, flags),
widget_(new ViewSourceWidget(this)),
update_timer_(new QTimer(this))
{ {
widget_ = new ViewSourceWidget;
setWidget(widget_); setWidget(widget_);
connect(widget_, SIGNAL(formatChanged()), this, SLOT(updateTitle()));
// setting the update timer
update_timer_->setSingleShot(true);
connect(update_timer_, SIGNAL(timeout()),
this, SLOT(realUpdateView()));
connect(widget_, SIGNAL(needUpdate()), this, SLOT(scheduleUpdateNow()));
} }
GuiViewSource::~GuiViewSource() void GuiViewSource::on_bufferViewChanged()
{ {
delete widget_; widget_->setText();
widget_->setEnabled((bool)bufferview());
} }
void GuiViewSource::updateView() void GuiViewSource::updateView()
{ {
if (widget_->autoUpdateCB->isChecked()) { if (widget_->autoUpdateCB->isChecked()) {
widget_->setBufferView(bufferview()); widget_->setEnabled((bool)bufferview());
widget_->updateView(); scheduleUpdate();
} }
widget_->masterPerspectiveCB->setEnabled(buffer().parent()); widget_->masterPerspectiveCB->setEnabled(buffer().parent());
updateTitle(); updateTitle();
@ -447,8 +443,9 @@ void GuiViewSource::updateView()
void GuiViewSource::enableView(bool enable) void GuiViewSource::enableView(bool enable)
{ {
widget_->setBufferView(bufferview()); widget_->setEnabled((bool)bufferview());
widget_->updateDefaultFormat(); if (bufferview())
widget_->updateDefaultFormat(*bufferview());
if (!enable) if (!enable)
// In the opposite case, updateView() will be called anyway. // In the opposite case, updateView() will be called anyway.
widget_->contentsChanged(); widget_->contentsChanged();

View File

@ -43,29 +43,27 @@ class ViewSourceWidget : public QWidget, public Ui::ViewSourceUi
Q_OBJECT Q_OBJECT
public: public:
ViewSourceWidget(); ViewSourceWidget(QWidget * parent);
///
void setBufferView(BufferView const * bv);
/// returns true if the string has changed /// returns true if the string has changed
bool setText(QString const & qstr = QString()); bool setText(QString const & qstr = QString());
/// ///
void saveSession(QString const & session_key) const; void saveSession(QString const & session_key) const;
/// ///
void restoreSession(QString const & session_key); void restoreSession(QString const & session_key);
///
int updateDelay() const;
protected: protected:
/// ///
void resizeEvent (QResizeEvent * event); void resizeEvent (QResizeEvent * event);
public Q_SLOTS: public Q_SLOTS:
/// schedule an update after delay ///
void updateView(); void updateView(BufferView const * bv);
/// schedule an update now
void updateViewNow();
/// ///
void setViewFormat(int const index); void setViewFormat(int const index);
// //
void updateDefaultFormat(); void updateDefaultFormat(BufferView const & bv);
/// ///
void contentsChanged(); void contentsChanged();
/// ///
@ -74,28 +72,20 @@ public Q_SLOTS:
docstring currentFormatName(BufferView const * bv) const; docstring currentFormatName(BufferView const * bv) const;
Q_SIGNALS: Q_SIGNALS:
void formatChanged() const; void needUpdate() const;
private Q_SLOTS:
/// update content
void realUpdateView();
private: private:
/// Get the source code of selected paragraphs, or the whole document. /// Get the source code of selected paragraphs, or the whole document.
void getContent(BufferView const * view, Buffer::OutputWhat output, void getContent(BufferView const & view, Buffer::OutputWhat output,
docstring & str, std::string const & format, bool master); docstring & str, std::string const & format, bool master);
/// Grab double clicks on the viewport /// Grab double clicks on the viewport
bool eventFilter(QObject * obj, QEvent * event); bool eventFilter(QObject * obj, QEvent * event);
/// ///
BufferView const * bv_;
///
QTextDocument * document_; QTextDocument * document_;
/// LaTeX syntax highlighter /// LaTeX syntax highlighter
LaTeXHighlighter * highlighter_; LaTeXHighlighter * highlighter_;
/// ///
std::string view_format_; std::string view_format_;
///
QTimer * update_timer_;
/// TexRow information from the last source view. If TexRow is unavailable /// TexRow information from the last source view. If TexRow is unavailable
/// for the last format then texrow_ is null. /// for the last format then texrow_ is null.
unique_ptr<TexRow> texrow_; unique_ptr<TexRow> texrow_;
@ -112,8 +102,6 @@ public:
Qt::DockWidgetArea area = Qt::BottomDockWidgetArea, ///< Position of the dock (and also drawer) Qt::DockWidgetArea area = Qt::BottomDockWidgetArea, ///< Position of the dock (and also drawer)
Qt::WindowFlags flags = 0); Qt::WindowFlags flags = 0);
~GuiViewSource();
/// Controller inherited method. /// Controller inherited method.
///@{ ///@{
bool initialiseParams(std::string const & source); bool initialiseParams(std::string const & source);
@ -129,13 +117,26 @@ public:
bool wantInitialFocus() const { return false; } bool wantInitialFocus() const { return false; }
///@} ///@}
public Q_SLOTS:
///
void on_bufferViewChanged();//override
private Q_SLOTS: private Q_SLOTS:
/// The title displayed by the dialog reflects source type. /// The title displayed by the dialog reflects source type.
void updateTitle(); void updateTitle();
/// schedule an update after delay
void scheduleUpdate();
/// schedule an update now
void scheduleUpdateNow();
/// update content
void realUpdateView();
private: private:
/// The encapsulated widget. /// The encapsulated widget.
ViewSourceWidget * widget_; ViewSourceWidget * widget_;
///
QTimer * update_timer_;
}; };
} // namespace frontend } // namespace frontend