| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405 | 
							- #include "vmdeditor.h"
 
- #include <QtWidgets>
 
- #include <QMenu>
 
- #include <QDebug>
 
- #include <QScopedPointer>
 
- #include <QClipboard>
 
- #include "vdocument.h"
 
- #include "utils/veditutils.h"
 
- #include "vedittab.h"
 
- #include "pegmarkdownhighlighter.h"
 
- #include "vcodeblockhighlighthelper.h"
 
- #include "vmdeditoperations.h"
 
- #include "vtableofcontent.h"
 
- #include "utils/veditutils.h"
 
- #include "dialog/vselectdialog.h"
 
- #include "dialog/vconfirmdeletiondialog.h"
 
- #include "vtextblockdata.h"
 
- #include "vorphanfile.h"
 
- #include "vnotefile.h"
 
- #include "vpreviewmanager.h"
 
- #include "utils/viconutils.h"
 
- #include "dialog/vcopytextashtmldialog.h"
 
- #include "utils/vwebutils.h"
 
- #include "dialog/vinsertlinkdialog.h"
 
- extern VWebUtils *g_webUtils;
 
- extern VConfigManager *g_config;
 
- VMdEditor::VMdEditor(VFile *p_file,
 
-                      VDocument *p_doc,
 
-                      MarkdownConverterType p_type,
 
-                      QWidget *p_parent)
 
-     : VTextEdit(p_parent),
 
-       VEditor(p_file, this),
 
-       m_pegHighlighter(NULL),
 
-       m_freshEdit(true),
 
-       m_textToHtmlDialog(NULL),
 
-       m_zoomDelta(0),
 
-       m_editTab(NULL),
 
-       m_copyTimeStamp(0)
 
- {
 
-     Q_ASSERT(p_file->getDocType() == DocType::Markdown);
 
-     VEditor::init();
 
-     // Hook functions from VEditor.
 
-     connect(this, &VTextEdit::cursorPositionChanged,
 
-             this, [this]() {
 
-                 highlightOnCursorPositionChanged();
 
-             });
 
-     connect(this, &VTextEdit::selectionChanged,
 
-             this, [this]() {
 
-                 highlightSelectedWord();
 
-             });
 
-     // End.
 
-     setReadOnly(true);
 
-     m_pegHighlighter = new PegMarkdownHighlighter(document());
 
-     m_pegHighlighter->init(g_config->getMdHighlightingStyles(),
 
-                            g_config->getCodeBlockStyles(),
 
-                            g_config->getEnableMathjax(),
 
-                            g_config->getMarkdownHighlightInterval());
 
-     connect(m_pegHighlighter, &PegMarkdownHighlighter::headersUpdated,
 
-             this, &VMdEditor::updateHeaders);
 
-     // After highlight, the cursor may trun into non-visible. We should make it visible
 
-     // in this case.
 
-     connect(m_pegHighlighter, &PegMarkdownHighlighter::highlightCompleted,
 
-             this, [this]() {
 
-             makeBlockVisible(textCursor().block());
 
-             if (m_freshEdit) {
 
-                 m_freshEdit = false;
 
-                 emit m_object->ready();
 
-             }
 
-     });
 
-     m_cbHighlighter = new VCodeBlockHighlightHelper(m_pegHighlighter,
 
-                                                     p_doc,
 
-                                                     p_type);
 
-     m_previewMgr = new VPreviewManager(this, m_pegHighlighter);
 
-     connect(m_pegHighlighter, &PegMarkdownHighlighter::imageLinksUpdated,
 
-             m_previewMgr, &VPreviewManager::updateImageLinks);
 
-     connect(m_previewMgr, &VPreviewManager::requestUpdateImageLinks,
 
-             m_pegHighlighter, &PegMarkdownHighlighter::updateHighlight);
 
-     m_editOps = new VMdEditOperations(this, m_file);
 
-     connect(m_editOps, &VEditOperations::statusMessage,
 
-             m_object, &VEditorObject::statusMessage);
 
-     connect(m_editOps, &VEditOperations::vimStatusUpdated,
 
-             m_object, &VEditorObject::vimStatusUpdated);
 
-     connect(this, &VTextEdit::cursorPositionChanged,
 
-             this, &VMdEditor::updateCurrentHeader);
 
-     connect(this, &VTextEdit::cursorPositionChanged,
 
-             m_object, &VEditorObject::cursorPositionChanged);
 
-     setDisplayScaleFactor(VUtils::calculateScaleFactor());
 
-     updateFontAndPalette();
 
-     updateConfig();
 
- }
 
- void VMdEditor::updateFontAndPalette()
 
- {
 
-     QFont font(g_config->getMdEditFont());
 
-     setFont(font);
 
-     const QPalette &palette = g_config->getMdEditPalette();
 
-     /*
 
-         Do not use this function in conjunction with Qt Style Sheets. When
 
-         using style sheets, the palette of a widget can be customized using
 
-         the "color", "background-color", "selection-color",
 
-         "selection-background-color" and "alternate-background-color".
 
-     */
 
-     // setPalette(palette);
 
-     // setTextColor(palette.color(QPalette::Text));
 
-     // Only this could override the font-family set of QWidget in QSS.
 
-     setFontAndPaletteByStyleSheet(font, palette);
 
-     updateLineNumberAreaWidth(QFontMetrics(font));
 
- }
 
- void VMdEditor::beginEdit()
 
- {
 
-     updateConfig();
 
-     initInitImages();
 
-     setModified(false);
 
-     setReadOnlyAndHighlightCurrentLine(false);
 
-     emit statusChanged();
 
-     if (m_freshEdit) {
 
-         m_pegHighlighter->updateHighlight();
 
-         relayout();
 
-     } else {
 
-         updateHeaders(m_pegHighlighter->getHeaderRegions());
 
-     }
 
- }
 
- void VMdEditor::endEdit()
 
- {
 
-     setReadOnlyAndHighlightCurrentLine(true);
 
-     clearUnusedImages();
 
- }
 
- void VMdEditor::saveFile()
 
- {
 
-     Q_ASSERT(m_file->isModifiable());
 
-     if (!document()->isModified()) {
 
-         return;
 
-     }
 
-     m_file->setContent(toPlainText());
 
-     setModified(false);
 
-     clearUnusedImages();
 
-     initInitImages();
 
- }
 
