[rkward-cvs] SF.net SVN: rkward:[2874] trunk/rkward/rkward/core

tfry at users.sourceforge.net tfry at users.sourceforge.net
Mon Jun 14 12:28:08 UTC 2010


Revision: 2874
          http://rkward.svn.sourceforge.net/rkward/?rev=2874&view=rev
Author:   tfry
Date:     2010-06-14 12:28:08 +0000 (Mon, 14 Jun 2010)

Log Message:
-----------
Start adding (unfinished, untested) support for editing rownames.
Add rkrownames.cpp rkrownames.h, missing from commit #2871.
Some more cleanups in RKVariable-API.

Modified Paths:
--------------
    trunk/rkward/rkward/core/rkvariable.cpp
    trunk/rkward/rkward/core/rkvariable.h

Added Paths:
-----------
    trunk/rkward/rkward/core/rkrownames.cpp
    trunk/rkward/rkward/core/rkrownames.h

Added: trunk/rkward/rkward/core/rkrownames.cpp
===================================================================
--- trunk/rkward/rkward/core/rkrownames.cpp	                        (rev 0)
+++ trunk/rkward/rkward/core/rkrownames.cpp	2010-06-14 12:28:08 UTC (rev 2874)
@@ -0,0 +1,129 @@
+/***************************************************************************
+                          rkrownames  -  description
+                             -------------------
+    begin                : Tue Mar 21 2010
+    copyright            : (C) 2010 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.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 "rkrownames.h"
+
+#include <limits.h>
+
+#include <klocale.h>
+
+#include "rcontainerobject.h"
+#include "../rkglobals.h"
+#include "../rbackend/rinterface.h"
+#include "rkmodificationtracker.h"
+
+#include "../debug.h"
+
+RKRowNames::RKRowNames (RContainerObject *parent) : RKVariable (parent, QString ()) {
+	RK_TRACE (OBJECTS);
+
+	type = Variable | NonVisibleObject;
+
+	setDataType (RObject::DataCharacter);
+	check_duplicates = true;
+	is_sequential_up_to_row = -1;
+}
+
+RKRowNames::~RKRowNames () {
+	RK_TRACE (OBJECTS);
+}
+
+QString RKRowNames::getFullName () const {
+//	RK_TRACE (OBJECTS);
+
+	return ("row.names (" + parent->getFullName () + ")");
+}
+
+void RKRowNames::writeData (int from_row, int to_row, RCommandChain *chain) {
+	RK_TRACE (OBJECTS);
+
+	if (is_sequential_up_to_row == getLength ()) {
+		RKGlobals::rInterface ()->issueCommand (getFullName () + " <- NULL", RCommand::App | RCommand::Sync, QString::null, 0,0, chain);
+
+		ChangeSet *set = new ChangeSet;
+		set->from_index = from_row;
+		set->to_index = to_row;
+		RKGlobals::tracker ()->objectDataChanged (this, set);
+	} else {
+		RKVariable::writeData (from_row, to_row, chain);
+	}
+}
+
+void RKRowNames::setText (int row, const QString &text) {
+	RK_TRACE (OBJECTS);
+
+	RKVariable::setText (row, QString());	// don't get in the way of duplicate checking!
+	QString real_text = text;
+	if (real_text.isEmpty ()) real_text = i18n ("new.row");		// empty row names are forbidden
+
+	bool is_sequential_number = false;
+	if (is_sequential_up_to_row >= (row - 1)) {
+		bool ok;
+		long num = text.toInt(&ok);
+		if (ok && (QString::number (num) == text)) {
+			is_sequential_number = true;
+			if (makeUnique (&real_text, true)) {
+				is_sequential_up_to_row = row;
+			}
+		}
+	}
+
+	makeUnique (&real_text, false);
+
+	RKVariable::setText (row, real_text);
+}
+
+bool RKRowNames::makeUnique (QString *text, bool non_sequentials_only) {
+	RK_TRACE (OBJECTS);
+
+	bool from_index = 0;
+	if (non_sequentials_only) from_index = is_sequential_up_to_row + 1;
+
+	QString dummy = *text;
+	for (long i = 0; i < INT_MAX; ++i) {
+		// check whether the text is unique on this iteration
+		bool is_unique = true;
+		for (int row = from_index; row <= getLength (); ++i) {
+			if (dummy == data->cell_strings[row]) {
+				is_unique = false;
+				break;
+			}
+		}
+		if (is_unique) {
+			if (i == 0) {
+				return true;	// was unique on first attempt
+			} else {
+				*text = dummy;
+				return false;
+			}
+		}
+
+		// try adjusted text on next iteration
+		QString dummy = *text + '.' + QString::number (i);
+	}
+
+	RK_ASSERT (false);
+	return false;
+}
+
+void RKRowNames::setCharacterFromR (int from_row, int to_row, QString *data) {
+	RK_TRACE (OBJECTS);
+
+	check_duplicates = false;
+	RKVariable::setCharacterFromR (from_row, to_row, data);
+	check_duplicates = true;
+}

Added: trunk/rkward/rkward/core/rkrownames.h
===================================================================
--- trunk/rkward/rkward/core/rkrownames.h	                        (rev 0)
+++ trunk/rkward/rkward/core/rkrownames.h	2010-06-14 12:28:08 UTC (rev 2874)
@@ -0,0 +1,50 @@
+/***************************************************************************
+                          rkrownames  -  description
+                             -------------------
+    begin                : Tue Mar 21 2010
+    copyright            : (C) 2010 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.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 RKROWNAMES_H
+#define RKROWNAMES_H
+
+#include "rkvariable.h"
+
+/** This class represents the row names of a data frame that is open for editing.
+This object is special in that it exists during editing, only. It is not represented in the RObjectList. */
+class RKRowNames : public RKVariable {
+public:
+	RKRowNames (RContainerObject *parent);
+	~RKRowNames ();
+
+	QString getFullName () const;
+/** Reimplemented to return "row.names" */
+	QString getBaseName () const { return QString ("row.names"); };
+/** Reimplemented to do nothing. There is no metadata on the rownames. */
+	void writeMetaData (RCommandChain *) {};
+
+/** Reimplemented to always try to write data as numbers, if possible */
+	void writeData (int from_row, int to_row, RCommandChain *chain=0);
+/** Reimplemented to check, whether the values are all 1:n, custom, or invalid. */
+	void setText (int row, const QString &text);
+protected:
+/** Reimplemented to disable duplicate checks during the setText() calls within */
+	void setCharacterFromR (int from_row, int to_row, QString *data);
+private:
+/** @returns: true if the text was already unique, false, if it had to be adjusted */
+	bool makeUnique (QString *text, bool non_sequentials_only);
+	int is_sequential_up_to_row;
+	bool check_duplicates;
+};
+
+#endif

