support editing external files

This commit is contained in:
Le Tan 2017-07-14 23:05:18 +08:00
parent 30c9403a21
commit 8a56dc8b87
20 changed files with 379 additions and 43 deletions

View File

@ -257,6 +257,10 @@ void VReadEditTab::customWebZoomChanged(int p_state)
VNoteManagementTab::VNoteManagementTab(QWidget *p_parent) VNoteManagementTab::VNoteManagementTab(QWidget *p_parent)
: QWidget(p_parent) : QWidget(p_parent)
{ {
m_noteBox = new QGroupBox(tr("Notes"));
m_externalBox = new QGroupBox(tr("External Files"));
// Note.
// Image folder. // Image folder.
m_customImageFolder = new QCheckBox(tr("Custom image folder"), this); m_customImageFolder = new QCheckBox(tr("Custom image folder"), this);
m_customImageFolder->setToolTip(tr("Set the global name of the image folder to store images " m_customImageFolder->setToolTip(tr("Set the global name of the image folder to store images "
@ -273,8 +277,35 @@ VNoteManagementTab::VNoteManagementTab(QWidget *p_parent)
imageFolderLayout->addWidget(m_customImageFolder); imageFolderLayout->addWidget(m_customImageFolder);
imageFolderLayout->addWidget(m_imageFolderEdit); imageFolderLayout->addWidget(m_imageFolderEdit);
QFormLayout *mainLayout = new QFormLayout(); QFormLayout *noteLayout = new QFormLayout();
mainLayout->addRow(imageFolderLayout); noteLayout->addRow(imageFolderLayout);
m_noteBox->setLayout(noteLayout);
// 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 "
"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, "
"so you need to clean up unused images manually."));
connect(m_customImageFolderExt, &QCheckBox::stateChanged,
this, &VNoteManagementTab::customImageFolderExtChanged);
m_imageFolderEditExt = new QLineEdit(this);
m_imageFolderEditExt->setPlaceholderText(tr("Name of the image folder"));
QHBoxLayout *imageFolderExtLayout = new QHBoxLayout();
imageFolderExtLayout->addWidget(m_customImageFolderExt);
imageFolderExtLayout->addWidget(m_imageFolderEditExt);
QFormLayout *externalLayout = new QFormLayout();
externalLayout->addRow(imageFolderExtLayout);
m_externalBox->setLayout(externalLayout);
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addWidget(m_noteBox);
mainLayout->addWidget(m_externalBox);
setLayout(mainLayout); setLayout(mainLayout);
} }
@ -285,6 +316,10 @@ bool VNoteManagementTab::loadConfiguration()
return false; return false;
} }
if (!loadImageFolderExt()) {
return false;
}
return true; return true;
} }
@ -294,6 +329,10 @@ bool VNoteManagementTab::saveConfiguration()
return false; return false;
} }
if (!saveImageFolderExt()) {
return false;
}
return true; return true;
} }
@ -329,3 +368,36 @@ void VNoteManagementTab::customImageFolderChanged(int p_state)
m_imageFolderEdit->setEnabled(false); m_imageFolderEdit->setEnabled(false);
} }
} }
bool VNoteManagementTab::loadImageFolderExt()
{
bool isCustom = vconfig.isCustomImageFolderExt();
m_customImageFolderExt->setChecked(isCustom);
m_imageFolderEditExt->setText(vconfig.getImageFolderExt());
m_imageFolderEditExt->setEnabled(isCustom);
return true;
}
bool VNoteManagementTab::saveImageFolderExt()
{
if (m_customImageFolderExt->isChecked()) {
vconfig.setImageFolderExt(m_imageFolderEditExt->text());
} else {
vconfig.setImageFolderExt("");
}
return true;
}
void VNoteManagementTab::customImageFolderExtChanged(int p_state)
{
if (p_state == Qt::Checked) {
m_imageFolderEditExt->setEnabled(true);
m_imageFolderEditExt->selectAll();
m_imageFolderEditExt->setFocus();
} else {
m_imageFolderEditExt->setEnabled(false);
}
}

View File