- void VMdEditor::reloadFile()
 
- {
 
-     bool readonly = isReadOnly();
 
-     setReadOnly(true);
 
-     const QString &content = m_file->getContent();
 
-     setPlainText(content);
 
-     setModified(false);
 
-     m_pegHighlighter->updateHighlightFast();
 
-     m_freshEdit = true;
 
-     setReadOnly(readonly);
 
-     refreshPreview();
 
- }
 
- bool VMdEditor::scrollToBlock(int p_blockNumber)
 
- {
 
-     QTextBlock block = document()->findBlockByNumber(p_blockNumber);
 
-     if (block.isValid()) {
 
-         VEditUtils::scrollBlockInPage(this, block.blockNumber(), 0);
 
-         moveCursor(QTextCursor::EndOfBlock);
 
-         return true;
 
-     }
 
-     return false;
 
- }
 
- // Get the visual offset of a block.
 
- #define GETVISUALOFFSETY(x) (contentOffsetY() + (int)(x).y())
 
- void VMdEditor::makeBlockVisible(const QTextBlock &p_block)
 
- {
 
-     if (!p_block.isValid() || !p_block.isVisible()) {
 
-         return;
 
-     }
 
-     QScrollBar *vbar = verticalScrollBar();
 
-     if (!vbar || (vbar->minimum() == vbar->maximum())) {
 
-         // No vertical scrollbar. No need to scroll.
 
-         return;
 
-     }
 
-     int height = rect().height();
 
-     QScrollBar *hbar = horizontalScrollBar();
 
-     if (hbar && (hbar->minimum() != hbar->maximum())) {
 
-         height -= hbar->height();
 
-     }
 
-     bool moved = false;
 
-     QAbstractTextDocumentLayout *layout = document()->documentLayout();
 
-     QRectF rt = layout->blockBoundingRect(p_block);
 
-     int y = GETVISUALOFFSETY(rt);
 
-     int rectHeight = (int)rt.height();
 
-     // Handle the case rectHeight >= height.
 
-     if (rectHeight >= height) {
 
-         if (y < 0) {
 
-             // Need to scroll up.
 
-             while (y + rectHeight < height && vbar->value() > vbar->minimum()) {
 
-                 moved = true;
 
-                 vbar->setValue(vbar->value() - vbar->singleStep());
 
-                 rt = layout->blockBoundingRect(p_block);
 
-                 rectHeight = (int)rt.height();
 
-                 y = GETVISUALOFFSETY(rt);
 
-             }
 
-         } else if (y > 0) {
 
-             // Need to scroll down.
 
-             while (y > 0 && vbar->value() < vbar->maximum()) {
 
-                 moved = true;
 
-                 vbar->setValue(vbar->value() + vbar->singleStep());
 
-                 rt = layout->blockBoundingRect(p_block);
 
-                 rectHeight = (int)rt.height();
 
-                 y = GETVISUALOFFSETY(rt);
 
-             }
 
-             if (y < 0) {
 
-                 // One step back.
 
-                 moved = true;
 
-                 vbar->setValue(vbar->value() - vbar->singleStep());
 
-             }
 
-         }
 
-         return;
 
-     }
 
-     // There is an extra line leading in the layout, so there will always be a scroll
 
-     // action to scroll the page down.
 
-     while (y < 0 && vbar->value() > vbar->minimum()) {
 
-         moved = true;
 
-         vbar->setValue(vbar->value() - vbar->singleStep());
 
-         rt = layout->blockBoundingRect(p_block);
 
-         y = GETVISUALOFFSETY(rt);
 
-     }
 
-     if (moved) {
 
-         return;
 
-     }
 
-     while (y + rectHeight > height && vbar->value() < vbar->maximum()) {
 
-         vbar->setValue(vbar->value() + vbar->singleStep());
 
-         rt = layout->blockBoundingRect(p_block);
 
-         rectHeight = (int)rt.height();
 
-         y = GETVISUALOFFSETY(rt);
 
-     }
 
- }
 
- void VMdEditor::contextMenuEvent(QContextMenuEvent *p_event)
 
- {
 
-     QScopedPointer<QMenu> menu(createStandardContextMenu());
 
-     menu->setToolTipsVisible(true);
 
-     if (m_editTab && m_editTab->isEditMode()) {
 
-         const QList<QAction *> actions = menu->actions();
 
-         if (textCursor().hasSelection()) {
 
-             initCopyAsMenu(actions.isEmpty() ? NULL : actions.last(), menu.data());
 
-         } else {
 
-             QAction *saveExitAct = new QAction(VIconUtils::menuIcon(":/resources/icons/save_exit.svg"),
 
-                                                tr("&Save Changes And Read"),
 
-                                                menu.data());
 
-             saveExitAct->setToolTip(tr("Save changes and exit edit mode"));
 
-             connect(saveExitAct, &QAction::triggered,
 
-                     this, [this]() {
 
-                         emit m_object->saveAndRead();
 
-                     });
 
-             QAction *discardExitAct = new QAction(VIconUtils::menuIcon(":/resources/icons/discard_exit.svg"),
 
-                                                   tr("&Discard Changes And Read"),
 
-                                                   menu.data());
 
-             discardExitAct->setToolTip(tr("Discard changes and exit edit mode"));
 
-             connect(discardExitAct, &QAction::triggered,
 
-                     this, [this]() {
 
-                         emit m_object->discardAndRead();
 
-                     });
 
-             QAction *toggleLivePreviewAct = new QAction(tr("Live Preview for Diagrams"), menu.data());
 
-             toggleLivePreviewAct->setToolTip(tr("Toggle live preview panel for diagrams"));
 
-             connect(toggleLivePreviewAct, &QAction::triggered,
 
-                     this, [this]() {
 
-                         m_editTab->toggleLivePreview();
 
-                     });
 
-             menu->insertAction(actions.isEmpty() ? NULL : actions[0], toggleLivePreviewAct);
 
-             menu->insertAction(toggleLivePreviewAct, discardExitAct);
 
-             menu->insertAction(discardExitAct, saveExitAct);
 
-             menu->insertSeparator(toggleLivePreviewAct);
 
-             if (!actions.isEmpty()) {
 
-                 menu->insertSeparator(actions[0]);
 
-             }
 
-         }
 
-         QClipboard *clipboard = QApplication::clipboard();
 
-         const QMimeData *mimeData = clipboard->mimeData();
 
-         if (mimeData->hasText()) {
 
-             initPasteAsBlockQuoteMenu(menu.data());
 
-         }
 
-     }
 
-     menu->exec(p_event->globalPos());
 
- }
 
