|
|
@@ -3,107 +3,34 @@
|
|
|
#include "vedit.h"
|
|
|
#include "vnote.h"
|
|
|
#include "vconfigmanager.h"
|
|
|
-#include "hgmarkdownhighlighter.h"
|
|
|
-#include "vmdeditoperations.h"
|
|
|
#include "vtoc.h"
|
|
|
#include "utils/vutils.h"
|
|
|
+#include "veditoperations.h"
|
|
|
|
|
|
extern VConfigManager vconfig;
|
|
|
|
|
|
VEdit::VEdit(VFile *p_file, QWidget *p_parent)
|
|
|
- : QTextEdit(p_parent), m_file(p_file), mdHighlighter(NULL)
|
|
|
+ : QTextEdit(p_parent), m_file(p_file), m_editOps(NULL)
|
|
|
{
|
|
|
connect(document(), &QTextDocument::modificationChanged,
|
|
|
(VFile *)m_file, &VFile::setModified);
|
|
|
-
|
|
|
- if (m_file->getDocType() == DocType::Markdown) {
|
|
|
- setAcceptRichText(false);
|
|
|
- mdHighlighter = new HGMarkdownHighlighter(vconfig.getMdHighlightingStyles(),
|
|
|
- 500, document());
|
|
|
- connect(mdHighlighter, &HGMarkdownHighlighter::highlightCompleted,
|
|
|
- this, &VEdit::generateEditOutline);
|
|
|
- editOps = new VMdEditOperations(this, m_file);
|
|
|
- } else {
|
|
|
- editOps = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- updateTabSettings();
|
|
|
- updateFontAndPalette();
|
|
|
- connect(this, &VEdit::cursorPositionChanged,
|
|
|
- this, &VEdit::updateCurHeader);
|
|
|
}
|
|
|
|
|
|
VEdit::~VEdit()
|
|
|
{
|
|
|
+ qDebug() << "VEdit destruction";
|
|
|
if (m_file) {
|
|
|
disconnect(document(), &QTextDocument::modificationChanged,
|
|
|
(VFile *)m_file, &VFile::setModified);
|
|
|
}
|
|
|
- if (editOps) {
|
|
|
- delete editOps;
|
|
|
- editOps = NULL;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void VEdit::updateFontAndPalette()
|
|
|
-{
|
|
|
- switch (m_file->getDocType()) {
|
|
|
- case DocType::Markdown:
|
|
|
- setFont(vconfig.getMdEditFont());
|
|
|
- setPalette(vconfig.getMdEditPalette());
|
|
|
- break;
|
|
|
- case DocType::Html:
|
|
|
- setFont(vconfig.getBaseEditFont());
|
|
|
- setPalette(vconfig.getBaseEditPalette());
|
|
|
- break;
|
|
|
- default:
|
|
|
- qWarning() << "error: unknown doc type" << int(m_file->getDocType());
|
|
|
- return;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void VEdit::updateTabSettings()
|
|
|
-{
|
|
|
- switch (m_file->getDocType()) {
|
|
|
- case DocType::Markdown:
|
|
|
- if (vconfig.getTabStopWidth() > 0) {
|
|
|
- QFontMetrics metrics(vconfig.getMdEditFont());
|
|
|
- setTabStopWidth(vconfig.getTabStopWidth() * metrics.width(' '));
|
|
|
- }
|
|
|
- break;
|
|
|
- case DocType::Html:
|
|
|
- if (vconfig.getTabStopWidth() > 0) {
|
|
|
- QFontMetrics metrics(vconfig.getBaseEditFont());
|
|
|
- setTabStopWidth(vconfig.getTabStopWidth() * metrics.width(' '));
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- qWarning() << "error: unknown doc type" << int(m_file->getDocType());
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- isExpandTab = vconfig.getIsExpandTab();
|
|
|
- if (isExpandTab && (vconfig.getTabStopWidth() > 0)) {
|
|
|
- tabSpaces = QString(vconfig.getTabStopWidth(), ' ');
|
|
|
+ if (m_editOps) {
|
|
|
+ delete m_editOps;
|
|
|
+ m_editOps = NULL;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void VEdit::beginEdit()
|
|
|
{
|
|
|
- updateTabSettings();
|
|
|
- updateFontAndPalette();
|
|
|
- switch (m_file->getDocType()) {
|
|
|
- case DocType::Html:
|
|
|
- setHtml(m_file->getContent());
|
|
|
- break;
|
|
|
- case DocType::Markdown:
|
|
|
- setFont(vconfig.getMdEditFont());
|
|
|
- setPlainText(m_file->getContent());
|
|
|
- initInitImages();
|
|
|
- break;
|
|
|
- default:
|
|
|
- qWarning() << "error: unknown doc type" << int(m_file->getDocType());
|
|
|
- }
|
|
|
setReadOnly(false);
|
|
|
setModified(false);
|
|
|
}
|
|
|
@@ -111,9 +38,6 @@ void VEdit::beginEdit()
|
|
|
void VEdit::endEdit()
|
|
|
{
|
|
|
setReadOnly(true);
|
|
|
- if (m_file->getDocType() == DocType::Markdown) {
|
|
|
- clearUnusedImages();
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
void VEdit::saveFile()
|
|
|
@@ -121,176 +45,38 @@ void VEdit::saveFile()
|
|
|
if (!document()->isModified()) {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- switch (m_file->getDocType()) {
|
|
|
- case DocType::Html:
|
|
|
- m_file->setContent(toHtml());
|
|
|
- break;
|
|
|
- case DocType::Markdown:
|
|
|
- m_file->setContent(toPlainText());
|
|
|
- break;
|
|
|
- default:
|
|
|
- qWarning() << "error: unknown doc type" << int(m_file->getDocType());
|
|
|
- }
|
|
|
+ m_file->setContent(toHtml());
|
|
|
document()->setModified(false);
|
|
|
}
|
|
|
|
|
|
void VEdit::reloadFile()
|
|
|
{
|
|
|
- switch (m_file->getDocType()) {
|
|
|
- case DocType::Html:
|
|
|
- setHtml(m_file->getContent());
|
|
|
- break;
|
|
|
- case DocType::Markdown:
|
|
|
- setPlainText(m_file->getContent());
|
|
|
- break;
|
|
|
- default:
|
|
|
- qWarning() << "error: unknown doc type" << int(m_file->getDocType());
|
|
|
- }
|
|
|
+ setHtml(m_file->getContent());
|
|
|
setModified(false);
|
|
|
}
|
|
|
|
|
|
-void VEdit::keyPressEvent(QKeyEvent *event)
|
|
|
+void VEdit::scrollToLine(int p_lineNumber)
|
|
|
{
|
|
|
- if ((event->key() == Qt::Key_Tab) && isExpandTab) {
|
|
|
- QTextCursor cursor(document());
|
|
|
- cursor.setPosition(textCursor().position());
|
|
|
- cursor.insertText(tabSpaces);
|
|
|
- return;
|
|
|
- }
|
|
|
- QTextEdit::keyPressEvent(event);
|
|
|
-}
|
|
|
-
|
|
|
-bool VEdit::canInsertFromMimeData(const QMimeData *source) const
|
|
|
-{
|
|
|
- return source->hasImage() || source->hasUrls()
|
|
|
- || QTextEdit::canInsertFromMimeData(source);
|
|
|
-}
|
|
|
-
|
|
|
-void VEdit::insertFromMimeData(const QMimeData *source)
|
|
|
-{
|
|
|
- if (source->hasImage()) {
|
|
|
- // Image data in the clipboard
|
|
|
- if (editOps) {
|
|
|
- bool ret = editOps->insertImageFromMimeData(source);
|
|
|
- if (ret) {
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (source->hasUrls()) {
|
|
|
- // Paste an image file
|
|
|
- if (editOps) {
|
|
|
- bool ret = editOps->insertURLFromMimeData(source);
|
|
|
- if (ret) {
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- QTextEdit::insertFromMimeData(source);
|
|
|
-}
|
|
|
-
|
|
|
-void VEdit::generateEditOutline()
|
|
|
-{
|
|
|
- QTextDocument *doc = document();
|
|
|
- headers.clear();
|
|
|
- // Assume that each block contains only one line
|
|
|
- // Only support # syntax for now
|
|
|
- QRegExp headerReg("(#{1,6})\\s*(\\S.*)"); // Need to trim the spaces
|
|
|
- for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) {
|
|
|
- Q_ASSERT(block.lineCount() == 1);
|
|
|
- if ((block.userState() == HighlightBlockState::BlockNormal) &&
|
|
|
- headerReg.exactMatch(block.text())) {
|
|
|
- VHeader header(headerReg.cap(1).length(),
|
|
|
- headerReg.cap(2).trimmed(), "", block.firstLineNumber());
|
|
|
- headers.append(header);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- emit headersChanged(headers);
|
|
|
- updateCurHeader();
|
|
|
-}
|
|
|
-
|
|
|
-void VEdit::scrollToLine(int lineNumber)
|
|
|
-{
|
|
|
- Q_ASSERT(lineNumber >= 0);
|
|
|
+ Q_ASSERT(p_lineNumber >= 0);
|
|
|
|
|
|
// Move the cursor to the end first
|
|
|
moveCursor(QTextCursor::End);
|
|
|
- QTextCursor cursor(document()->findBlockByLineNumber(lineNumber));
|
|
|
+ QTextCursor cursor(document()->findBlockByLineNumber(p_lineNumber));
|
|
|
cursor.movePosition(QTextCursor::EndOfBlock);
|
|
|
setTextCursor(cursor);
|
|
|
|
|
|
setFocus();
|
|
|
}
|
|
|
|
|
|
-void VEdit::updateCurHeader()
|
|
|
+bool VEdit::isModified() const
|
|
|
{
|
|
|
- int curHeader = 0;
|
|
|
- QTextCursor cursor(this->textCursor());
|
|
|
- int curLine = cursor.block().firstLineNumber();
|
|
|
- for (int i = headers.size() - 1; i >= 0; --i) {
|
|
|
- if (headers[i].lineNumber <= curLine) {
|
|
|
- curHeader = headers[i].lineNumber;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- emit curHeaderChanged(curHeader);
|
|
|
+ return document()->isModified();
|
|
|
}
|
|
|
|
|
|
-void VEdit::insertImage(const QString &name)
|
|
|
+void VEdit::setModified(bool p_modified)
|
|
|
{
|
|
|
- m_insertedImages.append(name);
|
|
|
-}
|
|
|
-
|
|
|
-void VEdit::initInitImages()
|
|
|
-{
|
|
|
- m_initImages = VUtils::imagesFromMarkdownFile(m_file->retrivePath());
|
|
|
-}
|
|
|
-
|
|
|
-void VEdit::clearUnusedImages()
|
|
|
-{
|
|
|
- QVector<QString> images = VUtils::imagesFromMarkdownFile(m_file->retrivePath());
|
|
|
-
|
|
|
- if (!m_insertedImages.isEmpty()) {
|
|
|
- QVector<QString> imageNames(images.size());
|
|
|
- for (int i = 0; i < imageNames.size(); ++i) {
|
|
|
- imageNames[i] = VUtils::fileNameFromPath(images[i]);
|
|
|
- }
|
|
|
-
|
|
|
- QDir dir = QDir(m_file->retriveImagePath());
|
|
|
- for (int i = 0; i < m_insertedImages.size(); ++i) {
|
|
|
- QString name = m_insertedImages[i];
|
|
|
- int j;
|
|
|
- for (j = 0; j < imageNames.size(); ++j) {
|
|
|
- if (name == imageNames[j]) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Delete it
|
|
|
- if (j == imageNames.size()) {
|
|
|
- QString imagePath = dir.filePath(name);
|
|
|
- QFile(imagePath).remove();
|
|
|
- qDebug() << "delete inserted image" << imagePath;
|
|
|
- }
|
|
|
- }
|
|
|
- m_insertedImages.clear();
|
|
|
- }
|
|
|
-
|
|
|
- for (int i = 0; i < m_initImages.size(); ++i) {
|
|
|
- QString imagePath = m_initImages[i];
|
|
|
- int j;
|
|
|
- for (j = 0; j < images.size(); ++j) {
|
|
|
- if (imagePath == images[j]) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // Delete it
|
|
|
- if (j == images.size()) {
|
|
|
- QFile(imagePath).remove();
|
|
|
- qDebug() << "delete existing image" << imagePath;
|
|
|
- }
|
|
|
+ document()->setModified(p_modified);
|
|
|
+ if (m_file) {
|
|
|
+ m_file->setModified(p_modified);
|
|
|
}
|
|
|
- m_initImages.clear();
|
|
|
}
|