diff --git a/src/resources/icons/move_tab_left.svg b/src/resources/icons/move_tab_left.svg new file mode 100644 index 00000000..37f3511b --- /dev/null +++ b/src/resources/icons/move_tab_left.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/resources/icons/move_tab_right.svg b/src/resources/icons/move_tab_right.svg new file mode 100644 index 00000000..332708ba --- /dev/null +++ b/src/resources/icons/move_tab_right.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/veditarea.cpp b/src/veditarea.cpp index 1f0c5d9a..518818ee 100644 --- a/src/veditarea.cpp +++ b/src/veditarea.cpp @@ -29,7 +29,7 @@ void VEditArea::setupUI() void VEditArea::insertSplitWindow(int idx) { - VEditWindow *win = new VEditWindow(vnote); + VEditWindow *win = new VEditWindow(vnote, this); splitter->insertWidget(idx, win); connect(win, &VEditWindow::tabStatusChanged, this, &VEditArea::curTabStatusChanged); @@ -385,3 +385,27 @@ VEditTab *VEditArea::currentEditTab() VEditWindow *win = getWindow(curWindowIndex); return win->currentEditTab(); } + +int VEditArea::windowIndex(const VEditWindow *p_window) const +{ + int nrWin = splitter->count(); + for (int i = 0; i < nrWin; ++i) { + if (p_window == getWindow(i)) { + return i; + } + } + return -1; +} + +void VEditArea::moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx) +{ + int nrWin = splitter->count(); + if (!p_widget || p_fromIdx < 0 || p_fromIdx >= nrWin + || p_toIdx < 0 || p_toIdx >= nrWin) { + return; + } + qDebug() << "move widget" << p_widget << "from" << p_fromIdx << "to" << p_toIdx; + if (!getWindow(p_toIdx)->addEditTab(p_widget)) { + delete p_widget; + } +} diff --git a/src/veditarea.h b/src/veditarea.h index 49268ec6..0e1b8ae6 100644 --- a/src/veditarea.h +++ b/src/veditarea.h @@ -30,6 +30,14 @@ public: bool closeFile(const VNotebook *p_notebook, bool p_forced); // Returns current edit tab. VEditTab *currentEditTab(); + // Returns the count of VEditWindow. + inline int windowCount() const; + // Returns the index of @p_window. + int windowIndex(const VEditWindow *p_window) const; + // Move tab widget @p_widget from window @p_fromIdx to @p_toIdx. + // @p_widget has been removed from the original window. + // If fail, just delete the p_widget. + void moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx); signals: void curTabStatusChanged(const VFile *p_file, const VEditTab *p_editTab, bool p_editMode); @@ -81,4 +89,9 @@ inline VEditWindow* VEditArea::getWindow(int windowIndex) const return dynamic_cast(splitter->widget(windowIndex)); } +inline int VEditArea::windowCount() const +{ + return splitter->count(); +} + #endif // VEDITAREA_H diff --git a/src/veditwindow.cpp b/src/veditwindow.cpp index 20c86809..7250b869 100644 --- a/src/veditwindow.cpp +++ b/src/veditwindow.cpp @@ -7,11 +7,12 @@ #include "utils/vutils.h" #include "vfile.h" #include "vmainwindow.h" +#include "veditarea.h" extern VConfigManager vconfig; -VEditWindow::VEditWindow(VNote *vnote, QWidget *parent) - : QTabWidget(parent), vnote(vnote) +VEditWindow::VEditWindow(VNote *vnote, VEditArea *editArea, QWidget *parent) + : QTabWidget(parent), vnote(vnote), m_editArea(editArea) { initTabActions(); setupCornerWidget(); @@ -37,11 +38,23 @@ VEditWindow::VEditWindow(VNote *vnote, QWidget *parent) void VEditWindow::initTabActions() { - locateAct = new QAction(QIcon(":/resources/icons/locate_note.svg"), - tr("Locate"), this); - locateAct->setStatusTip(tr("Locate the directory of current note")); - connect(locateAct, &QAction::triggered, + m_locateAct = new QAction(QIcon(":/resources/icons/locate_note.svg"), + tr("Locate"), this); + m_locateAct->setStatusTip(tr("Locate the directory of current note")); + connect(m_locateAct, &QAction::triggered, this, &VEditWindow::handleLocateAct); + + m_moveLeftAct = new QAction(QIcon(":/resources/icons/move_tab_left.svg"), + tr("Move One Split Left"), this); + m_moveLeftAct->setStatusTip(tr("Move current tab to the split on the left")); + connect(m_moveLeftAct, &QAction::triggered, + this, &VEditWindow::handleMoveLeftAct); + + m_moveRightAct = new QAction(QIcon(":/resources/icons/move_tab_right.svg"), + tr("Move One Split Right"), this); + m_moveRightAct->setStatusTip(tr("Move current tab to the split on the right")); + connect(m_moveRightAct, &QAction::triggered, + this, &VEditWindow::handleMoveRightAct); } void VEditWindow::setupCornerWidget() @@ -111,7 +124,6 @@ int VEditWindow::insertEditTab(int p_index, VFile *p_file, QWidget *p_page) { int idx = insertTab(p_index, p_page, p_file->getName()); setTabToolTip(idx, generateTooltip(p_file)); - setTabIcon(idx, QIcon(":/resources/icons/reading.svg")); return idx; } @@ -386,8 +398,23 @@ void VEditWindow::tabbarContextMenuRequested(QPoint p_pos) if (tab == -1) { return; } - locateAct->setData(tab); - menu.addAction(locateAct); + m_locateAct->setData(tab); + menu.addAction(m_locateAct); + + int totalWin = m_editArea->windowCount(); + int idx = m_editArea->windowIndex(this); + if (totalWin > 1) { + menu.addSeparator(); + if (idx > 0) { + m_moveLeftAct->setData(tab); + menu.addAction(m_moveLeftAct); + } + if (idx < totalWin - 1) { + m_moveRightAct->setData(tab); + menu.addAction(m_moveRightAct); + } + } + menu.exec(mapToGlobal(p_pos)); } @@ -596,9 +623,74 @@ VEditTab *VEditWindow::currentEditTab() void VEditWindow::handleLocateAct() { - int tab = locateAct->data().toInt(); - qDebug() << "context menu of tab" << tab; + int tab = m_locateAct->data().toInt(); VEditTab *editor = getTab(tab); QPointer file = editor->getFile(); vnote->getMainWindow()->locateFile(file); } + +void VEditWindow::handleMoveLeftAct() +{ + int tab = m_locateAct->data().toInt(); + Q_ASSERT(tab != -1); + VEditTab *editor = getTab(tab); + // Remove it from current window. This won't close the split even if it is + // the only tab. + removeTab(tab); + + // Disconnect all the signals. + disconnect(editor, 0, this, 0); + + int idx = m_editArea->windowIndex(this); + m_editArea->moveTab(editor, idx, idx - 1); + + // If there is no tab, remove current split. + if (count() == 0) { + emit requestRemoveSplit(this); + } +} + +void VEditWindow::handleMoveRightAct() +{ + int tab = m_locateAct->data().toInt(); + Q_ASSERT(tab != -1); + VEditTab *editor = getTab(tab); + // Remove it from current window. This won't close the split even if it is + // the only tab. + removeTab(tab); + + // Disconnect all the signals. + disconnect(editor, 0, this, 0); + + int idx = m_editArea->windowIndex(this); + m_editArea->moveTab(editor, idx, idx + 1); + + // If there is no tab, remove current split. + if (count() == 0) { + emit requestRemoveSplit(this); + } +} + +bool VEditWindow::addEditTab(QWidget *p_widget) +{ + if (!p_widget) { + return false; + } + VEditTab *editor = dynamic_cast(p_widget); + if (!editor) { + return false; + } + // Connect the signals. + connect(editor, &VEditTab::getFocused, + this, &VEditWindow::getFocused); + connect(editor, &VEditTab::outlineChanged, + this, &VEditWindow::handleOutlineChanged); + connect(editor, &VEditTab::curHeaderChanged, + this, &VEditWindow::handleCurHeaderChanged); + connect(editor, &VEditTab::statusChanged, + this, &VEditWindow::handleTabStatusChanged); + int idx = appendEditTab(editor->getFile(), editor); + setCurrentIndex(idx); + noticeTabStatus(idx); + return true; +} diff --git a/src/veditwindow.h b/src/veditwindow.h index 2ce7d2b5..a1e2970c 100644 --- a/src/veditwindow.h +++ b/src/veditwindow.h @@ -14,12 +14,13 @@ class VNote; class QPushButton; class QActionGroup; class VFile; +class VEditArea; class VEditWindow : public QTabWidget { Q_OBJECT public: - explicit VEditWindow(VNote *vnote, QWidget *parent = 0); + explicit VEditWindow(VNote *vnote, VEditArea *editArea, QWidget *parent = 0); int findTabByFile(const VFile *p_file) const; int openFile(VFile *p_file, OpenFileMode p_mode); bool closeFile(const VFile *p_file, bool p_forced); @@ -40,6 +41,8 @@ public: void updateDirectoryInfo(const VDirectory *p_dir); void updateNotebookInfo(const VNotebook *p_notebook); VEditTab *currentEditTab(); + // Insert a tab with @p_widget. @p_widget is a fully initialized VEditTab. + bool addEditTab(QWidget *p_widget); protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; @@ -68,6 +71,8 @@ private slots: void updateSplitMenu(); void tabbarContextMenuRequested(QPoint p_pos); void handleLocateAct(); + void handleMoveLeftAct(); + void handleMoveRightAct(); private: void initTabActions(); @@ -87,6 +92,7 @@ private: void setLeftCornerWidgetVisible(bool p_visible); VNote *vnote; + VEditArea *m_editArea; // Button in the right corner QPushButton *rightBtn; // Button in the left corner @@ -97,7 +103,9 @@ private: QAction *removeSplitAct; QActionGroup *tabListAct; // Locate current note in the directory and file list - QAction *locateAct; + QAction *m_locateAct; + QAction *m_moveLeftAct; + QAction *m_moveRightAct; }; inline VEditTab* VEditWindow::getTab(int tabIndex) const diff --git a/src/vnote.qrc b/src/vnote.qrc index 95b294e1..49f86cd0 100644 --- a/src/vnote.qrc +++ b/src/vnote.qrc @@ -77,5 +77,7 @@ resources/icons/editing.svg resources/icons/reading.svg resources/icons/locate_note.svg + resources/icons/move_tab_left.svg + resources/icons/move_tab_right.svg