[rkward/work/split_views] rkward: Start adding split-view functionality.

Thomas Friedrichsmeier null at kde.org
Mon Jun 19 07:32:20 UTC 2017


Git commit 80da70be928bb898fc2825c33163992a1f60284a by Thomas Friedrichsmeier.
Committed on 19/06/2017 at 07:29.
Pushed by tfry into branch 'work/split_views'.

Start adding split-view functionality.

This commit is just the base-work: Supports organizing the workplace view area into a multitude of tab widgets inside splitter(s).
TODO: -Actual functions and UI to do the splitting itself.
      -Allow having duplicate windows for most types (scripts / pages / editors), so they can be "split" in the first place.

M  +1    -1    rkward/rkward.cpp
M  +7    -2    rkward/windows/rkmdiwindow.cpp
M  +3    -1    rkward/windows/rkmdiwindow.h
M  +2    -2    rkward/windows/rkworkplace.cpp
M  +1    -1    rkward/windows/rkworkplace.h
M  +202  -91   rkward/windows/rkworkplaceview.cpp
M  +44   -17   rkward/windows/rkworkplaceview.h

https://commits.kde.org/rkward/80da70be928bb898fc2825c33163992a1f60284a

diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index 6e510412..52aac6d6 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -130,7 +130,7 @@ RKWardMainWindow::RKWardMainWindow () : KParts::MainWindow ((QWidget *)0, (Qt::W
 	initStatusBar();
 
 	new RKWorkplace (this);
-	RKWorkplace::mainWorkplace ()->initActions (actionCollection (), "left_window", "right_window");
+	RKWorkplace::mainWorkplace ()->initActions (actionCollection ());
 	setCentralWidget (RKWorkplace::mainWorkplace ());
 	connect (RKWorkplace::mainWorkplace ()->view (), &RKWorkplaceView::captionChanged, this, static_cast<void (RKWardMainWindow::*)(const QString&)>(&RKWardMainWindow::setCaption));
 	connect (RKWorkplace::mainWorkplace (), &RKWorkplace::workspaceUrlChanged, this, &RKWardMainWindow::addWorkspaceUrl);
diff --git a/rkward/windows/rkmdiwindow.cpp b/rkward/windows/rkmdiwindow.cpp
index fe341284..60c8e881 100644
--- a/rkward/windows/rkmdiwindow.cpp
+++ b/rkward/windows/rkmdiwindow.cpp
@@ -2,7 +2,7 @@
                           rkmdiwindow  -  description
                              -------------------
     begin                : Tue Sep 26 2006
-    copyright            : (C) 2006, 2007, 2008, 2009, 2010, 2011 by Thomas Friedrichsmeier
+    copyright            : (C) 2006 - 2017 by Thomas Friedrichsmeier
     email                : thomas.friedrichsmeier at kdemail.net
  ***************************************************************************/
 
@@ -115,6 +115,11 @@ bool RKMDIWindow::isActive () {
 	// don't trace, called pretty often
 
 	if (!topLevelWidget ()->isActiveWindow ()) return false;
+	return isActiveInsideToplevelWindow ();
+}
+
+bool RKMDIWindow::isActiveInsideToplevelWindow () {
+	// don't trace, called pretty often
 	return (active || (!isAttached ()));
 }
 
@@ -131,7 +136,7 @@ void RKMDIWindow::activate (bool with_focus) {
 			topLevelWidget ()->raise ();
 		}
 	} else {
-		if (isAttached ()) RKWorkplace::mainWorkplace ()->view ()->setCurrentWidget (this);
+		if (isAttached ()) RKWorkplace::mainWorkplace ()->view ()->showWindow (this);
 		else {
 			topLevelWidget ()->show ();
 			topLevelWidget ()->raise ();
diff --git a/rkward/windows/rkmdiwindow.h b/rkward/windows/rkmdiwindow.h
index 8e36e6f7..d5632a43 100644
--- a/rkward/windows/rkmdiwindow.h
+++ b/rkward/windows/rkmdiwindow.h
@@ -2,7 +2,7 @@
                           rkmdiwindow  -  description
                              -------------------
     begin                : Tue Sep 26 2006
-    copyright            : (C) 2006, 2007, 2008, 2009, 2010 by Thomas Friedrichsmeier
+    copyright            : (C) 2006 - 2017 by Thomas Friedrichsmeier
     email                : thomas.friedrichsmeier at kdemail.net
  ***************************************************************************/
 
@@ -115,6 +115,8 @@ is simply busy (e.g. when saving the current plot to history). */
 	bool acceptsEventsFor (QObject *object);
 /** Whether the window is active. This seems to be more reliable than hasFocus () */
 	bool isActive ();
+/** Like isActive (), but also returns true, if this window _would_ be the active one, if the parent topLevelWindow() _was_ the active Window. */
+	bool isActiveInsideToplevelWindow ();
 /** Returns a pointer to an action collection suitable to place RKStandardAction in. This collection (and the corresponding KXMLGUIClient) is created on the fly. */
 	KActionCollection *standardActionCollection ();
 /** plugin-accessible properties of this object in the global context. Currently used only by RKEditorDataFrame to give information on the currently active data.frame. NOTE: ATM, you cannot set arbitrary properties. Only those supported in RKStandardComponent will have an effect. */
diff --git a/rkward/windows/rkworkplace.cpp b/rkward/windows/rkworkplace.cpp
index 09b60b7a..659a6327 100644
--- a/rkward/windows/rkworkplace.cpp
+++ b/rkward/windows/rkworkplace.cpp
@@ -182,10 +182,10 @@ void RKWorkplace::saveSettings () {
 	for (int i = 0; i < TOOL_WINDOW_BAR_COUNT; ++i) tool_window_bars[i]->saveSize (toolbar_config);
 }
 
-void RKWorkplace::initActions (KActionCollection *ac, const char *left_id, const char *right_id) {
+void RKWorkplace::initActions (KActionCollection *ac) {
 	RK_TRACE (APP);
 
-	wview->initActions (ac, left_id, right_id);
+	wview->initActions (ac);
 }
 
 void RKWorkplace::attachWindow (RKMDIWindow *window) {
diff --git a/rkward/windows/rkworkplace.h b/rkward/windows/rkworkplace.h
index 88bfc5fe..abcd1d6e 100644
--- a/rkward/windows/rkworkplace.h
+++ b/rkward/windows/rkworkplace.h
@@ -77,7 +77,7 @@ public:
 @param parent: The parent widget for the workspace view (see view ()) */
 	explicit RKWorkplace (QWidget *parent);
 	~RKWorkplace ();
-	void initActions (KActionCollection *ac, const char *left_id, const char *right_id);
+	void initActions (KActionCollection *ac);
 
 /** @returns a pointer to the view of the workplace. Since possibly the workplace layout might change, better not rely on this pointer being valid for long */
 	RKWorkplaceView *view () { return wview; };
diff --git a/rkward/windows/rkworkplaceview.cpp b/rkward/windows/rkworkplaceview.cpp
index e2d1cfaa..7d86d27c 100644
--- a/rkward/windows/rkworkplaceview.cpp
+++ b/rkward/windows/rkworkplaceview.cpp
@@ -2,7 +2,7 @@
                           rkworkplaceview  -  description
                              -------------------
     begin                : Tue Sep 26 2006
-    copyright            : (C) 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
+    copyright            : (C) 2006 - 2017 by Thomas Friedrichsmeier
     email                : thomas.friedrichsmeier at kdemail.net
  ***************************************************************************/
 
@@ -37,193 +37,304 @@
 
 #include "../debug.h"
 
-
-RKWorkplaceView::RKWorkplaceView (QWidget *parent) : QTabWidget (parent) {
+RKWorkplaceViewPane::RKWorkplaceViewPane (RKWorkplaceView* parent) : QTabWidget (parent) {
 	RK_TRACE (APP);
 
+	workplace_view = parent;
+
 	// close button(s)
 	QToolButton* close_button = new QToolButton (this);
 	close_button->setIcon (QIcon::fromTheme("tab-close"));
-	connect (close_button, &QToolButton::clicked, this, &RKWorkplaceView::closeCurrentPage);
+	connect (close_button, &QToolButton::clicked, this, &RKWorkplaceViewPane::closeCurrentPage);
 	close_button->adjustSize ();
 	setCornerWidget (close_button, Qt::TopRightCorner);
 
 	setTabsClosable (true);
-	connect (this, &QTabWidget::tabCloseRequested, this, static_cast<void (RKWorkplaceView::*)(int)>(&RKWorkplaceView::closePage));
+	connect (this, &QTabWidget::tabCloseRequested, this, static_cast<void (RKWorkplaceViewPane::*)(int)>(&RKWorkplaceViewPane::closePage));
 
 	setMovable (true);
 
 	tabBar ()->setContextMenuPolicy (Qt::CustomContextMenu);
-	connect (tabBar (), &QWidget::customContextMenuRequested, this, &RKWorkplaceView::showContextMenu);
+	connect (tabBar (), &QWidget::customContextMenuRequested, this, &RKWorkplaceViewPane::showContextMenu);
 
 	KAcceleratorManager::setNoAccel (tabBar ());	// TODO: This is a WORKAROUND for a bug in kdelibs where tabs named "a0.txt", "a1.txt", etc. will steal the Alt+0/1... shortcuts
-	tabBar ()->hide ();		// initially
-	connect (this, &QTabWidget::currentChanged, this, &RKWorkplaceView::currentPageChanged);
+	connect (this, &QTabWidget::currentChanged, workplace_view, &RKWorkplaceView::currentPageChanged);
 }
 
-RKWorkplaceView::~RKWorkplaceView () {
+RKWorkplaceViewPane::~RKWorkplaceViewPane () {
 	RK_TRACE (APP);
 }
 
-void RKWorkplaceView::initActions (KActionCollection *ac, const char *id_left, const char *id_right) {
+bool RKWorkplaceViewPane::isActive () {
 	RK_TRACE (APP);
 
-	action_page_left = (QAction *) ac->addAction (id_left, this, SLOT (pageLeft()));
-	action_page_left->setText (i18n ("Window Left"));
-	ac->setDefaultShortcuts (action_page_left, QList<QKeySequence>() << Qt::ControlModifier + Qt::Key_Less << Qt::ControlModifier + Qt::Key_Comma);
+	return (currentWidget () && static_cast<RKMDIWindow*> (currentWidget ())->isActiveInsideToplevelWindow ());
+}
 
-	action_page_right = (QAction *) ac->addAction (id_right, this, SLOT (pageRight()));
-	action_page_right->setText (i18n ("Window Right"));
-	ac->setDefaultShortcuts (action_page_right, QList<QKeySequence>() << Qt::ControlModifier + Qt::Key_Greater << Qt::ControlModifier + Qt::Key_Period);
+void RKWorkplaceViewPane::showContextMenu (const QPoint &pos) {
+	RK_TRACE (APP);
 
-	updateActions ();
+	int tab = tabBar ()->tabAt (pos);
+	if (tab < 0) return;	// no context menu for the empty area
+
+	QMenu* m = new QMenu (this);
+	QAction *action = KStandardAction::close (this, SLOT (contextMenuClosePage()), this);
+	action->setData (tab);
+	m->addAction (action);
+	action = m->addAction (RKStandardIcons::getIcon (RKStandardIcons::ActionDetachWindow), i18n("Detach"), this, SLOT (contextMenuDetachWindow()));
+	action->setData (tab);
+	m->exec (mapToGlobal (pos));
+	delete m;
 }
 
-void RKWorkplaceView::updateActions () {
+void RKWorkplaceViewPane::closeCurrentPage () {
 	RK_TRACE (APP);
 
-	int index = currentIndex ();
-	action_page_left->setEnabled (index > 0);
-	action_page_right->setEnabled (index < (count () - 1));
+	closePage (currentWidget ());
 }
 
-void RKWorkplaceView::pageLeft () {
+void RKWorkplaceViewPane::closePage (int index) {
 	RK_TRACE (APP);
 
-	int index = currentIndex ();
-	RK_ASSERT (index > 0);
-	setCurrentIndex (index - 1);
+	closePage (widget (index));
 }
 
-void RKWorkplaceView::pageRight () {
+void RKWorkplaceViewPane::closePage (QWidget* page) {
 	RK_TRACE (APP);
 
-	int index = currentIndex ();
-	RK_ASSERT (index < (count () - 1));
-	setCurrentIndex (index + 1);
+	if (!page) {
+		RK_ASSERT (false);
+		return;
+	}
+	static_cast<RKMDIWindow*>(page)->close (true);
 }
 
-void RKWorkplaceView::addWindow (RKMDIWindow *widget) {
+void RKWorkplaceViewPane::tabRemoved (int index) {
 	RK_TRACE (APP);
+	QTabWidget::tabRemoved (index);
+	if (count () < 1) emit (becameEmpty (this));
+}
 
-	int id = -1;
+void RKWorkplaceViewPane::contextMenuClosePage () {
+	RK_TRACE (APP);
 
-	QIcon icon = widget->windowIcon ();
-	if (icon.isNull ()) icon = widget->topLevelWidget ()->windowIcon ();
-	if (icon.isNull ()) RK_ASSERT (false);
+	QAction* action = dynamic_cast<QAction*> (sender ());
+	if (!action) {
+		RK_ASSERT (false);
+		return;
+	}
 
-	id = addTab (widget, icon, widget->shortCaption ());
+	int tab = action->data ().toInt ();
+	RK_ASSERT (tab >= 0);
+	closePage (tab);
+}
 
-	connect (widget, &RKMDIWindow::captionChanged, this, &RKWorkplaceView::childCaptionChanged);
-	widget->show ();
+void RKWorkplaceViewPane::contextMenuDetachWindow () {
+	RK_TRACE (APP);
 
-	if (count () > 1) tabBar ()->show ();
+	QAction* action = dynamic_cast<QAction*> (sender ());
+	if (!action) {
+		RK_ASSERT (false);
+		return;
+	}
 
-	setCurrentIndex (id);		// activate the new tab
+	int tab = action->data ().toInt ();
+	RK_ASSERT (tab >= 0);
+	RKWorkplace::mainWorkplace ()->detachWindow (static_cast<RKMDIWindow*> (widget (tab)));
 }
 
-bool RKWorkplaceView::hasWindow (RKMDIWindow *widget) {
-	return (indexOf (widget) != -1);
+
+
+RKWorkplaceView::RKWorkplaceView (QWidget *parent) : QSplitter (parent) {
+	RK_TRACE (APP);
+	newPane (0);
 }
 
-void RKWorkplaceView::removeWindow (RKMDIWindow *widget, bool destroyed) {
+RKWorkplaceView::~RKWorkplaceView () {
 	RK_TRACE (APP);
+}
 
-	int id = indexOf (widget);		// which page is it?
-	if (id == -1) RK_DEBUG (APP, DL_WARNING, "did not find page in RKWorkplaceView::removeWindow");
-	if (!destroyed) disconnect (widget, &RKMDIWindow::captionChanged, this, &RKWorkplaceView::childCaptionChanged);
+RKWorkplaceViewPane* RKWorkplaceView::activePane () const {
+	RK_TRACE (APP);
 
-	removeTab (id);
-	if (count () <= 1) tabBar ()->hide ();
+	for (int i = 0; i < panes.size (); ++i) {
+		if (panes[i]->isActive ()) return panes[i];
+	}
+	if (!panes.isEmpty ()) return panes.first ();
+	return 0;
 }
 
-RKMDIWindow *RKWorkplaceView::activePage () {
+void RKWorkplaceView::initActions (KActionCollection *ac) {
 	RK_TRACE (APP);
 
-	QWidget *w = currentWidget ();
-	return (dynamic_cast<RKMDIWindow *> (w));
+	action_page_left = (QAction *) ac->addAction ("left_window", this, SLOT (pageLeft()));
+	action_page_left->setText (i18n ("Window Left"));
+	ac->setDefaultShortcuts (action_page_left, QList<QKeySequence>() << Qt::ControlModifier + Qt::Key_Less << Qt::ControlModifier + Qt::Key_Comma);
+
+	action_page_right = (QAction *) ac->addAction ("right_window", this, SLOT (pageRight()));
+	action_page_right->setText (i18n ("Window Right"));
+	ac->setDefaultShortcuts (action_page_right, QList<QKeySequence>() << Qt::ControlModifier + Qt::Key_Greater << Qt::ControlModifier + Qt::Key_Period);
+
+	updateActions ();
 }
 
-void RKWorkplaceView::closeCurrentPage () {
+void RKWorkplaceView::updateActions () {
 	RK_TRACE (APP);
 
-	RKMDIWindow* w = activePage ();
+	bool several_pages = panes.count () > 1 || (panes.count () > 0 && panes.first()->count () > 1);
+	action_page_left->setEnabled (several_pages);
+	action_page_right->setEnabled (several_pages);
+}
+
+void RKWorkplaceView::pageLeft () {
+	RK_TRACE (APP);
 
-	if (!w) {
-		RK_ASSERT (false);	// the close button should not be visible, if there are no pages
+	RKWorkplaceViewPane *current = activePane ();
+	if (!current) {
+		RK_ASSERT (current);  // can this happen? It should not, as long as the action does not get called on an empty workplace view
 		return;
 	}
 
-	w->close (true);
+	int index = current->currentIndex ();
+	if (index > 0) {
+		current->setCurrentIndex (index - 1);
+	} else {
+		int pindex = panes.indexOf (current);
+		if (pindex > 0) --pindex;
+		else pindex = panes.size () - 1;
+		if (panes[pindex]->count () < 1) {
+			RK_ASSERT (false); // it should have been purged.
+			return;
+		}
+		panes[pindex]->setCurrentIndex (panes[pindex]->count () - 1);
+	}
 }
 
-void RKWorkplaceView::closePage (QWidget* page) {
+void RKWorkplaceView::pageRight () {
 	RK_TRACE (APP);
 
-	if (!page) {
-		RK_ASSERT (false);
+	RKWorkplaceViewPane *current = activePane ();
+	if (!current) {
+		RK_ASSERT (current);  // can this happen? It should not, as long as the action does not get called on an empty workplace view
 		return;
 	}
-	static_cast<RKMDIWindow*>(page)->close (true);
+
+	int index = current->currentIndex ();
+	if (index < current->count () - 1) {
+		current->setCurrentIndex (index + 1);
+	} else {
+		int pindex = panes.indexOf (current);
+		if (pindex < panes.count () - 1) ++pindex;
+		else pindex = 0;
+		if (panes[pindex]->count () < 1) {
+			RK_ASSERT (false); // it should have been purged.
+			return;
+		}
+		panes[pindex]->setCurrentIndex (0);
+	}
 }
 
-void RKWorkplaceView::closePage (int page) {
+RKWorkplaceViewPane* RKWorkplaceView::newPane (int index) {
 	RK_TRACE (APP);
 
-	closePage (widget (page));
+	if (index < 0) index = count ();
+	RKWorkplaceViewPane *pane = new RKWorkplaceViewPane (this);
+	addWidget (pane);
+	connect (pane, &RKWorkplaceViewPane::becameEmpty, this, &RKWorkplaceView::purgePane);
+	panes.append (pane);
+	return pane;
 }
 
-void RKWorkplaceView::showContextMenu (const QPoint &pos) {
+void RKWorkplaceView::addWindow (RKMDIWindow *widget) {
 	RK_TRACE (APP);
 
-	int tab = tabBar ()->tabAt (pos);
-	if (tab < 0) return;	// no context menu for the empty area
+	int id = -1;
 
-	QMenu* m = new QMenu (this);
-	QAction *action = KStandardAction::close (this, SLOT (contextMenuClosePage()), this);
-	action->setData (tab);
-	m->addAction (action);
-	action = m->addAction (RKStandardIcons::getIcon (RKStandardIcons::ActionDetachWindow), i18n("Detach"), this, SLOT (contextMenuDetachWindow()));
-	action->setData (tab);
-	m->exec (mapToGlobal (pos));
-	delete m;
+	QIcon icon = widget->windowIcon ();
+	if (icon.isNull ()) icon = widget->topLevelWidget ()->windowIcon ();
+	if (icon.isNull ()) RK_ASSERT (false);
+
+	RKWorkplaceViewPane *pane = activePane ();
+	if (!pane) {
+		RK_ASSERT (count () == 0);
+		pane = newPane (0);
+	}
+	id = pane->addTab (widget, icon, widget->shortCaption ());
+
+	connect (widget, &RKMDIWindow::captionChanged, this, &RKWorkplaceView::childCaptionChanged);
+	widget->show ();
+
+	pane->setCurrentIndex (id);		// activate the new tab
 }
 
-void RKWorkplaceView::contextMenuClosePage () {
+void RKWorkplaceView::showWindow (RKMDIWindow *widget) {
 	RK_TRACE (APP);
 
-	QAction* action = dynamic_cast<QAction*> (sender ());
-	if (!action) {
-		RK_ASSERT (false);
-		return;
+	RKWorkplaceViewPane *pane = findWindow (widget);
+	pane->setCurrentIndex (pane->indexOf (widget));
+}
+
+RKWorkplaceViewPane* RKWorkplaceView::findWindow (RKMDIWindow *widget) const {
+	for (int i = 0; i < panes.size (); ++i) {
+		if (panes[i]->indexOf (widget) > -1) return panes[i];
 	}
+	return 0;
+}
 
-	int tab = action->data ().toInt ();
-	RK_ASSERT (tab >= 0);
-	closePage (tab);
+bool RKWorkplaceView::hasWindow (RKMDIWindow *widget) const {
+	return (findWindow (widget) != 0);
 }
 
-void RKWorkplaceView::contextMenuDetachWindow () {
+void RKWorkplaceView::removeWindow (RKMDIWindow *widget, bool destroyed) {
 	RK_TRACE (APP);
 
-	QAction* action = dynamic_cast<QAction*> (sender ());
-	if (!action) {
-		RK_ASSERT (false);
-		return;
+	RKWorkplaceViewPane *pane = findWindow (widget);
+	int id = pane ? pane->indexOf (widget) : -1;		// which page is it?
+	if (id == -1) RK_DEBUG (APP, DL_WARNING, "did not find page in RKWorkplaceView::removeWindow");
+	if (!destroyed) disconnect (widget, &RKMDIWindow::captionChanged, this, &RKWorkplaceView::childCaptionChanged);
+
+	if (pane) pane->removeTab (id);
+}
+
+void RKWorkplaceView::purgePane (RKWorkplaceViewPane* pane) {
+	RK_TRACE (APP);
+	RK_ASSERT (pane);
+	if (pane->count () > 0) return;
+	if (count () == 1 && pane->parentWidget () == this) return;  // keep at least one pane around for layout purposes
+
+	QSplitter* split = static_cast<QSplitter*> (pane->parentWidget ());
+	pane->hide ();
+	pane->setParent (0); // TODO: needed?
+	pane->deleteLater ();
+	while (split != this && split->count () < 1) {
+		QSplitter* p = static_cast<QSplitter*> (split->parentWidget ());
+		delete (split);
+		split = p;
 	}
+	bool removed = panes.removeAll (pane) > 0;
+	RK_ASSERT (removed);
+}
 
-	int tab = action->data ().toInt ();
-	RK_ASSERT (tab >= 0);
-	RKWorkplace::mainWorkplace ()->detachWindow (static_cast<RKMDIWindow*> (widget (tab)));
+RKMDIWindow *RKWorkplaceView::activePage () const {
+	RK_TRACE (APP);
+
+	RKWorkplaceViewPane *pane = activePane ();
+	if (pane) return (dynamic_cast<RKMDIWindow *> (pane->currentWidget ()));
+	return 0;
 }
 
 void RKWorkplaceView::childCaptionChanged (RKMDIWindow *widget) {
 	RK_TRACE (APP);
 
-	int id = indexOf (widget);
+	RKWorkplaceViewPane *pane = findWindow (widget);
+	if (!pane)  {
+		RK_ASSERT (pane);
+		return;
+	}
+	int id = pane->indexOf (widget);
 	RK_ASSERT (id >= 0);
-	setTabText (id, widget->shortCaption ());
-	if (id == currentIndex ()) setCaption (widget->shortCaption ());
+	pane->setTabText (id, widget->shortCaption ());
+	if (id == pane->currentIndex ()) setCaption (widget->shortCaption ());
 }
 
 void RKWorkplaceView::setCaption (const QString &caption) {
diff --git a/rkward/windows/rkworkplaceview.h b/rkward/windows/rkworkplaceview.h
index 457e69cd..39b088bc 100644
--- a/rkward/windows/rkworkplaceview.h
+++ b/rkward/windows/rkworkplaceview.h
@@ -2,7 +2,7 @@
                           rkworkplaceview  -  description
                              -------------------
     begin                : Tue Sep 26 2006
-    copyright            : (C) 2006, 2007, 2010 by Thomas Friedrichsmeier
+    copyright            : (C) 2006 - 017 by Thomas Friedrichsmeier
     email                : thomas.friedrichsmeier at kdemail.net
  ***************************************************************************/
 
@@ -19,16 +19,46 @@
 #define RKWORKPLACEVIEW_H
 
 #include <QTabWidget>
+#include <QSplitter>
 
 class RKMDIWindow;
 class QAction;
 class KActionCollection;
+class RKWorkplaceView;
+
+class RKWorkplaceViewPane : public QTabWidget {
+	Q_OBJECT
+friend class RKWorkplaceView;
+private:
+	explicit RKWorkplaceViewPane (RKWorkplaceView *parent);
+	~RKWorkplaceViewPane ();
+	RKWorkplaceView* workplace_view;
+/** Close a page given the correspoding widget */
+	void closePage (QWidget* page);
+/** Close a page given its index */
+	void closePage (int page);
+/** (Attempts to) close the current tab */
+	void closeCurrentPage ();
+	bool isActive ();
+protected:
+	void tabRemoved (int index) override;
+signals:
+	void becameEmpty (RKWorkplaceViewPane* pane);
+private slots:
+/** handle context menu requests */
+	void showContextMenu (const QPoint &pos);
+/** handle close request from context menu */
+	void contextMenuClosePage ();
+/** handle detach request from context menu */
+	void contextMenuDetachWindow ();
+};
 
 /** This is mostly a QTabWidget with some extras such as updating the caption, a context menu, etc.
  */
 
-class RKWorkplaceView : public QTabWidget {
+class RKWorkplaceView : public QSplitter {
 	Q_OBJECT
+friend class RKWorkplaceViewPane;
 public:
 /** constructor
 @param parent parent QWidget */
@@ -41,14 +71,16 @@ public:
 @param destroyed if the window is already destroyed, set this to true */
 	void removeWindow (RKMDIWindow *widget, bool destroyed=false);
 /** does this window exist in the view? */
-	bool hasWindow (RKMDIWindow *widget);
+	bool hasWindow (RKMDIWindow *widget) const;
+/** show the given page (does not set focus) */
+	void showWindow (RKMDIWindow *widget);
 
 /** @returns the currently active window */
-	RKMDIWindow *activePage ();
+	RKMDIWindow *activePage () const;
 /** reimplemented form QWidget::setCaption () to emit captionChanged () when the caption changes */
 	void setCaption (const QString &caption);
 /** initialize the window left/right actions */
-	void initActions (KActionCollection *ac, const char *id_left, const char *id_right);
+	void initActions (KActionCollection *ac);
 signals:
 /** a new page / window was activated
 @param widget the newly activated window */
@@ -57,14 +89,6 @@ signals:
 @param new_caption the new caption */
 	void captionChanged (const QString &new_caption);
 private slots:
-/** (Attempts to) close the current tab */
-	void closeCurrentPage ();
-/** handle context menu requests */
-	void showContextMenu (const QPoint &pos);
-/** handle close request from context menu */
-	void contextMenuClosePage ();
-/** handle detach request from context menu */
-	void contextMenuDetachWindow ();
 /** Internal function to update caption and actions, when the current page has changed. */
 	void currentPageChanged (int page);
 /** called when the caption of a window changes. Updates the tab-label, and - if appropriate - the caption of this widget */
@@ -73,15 +97,18 @@ private slots:
 	void pageLeft ();
 /** Active the page right of the current tab */
 	void pageRight ();
-/** Close a page given the correspoding widget */
-	void closePage (QWidget* page);
-/** Close a page given its index */
-	void closePage (int page);
+/** Purge the given pane (if it is empty) */
+	void purgePane (RKWorkplaceViewPane *pane);
 private:
 	void updateActions ();
+	RKWorkplaceViewPane *findWindow (RKMDIWindow *window) const;
+	RKWorkplaceViewPane *newPane (int index);
 
 	QAction *action_page_left;
 	QAction *action_page_right;
+
+	QList<RKWorkplaceViewPane*> panes;
+	RKWorkplaceViewPane *activePane () const;
 };
 
 #endif



More information about the rkward-tracker mailing list