Modified: trunk/rkward/rkward/core/rkvariable.cpp
===================================================================
--- trunk/rkward/rkward/core/rkvariable.cpp	2010-06-02 16:14:14 UTC (rev 2873)
+++ trunk/rkward/rkward/core/rkvariable.cpp	2010-06-14 12:28:08 UTC (rev 2874)
@@ -155,9 +155,9 @@
 		RK_ASSERT (cdata->getDataLength () == (unsigned int) getLength ()); // not a problem due to the line below, I'd still like to know if / when this happens.
 		extendToLength (cdata->getDataLength ());
 		if (cdata->getDataType () == RData::StringVector) {
-			setCharacter (0, getLength () - 1, cdata->getStringVector ());
+			setCharacterFromR (0, getLength () - 1, cdata->getStringVector ());
 		} else if (cdata->getDataType () == RData::RealVector) {
-			setNumeric (0, getLength () - 1, cdata->getRealVector ());
+			setNumericFromR (0, getLength () - 1, cdata->getRealVector ());
 		} else if (cdata->getDataType () == RData::IntVector) {
 			unsigned int len = getLength ();
 			double *dd = new double[len];
@@ -165,7 +165,7 @@
 				if (cdata->getIntVector ()[i] == INT_MIN) dd[i] = NAN;
 				else dd[i] = (double) cdata->getIntVector ()[i];
 			}
-			setNumeric (0, getLength () - 1, dd);
+			setNumericFromR (0, getLength () - 1, dd);
 			delete [] dd;
 		}
 
@@ -512,7 +512,6 @@
 	}
 }
 
-#warning this could/should be merged with setCharacter (which is currently less complete)
 void RKVariable::setText (int row, const QString &text) {
 	RK_TRACE (OBJECTS);
 	RK_ASSERT (row < getLength ());
@@ -572,21 +571,8 @@
 	return getText (row);
 }
 