- void VMdEditor::mousePressEvent(QMouseEvent *p_event)
 
- {
 
-     if (handleMousePressEvent(p_event)) {
 
-         return;
 
-     }
 
-     VTextEdit::mousePressEvent(p_event);
 
-     emit m_object->mousePressed(p_event);
 
- }
 
- void VMdEditor::mouseReleaseEvent(QMouseEvent *p_event)
 
- {
 
-     if (handleMouseReleaseEvent(p_event)) {
 
-         return;
 
-     }
 
-     VTextEdit::mouseReleaseEvent(p_event);
 
-     emit m_object->mouseReleased(p_event);
 
- }
 
- void VMdEditor::mouseMoveEvent(QMouseEvent *p_event)
 
- {
 
-     if (handleMouseMoveEvent(p_event)) {
 
-         return;
 
-     }
 
-     VTextEdit::mouseMoveEvent(p_event);
 
-     emit m_object->mouseMoved(p_event);
 
- }
 
- QVariant VMdEditor::inputMethodQuery(Qt::InputMethodQuery p_query) const
 
- {
 
-     QVariant ret;
 
-     if (handleInputMethodQuery(p_query, ret)) {
 
-         return ret;
 
-     }
 
-     return VTextEdit::inputMethodQuery(p_query);
 
- }
 
- bool VMdEditor::isBlockVisible(const QTextBlock &p_block)
 
- {
 
-     if (!p_block.isValid() || !p_block.isVisible()) {
 
-         return false;
 
-     }
 
-     QScrollBar *vbar = verticalScrollBar();
 
-     if (!vbar || !vbar->isVisible()) {
 
-         // No vertical scrollbar.
 
-         return true;
 
-     }
 
-     int height = rect().height();
 
-     QScrollBar *hbar = horizontalScrollBar();
 
-     if (hbar && hbar->isVisible()) {
 
-         height -= hbar->height();
 
-     }
 
-     QAbstractTextDocumentLayout *layout = document()->documentLayout();
 
-     QRectF rt = layout->blockBoundingRect(p_block);
 
-     int y = GETVISUALOFFSETY(rt);
 
-     int rectHeight = (int)rt.height();
 
-     return (y >= 0 && y < height) || (y < 0 && y + rectHeight > 0);
 
- }
 
- static void addHeaderSequence(QVector<int> &p_sequence, int p_level, int p_baseLevel)
 
- {
 
-     Q_ASSERT(p_level >= 1 && p_level < p_sequence.size());
 
-     if (p_level < p_baseLevel) {
 
-         p_sequence.fill(0);
 
-         return;
 
-     }
 
-     ++p_sequence[p_level];
 
-     for (int i = p_level + 1; i < p_sequence.size(); ++i) {
 
-         p_sequence[i] = 0;
 
-     }
 
- }
 
- static QString headerSequenceStr(const QVector<int> &p_sequence)
 
- {
 
-     QString res;
 
-     for (int i = 1; i < p_sequence.size(); ++i) {
 
-         if (p_sequence[i] != 0) {
 
-             res = res + QString::number(p_sequence[i]) + '.';
 
-         } else if (res.isEmpty()) {
 
-             continue;
 
-         } else {
 
-             break;
 
-         }
 
-     }
 
-     return res;
 
- }
 
- static void insertSequenceToHeader(QTextCursor& p_cursor,
 
-                                    const QTextBlock &p_block,
 
-                                    QRegExp &p_reg,
 
-                                    QRegExp &p_preReg,
 
-                                    const QString &p_seq)
 
- {
 
-     if (!p_block.isValid()) {
 
-         return;
 
-     }
 
-     QString text = p_block.text();
 
-     bool matched = p_reg.exactMatch(text);
 
-     Q_ASSERT(matched);
 
-     matched = p_preReg.exactMatch(text);
 
-     Q_ASSERT(matched);
 
-     int start = p_reg.cap(1).length() + 1;
 
-     int end = p_preReg.cap(1).length();
 
-     Q_ASSERT(start <= end);
 
-     p_cursor.setPosition(p_block.position() + start);
 
-     if (start != end) {
 
-         p_cursor.setPosition(p_block.position() + end, QTextCursor::KeepAnchor);
 
-     }
 
-     if (p_seq.isEmpty()) {
 
-         p_cursor.removeSelectedText();
 
-     } else {
 
-         p_cursor.insertText(p_seq + ' ');
 
-     }
 
- }
 
- void VMdEditor::updateHeaderSequenceByConfigChange()
 
- {
 
-     updateHeadersHelper(m_pegHighlighter->getHeaderRegions(), true);
 
- }
 
- void VMdEditor::updateHeadersHelper(const QVector<VElementRegion> &p_headerRegions, bool p_configChanged)
 
