notebook: prompt for new root folder path when it is missing

This commit is contained in:
Le Tan 2018-04-03 19:38:29 +08:00
parent 373d839497
commit 86b9a2e93f
10 changed files with 286 additions and 31 deletions

View File

@ -0,0 +1,144 @@
#include "vfixnotebookdialog.h"
#include <QtWidgets>
#include "vconfigmanager.h"
#include "vlineedit.h"
#include "vnotebook.h"
#include "utils/vutils.h"
extern VConfigManager *g_config;
VFixNotebookDialog::VFixNotebookDialog(const VNotebook *p_notebook,
const QVector<VNotebook *> &p_notebooks,
QWidget *p_parent)
: QDialog(p_parent), m_notebook(p_notebook), m_notebooks(p_notebooks)
{
setupUI();
handleInputChanged();
}
void VFixNotebookDialog::setupUI()
{
QLabel *infoLabel = new QLabel(tr("VNote could not find the root folder of notebook "
"<span style=\"%1\">%2</span>. Please specify the new path "
"to the root folder if you moved it somewhere, or VNote "
"will just remove this notebook.")
.arg(g_config->c_dataTextStyle)
.arg(m_notebook->getName()), this);
infoLabel->setWordWrap(true);
QLabel *nameLabel = new QLabel(m_notebook->getName(), this);
m_pathEdit = new VLineEdit(m_notebook->getPath(), this);
connect(m_pathEdit, &VLineEdit::textChanged,
this, &VFixNotebookDialog::handleInputChanged);
m_browseBtn = new QPushButton(tr("&Browse"), this);
connect(m_browseBtn, &QPushButton::clicked,
this, &VFixNotebookDialog::handleBrowseBtnClicked);
QHBoxLayout *pathLayout = new QHBoxLayout();
pathLayout->addWidget(m_pathEdit);
pathLayout->addWidget(m_browseBtn);
QFormLayout *topLayout = new QFormLayout();
topLayout->addRow(tr("Notebook name:"), nameLabel);
topLayout->addRow(tr("Notebook root folder:"), pathLayout);
// Warning label.
m_warnLabel = new QLabel(this);
m_warnLabel->setWordWrap(true);
m_warnLabel->hide();
// 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);
okBtn->setProperty("SpecialBtn", true);
m_pathEdit->setMinimumWidth(okBtn->sizeHint().width() * 3);
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addWidget(infoLabel);
mainLayout->addLayout(topLayout);
mainLayout->addWidget(m_warnLabel);
mainLayout->addWidget(m_btnBox);
setLayout(mainLayout);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
setWindowTitle(tr("Fix Notebook"));
}
void VFixNotebookDialog::handleBrowseBtnClicked()
{
static QString defaultPath;
if (defaultPath.isEmpty()) {
defaultPath = g_config->getVnoteNotebookFolderPath();
if (!QFileInfo::exists(defaultPath)) {
defaultPath = g_config->getDocumentPathOrHomePath();
}
}
QString dirPath = QFileDialog::getExistingDirectory(this,
tr("Select Root Folder Of The Notebook"),
defaultPath,
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!dirPath.isEmpty()) {
m_pathEdit->setText(dirPath);
defaultPath = VUtils::basePathFromPath(dirPath);
}
}
void VFixNotebookDialog::handleInputChanged()
{
QString warnText = tr("<span style=\"%1\">WARNING</span>: The folder chosen is NOT a valid root "
"folder of a notebook.")
.arg(g_config->c_warningTextStyle);
bool pathOk = false;
QString path = m_pathEdit->text();
if (!path.isEmpty()) {
if (VConfigManager::directoryConfigExist(path)) {
pathOk = true;
}
}
if (pathOk) {
// Check if this path has been in VNote.
int idx = -1;
for (idx = 0; idx < m_notebooks.size(); ++idx) {
if (m_notebooks[idx] != m_notebook
&& VUtils::equalPath(m_notebooks[idx]->getPath(), path)) {
break;
}
}
if (idx < m_notebooks.size()) {
pathOk = false;
QString existText = tr("<span style=\"%1\">WARNING</span>: The folder chosen has already been a root folder "
"of existing notebook <span style=\"%2\">%3</span> in VNote.")
.arg(g_config->c_warningTextStyle)
.arg(g_config->c_dataTextStyle)
.arg(m_notebooks[idx]->getName());
m_warnLabel->setText(existText);
}
} else {
m_warnLabel->setText(warnText);
}
m_warnLabel->setVisible(!pathOk);
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
okBtn->setEnabled(pathOk);
}
QString VFixNotebookDialog::getPathInput() const
{
// absoluteFilePath() to convert the drive to upper case.
// cleanPath() to remove duplicate separator, '.', and '..'.
return QDir::cleanPath(QFileInfo(m_pathEdit->text()).absoluteFilePath());
}

