00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "connector.h"
00012 #include "ecnode.h"
00013 #include "ecsubcircuit.h"
00014 #include "flowcodedocument.h"
00015 #include "flowcontainer.h"
00016 #include "fpnode.h"
00017 #include "itemdocumentdata.h"
00018 #include "itemlibrary.h"
00019 #include "picitem.h"
00020 #include "pinmapping.h"
00021
00022 #include <kdebug.h>
00023 #include <kio/netaccess.h>
00024 #include <klocale.h>
00025 #include <kmessagebox.h>
00026 #include <ktempfile.h>
00027 #include <qbitarray.h>
00028 #include <qfile.h>
00029
00030
00031
00032 static QString toAsciiHex( QBitArray _data )
00033 {
00034 QBitArray data = _data;
00035
00036
00037
00038 if ( (data.size() % 4) != 0 )
00039 {
00040 data.detach();
00041 data.resize( data.size() + 4 - (data.size()%4) );
00042 }
00043
00044 QString text;
00045 for ( unsigned i = 0; i < data.size()/4; ++i )
00046 {
00047 unsigned val = 0;
00048 for ( unsigned j = 0; j < 4; ++j )
00049 val += (data[4*i+j] ? 1:0) << j;
00050
00051 text += QString::number( val, 16 );
00052 }
00053 return text;
00054 }
00055
00056
00057 static QBitArray toQBitArray( QString text )
00058 {
00059 unsigned size = text.length();
00060 QBitArray data(size*4);
00061
00062 for ( unsigned i = 0; i < size; ++i )
00063 {
00064 unsigned val = QString(text[i]).toInt( 0, 16 );
00065 for ( unsigned j = 0; j < 4; ++j )
00066 data[4*i+j] = val & (1 << j);
00067 }
00068
00069
00070
00071 return data;
00072 }
00073
00074
00075
00076 ItemDocumentData::ItemDocumentData( uint documentType )
00077 {
00078 reset();
00079 m_documentType = documentType;
00080 }
00081
00082
00083 ItemDocumentData::~ItemDocumentData()
00084 {
00085 }
00086
00087
00088 void ItemDocumentData::reset()
00089 {
00090 m_itemDataMap.clear();
00091 m_connectorDataMap.clear();
00092 m_nodeDataMap.clear();
00093 m_microData.reset();
00094 m_documentType = Document::dt_none;
00095 }
00096
00097
00098 bool ItemDocumentData::loadData( const KURL &url )
00099 {
00100 QString target;
00101 if ( !KIO::NetAccess::download( url, target, 0 ) )
00102 {
00103
00104
00105 KMessageBox::error( 0, KIO::NetAccess::lastErrorString() );
00106
00107 return false;
00108 }
00109
00110 QFile file(target);
00111 if ( !file.open( IO_ReadOnly ) )
00112 {
00113 KMessageBox::sorry( 0, i18n("Could not open %1 for reading").arg(target) );
00114 return false;
00115 }
00116
00117 QString xml;
00118 QTextStream textStream( &file );
00119 while ( !textStream.eof() )
00120 xml += textStream.readLine() + '\n';
00121
00122 file.close();
00123 return fromXML(xml);
00124 }
00125
00126
00127 bool ItemDocumentData::fromXML( const QString &xml )
00128 {
00129 reset();
00130
00131 QDomDocument doc( "KTechlab" );
00132 QString errorMessage;
00133 if ( !doc.setContent( xml, &errorMessage ) )
00134 {
00135 KMessageBox::sorry( 0, i18n("Couldn't parse xml:\n%1").arg(errorMessage) );
00136 return false;
00137 }
00138
00139 QDomElement root = doc.documentElement();
00140
00141 QDomNode node = root.firstChild();
00142 while ( !node.isNull() )
00143 {
00144 QDomElement element = node.toElement();
00145 if ( !element.isNull() )
00146 {
00147 const QString tagName = element.tagName();
00148
00149 if ( tagName == "item" )
00150 elementToItemData(element);
00151
00152 else if ( tagName == "node" )
00153 elementToNodeData(element);
00154
00155 else if ( tagName == "connector" )
00156 elementToConnectorData(element);
00157
00158 else if ( tagName == "pic-settings" || tagName == "micro" )
00159 elementToMicroData(element);
00160
00161 else if ( tagName == "code" )
00162 ;
00163
00164 else
00165 kdWarning() << k_funcinfo << "Unrecognised element tag name: "<<tagName<<endl;
00166 }
00167
00168 node = node.nextSibling();
00169 }
00170
00171 return true;
00172 }
00173
00174
00175 bool ItemDocumentData::saveData( const KURL &url )
00176 {
00177
00178 if ( url.isLocalFile() )
00179 {
00180 QFile file( url.path() );
00181 if ( !file.open(IO_WriteOnly) )
00182 {
00183 KMessageBox::sorry( 0, i18n("Could not open '%1' for writing. Check that you have write permissions").arg(url.path()), i18n("Saving File") );
00184 return false;
00185 }
00186
00187 QTextStream stream(&file);
00188 stream << toXML();
00189 file.close();
00190 }
00191 else
00192 {
00193 KTempFile file;
00194 *file.textStream() << toXML();
00195 file.close();
00196
00197 if ( !KIO::NetAccess::upload( file.name(), url, 0 ) )
00198 {
00199 KMessageBox::error( 0, KIO::NetAccess::lastErrorString() );
00200 return false;
00201 }
00202 }
00203
00204 return true;
00205 }
00206
00207
00208 QString ItemDocumentData::toXML()
00209 {
00210 QDomDocument doc("KTechlab");
00211
00212
00213 QDomElement root = doc.createElement("document");
00214 root.setAttribute( "type", documentTypeString() );
00215 doc.appendChild(root);
00216
00217 {
00218 const ItemDataMap::iterator end = m_itemDataMap.end();
00219 for ( ItemDataMap::iterator it = m_itemDataMap.begin(); it != end; ++it )
00220 {
00221 QDomElement node = itemDataToElement( doc, it.data() );
00222 node.setAttribute( "id", it.key() );
00223 root.appendChild(node);
00224 }
00225 }
00226 {
00227 const ConnectorDataMap::iterator end = m_connectorDataMap.end();
00228 for ( ConnectorDataMap::iterator it = m_connectorDataMap.begin(); it != end; ++it )
00229 {
00230 QDomElement node = connectorDataToElement( doc, it.data() );
00231 node.setAttribute( "id", it.key() );
00232 root.appendChild(node);
00233 }
00234 }
00235 {
00236 const NodeDataMap::iterator end = m_nodeDataMap.end();
00237 for ( NodeDataMap::iterator it = m_nodeDataMap.begin(); it != end; ++it )
00238 {
00239 QDomElement node = nodeDataToElement( doc, it.data() );
00240 node.setAttribute( "id", it.key() );
00241 root.appendChild(node);
00242 }
00243 }
00244 if ( m_documentType == Document::dt_flowcode )
00245 {
00246 QDomElement node = microDataToElement(doc);
00247 root.appendChild(node);
00248 }
00249
00250 return doc.toString();
00251 }
00252
00253
00254
00255
00256 QDomElement ItemDocumentData::microDataToElement( QDomDocument &doc )
00257 {
00258 QDomElement node = doc.createElement("micro");
00259 node.setAttribute( "id", m_microData.id );
00260
00261 {
00262 const PinMappingMap::iterator end = m_microData.pinMappings.end();
00263 for ( PinMappingMap::iterator it = m_microData.pinMappings.begin(); it != end; ++it )
00264 {
00265 QDomElement pinMapNode = doc.createElement("pinmap");
00266
00267 QString type;
00268 switch ( it.data().type() )
00269 {
00270 case PinMapping::SevenSegment:
00271 type = "sevensegment";
00272 break;
00273
00274 case PinMapping::Keypad_4x3:
00275 type = "keypad_4x3";
00276 break;
00277
00278 case PinMapping::Keypad_4x4:
00279 type = "keypad_4x4";
00280 break;
00281
00282 case PinMapping::Invalid:
00283 break;
00284 }
00285
00286 pinMapNode.setAttribute( "id", it.key() );
00287 pinMapNode.setAttribute( "type", type );
00288 pinMapNode.setAttribute( "map", it.data().pins().join(" ") );
00289
00290 node.appendChild(pinMapNode);
00291 }
00292 }
00293
00294 {
00295 const PinDataMap::iterator end = m_microData.pinMap.end();
00296 for ( PinDataMap::iterator it = m_microData.pinMap.begin(); it != end; ++it )
00297 {
00298 QDomElement pinNode = doc.createElement("pin");
00299
00300 pinNode.setAttribute( "id", it.key() );
00301 pinNode.setAttribute( "type", (it.data().type == PinSettings::pt_input) ? "input" : "output" );
00302 pinNode.setAttribute( "state", (it.data().state == PinSettings::ps_off) ? "off" : "on" );
00303
00304 node.appendChild(pinNode);
00305 }
00306 }
00307
00308 {
00309 const QStringMap::iterator end = m_microData.variableMap.end();
00310 for ( QStringMap::iterator it = m_microData.variableMap.begin(); it != end; ++it )
00311 {
00312 QDomElement variableNode = doc.createElement("variable");
00313
00314 variableNode.setAttribute( "name", it.key() );
00315 variableNode.setAttribute( "value", it.data() );
00316
00317 node.appendChild(variableNode);
00318 }
00319 }
00320
00321 return node;
00322 }
00323
00324
00325 void ItemDocumentData::elementToMicroData( QDomElement element )
00326 {
00327 QString id = element.attribute( "id", QString::null );
00328
00329 if ( id.isNull() )
00330 id = element.attribute( "pic", QString::null );
00331
00332 if ( id.isNull() )
00333 {
00334 kdError() << k_funcinfo << "Could not find id in element" << endl;
00335 return;
00336 }
00337
00338 m_microData.reset();
00339 m_microData.id = id;
00340
00341 QDomNode node = element.firstChild();
00342 while ( !node.isNull() )
00343 {
00344 QDomElement childElement = node.toElement();
00345 if ( !childElement.isNull() )
00346 {
00347 const QString tagName = childElement.tagName();
00348
00349 if ( tagName == "pinmap" )
00350 {
00351 QString id = childElement.attribute( "id", QString::null );
00352 QString typeString = childElement.attribute( "type", QString::null );
00353
00354 if ( !id.isEmpty() && !typeString.isEmpty() )
00355 {
00356 PinMapping::Type type = PinMapping::Invalid;
00357
00358 if ( typeString == "sevensegment" )
00359 type = PinMapping::SevenSegment;
00360
00361 else if ( typeString == "keypad_4x3" )
00362 type = PinMapping::Keypad_4x3;
00363
00364 else if ( typeString == "keypad_4x4" )
00365 type = PinMapping::Keypad_4x4;
00366
00367 PinMapping pinMapping( type );
00368 pinMapping.setPins( QStringList::split( " ", childElement.attribute( "map", 0 ) ) );
00369
00370 m_microData.pinMappings[id] = pinMapping;
00371 }
00372 }
00373
00374 else if ( tagName == "pin" )
00375 {
00376 QString pinID = childElement.attribute( "id", QString::null );
00377 if ( !pinID.isEmpty() )
00378 {
00379 m_microData.pinMap[pinID].type = (childElement.attribute( "type", "input" ) == "input" ) ? PinSettings::pt_input : PinSettings::pt_output;
00380 m_microData.pinMap[pinID].state = (childElement.attribute( "state", "off" ) == "off" ) ? PinSettings::ps_off : PinSettings::ps_on;
00381 }
00382 }
00383
00384 else if ( tagName == "variable" )
00385 {
00386 QString variableId = childElement.attribute( "name", QString::null );
00387 m_microData.variableMap[variableId] = childElement.attribute( "value", QString::null );
00388 }
00389
00390 else
00391 kdError() << k_funcinfo << "Unrecognised element tag name: "<<tagName<<endl;
00392 }
00393
00394 node = node.nextSibling();
00395 }
00396 }
00397
00398
00399 QDomElement ItemDocumentData::itemDataToElement( QDomDocument &doc, const ItemData &itemData )
00400 {
00401 QDomElement node = doc.createElement("item");
00402 node.setAttribute( "type", itemData.type );
00403 node.setAttribute( "x", itemData.x );
00404 node.setAttribute( "y", itemData.y );
00405 if ( itemData.z != -1 )
00406 node.setAttribute( "z", itemData.z );
00407 if ( itemData.setSize )
00408 {
00409 node.setAttribute( "offset-x", itemData.size.x() );
00410 node.setAttribute( "offset-y", itemData.size.y() );
00411 node.setAttribute( "width", itemData.size.width() );
00412 node.setAttribute( "height", itemData.size.height() );
00413 }
00414
00415
00416 if ( itemData.orientation >= 0 )
00417 {
00418 node.setAttribute( "orientation", itemData.orientation );
00419 }
00420 else
00421 {
00422 node.setAttribute( "angle", itemData.angleDegrees );
00423 node.setAttribute( "flip", itemData.flipped );
00424 }
00425
00426 if ( !itemData.parentId.isEmpty() )
00427 node.setAttribute( "parent", itemData.parentId );
00428
00429 const QStringMap::const_iterator stringEnd = itemData.dataString.end();
00430 for ( QStringMap::const_iterator it = itemData.dataString.begin(); it != stringEnd; ++it )
00431 {
00432 QDomElement e = doc.createElement("data");
00433 node.appendChild(e);
00434 e.setAttribute( "id", it.key() );
00435 e.setAttribute( "type", "string" );
00436 e.setAttribute( "value", it.data() );
00437 }
00438
00439 const DoubleMap::const_iterator numberEnd = itemData.dataNumber.end();
00440 for ( DoubleMap::const_iterator it = itemData.dataNumber.begin(); it != numberEnd; ++it )
00441 {
00442 QDomElement e = doc.createElement("data");
00443 node.appendChild(e);
00444 e.setAttribute( "id", it.key() );
00445 e.setAttribute( "type", "number" );
00446 e.setAttribute( "value", QString::number(it.data()) );
00447 }
00448
00449 const QColorMap::const_iterator colorEnd = itemData.dataColor.end();
00450 for ( QColorMap::const_iterator it = itemData.dataColor.begin(); it != colorEnd; ++it )
00451 {
00452 QDomElement e = doc.createElement("data");
00453 node.appendChild(e);
00454 e.setAttribute( "id", it.key() );
00455 e.setAttribute( "type", "color" );
00456 e.setAttribute( "value", it.data().name() );
00457 }
00458
00459 const QBitArrayMap::const_iterator rawEnd = itemData.dataRaw.end();
00460 for ( QBitArrayMap::const_iterator it = itemData.dataRaw.begin(); it != rawEnd; ++it )
00461 {
00462 QDomElement e = doc.createElement("data");
00463 node.appendChild(e);
00464 e.setAttribute( "id", it.key() );
00465 e.setAttribute( "type", "raw" );
00466 e.setAttribute( "value", toAsciiHex(it.data()) );
00467 }
00468
00469 const BoolMap::const_iterator boolEnd = itemData.dataBool.end();
00470 for ( BoolMap::const_iterator it = itemData.dataBool.begin(); it != boolEnd; ++it )
00471 {
00472 QDomElement e = doc.createElement("data");
00473 node.appendChild(e);
00474 e.setAttribute( "id", it.key() );
00475 e.setAttribute( "type", "bool" );
00476 e.setAttribute( "value", QString::number(it.data()) );
00477 }
00478
00479 const BoolMap::const_iterator buttonEnd = itemData.buttonMap.end();
00480 for ( BoolMap::const_iterator it = itemData.buttonMap.begin(); it != buttonEnd; ++it )
00481 {
00482 QDomElement e = doc.createElement("button");
00483 node.appendChild(e);
00484 e.setAttribute( "id", it.key() );
00485 e.setAttribute( "state", QString::number(it.data()) );
00486 }
00487
00488 const IntMap::const_iterator sliderEnd = itemData.sliderMap.end();
00489 for ( IntMap::const_iterator it = itemData.sliderMap.begin(); it != sliderEnd; ++it )
00490 {
00491 QDomElement e = doc.createElement("slider");
00492 node.appendChild(e);
00493 e.setAttribute( "id", it.key() );
00494 e.setAttribute( "value", QString::number(it.data()) );
00495 }
00496
00497 return node;
00498 }
00499
00500
00501 void ItemDocumentData::elementToItemData( QDomElement element )
00502 {
00503 QString id = element.attribute( "id", QString::null );
00504 if ( id.isNull() )
00505 {
00506 kdError() << k_funcinfo << "Could not find id in element" << endl;
00507 return;
00508 }
00509
00510 ItemData itemData;
00511 itemData.type = element.attribute( "type", QString::null );
00512 itemData.x = element.attribute( "x", "120" ).toInt();
00513 itemData.y = element.attribute( "y", "120" ).toInt();
00514 itemData.z = element.attribute( "z", "-1" ).toInt();
00515
00516 if ( element.hasAttribute("width") &&
00517 element.hasAttribute("height") )
00518 {
00519 itemData.setSize = true;
00520 itemData.size = QRect( element.attribute( "offset-x", "0" ).toInt(),
00521 element.attribute( "offset-y", "0" ).toInt(),
00522 element.attribute( "width", "120" ).toInt(),
00523 element.attribute( "height", "120" ).toInt() );
00524 }
00525 else
00526 itemData.setSize = false;
00527
00528 itemData.angleDegrees = element.attribute( "angle", "0" ).toInt();
00529 itemData.flipped = element.attribute( "flip", "0" ).toInt();
00530 itemData.orientation = element.attribute( "orientation", "-1" ).toInt();
00531 itemData.parentId = element.attribute( "parent", QString::null );
00532
00533 m_itemDataMap[id] = itemData;
00534
00535 QDomNode node = element.firstChild();
00536 while ( !node.isNull() )
00537 {
00538 QDomElement childElement = node.toElement();
00539 if ( !childElement.isNull() )
00540 {
00541 const QString tagName = childElement.tagName();
00542
00543 if ( tagName == "item" )
00544 {
00545
00546
00547
00548 elementToItemData(childElement);
00549 QString childId = childElement.attribute( "id", QString::null );
00550 if ( !childId.isNull() )
00551 m_itemDataMap[childId].parentId = id;
00552 }
00553
00554 else if ( tagName == "data" )
00555 {
00556 QString dataId = childElement.attribute( "id", QString::null );
00557 if ( !dataId.isNull() )
00558 {
00559 QString dataType = childElement.attribute( "type", QString::null );
00560 QString value = childElement.attribute( "value", QString::null );
00561
00562 if ( dataType == "string" || dataType == "multiline" )
00563 m_itemDataMap[id].dataString[dataId] = value;
00564 else if ( dataType == "number" )
00565 m_itemDataMap[id].dataNumber[dataId] = value.toDouble();
00566 else if ( dataType == "color" )
00567 m_itemDataMap[id].dataColor[dataId] = QColor(value);
00568 else if ( dataType == "raw" )
00569 m_itemDataMap[id].dataRaw[dataId] = toQBitArray(value);
00570 else if ( dataType == "bool" )
00571 m_itemDataMap[id].dataBool[dataId] = bool(value.toInt());
00572 else
00573 kdError() << k_funcinfo << "Unknown data type of \""<<dataType<<"\" with id \""<<dataId<<"\""<<endl;
00574 }
00575 }
00576
00577 else if ( tagName == "button" )
00578 {
00579 QString buttonId = childElement.attribute( "id", QString::null );
00580 if ( !buttonId.isNull() )
00581 m_itemDataMap[id].buttonMap[buttonId] = childElement.attribute( "state", "0" ).toInt();
00582 }
00583
00584 else if ( tagName == "slider" )
00585 {
00586 QString sliderId = childElement.attribute( "id", QString::null );
00587 if ( !sliderId.isNull() )
00588 m_itemDataMap[id].sliderMap[sliderId] = childElement.attribute( "value", "0" ).toInt();
00589 }
00590
00591 else if ( tagName == "child-node" )
00592 ;
00593
00594 else
00595 kdError() << k_funcinfo << "Unrecognised element tag name: "<<tagName<<endl;
00596 }
00597
00598 node = node.nextSibling();
00599 }
00600 }
00601
00602
00603 QDomElement ItemDocumentData::nodeDataToElement( QDomDocument &doc, const NodeData &nodeData )
00604 {
00605 QDomElement node = doc.createElement("node");
00606 node.setAttribute( "x", nodeData.x );
00607 node.setAttribute( "y", nodeData.y );
00608 return node;
00609 }
00610
00611
00612 void ItemDocumentData::elementToNodeData( QDomElement element )
00613 {
00614 QString id = element.attribute( "id", QString::null );
00615 if ( id.isNull() )
00616 {
00617 kdError() << k_funcinfo << "Could not find id in element" << endl;
00618 return;
00619 }
00620
00621 NodeData nodeData;
00622 nodeData.x = element.attribute( "x", "120" ).toInt();
00623 nodeData.y = element.attribute( "y", "120" ).toInt();
00624
00625 m_nodeDataMap[id] = nodeData;
00626 }
00627
00628
00629 QDomElement ItemDocumentData::connectorDataToElement( QDomDocument &doc, const ConnectorData &connectorData )
00630 {
00631 QDomElement node = doc.createElement("connector");
00632
00633 node.setAttribute( "manual-route", connectorData.manualRoute );
00634
00635 QString route;
00636 const QPointList::const_iterator end = connectorData.route.end();
00637 for ( QPointList::const_iterator it = connectorData.route.begin(); it != end; ++it )
00638 {
00639 route.append( QString::number((*it).x())+"," );
00640 route.append( QString::number((*it).y())+"," );
00641 }
00642 node.setAttribute( "route", route );
00643
00644 if ( connectorData.startNodeIsChild )
00645 {
00646 node.setAttribute( "start-node-is-child", 1 );
00647 node.setAttribute( "start-node-cid", connectorData.startNodeCId );
00648 node.setAttribute( "start-node-parent", connectorData.startNodeParent );
00649 }
00650 else
00651 {
00652 node.setAttribute( "start-node-is-child", 0 );
00653 node.setAttribute( "start-node-id", connectorData.startNodeId );
00654 }
00655
00656
00657 if ( connectorData.endNodeIsChild )
00658 {
00659 node.setAttribute( "end-node-is-child", 1 );
00660 node.setAttribute( "end-node-cid", connectorData.endNodeCId );
00661 node.setAttribute( "end-node-parent", connectorData.endNodeParent );
00662 }
00663 else
00664 {
00665 node.setAttribute( "end-node-is-child", 0 );
00666 node.setAttribute( "end-node-id", connectorData.endNodeId );
00667 }
00668
00669 return node;
00670 }
00671
00672
00673 void ItemDocumentData::elementToConnectorData( QDomElement element )
00674 {
00675 QString id = element.attribute( "id", QString::null );
00676 if ( id.isNull() )
00677 {
00678 kdError() << k_funcinfo << "Could not find id in element" << endl;
00679 return;
00680 }
00681
00682 ConnectorData connectorData;
00683
00684 connectorData.manualRoute = element.attribute( "manual-route", "0" );
00685 QString route = element.attribute( "route", "" );
00686
00687 QStringList points = QStringList::split( ",", route );
00688 const QStringList::iterator end = points.end();
00689 for ( QStringList::iterator it = points.begin(); it != end; ++it )
00690 {
00691 int x = (*it).toInt();
00692 it++;
00693 if ( it != end )
00694 {
00695 int y = (*it).toInt();
00696 connectorData.route.append( QPoint(x,y) );
00697 }
00698 }
00699
00700 connectorData.startNodeIsChild = element.attribute( "start-node-is-child", "0" ).toInt();
00701 if ( connectorData.startNodeIsChild )
00702 {
00703 connectorData.startNodeCId = element.attribute( "start-node-cid", QString::null );
00704 connectorData.startNodeParent = element.attribute( "start-node-parent", QString::null );
00705 }
00706 else
00707 connectorData.startNodeId = element.attribute( "start-node-id", QString::null );
00708
00709
00710 connectorData.endNodeIsChild = element.attribute( "end-node-is-child", "0" ).toInt();
00711 if ( connectorData.endNodeIsChild )
00712 {
00713 connectorData.endNodeCId = element.attribute( "end-node-cid", QString::null );
00714 connectorData.endNodeParent = element.attribute( "end-node-parent", QString::null );
00715 }
00716 else
00717 connectorData.endNodeId = element.attribute( "end-node-id", QString::null );
00718
00719 m_connectorDataMap[id] = connectorData;
00720 }
00721
00722
00723
00724
00725 QString ItemDocumentData::documentTypeString() const
00726 {
00727 switch (m_documentType)
00728 {
00729 case Document::dt_circuit:
00730 return "circuit";
00731 break;
00732 case Document::dt_flowcode:
00733 return "flowcode";
00734 break;
00735 case Document::dt_mechanics:
00736 return "mechanics";
00737 break;
00738 case Document::dt_text:
00739 case Document::dt_none:
00740 default:
00741 return "none";
00742 break;
00743 }
00744 }
00745
00746
00747 QString ItemDocumentData::revisionString() const
00748 {
00749 return "1";
00750 }
00751
00752
00753 void ItemDocumentData::saveDocumentState( ItemDocument *itemDocument )
00754 {
00755 if (!itemDocument)
00756 return;
00757
00758 reset();
00759
00760 addItems( itemDocument->itemList() );
00761
00762 if ( ICNDocument *icnd = dynamic_cast<ICNDocument*>(itemDocument) )
00763 {
00764 addConnectors( icnd->connectorList() );
00765 addNodes( icnd->nodeList() );
00766
00767 if ( FlowCodeDocument *fcd = dynamic_cast<FlowCodeDocument*>(itemDocument) )
00768 {
00769 if ( fcd->microSettings() )
00770 setMicroData( fcd->microSettings()->microData() );
00771 }
00772 }
00773
00774 m_documentType = itemDocument->type();
00775 }
00776
00777
00778 void ItemDocumentData::generateUniqueIDs( ItemDocument *itemDocument )
00779 {
00780 if (!itemDocument)
00781 return;
00782
00783 QStringMap replaced;
00784 replaced[""] = QString::null;
00785 replaced[QString::null] = QString::null;
00786
00787 ItemDataMap newItemDataMap;
00788 ConnectorDataMap newConnectorDataMap;
00789 NodeDataMap newNodeDataMap;
00790
00791
00792 {
00793 const ItemDataMap::iterator end = m_itemDataMap.end();
00794 for ( ItemDataMap::iterator it = m_itemDataMap.begin(); it != end; ++it )
00795 {
00796 if ( !replaced.contains( it.key() ) )
00797 replaced[it.key()] = itemDocument->generateUID(it.key());
00798
00799 newItemDataMap[replaced[it.key()]] = it.data();
00800 }
00801 }
00802 {
00803 const NodeDataMap::iterator end = m_nodeDataMap.end();
00804 for ( NodeDataMap::iterator it = m_nodeDataMap.begin(); it != end; ++it )
00805 {
00806 if ( !replaced.contains( it.key() ) )
00807 replaced[it.key()] = itemDocument->generateUID(it.key());
00808
00809 newNodeDataMap[replaced[it.key()]] = it.data();
00810 }
00811 }
00812 {
00813 const ConnectorDataMap::iterator end = m_connectorDataMap.end();
00814 for ( ConnectorDataMap::iterator it = m_connectorDataMap.begin(); it != end; ++it )
00815 {
00816 if ( !replaced.contains( it.key() ) )
00817 replaced[it.key()] = itemDocument->generateUID(it.key());
00818
00819 newConnectorDataMap[replaced[it.key()]] = it.data();
00820 }
00821 }
00822
00823
00824
00825 {
00826 const ItemDataMap::iterator end = newItemDataMap.end();
00827 for ( ItemDataMap::iterator it = newItemDataMap.begin(); it != end; ++it )
00828 {
00829 it.data().parentId = replaced[it.data().parentId];
00830 }
00831 }
00832 {
00833 const ConnectorDataMap::iterator end = newConnectorDataMap.end();
00834 for ( ConnectorDataMap::iterator it = newConnectorDataMap.begin(); it != end; ++it )
00835 {
00836 it.data().startNodeParent = replaced[it.data().startNodeParent];
00837 it.data().endNodeParent = replaced[it.data().endNodeParent];
00838
00839 it.data().startNodeId = replaced[it.data().startNodeId];
00840 it.data().endNodeId = replaced[it.data().endNodeId];
00841 }
00842 }
00843
00844
00845
00846 m_itemDataMap = newItemDataMap;
00847 m_connectorDataMap = newConnectorDataMap;
00848 m_nodeDataMap = newNodeDataMap;
00849 }
00850
00851
00852 void ItemDocumentData::translateContents( int dx, int dy )
00853 {
00854
00855 {
00856 const ItemDataMap::iterator end = m_itemDataMap.end();
00857 for ( ItemDataMap::iterator it = m_itemDataMap.begin(); it != end; ++it )
00858 {
00859 it.data().x += dx;
00860 it.data().y += dx;
00861 }
00862 }
00863 {
00864 const NodeDataMap::iterator end = m_nodeDataMap.end();
00865 for ( NodeDataMap::iterator it = m_nodeDataMap.begin(); it != end; ++it )
00866 {
00867 it.data().x += dx;
00868 it.data().y += dy;
00869 }
00870 }
00871 {
00872 const ConnectorDataMap::iterator end = m_connectorDataMap.end();
00873 for ( ConnectorDataMap::iterator it = m_connectorDataMap.begin(); it != end; ++it )
00874 {
00875 const QPointList::iterator routeEnd = it.data().route.end();
00876 for ( QPointList::iterator routeIt = it.data().route.begin(); routeIt != routeEnd; ++routeIt )
00877 {
00878 *routeIt += QPoint( dx/8, dy/8 );
00879 }
00880 }
00881 }
00882 }
00883
00884
00885 void ItemDocumentData::restoreDocument( ItemDocument *itemDocument )
00886 {
00887 if ( !itemDocument )
00888 return;
00889
00890 ICNDocument *icnd = dynamic_cast<ICNDocument*>(itemDocument);
00891 FlowCodeDocument *fcd = dynamic_cast<FlowCodeDocument*>(icnd);
00892 if ( fcd && !m_microData.id.isEmpty() )
00893 {
00894 fcd->setPicType(m_microData.id);
00895 fcd->microSettings()->restoreFromMicroData(m_microData);
00896 }
00897
00898 mergeWithDocument(itemDocument,false);
00899
00900 {
00901 ItemList removeItems = itemDocument->itemList();
00902 removeItems.remove((Item*)0);
00903
00904 const ItemDataMap::iterator end = m_itemDataMap.end();
00905 for ( ItemDataMap::iterator it = m_itemDataMap.begin(); it != end; ++it )
00906 removeItems.remove( itemDocument->itemWithID(it.key()) );
00907
00908 const ItemList::iterator removeEnd = removeItems.end();
00909 for ( ItemList::iterator it = removeItems.begin(); it != removeEnd; ++it )
00910 {
00911 if ( (*it)->canvas() && (*it)->type() != PicItem::typeString() )
00912 (*it)->removeItem();
00913 }
00914 }
00915
00916 if (icnd)
00917 {
00918 {
00919 NodeList removeNodes = icnd->nodeList();
00920 removeNodes.remove((Node*)0);
00921
00922 const NodeDataMap::iterator end = m_nodeDataMap.end();
00923 for ( NodeDataMap::iterator it = m_nodeDataMap.begin(); it != end; ++it )
00924 removeNodes.remove( icnd->nodeWithID( it.key() ) );
00925
00926 const NodeList::iterator removeEnd = removeNodes.end();
00927 for ( NodeList::iterator it = removeNodes.begin(); it != removeEnd; ++it )
00928 {
00929 if ( (*it)->canvas() && !(*it)->isChildNode() )
00930 (*it)->removeNode();
00931 }
00932 }
00933 {
00934 ConnectorList removeConnectors = icnd->connectorList();
00935 removeConnectors.remove((Connector*)0);
00936
00937 const ConnectorDataMap::iterator end = m_connectorDataMap.end();
00938 for ( ConnectorDataMap::iterator it = m_connectorDataMap.begin(); it != end; ++it )
00939 removeConnectors.remove( icnd->connectorWithID(it.key()) );
00940
00941 const ConnectorList::iterator removeEnd = removeConnectors.end();
00942 for ( ConnectorList::iterator it = removeConnectors.begin(); it != removeEnd; ++it )
00943 {
00944 if ( (*it)->canvas() )
00945 (*it)->removeConnector();
00946 }
00947 }
00948 }
00949
00950 itemDocument->flushDeleteList();
00951 }
00952
00953
00954 void ItemDocumentData::mergeWithDocument( ItemDocument *itemDocument, bool selectNew )
00955 {
00956 if ( !itemDocument )
00957 return;
00958
00959 ICNDocument *icnd = dynamic_cast<ICNDocument*>(itemDocument);
00960
00961
00962 if (icnd)
00963 {
00964 const NodeDataMap::iterator nodeEnd = m_nodeDataMap.end();
00965 for ( NodeDataMap::iterator it = m_nodeDataMap.begin(); it != nodeEnd; ++it )
00966 {
00967 if ( !icnd->nodeWithID( it.key() ) )
00968 {
00969 QString id = it.key();
00970 if ( itemDocument->type() == Document::dt_circuit )
00971 new ECNode( icnd, Node::ec_junction, Node::dir_up, QPoint( int(it.data().x), int(it.data().y) ), &id );
00972
00973 else if ( itemDocument->type() == Document::dt_flowcode )
00974 new FPNode( icnd, Node::fp_junction, Node::dir_up, QPoint( int(it.data().x), int(it.data().y) ), &id );
00975 }
00976 }
00977 for ( NodeDataMap::iterator it = m_nodeDataMap.begin(); it != nodeEnd; ++it )
00978 {
00979 Node *node = icnd->nodeWithID( it.key() );
00980 if (node)
00981 node->move( it.data().x, it.data().y );
00982 }
00983 }
00984
00985
00986
00987
00988 const ItemDataMap::iterator itemEnd = m_itemDataMap.end();
00989 for ( ItemDataMap::iterator it = m_itemDataMap.begin(); it != itemEnd; ++it )
00990 {
00991 if ( !it.data().type.isEmpty() && !itemDocument->itemWithID( it.key() ) )
00992 {
00993 Item *item = itemLibrary()->createItem( it.data().type, itemDocument, false, it.key(), false );
00994 if ( item && !itemDocument->isValidItem(item) )
00995 {
00996 kdWarning() << "Attempted to create invalid item with id: " << it.key() << endl;
00997 item->removeItem();
00998 itemDocument->flushDeleteList();
00999 item = 0;
01000 }
01001 if (item)
01002 {
01003
01004
01005 item->move( it.data().x, it.data().y );
01006 }
01007 }
01008 }
01009 for ( ItemDataMap::iterator it = m_itemDataMap.begin(); it != itemEnd; ++it )
01010 {
01011 Item *item = itemDocument->itemWithID(it.key());
01012 if (!item)
01013 continue;
01014
01015 item->restoreFromItemData( it.data() );
01016 item->finishedCreation();
01017 if (selectNew)
01018 itemDocument->select(item);
01019 item->show();
01020 }
01021
01022
01023
01024 if (icnd)
01025 {
01026 const ConnectorDataMap::iterator connectorEnd = m_connectorDataMap.end();
01027 for ( ConnectorDataMap::iterator it = m_connectorDataMap.begin(); it != connectorEnd; ++it )
01028 {
01029 if ( icnd->connectorWithID( it.key() ) )
01030 continue;
01031
01032 QString id = it.key();
01033 Node *startNode = 0;
01034 Node *endNode = 0;
01035
01036 if ( it.data().startNodeIsChild )
01037 {
01038 CNItem *item = icnd->cnItemWithID( it.data().startNodeParent );
01039 if (!item)
01040 kdError() << k_funcinfo << "Unable to find node parent with id: "<<it.data().startNodeParent<<endl;
01041 else
01042 startNode = item->childNode( it.data().startNodeCId );
01043 }
01044 else
01045 startNode = icnd->nodeWithID( it.data().startNodeId );
01046
01047 if ( it.data().endNodeIsChild )
01048 {
01049 CNItem *item = icnd->cnItemWithID( it.data().endNodeParent );
01050 if (!item)
01051 kdError() << k_funcinfo << "Unable to find node parent with id: "<<it.data().endNodeParent<<endl;
01052 else
01053 endNode = item->childNode( it.data().endNodeCId );
01054 }
01055 else
01056 endNode = icnd->nodeWithID( it.data().endNodeId );
01057
01058 if ( !startNode || !endNode )
01059 {
01060 kdError() << k_funcinfo << "End and start nodes for the connector do not both exist" << endl;
01061 }
01062 else
01063 {
01064 Connector *connector = new Connector( startNode, endNode, icnd, &id );
01065
01066 startNode->addOutputConnector(connector);
01067 endNode->addInputConnector(connector);
01068 }
01069 }
01070 for ( ConnectorDataMap::iterator it = m_connectorDataMap.begin(); it != connectorEnd; ++it )
01071 {
01072 Connector *connector = icnd->connectorWithID( it.key() );
01073 if (connector)
01074 {
01075 connector->restoreFromConnectorData( it.data() );
01076 if (selectNew)
01077 icnd->select(connector);
01078 }
01079 }
01080 }
01081
01082
01083
01084 if ( FlowCodeDocument *fcd = dynamic_cast<FlowCodeDocument*>(itemDocument) )
01085 {
01086 const ItemList fcdItems = fcd->itemList();
01087 const ItemList::const_iterator fcdItemsEnd = fcdItems.constEnd();
01088 for ( ItemList::const_iterator it = fcdItems.constBegin(); it != fcdItemsEnd; ++it )
01089 {
01090 if ( FlowContainer * fc = dynamic_cast<FlowContainer*>((Item*)*it) )
01091 fc->updateContainedVisibility();
01092 }
01093 }
01094 }
01095
01096
01097 void ItemDocumentData::setMicroData( const MicroData &data )
01098 {
01099 m_microData = data;
01100 }
01101
01102
01103 void ItemDocumentData::addItems( const ItemList &itemList )
01104 {
01105 const ItemList::const_iterator end = itemList.constEnd();
01106 for ( ItemList::const_iterator it = itemList.constBegin(); it != end; ++it )
01107 {
01108 if ( *it && (*it)->canvas() && (*it)->type() != PicItem::typeString() )
01109 addItemData( (*it)->itemData(), (*it)->id() );
01110 }
01111 }
01112
01113
01114 void ItemDocumentData::addConnectors( const ConnectorList &connectorList )
01115 {
01116 const ConnectorList::const_iterator end = connectorList.constEnd();
01117 for ( ConnectorList::const_iterator it = connectorList.constBegin(); it != end; ++it )
01118 {
01119 if ( *it && (*it)->canvas() )
01120 {
01121 if ( (*it)->startNode() && (*it)->endNode() )
01122 addConnectorData( (*it)->connectorData(), (*it)->id() );
01123
01124 else
01125 kdDebug() << k_funcinfo << " *it="<<*it<<" (*it)->startNode()="<<(*it)->startNode()<<" (*it)->endNode()="<<(*it)->endNode()<<endl;
01126 }
01127 }
01128 }
01129
01130
01131 void ItemDocumentData::addNodes( const NodeList &nodeList )
01132 {
01133 const NodeList::const_iterator end = nodeList.constEnd();
01134 for ( NodeList::const_iterator it = nodeList.constBegin(); it != end; ++it )
01135 {
01136 if ( *it && (*it)->canvas() && !(*it)->isChildNode() )
01137 addNodeData( (*it)->nodeData(), (*it)->id() );
01138 }
01139 }
01140
01141
01142 void ItemDocumentData::addItemData( ItemData itemData, QString id )
01143 {
01144 m_itemDataMap[id] = itemData;
01145 }
01146
01147
01148 void ItemDocumentData::addConnectorData( ConnectorData connectorData, QString id )
01149 {
01150 m_connectorDataMap[id] = connectorData;
01151 }
01152
01153
01154 void ItemDocumentData::addNodeData( NodeData nodeData, QString id )
01155 {
01156 m_nodeDataMap[id] = nodeData;
01157 }
01158
01159
01160
01161
01162 ItemData::ItemData()
01163 {
01164 x = 0;
01165 y = 0;
01166 z = -1;
01167 angleDegrees = 0;
01168 flipped = false;
01169 orientation = -1;
01170 setSize = false;
01171 }
01172
01173
01174
01175
01176 ConnectorData::ConnectorData()
01177 {
01178 manualRoute = false;
01179 startNodeIsChild = false;
01180 endNodeIsChild = false;
01181 }
01182
01183
01184
01185
01186 NodeData::NodeData()
01187 {
01188 x = 0;
01189 y = 0;
01190 }
01191
01192
01193
01194
01195 PinData::PinData()
01196 {
01197 type = PinSettings::pt_input;
01198 state = PinSettings::ps_off;
01199 }
01200
01201
01202
01203
01204 MicroData::MicroData()