- {
 
-     QTextDocument *doc = document();
 
-     QVector<VTableOfContentItem> headers;
 
-     QVector<int> headerBlockNumbers;
 
-     QVector<QString> headerSequences;
 
-     if (!p_headerRegions.isEmpty()) {
 
-         headers.reserve(p_headerRegions.size());
 
-         headerBlockNumbers.reserve(p_headerRegions.size());
 
-         headerSequences.reserve(p_headerRegions.size());
 
-     }
 
-     // Assume that each block contains only one line
 
-     // Only support # syntax for now
 
-     QRegExp headerReg(VUtils::c_headerRegExp);
 
-     int baseLevel = -1;
 
-     for (auto const & reg : p_headerRegions) {
 
-         QTextBlock block = doc->findBlock(reg.m_startPos);
 
-         if (!block.isValid()) {
 
-             continue;
 
-         }
 
-         if (!block.contains(reg.m_endPos - 1)) {
 
-             qWarning() << "header accross multiple blocks, starting from block"
 
-                        << block.blockNumber()
 
-                        << block.text();
 
-         }
 
-         if (headerReg.exactMatch(block.text())) {
 
-             int level = headerReg.cap(1).length();
 
-             VTableOfContentItem header(headerReg.cap(2).trimmed(),
 
-                                        level,
 
-                                        block.blockNumber(),
 
-                                        headers.size());
 
-             headers.append(header);
 
-             headerBlockNumbers.append(block.blockNumber());
 
-             headerSequences.append(headerReg.cap(3));
 
-             if (baseLevel == -1) {
 
-                 baseLevel = level;
 
-             } else if (baseLevel > level) {
 
-                 baseLevel = level;
 
-             }
 
-         }
 
-     }
 
-     m_headers.clear();
 
-     bool autoSequence = m_config.m_enableHeadingSequence
 
-                         && !isReadOnly()
 
-                         && m_file->isModifiable();
 
-     int headingSequenceBaseLevel = g_config->getHeadingSequenceBaseLevel();
 
-     if (headingSequenceBaseLevel < 1 || headingSequenceBaseLevel > 6) {
 
-         headingSequenceBaseLevel = 1;
 
-     }
 
-     QVector<int> seqs(7, 0);
 
-     QRegExp preReg(VUtils::c_headerPrefixRegExp);
 
-     int curLevel = baseLevel - 1;
 
-     QTextCursor cursor(doc);
 
-     if(autoSequence || p_configChanged) {
 
-         cursor.beginEditBlock();
 
-     }
 
-     for (int i = 0; i < headers.size(); ++i) {
 
-         VTableOfContentItem &item = headers[i];
 
-         while (item.m_level > curLevel + 1) {
 
-             curLevel += 1;
 
-             // Insert empty level which is an invalid header.
 
-             m_headers.append(VTableOfContentItem(c_emptyHeaderName,
 
-                                                  curLevel,
 
-                                                  -1,
 
-                                                  m_headers.size()));
 
-             if (autoSequence || p_configChanged) {
 
-                 addHeaderSequence(seqs, curLevel, headingSequenceBaseLevel);
 
-             }
 
-         }
 
-         item.m_index = m_headers.size();
 
-         m_headers.append(item);
 
-         curLevel = item.m_level;
 
-         if (autoSequence || p_configChanged) {
 
-             addHeaderSequence(seqs, item.m_level, headingSequenceBaseLevel);
 
-             QString seqStr = autoSequence ? headerSequenceStr(seqs) : "";
 
-             if (headerSequences[i] != seqStr) {
 
-                 // Insert correct sequence.
 
-                 insertSequenceToHeader(cursor,
 
-                                        doc->findBlockByNumber(headerBlockNumbers[i]),
 
-                                        headerReg,
 
-                                        preReg,
 
-                                        seqStr);
 
-             }
 
-         }
 
-     }
 
-     if (autoSequence || p_configChanged) {
 
-         cursor.endEditBlock();
 
-     }
 
-     emit headersChanged(m_headers);
 
-     updateCurrentHeader();
 
- }
 
- void VMdEditor::updateHeaders(const QVector<VElementRegion> &p_headerRegions)
 
- {
 
-     updateHeadersHelper(p_headerRegions, false);
 
- }
 
- void VMdEditor::updateCurrentHeader()
 
- {
 
-     emit currentHeaderChanged(textCursor().block().blockNumber());
 
- }
 
- void VMdEditor::initInitImages()
 
- {
 
-     m_initImages = VUtils::fetchImagesFromMarkdownFile(m_file,
 
-                                                        ImageLink::LocalRelativeInternal);
 
- }
 
- void VMdEditor::clearUnusedImages()
 
- {
 
-     QVector<ImageLink> images = VUtils::fetchImagesFromMarkdownFile(m_file,
 
-                                                                     ImageLink::LocalRelativeInternal);
 
-     QSet<QString> unusedImages;
 
-     if (!m_insertedImages.isEmpty()) {
 
-         for (int i = 0; i < m_insertedImages.size(); ++i) {
 
-             const ImageLink &link = m_insertedImages[i];
 
-             if (link.m_type != ImageLink::LocalRelativeInternal) {
 
-                 continue;
 
-             }
 
-             int j;
 
-             for (j = 0; j < images.size(); ++j) {
 
-                 if (VUtils::equalPath(link.m_path, images[j].m_path)) {
 
-                     break;
 
-                 }
 
-             }
 
-             // This inserted image is no longer in the file.
 
-             if (j == images.size()) {
 
-                 unusedImages.insert(link.m_path);
 
-             }
 
-         }
 
-         m_insertedImages.clear();
 
-     }
 
-     for (int i = 0; i < m_initImages.size(); ++i) {
 
-         const ImageLink &link = m_initImages[i];
 
-         V_ASSERT(link.m_type == ImageLink::LocalRelativeInternal);
 
-         int j;
 
-         for (j = 0; j < images.size(); ++j) {
 
-             if (VUtils::equalPath(link.m_path, images[j].m_path)) {
 
-                 break;
 
-             }
 
-         }
 
-         // Original local relative image is no longer in the file.
 
-         if (j == images.size()) {
 
-             unusedImages.insert(link.m_path);
 
-         }
 
-     }
 
-     if (!unusedImages.isEmpty()) {
 
-         if (g_config->getConfirmImagesCleanUp()) {
 
-             QVector<ConfirmItemInfo> items;
 
-             for (auto const & img : unusedImages) {
 
-                 items.push_back(ConfirmItemInfo(img,
 
-                                                 img,
 
-                                                 img,
 
-                                                 NULL));
 
-             }
 
-             QString text = tr("Following images seems not to be used in this note anymore. "
 
-                               "Please confirm the deletion of these images.");
 
-             QString info = tr("Deleted files could be found in the recycle "
 
-                               "bin of this note.<br>"
 
-                               "Click \"Cancel\" to leave them untouched.");
 
-             VConfirmDeletionDialog dialog(tr("Confirm Cleaning Up Unused Images"),
 
-                                           text,
 
-                                           info,
 
-                                           items,
 
-                                           true,
 
-                                           true,
 
-                                           true,
 
-                                           this);
 
-             unusedImages.clear();
 
-             if (dialog.exec()) {
 
-                 items = dialog.getConfirmedItems();
 
-                 g_config->setConfirmImagesCleanUp(dialog.getAskAgainEnabled());
 
-                 for (auto const & item : items) {
 
-                     unusedImages.insert(item.m_name);
 
-                 }
 
-             }
 
-         }
 
-         for (auto const & item : unusedImages) {
 
-             bool ret = false;
 
-             if (m_file->getType() == FileType::Note) {
 
-                 const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)m_file);
 
-                 ret = VUtils::deleteFile(tmpFile->getNotebook(), item, false);
 
-             } else if (m_file->getType() == FileType::Orphan) {
 
-                 const VOrphanFile *tmpFile = dynamic_cast<const VOrphanFile *>((VFile *)m_file);
 
-                 ret = VUtils::deleteFile(tmpFile, item, false);
 
-             } else {
 
-                 Q_ASSERT(false);
 
-             }
 
-             if (!ret) {
 
-                 qWarning() << "fail to delete unused original image" << item;
 
-             } else {
 
-                 qDebug() << "delete unused image" << item;
 
-             }
 
-         }
 