View File

@ -0,0 +1,43 @@
#ifndef VFIXNOTEBOOKDIALOG_H
#define VFIXNOTEBOOKDIALOG_H
#include <QDialog>
class VNotebook;
class VLineEdit;
class QLabel;
class QPushButton;
class QDialogButtonBox;
class VFixNotebookDialog : public QDialog
{
Q_OBJECT
public:
VFixNotebookDialog(const VNotebook *p_notebook,
const QVector<VNotebook *> &p_notebooks,
QWidget *p_parent = nullptr);
QString getPathInput() const;
private slots:
void handleBrowseBtnClicked();
void handleInputChanged();
private:
void setupUI();
const VNotebook *m_notebook;
const QVector<VNotebook *> &m_notebooks;
VLineEdit *m_pathEdit;
QPushButton *m_browseBtn;
QLabel *m_warnLabel;
QDialogButtonBox *m_btnBox;
};
#endif // VFIXNOTEBOOKDIALOG_H

View File

@ -216,11 +216,13 @@ int main(int argc, char *argv[])
w.show();
w.checkNotebooks();
w.promptNewNotebookIfEmpty();
w.openStartupPages();
w.openFiles(filePaths);
w.promptNewNotebookIfEmpty();
return app.exec();
}

View File

@ -124,7 +124,8 @@ SOURCES += main.cpp\
vsearchue.cpp \
voutlineue.cpp \
vhelpue.cpp \
vlistfolderue.cpp
vlistfolderue.cpp \
dialog/vfixnotebookdialog.cpp
HEADERS += vmainwindow.h \
vdirectorytree.h \
@ -239,7 +240,8 @@ HEADERS += vmainwindow.h \
vsearchue.h \
voutlineue.h \
vhelpue.h \
vlistfolderue.h
vlistfolderue.h \
dialog/vfixnotebookdialog.h
RESOURCES += \
vnote.qrc \

View File

