support editing read-only files

This commit is contained in:
Le Tan 2017-10-22 21:26:39 +08:00
parent ae19191917
commit 73ee02d3b2
9 changed files with 103 additions and 53 deletions

View File

@ -141,20 +141,24 @@ void VEdit::beginEdit()
updateConfig(); updateConfig();
setReadOnly(false); setReadOnlyAndHighlight(false);
setModified(false); setModified(false);
} }
void VEdit::endEdit() void VEdit::endEdit()
{ {
setReadOnly(true); setReadOnlyAndHighlight(true);
} }
void VEdit::saveFile() void VEdit::saveFile()
{ {
Q_ASSERT(m_file->isModifiable());
if (!document()->isModified()) { if (!document()->isModified()) {
return; return;
} }
m_file->setContent(toHtml()); m_file->setContent(toHtml());
setModified(false); setModified(false);
} }
@ -600,12 +604,6 @@ void VEdit::highlightCurrentLine()
highlightExtraSelections(true); highlightExtraSelections(true);
} }
void VEdit::setReadOnly(bool p_ro)
{
QTextEdit::setReadOnly(p_ro);
highlightCurrentLine();
}
void VEdit::highlightSelectedWord() void VEdit::highlightSelectedWord()
{ {
QList<QTextEdit::ExtraSelection> &selects = m_extraSelections[(int)SelectionId::SelectedWord]; QList<QTextEdit::ExtraSelection> &selects = m_extraSelections[(int)SelectionId::SelectedWord];
@ -1469,3 +1467,9 @@ void VEdit::evaluateMagicWords()
setTextCursor(cursor); setTextCursor(cursor);
} }
} }
void VEdit::setReadOnlyAndHighlight(bool p_readonly)
{
setReadOnly(p_readonly);
highlightCurrentLine();
}

View File

@ -108,7 +108,6 @@ public:
const QString &p_replaceText, bool p_findNext); const QString &p_replaceText, bool p_findNext);
void replaceTextAll(const QString &p_text, uint p_options, void replaceTextAll(const QString &p_text, uint p_options,
const QString &p_replaceText); const QString &p_replaceText);
void setReadOnly(bool p_ro);
// Clear SearchedKeyword highlight. // Clear SearchedKeyword highlight.
void clearSearchedWordHighlight(); void clearSearchedWordHighlight();
@ -229,6 +228,9 @@ protected:
// Called in contextMenuEvent() to modify the context menu. // Called in contextMenuEvent() to modify the context menu.
virtual void alterContextMenu(QMenu *p_menu, const QList<QAction *> &p_actions); virtual void alterContextMenu(QMenu *p_menu, const QList<QAction *> &p_actions);
// Set read-only property and highlight current line.
void setReadOnlyAndHighlight(bool p_readonly);
private: private:
QLabel *m_wrapLabel; QLabel *m_wrapLabel;
QTimer *m_labelTimer; QTimer *m_labelTimer;

View File

@ -221,10 +221,10 @@ inline QString VEditWindow::generateTabText(int p_index, const VFile *p_file) co
return ""; return "";
} }
return QString("%1.%2%3").arg(QString::number(p_index + c_tabSequenceBase, 10)) return QString("%1.%2%3%4").arg(QString::number(p_index + c_tabSequenceBase, 10))
.arg(p_file->getName()) .arg(p_file->getName())
.arg(p_file->isModifiable() .arg(p_file->isModifiable() ? "" : "#")
? (p_file->isModified() ? "*" : "") : "#"); .arg(p_file->isModified() ? "*" : "");
} }
#endif // VEDITWINDOW_H #endif // VEDITWINDOW_H

View File