-     }
 
-     m_initImages.clear();
 
- }
 
- void VMdEditor::keyPressEvent(QKeyEvent *p_event)
 
- {
 
-     int key = p_event->key();
 
-     int modifiers = p_event->modifiers();
 
-     switch (key) {
 
-     case Qt::Key_Minus:
 
-     case Qt::Key_Underscore:
 
-         // Zoom out.
 
-         if (modifiers & Qt::ControlModifier) {
 
-             zoomPage(false);
 
-             return;
 
-         }
 
-         break;
 
-     case Qt::Key_Plus:
 
-     case Qt::Key_Equal:
 
-         // Zoom in.
 
-         if (modifiers & Qt::ControlModifier) {
 
-             zoomPage(true);
 
-             return;
 
-         }
 
-         break;
 
-     case Qt::Key_0:
 
-         // Restore zoom.
 
-         if (modifiers & Qt::ControlModifier) {
 
-             if (m_zoomDelta > 0) {
 
-                 zoomPage(false, m_zoomDelta);
 
-             } else if (m_zoomDelta < 0) {
 
-                 zoomPage(true, -m_zoomDelta);
 
-             }
 
-             return;
 
-         }
 
-         break;
 
-     default:
 
-         break;
 
-     }
 
-     if (m_editOps && m_editOps->handleKeyPressEvent(p_event)) {
 
-         return;
 
-     }
 
-     // Esc to exit edit mode when Vim is disabled.
 
-     if (key == Qt::Key_Escape) {
 
-         emit m_object->discardAndRead();
 
-         return;
 
-     }
 
-     VTextEdit::keyPressEvent(p_event);
 
- }
 
- bool VMdEditor::canInsertFromMimeData(const QMimeData *p_source) const
 
- {
 
-     return p_source->hasImage()
 
-            || p_source->hasUrls()
 
-            || VTextEdit::canInsertFromMimeData(p_source);
 
- }
 
- void VMdEditor::insertFromMimeData(const QMimeData *p_source)
 
- {
 
-     if (p_source->hasHtml()) {
 
-         // Handle <img>.
 
-         QRegExp reg("<img ([^>]*)src=\"([^\"]+)\"([^>]*)>");
 
-         QString html(p_source->html());
 
-         if (reg.indexIn(html) != -1 && VUtils::onlyHasImgInHtml(html)) {
 
-             if (p_source->hasImage()) {
 
-                 // Both image data and URL are embedded.
 
-                 VSelectDialog dialog(tr("Insert From Clipboard"), this);
 
-                 dialog.addSelection(tr("Insert From URL"), 0);
 
-                 dialog.addSelection(tr("Insert From Image Data"), 1);
 
-                 dialog.addSelection(tr("Insert As Image Link"), 2);
 
-                 if (dialog.exec() == QDialog::Accepted) {
 
-                     int selection = dialog.getSelection();
 
-                     if (selection == 1) {
 
-                         // Insert from image data.
 
-                         m_editOps->insertImageFromMimeData(p_source);
 
-                         return;
 
-                     } else if (selection == 2) {
 
-                         // Insert as link.
 
-                         insertImageLink("", reg.cap(2));
 
-                         return;
 
-                     }
 
-                 } else {
 
-                     return;
 
-                 }
 
-             }
 
-             m_editOps->insertImageFromURL(QUrl(reg.cap(2)));
 
-             return;
 
-         }
 
-     }
 
-     VSelectDialog dialog(tr("Insert From Clipboard"), this);
 
-     dialog.addSelection(tr("Insert As Image"), 0);
 
-     dialog.addSelection(tr("Insert As Text"), 1);
 
-     dialog.addSelection(tr("Insert As Image Link"), 2);
 
-     if (p_source->hasImage()) {
 
-         // Image data in the clipboard
 
-         if (p_source->hasText()) {
 
-             if (dialog.exec() == QDialog::Accepted) {
 
-                 int selection = dialog.getSelection();
 
-                 if (selection == 1) {
 
-                     // Insert as text.
 
-                     Q_ASSERT(p_source->hasText() && p_source->hasImage());
 
-                     VTextEdit::insertFromMimeData(p_source);
 
-                     return;
 
-                 } else if (selection == 2) {
 
-                     // Insert as link.
 
-                     insertImageLink("", p_source->text());
 
-                     return;
 
-                 }
 
-             } else {
 
-                 return;
 
-             }
 
-         }
 
-         m_editOps->insertImageFromMimeData(p_source);
 
-         return;
 
-     }
 
-     if (p_source->hasUrls()) {
 
-         QList<QUrl> urls = p_source->urls();
 
-         if (urls.size() == 1 && VUtils::isImageURL(urls[0])) {
 
-             if (dialog.exec() == QDialog::Accepted) {
 
-                 // FIXME: After calling dialog.exec(), p_source->hasUrl() returns false.
 
-                 int selection = dialog.getSelection();
 
-                 if (selection == 0) {
 
-                     // Insert as image.
 
-                     m_editOps->insertImageFromURL(urls[0]);
 
-                     return;
 
-                 } else if (selection == 2) {
 
-                     // Insert as link.
 
-                     insertImageLink("", urls[0].toString(QUrl::FullyEncoded));
 
-                     return;
 
-                 }
 
-                 QMimeData newSource;
 
-                 newSource.setUrls(urls);
 
-                 VTextEdit::insertFromMimeData(&newSource);
 
-                 return;
 
-             } else {
 
-                 return;
 
-             }
 
-         }
 
-     }
 
-     if (p_source->hasText()) {
 
-         QString text = p_source->text();
 
-         if (VUtils::isImageURLText(text)) {
 
-             // The text is a URL to an image.
 
-             if (dialog.exec() == QDialog::Accepted) {
 
-                 int selection = dialog.getSelection();
 
-                 if (selection == 0) {
 
-                     // Insert as image.
 
-                     QUrl url;
 
-                     if (QFileInfo::exists(text)) {
 
-                         url = QUrl::fromLocalFile(text);
 
-                     } else {
 
-                         url = QUrl(text);
 
-                     }
 
-                     if (url.isValid()) {
 
-                         m_editOps->insertImageFromURL(url);
 
-                     }
 
-                     return;
 
-                 } else if (selection == 2) {
 
-                     // Insert as link.
 
-                     insertImageLink("", text);
 
-                     return;
 
-                 }
 
-             } else {
 
-                 return;
 
-             }
 
-         }
 
-         Q_ASSERT(p_source->hasText());
 
-     }
 
-     VTextEdit::insertFromMimeData(p_source);
 
- }
 
