bug-fix: QTextDocument.clearUndoRedoStacks() will crash in VImagePreviewer

This commit is contained in:
Le Tan 2017-09-08 21:41:19 +08:00
parent f050d7d814
commit e55b0af00e
4 changed files with 68 additions and 28 deletions

View File

@ -48,6 +48,7 @@ void VImagePreviewer::kickOffPreview(const QVector<VElementRegion> &p_imageRegio
Q_ASSERT(m_imageRegions.isEmpty());
Q_ASSERT(m_previewImages.isEmpty());
Q_ASSERT(m_imageCache.isEmpty());
emit previewFinished();
return;
}
@ -60,6 +61,8 @@ void VImagePreviewer::kickOffPreview(const QVector<VElementRegion> &p_imageRegio
shrinkImageCache();
m_isPreviewing = false;
emit previewFinished();
}
void VImagePreviewer::previewImages()
@ -541,6 +544,7 @@ bool VImagePreviewer::updateImageWidth(QTextImageFormat &p_format)
void VImagePreviewer::updatePreviewImageWidth()
{
if (!m_previewEnabled) {
emit previewWidthUpdated();
return;
}
@ -568,6 +572,10 @@ void VImagePreviewer::doUpdatePreviewImageWidth()
if (updated) {
emit m_edit->statusChanged();
}
qDebug() << "update preview image width" << updated;
emit previewWidthUpdated();
}
bool VImagePreviewer::updatePreviewImageWidthOfBlock(const QTextBlock &p_block,
@ -631,32 +639,9 @@ void VImagePreviewer::shrinkImageCache()
void VImagePreviewer::saveEditStatus(EditStatus &p_status) const
{
p_status.m_modified = m_edit->isModified();
p_status.m_undoAvailable = m_document->isUndoAvailable();
p_status.m_redoAvailable = m_document->isRedoAvailable();
}
void VImagePreviewer::restoreEditStatus(const EditStatus &p_status)
{
int st = 0;
if (!p_status.m_undoAvailable) {
st |= 1;
}
if (!p_status.m_redoAvailable) {
st |= 2;
}
if (st > 0) {
QTextDocument::Stacks stack = QTextDocument::UndoStack;
if (st == 2) {
stack = QTextDocument::RedoStack;
} else if (st == 3) {
stack = QTextDocument::UndoAndRedoStacks;
}
m_document->clearUndoRedoStacks(stack);
}
// Clear undo and redo stacks will change the state to modified.
m_edit->setModified(p_status.m_modified);
}

View File

@ -48,6 +48,12 @@ signals:
// Request highlighter to update image links.
void requestUpdateImageLinks();
// Emit after finishing previewing.
void previewFinished();
// Emit after updating preview width.
void previewWidthUpdated();
private:
struct ImageInfo
{
@ -116,13 +122,11 @@ private:
struct EditStatus
{
EditStatus()
: m_modified(false), m_undoAvailable(false), m_redoAvailable(false)
: m_modified(false)
{
}
bool m_modified;
bool m_undoAvailable;
bool m_redoAvailable;
};
// Kick off new preview of m_imageRegions.

View File

@ -16,13 +16,17 @@
extern VConfigManager *g_config;
extern VNote *g_vnote;
const int VMdEdit::c_numberOfAysncJobs = 2;
VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
QWidget *p_parent)
: VEdit(p_file, p_parent), m_mdHighlighter(NULL)
: VEdit(p_file, p_parent), m_mdHighlighter(NULL), m_freshEdit(true),
m_finishedAsyncJobs(c_numberOfAysncJobs)
{
V_ASSERT(p_file->getDocType() == DocType::Markdown);
setAcceptRichText(false);
m_mdHighlighter = new HGMarkdownHighlighter(g_config->getMdHighlightingStyles(),
g_config->getCodeBlockStyles(),
g_config->getMarkdownHighlightInterval(),
@ -45,6 +49,19 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type,
m_imagePreviewer, &VImagePreviewer::imageLinksChanged);
connect(m_imagePreviewer, &VImagePreviewer::requestUpdateImageLinks,
m_mdHighlighter, &HGMarkdownHighlighter::updateHighlight);
connect(m_imagePreviewer, &VImagePreviewer::previewFinished,
this, [this](){
if (m_freshEdit) {
finishOneAsyncJob(0);
}
});
connect(m_imagePreviewer, &VImagePreviewer::previewWidthUpdated,
this, [this](){
if (m_freshEdit) {
finishOneAsyncJob(1);
}
});
m_editOps = new VMdEditOperations(this, m_file);
@ -80,11 +97,19 @@ void VMdEdit::beginEdit()
initInitImages();
setReadOnly(false);
setModified(false);
// Request update outline.
generateEditOutline();
if (m_freshEdit) {
// Will set to false when all async jobs completed.
setReadOnly(true);
// Disable and clear undo stacks temporary.
setUndoRedoEnabled(false);
} else {
setReadOnly(false);
}
}
void VMdEdit::endEdit()
@ -634,3 +659,21 @@ bool VMdEdit::jumpTitle(bool p_forward, int p_relativeLevel, int p_repeat)
return false;
}
void VMdEdit::finishOneAsyncJob(int p_idx)
{
Q_ASSERT(m_freshEdit);
if (m_finishedAsyncJobs[p_idx]) {
return;
}
m_finishedAsyncJobs[p_idx] = true;
if (-1 == m_finishedAsyncJobs.indexOf(false)) {
// All jobs finished.
m_freshEdit = false;
setUndoRedoEnabled(true);
setReadOnly(false);
setModified(false);
emit statusChanged();
}
}

View File

@ -100,6 +100,8 @@ private:
bool getPreviewImageRegionOfBlock(const QTextBlock &p_block,
QVector<Region> &p_regions) const;
void finishOneAsyncJob(int p_idx);
HGMarkdownHighlighter *m_mdHighlighter;
VCodeBlockHighlightHelper *m_cbHighlighter;
VImagePreviewer *m_imagePreviewer;
@ -111,6 +113,12 @@ private:
QVector<ImageLink> m_initImages;
QVector<VHeader> m_headers;
bool m_freshEdit;
QVector<bool> m_finishedAsyncJobs;
static const int c_numberOfAysncJobs;
};
#endif // VMDEDIT_H