@ -62,16 +62,27 @@ public:
bool loadConfiguration(); bool loadConfiguration();
bool saveConfiguration(); bool saveConfiguration();
QGroupBox *m_noteBox;
QGroupBox *m_externalBox;
// Image folder. // Image folder.
QCheckBox *m_customImageFolder; QCheckBox *m_customImageFolder;
QLineEdit *m_imageFolderEdit; QLineEdit *m_imageFolderEdit;
// Image folder of External File.
QCheckBox *m_customImageFolderExt;
QLineEdit *m_imageFolderEditExt;
private slots: private slots:
void customImageFolderChanged(int p_state); void customImageFolderChanged(int p_state);
void customImageFolderExtChanged(int p_state);
private: private:
bool loadImageFolder(); bool loadImageFolder();
bool saveImageFolder(); bool saveImageFolder();
bool loadImageFolderExt();
bool saveImageFolderExt();
}; };
class VSettingsDialog : public QDialog class VSettingsDialog : public QDialog

View File

@ -44,6 +44,9 @@ enable_image_caption=false
; Image folder name for the notes ; Image folder name for the notes
image_folder=_v_images image_folder=_v_images
; Image folder name for the external files
external_image_folder=_v_images
; Enable trailing space highlight ; Enable trailing space highlight
enable_trailing_space_highlight=true enable_trailing_space_highlight=true

View File

@ -228,6 +228,42 @@ QLabel[TitleLabel="true"] {
background-color: @base-color; background-color: @base-color;
} }
QLabel[ColorRedLabel="true"] {
padding-left: 3px;
padding-right: 3px;
font: bold;
color: white;
border-radius: 2px;
background-color: @Red7;
}
QLabel[ColorGreenLabel="true"] {
padding-left: 3px;
padding-right: 3px;
font: bold;
color: white;
border-radius: 2px;
background-color: @Green7;
}
QLabel[ColorGreyLabel="true"] {
padding-left: 3px;
padding-right: 3px;
font: bold;
color: white;
border-radius: 2px;
background-color: @Grey7;
}
QLabel[ColorTealLabel="true"] {
padding-left: 3px;
padding-right: 3px;
font: bold;
color: white;
border-radius: 2px;
background-color: @Teal7;
}
QWidget[NotebookPanel="true"] { QWidget[NotebookPanel="true"] {
padding-left: 3px; padding-left: 3px;
} }

View File

@ -142,6 +142,9 @@ void VConfigManager::initialize()
m_imageFolder = getConfigFromSettings("global", m_imageFolder = getConfigFromSettings("global",
"image_folder").toString(); "image_folder").toString();
m_imageFolderExt = getConfigFromSettings("global",
"external_image_folder").toString();
m_enableTrailingSpaceHighlight = getConfigFromSettings("global", m_enableTrailingSpaceHighlight = getConfigFromSettings("global",
"enable_trailing_space_highlight").toBool(); "enable_trailing_space_highlight").toBool();

View File

@ -194,6 +194,11 @@ public:
void setImageFolder(const QString &p_folder); void setImageFolder(const QString &p_folder);
bool isCustomImageFolder() const; bool isCustomImageFolder() const;
const QString &getImageFolderExt() const;
// Empty string to reset the default folder.
void setImageFolderExt(const QString &p_folder);
bool isCustomImageFolderExt() const;
bool getEnableTrailingSpaceHighlight() const; bool getEnableTrailingSpaceHighlight() const;
void setEnableTrailingSapceHighlight(bool p_enabled); void setEnableTrailingSapceHighlight(bool p_enabled);
@ -398,6 +403,10 @@ private:
// Each notebook can specify its custom folder. // Each notebook can specify its custom folder.
QString m_imageFolder; QString m_imageFolder;
// Global default folder name to store images of all external files.
// Each file can specify its custom folder.
QString m_imageFolderExt;
// Enable trailing-space highlight. // Enable trailing-space highlight.
bool m_enableTrailingSpaceHighlight; bool m_enableTrailingSpaceHighlight;
@ -992,6 +1001,32 @@ inline bool VConfigManager::isCustomImageFolder() const
return m_imageFolder != getDefaultConfig("global", "image_folder").toString(); return m_imageFolder != getDefaultConfig("global", "image_folder").toString();
} }
inline const QString &VConfigManager::getImageFolderExt() const
{
return m_imageFolderExt;
}
inline void VConfigManager::setImageFolderExt(const QString &p_folder)
{
if (p_folder.isEmpty()) {
// Reset the default folder.
m_imageFolderExt = resetDefaultConfig("global", "external_image_folder").toString();
return;
}
if (m_imageFolderExt == p_folder) {
return;
}
m_imageFolderExt = p_folder;
setConfigToSettings("global", "external_image_folder", m_imageFolderExt);
}
inline bool VConfigManager::isCustomImageFolderExt() const
{
return m_imageFolderExt != getDefaultConfig("global", "external_image_folder").toString();
}
inline bool VConfigManager::getEnableTrailingSpaceHighlight() const inline bool VConfigManager::getEnableTrailingSpaceHighlight() const
{ {
return m_enableTrailingSpaceHighlight; return m_enableTrailingSpaceHighlight;

View File

@ -275,3 +275,13 @@ bool VFile::rename(const QString &p_name)
return true; return true;
} }
bool VFile::isRelativeImageFolder() const
{
return true;
}
QString VFile::getImageFolderInLink() const
{
return getNotebook()->getImageFolder();
}