- void VMdEditor::imageInserted(const QString &p_path, const QString &p_url)
 
- {
 
-     ImageLink link;
 
-     link.m_path = p_path;
 
-     link.m_url = p_url;
 
-     if (m_file->useRelativeImageFolder()) {
 
-         link.m_type = ImageLink::LocalRelativeInternal;
 
-     } else {
 
-         link.m_type = ImageLink::LocalAbsolute;
 
-     }
 
-     m_insertedImages.append(link);
 
- }
 
- bool VMdEditor::scrollToHeader(int p_blockNumber)
 
- {
 
-     if (p_blockNumber < 0) {
 
-         return false;
 
-     }
 
-     return scrollToBlock(p_blockNumber);
 
- }
 
- int VMdEditor::indexOfCurrentHeader() const
 
- {
 
-     if (m_headers.isEmpty()) {
 
-         return -1;
 
-     }
 
-     int blockNumber = textCursor().block().blockNumber();
 
-     for (int i = m_headers.size() - 1; i >= 0; --i) {
 
-         if (!m_headers[i].isEmpty()
 
-             && m_headers[i].m_blockNumber <= blockNumber) {
 
-             return i;
 
-         }
 
-     }
 
-     return -1;
 
- }
 
- bool VMdEditor::jumpTitle(bool p_forward, int p_relativeLevel, int p_repeat)
 
- {
 
-     if (m_headers.isEmpty()) {
 
-         return false;
 
-     }
 
-     QTextCursor cursor = textCursor();
 
-     int cursorLine = cursor.block().blockNumber();
 
-     int targetIdx = -1;
 
-     // -1: skip level check.
 
-     int targetLevel = 0;
 
-     int idx = indexOfCurrentHeader();
 
-     if (idx == -1) {
 
-         // Cursor locates at the beginning, before any headers.
 
-         if (p_relativeLevel < 0 || !p_forward) {
 
-             return false;
 
-         }
 
-     }
 
-     int delta = 1;
 
-     if (!p_forward) {
 
-         delta = -1;
 
-     }
 
-     bool firstHeader = true;
 
-     for (targetIdx = idx == -1 ? 0 : idx;
 
-          targetIdx >= 0 && targetIdx < m_headers.size();
 
-          targetIdx += delta) {
 
-         const VTableOfContentItem &header = m_headers[targetIdx];
 
-         if (header.isEmpty()) {
 
-             continue;
 
-         }
 
-         if (targetLevel == 0) {
 
-             // The target level has not been init yet.
 
-             Q_ASSERT(firstHeader);
 
-             targetLevel = header.m_level;
 
-             if (p_relativeLevel < 0) {
 
-                 targetLevel += p_relativeLevel;
 
-                 if (targetLevel < 1) {
 
-                     // Invalid level.
 
-                     return false;
 
-                 }
 
-             } else if (p_relativeLevel > 0) {
 
-                 targetLevel = -1;
 
-             }
 
-         }
 
-         if (targetLevel == -1 || header.m_level == targetLevel) {
 
-             if (firstHeader
 
-                 && (cursorLine == header.m_blockNumber
 
-                     || p_forward)
 
-                 && idx != -1) {
 
-                 // This header is not counted for the repeat.
 
-                 firstHeader = false;
 
-                 continue;
 
-             }
 
-             if (--p_repeat == 0) {
 
-                 // Found.
 
-                 break;
 
-             }
 
-         } else if (header.m_level < targetLevel) {
 
-             // Stop by higher level.
 
-             return false;
 
-         }
 
-         firstHeader = false;
 
-     }
 
-     if (targetIdx < 0 || targetIdx >= m_headers.size()) {
 
-         return false;
 
-     }
 
-     // Jump to target header.
 
-     int line = m_headers[targetIdx].m_blockNumber;
 
-     if (line > -1) {
 
-         QTextBlock block = document()->findBlockByNumber(line);
 
-         if (block.isValid()) {
 
-             cursor.setPosition(block.position());
 
-             setTextCursor(cursor);
 
-             return true;
 
-         }
 
-     }
 
-     return false;
 
- }
 
- void VMdEditor::scrollBlockInPage(int p_blockNum, int p_dest)
 
- {
 
-     VEditUtils::scrollBlockInPage(this, p_blockNum, p_dest);
 
- }
 
- void VMdEditor::updateTextEditConfig()
 
- {
 
-     setBlockImageEnabled(g_config->getEnablePreviewImages());
 
-     setImageWidthConstrainted(g_config->getEnablePreviewImageConstraint());
 
-     setLineLeading(m_config.m_lineDistanceHeight);
 
-     setImageLineColor(g_config->getEditorPreviewImageLineFg());
 
-     int lineNumber = g_config->getEditorLineNumber();
 
-     if (lineNumber < (int)LineNumberType::None || lineNumber >= (int)LineNumberType::Invalid) {
 
-         lineNumber = (int)LineNumberType::None;
 
-     }
 
-     setLineNumberType((LineNumberType)lineNumber);
 
-     setLineNumberColor(g_config->getEditorLineNumberFg(),
 
-                        g_config->getEditorLineNumberBg());
 
-     m_previewMgr->setPreviewEnabled(g_config->getEnablePreviewImages());
 
- }
 
