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 <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-12-24 15:02:14 +08:00
parent 1aa264adc8
commit 16858d7474
7 changed files with 171 additions and 14 deletions

View File

@ -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>

After

Width:  |  Height:  |  Size: 779 B

View File

@ -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>

After

Width:  |  Height:  |  Size: 783 B

View File

@ -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;
}
}

View File

@ -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

View File

@ -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"),
m_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->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;
}

View File

@ -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

View File

@ -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>