View File

@ -35,7 +35,10 @@ public:
virtual QString retrivePath() const; virtual QString retrivePath() const;
virtual QString retriveRelativePath() const; virtual QString retriveRelativePath() const;
virtual QString retriveBasePath() const; virtual QString retriveBasePath() const;
// The path of the image folder.
virtual QString retriveImagePath() const; virtual QString retriveImagePath() const;
bool isModified() const; bool isModified() const;
bool isModifiable() const; bool isModifiable() const;
bool isOpened() const; bool isOpened() const;
@ -52,6 +55,12 @@ public:
// Rename the file. // Rename the file.
virtual bool rename(const QString &p_name); virtual bool rename(const QString &p_name);
// Whether the image folder is a relative path.
virtual bool isRelativeImageFolder() const;
// Return the image folder part in an image link.
virtual QString getImageFolderInLink() const;
public slots: public slots:
void setModified(bool p_modified); void setModified(bool p_modified);

View File

@ -23,6 +23,7 @@
#include "vvimindicator.h" #include "vvimindicator.h"
#include "vtabindicator.h" #include "vtabindicator.h"
#include "dialog/vupdater.h" #include "dialog/vupdater.h"
#include "vorphanfile.h"
extern VConfigManager vconfig; extern VConfigManager vconfig;
@ -616,10 +617,32 @@ void VMainWindow::initFileMenu()
QMenu *fileMenu = menuBar()->addMenu(tr("&File")); QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->setToolTipsVisible(true); fileMenu->setToolTipsVisible(true);
// Open external files.
QAction *openAct = new QAction(tr("&Open"), this);
openAct->setToolTip(tr("Open external file to edit"));
connect(openAct, &QAction::triggered,
this, [this](){
static QString lastPath = QDir::homePath();
QStringList files = QFileDialog::getOpenFileNames(this,
tr("Select External Files To Open"),
lastPath);
if (files.isEmpty()) {
return;
}
// Update lastPath
lastPath = QFileInfo(files[0]).path();
openExternalFiles(files);
});
fileMenu->addAction(openAct);
// Import notes from files. // Import notes from files.
m_importNoteAct = newAction(QIcon(":/resources/icons/import_note.svg"), m_importNoteAct = newAction(QIcon(":/resources/icons/import_note.svg"),
tr("&Import Notes From Files"), this); tr("&Import Notes From Files"), this);
m_importNoteAct->setToolTip(tr("Import notes from external files into current folder")); m_importNoteAct->setToolTip(tr("Import notes from external files into current folder by copy"));
connect(m_importNoteAct, &QAction::triggered, connect(m_importNoteAct, &QAction::triggered,
this, &VMainWindow::importNoteFromFile); this, &VMainWindow::importNoteFromFile);
m_importNoteAct->setEnabled(false); m_importNoteAct->setEnabled(false);
@ -952,6 +975,7 @@ void VMainWindow::importNoteFromFile()
if (files.isEmpty()) { if (files.isEmpty()) {
return; return;
} }
// Update lastPath // Update lastPath
lastPath = QFileInfo(files[0]).path(); lastPath = QFileInfo(files[0]).path();
@ -1695,7 +1719,9 @@ void VMainWindow::shortcutHelp()
if (locale == "zh_CN") { if (locale == "zh_CN") {
docName = VNote::c_shortcutsDocFile_zh; docName = VNote::c_shortcutsDocFile_zh;
} }
VFile *file = vnote->getOrphanFile(docName);
VFile *file = vnote->getOrphanFile(docName, false);
(dynamic_cast<VOrphanFile *>(file))->setNotebookName(tr("[Help]"));
editArea->openFile(file, OpenFileMode::Read); editArea->openFile(file, OpenFileMode::Read);
} }
@ -1780,3 +1806,12 @@ void VMainWindow::handleVimStatusUpdated(const VVim *p_vim)
m_vimIndicator->show(); m_vimIndicator->show();
} }
} }
void VMainWindow::openExternalFiles(const QStringList &p_files)
{
qDebug() << "open external files" << p_files;
for (int i = 0; i < p_files.size(); ++i) {
VFile *file = vnote->getOrphanFile(p_files[i], true);
editArea->openFile(file, OpenFileMode::Read);
}
}

