Selaa lähdekoodia

support moving tabs between windows

Add two menu item on the tab's context menu to move one split
left/right.

Signed-off-by: Le Tan <[email protected]>
Le Tan 9 vuotta sitten
vanhempi
sitoutus
16858d7474

+ 9 - 0
src/resources/icons/move_tab_left.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<path d="M189.3,128.4L89,233.4c-6,5.8-9,13.7-9,22.4c0,8.7,3,16.5,9,22.4l100.3,105.4c11.9,12.5,31.3,12.5,43.2,0
+	c11.9-12.5,11.9-32.7,0-45.2L184.4,288h217c16.9,0,30.6-14.3,30.6-32c0-17.7-13.7-32-30.6-32h-217l48.2-50.4
+	c11.9-12.5,11.9-32.7,0-45.2C220.6,115.9,201.3,115.9,189.3,128.4z"/>
+</svg>

+ 9 - 0
src/resources/icons/move_tab_right.svg

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<path d="M322.7,128.4L423,233.4c6,5.8,9,13.7,9,22.4c0,8.7-3,16.5-9,22.4L322.7,383.6c-11.9,12.5-31.3,12.5-43.2,0
+	c-11.9-12.5-11.9-32.7,0-45.2l48.2-50.4h-217C93.7,288,80,273.7,80,256c0-17.7,13.7-32,30.6-32h217l-48.2-50.4
+	c-11.9-12.5-11.9-32.7,0-45.2C291.4,115.9,310.7,115.9,322.7,128.4z"/>
+</svg>

+ 25 - 1
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;
+    }
+}

+ 13 - 0
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<VEditWindow *>(splitter->widget(windowIndex));
 }
 
+inline int VEditArea::windowCount() const
+{
+    return splitter->count();
+}
+
 #endif // VEDITAREA_H

+ 103 - 11
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<VFile> 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<VEditTab *>(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;
+}

+ 10 - 2
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

+ 2 - 0
src/vnote.qrc

@@ -77,5 +77,7 @@
         <file>resources/icons/editing.svg</file>
         <file>resources/icons/reading.svg</file>
         <file>resources/icons/locate_note.svg</file>
+        <file>resources/icons/move_tab_left.svg</file>
+        <file>resources/icons/move_tab_right.svg</file>
     </qresource>
 </RCC>