瀏覽代碼

use QStackedWidget to hold QTextBrowser and VEdit

Use QTextBrowser to display file in read mode and VEdit to display file
in edit mode.

Signed-off-by: Le Tan <[email protected]>
Le Tan 9 年之前
父節點
當前提交
e3e18d040c
共有 9 個文件被更改,包括 305 次插入157 次删除
  1. 7 2
      VNote.pro
  2. 6 0
      vconstants.h
  3. 27 117
      vedit.cpp
  4. 13 22
      vedit.h
  5. 167 0
      veditor.cpp
  6. 40 0
      veditor.h
  7. 9 0
      vnotefile.cpp
  8. 20 0
      vnotefile.h
  9. 16 16
      vtabwidget.cpp

+ 7 - 2
VNote.pro

@@ -22,7 +22,9 @@ SOURCES += main.cpp\
     vfilelist.cpp \
     vnewfiledialog.cpp \
     vtabwidget.cpp \
-    vedit.cpp
+    vedit.cpp \
+    veditor.cpp \
+    vnotefile.cpp
 
 HEADERS  += vmainwindow.h \
     vdirectorytree.h \
@@ -33,7 +35,10 @@ HEADERS  += vmainwindow.h \
     vfilelist.h \
     vnewfiledialog.h \
     vtabwidget.h \
-    vedit.h
+    vedit.h \
+    veditor.h \
+    vconstants.h \
+    vnotefile.h
 
 RESOURCES += \
     vnote.qrc

+ 6 - 0
vconstants.h

@@ -0,0 +1,6 @@
+#ifndef VCONSTANTS_H
+#define VCONSTANTS_H
+
+enum class DocType { Html, Markdown };
+
+#endif

+ 27 - 117
vedit.cpp

@@ -1,154 +1,64 @@
 #include <QtWidgets>
 #include "vedit.h"
 
-VEdit::VEdit(const QString &path, const QString &name, bool modifiable,
-             QWidget *parent)
-    : QTextEdit(parent), path(path), name(name), modifiable(modifiable)
+VEdit::VEdit(VNoteFile *noteFile, QWidget *parent)
+    : QTextEdit(parent), noteFile(noteFile)
 {
-    docType = isMarkdown() ? DocType::Markdown : DocType::Html;
-    fileText = readFileFromDisk(QDir(path).filePath(name));
-    showFileReadMode();
-    fileLoaded = true;
-    qDebug() << "VEdit:" << name << (docType == DocType::Markdown ? "Markdown" : "Html");
 }
 
-void VEdit::showFileReadMode()
-{
-    setReadOnly(true);
-    switch (docType) {
-    case DocType::Html:
-        if (!fileLoaded) {
-            setHtml(fileText);
-        }
-        break;
-    case DocType::Markdown:
-        setText(fileText);
-        break;
-    default:
-        qWarning() << "error: unknown doc type" << int(docType);
-    }
-}
-
-void VEdit::showFileEditMode()
+void VEdit::beginEdit()
 {
     setReadOnly(false);
-    switch (docType) {
+    switch (noteFile->docType) {
     case DocType::Html:
-        if (!fileLoaded) {
-            setHtml(fileText);
-        }
+        setHtml(noteFile->content);
         break;
     case DocType::Markdown:
-        setText(fileText);
+        setPlainText(noteFile->content);
         break;
     default:
-        qWarning() << "error: unknown doc type" << int(docType);
+        qWarning() << "error: unknown doc type" << int(noteFile->docType);
     }
 }
 
-QString VEdit::readFileFromDisk(const QString &filePath)
+bool VEdit::tryEndEdit()
 {
-    QFile file(filePath);
-    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
-        qWarning() << "error: fail to read file" << filePath;
-        return QString();
-    }
-    QString fileText(file.readAll());
-    file.close();
-    qDebug() << "read file content:" << filePath;
-    return fileText;
+    return !document()->isModified();
 }
 
