[education/rkward/devel/workspace_output] rkward: WIP: Start working on a sane save dialog for everything that may need saving on exit (or project switch)

Thomas Friedrichsmeier null at kde.org
Sat Oct 10 09:18:45 BST 2020


Git commit a385a01753771c6aff8085ca0972f17e466569b2 by Thomas Friedrichsmeier.
Committed on 29/11/2017 at 11:55.
Pushed by tfry into branch 'devel/workspace_output'.

WIP: Start working on a sane save dialog for everything that may need saving on exit (or project switch)

M  +1    -0    rkward/dialogs/CMakeLists.txt
A  +114  -0    rkward/dialogs/rksavemodifieddialog.cpp     [License: GPL (v2+)]
A  +45   -0    rkward/dialogs/rksavemodifieddialog.h     [License: GPL (v2+)]
M  +11   -5    rkward/windows/rkworkplace.cpp
M  +6    -4    rkward/windows/rkworkplace.h

https://invent.kde.org/education/rkward/commit/a385a01753771c6aff8085ca0972f17e466569b2

diff --git a/rkward/dialogs/CMakeLists.txt b/rkward/dialogs/CMakeLists.txt
index 08a8b21d..da6936cc 100644
--- a/rkward/dialogs/CMakeLists.txt
+++ b/rkward/dialogs/CMakeLists.txt
@@ -8,6 +8,7 @@ SET(dialogs_STAT_SRCS
    rkselectlistdialog.cpp
    rkrecoverdialog.cpp
    rkerrordialog.cpp
+   rksavemodifieddialog.cpp
    )
 
 ADD_LIBRARY(dialogs STATIC ${dialogs_STAT_SRCS})
