diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index ec37a745..005cd693 100644 --- a/src/resources/vnote.ini +++ b/src/resources/vnote.ini @@ -192,6 +192,9 @@ close_before_external_editor=true ; Each item is in the form "Name:Color" custom_colors=White:#FFFFFF,LightGrey:#EEEEEE +; Single click to open a file then close previous tab +single_click_close_previous_tab=true + [web] ; Location and configuration for Mathjax mathjax_javascript=https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp index 36b13f3d..234ba4a9 100644 --- a/src/vconfigmanager.cpp +++ b/src/vconfigmanager.cpp @@ -287,6 +287,9 @@ void VConfigManager::initialize() m_stylesToInlineWhenCopied = getConfigFromSettings("web", "styles_to_inline_when_copied").toStringList().join(","); + + m_singleClickClosePreviousTab = getConfigFromSettings("global", + "single_click_close_previous_tab").toBool(); } void VConfigManager::initSettings() diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h index ae09b84a..6e08f2ae 100644 --- a/src/vconfigmanager.h +++ b/src/vconfigmanager.h @@ -438,6 +438,8 @@ public: bool getMenuBarChecked() const; void setMenuBarChecked(bool p_checked); + bool getSingleClickClosePreviousTab() const; + private: // Look up a config from user and default settings. QVariant getConfigFromSettings(const QString §ion, const QString &key) const; @@ -835,6 +837,9 @@ private: // The string containing styles to inline when copied in edit mode. QString m_stylesToInlineWhenCopied; + // Single click to open file and then close previous tab. + bool m_singleClickClosePreviousTab; + // The name of the config file in each directory, obsolete. // Use c_dirConfigFile instead. static const QString c_obsoleteDirConfigFile; @@ -2036,4 +2041,9 @@ inline void VConfigManager::setMenuBarChecked(bool p_checked) { setConfigToSettings("global", "menu_bar_checked", p_checked); } + +inline bool VConfigManager::getSingleClickClosePreviousTab() const +{ + return m_singleClickClosePreviousTab; +} #endif // VCONFIGMANAGER_H diff --git a/src/veditwindow.cpp b/src/veditwindow.cpp index 4effb396..66f19b77 100644 --- a/src/veditwindow.cpp +++ b/src/veditwindow.cpp @@ -313,11 +313,6 @@ int VEditWindow::insertEditTab(int p_index, VFile *p_file, QWidget *p_page) return idx; } -int VEditWindow::appendEditTab(VFile *p_file, QWidget *p_page) -{ - return insertEditTab(count(), p_file, p_page); -} - int VEditWindow::openFile(VFile *p_file, OpenFileMode p_mode) { qDebug() << "open" << p_file->getName(); @@ -326,6 +321,7 @@ int VEditWindow::openFile(VFile *p_file, OpenFileMode p_mode) if (idx > -1) { goto out; } + idx = openFileInTab(p_file, p_mode); out: @@ -459,8 +455,9 @@ int VEditWindow::openFileInTab(VFile *p_file, OpenFileMode p_mode) // Connect the signals. connectEditTab(editor); - int idx = appendEditTab(p_file, editor); - return idx; + // Insert right after current tab. + // VFileList will depends on this behavior. + return insertEditTab(currentIndex() + 1, p_file, editor); } int VEditWindow::findTabByFile(const VFile *p_file) const @@ -990,7 +987,7 @@ bool VEditWindow::addEditTab(QWidget *p_widget) // Connect the signals. connectEditTab(editor); - int idx = appendEditTab(editor->getFile(), editor); + int idx = insertEditTab(currentIndex() + 1, editor->getFile(), editor); setCurrentIndex(idx); updateTabStatus(idx); return true; diff --git a/src/veditwindow.h b/src/veditwindow.h index f299ae6b..3fe352ff 100644 --- a/src/veditwindow.h +++ b/src/veditwindow.h @@ -149,8 +149,9 @@ private: void initTabActions(); void setupCornerWidget(); void removeEditTab(int p_index); + int insertEditTab(int p_index, VFile *p_file, QWidget *p_page); - int appendEditTab(VFile *p_file, QWidget *p_page); + int openFileInTab(VFile *p_file, OpenFileMode p_mode); QString generateTooltip(const VFile *p_file) const; diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index 21aabb68..5c17fe2f 100644 --- a/src/vfilelist.cpp +++ b/src/vfilelist.cpp @@ -1,6 +1,8 @@ #include #include #include +#include + #include "vfilelist.h" #include "vconfigmanager.h" #include "dialog/vnewfiledialog.h" @@ -30,11 +32,31 @@ const QString VFileList::c_cutShortcutSequence = "Ctrl+X"; const QString VFileList::c_pasteShortcutSequence = "Ctrl+V"; VFileList::VFileList(QWidget *parent) - : QWidget(parent), VNavigationMode() + : QWidget(parent), + VNavigationMode(), + m_itemClicked(NULL), + m_fileToCloseInSingleClick(NULL) { setupUI(); initShortcuts(); initActions(); + + m_clickTimer = new QTimer(this); + m_clickTimer->setSingleShot(true); + m_clickTimer->setInterval(QApplication::doubleClickInterval()); + // When timer timeouts, we need to close the previous tab to simulate the + // effect as opening file in current tab. + connect(m_clickTimer, &QTimer::timeout, + this, [this]() { + m_itemClicked = NULL; + VFile *file = m_fileToCloseInSingleClick; + m_fileToCloseInSingleClick = NULL; + + if (file) { + editArea->closeFile(file, false); + fileList->setFocus(); + } + }); } void VFileList::setupUI() @@ -613,18 +635,62 @@ QListWidgetItem* VFileList::findItem(const VNoteFile *p_file) void VFileList::handleItemClicked(QListWidgetItem *p_item) { - activateItem(p_item); + Q_ASSERT(p_item); - fileList->setFocus(); -} - -void VFileList::activateItem(QListWidgetItem *p_item) -{ Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers(); if (modifiers != Qt::NoModifier) { return; } + m_clickTimer->stop(); + if (m_itemClicked) { + // Timer will not trigger. + if (m_itemClicked == p_item) { + // Double clicked. + m_itemClicked = NULL; + m_fileToCloseInSingleClick = NULL; + return; + } else { + // Handle previous clicked item as single click. + m_itemClicked = NULL; + if (m_fileToCloseInSingleClick) { + editArea->closeFile(m_fileToCloseInSingleClick, false); + m_fileToCloseInSingleClick = NULL; + } + } + } + + // Pending @p_item. + bool singleClickClose = g_config->getSingleClickClosePreviousTab(); + if (singleClickClose) { + VFile *file = getVFile(p_item); + Q_ASSERT(file); + if (editArea->isFileOpened(file)) { + // File already opened. + activateItem(p_item, true); + return; + } + + // Get current tab which will be closed if click timer timeouts. + VEditTab *tab = editArea->getCurrentTab(); + if (tab) { + m_fileToCloseInSingleClick = tab->getFile(); + } else { + m_fileToCloseInSingleClick = NULL; + } + } + + // Activate it. + activateItem(p_item, true); + + if (singleClickClose) { + m_itemClicked = p_item; + m_clickTimer->start(); + } +} + +void VFileList::activateItem(QListWidgetItem *p_item, bool p_restoreFocus) +{ if (!p_item) { emit fileClicked(NULL); return; @@ -633,6 +699,10 @@ void VFileList::activateItem(QListWidgetItem *p_item) // Qt seems not to update the QListWidget correctly. Manually force it to repaint. fileList->update(); emit fileClicked(getVFile(p_item), g_config->getNoteOpenMode()); + + if (p_restoreFocus) { + fileList->setFocus(); + } } bool VFileList::importFiles(const QStringList &p_files, QString *p_errMsg) @@ -859,7 +929,23 @@ void VFileList::keyPressEvent(QKeyEvent *p_event) if (p_event->key() == Qt::Key_Return) { QListWidgetItem *item = fileList->currentItem(); if (item) { - activateItem(item); + VFile *fileToClose = NULL; + if (!(p_event->modifiers() & Qt::ControlModifier)) { + VFile *file = getVFile(item); + Q_ASSERT(file); + if (!editArea->isFileOpened(file)) { + VEditTab *tab = editArea->getCurrentTab(); + if (tab) { + fileToClose = tab->getFile(); + } + } + + } + + activateItem(item, false); + if (fileToClose) { + editArea->closeFile(fileToClose, false); + } } } diff --git a/src/vfilelist.h b/src/vfilelist.h index de8d02af..2238f75f 100644 --- a/src/vfilelist.h +++ b/src/vfilelist.h @@ -22,6 +22,7 @@ class VEditArea; class QFocusEvent; class QLabel; class QMenu; +class QTimer; class VFileList : public QWidget, public VNavigationMode { @@ -162,7 +163,7 @@ private: // Init Open With menu. void initOpenWithMenu(); - void activateItem(QListWidgetItem *p_item); + void activateItem(QListWidgetItem *p_item, bool p_restoreFocus = false); VEditArea *editArea; QListWidget *fileList; @@ -190,6 +191,12 @@ private: // Context sub-menu of Open With. QMenu *m_openWithMenu; + QTimer *m_clickTimer; + + QListWidgetItem *m_itemClicked; + + VFile *m_fileToCloseInSingleClick; + static const QString c_infoShortcutSequence; static const QString c_copyShortcutSequence; static const QString c_cutShortcutSequence;