View File

@ -149,6 +149,9 @@ private:
const QString &p_text, const QString &p_text,
QObject *p_parent = nullptr); QObject *p_parent = nullptr);
// Open external files @p_files as orphan files.
void openExternalFiles(const QStringList &p_files);
VNote *vnote; VNote *vnote;
QPointer<VFile> m_curFile; QPointer<VFile> m_curFile;
QPointer<VEditTab> m_curTab; QPointer<VEditTab> m_curTab;

View File

@ -197,7 +197,11 @@ void VMdEdit::imageInserted(const QString &p_path)
{ {
ImageLink link; ImageLink link;
link.m_path = p_path; link.m_path = p_path;
link.m_type = ImageLink::LocalRelativeInternal; if (m_file->isRelativeImageFolder()) {
link.m_type = ImageLink::LocalRelativeInternal;
} else {
link.m_type = ImageLink::LocalAbsolute;
}
m_insertedImages.append(link); m_insertedImages.append(link);
} }
@ -217,7 +221,9 @@ void VMdEdit::clearUnusedImages()
for (int i = 0; i < m_insertedImages.size(); ++i) { for (int i = 0; i < m_insertedImages.size(); ++i) {
const ImageLink &link = m_insertedImages[i]; const ImageLink &link = m_insertedImages[i];
V_ASSERT(link.m_type == ImageLink::LocalRelativeInternal); if (link.m_type != ImageLink::LocalRelativeInternal) {
continue;
}
int j; int j;
for (j = 0; j < images.size(); ++j) { for (j = 0; j < images.size(); ++j) {

View File

@ -44,13 +44,16 @@ bool VMdEditOperations::insertImageFromMimeData(const QMimeData *source)
dialog.setBrowseable(false); dialog.setBrowseable(false);
dialog.setImage(image); dialog.setImage(image);
if (dialog.exec() == QDialog::Accepted) { if (dialog.exec() == QDialog::Accepted) {
insertImageFromQImage(dialog.getImageTitleInput(), m_file->retriveImagePath(), image); insertImageFromQImage(dialog.getImageTitleInput(),
m_file->retriveImagePath(),
m_file->getImageFolderInLink(),
image);
} }
return true; return true;
} }
void VMdEditOperations::insertImageFromQImage(const QString &title, const QString &path, void VMdEditOperations::insertImageFromQImage(const QString &title, const QString &path,
const QImage &image) const QString &folderInLink, const QImage &image)
{ {
QString fileName = VUtils::generateImageFileName(path, title); QString fileName = VUtils::generateImageFileName(path, title);
QString filePath = QDir(path).filePath(fileName); QString filePath = QDir(path).filePath(fileName);
@ -79,7 +82,7 @@ void VMdEditOperations::insertImageFromQImage(const QString &title, const QStrin
return; return;
} }
QString md = QString("![%1](%2/%3)").arg(title).arg(VUtils::directoryNameFromPath(path)).arg(fileName); QString md = QString("![%1](%2/%3)").arg(title).arg(folderInLink).arg(fileName);
insertTextAtCurPos(md); insertTextAtCurPos(md);
qDebug() << "insert image" << title << filePath; qDebug() << "insert image" << title << filePath;
@ -89,8 +92,8 @@ void VMdEditOperations::insertImageFromQImage(const QString &title, const QStrin
mdEditor->imageInserted(filePath); mdEditor->imageInserted(filePath);
} }
void VMdEditOperations::insertImageFromPath(const QString &title, void VMdEditOperations::insertImageFromPath(const QString &title, const QString &path,
const QString &path, const QString &oriImagePath) const QString &folderInLink, const QString &oriImagePath)
{ {
QString fileName = VUtils::generateImageFileName(path, title, QFileInfo(oriImagePath).suffix()); QString fileName = VUtils::generateImageFileName(path, title, QFileInfo(oriImagePath).suffix());
QString filePath = QDir(path).filePath(fileName); QString filePath = QDir(path).filePath(fileName);
@ -119,7 +122,7 @@ void VMdEditOperations::insertImageFromPath(const QString &title,
return; return;
} }
QString md = QString("![%1](%2/%3)").arg(title).arg(VUtils::directoryNameFromPath(path)).arg(fileName); QString md = QString("![%1](%2/%3)").arg(title).arg(folderInLink).arg(fileName);
insertTextAtCurPos(md); insertTextAtCurPos(md);
qDebug() << "insert image" << title << filePath; qDebug() << "insert image" << title << filePath;
@ -168,10 +171,12 @@ bool VMdEditOperations::insertImageFromURL(const QUrl &imageUrl)
if (isLocal) { if (isLocal) {
insertImageFromPath(dialog.getImageTitleInput(), insertImageFromPath(dialog.getImageTitleInput(),
m_file->retriveImagePath(), m_file->retriveImagePath(),
m_file->getImageFolderInLink(),
imagePath); imagePath);
} else { } else {
insertImageFromQImage(dialog.getImageTitleInput(), insertImageFromQImage(dialog.getImageTitleInput(),
m_file->retriveImagePath(), m_file->retriveImagePath(),
m_file->getImageFolderInLink(),
dialog.getImage()); dialog.getImage());
} }
} }
@ -186,7 +191,10 @@ bool VMdEditOperations::insertImage()
QString title = dialog.getImageTitleInput(); QString title = dialog.getImageTitleInput();
QString imagePath = dialog.getPathInput(); QString imagePath = dialog.getPathInput();
qDebug() << "insert image from" << imagePath << "as" << title; qDebug() << "insert image from" << imagePath << "as" << title;
insertImageFromPath(title, m_file->retriveImagePath(), imagePath); insertImageFromPath(title,
m_file->retriveImagePath(),
m_file->getImageFolderInLink(),
imagePath);
} }
return true; return true;
} }

