|
From: <dhu...@us...> - 2007-02-09 20:26:38
|
Revision: 300
http://svn.sourceforge.net/qcell/?rev=300&view=rev
Author: dhubleizh
Date: 2007-02-09 12:26:35 -0800 (Fri, 09 Feb 2007)
Log Message:
-----------
- exporting works
- no data checks - if it isn't a LIF function, things could happen...
- menu Export option and so on...
Modified Paths:
--------------
trunk/qcell/parsers/Life-1.05/Life105ParserPlugin.cpp
trunk/qcell/parsers/Life-1.05/Life105ParserPlugin.h
trunk/qcell/visgui/MainWindow.cpp
trunk/qcell/visgui/MainWindow.h
trunk/qcell/visgui/MainWindow.ui
Modified: trunk/qcell/parsers/Life-1.05/Life105ParserPlugin.cpp
===================================================================
--- trunk/qcell/parsers/Life-1.05/Life105ParserPlugin.cpp 2007-02-09 13:16:59 UTC (rev 299)
+++ trunk/qcell/parsers/Life-1.05/Life105ParserPlugin.cpp 2007-02-09 20:26:35 UTC (rev 300)
@@ -13,10 +13,10 @@
<< "Neighbourhood"
<< "LocalFunction"
<< "World";
- supported_file_types << "LIF";
+ supported_file_types << "LIF"
+ << "LIFE";
}
-/// @todo Incorporate genreal Function file to output resulting XML
QString Life105ParserPlugin::realParser(const QByteArray content, const QString type, const QString subtype)
{
QStringList lines;
@@ -28,8 +28,8 @@
LocalFunction lf;
// Keep track of header
bool header = true;
- CalculationData cd;
- QHash<QPoint, Universe> objects;
+ CalculationData *cd;
+ int version = -1;
// Set up MCells Neighbourhood (Conways)
Neighbourhood N;
@@ -69,25 +69,31 @@
}
// Function type
- format = QRegExp("^#Life1\\.05$");
+ format = QRegExp("^#Life 1\\.05$");
+ QRegExp format2("^#Life 1\\.06$");
lines[0] = lines[0].trimmed();
if(format.exactMatch(lines[0]))
{
- lines.removeFirst();
- line_nr++;
+ version = 105;
}
+ else if (format2.exactMatch(lines[0]))
+ {
+ version = 106;
+ }
else {
qDebug(tr("Wrong file specification in header line %1. Should be %2, but is %3.")
.arg(line_nr)
- .arg("#Life1.05")
+ .arg("#Life 1.05")
.arg(lines[0])
.toAscii()
);
return QString();
}
+ lines.removeFirst();
+ line_nr++;
// Dealing with the header
- QRegExp comment("^#D.*$");
+ QRegExp comment("^#(D|C|O).*$");
QRegExp conway("^#N$");
QRegExp rule("^#R [1-8]{1,8}/[1-8]{1,8}");
while (header)
@@ -169,18 +175,178 @@
return QString();
}
lines[0] = lines[0].trimmed();
- format = QRegExp("^(\\.|\\*)*$");
+ switch (version)
+ {
+ case 105:
+ {
+ cd = parseIn105(&lines, line_nr);
+ break;
+ }
+ case 106:
+ {
+ cd = parseIn106(&lines, line_nr);
+ break;
+ }
+ }
+ // If error occurred while parsing, cd could be null
+ if (cd == NULL)
+ {
+ return QString();
+ }
+
+ if (type == "Neighbourhood")
+ {
+// qDebug(N.toXmlString().toAscii());
+ delete cd;
+ return N.toXmlString();
+ }
+ else if (type == "LocalFunction")
+ {
+// qDebug(lf.toXmlString().toAscii());
+ delete cd;
+ return lf.toXmlString();
+ }
+ else if (type == "World")
+ {
+// qDebug(cd->toXmlString().toAscii());
+ QString ret = cd->toXmlString();
+ delete cd;
+ return ret;
+ }
+}
+
+/// @todo Check N LF and CD if they really are apropriate to save them in LIF
+QByteArray Life105ParserPlugin::parseOut(QString content, const QString type, const QString subtype)
+{
+ // The resulting array to write to file by the backend
+ QByteArray result;
+
+ if (type == "Neighbourhood")
+ {
+ Neighbourhood N;
+ N.fromXmlString(&content);
+ // Check if we can use the generic type from the XML string
+ if(!N.fromXmlString(&content))
+ {
+ qDebug(tr("Unable to parse out LocalFunction data!").toAscii());
+ return QByteArray();
+ }
+
+ // Header
+ result.append("#Life 1.05\n");
+ result.append("#D Generated by QCell\n");
+ result.append("#D http://www.qcell.sourceforge.net");
+ result.append("#O Cezary Krzy\xBFanowsky & Leszek Smentek 2007");
+ }
+ else if (type == "LocalFunction")
+ {
+ LocalFunction lf;
+ // Check if we can use the generic type from the XML string
+ if(!lf.fromXmlString(&content))
+ {
+ qDebug(tr("Unable to parse out Neighbourhood data!").toAscii());
+ return QByteArray();
+ }
+
+ // Parse out LocalFunction
+ QList<int> survive_sums, born_sums;
+ for (int i = 0; i < 8; i++)
+ {
+ // When cell is 0
+ if (lf.getValueAt(i * 2) == 1)
+ {
+ survive_sums.append(i);
+ }
+ // When cell i 1
+ if (lf.getValueAt(i * 2 + 1))
+ {
+ born_sums.append(i);
+ }
+ }
+
+ result.append("#R ");
+ // Write down survive values
+ for (int i = 0; i < survive_sums.size(); i++)
+ {
+ result.append(QString::number(survive_sums[i]).toAscii());
+ }
+ // Separator
+ result.append('/');
+ // Write down born values
+ for (int i = 0; i < born_sums.size(); i++)
+ {
+ result.append(QString::number(born_sums[i]).toAscii());
+ }
+ // Finally the line ends
+ result.append('\n');
+ }
+ else if (type == "World")
+ {
+ CalculationData cd;
+ // Check if we can use the generic type from the XML string
+ if (!cd.setFromXmlString(&content))
+ {
+ qDebug(tr("Unable to parse out Neighbourhood data!").toAscii());
+ return QByteArray();
+ }
+ // #P to place the object in the middle
+ result.append(QString("#P %1 %2\n")
+ .arg(-(cd.getSizeX() / 2 + 1))
+ .arg(-(cd.getSizeY() / 2 + 1))
+ .toAscii()
+ );
+
+ // Finally the universe writing
+ for (int y = 0; y < cd.getSizeY(); y++)
+ {
+ for (int x = 0; x < cd.getSizeX(); x++)
+ {
+ if (cd.getValueAt_i(x, y) == 0)
+ {
+ result.append('.');
+ }
+ else
+ {
+ result.append('*');
+ }
+ }
+
+ // Break for each line
+ result.append('\n');
+ }
+ }
+
+ return result;
+}
+
+CalculationData* Life105ParserPlugin::parseIn105(QStringList *lines, int line_nr)
+{
+ // The return object
+ CalculationData* cd = new CalculationData;
+ // Parsed objects holder
+ QHash<QPoint, Universe> objects;
+
+ // Content line fotmat
+ QRegExp format = QRegExp("^(\\.|\\*)*$");
+ // Coordinates line
QRegExp coords("^#P (-)?(\\d)* (-)?(\\d)*$");
+ // Empty line
QRegExp line_separator("^\\.$");
+ // Needed for universe size determination
int min_x, max_x, min_y, max_y;
min_x = max_x = min_y = max_y = 0;
+ // Holds the #P's line value
QPoint tmp_point(0, 0);
+ // The object being read
Universe tmp_object;
- foreach(QString line, lines)
+ foreach(QString line, *lines)
{
if(format.exactMatch(line))
{
+ // Append new line to output for each input line
tmp_object.append(QVector<bool>(line.size(), 0));
+ // Parse the line in search of 1-s, as the resulting
+ // table is filled with 0-s by default
for (int i = 0; i < line.size(); i++)
{
if (line[i] == '*')
@@ -189,6 +355,7 @@
}
}
+ // Check max exceeding
if ((tmp_point.x() + line.size()) > max_x)
{
max_x = tmp_point.x() + line.size();
@@ -227,6 +394,7 @@
}
else if (line_separator.exactMatch(line))
{
+ // Empty line while separator
tmp_object.append(QVector<bool>());
}
else if (!line.isEmpty())
@@ -236,7 +404,7 @@
.toAscii()
);
- return QString();
+ return NULL;
}
// To keep count of current line nr
@@ -266,7 +434,7 @@
qDebug(tr("This file doesn't contain any object.")
.toAscii()
);
- return QString();
+ return NULL;
}
//// Prepare the actual structures in QCell
@@ -281,10 +449,10 @@
{
size_y++;
}
- cd.resizeData(size_x, size_y);
- QPoint center(cd.getSizeX()/2, cd.getSizeY()/2);
+ cd->resizeData(size_x, size_y);
+ QPoint center(cd->getSizeX()/2, cd->getSizeY()/2);
// Fill the whole universe with 0-s
- cd.fillData(0);
+ cd->fillData(0);
// Actual object placement in the universe
QHash<QPoint, Universe>::const_iterator i = objects.begin();
@@ -294,7 +462,7 @@
{
for (int dx = 0; dx < i.value()[dy].size(); dx++)
{
- cd.setValueAt(
+ cd->setValueAt(
(int)i.value()[dy][dx], /*value*/
center.x() + (i.key().x() + dx), /*x*/
center.y() + (i.key().y() + dy) /*y*/
@@ -304,68 +472,93 @@
++i;
}
- if (type == "Neighbourhood")
- {
-// qDebug(N.toXmlString().toAscii());
- return N.toXmlString();
- }
- else if (type == "LocalFunction")
- {
-// qDebug(lf.toXmlString().toAscii());
- return lf.toXmlString();
- }
- else if (type == "World")
- {
-// qDebug(cd.toXmlString().toAscii());
- return cd.toXmlString();
- }
+ return cd;
}
-
-QByteArray Life105ParserPlugin::parseOut(QString content, const QString type, const QString subtype)
+CalculationData* Life105ParserPlugin::parseIn106(QStringList *lines, int line_nr)
{
- // The resulting array to write to file by the backend
- QByteArray result;
- // Generic type to parse XML request
- LocalFunction lf;
+ CalculationData* cd = new CalculationData;
- // Check if we can use the generic type from the XML string
- if(!lf.fromXmlString(&content));
+ QRegExp format = QRegExp("^-?(\\d)* -?(\\d)*$");
+ QRegExp line_separator("^\\.$");
+ int min_x, max_x, min_y, max_y;
+ min_x = max_x = min_y = max_y = 0;
+ QList<QPoint> points;
+ QPoint tmp_point;
+ QStringList numbers;
+ foreach(QString line, *lines)
{
- qDebug(tr("Unable to parse out internal data!").toAscii());
+ if(format.exactMatch(line))
+ {
+ // Split the line
+ numbers = line.split(' ');
+ tmp_point.setX(numbers[0].toInt());
+ tmp_point.setY(numbers[1].toInt());
- return QByteArray();
+ // Actually append the point
+ points.append(tmp_point);
+
+ // Borders check
+ if (tmp_point.x() > max_x)
+ {
+ max_x = tmp_point.x();
+ }
+ else if (tmp_point.x() < min_x)
+ {
+ min_x = tmp_point.x();
+ }
+
+ if (tmp_point.y() > max_y)
+ {
+ max_y = tmp_point.y();
+ }
+ else if (tmp_point.y() < min_y)
+ {
+ min_y = tmp_point.y();
+ }
+ }
+ else if (!line.isEmpty())
+ {
+ qDebug(tr("Bogus characters in line %1.")
+ .arg(line_nr)
+ .toAscii()
+ );
+
+ return NULL;
+ }
+
+ // To keep count of current line nr
+ line_nr++;
}
- // Header
- result.append("Life105");
- result.append('\n');
-
- // Second line
- // Num of args
- result.append(lf.getNumberOfArgs());
- result.append(' ');
- // Num of arg values
- result.append(lf.getAlphabetSize());
- result.append(' ');
- // Num of return values
- result.append(lf.getMaxReturnValues());
- result.append(' ');
- result.append('\n');
+ //// Prepare the actual structures in QCell
+ // Scale the universe to be SCALE times bigger then the object from file take
+ int size_x = (abs(min_x) + max_x) * SCALE;
+ if ((size_x % 2) == 0)
+ {
+ size_x++;
+ }
+ int size_y = (abs(min_y) + max_y) * SCALE;
+ if ((size_y % 2) == 0)
+ {
+ size_y++;
+ }
- // Third line - summed args
- foreach(int arg, lf.getSummedArguments())
+ cd->resizeData(size_x, size_y);
+ QPoint center(cd->getSizeX()/2, cd->getSizeY()/2);
+ // Fill the whole universe with 0-s
+ cd->fillData(0);
+
+ for (int i = 0; i < points.size(); i++)
{
- result.append(QString::number(arg)[0].toAscii());
- result.append(',');
+ cd->setValueAt(
+ 1, /*value*/
+ center.x() + points[i].x(), /*x*/
+ center.y() + points[i].y() /*y*/
+ );
}
- // Get rid of the penging `,'
- result.chop(1);
- result.append('\n');
- /// @todo Main function writing
-
- return result;
+ return cd;
}
Q_EXPORT_PLUGIN2(Life105FileParser, Life105ParserPlugin)
Modified: trunk/qcell/parsers/Life-1.05/Life105ParserPlugin.h
===================================================================
--- trunk/qcell/parsers/Life-1.05/Life105ParserPlugin.h 2007-02-09 13:16:59 UTC (rev 299)
+++ trunk/qcell/parsers/Life-1.05/Life105ParserPlugin.h 2007-02-09 20:26:35 UTC (rev 300)
@@ -14,6 +14,7 @@
#include <QList>
#include <QHash>
#include <QPoint>
+#include <QDomDocument>
#include "GenericParserPlugin.h"
#include "Neighbourhood.h"
@@ -21,7 +22,7 @@
#include "CalculationData.h"
#define LIFE105_PARSER_TYPE "Function"
-#define SCALE 5
+#define SCALE 2
typedef QVector<QVector<bool> > Universe;
int qHash(const QPoint &point)
@@ -33,6 +34,8 @@
{
protected:
QString realParser(const QByteArray content, const QString type, const QString subtype);
+ CalculationData* parseIn105(QStringList *lines, int line_nr);
+ CalculationData* parseIn106(QStringList *lines, int line_nr);
public:
Life105ParserPlugin();
Modified: trunk/qcell/visgui/MainWindow.cpp
===================================================================
--- trunk/qcell/visgui/MainWindow.cpp 2007-02-09 13:16:59 UTC (rev 299)
+++ trunk/qcell/visgui/MainWindow.cpp 2007-02-09 20:26:35 UTC (rev 300)
@@ -275,7 +275,6 @@
}
/// @todo This function doesn't belong here. It initializes things not fore GUI
setupEngine();
-
}
void MainWindow::on_action_About_activated()
@@ -667,6 +666,46 @@
/// @todo Wait for toXmlString
file.write(world_parsers[subtype]->parseOut(sw->getStorage()->toXmlString(), type, subtype));
}
+ else if (type == "Import")
+ {
+ if (!import_parsers.contains(subtype))
+ {
+ qDebug(tr("Exporting to %1 isn't supported")
+ .arg(subtype)
+ .toAscii()
+ );
+ return;
+ }
+
+ QByteArray result, tmp_result;
+
+ // Neighbourhood checking
+ tmp_result = import_parsers[subtype]->parseOut(neighbourhood->toXmlString(), "Neighbourhood", subtype);
+ if (tmp_result.isEmpty())
+ {
+ return;
+ }
+ result.append(QByteArray(tmp_result));
+
+ // LocalFunction parsing
+ tmp_result = import_parsers[subtype]->parseOut(local_function->toXmlString(), "LocalFunction", subtype);
+ if (tmp_result.isEmpty())
+ {
+ return;
+ }
+ result.append(QByteArray(tmp_result));
+
+ // World parsing
+ tmp_result = import_parsers[subtype]->parseOut(sw->getStorage()->toXmlString(), "World", subtype);
+ if (tmp_result.isEmpty())
+ {
+ return;
+ }
+ result.append(QByteArray(tmp_result));
+
+ // Finally - write to the file
+ file.write(result);
+ }
else
{
qDebug(tr("Unsupported file type to parse.").toAscii());
@@ -1464,4 +1503,49 @@
action_World_save->setEnabled(true);
}
+void MainWindow::on_action_Export_activated()
+{
+ if(import_parsers.count() == 0)
+ {
+ QMessageBox::warning(
+ /*parent*/ this,
+ /*title*/ tr("Plugins warning"),
+ /*message*/ tr("There are no plugins loaded to handle exporting.")
+ );
+ return;
+ }
+
+ QFileDialog fd(
+ /*parent*/ this,
+ /*cation*/ tr("Export Experiment"),
+ /*dir*/ "."
+ );
+
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.setFileMode(QFileDialog::AnyFile);
+
+ QStringList filters;
+ QString filter;
+ // Add filter in format %{name} files (*.%{name})
+ foreach(QString key, import_parsers.keys())
+ {
+ // Don't shorten this, as it is made for translations
+ // purposes
+ filter = key + " " + tr("files") + " (*." + key + ")";
+ filters << filter;
+ }
+ fd.setFilters(filters);
+ /// @todo Forge some real suffix adding
+ fd.setDefaultSuffix("*");
+
+ if(fd.exec())
+ {
+ if(!fd.selectedFiles().isEmpty())
+ {
+ callSaver(fd.selectedFiles().first(), "Import");
+
+ }
+ }
+}
+
Modified: trunk/qcell/visgui/MainWindow.h
===================================================================
--- trunk/qcell/visgui/MainWindow.h 2007-02-09 13:16:59 UTC (rev 299)
+++ trunk/qcell/visgui/MainWindow.h 2007-02-09 20:26:35 UTC (rev 300)
@@ -57,6 +57,7 @@
void on_action_Function_activated();
void on_action_World_activated();
void on_action_Import_activated();
+ void on_action_Export_activated();
void on_action_World_save_activated();
void on_action_Neighbourhood_save_activated();
Modified: trunk/qcell/visgui/MainWindow.ui
===================================================================
--- trunk/qcell/visgui/MainWindow.ui 2007-02-09 13:16:59 UTC (rev 299)
+++ trunk/qcell/visgui/MainWindow.ui 2007-02-09 20:26:35 UTC (rev 300)
@@ -102,6 +102,7 @@
<addaction name="action_Open_experiment" />
<addaction name="action_Continue_experiment" />
<addaction name="action_Import" />
+ <addaction name="action_Export" />
<addaction name="menu_Save" />
<addaction name="action_Save_experiment" />
<addaction name="separator" />
@@ -167,7 +168,7 @@
<bool>false</bool>
</property>
<property name="text" >
- <string>Open &experiment</string>
+ <string>Open ex&periment</string>
</property>
<property name="statusTip" >
<string>Opens a predefined experiment.</string>
@@ -334,6 +335,11 @@
<string>Imports experiments from other programs.</string>
</property>
</action>
+ <action name="action_Export" >
+ <property name="text" >
+ <string>&Export</string>
+ </property>
+ </action>
</widget>
<resources/>
<connections/>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|