- void VMdEditor::updateConfig()
 
- {
 
-     updateEditConfig();
 
-     updateTextEditConfig();
 
- }
 
- QString VMdEditor::getContent() const
 
- {
 
-     return toPlainText();
 
- }
 
- void VMdEditor::setContent(const QString &p_content, bool p_modified)
 
- {
 
-     if (p_modified) {
 
-         QTextCursor cursor = textCursor();
 
-         cursor.select(QTextCursor::Document);
 
-         cursor.insertText(p_content);
 
-         setTextCursor(cursor);
 
-     } else {
 
-         setPlainText(p_content);
 
-     }
 
- }
 
- void VMdEditor::refreshPreview()
 
- {
 
-     m_previewMgr->refreshPreview();
 
- }
 
- void VMdEditor::updateInitAndInsertedImages(bool p_fileChanged, UpdateAction p_act)
 
- {
 
-     if (p_fileChanged && p_act == UpdateAction::InfoChanged) {
 
-         return;
 
-     }
 
-     if (!isModified()) {
 
-         Q_ASSERT(m_insertedImages.isEmpty());
 
-         m_insertedImages.clear();
 
-         if (!m_initImages.isEmpty()) {
 
-             // Re-generate init images.
 
-             initInitImages();
 
-         }
 
-         return;
 
-     }
 
-     // Update init images.
 
-     QVector<ImageLink> tmp = m_initImages;
 
-     initInitImages();
 
-     Q_ASSERT(tmp.size() == m_initImages.size());
 
-     QDir dir(m_file->fetchBasePath());
 
-     // File has been moved.
 
-     if (p_fileChanged) {
 
-         // Since we clear unused images once user save the note, all images
 
-         // in m_initImages now are moved already.
 
-         // Update inserted images.
 
-         // Inserted images should be moved manually here. Then update all the
 
-         // paths.
 
-         for (auto & link : m_insertedImages) {
 
-             if (link.m_type == ImageLink::LocalAbsolute) {
 
-                 continue;
 
-             }
 
-             QString newPath = QDir::cleanPath(dir.absoluteFilePath(link.m_url));
 
-             if (VUtils::equalPath(link.m_path, newPath)) {
 
-                 continue;
 
-             }
 
-             if (!VUtils::copyFile(link.m_path, newPath, true)) {
 
-                 VUtils::showMessage(QMessageBox::Warning,
 
-                                     tr("Warning"),
 
-                                     tr("Fail to move unsaved inserted image %1 to %2.")
 
-                                     .arg(link.m_path)
 
-                                     .arg(newPath),
 
-                                     tr("Please check it manually to avoid image loss."),
 
-                                     QMessageBox::Ok,
 
-                                     QMessageBox::Ok,
 
-                                     this);
 
-                 continue;
 
-             }
 
-             link.m_path = newPath;
 
-         }
 
-     } else {
 
-         // Directory changed.
 
-         // Update inserted images.
 
-         for (auto & link : m_insertedImages) {
 
-             if (link.m_type == ImageLink::LocalAbsolute) {
 
-                 continue;
 
-             }
 
-             QString newPath = QDir::cleanPath(dir.absoluteFilePath(link.m_url));
 
-             link.m_path = newPath;
 
-         }
 
-     }
 
- }
 
- void VMdEditor::handleCopyAsAction(QAction *p_act)
 
- {
 
-     ++m_copyTimeStamp;
 
-     QTextCursor cursor = textCursor();
 
-     Q_ASSERT(cursor.hasSelection());
 
-     QString text = VEditUtils::selectedText(cursor);
 
-     Q_ASSERT(!text.isEmpty());
 
-     Q_ASSERT(!m_textToHtmlDialog);
 
-     m_textToHtmlDialog = new VCopyTextAsHtmlDialog(text, p_act->data().toString(), this);
 
-     // For Hoedown, we use marked.js to convert the text to have a general interface.
 
-     emit requestTextToHtml(text, 0, m_copyTimeStamp);
 
-     m_textToHtmlDialog->exec();
 
-     delete m_textToHtmlDialog;
 
-     m_textToHtmlDialog = NULL;
 
- }
 
- void VMdEditor::textToHtmlFinished(int p_id,
 
-                                    int p_timeStamp,
 
-                                    const QUrl &p_baseUrl,
 
-                                    const QString &p_html)
 
- {
 
-     Q_UNUSED(p_id);
 
-     if (m_textToHtmlDialog && p_timeStamp == m_copyTimeStamp) {
 
-         m_textToHtmlDialog->setConvertedHtml(p_baseUrl, p_html);
 
-     }
 
- }
 
- void VMdEditor::wheelEvent(QWheelEvent *p_event)
 
- {
 
-     if (handleWheelEvent(p_event)) {
 
-         return;
 
-     }
 
-     VTextEdit::wheelEvent(p_event);
 
- }
 
- void VMdEditor::zoomPage(bool p_zoomIn, int p_range)
 
- {
 
-     const int minSize = 2;
 
-     int delta = p_zoomIn ? p_range : -p_range;
 
-     // zoomIn() and zoomOut() does not work if we set stylesheet of VMdEditor.
 
-     int ptSz = font().pointSize() + delta;
 
-     if (ptSz < minSize) {
 
-         ptSz = minSize;
 
-     }
 
-     setFontPointSizeByStyleSheet(ptSz);
 
-     emit m_object->statusMessage(QObject::tr("Set base font point size %1").arg(ptSz));
 
-     m_zoomDelta += delta;
 
-     QVector<HighlightingStyle> &styles = m_pegHighlighter->getStyles();
 
-     for (auto & it : styles) {
 
-         int size = it.format.fontPointSize();
 
-         if (size == 0) {
 
-             // It contains no font size format.
 
-             continue;
 
-         }
 
-         size += delta;
 
-         if (size < minSize) {
 
-             size = minSize;
 
-         }
 
-         it.format.setFontPointSize(size);
 
-     }
 
-     QHash<QString, QTextCharFormat> &cbStyles = m_pegHighlighter->getCodeBlockStyles();
 
-     for (auto it = cbStyles.begin(); it != cbStyles.end(); ++it) {
 
-         int size = it.value().fontPointSize();
 
-         if (size == 0) {
 
-             // It contains no font size format.
 
-             continue;
 
-         }
 
-         size += delta;
 
-         if (size < minSize) {
 
-             size = minSize;
 
-         }
 
-         it.value().setFontPointSize(size);
 
-     }
 
-     m_pegHighlighter->rehighlight();
 
- }
 