View File

@ -26,12 +26,17 @@ public:
void decorateText(TextDecoration p_decoration) Q_DECL_OVERRIDE; void decorateText(TextDecoration p_decoration) Q_DECL_OVERRIDE;
private: private:
void insertImageFromPath(const QString &title, const QString &path, const QString &oriImagePath); // Insert image from @oriImagePath as @path.
// @folderInLink: the folder part in the image link.
void insertImageFromPath(const QString &title, const QString &path,
const QString &folderInLink, const QString &oriImagePath);
// @title: title of the inserted image; // @title: title of the inserted image;
// @path: the image folder path to insert the image in; // @path: the image folder path to insert the image in;
// @folderInLink: the folder part in the image link.
// @image: the image to be inserted; // @image: the image to be inserted;
void insertImageFromQImage(const QString &title, const QString &path, const QImage &image); void insertImageFromQImage(const QString &title, const QString &path,
const QString &folderInLink, const QImage &image);
// Key press handlers. // Key press handlers.
bool handleKeyTab(QKeyEvent *p_event); bool handleKeyTab(QKeyEvent *p_event);

View File

@ -77,6 +77,10 @@ void VNote::initPalette(QPalette palette)
m_palette.append(QPair<QString, QString>("Teal3", "#4DB6AC")); m_palette.append(QPair<QString, QString>("Teal3", "#4DB6AC"));
m_palette.append(QPair<QString, QString>("Teal4", "#26A69A")); m_palette.append(QPair<QString, QString>("Teal4", "#26A69A"));
m_palette.append(QPair<QString, QString>("Teal5", "#009688")); m_palette.append(QPair<QString, QString>("Teal5", "#009688"));
m_palette.append(QPair<QString, QString>("Teal6", "#00897B"));
m_palette.append(QPair<QString, QString>("Teal7", "#00796B"));
m_palette.append(QPair<QString, QString>("Teal8", "#00695C"));
m_palette.append(QPair<QString, QString>("Teal9", "#004D40"));
m_palette.append(QPair<QString, QString>("Indigo0", "#E8EAF6")); m_palette.append(QPair<QString, QString>("Indigo0", "#E8EAF6"));
m_palette.append(QPair<QString, QString>("Indigo1", "#C5CAE9")); m_palette.append(QPair<QString, QString>("Indigo1", "#C5CAE9"));
@ -272,7 +276,7 @@ const QString &VNote::getMonospacedFont() const
return font; return font;
} }
VFile *VNote::getOrphanFile(const QString &p_path) VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable)
{ {
if (p_path.isEmpty()) { if (p_path.isEmpty()) {
return NULL; return NULL;
@ -280,16 +284,25 @@ VFile *VNote::getOrphanFile(const QString &p_path)
// See if the file has already been opened before. // See if the file has already been opened before.
for (auto const &file : m_externalFiles) { for (auto const &file : m_externalFiles) {
if (file->getType() == FileType::Orphan && file->retrivePath() == p_path) { Q_ASSERT(file->getType() == FileType::Orphan);
qDebug() << "find a VFile for path" << p_path; if (file->retrivePath() == p_path
&& file->isModifiable() == p_modifiable) {
return file; return file;
} }
} }
// TODO: Clean up unopened file here. for (int i = 0; i < m_externalFiles.size(); ++i) {
VFile *file = m_externalFiles[i];
if (!file->isOpened()) {
qDebug() << "release orphan file" << file;
m_externalFiles.removeAt(i);
delete file;
--i;
}
}
// Create a VOrphanFile for p_path. // Create a VOrphanFile for p_path.
VOrphanFile *file = new VOrphanFile(p_path, this); VOrphanFile *file = new VOrphanFile(p_path, this, p_modifiable);
m_externalFiles.append(file); m_externalFiles.append(file);
return file; return file;
} }

View File

@ -75,7 +75,7 @@ public:
QString getNavigationLabelStyle(const QString &p_str) const; QString getNavigationLabelStyle(const QString &p_str) const;
// Given the path of an external file, create a VFile struct. // Given the path of an external file, create a VFile struct.
VFile *getOrphanFile(const QString &p_path); VFile *getOrphanFile(const QString &p_path, bool p_modifiable);
public slots: public slots:
void updateTemplate(); void updateTemplate();

View File

@ -80,16 +80,22 @@ void VOpenedListMenu::updateOpenedList()
// Whether add separator. // Whether add separator.
QString curNotebook = file->getNotebookName(); QString curNotebook = file->getNotebookName();
if (curNotebook != notebook || file->getDirectory() != directory) { if (curNotebook != notebook
|| file->getDirectory() != directory) {
notebook = curNotebook; notebook = curNotebook;
directory = file->getDirectory(); directory = file->getDirectory();
QString dirName; QString dirName;
if (!directory) { if (directory) {
dirName = file->retriveBasePath();
} else {
dirName = directory->getName(); dirName = directory->getName();
} }
QString text = QString("[%1] %2").arg(notebook).arg(dirName);
QString text;
if (dirName.isEmpty()) {
text = QString("[%1]").arg(notebook);
} else {
text = QString("[%1] %2").arg(notebook).arg(dirName);
}
QAction *sepAct = addSection(text); QAction *sepAct = addSection(text);
sepAct->setFont(sepFont); sepAct->setFont(sepFont);
} }

View File

@ -4,12 +4,15 @@
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vconfigmanager.h"
VOrphanFile::VOrphanFile(const QString &p_path, QObject *p_parent) extern VConfigManager vconfig;
: VFile(VUtils::fileNameFromPath(p_path), p_parent, FileType::Orphan, false),
m_path(p_path) VOrphanFile::VOrphanFile(const QString &p_path, QObject *p_parent, bool p_modifiable)
: VFile(VUtils::fileNameFromPath(p_path), p_parent, FileType::Orphan, p_modifiable),
m_path(p_path), m_notebookName("[EXTERNAL]")
{ {
qDebug() << "VOrphanFile" << p_path << m_name; qDebug() << "VOrphanFile" << p_path << m_name << p_modifiable;
} }
bool VOrphanFile::open() bool VOrphanFile::open()
@ -18,8 +21,10 @@ bool VOrphanFile::open()
if (m_opened) { if (m_opened) {
return true; return true;
} }
Q_ASSERT(m_content.isEmpty()); Q_ASSERT(m_content.isEmpty());
Q_ASSERT(QFileInfo::exists(m_path)); Q_ASSERT(QFileInfo::exists(m_path));
m_content = VUtils::readFileFromDisk(m_path); m_content = VUtils::readFileFromDisk(m_path);
m_modified = false; m_modified = false;
m_opened = true; m_opened = true;
@ -43,14 +48,24 @@ QString VOrphanFile::retriveBasePath() const
QString VOrphanFile::retriveImagePath() const QString VOrphanFile::retriveImagePath() const
{ {
V_ASSERT(false); QString folder = m_imageFolder;
return ""; if (m_imageFolder.isEmpty()) {
folder = vconfig.getImageFolderExt();
}
QFileInfo fi(folder);
if (fi.isAbsolute()) {
return folder;
} else {
return QDir(retriveBasePath()).filePath(folder);
}
} }
bool VOrphanFile::save() bool VOrphanFile::save()
{ {
V_ASSERT(false); Q_ASSERT(m_opened);
return false; Q_ASSERT(m_modifiable);
return VUtils::writeFileToDisk(retrivePath(), m_content);
} }
void VOrphanFile::convert(DocType /* p_curType */, DocType /* p_targetType */) void VOrphanFile::convert(DocType /* p_curType */, DocType /* p_targetType */)
@ -75,7 +90,12 @@ const VDirectory *VOrphanFile::getDirectory() const
QString VOrphanFile::getNotebookName() const QString VOrphanFile::getNotebookName() const
{ {
return "[EMPTY]"; return m_notebookName;
}
void VOrphanFile::setNotebookName(const QString &p_notebook)
{
m_notebookName = p_notebook;
} }
VNotebook *VOrphanFile::getNotebook() VNotebook *VOrphanFile::getNotebook()
@ -83,15 +103,16 @@ VNotebook *VOrphanFile::getNotebook()
return NULL; return NULL;
} }
void VOrphanFile::setContent(const QString & /* p_content */) void VOrphanFile::setContent(const QString & p_content)
{ {
V_ASSERT(false); m_content = p_content;
} }
bool VOrphanFile::isInternalImageFolder(const QString &p_path) const bool VOrphanFile::isInternalImageFolder(const QString &p_path) const
{ {
return VUtils::equalPath(VUtils::basePathFromPath(p_path), return VUtils::equalPath(VUtils::basePathFromPath(p_path),
VUtils::basePathFromPath(m_path)); retriveBasePath())
|| VUtils::equalPath(p_path, retriveImagePath());
} }
bool VOrphanFile::rename(const QString &p_name) bool VOrphanFile::rename(const QString &p_name)
@ -106,3 +127,28 @@ bool VOrphanFile::rename(const QString &p_name)
m_path = dir.filePath(m_name); m_path = dir.filePath(m_name);
return true; return true;
} }
void VOrphanFile::setImageFolder(const QString &p_path)
{
m_imageFolder = p_path;
}
bool VOrphanFile::isRelativeImageFolder() const
{
QString folder = m_imageFolder;
if (m_imageFolder.isEmpty()) {
folder = vconfig.getImageFolderExt();
}
return !QFileInfo(folder).isAbsolute();
}
QString VOrphanFile::getImageFolderInLink() const
{
QString folder = m_imageFolder;
if (m_imageFolder.isEmpty()) {
folder = vconfig.getImageFolderExt();
}
return folder;
}

