diff --git a/src/dialog/vfileinfodialog.cpp b/src/dialog/vfileinfodialog.cpp index fdae507f..01a17042 100644 --- a/src/dialog/vfileinfodialog.cpp +++ b/src/dialog/vfileinfodialog.cpp @@ -39,6 +39,7 @@ void VFileInfoDialog::setupUI() if (infoLabel) { mainLayout->addWidget(infoLabel); } + mainLayout->addLayout(topLayout); mainLayout->addWidget(m_btnBox); mainLayout->setSizeConstraint(QLayout::SetFixedSize); diff --git a/src/dialog/vorphanfileinfodialog.cpp b/src/dialog/vorphanfileinfodialog.cpp new file mode 100644 index 00000000..bb3f0063 --- /dev/null +++ b/src/dialog/vorphanfileinfodialog.cpp @@ -0,0 +1,72 @@ +#include "vorphanfileinfodialog.h" + +#include +#include "vorphanfile.h" +#include "vconfigmanager.h" +#include "utils/vutils.h" + +extern VConfigManager vconfig; + +VOrphanFileInfoDialog::VOrphanFileInfoDialog(const VOrphanFile *p_file, QWidget *p_parent) + : QDialog(p_parent), m_file(p_file) +{ + setupUI(); + + connect(m_imageFolderEdit, &QLineEdit::textChanged, + this, &VOrphanFileInfoDialog::handleInputChanged); + + handleInputChanged(); +} + +void VOrphanFileInfoDialog::setupUI() +{ + QFormLayout *topLayout = new QFormLayout(); + + QLabel *fileLabel = new QLabel(m_file->retrivePath()); + topLayout->addRow(tr("File:"), fileLabel); + + QLabel *imageFolderLabel = new QLabel(tr("Image folder:")); + m_imageFolderEdit = new QLineEdit(m_file->getImageFolder()); + m_imageFolderEdit->setPlaceholderText(tr("Use global configuration (%1)") + .arg(vconfig.getImageFolderExt())); + QString imgFolderTip = tr("Set the path of the image folder to store images " + "of this file.\nIf absolute path is used, " + "VNote will not manage those images." + "(empty to use global configuration)"); + imageFolderLabel->setToolTip(imgFolderTip); + m_imageFolderEdit->setToolTip(imgFolderTip); + topLayout->addRow(imageFolderLabel, m_imageFolderEdit); + + // Ok is the default button. + m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(m_btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok); + m_imageFolderEdit->setMinimumWidth(okBtn->sizeHint().width() * 3); + + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->addLayout(topLayout); + mainLayout->addWidget(m_btnBox); + mainLayout->setSizeConstraint(QLayout::SetFixedSize); + + setLayout(mainLayout); + setWindowTitle(tr("External File Information")); +} + +QString VOrphanFileInfoDialog::getImageFolder() const +{ + return m_imageFolderEdit->text(); +} + +void VOrphanFileInfoDialog::handleInputChanged() +{ + bool ok = false; + QString imgFolder = m_imageFolderEdit->text(); + if (imgFolder.isEmpty() || VUtils::checkPathLegal(imgFolder)) { + ok = true; + } + + QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok); + okBtn->setEnabled(ok); +} diff --git a/src/dialog/vorphanfileinfodialog.h b/src/dialog/vorphanfileinfodialog.h new file mode 100644 index 00000000..f0d2a862 --- /dev/null +++ b/src/dialog/vorphanfileinfodialog.h @@ -0,0 +1,34 @@ +#ifndef VORPHANFILEINFODIALOG_H +#define VORPHANFILEINFODIALOG_H + +#include + +class VOrphanFile; +class QDialogButtonBox; +class QLineEdit; + +class VOrphanFileInfoDialog : public QDialog +{ + Q_OBJECT + +public: + VOrphanFileInfoDialog(const VOrphanFile *p_file, QWidget *p_parent = 0); + + // Get the custom image folder for this external file. + // Empty string indicates using global config. + QString getImageFolder() const; + +private slots: + // Handle the change of the image folder input. + void handleInputChanged(); + +private: + void setupUI(); + + const VOrphanFile *m_file; + + QDialogButtonBox *m_btnBox; + QLineEdit *m_imageFolderEdit; +}; + +#endif // VORPHANFILEINFODIALOG_H diff --git a/src/dialog/vsettingsdialog.cpp b/src/dialog/vsettingsdialog.cpp index d5d23c25..dd03eea5 100644 --- a/src/dialog/vsettingsdialog.cpp +++ b/src/dialog/vsettingsdialog.cpp @@ -270,6 +270,7 @@ VNoteManagementTab::VNoteManagementTab(QWidget *p_parent) m_imageFolderEdit = new QLineEdit(this); m_imageFolderEdit->setPlaceholderText(tr("Name of the image folder")); + m_imageFolderEdit->setToolTip(m_customImageFolder->toolTip()); QValidator *validator = new QRegExpValidator(QRegExp(VUtils::c_fileNameRegExp), this); m_imageFolderEdit->setValidator(validator); @@ -284,15 +285,16 @@ VNoteManagementTab::VNoteManagementTab(QWidget *p_parent) // External File. // Image folder. m_customImageFolderExt = new QCheckBox(tr("Custom image folder"), this); - m_customImageFolderExt->setToolTip(tr("Set the global name of the image folder to store images " + m_customImageFolderExt->setToolTip(tr("Set the path of the global image folder to store images " "of external files (restart VNote to make it work).\nYou " - "could use both absolute or relative path here. If you " - "use an absolute path, VNote will not manage\nthose images, " + "could use both absolute or relative path here. If " + "absolute path is used, VNote will not manage\nthose images, " "so you need to clean up unused images manually.")); connect(m_customImageFolderExt, &QCheckBox::stateChanged, this, &VNoteManagementTab::customImageFolderExtChanged); m_imageFolderEditExt = new QLineEdit(this); + m_imageFolderEditExt->setToolTip(m_customImageFolderExt->toolTip()); m_imageFolderEditExt->setPlaceholderText(tr("Name of the image folder")); QHBoxLayout *imageFolderExtLayout = new QHBoxLayout(); diff --git a/src/resources/vnote.qss b/src/resources/vnote.qss index 98f0c942..ac696ef6 100644 --- a/src/resources/vnote.qss +++ b/src/resources/vnote.qss @@ -281,3 +281,9 @@ QTabBar::close-button:focus { image: url(:/resources/icons/close.svg); background-color: @focus-color; } + +QLineEdit[VimCommandLine="true"] { + padding: 0px; + margin: 0px; + border: none; +} diff --git a/src/src.pro b/src/src.pro index 3ac35340..2dd1a518 100644 --- a/src/src.pro +++ b/src/src.pro @@ -70,7 +70,8 @@ SOURCES += main.cpp\ vvimindicator.cpp \ vbuttonwithwidget.cpp \ vtabindicator.cpp \ - dialog/vupdater.cpp + dialog/vupdater.cpp \ + dialog/vorphanfileinfodialog.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ @@ -128,7 +129,8 @@ HEADERS += vmainwindow.h \ vbuttonwithwidget.h \ vedittabinfo.h \ vtabindicator.h \ - dialog/vupdater.h + dialog/vupdater.h \ + dialog/vorphanfileinfodialog.h RESOURCES += \ vnote.qrc \ diff --git a/src/veditwindow.cpp b/src/veditwindow.cpp index 69c32b8f..03333c5b 100644 --- a/src/veditwindow.cpp +++ b/src/veditwindow.cpp @@ -5,14 +5,16 @@ #include "vnote.h" #include "vconfigmanager.h" #include "utils/vutils.h" -#include "vfile.h" +#include "vorphanfile.h" #include "vmainwindow.h" #include "veditarea.h" #include "vopenedlistmenu.h" #include "vmdtab.h" #include "vhtmltab.h" +#include "vfilelist.h" extern VConfigManager vconfig; +extern VNote *g_vnote; VEditWindow::VEditWindow(VNote *vnote, VEditArea *editArea, QWidget *parent) : QTabWidget(parent), vnote(vnote), m_editArea(editArea), @@ -62,7 +64,8 @@ void VEditWindow::initTabActions() connect(m_moveRightAct, &QAction::triggered, this, &VEditWindow::handleMoveRightAct); - m_closeTabAct = new QAction(tr("Close Tab"), this); + m_closeTabAct = new QAction(QIcon(":/resources/icons/close.svg"), + tr("Close Tab"), this); m_closeTabAct->setToolTip(tr("Close current note tab")); connect(m_closeTabAct, &QAction::triggered, this, [this](){ @@ -110,6 +113,24 @@ void VEditWindow::initTabActions() } } }); + + m_noteInfoAct = new QAction(QIcon(":/resources/icons/note_info.svg"), + tr("Note Info"), this); + m_noteInfoAct->setToolTip(tr("View and edit information of the note")); + connect(m_noteInfoAct, &QAction::triggered, + this, [this](){ + int tab = this->m_closeTabAct->data().toInt(); + Q_ASSERT(tab != -1); + + VEditTab *editor = getTab(tab); + QPointer file = editor->getFile(); + Q_ASSERT(file); + if (file->getType() == FileType::Normal) { + g_vnote->getMainWindow()->getFileList()->fileInfo(file); + } else if (file->getType() == FileType::Orphan) { + g_vnote->getMainWindow()->editOrphanFileInfo(file); + } + }); } void VEditWindow::setupCornerWidget() @@ -500,14 +521,21 @@ void VEditWindow::tabbarContextMenuRequested(QPoint p_pos) return; } - m_locateAct->setData(tab); VEditTab *editor = getTab(tab); - QPointer file = editor->getFile(); + VFile *file = editor->getFile(); if (file->getType() == FileType::Normal) { // Locate to folder. + m_locateAct->setData(tab); menu.addAction(m_locateAct); + m_noteInfoAct->setData(tab); + menu.addAction(m_noteInfoAct); + } else if (file->getType() == FileType::Orphan + && !dynamic_cast(file)->isSystemFile()) { + m_noteInfoAct->setData(tab); + menu.addAction(m_noteInfoAct); } + int totalWin = m_editArea->windowCount(); // When there is only one tab and one split window, there is no need to // display these two actions. diff --git a/src/veditwindow.h b/src/veditwindow.h index a8faa961..25506385 100644 --- a/src/veditwindow.h +++ b/src/veditwindow.h @@ -165,6 +165,9 @@ private: // Close tabs to the right in tab menu. QAction *m_closeRightAct; + + // View and edit info about this note. + QAction *m_noteInfoAct; }; inline QString VEditWindow::generateTooltip(const VFile *p_file) const diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index cf09d1ed..2f118a38 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -24,6 +24,7 @@ #include "vtabindicator.h" #include "dialog/vupdater.h" #include "vorphanfile.h" +#include "dialog/vorphanfileinfodialog.h" extern VConfigManager vconfig; @@ -1720,7 +1721,7 @@ void VMainWindow::shortcutHelp() docName = VNote::c_shortcutsDocFile_zh; } - VFile *file = vnote->getOrphanFile(docName, false); + VFile *file = vnote->getOrphanFile(docName, false, true); (dynamic_cast(file))->setNotebookName(tr("[Help]")); editArea->openFile(file, OpenFileMode::Read); } @@ -1815,3 +1816,15 @@ void VMainWindow::openExternalFiles(const QStringList &p_files) editArea->openFile(file, OpenFileMode::Read); } } + +void VMainWindow::editOrphanFileInfo(VFile *p_file) +{ + VOrphanFile *file = dynamic_cast(p_file); + Q_ASSERT(file); + + VOrphanFileInfoDialog dialog(file, this); + if (dialog.exec() == QDialog::Accepted) { + QString imgFolder = dialog.getImageFolder(); + file->setImageFolder(imgFolder); + } +} diff --git a/src/vmainwindow.h b/src/vmainwindow.h index 2e6f48c4..88167a90 100644 --- a/src/vmainwindow.h +++ b/src/vmainwindow.h @@ -44,6 +44,11 @@ public: void locateFile(VFile *p_file); void locateCurrentFile(); + VFileList *getFileList() const; + + // View and edit the information of @p_file, which is an orphan file. + void editOrphanFileInfo(VFile *p_file); + private slots: void importNoteFromFile(); void viewSettings(); @@ -213,4 +218,9 @@ private: QVector predefinedColorPixmaps; }; +inline VFileList *VMainWindow::getFileList() const +{ + return fileList; +} + #endif // VMAINWINDOW_H diff --git a/src/vmdeditoperations.cpp b/src/vmdeditoperations.cpp index 9606333a..da9cd732 100644 --- a/src/vmdeditoperations.cpp +++ b/src/vmdeditoperations.cpp @@ -672,31 +672,34 @@ void VMdEditOperations::decorateText(TextDecoration p_decoration) return; } + bool validDecoration = true; switch (p_decoration) { case TextDecoration::Bold: - m_vim->setMode(VimMode::Insert, false); decorateBold(); break; case TextDecoration::Italic: - m_vim->setMode(VimMode::Insert, false); decorateItalic(); break; case TextDecoration::Strikethrough: - m_vim->setMode(VimMode::Insert, false); decorateStrikethrough(); break; case TextDecoration::InlineCode: - m_vim->setMode(VimMode::Insert, false); decorateInlineCode(); break; default: + validDecoration = false; qDebug() << "decoration" << (int)p_decoration << "is not implemented yet"; break; } + + if (validDecoration && m_editConfig->m_enableVimMode) { + Q_ASSERT(m_vim); + m_vim->setMode(VimMode::Insert, false); + } } void VMdEditOperations::decorateBold() diff --git a/src/vnote.cpp b/src/vnote.cpp index 3ce7a915..af5c13e0 100644 --- a/src/vnote.cpp +++ b/src/vnote.cpp @@ -276,7 +276,7 @@ const QString &VNote::getMonospacedFont() const return font; } -VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable) +VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable, bool p_systemFile) { if (p_path.isEmpty()) { return NULL; @@ -285,8 +285,10 @@ VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable) // See if the file has already been opened before. for (auto const &file : m_externalFiles) { Q_ASSERT(file->getType() == FileType::Orphan); - if (file->retrivePath() == p_path - && file->isModifiable() == p_modifiable) { + VOrphanFile *oFile = dynamic_cast(file); + if (oFile->retrivePath() == p_path) { + Q_ASSERT(oFile->isModifiable() == p_modifiable); + Q_ASSERT(oFile->isSystemFile() == p_systemFile); return file; } } @@ -302,7 +304,7 @@ VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable) } // Create a VOrphanFile for p_path. - VOrphanFile *file = new VOrphanFile(p_path, this, p_modifiable); + VOrphanFile *file = new VOrphanFile(p_path, this, p_modifiable, p_systemFile); m_externalFiles.append(file); return file; } diff --git a/src/vnote.h b/src/vnote.h index 013f270f..158a06d6 100644 --- a/src/vnote.h +++ b/src/vnote.h @@ -67,15 +67,16 @@ public: static const QString c_shortcutsDocFile_en; static const QString c_shortcutsDocFile_zh; - inline const QVector > &getPalette() const; + const QVector > &getPalette() const; void initPalette(QPalette palette); QString getColorFromPalette(const QString &p_name) const; - inline VMainWindow *getMainWindow() const; + VMainWindow *getMainWindow() const; QString getNavigationLabelStyle(const QString &p_str) const; // Given the path of an external file, create a VFile struct. - VFile *getOrphanFile(const QString &p_path, bool p_modifiable); + VFile *getOrphanFile(const QString &p_path, bool p_modifiable, + bool p_systemFile = false); public slots: void updateTemplate(); diff --git a/src/vorphanfile.cpp b/src/vorphanfile.cpp index accbd469..f5a325c5 100644 --- a/src/vorphanfile.cpp +++ b/src/vorphanfile.cpp @@ -8,9 +8,10 @@ extern VConfigManager vconfig; -VOrphanFile::VOrphanFile(const QString &p_path, QObject *p_parent, bool p_modifiable) +VOrphanFile::VOrphanFile(const QString &p_path, QObject *p_parent, + bool p_modifiable, bool p_systemFile) : VFile(VUtils::fileNameFromPath(p_path), p_parent, FileType::Orphan, p_modifiable), - m_path(p_path), m_notebookName("[EXTERNAL]") + m_path(p_path), m_notebookName("[EXTERNAL]"), m_systemFile(p_systemFile) { qDebug() << "VOrphanFile" << p_path << m_name << p_modifiable; } @@ -130,6 +131,8 @@ bool VOrphanFile::rename(const QString &p_name) void VOrphanFile::setImageFolder(const QString &p_path) { + qDebug() << "orphan file" << retrivePath() << "image folder" + << m_imageFolder << "->" << p_path; m_imageFolder = p_path; } diff --git a/src/vorphanfile.h b/src/vorphanfile.h index f5c832f9..9c70804c 100644 --- a/src/vorphanfile.h +++ b/src/vorphanfile.h @@ -8,7 +8,8 @@ class VOrphanFile : public VFile { Q_OBJECT public: - VOrphanFile(const QString &p_path, QObject *p_parent, bool p_modifiable); + VOrphanFile(const QString &p_path, QObject *p_parent, + bool p_modifiable, bool p_systemFile = false); bool open() Q_DECL_OVERRIDE; QString retrivePath() const Q_DECL_OVERRIDE; @@ -27,12 +28,16 @@ public: void setImageFolder(const QString &p_path); + const QString getImageFolder() const; + // Whether the image folder is a relative path. bool isRelativeImageFolder() const Q_DECL_OVERRIDE; // Return the image folder part in an image link. QString getImageFolderInLink() const Q_DECL_OVERRIDE; + bool isSystemFile() const; + private: bool save() Q_DECL_OVERRIDE; void convert(DocType p_curType, DocType p_targetType) Q_DECL_OVERRIDE; @@ -50,7 +55,20 @@ private: // Empty to use the global default config. QString m_imageFolder; + // Whether it is a system internal file. + bool m_systemFile; + friend class VDirectory; }; +inline bool VOrphanFile::isSystemFile() const +{ + return m_systemFile; +} + +inline const QString VOrphanFile::getImageFolder() const +{ + return m_imageFolder; +} + #endif // VORPHANFILE_H diff --git a/src/vtabindicator.cpp b/src/vtabindicator.cpp index a724b21b..fda1d642 100644 --- a/src/vtabindicator.cpp +++ b/src/vtabindicator.cpp @@ -4,6 +4,7 @@ #include #include "vedittab.h" +#include "vorphanfile.h" VTabIndicator::VTabIndicator(QWidget *p_parent) : QWidget(p_parent) @@ -25,11 +26,16 @@ void VTabIndicator::setupUI() m_externalLabel->setToolTip(tr("This file is not managed by any notebook or folder")); m_externalLabel->setProperty("ColorTealLabel", true); + m_systemLabel = new QLabel(tr("System"), this); + m_systemLabel->setToolTip(tr("This file is a system file")); + m_systemLabel->setProperty("ColorGreenLabel", true); + m_cursorLabel = new QLabel(this); QHBoxLayout *mainLayout = new QHBoxLayout(this); mainLayout->addWidget(m_cursorLabel); mainLayout->addWidget(m_externalLabel); + mainLayout->addWidget(m_systemLabel); mainLayout->addWidget(m_readonlyLabel); mainLayout->addWidget(m_docTypeLabel); mainLayout->setContentsMargins(0, 0, 0, 0); @@ -73,6 +79,7 @@ void VTabIndicator::update(const VEditTabInfo &p_info) DocType docType = DocType::Html; bool readonly = false; bool external = false; + bool system = false; QString cursorStr; if (p_info.m_editTab) @@ -82,6 +89,7 @@ void VTabIndicator::update(const VEditTabInfo &p_info) docType = file->getDocType(); readonly = !file->isModifiable(); external = file->getType() == FileType::Orphan; + system = external && dynamic_cast(file)->isSystemFile(); if (editTab->isEditMode()) { int line = p_info.m_cursorBlockNumber + 1; @@ -107,4 +115,5 @@ void VTabIndicator::update(const VEditTabInfo &p_info) m_docTypeLabel->setText(docTypeToString(docType)); m_readonlyLabel->setVisible(readonly); m_externalLabel->setVisible(external); + m_systemLabel->setVisible(system); } diff --git a/src/vtabindicator.h b/src/vtabindicator.h index b5fb8e26..b029eaa8 100644 --- a/src/vtabindicator.h +++ b/src/vtabindicator.h @@ -28,6 +28,9 @@ private: // Indicate whether it is a normal note or an external file. QLabel *m_externalLabel; + // Indicate whether it is a system file. + QLabel *m_systemLabel; + // Indicate the position of current cursor. QLabel *m_cursorLabel; }; diff --git a/src/vvimindicator.cpp b/src/vvimindicator.cpp index bbc9cd6f..2289993c 100644 --- a/src/vvimindicator.cpp +++ b/src/vvimindicator.cpp @@ -23,6 +23,7 @@ VVimIndicator::VVimIndicator(QWidget *p_parent) void VVimIndicator::setupUI() { m_cmdLineEdit = new VVimCmdLineEdit(this); + m_cmdLineEdit->setProperty("VimCommandLine", true); connect(m_cmdLineEdit, &VVimCmdLineEdit::commandCancelled, this, [this](){ if (m_vim) {