diff --git a/rkward/dialogs/rksavemodifieddialog.cpp b/rkward/dialogs/rksavemodifieddialog.cpp
new file mode 100644
index 00000000..3e0fc845
--- /dev/null
+++ b/rkward/dialogs/rksavemodifieddialog.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+                          rksavemodifieddialog  -  description
+                             -------------------
+    begin                : Wed Jul 12 2017
+    copyright            : (C) 2017 by Thomas Friedrichsmeier
+    email                : thomas.friedrichsmeier at kdemail.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/ 
+
+#include "rksavemodifieddialog.h"
+
+#include <QTreeWidget>
+#include <QDialogButtonBox>
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QHeaderView>
+#include <QLabel>
+#include <QPointer>
+
+#include <klocale.h>
+
+#include "../debug.h"
+
+bool RKSaveModifiedDialog::askSaveModified (QWidget* parent, QList <RKMDIWindow*> windows, bool project) {
+	RK_TRACE (APP);
+
+	QList<RKMDIWindow*> modified_wins;
+	for (int i = 0; i < windows.size (); ++i) {
+		if (windows[i]->isModified ()) {
+			modified_wins.append (windows[i]);
+		}
+	}
+
+	if (project || !modified_wins.isEmpty ()) {
+		RKSaveModifiedDialog dialog (parent, modified_wins, project);
+		dialog.exec ();
+		if (dialog.result () == QDialog::Rejected) return false;
+	}
+
+	return true;
+}
+
+RKSaveModifiedDialog::RKSaveModifiedDialog (QWidget* parent, QList<RKMDIWindow*> modified_wins, bool project) : QDialog (parent) {
+	RK_TRACE (APP);
+
+	setWindowTitle (i18n ("Save modified"));
+
+	QVBoxLayout* v_layout = new QVBoxLayout (this);
+	QLabel *label = new QLabel (i18n ("The following items have been modified. Do you want to save them before closing?"));
+	v_layout->addWidget (label);
+
+	QTreeWidget *tree = new QTreeWidget ();
+	v_layout->addWidget (tree);
+
+	tree->header ()->hide ();
+	if (project) {
+	}
+	if (!modified_wins.isEmpty ()) {
+		QTreeWidgetItem* header = new QTreeWidgetItem (QStringList (i18n ("Scripts")));
+		header->setFirstColumnSpanned (true);
+		header->setFlags (Qt::ItemIsEnabled);
+		QFont f = tree->font ();
+		f.setBold (true);
+		header->setFont (0, f);
+		tree->addTopLevelItem (header);
+		header->setExpanded (true);
+		for (int i = 0; i < modified_wins.size (); ++i) {
+			QTreeWidgetItem *item = new QTreeWidgetItem (QStringList (modified_wins[i]->fullCaption ()));
+			item->setFirstColumnSpanned (true);
+			header->addChild (item);
+			item->setCheckState (0, Qt::Checked);
+			item->setData (0, Qt::UserRole, QVariant::fromValue (QPointer<RKMDIWindow> (modified_wins[i])));
+		}
+	}
+
+	QDialogButtonBox *buttonbox = new QDialogButtonBox (this);
+	v_layout->addWidget (buttonbox);
+
+	buttonbox->setStandardButtons (QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel);
+	buttonbox->button (QDialogButtonBox::Save)->setDefault (true);
+	buttonbox->button (QDialogButtonBox::Save)->setText (i18nc ("Save the selected items", "Save selected"));
+	buttonbox->button (QDialogButtonBox::Discard)->setText (i18n ("Discard all"));
+	buttonbox->button (QDialogButtonBox::Cancel)->setText (i18n ("Do not close"));
+
+	connect (buttonbox->button (QDialogButtonBox::Save), &QPushButton::clicked, this, &RKSaveModifiedDialog::saveSelected);
+	connect (buttonbox->button (QDialogButtonBox::Discard), &QPushButton::clicked, this, &QDialog::accept);
+	connect (buttonbox->button (QDialogButtonBox::Cancel), &QPushButton::clicked, this, &QDialog::reject);
+
+	setModal (true);
+}
+
+RKSaveModifiedDialog::~RKSaveModifiedDialog () {
+	RK_TRACE (APP);
+}
+
+void RKSaveModifiedDialog::saveWorkplaceChanged () {
+	RK_TRACE (APP);
+// TODO: enable / disable "save with workplace" option for Output windows
+}
+
+void RKSaveModifiedDialog::saveSelected () {
+	RK_TRACE (APP);
+// TODO: get list of selected items from tree, and save them
+// TODO: _when done_:
+//	accepted ();
+}
diff --git a/rkward/dialogs/rksavemodifieddialog.h b/rkward/dialogs/rksavemodifieddialog.h
new file mode 100644
index 00000000..9a711bf9
--- /dev/null
+++ b/rkward/dialogs/rksavemodifieddialog.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+                          rksavemodifieddialog  -  description
+                             -------------------
+    begin                : Wed Jul 12 2017
+    copyright            : (C) 2017 by Thomas Friedrichsmeier
+    email                : thomas.friedrichsmeier at kdemail.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/ 
+
+#ifndef RKSAVEMODIFIEDDIALOG_H
+#define RKSAVEMODIFIEDDIALOG_H
+
+#include <QDialog>
+#include <QList>
+
+#include "../windows/rkmdiwindow.h"
+
+class QTreeWidget;
+
+class RKSaveModifiedDialog : public QDialog {
+	Q_OBJECT
+public:
+/** Provide a combined dialog to ask for saving and modified documents among the given list of windows. Call before closing the app, merging workspaces, etc.
+ *  @param windows List of windows to ask about
+ *  @param project Whether to also ask about saving project related resources: Outputs, Workplace, Workspace.
+ *  @returns true, if the user chose to proceed (with or without saving modications), _and_ saving was successful; false, if the user cancelled the operation, or some saves failed. */
+	static bool askSaveModified (QWidget* parent, QList<RKMDIWindow*> windows, bool project);
+private:
+	RKSaveModifiedDialog (QWidget* parent, QList<RKMDIWindow*> modified_windows, bool project);
+	virtual ~RKSaveModifiedDialog ();
+	QTreeWidget *tree;
+private slots:
+	void saveWorkplaceChanged ();
+	void saveSelected ();
+};
+
+#endif
diff --git a/rkward/windows/rkworkplace.cpp b/rkward/windows/rkworkplace.cpp
index 45ee406c..f33be251 100644
--- a/rkward/windows/rkworkplace.cpp
+++ b/rkward/windows/rkworkplace.cpp
@@ -43,6 +43,7 @@
 #include "../core/robjectlist.h"
 #include "../dataeditor/rkeditor.h"
 #include "../dataeditor/rkeditordataframe.h"
