[rkward/work/split_views] /: Restoring split views works in principle (with heavy issues, including geometry and orientation)

Thomas Friedrichsmeier null at kde.org
Tue Jun 20 21:51:56 UTC 2017


Git commit 01464f05e7039c3299d89b62448bec832d5040d7 by Thomas Friedrichsmeier.
Committed on 20/06/2017 at 21:51.
Pushed by tfry into branch 'work/split_views'.

Restoring split views works in principle (with heavy issues, including geometry and orientation)

M  +2    -0    ChangeLog
M  +7    -17   rkward/windows/rkworkplace.cpp
M  +104  -20   rkward/windows/rkworkplaceview.cpp
M  +11   -4    rkward/windows/rkworkplaceview.h

https://commits.kde.org/rkward/01464f05e7039c3299d89b62448bec832d5040d7

diff --git a/ChangeLog b/ChangeLog
index e2900b48..1cdb1835 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+TODO: Workplace save as does not as for overwrite confirmation
+
 - Fixed: Creating trellis on-screen plots, while package lattice is not on the search path would produce errors in plot history mechanism
 - Limit the number of debug log-files to keep (at most three, each, for frontend and backend)
 - Remove Windows-only UI for setInternet2()-option (no longer available in R, with setInternet2(TRUE) the default since R 3.2.2)
diff --git a/rkward/windows/rkworkplace.cpp b/rkward/windows/rkworkplace.cpp
index ec46de60..59092da4 100644
--- a/rkward/windows/rkworkplace.cpp
+++ b/rkward/windows/rkworkplace.cpp
@@ -874,16 +874,8 @@ QStringList RKWorkplace::makeWorkplaceDescription () {
 		if (!desc.isEmpty ()) workplace_description.append (desc);
 	}
 