@ -59,6 +59,7 @@ void VFile::close()
bool VFile::save() bool VFile::save()
{ {
Q_ASSERT(m_opened); Q_ASSERT(m_opened);
Q_ASSERT(m_modifiable);
bool ret = VUtils::writeFileToDisk(fetchPath(), m_content); bool ret = VUtils::writeFileToDisk(fetchPath(), m_content);
if (ret) { if (ret) {
m_modifiedTimeUtc = QDateTime::currentDateTimeUtc(); m_modifiedTimeUtc = QDateTime::currentDateTimeUtc();

View File

@ -63,10 +63,6 @@ void VHtmlTab::showFileReadMode()
void VHtmlTab::showFileEditMode() void VHtmlTab::showFileEditMode()
{ {
if (!m_file->isModifiable()) {
return;
}
m_isEditMode = true; m_isEditMode = true;
m_editor->beginEdit(); m_editor->beginEdit();
@ -92,7 +88,7 @@ bool VHtmlTab::closeFile(bool p_forced)
void VHtmlTab::editFile() void VHtmlTab::editFile()
{ {
if (m_isEditMode || !m_file->isModifiable()) { if (m_isEditMode) {
return; return;
} }
@ -107,15 +103,26 @@ void VHtmlTab::readFile()
if (m_editor && m_editor->isModified()) { if (m_editor && m_editor->isModified()) {
// Prompt to save the changes. // Prompt to save the changes.
int ret = VUtils::showMessage(QMessageBox::Information, tr("Information"), bool modifiable = m_file->isModifiable();
int ret = VUtils::showMessage(QMessageBox::Information,
tr("Information"),
tr("Note <span style=\"%1\">%2</span> has been modified.") tr("Note <span style=\"%1\">%2</span> has been modified.")
.arg(g_config->c_dataTextStyle).arg(m_file->getName()), .arg(g_config->c_dataTextStyle).arg(m_file->getName()),
tr("Do you want to save your changes?"), tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, modifiable ? (QMessageBox::Save
QMessageBox::Save, this); | QMessageBox::Discard
| QMessageBox::Cancel)
: (QMessageBox::Discard
| QMessageBox::Cancel),
modifiable ? QMessageBox::Save
: QMessageBox::Cancel,
this);
switch (ret) { switch (ret) {
case QMessageBox::Save: case QMessageBox::Save:
saveFile(); if (!saveFile()) {
return;
}
// Fall through // Fall through
case QMessageBox::Discard: case QMessageBox::Discard:
@ -127,7 +134,7 @@ void VHtmlTab::readFile()
return; return;
default: default:
qWarning() << "wrong return value from QMessageBox:" << ret; Q_ASSERT(false);
return; return;
} }
} }
@ -145,10 +152,22 @@ bool VHtmlTab::saveFile()
return true; return true;
} }
bool ret; QString filePath = m_file->fetchPath();
if (!m_file->isModifiable()) {
VUtils::showMessage(QMessageBox::Warning,
tr("Warning"),
tr("Could not modify a read-only note <span style=\"%1\">%2</span>.")
.arg(g_config->c_dataTextStyle).arg(filePath),
tr("Please save your changes to other notes manually."),
QMessageBox::Ok,
QMessageBox::Ok,
this);
return false;
}
// Make sure the file already exists. Temporary deal with cases when user delete or move // Make sure the file already exists. Temporary deal with cases when user delete or move
// a file. // a file.
QString filePath = m_file->fetchPath();
if (!QFileInfo::exists(filePath)) { if (!QFileInfo::exists(filePath)) {
qWarning() << filePath << "being written has been removed"; qWarning() << filePath << "being written has been removed";
VUtils::showMessage(QMessageBox::Warning, tr("Warning"), tr("Fail to save note."), VUtils::showMessage(QMessageBox::Warning, tr("Warning"), tr("Fail to save note."),
@ -159,7 +178,7 @@ bool VHtmlTab::saveFile()
} }
m_editor->saveFile(); m_editor->saveFile();
ret = m_file->save(); bool ret = m_file->save();
if (!ret) { if (!ret) {
VUtils::showMessage(QMessageBox::Warning, tr("Warning"), tr("Fail to save note."), VUtils::showMessage(QMessageBox::Warning, tr("Warning"), tr("Fail to save note."),
tr("Fail to write to disk when saving a note. Please try it again."), tr("Fail to write to disk when saving a note. Please try it again."),

View File

@ -1793,9 +1793,9 @@ void VMainWindow::updateActionsStateFromTab(const VEditTab *p_tab)
discardExitAct->setVisible(file && editMode); discardExitAct->setVisible(file && editMode);
saveExitAct->setVisible(file && editMode); saveExitAct->setVisible(file && editMode);
editNoteAct->setEnabled(file && file->isModifiable() && !editMode); editNoteAct->setEnabled(file && !editMode);
editNoteAct->setVisible(!saveExitAct->isVisible()); editNoteAct->setVisible(!saveExitAct->isVisible());
saveNoteAct->setEnabled(file && editMode); saveNoteAct->setEnabled(file && editMode && file->isModifiable());
deleteNoteAct->setEnabled(file && file->getType() == FileType::Note); deleteNoteAct->setEnabled(file && file->getType() == FileType::Note);
noteInfoAct->setEnabled(file && !systemFile); noteInfoAct->setEnabled(file && !systemFile);
@ -1846,13 +1846,13 @@ void VMainWindow::handleAreaTabStatusUpdated(const VEditTabInfo &p_info)
title = QString("%1").arg(m_curFile->fetchPath()); title = QString("%1").arg(m_curFile->fetchPath());
} }
if (m_curFile->isModifiable()) { if (!m_curFile->isModifiable()) {
title.append('#');
}
if (m_curFile->isModified()) { if (m_curFile->isModified()) {
title.append('*'); title.append('*');
} }
} else {
title.append('#');
}
} }
updateWindowTitle(title); updateWindowTitle(title);

View File

@ -104,11 +104,11 @@ void VMdEdit::beginEdit()
if (m_freshEdit) { if (m_freshEdit) {
// Will set to false when all async jobs completed. // Will set to false when all async jobs completed.
setReadOnly(true); setReadOnlyAndHighlight(true);
// Disable and clear undo stacks temporary. // Disable and clear undo stacks temporary.
setUndoRedoEnabled(false); setUndoRedoEnabled(false);
} else { } else {
setReadOnly(false); setReadOnlyAndHighlight(false);
} }
updateHeaders(m_mdHighlighter->getHeaderRegions()); updateHeaders(m_mdHighlighter->getHeaderRegions());
@ -116,12 +116,14 @@ void VMdEdit::beginEdit()
void VMdEdit::endEdit() void VMdEdit::endEdit()
{ {
setReadOnly(true); setReadOnlyAndHighlight(true);
clearUnusedImages(); clearUnusedImages();
} }
void VMdEdit::saveFile() void VMdEdit::saveFile()
{ {
Q_ASSERT(m_file->isModifiable());
if (!document()->isModified()) { if (!document()->isModified()) {
return; return;
} }
@ -464,7 +466,9 @@ void VMdEdit::updateHeaders(const QVector<VElementRegion> &p_headerRegions)
m_headers.clear(); m_headers.clear();
bool autoSequence = m_config.m_enableHeadingSequence && !isReadOnly(); bool autoSequence = m_config.m_enableHeadingSequence
&& !isReadOnly()
&& m_file->isModifiable();
int headingSequenceBaseLevel = g_config->getHeadingSequenceBaseLevel(); int headingSequenceBaseLevel = g_config->getHeadingSequenceBaseLevel();
if (headingSequenceBaseLevel < 1 || headingSequenceBaseLevel > 6) { if (headingSequenceBaseLevel < 1 || headingSequenceBaseLevel > 6) {
headingSequenceBaseLevel = 1; headingSequenceBaseLevel = 1;
@ -523,9 +527,9 @@ QString VMdEdit::toPlainTextWithoutImg()
{ {
QString text; QString text;
bool readOnly = isReadOnly(); bool readOnly = isReadOnly();
setReadOnly(true); setReadOnlyAndHighlight(true);
text = getPlainTextWithoutPreviewImage(); text = getPlainTextWithoutPreviewImage();
setReadOnly(readOnly); setReadOnlyAndHighlight(readOnly);
return text; return text;
} }
@ -806,7 +810,9 @@ void VMdEdit::finishOneAsyncJob(int p_idx)
if (-1 == m_finishedAsyncJobs.indexOf(false)) { if (-1 == m_finishedAsyncJobs.indexOf(false)) {
// All jobs finished. // All jobs finished.
setUndoRedoEnabled(true); setUndoRedoEnabled(true);
setReadOnly(false);
setReadOnlyAndHighlight(false);
setModified(false); setModified(false);
m_freshEdit = false; m_freshEdit = false;
emit statusChanged(); emit statusChanged();

View File

@ -181,10 +181,6 @@ void VMdTab::viewWebByConverter()
void VMdTab::showFileEditMode() void VMdTab::showFileEditMode()
{ {
if (!m_file->isModifiable()) {
return;
}
VHeaderPointer header(m_currentHeader); VHeaderPointer header(m_currentHeader);
m_isEditMode = true; m_isEditMode = true;
@ -227,7 +223,7 @@ bool VMdTab::closeFile(bool p_forced)
void VMdTab::editFile() void VMdTab::editFile()
{ {
if (m_isEditMode || !m_file->isModifiable()) { if (m_isEditMode) {
return; return;
} }
@ -242,15 +238,25 @@ void VMdTab::readFile()
if (m_editor && m_editor->isModified()) { if (m_editor && m_editor->isModified()) {
// Prompt to save the changes. // Prompt to save the changes.
bool modifiable = m_file->isModifiable();
int ret = VUtils::showMessage(QMessageBox::Information, tr("Information"), int ret = VUtils::showMessage(QMessageBox::Information, tr("Information"),
tr("Note <span style=\"%1\">%2</span> has been modified.") tr("Note <span style=\"%1\">%2</span> has been modified.")
.arg(g_config->c_dataTextStyle).arg(m_file->getName()), .arg(g_config->c_dataTextStyle).arg(m_file->getName()),
tr("Do you want to save your changes?"), tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, modifiable ? (QMessageBox::Save
QMessageBox::Save, this); | QMessageBox::Discard
| QMessageBox::Cancel)
: (QMessageBox::Discard
| QMessageBox::Cancel),
modifiable ? QMessageBox::Save
: QMessageBox::Cancel,
this);
switch (ret) { switch (ret) {
case QMessageBox::Save: case QMessageBox::Save:
saveFile(); if (!saveFile()) {
return;
}
// Fall through // Fall through
case QMessageBox::Discard: case QMessageBox::Discard:
@ -286,10 +292,23 @@ bool VMdTab::saveFile()
return true; return true;
} }
QString filePath = m_file->fetchPath();
if (!m_file->isModifiable()) {
VUtils::showMessage(QMessageBox::Warning,
tr("Warning"),
tr("Could not modify a read-only note <span style=\"%1\">%2</span>.")
.arg(g_config->c_dataTextStyle).arg(filePath),
tr("Please save your changes to other notes manually."),
QMessageBox::Ok,
QMessageBox::Ok,
this);
return false;
}
bool ret = true; bool ret = true;
// Make sure the file already exists. Temporary deal with cases when user delete or move // Make sure the file already exists. Temporary deal with cases when user delete or move
// a file. // a file.
QString filePath = m_file->fetchPath();
if (!QFileInfo::exists(filePath)) { if (!QFileInfo::exists(filePath)) {
qWarning() << filePath << "being written has been removed"; qWarning() << filePath << "being written has been removed";
VUtils::showMessage(QMessageBox::Warning, tr("Warning"), tr("Fail to save note."), VUtils::showMessage(QMessageBox::Warning, tr("Warning"), tr("Fail to save note."),
@ -356,7 +375,7 @@ void VMdTab::setupMarkdownViewer()
void VMdTab::setupMarkdownEditor() void VMdTab::setupMarkdownEditor()
{ {
Q_ASSERT(m_file->isModifiable() && !m_editor); Q_ASSERT(!m_editor);
qDebug() << "create Markdown editor"; qDebug() << "create Markdown editor";
m_editor = new VMdEdit(m_file, m_document, m_mdConType, this); m_editor = new VMdEdit(m_file, m_document, m_mdConType, this);

View File

@ -169,12 +169,11 @@ inline VEdit *VMdTab::getEditor()
{ {
if (m_editor) { if (m_editor) {
return m_editor; return m_editor;
} else if (m_file->isModifiable()) { } else {
setupMarkdownEditor(); setupMarkdownEditor();
}
return m_editor; return m_editor;
} }
}
inline VEdit *VMdTab::getEditor() const inline VEdit *VMdTab::getEditor() const
{ {