-bool VEdit::writeFileToDisk(const QString &filePath, const QString &text)
+void VEdit::beginSave()
 {
-    QFile file(filePath);
-    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
-        qWarning() << "error: fail to open file" << filePath << "to write to";
-        return false;
-    }
-    QTextStream stream(&file);
-    stream << text;
-    file.close();
-    qDebug() << "write file content:" << filePath;
-    return true;
-}
-
-bool VEdit::requestClose()
-{
-    readFile();
-    return isReadOnly();
-}
-
-void VEdit::editFile()
-{
-    if (!modifiable || !isReadOnly()) {
+    if (!document()->isModified()) {
         return;
     }
-    showFileEditMode();
-}
 
-void VEdit::readFile()
-{
-    if (isReadOnly()) {
-        return;
-    }
-    if (document()->isModified()) {
-        QMessageBox msgBox(QMessageBox::Information, tr("Exit edit mode"),
-                           QString("Note has been changed. Do you want to save it before exit?"));
-        msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::No | QMessageBox::Cancel);
-        msgBox.setDefaultButton(QMessageBox::Save);
-        int ret = msgBox.exec();
-        switch (ret) {
-        case QMessageBox::Save:
-            saveFile();
-            // Fall through
-        case QMessageBox::No:
-            showFileReadMode();
-            break;
-        case QMessageBox::Cancel:
-            break;
-        default:
-            qWarning() << "error: wrong return value from QMessageBox:" << ret;
-        }
-    } else {
-        showFileReadMode();
-    }
-}
-
-void VEdit::saveFile()
-{
-    if (!modifiable || !document()->isModified()) {
-        return;
-    }
-
-    switch (docType) {
+    switch (noteFile->docType) {
     case DocType::Html:
-        fileText = toHtml();
-        writeFileToDisk(QDir(path).filePath(name), fileText);
+        noteFile->content = toHtml();
         break;
     case DocType::Markdown:
 
         break;
     default:
-        qWarning() << "error: unknown doc type" << int(docType);
+        qWarning() << "error: unknown doc type" << int(noteFile->docType);
     }
+}
 
+void VEdit::endSave()
+{
     document()->setModified(false);
 }
 
-bool VEdit::isMarkdown()
+void VEdit::reloadFile()
 {
-    const QVector<QString> mdPostfix({"md", "markdown", "mkd"});
-
-    QStringList list = name.split('.', QString::SkipEmptyParts);
-    if (list.isEmpty()) {
-        return false;
-    }
-    const QString &postfix = list.last();
-    for (int i = 0; i < mdPostfix.size(); ++i) {
-        if (postfix == mdPostfix[i]) {
-            return true;
-        }
+    switch (noteFile->docType) {
+    case DocType::Html:
+        setHtml(noteFile->content);
+        break;
+    case DocType::Markdown:
+        setPlainText(noteFile->content);
+        break;
+    default:
+        qWarning() << "error: unknown doc type" << int(noteFile->docType);
     }
-    return false;
 }

+ 13 - 22
vedit.h

@@ -3,20 +3,23 @@
 
 #include <QTextEdit>
 #include <QString>
+#include "vconstants.h"
+#include "vnotefile.h"
 
 class VEdit : public QTextEdit
 {
     Q_OBJECT
 public:
-    explicit VEdit(const QString &path, const QString &name, bool modifiable = false,
-                   QWidget *parent = 0);
-    bool requestClose();
-    // Enter edit mode
-    void editFile();
-    // Enter read mode
-    void readFile();
-    // Save file
-    void saveFile();
+    VEdit(VNoteFile *noteFile, QWidget *parent = 0);
+    void beginEdit();
+    bool tryEndEdit();
+
+    // begin: sync the buffer to noteFile->content;
+    // end: setModified(false)
+    void beginSave();
+    void endSave();
+
+    void reloadFile();
 
 signals:
 
@@ -24,19 +27,7 @@ public slots:
 
 
 private:
-    enum class DocType { Html, Markdown };
-    QString readFileFromDisk(const QString &filePath);
-    bool writeFileToDisk(const QString &filePath, const QString &text);
-    void showFileReadMode();
-    void showFileEditMode();
-    bool isMarkdown();
-
-    QString path;
-    QString name;
-    QString fileText;
-    DocType docType;
-    bool modifiable;
-    bool fileLoaded;
+    VNoteFile *noteFile;
 };
 
 #endif // VEDIT_H

+ 167 - 0
veditor.cpp

@@ -0,0 +1,167 @@
+#include <QtWidgets>
+#include <QTextBrowser>
+#include "veditor.h"
+#include "vedit.h"
+
+VEditor::VEditor(const QString &path, const QString &name, bool modifiable,
+                 QWidget *parent)
+    : QStackedWidget(parent)
+{
+    DocType docType = isMarkdown(name) ? DocType::Markdown : DocType::Html;
+    QString fileText = readFileFromDisk(QDir(path).filePath(name));
+    noteFile = new VNoteFile(path, name, fileText, docType, modifiable);
+
+    isEditMode = false;
+
+    setupUI();
+
+    showFileReadMode();
+}
+
+VEditor::~VEditor()
+{
+    delete noteFile;
+}
+
+void VEditor::setupUI()
+{
+    textEditor = new VEdit(noteFile);
+    textBrowser = new QTextBrowser();
+    addWidget(textBrowser);
+    addWidget(textEditor);
+}
+
+bool VEditor::isMarkdown(const QString &name)
+{
+    const QVector<QString> mdPostfix({"md", "markdown", "mkd"});
+
+    QStringList list = name.split('.', QString::SkipEmptyParts);
+    if (list.isEmpty()) {
+        return false;
+    }
+    const QString &postfix = list.last();
+    for (int i = 0; i < mdPostfix.size(); ++i) {
+        if (postfix == mdPostfix[i]) {
+            return true;
+        }
+    }
+    return false;
+}
+
+QString VEditor::readFileFromDisk(const QString &filePath)
+{
+    QFile file(filePath);
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        qWarning() << "error: fail to read file" << filePath;
+        return QString();
+    }
+    QString fileText(file.readAll());
+    file.close();
+    qDebug() << "read file content:" << filePath;
+    return fileText;
+}
+
+bool VEditor::writeFileToDisk(const QString &filePath, const QString &text)
+{
+    QFile file(filePath);
+    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+        qWarning() << "error: fail to open file" << filePath << "to write to";
+        return false;
+    }
+    QTextStream stream(&file);
+    stream << text;
+    file.close();
+    qDebug() << "write file content:" << filePath;
+    return true;
+}
+
+void VEditor::showFileReadMode()
+{
+    isEditMode = false;
+    switch (noteFile->docType) {
+    case DocType::Html:
+        textBrowser->setHtml(noteFile->content);
+        break;
+    case DocType::Markdown:
+
+        break;
+    default:
+        qWarning() << "error: unknown doc type" << int(noteFile->docType);
+    }
+    setCurrentWidget(textBrowser);
+}
+
+void VEditor::showFileEditMode()
+{
+    isEditMode = true;
+    textEditor->beginEdit();
+    setCurrentWidget(textEditor);
+}
+
+bool VEditor::requestClose()
+{
+    readFile();
+    return !isEditMode;
+}
+
+void VEditor::editFile()
+{
+    if (isEditMode || !noteFile->modifiable) {
+        return;
+    }
+    showFileEditMode();
+}
+
+void VEditor::readFile()
+{
+    if (!isEditMode) {
+        return;
+    }
+    bool canExit = textEditor->tryEndEdit();
+    if (!canExit) {
+        // Need to save the changes
+        QMessageBox msgBox;
+        msgBox.setText("The note has been modified.");
+        msgBox.setInformativeText("Do you want to save your changes?");
+        msgBox.setIcon(QMessageBox::Information);
+        msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
+        msgBox.setDefaultButton(QMessageBox::Save);
+        int ret = msgBox.exec();
+        switch (ret) {
+        case QMessageBox::Save:
+            saveFile();
+            // Fall through
+        case QMessageBox::Discard:
+            textEditor->reloadFile();
+            break;
+        case QMessageBox::Cancel:
+            // Nothing to do if user cancel this action
+            return;
+        default:
+            qWarning() << "error: wrong return value from QMessageBox:" << ret;
+            return;
+        }
+    }
+    textEditor->setReadOnly(true);
+    showFileReadMode();
+}
+
+bool VEditor::saveFile()
+{
+    if (!isEditMode || !noteFile->modifiable) {
+        return true;
+    }
+    textEditor->beginSave();
+    bool ret = writeFileToDisk(QDir(noteFile->path).filePath(noteFile->name),
+                               noteFile->content);
+    if (!ret) {
+        QMessageBox msgBox(QMessageBox::Warning, tr("Fail to save to file"),
+                           QString("Fail to write to disk when saving a note. Please try it again."));
+        msgBox.setStandardButtons(QMessageBox::Ok);
+        msgBox.setDefaultButton(QMessageBox::Ok);
+        msgBox.exec();
+        return false;
+    }
+    textEditor->endSave();
+    return true;
+}

