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 frontend {
ViewSourceWidget::ViewSourceWidget()
: bv_(0), document_(new QTextDocument(this)),
highlighter_(new LaTeXHighlighter(document_)),
update_timer_(new QTimer(this))
ViewSourceWidget::ViewSourceWidget(QWidget * parent)
: QWidget(parent),
document_(new QTextDocument(this)),
highlighter_(new LaTeXHighlighter(document_))
{
setupUi(this);
@ -63,16 +63,9 @@ ViewSourceWidget::ViewSourceWidget()
connect(masterPerspectiveCB, SIGNAL(toggled(bool)),
this, SLOT(contentsChanged()));
connect(updatePB, SIGNAL(clicked()),
this, SLOT(updateViewNow()));
this, SIGNAL(needUpdate()));
connect(outputFormatCO, SIGNAL(activated(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
// 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,
bool master)
{
@ -102,33 +95,23 @@ void ViewSourceWidget::getContent(BufferView const * view,
pit_type par_begin;
pit_type par_end;
if (!view->cursor().selection()) {
par_begin = view->cursor().bottom().pit();
if (!view.cursor().selection()) {
par_begin = view.cursor().bottom().pit();
par_end = par_begin;
} else {
par_begin = view->cursor().selectionBegin().bottom().pit();
par_end = view->cursor().selectionEnd().bottom().pit();
par_begin = view.cursor().selectionBegin().bottom().pit();
par_end = view.cursor().selectionEnd().bottom().pit();
}
if (par_begin > par_end)
swap(par_begin, par_end);
odocstringstream ostr;
texrow_ = view->buffer()
texrow_ = view.buffer()
.getSourceCode(ostr, format, par_begin, par_end + 1, output, master);
//ensure that the last line can always be selected in its full width
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 const changed = document_->toPlainText() != qstr;
@ -142,7 +125,7 @@ bool ViewSourceWidget::setText(QString const & qstr)
void ViewSourceWidget::contentsChanged()
{
if (autoUpdateCB->isChecked())
updateViewNow();
Q_EMIT needUpdate();
}
@ -152,31 +135,42 @@ void ViewSourceWidget::setViewFormat(int const index)
string format = fromqstr(outputFormatCO->itemData(index).toString());
if (view_format_ != format) {
view_format_ = format;
// emit signal
formatChanged();
Q_EMIT needUpdate();
}
}
void ViewSourceWidget::updateView()
int ViewSourceWidget::updateDelay() const
{
const int long_delay = 400;
const int short_delay = 60;
// a shorter delay if just the current paragraph is shown
update_timer_->start((contentsCO->currentIndex() == 0) ?
short_delay : long_delay);
return (contentsCO->currentIndex() == 0) ? short_delay : long_delay;
}
void ViewSourceWidget::updateViewNow()
void GuiViewSource::scheduleUpdate()
{
update_timer_->start(widget_->updateDelay());
}
void GuiViewSource::scheduleUpdateNow()
{
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();
setEnabled(false);
return;
@ -199,7 +193,7 @@ void ViewSourceWidget::realUpdateView()
output = Buffer::OnlyBody;
docstring content;
getContent(bv_, output, content, view_format_,
getContent(*bv, output, content, view_format_,
masterPerspectiveCB->isChecked());
QString old = document_->toPlainText();
QString qcontent = toqstr(content);
@ -218,7 +212,7 @@ void ViewSourceWidget::realUpdateView()
}
#endif
// prevent gotoCursor()
viewSourceTV->blockSignals(true);
QSignalBlocker blocker(viewSourceTV);
bool const changed = setText(qcontent);
if (changed && !texrow_) {
@ -254,7 +248,7 @@ void ViewSourceWidget::realUpdateView()
} else if (texrow_) {
// Use the available position-to-row conversion to highlight
// 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 end_row = rows.second;
@ -306,7 +300,6 @@ void ViewSourceWidget::realUpdateView()
viewSourceTV->setTextCursor(c);
viewSourceTV->horizontalScrollBar()->setValue(h_scroll);
} // 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_)
return;
outputFormatCO->blockSignals(true);
QSignalBlocker blocker(outputFormatCO);
outputFormatCO->clear();
outputFormatCO->addItem(qt_("Default"),
QVariant(QString("default")));
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 en = tmp.end();
for (; it != en; ++it) {
@ -370,8 +360,6 @@ void ViewSourceWidget::updateDefaultFormat()
index = outputFormatCO->count() -1;
}
setViewFormat(index);
outputFormatCO->blockSignals(false);
}
@ -414,31 +402,39 @@ void ViewSourceWidget::restoreSession(QString const & session_key)
.toBool();
autoUpdateCB->setChecked(checked);
if (checked)
updateView();
Q_EMIT needUpdate();
}
GuiViewSource::GuiViewSource(GuiView & parent,
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_);
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()
{
if (widget_->autoUpdateCB->isChecked()) {
widget_->setBufferView(bufferview());
widget_->updateView();
widget_->setEnabled((bool)bufferview());
scheduleUpdate();
}
widget_->masterPerspectiveCB->setEnabled(buffer().parent());
updateTitle();
@ -447,8 +443,9 @@ void GuiViewSource::updateView()
void GuiViewSource::enableView(bool enable)
{
widget_->setBufferView(bufferview());
widget_->updateDefaultFormat();
widget_->setEnabled((bool)bufferview());
if (bufferview())
widget_->updateDefaultFormat(*bufferview());
if (!enable)
// In the opposite case, updateView() will be called anyway.
widget_->contentsChanged();

View File

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