[education/rkward] /: Do not crash on data.frames containing list-like columns

Thomas Friedrichsmeier null at kde.org
Wed Jul 10 15:13:18 BST 2024


Git commit 3e99ee5311da38f2470737835490625ec194b4f3 by Thomas Friedrichsmeier.
Committed on 10/07/2024 at 14:13.
Pushed by tfry into branch 'master'.

Do not crash on data.frames containing list-like columns

M  +1    -0    ChangeLog
M  +0    -3    rkward/dataeditor/rkeditordataframe.cpp
M  +15   -6    rkward/dataeditor/rkvareditmodel.cpp
M  +2    -0    rkward/dataeditor/rkvareditmodel.h
M  +8    -3    rkward/dataeditor/twintable.cpp

https://invent.kde.org/education/rkward/-/commit/3e99ee5311da38f2470737835490625ec194b4f3

diff --git a/ChangeLog b/ChangeLog
index c4a84e51e..89ed0d3d3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+- Fixed: Crash when trying to edit a data.frame containing columns that are not vectors
 - Fixed: Basic statistics would refuse to "overwrite file", even if saving to file was unchecked
 - Added: Ability to open PDF documents inside the RKWard window, and associated R function rk.show.pdf()
 - Fixed: Add breeze icons as a fallback on systems that use a different icon theme (fixes missing icons)
diff --git a/rkward/dataeditor/rkeditordataframe.cpp b/rkward/dataeditor/rkeditordataframe.cpp
index c4aae1ed8..d4b2ea741 100644
--- a/rkward/dataeditor/rkeditordataframe.cpp
+++ b/rkward/dataeditor/rkeditordataframe.cpp
@@ -22,9 +22,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "../debug.h"
 
-// warning! numbers above GET_DATA_OFFSET are used to determine, which row, the data should go to!
-#define GET_DATA_OFFSET 10
-
 RKEditorDataFrame::RKEditorDataFrame (RContainerObject* object, QWidget *parent) : TwinTable (parent) {
 	RK_TRACE (EDITOR);
 
diff --git a/rkward/dataeditor/rkvareditmodel.cpp b/rkward/dataeditor/rkvareditmodel.cpp
index 09a27ec14..577fe4e98 100644
--- a/rkward/dataeditor/rkvareditmodel.cpp
+++ b/rkward/dataeditor/rkvareditmodel.cpp
@@ -1,6 +1,6 @@
 /*
 rkvareditmodel - This file is part of RKWard (https://rkward.kde.org). Created: Mon Nov 05 2007
-SPDX-FileCopyrightText: 2007-2014 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
+SPDX-FileCopyrightText: 2007-2024 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
 SPDX-FileContributor: The RKWard Team <rkward-devel at kde.org>
 SPDX-License-Identifier: GPL-2.0-or-later
 */
@@ -278,7 +278,10 @@ QVariant RKVarEditModel::data (const QModelIndex& index, int role) const {
 
 	// a normal cell
 	RKVariable *var = objects[col];
-	RK_ASSERT (var);
+	if (!var) {
+		RK_ASSERT(var);
+		return QVariant();
+	}
 
 	if (role == Qt::EditRole) return var->getText (row, false);
 
@@ -553,7 +556,10 @@ QVariant RKVarEditMetaModel::data (const QModelIndex& index, int role) const {
 
 	if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) {
 		RKVariable *var = data_model->objects[col];
-		RK_ASSERT (var);
+		if (!var) {
+			RK_ASSERT(var);
+			return QVariant();
+		}
 
 		if (row == NameRow) return var->getShortName ();
 		if (row == LabelRow) return var->getLabel ();
@@ -826,9 +832,12 @@ void RKVarEditDataFrameModel::init (RContainerObject* dataframe) {
 
 	for (int i = 0; i < dataframe->numChildren (); ++i) {
 		RObject* obj = dataframe->findChildByIndex (i);
-		RK_ASSERT (obj);
-		RK_ASSERT (obj->isVariable ());
-		addObject (i, static_cast<RKVariable*> (obj));
+		RK_ASSERT(obj);
+		if (obj->isVariable()) {
+			addObject(i, static_cast<RKVariable*>(obj));
+		} else {
+			problem_details.append(i18n("Object '%1' is not a vector", obj->getShortName()));
+		}
 	}
 	rownames = dataframe->rowNames ();
 	addObject (0, rownames);
diff --git a/rkward/dataeditor/rkvareditmodel.h b/rkward/dataeditor/rkvareditmodel.h
index 244a191ad..075ef7e62 100644
--- a/rkward/dataeditor/rkvareditmodel.h
+++ b/rkward/dataeditor/rkvareditmodel.h
@@ -82,6 +82,7 @@ public:
 	void objectDataChanged (RObject* object, const RObject::ChangeSet *changes) override;
 
 	RKVariable* getObject (int index) const;
+	QStringList problems() const { return problem_details; };
 Q_SIGNALS:
 	void modelDepleted ();
 	void hasDuplicates (const QStringList& dupes);
@@ -94,6 +95,7 @@ private:
 protected:
 friend class RKVarEditMetaModel;
 	QList<RKVariable*> objects;
+	QStringList problem_details;
 	RKRowNames *rownames;
 
 	/** very simple convenience function to return the number of true cols + trailing cols */
diff --git a/rkward/dataeditor/twintable.cpp b/rkward/dataeditor/twintable.cpp
index 35db3af8a..e1c1ffe33 100644
--- a/rkward/dataeditor/twintable.cpp
+++ b/rkward/dataeditor/twintable.cpp
@@ -1,6 +1,6 @@
 /*
 twintable.cpp - This file is part of RKWard (https://rkward.kde.org). Created: Tue Oct 29 2002
-SPDX-FileCopyrightText: 2002-2022 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
+SPDX-FileCopyrightText: 2002-2024 by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
 SPDX-FileContributor: The RKWard Team <rkward-devel at kde.org>
 SPDX-License-Identifier: GPL-2.0-or-later
 */
@@ -168,10 +168,11 @@ void TwinTable::initActions () {
 void TwinTable::initTable (RKVarEditModel* model, RObject* object) {
 	RK_TRACE (EDITOR);
 
+	auto problems = model->problems();
 	datamodel = model;
 	main_object = object;
-	action_enable_editing->setEnabled (object->canWrite ());
-	action_tb_unlock_editing->setEnabled (object->canWrite ());
+	action_enable_editing->setEnabled(object->canWrite() && problems.isEmpty());
+	action_tb_unlock_editing->setEnabled(object->canWrite() && problems.isEmpty());
 	dataview->setRKModel (model);
 	metaview->setRKModel (model->getMetaModel ());
 	model->setEditor (this);
@@ -188,6 +189,10 @@ void TwinTable::initTable (RKVarEditModel* model, RObject* object) {
 	listenForObject (object);
 	objectMetaChanged (object);
 	connect (model, &RKVarEditModel::hasDuplicates, this, &TwinTable::containsDuplicates);
+
+	if (!problems.isEmpty()) {
+		KMessageBox::detailedError(this, i18n("The object's internal structure does not confrom to a regular <tt>data.frame</tt>. Editing has been disabled, and some columns may not be shown. It may be possible to convert this object to a regular <tt>data.frame</tt> using <tt>as.data.frame()</tt>."), problems.join("\n"), i18n("Problem detected"));
+	}
 }
 
 void TwinTable::setWindowStyleHint (const QString& hint) {


More information about the rkward-tracker mailing list