+ 40 - 0
veditor.h

@@ -0,0 +1,40 @@
+#ifndef VEDITOR_H
+#define VEDITOR_H
+
+#include <QStackedWidget>
+#include <QString>
+#include "vconstants.h"
+#include "vnotefile.h"
+
+class QTextBrowser;
+class VEdit;
+
+class VEditor : public QStackedWidget
+{
+public:
+    VEditor(const QString &path, const QString &name, bool modifiable,
+            QWidget *parent = 0);
+    ~VEditor();
+    bool requestClose();
+    // Enter edit mode
+    void editFile();
+    // Enter read mode
+    void readFile();
+    // Save file
+    bool saveFile();
+
+private:
+    bool isMarkdown(const QString &name);
+    QString readFileFromDisk(const QString &filePath);
+    bool writeFileToDisk(const QString &filePath, const QString &text);
+    void setupUI();
+    void showFileReadMode();
+    void showFileEditMode();
+
+    VNoteFile *noteFile;
+    bool isEditMode;
+    QTextBrowser *textBrowser;
+    VEdit *textEditor;
+};
+
+#endif // VEDITOR_H

+ 9 - 0
vnotefile.cpp

@@ -0,0 +1,9 @@
+#include "vnotefile.h"
+
+VNoteFile::VNoteFile(const QString &path, const QString &name,
+                     const QString &content, DocType docType, bool modifiable)
+    : path(path), name(name), content(content), docType(docType),
+      modifiable(modifiable)
+{
+
+}