-	QVariantList attached_list = wview->listContents ();
-	for (int i=0; i < attached_list.count (); ++i) {
-		if (attached_list[i].canConvert<QObject*>()) {
-			RKMDIWindow *win = static_cast<RKMDIWindow*> (attached_list[i].value<QObject*>());
-			QString desc = makeItemDescription (win);
-			if (!desc.isEmpty ()) workplace_description.append (desc);
-		} else {
-			workplace_description.append (attached_list[i].toString ());
-		}
-	}
+	workplace_description.append (QStringLiteral ("layout::::") + wview->listLayout ());
+	workplace_description.append (wview->listContents ());
 
 	list = getObjectList (RKMDIWindow::ToolWindow, RKMDIWindow::AnyWindowState);
 	foreach (RKMDIWindow *win, list) {
@@ -917,11 +909,6 @@ void RKWorkplace::restoreWorkplace (const QStringList &description) {
 	RKWardMainWindow::getMain ()->lockGUIRebuild (true);
 	QString base;
 	for (int i = 0; i < description.size (); ++i) {
-/*		if (split_next) {
-			split_next = false;
-			view ()->restoreSplitView (split_orientation, description[i], base);
-		} */
-
 		ItemSpecification spec = parseItemDescription (description[i]);
 		RKMDIWindow *win = 0;
 		if (spec.type == "base") {
@@ -929,8 +916,10 @@ void RKWorkplace::restoreWorkplace (const QStringList &description) {
 			base = spec.specification;
 		} else if (restoreDocumentWindowInternal (this, spec, base)) {
 			// it was restored. nothing else to do
-		} else if (spec.type == "split") {
-#warning implement
+		} else if (spec.type == "layout") {
+			view ()->restoreLayout (spec.specification);
+		} else if (spec.type == "pane_end") {
+			view ()->nextPane ();
 		} else {
 			win = RKToolWindowList::findToolWindowById (spec.type);
 			RK_ASSERT (win);
@@ -952,6 +941,7 @@ void RKWorkplace::restoreWorkplace (const QStringList &description) {
 			}
 		}
 	}
+	view ()->purgeEmptyPanes ();
 	RKWardMainWindow::getMain ()->lockGUIRebuild (false);
 }
 
diff --git a/rkward/windows/rkworkplaceview.cpp b/rkward/windows/rkworkplaceview.cpp
index afcd6942..0ac5218b 100644
--- a/rkward/windows/rkworkplaceview.cpp
+++ b/rkward/windows/rkworkplaceview.cpp
@@ -178,7 +178,7 @@ void RKWorkplaceViewPane::contextMenuDetachWindow () {
 	RKWorkplace::mainWorkplace ()->detachWindow (static_cast<RKMDIWindow*> (widget (tab)));
 }
 
-void RKWorkplaceViewPane::currentPageChanged (int page) {
+void RKWorkplaceViewPane::currentPageChanged (int) {
 	RK_TRACE (APP);
 
 	RKMDIWindow *w = static_cast<RKMDIWindow*> (currentWidget ());
@@ -192,6 +192,14 @@ void RKWorkplaceViewPane::currentPageChanged (int page) {
 }
 
 
+// Create new splitter with default setup
+QSplitter *createSplitter (Qt::Orientation orientation) {
+	RK_TRACE (APP);
+
+	QSplitter* ret = new QSplitter (orientation);
+	ret->setChildrenCollapsible (false);
+	return ret;
+}
 
 RKWorkplaceViewPane* RKWorkplaceView::createPane () {
 	RK_TRACE (APP);
@@ -314,19 +322,19 @@ void RKWorkplaceView::pageRight () {
 
 void RKWorkplaceView::splitViewHoriz () {
 	RK_TRACE (APP);
-	splitView (Qt::Vertical, activePane ());
+	splitView (Qt::Vertical);
 }
 
 void RKWorkplaceView::splitViewVert () {
 	RK_TRACE (APP);
-	splitView (Qt::Horizontal, activePane ());
+	splitView (Qt::Horizontal);
 }
 
 // NOTE: Some of this function taken from kate's kateviewmanager.cpp
-RKWorkplaceViewPane* RKWorkplaceView::splitView (Qt::Orientation orientation, RKWorkplaceViewPane *pane, const QString &description, const QString &base) {
+void RKWorkplaceView::splitView (Qt::Orientation orientation, const QString &description, const QString &base) {
 	RK_TRACE (APP);
 
-	if (!pane) pane = activePane ();
+	RKWorkplaceViewPane* pane = activePane ();
 
 	QString _description = description;
 	if (_description.isEmpty ()) {
@@ -343,7 +351,7 @@ RKWorkplaceViewPane* RKWorkplaceView::splitView (Qt::Orientation orientation, RK
 	QSplitter *splitter = qobject_cast<QSplitter *> (pane->parentWidget ());
     if (!splitter) {
 		RK_ASSERT (splitter);
-		return 0;
+		return;
 	}
 
 	setUpdatesEnabled (false);
@@ -371,8 +379,7 @@ RKWorkplaceViewPane* RKWorkplaceView::splitView (Qt::Orientation orientation, RK
 
 		splitter->insertWidget (index + 1, newpane);
 	} else {
-		QSplitter *newsplitter = new QSplitter (orientation);
-		newsplitter->setChildrenCollapsible (false);
+		QSplitter *newsplitter = createSplitter (orientation);
 		newsplitter->addWidget (pane);
 		newsplitter->addWidget (newpane);
 		splitter->insertWidget (index, newsplitter);
@@ -386,13 +393,10 @@ RKWorkplaceViewPane* RKWorkplaceView::splitView (Qt::Orientation orientation, RK
 	if (!RKWorkplace::mainWorkplace ()->restoreDocumentWindow (_description, base)) {
 		RKWorkplace::mainWorkplace ()->openHelpWindow (QUrl ("rkward://page/rkward_split_views"));
 	}
-	RKWorkplaceViewPane *ret = newpane;
 	newpane = 0;
 
 	splitter->setSizes (sizes);
 	setUpdatesEnabled (true);
-
-	return ret;
 }
 
 void RKWorkplaceView::addWindow (RKMDIWindow *widget) {
@@ -495,7 +499,86 @@ void RKWorkplaceView::setCaption (const QString &caption) {
 	emit (captionChanged (caption));
 }
 
-void listContents (const QSplitter *parent, QVariantList *ret) {
+void RKWorkplaceView::restoreLayout(const QString& desc) {
+	RK_TRACE (APP);
+
+	QList<QSplitter*> parents;
+	parents.append (this);
+	QStringList dl = desc.split ('-');
+	if (dl.value (0) == QStringLiteral ("col")) setOrientation (Qt::Vertical);
+	else setOrientation (Qt::Horizontal);
+
+	for (int i = 1; i < dl.size () - 1; ++i) {
+		if (dl[i] == QStringLiteral ("p")) {
+			RKWorkplaceViewPane *pane = createPane ();
+			panes.append (pane);
+			parents.last ()->insertWidget (-1, pane);
+		} else if (dl[i] == QStringLiteral ("row")) {
+			QSplitter* newsplit = createSplitter (Qt::Horizontal);
+			parents.last ()->insertWidget (-1, newsplit);
+			parents.append (newsplit);
+		} else if (dl[i] == QStringLiteral ("col")) {
+			QSplitter* newsplit = createSplitter (Qt::Vertical);
+			parents.last ()->insertWidget (-1, newsplit);
+			parents.append (newsplit);
+		} else {
+			RK_ASSERT (dl[i] == QStringLiteral ("end"));
+			if (parents.isEmpty ()) {
+				RK_ASSERT (!parents.isEmpty ());
+			} else {
+				parents.pop_back ();
+			}
+		}
+		if (parents.isEmpty ()) {
+			RK_DEBUG (APP, DL_ERROR, "Bad specification while restoring workplace view layout");
+		}
+	}
+
+	newpane = panes.value (0);
+}
+
+void RKWorkplaceView::nextPane () {
+	RK_TRACE (APP);
+
+	RKWorkplaceViewPane *pane = activePane ();
+	int index = panes.indexOf (pane);
+	newpane = panes.value (index + 1);
+
+	RK_DEBUG (APP, DL_DEBUG, "Activating pane %p after pane %p (index %d / %d)", newpane, pane, index + 1, index);
+}
+
+void RKWorkplaceView::purgeEmptyPanes () {
+	RK_TRACE (APP);
+
+	newpane = 0; // just in case of broken specifications during workplace restoration
+	for (int i = 0; i < panes.count (); ++i) {
+		if (panes[i]->count () < 1) {
+			purgePane (panes[i]);
+			--i;
+		}
+	}
+}
+
+QString listLayout (const QSplitter *parent) {
+	RK_TRACE (APP);
+
+	QString ret = (parent->orientation () == Qt::Horizontal ? QStringLiteral ("row") : QStringLiteral ("col"));
+
+	for (int i = 0; i < parent->count (); ++i) {
+		QWidget* w = parent->widget (i);
+		RKWorkplaceViewPane *pane = qobject_cast<RKWorkplaceViewPane*> (w);
+		if (pane) {
+			ret.append (QStringLiteral ("-p"));
+		} else {
+			QSplitter* sub = qobject_cast<QSplitter*> (w);
+			ret.append ('-' + listLayout (sub));
+		}
+	}
+
+	return ret + QStringLiteral ("-end");
+}
+
+void listContents (const QSplitter *parent, QStringList *ret) {
 	RK_TRACE (APP);
 
 	for (int i = 0; i < parent->count (); ++i) {
@@ -503,24 +586,25 @@ void listContents (const QSplitter *parent, QVariantList *ret) {
 		RKWorkplaceViewPane *pane = qobject_cast<RKWorkplaceViewPane*> (w);
 		if (pane) {
 			for (int j = 0; j < pane->count (); ++j) {
-				ret->append (QVariant::fromValue<QObject*> (pane->widget (j)));
+				QString desc = RKWorkplace::mainWorkplace ()->makeItemDescription (static_cast<RKMDIWindow*> (pane->widget (j)));
+				if (!desc.isEmpty ()) ret->append (desc);
 			}
+			ret->append (QStringLiteral ("pane_end::::"));
 		} else {
 			QSplitter* sub = qobject_cast<QSplitter*> (w);
 			listContents (sub, ret);
 		}
-		if (i < parent->count () - 1) {
-			if (parent->orientation () == Qt::Vertical) ret->append (QStringLiteral ("split::::vert"));
-			else ret->append (QStringLiteral ("split::::horiz"));
-		}
 	}
-	ret->append (QStringLiteral ("split::::end"));
 }
 
-QVariantList RKWorkplaceView::listContents () const {
+QString RKWorkplaceView::listLayout () const {
+	return (::listLayout (this));
+}
+
+QStringList RKWorkplaceView::listContents () const {
 	RK_TRACE (APP);
 
-	QVariantList ret;
+	QStringList ret;
 	::listContents (this, &ret);
 	return ret;
 }
diff --git a/rkward/windows/rkworkplaceview.h b/rkward/windows/rkworkplaceview.h
index 12be7455..0345d1e9 100644
--- a/rkward/windows/rkworkplaceview.h
+++ b/rkward/windows/rkworkplaceview.h
@@ -89,10 +89,16 @@ public:
 /** initialize the window left/right actions */
 	void initActions (KActionCollection *ac);
 
-/** List the contents of the view, recursively. Windows are returned as pointers in the list, Splits are returned as strings "split::::horiz", "split::::vert", or "split::::end" (for end of current splitter) */
-	QVariantList listContents () const;
-/** Public for use by RKWorkplace while restoring a workplace, only. @return the newly created pane */
-	RKWorkplaceViewPane* splitView (Qt::Orientation orientation, RKWorkplaceViewPane *pane, const QString &description=QString (), const QString &base=QString ());
+/** List the contents of the view, recursively. @see RKWorkplace::makeItemDescription() */
+	QStringList listContents () const;
+/** List the layout of the view, recursively. @see RKWorkplace::makeItemDescription() */
+	QString listLayout () const;
+/** For use during workplace restoration, only: Make the next pane the active one, so it can be filled with content. @see restoreLayout */
+	void nextPane ();
+/** For use during workplace restoration, only: Set up splitters and panes according to the given description (generated by listContents()) */
+	void restoreLayout (const QString& desc);
+/** For use right after workplace restoration: Purge any panes set up by restoreLayout(), but left empty */
+	void purgeEmptyPanes ();
 signals:
 /** a new page / window was activated
 @param widget the newly activated window */
@@ -117,6 +123,7 @@ private:
 	void updateActions ();
 	RKWorkplaceViewPane *createPane ();
 	RKWorkplaceViewPane *findWindow (RKMDIWindow *window) const;
+	void splitView (Qt::Orientation orientation, const QString &description=QString (), const QString &base=QString ());
 
 	QAction *action_page_left;
 	QAction *action_page_right;



More information about the rkward-tracker mailing list