-double *RKVariable::getNumeric (int from_row, int to_row) const {
+void RKVariable::setNumericFromR (int from_row, int to_row, double *numdata) {
 	RK_TRACE (OBJECTS);
-	if (to_row >= getLength ()) {
-		RK_ASSERT (false);
-		return 0;
-	}
-	RK_ASSERT (from_row <= to_row);
-
-	// TODO: no, this is not good. Return a _copy_!
-	// we simply return the whole array starting at the given offset for now. Change this, if the storage mechanism gets changed!
-	return &(data->cell_doubles[from_row]);
-}
-
-void RKVariable::setNumeric (int from_row, int to_row, double *numdata) {
-	RK_TRACE (OBJECTS);
 	RK_ASSERT (to_row < getLength ());
 
 	if (getDataType () == DataCharacter) {
@@ -646,7 +632,7 @@
 	return ret;
 }
 
-void RKVariable::setCharacter (int from_row, int to_row, QString *txtdata) {
+void RKVariable::setCharacterFromR (int from_row, int to_row, QString *txtdata) {
 	RK_TRACE (OBJECTS);
 	RK_ASSERT (to_row < getLength ());
 
@@ -662,18 +648,6 @@
 	}
 }
 
-void RKVariable::setUnknown (int from_row, int to_row) {
-	RK_TRACE (OBJECTS);
-	RK_ASSERT (to_row < getLength ());
-
-	if ((from_row < 0)) from_row = 0;
-	if ((to_row < 0)) to_row = data->allocated_length - 1;
-		
-	for (int row=from_row; row <= to_row; ++row) {
-		data->cell_strings[row] = RKVarEditData::Unknown;
-	}
-}
-
 RKVariable::Status RKVariable::cellStatus (int row) const {
 	if (data->cell_states[row] == RKVarEditData::Unknown) return ValueUnknown;
 	if (data->cell_states[row] & RKVarEditData::NA) return ValueUnused;

Modified: trunk/rkward/rkward/core/rkvariable.h
===================================================================
--- trunk/rkward/rkward/core/rkvariable.h	2010-06-02 16:14:14 UTC (rev 2873)
+++ trunk/rkward/rkward/core/rkvariable.h	2010-06-14 12:28:08 UTC (rev 2874)
@@ -66,24 +66,14 @@
 /** get the value at the given row in text-form suitable for submission to R. I.e. strings are quoted, numbers are not, empty values are returned as NA */
 	QString getRText (int row) const;
 /** set the value at the given row in text-form. Will try to convert the given string to the internal storage format if possible. */
-	void setText (int row, const QString &text);
+	virtual void setText (int row, const QString &text);
 
-/** get a copy of the numeric values of rows starting from from_index, going to to_index. Do not use this before making sure that the rStorage () is really
-numeric!  TODO: unused  */
-	double *getNumeric (int from_row, int to_row) const;
-/** set numeric values in the given range. Assumes you provide enough values for the range. If internalStorage is String, all values will be converted to strings, so you should use this function only, if you know you are dealing with a numeric object */
-	void setNumeric (int from_row, int to_row, double *data);
-/** like getNumeric, but returns values as an array of QStrings. TODO: unused */
+/** get a copy of the text values of rows from from_index to to_index. TODO: This could be made, but currently is not, more efficient than calling getText in a loop. */
 	QString *getCharacter (int from_row, int to_row) const;
-/** like setNumeric, but sets chars. If internalStorage () is numeric, attempts to convert the given strings to numbers. I.e. the function behaves essentially like setText (), but operates on a range of cells. */
-	void setCharacter (int from_row, int to_row, QString *data);
 	
 /** returns the current status of the given cell */
 	Status cellStatus (int row) const;
 
-/** sets the status of the given range of cells to Unknown (the entire row if from_row and to_row are -1). Usually you call this, when you are about to update the given data-range, but haven't fetched the data for that, yet. The unknown-flag is cleared for the cells, as soon as data is written to those cells. The effect is that the cells will not be editable until the data was updated. */
-	void setUnknown (int from_row=-1, int to_row=-1);
-
 /** entirely remove the given rows (i.e. the cells). Will also take care of updating the state (are there any invalid cells left?). Does not sync with the backend for technical reasons! You have to remove the row in the backend explicitly. */
 	void removeRows (int from_row, int to_row);
 /** inserts count rows (with empty values) just above the given index. Does not sync with the backend for technical reasons! You have to insert the row in the backend explicitly. */
@@ -137,6 +127,10 @@
 /** inverse of parseFormattingOptionsString () */
 	static QString formattingOptionsToString (const FormattingOptions& options);
 protected:
+/** like setNumeric, but sets chars. If internalStorage () is numeric, attempts to convert the given strings to numbers. I.e. the function behaves essentially like setText (), but operates on a range of cells. Code may assume that all data comes directly from R, is entirely valid in R. */
+	virtual void setCharacterFromR (int from_row, int to_row, QString *data);
+/** set numeric values in the given range. Assumes you provide enough values for the range. If internalStorage is String, all values will be converted to strings, so you should use this function only, if you know you are dealing with a numeric object. Code may assume that all data comes directly from R, is entirely valid in R. */
+	void setNumericFromR (int from_row, int to_row, double *data);
 /** reimplemented from RObject to change the internal data storage mode, if the var is being edited */
 	bool updateType (RData *new_data);
 /** Extended from RObject::EditData to actually contain data. */
@@ -175,7 +169,7 @@
 	void beginEdit ();
 /** reimplemented from RObject */
 	void endEdit ();
-private:
+
 /** changes the allocated storage to contain a least length elements. More data may be allocated than acutally needed. This function only ever does upsizing. */
 	void extendToLength (int length);
 /** changes the allocated storage to contain a least getLength elements. More data may be allocated than acutally needed. This function only ever does downsizing. */


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the rkward-tracker mailing list