mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-06 14:29:54 +08:00
support custom startup pages
- Support continuing where user left off on startup; - Support recovering the edit/read mode and the anchor position; - Support opening user-specified files on startup; - Add config startup_page_type, startup_pages, and last_opened_files;
This commit is contained in:
parent
fa870f132e
commit
598e8144bb
@ -142,7 +142,8 @@ void VNewNotebookDialog::handleBrowseBtnClicked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString dirPath = QFileDialog::getExistingDirectory(this, tr("Select Root Folder Of The Notebook"),
|
QString dirPath = QFileDialog::getExistingDirectory(this,
|
||||||
|
tr("Select Root Folder Of The Notebook"),
|
||||||
defaultPath,
|
defaultPath,
|
||||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||||
|
|
||||||
|
@ -169,9 +169,6 @@ VGeneralTab::VGeneralTab(QWidget *p_parent)
|
|||||||
m_langCombo->addItem(lang.second, lang.first);
|
m_langCombo->addItem(lang.second, lang.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
QLabel *langLabel = new QLabel(tr("Language:"), this);
|
|
||||||
langLabel->setToolTip(m_langCombo->toolTip());
|
|
||||||
|
|
||||||
// System tray checkbox.
|
// System tray checkbox.
|
||||||
m_systemTray = new QCheckBox(tr("System tray"), this);
|
m_systemTray = new QCheckBox(tr("System tray"), this);
|
||||||
m_systemTray->setToolTip(tr("Minimized to the system tray after closing VNote"
|
m_systemTray->setToolTip(tr("Minimized to the system tray after closing VNote"
|
||||||
@ -181,9 +178,13 @@ VGeneralTab::VGeneralTab(QWidget *p_parent)
|
|||||||
m_systemTray->setEnabled(false);
|
m_systemTray->setEnabled(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Startup pages.
|
||||||
|
QLayout *startupLayout = setupStartupPagesLayout();
|
||||||
|
|
||||||
QFormLayout *optionLayout = new QFormLayout();
|
QFormLayout *optionLayout = new QFormLayout();
|
||||||
optionLayout->addRow(langLabel, m_langCombo);
|
optionLayout->addRow(tr("Language:"), m_langCombo);
|
||||||
optionLayout->addRow(m_systemTray);
|
optionLayout->addRow(m_systemTray);
|
||||||
|
optionLayout->addRow(tr("Startup pages:"), startupLayout);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||||
mainLayout->addLayout(optionLayout);
|
mainLayout->addLayout(optionLayout);
|
||||||
@ -191,6 +192,60 @@ VGeneralTab::VGeneralTab(QWidget *p_parent)
|
|||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QLayout *VGeneralTab::setupStartupPagesLayout()
|
||||||
|
{
|
||||||
|
m_startupPageTypeCombo = new QComboBox(this);
|
||||||
|
m_startupPageTypeCombo->setToolTip(tr("Restore tabs or open specific notes on startup"));
|
||||||
|
m_startupPageTypeCombo->addItem(tr("None"), (int)StartupPageType::None);
|
||||||
|
m_startupPageTypeCombo->addItem(tr("Continue where you left off"), (int)StartupPageType::ContinueLeftOff);
|
||||||
|
m_startupPageTypeCombo->addItem(tr("Open specific pages"), (int)StartupPageType::SpecificPages);
|
||||||
|
connect(m_startupPageTypeCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
|
||||||
|
this, [this](int p_index) {
|
||||||
|
int type = m_startupPageTypeCombo->itemData(p_index).toInt();
|
||||||
|
bool pagesEditVisible = type == (int)StartupPageType::SpecificPages;
|
||||||
|
m_startupPagesEdit->setVisible(pagesEditVisible);
|
||||||
|
m_startupPagesAddBtn->setVisible(pagesEditVisible);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_startupPagesEdit = new QPlainTextEdit(this);
|
||||||
|
m_startupPagesEdit->setToolTip(tr("Absolute path of the notes to open on startup (one note per line)"));
|
||||||
|
|
||||||
|
m_startupPagesAddBtn = new QPushButton(tr("Browse"), this);
|
||||||
|
m_startupPagesAddBtn->setToolTip(tr("Select files to add as startup pages"));
|
||||||
|
connect(m_startupPagesAddBtn, &QPushButton::clicked,
|
||||||
|
this, [this]() {
|
||||||
|
static QString lastPath = QDir::homePath();
|
||||||
|
QStringList files = QFileDialog::getOpenFileNames(this,
|
||||||
|
tr("Select Files As Startup Pages"),
|
||||||
|
lastPath);
|
||||||
|
if (files.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update lastPath
|
||||||
|
lastPath = QFileInfo(files[0]).path();
|
||||||
|
|
||||||
|
m_startupPagesEdit->appendPlainText(files.join("\n"));
|
||||||
|
});
|
||||||
|
|
||||||
|
QHBoxLayout *startupPagesBtnLayout = new QHBoxLayout();
|
||||||
|
startupPagesBtnLayout->addStretch();
|
||||||
|
startupPagesBtnLayout->addWidget(m_startupPagesAddBtn);
|
||||||
|
|
||||||
|
QVBoxLayout *startupPagesLayout = new QVBoxLayout();
|
||||||
|
startupPagesLayout->addWidget(m_startupPagesEdit);
|
||||||
|
startupPagesLayout->addLayout(startupPagesBtnLayout);
|
||||||
|
|
||||||
|
QVBoxLayout *startupLayout = new QVBoxLayout();
|
||||||
|
startupLayout->addWidget(m_startupPageTypeCombo);
|
||||||
|
startupLayout->addLayout(startupPagesLayout);
|
||||||
|
|
||||||
|
m_startupPagesEdit->hide();
|
||||||
|
m_startupPagesAddBtn->hide();
|
||||||
|
|
||||||
|
return startupLayout;
|
||||||
|
}
|
||||||
|
|
||||||
bool VGeneralTab::loadConfiguration()
|
bool VGeneralTab::loadConfiguration()
|
||||||
{
|
{
|
||||||
if (!loadLanguage()) {
|
if (!loadLanguage()) {
|
||||||
@ -201,6 +256,10 @@ bool VGeneralTab::loadConfiguration()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!loadStartupPageType()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +273,10 @@ bool VGeneralTab::saveConfiguration()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!saveStartupPageType()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,6 +327,42 @@ bool VGeneralTab::saveSystemTray()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VGeneralTab::loadStartupPageType()
|
||||||
|
{
|
||||||
|
StartupPageType type = g_config->getStartupPageType();
|
||||||
|
bool found = false;
|
||||||
|
for (int i = 0; i < m_startupPageTypeCombo->count(); ++i) {
|
||||||
|
if (m_startupPageTypeCombo->itemData(i).toInt() == (int)type) {
|
||||||
|
found = true;
|
||||||
|
m_startupPageTypeCombo->setCurrentIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ASSERT(found);
|
||||||
|
|
||||||
|
const QStringList &pages = g_config->getStartupPages();
|
||||||
|
m_startupPagesEdit->setPlainText(pages.join("\n"));
|
||||||
|
|
||||||
|
bool pagesEditVisible = type == StartupPageType::SpecificPages;
|
||||||
|
m_startupPagesEdit->setVisible(pagesEditVisible);
|
||||||
|
m_startupPagesAddBtn->setVisible(pagesEditVisible);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VGeneralTab::saveStartupPageType()
|
||||||
|
{
|
||||||
|
StartupPageType type = (StartupPageType)m_startupPageTypeCombo->currentData().toInt();
|
||||||
|
g_config->setStartupPageType(type);
|
||||||
|
|
||||||
|
if (type == StartupPageType::SpecificPages) {
|
||||||
|
QStringList pages = m_startupPagesEdit->toPlainText().split("\n");
|
||||||
|
g_config->setStartupPages(pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
VReadEditTab::VReadEditTab(QWidget *p_parent)
|
VReadEditTab::VReadEditTab(QWidget *p_parent)
|
||||||
: QWidget(p_parent)
|
: QWidget(p_parent)
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,8 @@ class QCheckBox;
|
|||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QStackedLayout;
|
class QStackedLayout;
|
||||||
class QListWidget;
|
class QListWidget;
|
||||||
|
class QPlainTextEdit;
|
||||||
|
class QVBoxLayout;
|
||||||
|
|
||||||
class VGeneralTab : public QWidget
|
class VGeneralTab : public QWidget
|
||||||
{
|
{
|
||||||
@ -23,18 +25,32 @@ public:
|
|||||||
bool saveConfiguration();
|
bool saveConfiguration();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QLayout *setupStartupPagesLayout();
|
||||||
|
|
||||||
bool loadLanguage();
|
bool loadLanguage();
|
||||||
bool saveLanguage();
|
bool saveLanguage();
|
||||||
|
|
||||||
bool loadSystemTray();
|
bool loadSystemTray();
|
||||||
bool saveSystemTray();
|
bool saveSystemTray();
|
||||||
|
|
||||||
|
bool loadStartupPageType();
|
||||||
|
bool saveStartupPageType();
|
||||||
|
|
||||||
// Language
|
// Language
|
||||||
QComboBox *m_langCombo;
|
QComboBox *m_langCombo;
|
||||||
|
|
||||||
// System tray
|
// System tray
|
||||||
QCheckBox *m_systemTray;
|
QCheckBox *m_systemTray;
|
||||||
|
|
||||||
|
// Startup page type.
|
||||||
|
QComboBox *m_startupPageTypeCombo;
|
||||||
|
|
||||||
|
// Startup pages.
|
||||||
|
QPlainTextEdit *m_startupPagesEdit;
|
||||||
|
|
||||||
|
// Startup pages add files button.
|
||||||
|
QPushButton *m_startupPagesAddBtn;
|
||||||
|
|
||||||
static const QVector<QString> c_availableLangs;
|
static const QVector<QString> c_availableLangs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
22
src/main.cpp
22
src/main.cpp
@ -116,22 +116,10 @@ int main(int argc, char *argv[])
|
|||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
// The file path passed via command line arguments.
|
// The file path passed via command line arguments.
|
||||||
QStringList filePaths;
|
QStringList filePaths = VUtils::filterFilePathsToOpen(app.arguments().mid(1));
|
||||||
QStringList args = app.arguments();
|
|
||||||
for (int i = 1; i < args.size(); ++i) {
|
|
||||||
if (QFileInfo::exists(args[i])) {
|
|
||||||
QString filePath = args[i];
|
|
||||||
QFileInfo fi(filePath);
|
|
||||||
if (fi.isFile()) {
|
|
||||||
// Need to use absolute path here since VNote may be launched
|
|
||||||
// in different working directory.
|
|
||||||
filePath = QDir::cleanPath(fi.absoluteFilePath());
|
|
||||||
filePaths.append(filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "command line arguments" << args;
|
qDebug() << "command line arguments" << app.arguments();
|
||||||
|
qDebug() << "files to open from arguments" << filePaths;
|
||||||
|
|
||||||
if (!canRun) {
|
if (!canRun) {
|
||||||
// Ask another instance to open files passed in.
|
// Ask another instance to open files passed in.
|
||||||
@ -178,7 +166,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
w.show();
|
w.show();
|
||||||
|
|
||||||
w.openExternalFiles(filePaths);
|
w.openFiles(filePaths);
|
||||||
|
|
||||||
|
w.openStartupPages();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,16 @@ enable_compact_mode=false
|
|||||||
; Whether enable tools dock widget
|
; Whether enable tools dock widget
|
||||||
tools_dock_checked=true
|
tools_dock_checked=true
|
||||||
|
|
||||||
|
; Pages to open on startup
|
||||||
|
; 0 - none; 1 - Continue where you left off; 2 - specific pages
|
||||||
|
startup_page_type=0
|
||||||
|
|
||||||
|
; Specific pages to open on startup when startup_page_type is 2
|
||||||
|
; A list of file path separated by ,
|
||||||
|
; Notice: should escape \ by \\
|
||||||
|
; C:\users\vnote\vnote.md -> C:\\users\\vnote\\vnote.md
|
||||||
|
startup_pages=
|
||||||
|
|
||||||
[web]
|
[web]
|
||||||
; Location and configuration for Mathjax
|
; Location and configuration for Mathjax
|
||||||
mathjax_javascript=https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML
|
mathjax_javascript=https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML
|
||||||
|
@ -77,7 +77,8 @@ SOURCES += main.cpp\
|
|||||||
dialog/vconfirmdeletiondialog.cpp \
|
dialog/vconfirmdeletiondialog.cpp \
|
||||||
vnotefile.cpp \
|
vnotefile.cpp \
|
||||||
vattachmentlist.cpp \
|
vattachmentlist.cpp \
|
||||||
dialog/vsortdialog.cpp
|
dialog/vsortdialog.cpp \
|
||||||
|
vfilesessioninfo.cpp
|
||||||
|
|
||||||
HEADERS += vmainwindow.h \
|
HEADERS += vmainwindow.h \
|
||||||
vdirectorytree.h \
|
vdirectorytree.h \
|
||||||
@ -142,7 +143,8 @@ HEADERS += vmainwindow.h \
|
|||||||
dialog/vconfirmdeletiondialog.h \
|
dialog/vconfirmdeletiondialog.h \
|
||||||
vnotefile.h \
|
vnotefile.h \
|
||||||
vattachmentlist.h \
|
vattachmentlist.h \
|
||||||
dialog/vsortdialog.h
|
dialog/vsortdialog.h \
|
||||||
|
vfilesessioninfo.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
vnote.qrc \
|
vnote.qrc \
|
||||||
|
@ -959,3 +959,30 @@ void VUtils::addErrMsg(QString *p_msg, const QString &p_str)
|
|||||||
*p_msg = *p_msg + '\n' + p_str;
|
*p_msg = *p_msg + '\n' + p_str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList VUtils::filterFilePathsToOpen(const QStringList &p_files)
|
||||||
|
{
|
||||||
|
QStringList paths;
|
||||||
|
for (int i = 0; i < p_files.size(); ++i) {
|
||||||
|
QString path = validFilePathToOpen(p_files[i]);
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
paths.append(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString VUtils::validFilePathToOpen(const QString &p_file)
|
||||||
|
{
|
||||||
|
if (QFileInfo::exists(p_file)) {
|
||||||
|
QFileInfo fi(p_file);
|
||||||
|
if (fi.isFile()) {
|
||||||
|
// Need to use absolute path here since VNote may be launched
|
||||||
|
// in different working directory.
|
||||||
|
return QDir::cleanPath(fi.absoluteFilePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
@ -232,6 +232,13 @@ public:
|
|||||||
// Assign @p_str to @p_msg if it is not NULL.
|
// Assign @p_str to @p_msg if it is not NULL.
|
||||||
static void addErrMsg(QString *p_msg, const QString &p_str);
|
static void addErrMsg(QString *p_msg, const QString &p_str);
|
||||||
|
|
||||||
|
// Check each file of @p_files and return valid ones for VNote to open.
|
||||||
|
static QStringList filterFilePathsToOpen(const QStringList &p_files);
|
||||||
|
|
||||||
|
// Return the normalized file path of @p_file if it is valid to open.
|
||||||
|
// Return empty if it is not valid.
|
||||||
|
static QString validFilePathToOpen(const QString &p_file);
|
||||||
|
|
||||||
// Regular expression for image link.
|
// Regular expression for image link.
|
||||||
// 
|
// 
|
||||||
// Captured texts (need to be trimmed):
|
// Captured texts (need to be trimmed):
|
||||||
|
@ -275,7 +275,7 @@ bool VCaptain::handleKeyPress(int p_key, Qt::KeyboardModifiers p_modifiers)
|
|||||||
// Remove current window split.
|
// Remove current window split.
|
||||||
m_mainWindow->editArea->removeCurrentWindow();
|
m_mainWindow->editArea->removeCurrentWindow();
|
||||||
|
|
||||||
QWidget *nextFocus = m_mainWindow->editArea->currentEditTab();
|
QWidget *nextFocus = m_mainWindow->editArea->getCurrentTab();
|
||||||
m_widgetBeforeCaptain = nextFocus ? nextFocus : m_mainWindow->getFileList();
|
m_widgetBeforeCaptain = nextFocus ? nextFocus : m_mainWindow->getFileList();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -304,7 +304,7 @@ bool VCaptain::handleKeyPress(int p_key, Qt::KeyboardModifiers p_modifiers)
|
|||||||
m_mainWindow->closeCurrentFile();
|
m_mainWindow->closeCurrentFile();
|
||||||
|
|
||||||
// m_widgetBeforeCaptain may be the closed tab which will cause crash.
|
// m_widgetBeforeCaptain may be the closed tab which will cause crash.
|
||||||
QWidget *nextFocus = m_mainWindow->editArea->currentEditTab();
|
QWidget *nextFocus = m_mainWindow->editArea->getCurrentTab();
|
||||||
m_widgetBeforeCaptain = nextFocus ? nextFocus : m_mainWindow->getFileList();
|
m_widgetBeforeCaptain = nextFocus ? nextFocus : m_mainWindow->getFileList();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -235,6 +235,18 @@ void VConfigManager::initialize()
|
|||||||
m_enableCompactMode = getConfigFromSettings("global",
|
m_enableCompactMode = getConfigFromSettings("global",
|
||||||
"enable_compact_mode").toBool();
|
"enable_compact_mode").toBool();
|
||||||
|
|
||||||
|
int tmpStartupPageMode = getConfigFromSettings("global",
|
||||||
|
"startup_page_type").toInt();
|
||||||
|
if (tmpStartupPageMode < (int)StartupPageType::Invalid
|
||||||
|
&& tmpStartupPageMode >= (int)StartupPageType::None) {
|
||||||
|
m_startupPageType = (StartupPageType)tmpStartupPageMode;
|
||||||
|
} else {
|
||||||
|
m_startupPageType = StartupPageType::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_startupPages = getConfigFromSettings("global",
|
||||||
|
"startup_pages").toStringList();
|
||||||
|
|
||||||
initFromSessionSettings();
|
initFromSessionSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,6 +254,8 @@ void VConfigManager::initSettings()
|
|||||||
{
|
{
|
||||||
Q_ASSERT(!userSettings && !defaultSettings && !m_sessionSettings);
|
Q_ASSERT(!userSettings && !defaultSettings && !m_sessionSettings);
|
||||||
|
|
||||||
|
const char *codecForIni = "UTF-8";
|
||||||
|
|
||||||
// vnote.ini.
|
// vnote.ini.
|
||||||
// First try to read vnote.ini from the directory of the executable.
|
// First try to read vnote.ini from the directory of the executable.
|
||||||
QString userIniPath = QDir(QCoreApplication::applicationDirPath()).filePath(c_defaultConfigFile);
|
QString userIniPath = QDir(QCoreApplication::applicationDirPath()).filePath(c_defaultConfigFile);
|
||||||
@ -257,15 +271,19 @@ void VConfigManager::initSettings()
|
|||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userSettings->setIniCodec(codecForIni);
|
||||||
|
|
||||||
qDebug() << "use user config" << userSettings->fileName();
|
qDebug() << "use user config" << userSettings->fileName();
|
||||||
|
|
||||||
// Default vnote.ini from resource file.
|
// Default vnote.ini from resource file.
|
||||||
defaultSettings = new QSettings(c_defaultConfigFilePath, QSettings::IniFormat, this);
|
defaultSettings = new QSettings(c_defaultConfigFilePath, QSettings::IniFormat, this);
|
||||||
|
defaultSettings->setIniCodec(codecForIni);
|
||||||
|
|
||||||
// session.ini.
|
// session.ini.
|
||||||
m_sessionSettings = new QSettings(QDir(getConfigFolder()).filePath(c_sessionConfigFile),
|
m_sessionSettings = new QSettings(QDir(getConfigFolder()).filePath(c_sessionConfigFile),
|
||||||
QSettings::IniFormat,
|
QSettings::IniFormat,
|
||||||
this);
|
this);
|
||||||
|
m_sessionSettings->setIniCodec(codecForIni);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VConfigManager::initFromSessionSettings()
|
void VConfigManager::initFromSessionSettings()
|
||||||
@ -364,7 +382,7 @@ QVariant VConfigManager::getConfigFromSettings(const QString §ion, const QSt
|
|||||||
// First, look up the user-scoped config file
|
// First, look up the user-scoped config file
|
||||||
QVariant value = getConfigFromSettingsBySectionKey(userSettings, section, key);
|
QVariant value = getConfigFromSettingsBySectionKey(userSettings, section, key);
|
||||||
if (!value.isNull()) {
|
if (!value.isNull()) {
|
||||||
qDebug() << "user config:" << (section + "/" + key) << value.toString();
|
qDebug() << "user config:" << (section + "/" + key) << value;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,13 +394,13 @@ void VConfigManager::setConfigToSettings(const QString §ion, const QString &
|
|||||||
{
|
{
|
||||||
// Set the user-scoped config file
|
// Set the user-scoped config file
|
||||||
setConfigToSettingsBySectionKey(userSettings, section, key, value);
|
setConfigToSettingsBySectionKey(userSettings, section, key, value);
|
||||||
qDebug() << "set user config:" << (section + "/" + key) << value.toString();
|
qDebug() << "set user config:" << (section + "/" + key) << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant VConfigManager::getDefaultConfig(const QString &p_section, const QString &p_key) const
|
QVariant VConfigManager::getDefaultConfig(const QString &p_section, const QString &p_key) const
|
||||||
{
|
{
|
||||||
QVariant value = getConfigFromSettingsBySectionKey(defaultSettings, p_section, p_key);
|
QVariant value = getConfigFromSettingsBySectionKey(defaultSettings, p_section, p_key);
|
||||||
qDebug() << "default config:" << (p_section + "/" + p_key) << value.toString();
|
qDebug() << "default config:" << (p_section + "/" + p_key) << value;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1090,3 +1108,41 @@ void VConfigManager::initDocSuffixes()
|
|||||||
|
|
||||||
qDebug() << "doc suffixes" << m_docSuffixes;
|
qDebug() << "doc suffixes" << m_docSuffixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<VFileSessionInfo> VConfigManager::getLastOpenedFiles()
|
||||||
|
{
|
||||||
|
QVector<VFileSessionInfo> files;
|
||||||
|
int size = m_sessionSettings->beginReadArray("last_opened_files");
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
m_sessionSettings->setArrayIndex(i);
|
||||||
|
files.push_back(VFileSessionInfo::fromSettings(m_sessionSettings));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sessionSettings->endArray();
|
||||||
|
qDebug() << "read" << files.size()
|
||||||
|
<< "items from [last_opened_files] section";
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VConfigManager::setLastOpenedFiles(const QVector<VFileSessionInfo> &p_files)
|
||||||
|
{
|
||||||
|
const QString section("last_opened_files");
|
||||||
|
|
||||||
|
// Clear it first
|
||||||
|
m_sessionSettings->beginGroup(section);
|
||||||
|
m_sessionSettings->remove("");
|
||||||
|
m_sessionSettings->endGroup();
|
||||||
|
|
||||||
|
m_sessionSettings->beginWriteArray(section);
|
||||||
|
for (int i = 0; i < p_files.size(); ++i) {
|
||||||
|
m_sessionSettings->setArrayIndex(i);
|
||||||
|
const VFileSessionInfo &info = p_files[i];
|
||||||
|
info.toSettings(m_sessionSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sessionSettings->endArray();
|
||||||
|
qDebug() << "write" << p_files.size()
|
||||||
|
<< "items in [last_opened_files] section";
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "hgmarkdownhighlighter.h"
|
#include "hgmarkdownhighlighter.h"
|
||||||
#include "vmarkdownconverter.h"
|
#include "vmarkdownconverter.h"
|
||||||
#include "vconstants.h"
|
#include "vconstants.h"
|
||||||
|
#include "vfilesessioninfo.h"
|
||||||
|
|
||||||
|
|
||||||
class QJsonObject;
|
class QJsonObject;
|
||||||
class QString;
|
class QString;
|
||||||
@ -300,6 +302,18 @@ public:
|
|||||||
bool getEnableCompactMode() const;
|
bool getEnableCompactMode() const;
|
||||||
void setEnableCompactMode(bool p_enabled);
|
void setEnableCompactMode(bool p_enabled);
|
||||||
|
|
||||||
|
StartupPageType getStartupPageType() const;
|
||||||
|
void setStartupPageType(StartupPageType p_type);
|
||||||
|
|
||||||
|
const QStringList &getStartupPages() const;
|
||||||
|
void setStartupPages(const QStringList &p_pages);
|
||||||
|
|
||||||
|
// Read last opened files from [last_opened_files] of session.ini.
|
||||||
|
QVector<VFileSessionInfo> getLastOpenedFiles();
|
||||||
|
|
||||||
|
// Write last opened files to [last_opened_files] of session.ini.
|
||||||
|
void setLastOpenedFiles(const QVector<VFileSessionInfo> &p_files);
|
||||||
|
|
||||||
// Return the configured key sequence of @p_operation.
|
// Return the configured key sequence of @p_operation.
|
||||||
// Return empty if there is no corresponding config.
|
// Return empty if there is no corresponding config.
|
||||||
QString getShortcutKeySequence(const QString &p_operation) const;
|
QString getShortcutKeySequence(const QString &p_operation) const;
|
||||||
@ -635,6 +649,12 @@ private:
|
|||||||
// Whether put folder and note panel in one single column.
|
// Whether put folder and note panel in one single column.
|
||||||
bool m_enableCompactMode;
|
bool m_enableCompactMode;
|
||||||
|
|
||||||
|
// Type of the pages to open on startup.
|
||||||
|
StartupPageType m_startupPageType;
|
||||||
|
|
||||||
|
// File paths to open on startup.
|
||||||
|
QStringList m_startupPages;
|
||||||
|
|
||||||
// The name of the config file in each directory, obsolete.
|
// The name of the config file in each directory, obsolete.
|
||||||
// Use c_dirConfigFile instead.
|
// Use c_dirConfigFile instead.
|
||||||
static const QString c_obsoleteDirConfigFile;
|
static const QString c_obsoleteDirConfigFile;
|
||||||
@ -1666,4 +1686,34 @@ inline void VConfigManager::setEnableCompactMode(bool p_enabled)
|
|||||||
setConfigToSettings("global", "enable_compact_mode", m_enableCompactMode);
|
setConfigToSettings("global", "enable_compact_mode", m_enableCompactMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline StartupPageType VConfigManager::getStartupPageType() const
|
||||||
|
{
|
||||||
|
return m_startupPageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VConfigManager::setStartupPageType(StartupPageType p_type)
|
||||||
|
{
|
||||||
|
if (m_startupPageType == p_type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_startupPageType = p_type;
|
||||||
|
setConfigToSettings("global", "startup_page_type", (int)m_startupPageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QStringList &VConfigManager::getStartupPages() const
|
||||||
|
{
|
||||||
|
return m_startupPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VConfigManager::setStartupPages(const QStringList &p_pages)
|
||||||
|
{
|
||||||
|
if (m_startupPages == p_pages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_startupPages = p_pages;
|
||||||
|
setConfigToSettings("global", "startup_pages", m_startupPages);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // VCONFIGMANAGER_H
|
#endif // VCONFIGMANAGER_H
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef VCONSTANTS_H
|
#ifndef VCONSTANTS_H
|
||||||
#define VCONSTANTS_H
|
#define VCONSTANTS_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
// Html: rich text file;
|
// Html: rich text file;
|
||||||
// Markdown: Markdown text file;
|
// Markdown: Markdown text file;
|
||||||
// List: Infinite list file like WorkFlowy;
|
// List: Infinite list file like WorkFlowy;
|
||||||
@ -22,7 +24,7 @@ namespace ClipboardConfig
|
|||||||
static const QString c_dirs = "dirs";
|
static const QString c_dirs = "dirs";
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class OpenFileMode {Read = 0, Edit};
|
enum class OpenFileMode {Read = 0, Edit, Invalid };
|
||||||
|
|
||||||
static const qreal c_webZoomFactorMax = 5;
|
static const qreal c_webZoomFactorMax = 5;
|
||||||
static const qreal c_webZoomFactorMin = 0.25;
|
static const qreal c_webZoomFactorMin = 0.25;
|
||||||
@ -97,4 +99,13 @@ enum class LineNumberType
|
|||||||
CodeBlock
|
CodeBlock
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Pages to open on start up.
|
||||||
|
enum class StartupPageType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
ContinueLeftOff = 1,
|
||||||
|
SpecificPages = 2,
|
||||||
|
Invalid
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -163,6 +163,9 @@ signals:
|
|||||||
// Request the edit tab to close find and replace dialog.
|
// Request the edit tab to close find and replace dialog.
|
||||||
void requestCloseFindReplaceDialog();
|
void requestCloseFindReplaceDialog();
|
||||||
|
|
||||||
|
// Emit when all initialization is ready.
|
||||||
|
void ready();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void highlightCurrentLine();
|
virtual void highlightCurrentLine();
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "vfile.h"
|
#include "vfile.h"
|
||||||
#include "dialog/vfindreplacedialog.h"
|
#include "dialog/vfindreplacedialog.h"
|
||||||
#include "utils/vutils.h"
|
#include "utils/vutils.h"
|
||||||
|
#include "vfilesessioninfo.h"
|
||||||
|
|
||||||
extern VConfigManager *g_config;
|
extern VConfigManager *g_config;
|
||||||
extern VNote *g_vnote;
|
extern VNote *g_vnote;
|
||||||
@ -119,17 +120,17 @@ void VEditArea::removeSplitWindow(VEditWindow *win)
|
|||||||
win->deleteLater();
|
win->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VEditArea::openFile(VFile *p_file, OpenFileMode p_mode, bool p_forceMode)
|
VEditTab *VEditArea::openFile(VFile *p_file, OpenFileMode p_mode, bool p_forceMode)
|
||||||
{
|
{
|
||||||
if (!p_file) {
|
if (!p_file) {
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it is DocType::Unknown, open it using system default method.
|
// If it is DocType::Unknown, open it using system default method.
|
||||||
if (p_file->getDocType() == DocType::Unknown) {
|
if (p_file->getDocType() == DocType::Unknown) {
|
||||||
QUrl url = QUrl::fromLocalFile(p_file->fetchPath());
|
QUrl url = QUrl::fromLocalFile(p_file->fetchPath());
|
||||||
QDesktopServices::openUrl(url);
|
QDesktopServices::openUrl(url);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find if it has been opened already
|
// Find if it has been opened already
|
||||||
@ -165,6 +166,8 @@ void VEditArea::openFile(VFile *p_file, OpenFileMode p_mode, bool p_forceMode)
|
|||||||
tabIdx = openFileInWindow(winIdx, p_file, p_mode);
|
tabIdx = openFileInWindow(winIdx, p_file, p_mode);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
VEditTab *tab = getTab(winIdx, tabIdx);
|
||||||
|
|
||||||
setCurrentTab(winIdx, tabIdx, setFocus);
|
setCurrentTab(winIdx, tabIdx, setFocus);
|
||||||
|
|
||||||
if (existFile && p_forceMode) {
|
if (existFile && p_forceMode) {
|
||||||
@ -174,6 +177,8 @@ out:
|
|||||||
editFile();
|
editFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QPair<int, int> > VEditArea::findTabsByFile(const VFile *p_file)
|
QVector<QPair<int, int> > VEditArea::findTabsByFile(const VFile *p_file)
|
||||||
@ -482,13 +487,35 @@ void VEditArea::handleNotebookUpdated(const VNotebook *p_notebook)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VEditTab *VEditArea::currentEditTab()
|
VEditTab *VEditArea::getCurrentTab() const
|
||||||
{
|
{
|
||||||
if (curWindowIndex == -1) {
|
if (curWindowIndex == -1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VEditWindow *win = getWindow(curWindowIndex);
|
VEditWindow *win = getWindow(curWindowIndex);
|
||||||
return win->currentEditTab();
|
return win->getCurrentTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
VEditTab *VEditArea::getTab(int p_winIdx, int p_tabIdx) const
|
||||||
|
{
|
||||||
|
VEditWindow *win = getWindow(p_winIdx);
|
||||||
|
if (!win) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return win->getTab(p_tabIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<VEditTabInfo> VEditArea::getAllTabsInfo() const
|
||||||
|
{
|
||||||
|
QVector<VEditTabInfo> tabs;
|
||||||
|
int nrWin = splitter->count();
|
||||||
|
for (int i = 0; i < nrWin; ++i) {
|
||||||
|
tabs.append(getWindow(i)->getAllTabsInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VEditArea::windowIndex(const VEditWindow *p_window) const
|
int VEditArea::windowIndex(const VEditWindow *p_window) const
|
||||||
@ -518,7 +545,7 @@ void VEditArea::moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx)
|
|||||||
// Only propogate the search in the IncrementalSearch case.
|
// Only propogate the search in the IncrementalSearch case.
|
||||||
void VEditArea::handleFindTextChanged(const QString &p_text, uint p_options)
|
void VEditArea::handleFindTextChanged(const QString &p_text, uint p_options)
|
||||||
{
|
{
|
||||||
VEditTab *tab = currentEditTab();
|
VEditTab *tab = getCurrentTab();
|
||||||
if (tab) {
|
if (tab) {
|
||||||
if (p_options & FindOption::IncrementalSearch) {
|
if (p_options & FindOption::IncrementalSearch) {
|
||||||
tab->findText(p_text, p_options, true);
|
tab->findText(p_text, p_options, true);
|
||||||
@ -539,7 +566,7 @@ void VEditArea::handleFindNext(const QString &p_text, uint p_options,
|
|||||||
bool p_forward)
|
bool p_forward)
|
||||||
{
|
{
|
||||||
qDebug() << "find next" << p_text << p_options << p_forward;
|
qDebug() << "find next" << p_text << p_options << p_forward;
|
||||||
VEditTab *tab = currentEditTab();
|
VEditTab *tab = getCurrentTab();
|
||||||
if (tab) {
|
if (tab) {
|
||||||
tab->findText(p_text, p_options, false, p_forward);
|
tab->findText(p_text, p_options, false, p_forward);
|
||||||
}
|
}
|
||||||
@ -550,7 +577,7 @@ void VEditArea::handleReplace(const QString &p_text, uint p_options,
|
|||||||
{
|
{
|
||||||
qDebug() << "replace" << p_text << p_options << "with" << p_replaceText
|
qDebug() << "replace" << p_text << p_options << "with" << p_replaceText
|
||||||
<< p_findNext;
|
<< p_findNext;
|
||||||
VEditTab *tab = currentEditTab();
|
VEditTab *tab = getCurrentTab();
|
||||||
if (tab) {
|
if (tab) {
|
||||||
tab->replaceText(p_text, p_options, p_replaceText, p_findNext);
|
tab->replaceText(p_text, p_options, p_replaceText, p_findNext);
|
||||||
}
|
}
|
||||||
@ -560,7 +587,7 @@ void VEditArea::handleReplaceAll(const QString &p_text, uint p_options,
|
|||||||
const QString &p_replaceText)
|
const QString &p_replaceText)
|
||||||
{
|
{
|
||||||
qDebug() << "replace all" << p_text << p_options << "with" << p_replaceText;
|
qDebug() << "replace all" << p_text << p_options << "with" << p_replaceText;
|
||||||
VEditTab *tab = currentEditTab();
|
VEditTab *tab = getCurrentTab();
|
||||||
if (tab) {
|
if (tab) {
|
||||||
tab->replaceTextAll(p_text, p_options, p_replaceText);
|
tab->replaceTextAll(p_text, p_options, p_replaceText);
|
||||||
}
|
}
|
||||||
@ -584,7 +611,7 @@ void VEditArea::handleFindDialogClosed()
|
|||||||
|
|
||||||
QString VEditArea::getSelectedText()
|
QString VEditArea::getSelectedText()
|
||||||
{
|
{
|
||||||
VEditTab *tab = currentEditTab();
|
VEditTab *tab = getCurrentTab();
|
||||||
if (tab) {
|
if (tab) {
|
||||||
return tab->getSelectedText();
|
return tab->getSelectedText();
|
||||||
} else {
|
} else {
|
||||||
@ -694,3 +721,29 @@ bool VEditArea::handleKeyNavigation(int p_key, bool &p_succeed)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VEditArea::openFiles(const QVector<VFileSessionInfo> &p_files)
|
||||||
|
{
|
||||||
|
int nrOpened = 0;
|
||||||
|
for (auto const & info : p_files) {
|
||||||
|
QString filePath = VUtils::validFilePathToOpen(info.m_file);
|
||||||
|
if (filePath.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VFile *file = g_vnote->getFile(filePath);
|
||||||
|
if (!file) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VEditTab *tab = openFile(file, info.m_mode, true);
|
||||||
|
++nrOpened;
|
||||||
|
|
||||||
|
VEditTabInfo tabInfo;
|
||||||
|
tabInfo.m_editTab = tab;
|
||||||
|
info.toEditTabInfo(&tabInfo);
|
||||||
|
|
||||||
|
tab->tryRestoreFromTabInfo(tabInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nrOpened;
|
||||||
|
}
|
||||||
|
@ -35,17 +35,31 @@ public:
|
|||||||
bool closeFile(const VFile *p_file, bool p_forced);
|
bool closeFile(const VFile *p_file, bool p_forced);
|
||||||
bool closeFile(const VDirectory *p_dir, bool p_forced);
|
bool closeFile(const VDirectory *p_dir, bool p_forced);
|
||||||
bool closeFile(const VNotebook *p_notebook, bool p_forced);
|
bool closeFile(const VNotebook *p_notebook, bool p_forced);
|
||||||
// Returns current edit tab.
|
|
||||||
VEditTab *currentEditTab();
|
// Return current edit window.
|
||||||
// Returns the count of VEditWindow.
|
VEditWindow *getCurrentWindow() const;
|
||||||
inline int windowCount() const;
|
|
||||||
|
// Return current edit tab.
|
||||||
|
VEditTab *getCurrentTab() const;
|
||||||
|
|
||||||
|
// Return the @p_tabIdx tab in the @p_winIdx window.
|
||||||
|
VEditTab *getTab(int p_winIdx, int p_tabIdx) const;
|
||||||
|
|
||||||
|
// Return VEditTabInfo of all edit tabs.
|
||||||
|
QVector<VEditTabInfo> getAllTabsInfo() const;
|
||||||
|
|
||||||
|
// Return the count of VEditWindow.
|
||||||
|
int windowCount() const;
|
||||||
|
|
||||||
// Returns the index of @p_window.
|
// Returns the index of @p_window.
|
||||||
int windowIndex(const VEditWindow *p_window) const;
|
int windowIndex(const VEditWindow *p_window) const;
|
||||||
// Move tab widget @p_widget from window @p_fromIdx to @p_toIdx.
|
// Move tab widget @p_widget from window @p_fromIdx to @p_toIdx.
|
||||||
// @p_widget has been removed from the original window.
|
// @p_widget has been removed from the original window.
|
||||||
// If fail, just delete the p_widget.
|
// If fail, just delete the p_widget.
|
||||||
void moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx);
|
void moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx);
|
||||||
inline VFindReplaceDialog *getFindReplaceDialog() const;
|
|
||||||
|
VFindReplaceDialog *getFindReplaceDialog() const;
|
||||||
|
|
||||||
// Return selected text of current edit tab.
|
// Return selected text of current edit tab.
|
||||||
QString getSelectedText();
|
QString getSelectedText();
|
||||||
void splitCurrentWindow();
|
void splitCurrentWindow();
|
||||||
@ -54,7 +68,6 @@ public:
|
|||||||
// Return the new current window index, otherwise, return -1.
|
// Return the new current window index, otherwise, return -1.
|
||||||
int focusNextWindow(int p_biaIdx);
|
int focusNextWindow(int p_biaIdx);
|
||||||
void moveCurrentTabOneSplit(bool p_right);
|
void moveCurrentTabOneSplit(bool p_right);
|
||||||
VEditWindow *getCurrentWindow() const;
|
|
||||||
|
|
||||||
// Implementations for VNavigationMode.
|
// Implementations for VNavigationMode.
|
||||||
void registerNavigation(QChar p_majorKey) Q_DECL_OVERRIDE;
|
void registerNavigation(QChar p_majorKey) Q_DECL_OVERRIDE;
|
||||||
@ -62,6 +75,9 @@ public:
|
|||||||
void hideNavigation() Q_DECL_OVERRIDE;
|
void hideNavigation() Q_DECL_OVERRIDE;
|
||||||
bool handleKeyNavigation(int p_key, bool &p_succeed) Q_DECL_OVERRIDE;
|
bool handleKeyNavigation(int p_key, bool &p_succeed) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
// Open files @p_files.
|
||||||
|
int openFiles(const QVector<VFileSessionInfo> &p_files);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// Emit when current window's tab status updated.
|
// Emit when current window's tab status updated.
|
||||||
void tabStatusUpdated(const VEditTabInfo &p_info);
|
void tabStatusUpdated(const VEditTabInfo &p_info);
|
||||||
@ -84,7 +100,7 @@ public slots:
|
|||||||
// @p_forceMode is true.
|
// @p_forceMode is true.
|
||||||
// A given file can be opened in multiple split windows. A given file could be
|
// A given file can be opened in multiple split windows. A given file could be
|
||||||
// opened at most in one tab inside a window.
|
// opened at most in one tab inside a window.
|
||||||
void openFile(VFile *p_file, OpenFileMode p_mode, bool p_forceMode = false);
|
VEditTab *openFile(VFile *p_file, OpenFileMode p_mode, bool p_forceMode = false);
|
||||||
|
|
||||||
void editFile();
|
void editFile();
|
||||||
void saveFile();
|
void saveFile();
|
||||||
@ -128,7 +144,9 @@ private:
|
|||||||
int openFileInWindow(int windowIndex, VFile *p_file, OpenFileMode p_mode);
|
int openFileInWindow(int windowIndex, VFile *p_file, OpenFileMode p_mode);
|
||||||
void setCurrentTab(int windowIndex, int tabIndex, bool setFocus);
|
void setCurrentTab(int windowIndex, int tabIndex, bool setFocus);
|
||||||
void setCurrentWindow(int windowIndex, bool setFocus);
|
void setCurrentWindow(int windowIndex, bool setFocus);
|
||||||
inline VEditWindow *getWindow(int windowIndex) const;
|
|
||||||
|
VEditWindow *getWindow(int windowIndex) const;
|
||||||
|
|
||||||
void insertSplitWindow(int idx);
|
void insertSplitWindow(int idx);
|
||||||
void removeSplitWindow(VEditWindow *win);
|
void removeSplitWindow(VEditWindow *win);
|
||||||
|
|
||||||
|
@ -82,13 +82,37 @@ void VEditTab::updateStatus()
|
|||||||
{
|
{
|
||||||
m_modified = m_file->isModified();
|
m_modified = m_file->isModified();
|
||||||
|
|
||||||
emit statusUpdated(createEditTabInfo());
|
emit statusUpdated(fetchTabInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
VEditTabInfo VEditTab::createEditTabInfo()
|
VEditTabInfo VEditTab::fetchTabInfo()
|
||||||
{
|
{
|
||||||
VEditTabInfo info;
|
VEditTabInfo info;
|
||||||
info.m_editTab = this;
|
info.m_editTab = this;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VAnchor VEditTab::getCurrentHeader() const
|
||||||
|
{
|
||||||
|
return m_curHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VEditTab::tryRestoreFromTabInfo(const VEditTabInfo &p_info)
|
||||||
|
{
|
||||||
|
if (p_info.m_editTab != this) {
|
||||||
|
// Clear and return.
|
||||||
|
m_infoToRestore.m_editTab = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restoreFromTabInfo(p_info)) {
|
||||||
|
// Clear and return.
|
||||||
|
m_infoToRestore.m_editTab = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save it and restore later.
|
||||||
|
m_infoToRestore = p_info;
|
||||||
|
qDebug() << "save info for restore later" << p_info.m_anchorIndex;
|
||||||
|
}
|
||||||
|
@ -69,7 +69,16 @@ public:
|
|||||||
virtual void requestUpdateVimStatus() = 0;
|
virtual void requestUpdateVimStatus() = 0;
|
||||||
|
|
||||||
// Insert decoration markers or decorate selected text.
|
// Insert decoration markers or decorate selected text.
|
||||||
virtual void decorateText(TextDecoration p_decoration) {Q_UNUSED(p_decoration);};
|
virtual void decorateText(TextDecoration p_decoration) {Q_UNUSED(p_decoration);}
|
||||||
|
|
||||||
|
// Create a filled VEditTabInfo.
|
||||||
|
virtual VEditTabInfo fetchTabInfo();
|
||||||
|
|
||||||
|
VAnchor getCurrentHeader() const;
|
||||||
|
|
||||||
|
// Restore status from @p_info.
|
||||||
|
// If this tab is not ready yet, it will restore once it is ready.
|
||||||
|
void tryRestoreFromTabInfo(const VEditTabInfo &p_info);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
// Enter edit mode
|
// Enter edit mode
|
||||||
@ -87,8 +96,9 @@ protected:
|
|||||||
// Called to zoom in/out content.
|
// Called to zoom in/out content.
|
||||||
virtual void zoom(bool p_zoomIn, qreal p_step = 0.25) = 0;
|
virtual void zoom(bool p_zoomIn, qreal p_step = 0.25) = 0;
|
||||||
|
|
||||||
// Create a filled VEditTabInfo.
|
// Restore from @p_fino.
|
||||||
virtual VEditTabInfo createEditTabInfo();
|
// Return true if succeed.
|
||||||
|
virtual bool restoreFromTabInfo(const VEditTabInfo &p_info) = 0;
|
||||||
|
|
||||||
// File related to this tab.
|
// File related to this tab.
|
||||||
QPointer<VFile> m_file;
|
QPointer<VFile> m_file;
|
||||||
@ -98,6 +108,9 @@ protected:
|
|||||||
VAnchor m_curHeader;
|
VAnchor m_curHeader;
|
||||||
VEditArea *m_editArea;
|
VEditArea *m_editArea;
|
||||||
|
|
||||||
|
// Tab info to restore from once ready.
|
||||||
|
VEditTabInfo m_infoToRestore;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void getFocused();
|
void getFocused();
|
||||||
|
|
||||||
|
@ -6,8 +6,13 @@ class VEditTab;
|
|||||||
struct VEditTabInfo
|
struct VEditTabInfo
|
||||||
{
|
{
|
||||||
VEditTabInfo()
|
VEditTabInfo()
|
||||||
: m_editTab(NULL), m_cursorBlockNumber(-1), m_cursorPositionInBlock(-1),
|
: m_editTab(NULL),
|
||||||
m_blockCount(-1) {}
|
m_cursorBlockNumber(-1),
|
||||||
|
m_cursorPositionInBlock(-1),
|
||||||
|
m_blockCount(-1),
|
||||||
|
m_anchorIndex(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
VEditTab *m_editTab;
|
VEditTab *m_editTab;
|
||||||
|
|
||||||
@ -15,6 +20,9 @@ struct VEditTabInfo
|
|||||||
int m_cursorBlockNumber;
|
int m_cursorBlockNumber;
|
||||||
int m_cursorPositionInBlock;
|
int m_cursorPositionInBlock;
|
||||||
int m_blockCount;
|
int m_blockCount;
|
||||||
|
|
||||||
|
// Anchor index in outline.
|
||||||
|
int m_anchorIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VEDITTABINFO_H
|
#endif // VEDITTABINFO_H
|
||||||
|
@ -794,15 +794,30 @@ void VEditWindow::updateNotebookInfo(const VNotebook *p_notebook)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VEditTab *VEditWindow::currentEditTab()
|
VEditTab *VEditWindow::getCurrentTab() const
|
||||||
{
|
{
|
||||||
int idx = currentIndex();
|
int idx = currentIndex();
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getTab(idx);
|
return getTab(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<VEditTabInfo> VEditWindow::getAllTabsInfo() const
|
||||||
|
{
|
||||||
|
int nrTab = count();
|
||||||
|
|
||||||
|
QVector<VEditTabInfo> tabs;
|
||||||
|
tabs.reserve(nrTab);
|
||||||
|
for (int i = 0; i < nrTab; ++i) {
|
||||||
|
VEditTab *editTab = getTab(i);
|
||||||
|
tabs.push_back(editTab->fetchTabInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabs;
|
||||||
|
}
|
||||||
|
|
||||||
void VEditWindow::handleLocateAct()
|
void VEditWindow::handleLocateAct()
|
||||||
{
|
{
|
||||||
int tab = m_locateAct->data().toInt();
|
int tab = m_locateAct->data().toInt();
|
||||||
@ -1014,7 +1029,7 @@ void VEditWindow::dropEvent(QDropEvent *p_event)
|
|||||||
|
|
||||||
if (!files.isEmpty()) {
|
if (!files.isEmpty()) {
|
||||||
focusWindow();
|
focusWindow();
|
||||||
g_vnote->getMainWindow()->openExternalFiles(files);
|
g_vnote->getMainWindow()->openFiles(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_event->acceptProposedAction();
|
p_event->acceptProposedAction();
|
||||||
|
@ -40,7 +40,13 @@ public:
|
|||||||
void updateFileInfo(const VFile *p_file);
|
void updateFileInfo(const VFile *p_file);
|
||||||
void updateDirectoryInfo(const VDirectory *p_dir);
|
void updateDirectoryInfo(const VDirectory *p_dir);
|
||||||
void updateNotebookInfo(const VNotebook *p_notebook);
|
void updateNotebookInfo(const VNotebook *p_notebook);
|
||||||
VEditTab *currentEditTab();
|
|
||||||
|
VEditTab *getCurrentTab() const;
|
||||||
|
|
||||||
|
VEditTab *getTab(int tabIndex) const;
|
||||||
|
|
||||||
|
QVector<VEditTabInfo> getAllTabsInfo() const;
|
||||||
|
|
||||||
// Insert a tab with @p_widget. @p_widget is a fully initialized VEditTab.
|
// Insert a tab with @p_widget. @p_widget is a fully initialized VEditTab.
|
||||||
bool addEditTab(QWidget *p_widget);
|
bool addEditTab(QWidget *p_widget);
|
||||||
// Set whether it is the current window.
|
// Set whether it is the current window.
|
||||||
@ -53,7 +59,6 @@ public:
|
|||||||
bool activateTab(int p_sequence);
|
bool activateTab(int p_sequence);
|
||||||
// Switch to previous activated tab.
|
// Switch to previous activated tab.
|
||||||
bool alternateTab();
|
bool alternateTab();
|
||||||
VEditTab *getTab(int tabIndex) const;
|
|
||||||
|
|
||||||
// Ask tab @p_index to update its status and propogate.
|
// Ask tab @p_index to update its status and propogate.
|
||||||
// The status here means tab status, outline, current header.
|
// The status here means tab status, outline, current header.
|
||||||
@ -124,9 +129,9 @@ private:
|
|||||||
int insertEditTab(int p_index, VFile *p_file, QWidget *p_page);
|
int insertEditTab(int p_index, VFile *p_file, QWidget *p_page);
|
||||||
int appendEditTab(VFile *p_file, QWidget *p_page);
|
int appendEditTab(VFile *p_file, QWidget *p_page);
|
||||||
int openFileInTab(VFile *p_file, OpenFileMode p_mode);
|
int openFileInTab(VFile *p_file, OpenFileMode p_mode);
|
||||||
inline QString generateTooltip(const VFile *p_file) const;
|
QString generateTooltip(const VFile *p_file) const;
|
||||||
inline QString generateTabText(int p_index, const QString &p_name,
|
QString generateTabText(int p_index, const QString &p_name,
|
||||||
bool p_modified, bool p_modifiable) const;
|
bool p_modified, bool p_modifiable) const;
|
||||||
bool canRemoveSplit();
|
bool canRemoveSplit();
|
||||||
|
|
||||||
// Move tab at @p_tabIdx one split window.
|
// Move tab at @p_tabIdx one split window.
|
||||||
|
@ -374,7 +374,7 @@ void VFileList::newFile()
|
|||||||
|
|
||||||
// Move cursor down if content has been inserted.
|
// Move cursor down if content has been inserted.
|
||||||
if (contentInserted) {
|
if (contentInserted) {
|
||||||
const VMdTab *tab = dynamic_cast<VMdTab *>(editArea->currentEditTab());
|
const VMdTab *tab = dynamic_cast<VMdTab *>(editArea->getCurrentTab());
|
||||||
if (tab) {
|
if (tab) {
|
||||||
VMdEdit *edit = dynamic_cast<VMdEdit *>(tab->getEditor());
|
VMdEdit *edit = dynamic_cast<VMdEdit *>(tab->getEditor());
|
||||||
if (edit && edit->getFile() == file) {
|
if (edit && edit->getFile() == file) {
|
||||||
|
74
src/vfilesessioninfo.cpp
Normal file
74
src/vfilesessioninfo.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include "vfilesessioninfo.h"
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
#include "vedittabinfo.h"
|
||||||
|
#include "vtoc.h"
|
||||||
|
#include "vedittab.h"
|
||||||
|
|
||||||
|
|
||||||
|
VFileSessionInfo::VFileSessionInfo()
|
||||||
|
: m_mode(OpenFileMode::Read),
|
||||||
|
m_anchorIndex(-1),
|
||||||
|
m_cursorBlockNumber(-1),
|
||||||
|
m_cursorPositionInBlock(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VFileSessionInfo::VFileSessionInfo(const QString &p_file,
|
||||||
|
OpenFileMode p_mode)
|
||||||
|
: m_file(p_file),
|
||||||
|
m_mode(p_mode),
|
||||||
|
m_anchorIndex(-1),
|
||||||
|
m_cursorBlockNumber(-1),
|
||||||
|
m_cursorPositionInBlock(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch VFileSessionInfo from @p_tabInfo.
|
||||||
|
VFileSessionInfo VFileSessionInfo::fromEditTabInfo(const VEditTabInfo *p_tabInfo)
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_tabInfo);
|
||||||
|
VEditTab *tab = p_tabInfo->m_editTab;
|
||||||
|
VFileSessionInfo info(tab->getFile()->fetchPath(),
|
||||||
|
tab->isEditMode() ? OpenFileMode::Edit : OpenFileMode::Read);
|
||||||
|
info.m_anchorIndex = p_tabInfo->m_anchorIndex;
|
||||||
|
info.m_cursorBlockNumber = p_tabInfo->m_cursorBlockNumber;
|
||||||
|
info.m_cursorPositionInBlock = p_tabInfo->m_cursorPositionInBlock;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFileSessionInfo::toEditTabInfo(VEditTabInfo *p_tabInfo) const
|
||||||
|
{
|
||||||
|
p_tabInfo->m_anchorIndex = m_anchorIndex;
|
||||||
|
p_tabInfo->m_cursorBlockNumber = m_cursorBlockNumber;
|
||||||
|
p_tabInfo->m_cursorPositionInBlock = m_cursorPositionInBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
VFileSessionInfo VFileSessionInfo::fromSettings(const QSettings *p_settings)
|
||||||
|
{
|
||||||
|
VFileSessionInfo info;
|
||||||
|
info.m_file = p_settings->value(FileSessionConfig::c_file).toString();
|
||||||
|
int tmpMode = p_settings->value(FileSessionConfig::c_mode).toInt();
|
||||||
|
if (tmpMode >= (int)OpenFileMode::Read && tmpMode < (int)OpenFileMode::Invalid) {
|
||||||
|
info.m_mode = (OpenFileMode)tmpMode;
|
||||||
|
} else {
|
||||||
|
info.m_mode = OpenFileMode::Read;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.m_anchorIndex = p_settings->value(FileSessionConfig::c_anchorIndex).toInt();
|
||||||
|
info.m_cursorBlockNumber = p_settings->value(FileSessionConfig::c_cursorBlockNumber).toInt();
|
||||||
|
info.m_cursorPositionInBlock = p_settings->value(FileSessionConfig::c_cursorPositionInBlock).toInt();
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFileSessionInfo::toSettings(QSettings *p_settings) const
|
||||||
|
{
|
||||||
|
p_settings->setValue(FileSessionConfig::c_file, m_file);
|
||||||
|
p_settings->setValue(FileSessionConfig::c_mode, (int)m_mode);
|
||||||
|
p_settings->setValue(FileSessionConfig::c_anchorIndex, m_anchorIndex);
|
||||||
|
p_settings->setValue(FileSessionConfig::c_cursorBlockNumber, m_cursorBlockNumber);
|
||||||
|
p_settings->setValue(FileSessionConfig::c_cursorPositionInBlock, m_cursorPositionInBlock);
|
||||||
|
}
|
57
src/vfilesessioninfo.h
Normal file
57
src/vfilesessioninfo.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef VFILESESSIONINFO_H
|
||||||
|
#define VFILESESSIONINFO_H
|
||||||
|
|
||||||
|
#include "vconstants.h"
|
||||||
|
|
||||||
|
struct VEditTabInfo;
|
||||||
|
class QSettings;
|
||||||
|
|
||||||
|
namespace FileSessionConfig
|
||||||
|
{
|
||||||
|
static const QString c_file = "file";
|
||||||
|
static const QString c_mode = "mode";
|
||||||
|
|
||||||
|
// Index in outline of the anchor.
|
||||||
|
static const QString c_anchorIndex = "anchor_index";
|
||||||
|
|
||||||
|
static const QString c_cursorBlockNumber = "cursor_block_number";
|
||||||
|
static const QString c_cursorPositionInBlock = "cursor_position_in_block";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Information about an opened file (session).
|
||||||
|
class VFileSessionInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VFileSessionInfo();
|
||||||
|
|
||||||
|
VFileSessionInfo(const QString &p_file,
|
||||||
|
OpenFileMode p_mode);
|
||||||
|
|
||||||
|
// Fetch VFileSessionInfo from @p_tabInfo.
|
||||||
|
static VFileSessionInfo fromEditTabInfo(const VEditTabInfo *p_tabInfo);
|
||||||
|
|
||||||
|
// Fill corresponding fields of @p_tabInfo.
|
||||||
|
void toEditTabInfo(VEditTabInfo *p_tabInfo) const;
|
||||||
|
|
||||||
|
// Fetch VFileSessionInfo from @p_settings.
|
||||||
|
static VFileSessionInfo fromSettings(const QSettings *p_settings);
|
||||||
|
|
||||||
|
void toSettings(QSettings *p_settings) const;
|
||||||
|
|
||||||
|
// Absolute path of the file.
|
||||||
|
QString m_file;
|
||||||
|
|
||||||
|
// Mode of this file in this session.
|
||||||
|
OpenFileMode m_mode;
|
||||||
|
|
||||||
|
// Index in outline of the anchor.
|
||||||
|
int m_anchorIndex;
|
||||||
|
|
||||||
|
// Block number of cursor block.
|
||||||
|
int m_cursorBlockNumber;
|
||||||
|
|
||||||
|
// Position in block of cursor.
|
||||||
|
int m_cursorPositionInBlock;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VFILESESSIONINFO_H
|
@ -252,3 +252,12 @@ void VHtmlTab::requestUpdateVimStatus()
|
|||||||
{
|
{
|
||||||
m_editor->requestUpdateVimStatus();
|
m_editor->requestUpdateVimStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VHtmlTab::restoreFromTabInfo(const VEditTabInfo &p_info)
|
||||||
|
{
|
||||||
|
if (p_info.m_editTab != this) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -78,6 +78,10 @@ private:
|
|||||||
// Focus the proper child widget.
|
// Focus the proper child widget.
|
||||||
void focusChild() Q_DECL_OVERRIDE;
|
void focusChild() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
// Restore from @p_fino.
|
||||||
|
// Return true if succeed.
|
||||||
|
bool restoreFromTabInfo(const VEditTabInfo &p_info) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
VEdit *m_editor;
|
VEdit *m_editor;
|
||||||
};
|
};
|
||||||
#endif // VHTMLTAB_H
|
#endif // VHTMLTAB_H
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "vnotefile.h"
|
#include "vnotefile.h"
|
||||||
#include "vbuttonwithwidget.h"
|
#include "vbuttonwithwidget.h"
|
||||||
#include "vattachmentlist.h"
|
#include "vattachmentlist.h"
|
||||||
|
#include "vfilesessioninfo.h"
|
||||||
|
|
||||||
extern VConfigManager *g_config;
|
extern VConfigManager *g_config;
|
||||||
|
|
||||||
@ -766,7 +767,7 @@ void VMainWindow::initFileMenu()
|
|||||||
// Update lastPath
|
// Update lastPath
|
||||||
lastPath = QFileInfo(files[0]).path();
|
lastPath = QFileInfo(files[0]).path();
|
||||||
|
|
||||||
openExternalFiles(files);
|
openFiles(VUtils::filterFilePathsToOpen(files));
|
||||||
});
|
});
|
||||||
|
|
||||||
fileMenu->addAction(openAct);
|
fileMenu->addAction(openAct);
|
||||||
@ -1956,12 +1957,33 @@ void VMainWindow::closeEvent(QCloseEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isExit || !m_trayIcon->isVisible()) {
|
if (isExit || !m_trayIcon->isVisible()) {
|
||||||
|
// Get all the opened tabs.
|
||||||
|
bool saveOpenedNotes = g_config->getStartupPageType() == StartupPageType::ContinueLeftOff;
|
||||||
|
QVector<VFileSessionInfo> fileInfos;
|
||||||
|
QVector<VEditTabInfo> tabs;
|
||||||
|
if (saveOpenedNotes) {
|
||||||
|
tabs = editArea->getAllTabsInfo();
|
||||||
|
|
||||||
|
fileInfos.reserve(tabs.size());
|
||||||
|
|
||||||
|
for (auto const & tab : tabs) {
|
||||||
|
VFileSessionInfo info = VFileSessionInfo::fromEditTabInfo(&tab);
|
||||||
|
fileInfos.push_back(info);
|
||||||
|
|
||||||
|
qDebug() << "file session:" << info.m_file << (info.m_mode == OpenFileMode::Edit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!editArea->closeAllFiles(false)) {
|
if (!editArea->closeAllFiles(false)) {
|
||||||
// Fail to close all the opened files, cancel closing app.
|
// Fail to close all the opened files, cancel closing app.
|
||||||
event->ignore();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (saveOpenedNotes) {
|
||||||
|
g_config->setLastOpenedFiles(fileInfos);
|
||||||
|
}
|
||||||
|
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
} else {
|
} else {
|
||||||
hide();
|
hide();
|
||||||
@ -2059,7 +2081,7 @@ void VMainWindow::insertImage()
|
|||||||
if (!m_curTab) {
|
if (!m_curTab) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Q_ASSERT(m_curTab == editArea->currentEditTab());
|
Q_ASSERT(m_curTab == editArea->getCurrentTab());
|
||||||
m_curTab->insertImage();
|
m_curTab->insertImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2310,9 +2332,8 @@ bool VMainWindow::tryOpenInternalFile(const QString &p_filePath)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMainWindow::openExternalFiles(const QStringList &p_files, bool p_forceOrphan)
|
void VMainWindow::openFiles(const QStringList &p_files, bool p_forceOrphan)
|
||||||
{
|
{
|
||||||
qDebug() << "open external files" << p_files;
|
|
||||||
for (int i = 0; i < p_files.size(); ++i) {
|
for (int i = 0; i < p_files.size(); ++i) {
|
||||||
VFile *file = NULL;
|
VFile *file = NULL;
|
||||||
if (!p_forceOrphan) {
|
if (!p_forceOrphan) {
|
||||||
@ -2344,7 +2365,7 @@ void VMainWindow::checkSharedMemory()
|
|||||||
QStringList files = m_guard->fetchFilesToOpen();
|
QStringList files = m_guard->fetchFilesToOpen();
|
||||||
if (!files.isEmpty()) {
|
if (!files.isEmpty()) {
|
||||||
qDebug() << "shared memory fetch files" << files;
|
qDebug() << "shared memory fetch files" << files;
|
||||||
openExternalFiles(files);
|
openFiles(files);
|
||||||
|
|
||||||
// Eliminate the signal.
|
// Eliminate the signal.
|
||||||
m_guard->fetchAskedToShow();
|
m_guard->fetchAskedToShow();
|
||||||
@ -2416,3 +2437,28 @@ void VMainWindow::showAttachmentList()
|
|||||||
m_attachmentBtn->showPopupWidget();
|
m_attachmentBtn->showPopupWidget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VMainWindow::openStartupPages()
|
||||||
|
{
|
||||||
|
StartupPageType type = g_config->getStartupPageType();
|
||||||
|
switch (type) {
|
||||||
|
case StartupPageType::ContinueLeftOff:
|
||||||
|
{
|
||||||
|
QVector<VFileSessionInfo> files = g_config->getLastOpenedFiles();
|
||||||
|
qDebug() << "open" << files.size() << "last opened files";
|
||||||
|
editArea->openFiles(files);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case StartupPageType::SpecificPages:
|
||||||
|
{
|
||||||
|
QStringList pagesToOpen = VUtils::filterFilePathsToOpen(g_config->getStartupPages());
|
||||||
|
qDebug() << "open startup pages" << pagesToOpen;
|
||||||
|
openFiles(pagesToOpen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -68,10 +68,10 @@ public:
|
|||||||
// View and edit the information of @p_file, which is an orphan file.
|
// View and edit the information of @p_file, which is an orphan file.
|
||||||
void editOrphanFileInfo(VFile *p_file);
|
void editOrphanFileInfo(VFile *p_file);
|
||||||
|
|
||||||
// Open external files @p_files as orphan files.
|
// Open files @p_files as orphan files or internal note files.
|
||||||
// If @p_forceOrphan is false, for each file, VNote will try to find out if
|
// If @p_forceOrphan is false, for each file, VNote will try to find out if
|
||||||
// it is a note inside VNote. If yes, VNote will open it as internal file.
|
// it is a note inside VNote. If yes, VNote will open it as internal file.
|
||||||
void openExternalFiles(const QStringList &p_files, bool p_forceOrphan = false);
|
void openFiles(const QStringList &p_files, bool p_forceOrphan = false);
|
||||||
|
|
||||||
// Try to open @p_filePath as internal note.
|
// Try to open @p_filePath as internal note.
|
||||||
bool tryOpenInternalFile(const QString &p_filePath);
|
bool tryOpenInternalFile(const QString &p_filePath);
|
||||||
@ -82,6 +82,9 @@ public:
|
|||||||
// Popup the attachment list if it is enabled.
|
// Popup the attachment list if it is enabled.
|
||||||
void showAttachmentList();
|
void showAttachmentList();
|
||||||
|
|
||||||
|
// Open startup pages according to configuration.
|
||||||
|
void openStartupPages();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void importNoteFromFile();
|
void importNoteFromFile();
|
||||||
void viewSettings();
|
void viewSettings();
|
||||||
|
@ -539,7 +539,7 @@ void VMdEdit::updateOutline(const QVector<VElementRegion> &p_headerRegions)
|
|||||||
updateCurHeader();
|
updateCurHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMdEdit::scrollToHeader(const VAnchor &p_anchor)
|
void VMdEdit::scrollToAnchor(const VAnchor &p_anchor)
|
||||||
{
|
{
|
||||||
if (p_anchor.lineNumber == -1
|
if (p_anchor.lineNumber == -1
|
||||||
|| p_anchor.m_outlineIndex < 0) {
|
|| p_anchor.m_outlineIndex < 0) {
|
||||||
@ -557,6 +557,20 @@ void VMdEdit::scrollToHeader(const VAnchor &p_anchor)
|
|||||||
scrollToLine(p_anchor.lineNumber);
|
scrollToLine(p_anchor.lineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VMdEdit::scrollToAnchor(int p_anchorIndex)
|
||||||
|
{
|
||||||
|
if (p_anchorIndex >= 0 && p_anchorIndex < m_headers.size()) {
|
||||||
|
int lineNumber = m_headers[p_anchorIndex].lineNumber;
|
||||||
|
if (lineNumber >= 0) {
|
||||||
|
scrollToLine(lineNumber);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QString VMdEdit::toPlainTextWithoutImg()
|
QString VMdEdit::toPlainTextWithoutImg()
|
||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
@ -838,5 +852,7 @@ void VMdEdit::finishOneAsyncJob(int p_idx)
|
|||||||
emit statusChanged();
|
emit statusChanged();
|
||||||
|
|
||||||
updateOutline(m_mdHighlighter->getHeaderRegions());
|
updateOutline(m_mdHighlighter->getHeaderRegions());
|
||||||
|
|
||||||
|
emit ready();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,11 @@ public:
|
|||||||
// @p_path is the absolute path of the inserted image.
|
// @p_path is the absolute path of the inserted image.
|
||||||
void imageInserted(const QString &p_path);
|
void imageInserted(const QString &p_path);
|
||||||
|
|
||||||
void scrollToHeader(const VAnchor &p_anchor);
|
void scrollToAnchor(const VAnchor &p_anchor);
|
||||||
|
|
||||||
|
// Scroll to anchor given the the index in outline.
|
||||||
|
// Return true if @p_anchorIndex is valid.
|
||||||
|
bool scrollToAnchor(int p_anchorIndex);
|
||||||
|
|
||||||
// Like toPlainText(), but remove image preview characters.
|
// Like toPlainText(), but remove image preview characters.
|
||||||
QString toPlainTextWithoutImg();
|
QString toPlainTextWithoutImg();
|
||||||
|
@ -77,27 +77,46 @@ void VMdTab::showFileReadMode()
|
|||||||
m_stacks->setCurrentWidget(m_webViewer);
|
m_stacks->setCurrentWidget(m_webViewer);
|
||||||
clearSearchedWordHighlight();
|
clearSearchedWordHighlight();
|
||||||
|
|
||||||
scrollWebViewToHeader(outlineIndex);
|
scrollWebViewToAnchor(outlineIndex);
|
||||||
|
|
||||||
updateStatus();
|
updateStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMdTab::scrollWebViewToHeader(int p_outlineIndex)
|
bool VMdTab::scrollWebViewToAnchor(int p_anchorIndex, bool p_strict)
|
||||||
{
|
{
|
||||||
QString anchor;
|
QString anchor;
|
||||||
|
|
||||||
m_curHeader = VAnchor(m_file, anchor, -1, p_outlineIndex);
|
VAnchor anch(m_file, anchor, -1, p_anchorIndex);
|
||||||
|
|
||||||
if (p_outlineIndex < m_toc.headers.size() && p_outlineIndex >= 0) {
|
bool validIndex = false;
|
||||||
QString tmp = m_toc.headers[p_outlineIndex].anchor;
|
if (p_anchorIndex < m_toc.headers.size() && p_anchorIndex >= 0) {
|
||||||
V_ASSERT(!tmp.isEmpty());
|
QString tmp = m_toc.headers[p_anchorIndex].anchor;
|
||||||
m_curHeader.anchor = tmp;
|
Q_ASSERT(!tmp.isEmpty());
|
||||||
|
anch.anchor = tmp;
|
||||||
anchor = tmp.mid(1);
|
anchor = tmp.mid(1);
|
||||||
|
validIndex = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_document->scrollToAnchor(anchor);
|
if (validIndex || !p_strict) {
|
||||||
|
m_curHeader = anch;
|
||||||
|
|
||||||
emit curHeaderChanged(m_curHeader);
|
m_document->scrollToAnchor(anchor);
|
||||||
|
|
||||||
|
emit curHeaderChanged(m_curHeader);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VMdTab::scrollToAnchor(int p_anchorIndex, bool p_strict)
|
||||||
|
{
|
||||||
|
if (m_isEditMode) {
|
||||||
|
return dynamic_cast<VMdEdit *>(getEditor())->scrollToAnchor(p_anchorIndex);
|
||||||
|
} else {
|
||||||
|
return scrollWebViewToAnchor(p_anchorIndex, p_strict);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMdTab::viewWebByConverter()
|
void VMdTab::viewWebByConverter()
|
||||||
@ -148,7 +167,7 @@ void VMdTab::showFileEditMode()
|
|||||||
|
|
||||||
VAnchor anchor(m_file, "", lineNumber, outlineIndex);
|
VAnchor anchor(m_file, "", lineNumber, outlineIndex);
|
||||||
|
|
||||||
mdEdit->scrollToHeader(anchor);
|
mdEdit->scrollToAnchor(anchor);
|
||||||
|
|
||||||
mdEdit->setFocus();
|
mdEdit->setFocus();
|
||||||
|
|
||||||
@ -290,6 +309,8 @@ void VMdTab::setupMarkdownViewer()
|
|||||||
this, SLOT(updateCurHeader(const QString &)));
|
this, SLOT(updateCurHeader(const QString &)));
|
||||||
connect(m_document, &VDocument::keyPressed,
|
connect(m_document, &VDocument::keyPressed,
|
||||||
this, &VMdTab::handleWebKeyPressed);
|
this, &VMdTab::handleWebKeyPressed);
|
||||||
|
connect(m_document, SIGNAL(logicsFinished(void)),
|
||||||
|
this, SLOT(restoreFromTabInfo(void)));
|
||||||
page->setWebChannel(channel);
|
page->setWebChannel(channel);
|
||||||
|
|
||||||
m_webViewer->setHtml(VUtils::generateHtmlTemplate(m_mdConType, false),
|
m_webViewer->setHtml(VUtils::generateHtmlTemplate(m_mdConType, false),
|
||||||
@ -324,9 +345,11 @@ void VMdTab::setupMarkdownEditor()
|
|||||||
connect(m_editor, &VEdit::vimStatusUpdated,
|
connect(m_editor, &VEdit::vimStatusUpdated,
|
||||||
this, &VEditTab::vimStatusUpdated);
|
this, &VEditTab::vimStatusUpdated);
|
||||||
connect(m_editor, &VEdit::requestCloseFindReplaceDialog,
|
connect(m_editor, &VEdit::requestCloseFindReplaceDialog,
|
||||||
this, [this](){
|
this, [this]() {
|
||||||
this->m_editArea->getFindReplaceDialog()->closeDialog();
|
this->m_editArea->getFindReplaceDialog()->closeDialog();
|
||||||
});
|
});
|
||||||
|
connect(m_editor, SIGNAL(ready(void)),
|
||||||
|
this, SLOT(restoreFromTabInfo(void)));
|
||||||
|
|
||||||
m_editor->reloadFile();
|
m_editor->reloadFile();
|
||||||
m_stacks->addWidget(m_editor);
|
m_stacks->addWidget(m_editor);
|
||||||
@ -467,7 +490,7 @@ void VMdTab::scrollToAnchor(const VAnchor &p_anchor)
|
|||||||
m_curHeader = p_anchor;
|
m_curHeader = p_anchor;
|
||||||
|
|
||||||
if (m_isEditMode) {
|
if (m_isEditMode) {
|
||||||
dynamic_cast<VMdEdit *>(getEditor())->scrollToHeader(p_anchor);
|
dynamic_cast<VMdEdit *>(getEditor())->scrollToAnchor(p_anchor);
|
||||||
} else {
|
} else {
|
||||||
if (!p_anchor.anchor.isEmpty()) {
|
if (!p_anchor.anchor.isEmpty()) {
|
||||||
m_document->scrollToAnchor(p_anchor.anchor.mid(1));
|
m_document->scrollToAnchor(p_anchor.anchor.mid(1));
|
||||||
@ -682,9 +705,9 @@ void VMdTab::requestUpdateVimStatus()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VEditTabInfo VMdTab::createEditTabInfo()
|
VEditTabInfo VMdTab::fetchTabInfo()
|
||||||
{
|
{
|
||||||
VEditTabInfo info = VEditTab::createEditTabInfo();
|
VEditTabInfo info = VEditTab::fetchTabInfo();
|
||||||
|
|
||||||
if (m_editor) {
|
if (m_editor) {
|
||||||
QTextCursor cursor = m_editor->textCursor();
|
QTextCursor cursor = m_editor->textCursor();
|
||||||
@ -693,6 +716,8 @@ VEditTabInfo VMdTab::createEditTabInfo()
|
|||||||
info.m_blockCount = m_editor->document()->blockCount();
|
info.m_blockCount = m_editor->document()->blockCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.m_anchorIndex = m_curHeader.m_outlineIndex;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,3 +727,25 @@ void VMdTab::decorateText(TextDecoration p_decoration)
|
|||||||
m_editor->decorateText(p_decoration);
|
m_editor->decorateText(p_decoration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VMdTab::restoreFromTabInfo(const VEditTabInfo &p_info)
|
||||||
|
{
|
||||||
|
qDebug() << "restoreFromTabInfo" << p_info.m_anchorIndex;
|
||||||
|
if (p_info.m_editTab != this) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore anchor.
|
||||||
|
int anchorIdx = p_info.m_anchorIndex;
|
||||||
|
bool ret = scrollToAnchor(anchorIdx, true);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMdTab::restoreFromTabInfo()
|
||||||
|
{
|
||||||
|
restoreFromTabInfo(m_infoToRestore);
|
||||||
|
|
||||||
|
// Clear it anyway.
|
||||||
|
m_infoToRestore.m_editTab = NULL;
|
||||||
|
}
|
||||||
|
25
src/vmdtab.h
25
src/vmdtab.h
@ -62,6 +62,9 @@ public:
|
|||||||
// Insert decoration markers or decorate selected text.
|
// Insert decoration markers or decorate selected text.
|
||||||
void decorateText(TextDecoration p_decoration) Q_DECL_OVERRIDE;
|
void decorateText(TextDecoration p_decoration) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
// Create a filled VEditTabInfo.
|
||||||
|
VEditTabInfo fetchTabInfo() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
// Enter edit mode.
|
// Enter edit mode.
|
||||||
void editFile() Q_DECL_OVERRIDE;
|
void editFile() Q_DECL_OVERRIDE;
|
||||||
@ -91,6 +94,9 @@ private slots:
|
|||||||
// m_editor requests to discard changes and enter read mode.
|
// m_editor requests to discard changes and enter read mode.
|
||||||
void discardAndRead();
|
void discardAndRead();
|
||||||
|
|
||||||
|
// Restore from m_infoToRestore.
|
||||||
|
void restoreFromTabInfo();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Setup UI.
|
// Setup UI.
|
||||||
void setupUI();
|
void setupUI();
|
||||||
@ -111,8 +117,16 @@ private:
|
|||||||
void viewWebByConverter();
|
void viewWebByConverter();
|
||||||
|
|
||||||
// Scroll Web view to given header.
|
// Scroll Web view to given header.
|
||||||
// @p_outlineIndex is the index in m_toc.headers.
|
// @p_anchorIndex is the index in m_toc.headers.
|
||||||
void scrollWebViewToHeader(int p_outlineIndex);
|
// @p_strict: if true, scroll only when @p_anchorIndex is valid.
|
||||||
|
// Return true if scroll was made.
|
||||||
|
bool scrollWebViewToAnchor(int p_anchorIndex, bool p_strict = false);
|
||||||
|
|
||||||
|
// Scroll web/editor to given header.
|
||||||
|
// @p_anchorIndex is the index in m_toc.headers.
|
||||||
|
// @p_strict: if true, scroll only when @p_anchorIndex is valid.
|
||||||
|
// Return true if scroll was made.
|
||||||
|
bool scrollToAnchor(int p_anchorIndex, bool p_strict = false);
|
||||||
|
|
||||||
// Search text in Web view.
|
// Search text in Web view.
|
||||||
void findTextInWebView(const QString &p_text, uint p_options, bool p_peek,
|
void findTextInWebView(const QString &p_text, uint p_options, bool p_peek,
|
||||||
@ -127,12 +141,13 @@ private:
|
|||||||
// Focus the proper child widget.
|
// Focus the proper child widget.
|
||||||
void focusChild() Q_DECL_OVERRIDE;
|
void focusChild() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
// Create a filled VEditTabInfo.
|
|
||||||
VEditTabInfo createEditTabInfo() Q_DECL_OVERRIDE;
|
|
||||||
|
|
||||||
// Get the markdown editor. If not init yet, init and return it.
|
// Get the markdown editor. If not init yet, init and return it.
|
||||||
VEdit *getEditor();
|
VEdit *getEditor();
|
||||||
|
|
||||||
|
// Restore from @p_fino.
|
||||||
|
// Return true if succeed.
|
||||||
|
bool restoreFromTabInfo(const VEditTabInfo &p_info) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
VEdit *m_editor;
|
VEdit *m_editor;
|
||||||
VWebView *m_webViewer;
|
VWebView *m_webViewer;
|
||||||
VDocument *m_document;
|
VDocument *m_document;
|
||||||
|
@ -330,6 +330,16 @@ VNoteFile *VNote::getInternalFile(const QString &p_path)
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VFile *VNote::getFile(const QString &p_path)
|
||||||
|
{
|
||||||
|
VFile *file = getInternalFile(p_path);
|
||||||
|
if (!file) {
|
||||||
|
file = getOrphanFile(p_path, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
VDirectory *VNote::getInternalDirectory(const QString &p_path)
|
VDirectory *VNote::getInternalDirectory(const QString &p_path)
|
||||||
{
|
{
|
||||||
VDirectory *dir = NULL;
|
VDirectory *dir = NULL;
|
||||||
|
@ -78,6 +78,10 @@ public:
|
|||||||
|
|
||||||
QString getNavigationLabelStyle(const QString &p_str) const;
|
QString getNavigationLabelStyle(const QString &p_str) const;
|
||||||
|
|
||||||
|
// Given the path of a file, first try to open it as note file,
|
||||||
|
// then try to open it as orphan file.
|
||||||
|
VFile *getFile(const QString &p_path);
|
||||||
|
|
||||||
// Given the path of an external file, create a VOrphanFile struct.
|
// Given the path of an external file, create a VOrphanFile struct.
|
||||||
VOrphanFile *getOrphanFile(const QString &p_path,
|
VOrphanFile *getOrphanFile(const QString &p_path,
|
||||||
bool p_modifiable,
|
bool p_modifiable,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user