View File

@ -4,12 +4,12 @@
#include "vfile.h" #include "vfile.h"
// VOrphanFile is file not belong to any notebooks or directories. // VOrphanFile is file not belong to any notebooks or directories.
// Given the path of the file, VNote could load its content as read-only.
class VOrphanFile : public VFile class VOrphanFile : public VFile
{ {
Q_OBJECT Q_OBJECT
public: public:
VOrphanFile(const QString &p_path, QObject *p_parent); VOrphanFile(const QString &p_path, QObject *p_parent, bool p_modifiable);
bool open() Q_DECL_OVERRIDE; bool open() Q_DECL_OVERRIDE;
QString retrivePath() const Q_DECL_OVERRIDE; QString retrivePath() const Q_DECL_OVERRIDE;
QString retriveRelativePath() const Q_DECL_OVERRIDE; QString retriveRelativePath() const Q_DECL_OVERRIDE;
@ -17,11 +17,22 @@ public:
VDirectory *getDirectory() Q_DECL_OVERRIDE; VDirectory *getDirectory() Q_DECL_OVERRIDE;
const VDirectory *getDirectory() const Q_DECL_OVERRIDE; const VDirectory *getDirectory() const Q_DECL_OVERRIDE;
QString getNotebookName() const Q_DECL_OVERRIDE; QString getNotebookName() const Q_DECL_OVERRIDE;
void setNotebookName(const QString &p_notebook);
VNotebook *getNotebook() Q_DECL_OVERRIDE; VNotebook *getNotebook() Q_DECL_OVERRIDE;
// Rename file. // Rename file.
bool rename(const QString &p_name) Q_DECL_OVERRIDE; bool rename(const QString &p_name) Q_DECL_OVERRIDE;
void setImageFolder(const QString &p_path);
// 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;
private: private:
bool save() Q_DECL_OVERRIDE; bool save() Q_DECL_OVERRIDE;
void convert(DocType p_curType, DocType p_targetType) Q_DECL_OVERRIDE; void convert(DocType p_curType, DocType p_targetType) Q_DECL_OVERRIDE;
@ -31,6 +42,14 @@ private:
bool isInternalImageFolder(const QString &p_path) const Q_DECL_OVERRIDE; bool isInternalImageFolder(const QString &p_path) const Q_DECL_OVERRIDE;
QString m_path; QString m_path;
QString m_notebookName;
// Image folder path of this file.
// It could be an absolute or relative path.
// Empty to use the global default config.
QString m_imageFolder;
friend class VDirectory; friend class VDirectory;
}; };