@ -44,6 +44,7 @@
#include "voutlineue.h"
#include "vhelpue.h"
#include "vlistfolderue.h"
#include "dialog/vfixnotebookdialog.h"
extern VConfigManager *g_config;
@ -108,7 +109,7 @@ VMainWindow::VMainWindow(VSingleInstanceGuard *p_guard, QWidget *p_parent)
setContextMenuPolicy(Qt::NoContextMenu);
notebookSelector->update();
m_notebookSelector->update();
initSharedMemoryWatcher();
@ -148,7 +149,7 @@ void VMainWindow::initCaptain()
void VMainWindow::registerCaptainAndNavigationTargets()
{
m_captain->registerNavigationTarget(notebookSelector);
m_captain->registerNavigationTarget(m_notebookSelector);
m_captain->registerNavigationTarget(directoryTree);
m_captain->registerNavigationTarget(m_fileList);
m_captain->registerNavigationTarget(m_editArea);
@ -234,9 +235,9 @@ void VMainWindow::setupUI()
connect(directoryTree, &VDirectoryTree::directoryUpdated,
m_editArea, &VEditArea::handleDirectoryUpdated);
connect(notebookSelector, &VNotebookSelector::notebookUpdated,
connect(m_notebookSelector, &VNotebookSelector::notebookUpdated,
m_editArea, &VEditArea::handleNotebookUpdated);
connect(notebookSelector, &VNotebookSelector::notebookCreated,
connect(m_notebookSelector, &VNotebookSelector::notebookCreated,
directoryTree, [this](const QString &p_name, bool p_import) {
Q_UNUSED(p_name);
if (!p_import) {
@ -283,9 +284,9 @@ QWidget *VMainWindow::setupDirectoryPanel()
QLabel *notebookLabel = new QLabel(tr("Notebooks"));
notebookLabel->setProperty("TitleLabel", true);
notebookSelector = new VNotebookSelector();
notebookSelector->setObjectName("NotebookSelector");
notebookSelector->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
m_notebookSelector = new VNotebookSelector();
m_notebookSelector->setObjectName("NotebookSelector");
m_notebookSelector->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
// Navigation panel.
QLabel *directoryLabel = new QLabel(tr("Folders"));
@ -316,7 +317,7 @@ QWidget *VMainWindow::setupDirectoryPanel()
QVBoxLayout *nbLayout = new QVBoxLayout;
nbLayout->addWidget(notebookLabel);
nbLayout->addWidget(notebookSelector);
nbLayout->addWidget(m_notebookSelector);
nbLayout->addWidget(m_naviSplitter);
nbLayout->setContentsMargins(3, 0, 0, 0);
nbLayout->setSpacing(0);
@ -324,13 +325,13 @@ QWidget *VMainWindow::setupDirectoryPanel()
nbContainer->setLayout(nbLayout);
nbContainer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
connect(notebookSelector, &VNotebookSelector::curNotebookChanged,
connect(m_notebookSelector, &VNotebookSelector::curNotebookChanged,
this, [this](VNotebook *p_notebook) {
directoryTree->setNotebook(p_notebook);
directoryTree->setFocus();
});
connect(notebookSelector, &VNotebookSelector::curNotebookChanged,
connect(m_notebookSelector, &VNotebookSelector::curNotebookChanged,
this, &VMainWindow::handleCurrentNotebookChanged);
connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
@ -2312,7 +2313,7 @@ bool VMainWindow::locateFile(VFile *p_file)
VNoteFile *file = dynamic_cast<VNoteFile *>(p_file);
VNotebook *notebook = file->getNotebook();
if (notebookSelector->locateNotebook(notebook)) {
if (m_notebookSelector->locateNotebook(notebook)) {
while (directoryTree->currentNotebook() != notebook) {
QCoreApplication::sendPostedEvents();
}
@ -2348,7 +2349,7 @@ bool VMainWindow::locateDirectory(VDirectory *p_directory)
}
VNotebook *notebook = p_directory->getNotebook();
if (notebookSelector->locateNotebook(notebook)) {
if (m_notebookSelector->locateNotebook(notebook)) {
while (directoryTree->currentNotebook() != notebook) {
QCoreApplication::sendPostedEvents();
}
@ -2833,7 +2834,7 @@ bool VMainWindow::exportByCaptain(void *p_target, void *p_data)
void VMainWindow::promptNewNotebookIfEmpty()
{
if (vnote->getNotebooks().isEmpty()) {
notebookSelector->newNotebook();
m_notebookSelector->newNotebook();
}
}
@ -3151,7 +3152,7 @@ void VMainWindow::updateEditReadAct(const VEditTab *p_tab)
void VMainWindow::handleExportAct()
{
VExportDialog dialog(notebookSelector->currentNotebook(),
VExportDialog dialog(m_notebookSelector->currentNotebook(),
directoryTree->currentDirectory(),
m_curFile,
m_cart,
@ -3162,7 +3163,7 @@ void VMainWindow::handleExportAct()
VNotebook *VMainWindow::getCurrentNotebook() const
{
return notebookSelector->currentNotebook();
return m_notebookSelector->currentNotebook();
}
void VMainWindow::activateUniversalEntry()
@ -3218,3 +3219,34 @@ void VMainWindow::initUniversalEntry()
m_ue->registerEntry('m', new VListFolderUE(this), 0);
m_ue->registerEntry('?', new VHelpUE(this), 0);
}
void VMainWindow::checkNotebooks()
{
bool updated = false;
QVector<VNotebook *> &notebooks = g_vnote->getNotebooks();
for (int i = 0; i < notebooks.size(); ++i) {
VNotebook *nb = notebooks[i];
if (nb->isValid()) {
continue;
}
VFixNotebookDialog dialog(nb, notebooks, this);
if (dialog.exec()) {
qDebug() << "fix path of notebook" << nb->getName() << "to" << dialog.getPathInput();
nb->updatePath(dialog.getPathInput());
} else {
notebooks.removeOne(nb);
--i;
}
updated = true;
}
if (updated) {
g_config->setNotebooks(notebooks);
m_notebookSelector->update();
}
m_notebookSelector->restoreCurrentNotebook();
}

View File

@ -102,6 +102,9 @@ public:
// Prompt user for new notebook if there is no notebook.
void promptNewNotebookIfEmpty();
// Check invalid notebooks. Set current notebook according to config.
void checkNotebooks();
VFile *getCurrentFile() const;
VEditTab *getCurrentTab() const;
@ -317,7 +320,7 @@ private:
VCaptain *m_captain;
VNotebookSelector *notebookSelector;
VNotebookSelector *m_notebookSelector;
VFileList *m_fileList;
VDirectoryTree *directoryTree;
@ -486,6 +489,6 @@ inline VDirectoryTree *VMainWindow::getDirectoryTree() const
inline VNotebookSelector *VMainWindow::getNotebookSelector() const
{
return notebookSelector;
return m_notebookSelector;
}
#endif // VMAINWINDOW_H

View File

@ -15,7 +15,7 @@ VNotebook::VNotebook(const QString &name, const QString &path, QObject *parent)
m_recycleBinFolder = g_config->getRecycleBinFolder();
m_rootDir = new VDirectory(this,
NULL,
VUtils::directoryNameFromPath(path),
VUtils::directoryNameFromPath(m_path),
QDateTime::currentDateTimeUtc());
}
@ -132,6 +132,10 @@ void VNotebook::close()
bool VNotebook::open()
{
if (!m_valid) {
return false;
}
QString recycleBinPath = getRecycleBinFolderPath();
if (!QFileInfo::exists(recycleBinPath)) {
QDir dir(m_path);
@ -386,3 +390,17 @@ QList<QString> VNotebook::collectFiles()
return files;
}
void VNotebook::updatePath(const QString &p_path)
{
Q_ASSERT(!isOpened());
m_valid = false;
m_path = QDir::cleanPath(p_path);
delete m_rootDir;
m_rootDir = new VDirectory(this,
NULL,
VUtils::directoryNameFromPath(m_path),
QDateTime::currentDateTimeUtc());
readConfigNotebook();
}

View File

@ -44,8 +44,11 @@ public:
VDirectory *tryLoadDirectory(const QString &p_path);
const QString &getName() const;
const QString &getPath() const;
void updatePath(const QString &p_path);
VDirectory *getRootDir() const;
void rename(const QString &p_name);

View File

@ -160,8 +160,6 @@ void VNotebookSelector::updateComboBox()
{
m_muted = true;
int index = g_config->getCurNotebookIndex();
clear();
m_listWidget->clear();
@ -179,16 +177,24 @@ void VNotebookSelector::updateComboBox()
if (m_notebooks.isEmpty()) {
g_config->setCurNotebookIndex(-1);
setCurrentIndex(0);
} else {
}
}
void VNotebookSelector::restoreCurrentNotebook()
{
int index = g_config->getCurNotebookIndex();
if (index < 0 || index >= m_notebooks.size()) {
index = 0;
}
const VNotebook *nb = NULL;
if (index >= 0 && index < m_notebooks.size()) {
if (index < m_notebooks.size()) {
nb = m_notebooks[index];
}
if (nb) {
setCurrentItemToNotebook(nb);
}
qDebug() << "notebooks" << m_notebooks.size() << "current index" << index;
}
void VNotebookSelector::setCurrentItemToNotebook(const VNotebook *p_notebook)

View File

@ -29,6 +29,8 @@ public:
VNotebook *currentNotebook() const;
void restoreCurrentNotebook();
// Implementations for VNavigationMode.
void registerNavigation(QChar p_majorKey) Q_DECL_OVERRIDE;
void showNavigation() Q_DECL_OVERRIDE;