+#include "../dialogs/rksavemodifieddialog.h"
 #include "../robjectviewer.h"
 #include "../settings/rksettingsmodulegeneral.h"
 #include "../settings/rksettingsmodulecommandeditor.h"
@@ -639,20 +640,25 @@ RKWorkplace::RKWorkplaceObjectList RKWorkplace::getObjectList (int type, int sta
 	return ret;
 }
 
-void RKWorkplace::closeAll (int type, int state) {
+bool RKWorkplace::closeAll (int type, int state) {
 	RK_TRACE (APP);
 
-	closeWindows (getObjectList (type, state));
+	return closeWindows (windows);
 }
 
-void RKWorkplace::closeWindows (QList<RKMDIWindow*> windows) {
+bool RKWorkplace::closeWindows (QList<RKMDIWindow*> windows) {
 	RK_TRACE (APP);
 
 	RKWardMainWindow::getMain ()->lockGUIRebuild (true);
-	for (int i = windows.size () - 1; i >= 0; --i) {
-		closeWindow (windows[i]);
+	bool ok = RKSaveModifiedDialog::askSaveModified (this, windows, false);
+	if (ok) {
+		for (int i = windows.size () - 1; i >= 0; --i) {
+			closeWindow (windows[i]);
+			// TODO: Do not ask for saving _again_
+		}
 	}
 	RKWardMainWindow::getMain ()->lockGUIRebuild (false);
+	return ok;
 }
 
 void RKWorkplace::removeWindow (QObject *object) {
diff --git a/rkward/windows/rkworkplace.h b/rkward/windows/rkworkplace.h
index 73a7e4e5..f43673ab 100644
--- a/rkward/windows/rkworkplace.h
+++ b/rkward/windows/rkworkplace.h
@@ -139,12 +139,14 @@ public:
 @param window window to close */
 	void closeWindow (RKMDIWindow *window);
 /** Close the given windows, whether they are attached or detached. TODO: Be smart about asking what to save.
- at param windows list windows to close */
-	void closeWindows (QList<RKMDIWindow*> windows);
+ at param windows list windows to close
+ at returns false if cancelled by user (user was prompted for saving, and chose cancel) */
+	bool closeWindows (QList<RKMDIWindow*> windows);
 /** Closes all windows of the given type(s). Default call (no arguments) closes all windows
 @param type: A bitwise OR of RKWorkplaceObjectType
- at param state: A bitwise OR of RKWorkplaceObjectState */
-	void closeAll (int type=RKMDIWindow::AnyType, int state=RKMDIWindow::AnyWindowState);
+ at param state: A bitwise OR of RKWorkplaceObjectState
+ at returns false if cancelled by user (user was prompted for saving, and chose cancel) */
+	bool closeAll (int type=RKMDIWindow::AnyType, int state=RKMDIWindow::AnyWindowState);
 
 /** Write a description of all current windows to the R backend. This can later be read by restoreWorkplace (). Has no effect, if RKSettingsModuleGeneral::workplaceSaveMode () != RKSettingsModuleGeneral::SaveWorkplaceWithWorkspace
 @param chain command chain to place the command in */




More information about the rkward-tracker mailing list