mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
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 <tamlokveer@gmail.com>
This commit is contained in:
parent
b55ebe8f91
commit
e3e18d040c
@ -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
vconstants.h
Normal file
6
vconstants.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef VCONSTANTS_H
|
||||
#define VCONSTANTS_H
|
||||
|
||||
enum class DocType { Html, Markdown };
|
||||
|
||||
#endif
|
144
vedit.cpp
144
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()) {
|
||||
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()) {
|
||||
if (!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;
|
||||
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);
|
||||
}
|
||||
const QString &postfix = list.last();
|
||||
for (int i = 0; i < mdPostfix.size(); ++i) {
|
||||
if (postfix == mdPostfix[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
35
vedit.h
35
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
veditor.cpp
Normal file
167
veditor.cpp
Normal file
@ -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
veditor.h
Normal file
40
veditor.h
Normal file
@ -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
vnotefile.cpp
Normal file
9
vnotefile.cpp
Normal file
@ -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
vnotefile.h
Normal file
20
vnotefile.h
Normal file
@ -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
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user