- void VMdEditor::initCopyAsMenu(QAction *p_before, QMenu *p_menu)
 
- {
 
-     QStringList targets = g_webUtils->getCopyTargetsName();
 
-     if (targets.isEmpty()) {
 
-         return;
 
-     }
 
-     QMenu *subMenu = new QMenu(tr("Copy HTML As"), p_menu);
 
-     subMenu->setToolTipsVisible(true);
 
-     for (auto const & target : targets) {
 
-         QAction *act = new QAction(target, subMenu);
 
-         act->setData(target);
 
-         act->setToolTip(tr("Copy selected content as HTML using rules specified by target %1").arg(target));
 
-         subMenu->addAction(act);
 
-     }
 
-     connect(subMenu, &QMenu::triggered,
 
-             this, &VMdEditor::handleCopyAsAction);
 
-     QAction *menuAct = p_menu->insertMenu(p_before, subMenu);
 
-     if (p_before) {
 
-         p_menu->removeAction(p_before);
 
-         p_menu->insertAction(menuAct, p_before);
 
-         p_menu->insertSeparator(menuAct);
 
-     }
 
- }
 
- void VMdEditor::initPasteAsBlockQuoteMenu(QMenu *p_menu)
 
- {
 
-     QAction *pbqAct = new QAction(tr("Paste As Block &Quote"), p_menu);
 
-     pbqAct->setToolTip(tr("Paste text from clipboard as block quote"));
 
-     connect(pbqAct, &QAction::triggered,
 
-             this, [this]() {
 
-                 QClipboard *clipboard = QApplication::clipboard();
 
-                 const QMimeData *mimeData = clipboard->mimeData();
 
-                 QString text = mimeData->text();
 
-                 QTextCursor cursor = textCursor();
 
-                 cursor.removeSelectedText();
 
-                 QTextBlock block = cursor.block();
 
-                 QString indent = VEditUtils::fetchIndentSpaces(block);
 
-                 // Insert '> ' in front of each line.
 
-                 VEditUtils::insertBeforeEachLine(text, indent + QStringLiteral("> "));
 
-                 if (VEditUtils::isSpaceBlock(block)) {
 
-                     if (!indent.isEmpty()) {
 
-                         // Remove the indent.
 
-                         cursor.movePosition(QTextCursor::StartOfBlock);
 
-                         cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
 
-                         cursor.removeSelectedText();
 
-                     }
 
-                 } else {
 
-                     // Insert a new block.
 
-                     VEditUtils::insertBlock(cursor, false);
 
-                 }
 
-                 cursor.insertText(text);
 
-                 setTextCursor(cursor);
 
-             });
 
-     p_menu->addSeparator();
 
-     p_menu->addAction(pbqAct);
 
- }
 
- void VMdEditor::insertImageLink(const QString &p_text, const QString &p_url)
 
- {
 
-     VInsertLinkDialog dialog(tr("Insert Image Link"),
 
-                              "",
 
-                              "",
 
-                              p_text,
 
-                              p_url,
 
-                              true,
 
-                              this);
 
-     if (dialog.exec() == QDialog::Accepted) {
 
-         QString linkText = dialog.getLinkText();
 
-         QString linkUrl = dialog.getLinkUrl();
 
-         static_cast<VMdEditOperations *>(m_editOps)->insertImageLink(linkText, linkUrl);
 
-     }
 
- }
 
- VWordCountInfo VMdEditor::fetchWordCountInfo() const
 
- {
 
-     VWordCountInfo info;
 
-     QTextDocument *doc = document();
 
-     // Char without spaces.
 
-     int cns = 0;
 
-     int wc = 0;
 
-     // Remove th ending new line.
 
-     int cc = doc->characterCount() - 1;
 
-     // 0 - not in word;
 
-     // 1 - in English word;
 
-     // 2 - in non-English word;
 
-     int state = 0;
 
-     for (int i = 0; i < cc; ++i) {
 
-         QChar ch = doc->characterAt(i);
 
-         if (ch.isSpace()) {
 
-             if (state) {
 
-                 state = 0;
 
-             }
 
-             continue;
 
-         } else if (ch.unicode() < 128) {
 
-             if (state != 1) {
 
-                 state = 1;
 
-                 ++wc;
 
-             }
 
-         } else {
 
-             state = 2;
 
-             ++wc;
 
-         }
 
-         ++cns;
 
-     }
 
-     info.m_mode = VWordCountInfo::Edit;
 
-     info.m_wordCount = wc;
 
-     info.m_charWithoutSpacesCount = cns;
 
-     info.m_charWithSpacesCount = cc;
 
-     return info;
 
- }
 
- void VMdEditor::setEditTab(VEditTab *p_editTab)
 
- {
 
-     m_editTab = p_editTab;
 
- }
 
- void VMdEditor::setFontPointSizeByStyleSheet(int p_ptSize)
 
- {
 
-     QFont ft = font();
 
-     ft.setPointSize(p_ptSize);
 
-     setFontAndPaletteByStyleSheet(ft, palette());
 
-     ensurePolished();
 
-     updateLineNumberAreaWidth(QFontMetrics(ft));
 
- }
 
- void VMdEditor::setFontAndPaletteByStyleSheet(const QFont &p_font, const QPalette &p_palette)
 
- {
 
-     setStyleSheet(QString("VMdEditor, VLineNumberArea {"
 
-                           "font-family: \"%1\";"
 
-                           "font-size: %2pt;"
 
-                           "color: %3;"
 
-                           "background-color: %4; }")
 
-                          .arg(p_font.family())
 
-                          .arg(p_font.pointSize())
 
-                          .arg(p_palette.color(QPalette::Text).name())
 
-                          .arg(p_palette.color(QPalette::Base).name()));
 
- }
 
 
  |