View File

@ -14,12 +14,22 @@ VTabIndicator::VTabIndicator(QWidget *p_parent)
void VTabIndicator::setupUI() void VTabIndicator::setupUI()
{ {
m_docTypeLabel = new QLabel(this); m_docTypeLabel = new QLabel(this);
m_readonlyLabel = new QLabel(tr("<span style=\"font-weight:bold; color:red;\">ReadOnly</span>"), m_docTypeLabel->setToolTip(tr("The type of the file"));
this); m_docTypeLabel->setProperty("ColorGreyLabel", true);
m_readonlyLabel = new QLabel(tr("ReadOnly"), this);
m_readonlyLabel->setToolTip(tr("This file is read-only"));
m_readonlyLabel->setProperty("ColorRedLabel", true);
m_externalLabel = new QLabel(tr("Standalone"), this);
m_externalLabel->setToolTip(tr("This file is not managed by any notebook or folder"));
m_externalLabel->setProperty("ColorTealLabel", true);
m_cursorLabel = new QLabel(this); m_cursorLabel = new QLabel(this);
QHBoxLayout *mainLayout = new QHBoxLayout(this); QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->addWidget(m_cursorLabel); mainLayout->addWidget(m_cursorLabel);
mainLayout->addWidget(m_externalLabel);
mainLayout->addWidget(m_readonlyLabel); mainLayout->addWidget(m_readonlyLabel);
mainLayout->addWidget(m_docTypeLabel); mainLayout->addWidget(m_docTypeLabel);
mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setContentsMargins(0, 0, 0, 0);
@ -61,7 +71,8 @@ void VTabIndicator::update(const VEditTabInfo &p_info)
const VEditTab *editTab = NULL; const VEditTab *editTab = NULL;
const VFile *file = NULL; const VFile *file = NULL;
DocType docType = DocType::Html; DocType docType = DocType::Html;
bool readonly = true; bool readonly = false;
bool external = false;
QString cursorStr; QString cursorStr;
if (p_info.m_editTab) if (p_info.m_editTab)
@ -70,6 +81,7 @@ void VTabIndicator::update(const VEditTabInfo &p_info)
file = editTab->getFile(); file = editTab->getFile();
docType = file->getDocType(); docType = file->getDocType();
readonly = !file->isModifiable(); readonly = !file->isModifiable();
external = file->getType() == FileType::Orphan;
if (editTab->isEditMode()) { if (editTab->isEditMode()) {
int line = p_info.m_cursorBlockNumber + 1; int line = p_info.m_cursorBlockNumber + 1;
@ -94,4 +106,5 @@ void VTabIndicator::update(const VEditTabInfo &p_info)
m_docTypeLabel->setText(docTypeToString(docType)); m_docTypeLabel->setText(docTypeToString(docType));
m_readonlyLabel->setVisible(readonly); m_readonlyLabel->setVisible(readonly);
m_externalLabel->setVisible(external);
} }

View File

@ -25,6 +25,9 @@ private:
// Indicate the readonly property. // Indicate the readonly property.
QLabel *m_readonlyLabel; QLabel *m_readonlyLabel;
// Indicate whether it is a normal note or an external file.
QLabel *m_externalLabel;
// Indicate the position of current cursor. // Indicate the position of current cursor.
QLabel *m_cursorLabel; QLabel *m_cursorLabel;
}; };