+ 20 - 0
vnotefile.h

@@ -0,0 +1,20 @@
+#ifndef VNOTEFILE_H
+#define VNOTEFILE_H
+
+#include <QString>
+#include "vconstants.h"
+
+class VNoteFile
+{
+public:
+    VNoteFile(const QString &path, const QString &name, const QString &content,
+              DocType docType, bool modifiable);
+
+    QString path;
+    QString name;
+    QString content;
+    DocType docType;
+    bool modifiable;
+};
+
+#endif // VNOTEFILE_H

+ 16 - 16
vtabwidget.cpp

@@ -1,7 +1,7 @@
 #include <QtWidgets>
 #include <QtDebug>
 #include "vtabwidget.h"
-#include "vedit.h"
+#include "veditor.h"
 
 VTabWidget::VTabWidget(const QString &welcomePageUrl, QWidget *parent)
     : QTabWidget(parent), welcomePageUrl(welcomePageUrl)
@@ -59,11 +59,11 @@ void VTabWidget::openFile(QJsonObject fileJson)
 
 int VTabWidget::openFileInTab(const QString &path, const QString &name, bool modifiable)
 {
-    VEdit *edit = new VEdit(path, name, modifiable);
+    VEditor *editor = new VEditor(path, name, modifiable);
     QJsonObject tabJson;
     tabJson["path"] = path;
     tabJson["name"] = name;
-    int idx = appendTabWithData(edit, name, tabJson);
+    int idx = appendTabWithData(editor, name, tabJson);
     setTabToolTip(idx, path);
     return idx;
 }
@@ -85,32 +85,32 @@ int VTabWidget::findTabByFile(const QString &path, const QString &name)
 void VTabWidget::handleTabCloseRequest(int index)
 {
     qDebug() << "request closing tab" << index;
-    VEdit *edit = dynamic_cast<VEdit *>(widget(index));
-    Q_ASSERT(edit);
-    bool ok = edit->requestClose();
+    VEditor *editor = dynamic_cast<VEditor *>(widget(index));
+    Q_ASSERT(editor);
+    bool ok = editor->requestClose();
     if (ok) {
         removeTab(index);
-        delete edit;
+        delete editor;
     }
 }
 
 void VTabWidget::readFile()
 {
-    VEdit *edit = dynamic_cast<VEdit *>(currentWidget());
-    Q_ASSERT(edit);
-    edit->readFile();
+    VEditor *editor = dynamic_cast<VEditor *>(currentWidget());
+    Q_ASSERT(editor);
+    editor->readFile();
 }
 
 void VTabWidget::editFile()
 {
-    VEdit *edit = dynamic_cast<VEdit *>(currentWidget());
-    Q_ASSERT(edit);
-    edit->editFile();
+    VEditor *editor = dynamic_cast<VEditor *>(currentWidget());
+    Q_ASSERT(editor);
+    editor->editFile();
 }
 
 void VTabWidget::saveFile()
 {
-    VEdit *edit = dynamic_cast<VEdit *>(currentWidget());
-    Q_ASSERT(edit);
-    edit->saveFile();
+    VEditor *editor = dynamic_cast<VEditor *>(currentWidget());
+    Q_ASSERT(editor);
+    editor->saveFile();
 }