1 /*******************************************************************
2
3 Part of the Fritzing project - http://fritzing.org
4 Copyright (c) 2007-2014 Fachhochschule Potsdam - http://fh-potsdam.de
5
6 Fritzing is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Fritzing is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Fritzing. If not, see <http://www.gnu.org/licenses/>.
18
19 ********************************************************************
20
21 $Revision: 6956 $:
22 $Author: irascibl@gmail.com $:
23 $Date: 2013-04-07 12:14:50 +0200 (So, 07. Apr 2013) $
24
25 ********************************************************************/
26
27 #include "modelpart.h"
28 #include "../debugdialog.h"
29 #include "../connectors/connectorshared.h"
30 #include "../connectors/busshared.h"
31 #include "../connectors/bus.h"
32 #include "../version/version.h"
33 #include "../utils/folderutils.h"
34 #include "../utils/textutils.h"
35 #include "../items/itembase.h"
36 #include "../items/partfactory.h"
37
38 #include <QDomElement>
39 #include <QBitArray>
40
41 long ModelPart::m_nextIndex = 0;
42 const int ModelPart::indexMultiplier = 10;
43 QStringList ModelPart::m_possibleFolders;
44
45 typedef QHash<QString, ModelPartList*> InstanceTitleIncrementHash;
46 static QHash<QObject *, InstanceTitleIncrementHash *> AllInstanceTitleIncrements;
47 InstanceTitleIncrementHash NullInstanceTitleIncrements;
48
49 static const QRegExp InstanceTitleRegExp("^(.*[^\\d])(\\d+)$");
50
51 static const QList<ViewImage *> EmptyViewImages;
52
53 ////////////////////////////////////////
54
ModelPart(ItemType type)55 ModelPart::ModelPart(ItemType type)
56 : QObject()
57 {
58 commonInit(type);
59 m_modelPartShared = NULL;
60 m_index = m_nextIndex++;
61 }
62
ModelPart(QDomDocument & domDocument,const QString & path,ItemType type)63 ModelPart::ModelPart(QDomDocument & domDocument, const QString & path, ItemType type)
64 : QObject()
65 {
66 commonInit(type);
67 m_modelPartShared = new ModelPartShared(domDocument, path);
68 m_modelPartShared->addOwner(this);
69 }
70
commonInit(ItemType type)71 void ModelPart::commonInit(ItemType type) {
72 m_type = type;
73 m_locationFlags = 0;
74 m_indexSynched = false;
75 }
76
~ModelPart()77 ModelPart::~ModelPart() {
78 //DebugDialog::debug(QString("deleting modelpart %1 %2").arg((long) this, 0, 16).arg(m_index));
79
80 clearOldInstanceTitle(m_instanceTitle);
81
82 InstanceTitleIncrementHash * itih = AllInstanceTitleIncrements.value(this);
83 if (itih) {
84 AllInstanceTitleIncrements.remove(this);
85 foreach (ModelPartList * list, itih->values()) {
86 delete list;
87 }
88 delete itih;
89 }
90
91 foreach (Connector * connector, m_connectorHash.values()) {
92 delete connector;
93 }
94 m_connectorHash.clear();
95
96 clearBuses();
97 }
98
moduleID() const99 const QString & ModelPart::moduleID() const {
100 if (m_modelPartShared != NULL) return m_modelPartShared->moduleID();
101
102 return ___emptyString___;
103 }
104
label()105 const QString & ModelPart::label() {
106 if (m_modelPartShared != NULL) return m_modelPartShared->label();
107
108 return ___emptyString___;
109 }
110
author()111 const QString & ModelPart::author() {
112 if (m_modelPartShared != NULL) return m_modelPartShared->author();
113
114 return ___emptyString___;
115 }
116
taxonomy()117 const QString & ModelPart::taxonomy() {
118 if (m_modelPartShared != NULL) return m_modelPartShared->taxonomy();
119
120 return ___emptyString___;
121 }
122
uri()123 const QString & ModelPart::uri() {
124 if (m_modelPartShared != NULL) return m_modelPartShared->uri();
125
126 return ___emptyString___;
127 }
128
date()129 const QDate & ModelPart::date() {
130 if (m_modelPartShared != NULL) return m_modelPartShared->date();
131
132 static QDate tempDate;
133 tempDate = QDate::currentDate();
134 return tempDate;
135 }
136
setItemType(ItemType t)137 void ModelPart::setItemType(ItemType t) {
138 m_type = t;
139 }
140
copy(ModelPart * modelPart)141 void ModelPart::copy(ModelPart * modelPart) {
142 if (modelPart == NULL) return;
143
144 m_type = modelPart->itemType();
145 m_modelPartShared = modelPart->modelPartShared();
146 if (m_modelPartShared) m_modelPartShared->addOwner(this);
147 m_locationFlags = modelPart->m_locationFlags;
148 }
149
copyNew(ModelPart * modelPart)150 void ModelPart::copyNew(ModelPart * modelPart) {
151 copy(modelPart);
152 }
153
copyStuff(ModelPart * modelPart)154 void ModelPart::copyStuff(ModelPart * modelPart) {
155 modelPartShared()->copy(modelPart->modelPartShared());
156 }
157
modelPartShared()158 ModelPartShared * ModelPart::modelPartShared() {
159 if(!m_modelPartShared) {
160 m_modelPartShared = new ModelPartShared();
161 m_modelPartShared->addOwner(this);
162 }
163 return m_modelPartShared;
164 }
165
modelPartSharedRoot()166 ModelPartSharedRoot * ModelPart::modelPartSharedRoot() {
167 return qobject_cast<ModelPartSharedRoot *>(m_modelPartShared);
168 }
169
setModelPartShared(ModelPartShared * modelPartShared)170 void ModelPart::setModelPartShared(ModelPartShared * modelPartShared) {
171 m_modelPartShared = modelPartShared;
172 if (modelPartShared) m_modelPartShared->addOwner(this);
173 }
174
addViewItem(ItemBase * item)175 void ModelPart::addViewItem(ItemBase * item) {
176 m_viewItems.append(item);
177 }
178
removeViewItem(ItemBase * item)179 void ModelPart::removeViewItem(ItemBase * item) {
180 m_viewItems.removeOne(item);
181 }
182
viewItem(QGraphicsScene * scene)183 ItemBase * ModelPart::viewItem(QGraphicsScene * scene) {
184 foreach (ItemBase * itemBase, m_viewItems) {
185 if (itemBase->scene() == scene) return itemBase;
186 }
187
188 return NULL;
189 }
190
viewItem(ViewLayer::ViewID viewID)191 ItemBase * ModelPart::viewItem(ViewLayer::ViewID viewID) {
192 foreach (ItemBase * itemBase, m_viewItems) {
193 if (itemBase->viewID() == viewID) return itemBase;
194 }
195
196 return NULL;
197 }
198
saveInstances(const QString & fileName,QXmlStreamWriter & streamWriter,bool startDocument)199 void ModelPart::saveInstances(const QString & fileName, QXmlStreamWriter & streamWriter, bool startDocument) {
200 if (startDocument) {
201 streamWriter.writeStartDocument();
202 streamWriter.writeStartElement("module");
203 streamWriter.writeAttribute("fritzingVersion", Version::versionString());
204 ModelPartSharedRoot * root = modelPartSharedRoot();
205 if (root) {
206 if (!root->icon().isEmpty()) {
207 streamWriter.writeAttribute("icon", root->icon());
208 }
209 if (!root->searchTerm().isEmpty()) {
210 streamWriter.writeAttribute("search", root->searchTerm());
211 }
212 }
213 QString title = this->title();
214 if(!title.isNull() && !title.isEmpty()) {
215 streamWriter.writeTextElement("title",title);
216 }
217
218 emit startSaveInstances(fileName, this, streamWriter);
219
220 streamWriter.writeStartElement("instances");
221 }
222
223 if (parent() != NULL) { // m_viewItems.size() > 0
224 saveInstance(streamWriter);
225 }
226
227 QList<QObject *> children = this->children();
228 if(m_orderedChildren.count() > 0) {
229 children = m_orderedChildren;
230 }
231
232 QList<QObject *>::const_iterator i;
233 for (i = children.constBegin(); i != children.constEnd(); ++i) {
234 ModelPart* mp = qobject_cast<ModelPart *>(*i);
235 if (mp == NULL) continue;
236
237 mp->saveInstances(fileName, streamWriter, false);
238 }
239
240
241 if (startDocument) {
242 streamWriter.writeEndElement(); // instances
243 streamWriter.writeEndElement(); // module
244 streamWriter.writeEndDocument();
245 }
246 }
247
saveInstance(QXmlStreamWriter & streamWriter)248 void ModelPart::saveInstance(QXmlStreamWriter & streamWriter)
249 {
250 if (localProp("ratsnest").toBool()) {
251 return; // don't save virtual wires
252 }
253
254 streamWriter.writeStartElement("instance");
255 if (m_modelPartShared != NULL) {
256 QString moduleIdRef = m_modelPartShared->moduleID();
257 moduleIdRef.remove(PartFactory::OldSchematicPrefix);
258 streamWriter.writeAttribute("moduleIdRef", moduleIdRef);
259 streamWriter.writeAttribute("modelIndex", QString::number(m_index));
260 streamWriter.writeAttribute("path", m_modelPartShared->path());
261 if (m_modelPartShared->flippedSMD()) {
262 streamWriter.writeAttribute("flippedSMD", "true");
263 }
264 }
265
266 bool writeLocal = false;
267 foreach (Connector * connector, this->connectors()) {
268 if (!connector->connectorLocalName().isEmpty()) {
269 writeLocal = true;
270 break;
271 }
272 }
273
274 if (writeLocal) {
275 streamWriter.writeStartElement("localConnectors");
276 foreach (Connector * connector, this->connectors()) {
277 if (!connector->connectorLocalName().isEmpty()) {
278 streamWriter.writeStartElement("localConnector");
279 streamWriter.writeAttribute("id", connector->connectorSharedID());
280 streamWriter.writeAttribute("name", TextUtils::stripNonValidXMLCharacters(TextUtils::escapeAnd(connector->connectorLocalName())));
281 streamWriter.writeEndElement();
282 }
283 }
284 streamWriter.writeEndElement();
285 }
286
287 foreach (QByteArray byteArray, dynamicPropertyNames()) {
288 streamWriter.writeStartElement("property");
289 streamWriter.writeAttribute("name", byteArray.data());
290 streamWriter.writeAttribute("value", property(byteArray.data()).toString());
291 streamWriter.writeEndElement();
292 }
293
294 QString title = instanceTitle();
295 if(!title.isNull() && !title.isEmpty()) {
296 writeTag(streamWriter,"title",title);
297 }
298
299 QString text = instanceText();
300 if(!text.isNull() && !text.isEmpty()) {
301 streamWriter.writeStartElement("text");
302 streamWriter.writeCharacters(text);
303 streamWriter.writeEndElement();
304 }
305
306 // tell the views to write themselves out
307 streamWriter.writeStartElement("views");
308 foreach (ItemBase * itemBase, m_viewItems) {
309 itemBase->saveInstance(streamWriter);
310 }
311 streamWriter.writeEndElement(); // views
312 streamWriter.writeEndElement(); //instance
313 }
314
writeTag(QXmlStreamWriter & streamWriter,QString tagName,QString tagValue)315 void ModelPart::writeTag(QXmlStreamWriter & streamWriter, QString tagName, QString tagValue) {
316 if(!tagValue.isEmpty()) {
317 streamWriter.writeTextElement(tagName,tagValue);
318 }
319 }
320
writeNestedTag(QXmlStreamWriter & streamWriter,QString tagName,const QStringList & values,QString childTag)321 void ModelPart::writeNestedTag(QXmlStreamWriter & streamWriter, QString tagName, const QStringList &values, QString childTag) {
322 if(values.count() > 0) {
323 streamWriter.writeStartElement(tagName);
324 for(int i=0; i<values.count(); i++) {
325 writeTag(streamWriter, childTag, values[i]);
326 }
327 streamWriter.writeEndElement();
328 }
329 }
330
writeNestedTag(QXmlStreamWriter & streamWriter,QString tagName,const QHash<QString,QString> & values,QString childTag,QString attrName)331 void ModelPart::writeNestedTag(QXmlStreamWriter & streamWriter, QString tagName, const QHash<QString,QString> &values, QString childTag, QString attrName) {
332 streamWriter.writeStartElement(tagName);
333 for(int i=0; i<values.keys().count(); i++) {
334 streamWriter.writeStartElement(childTag);
335 QString key = values.keys()[i];
336 streamWriter.writeAttribute(attrName,key);
337 streamWriter.writeCharacters(values[key]);
338 streamWriter.writeEndElement();
339 }
340 streamWriter.writeEndElement();
341 }
342
saveAsPart(QXmlStreamWriter & streamWriter,bool startDocument)343 void ModelPart::saveAsPart(QXmlStreamWriter & streamWriter, bool startDocument) {
344 if (startDocument) {
345 streamWriter.writeStartDocument();
346 streamWriter.writeStartElement("module");
347 streamWriter.writeAttribute("fritzingVersion", Version::versionString());
348 QString moduleID = m_modelPartShared->moduleID();
349 moduleID.remove(PartFactory::OldSchematicPrefix);
350 streamWriter.writeAttribute("moduleId", moduleID);
351 writeTag(streamWriter,"version",m_modelPartShared->version());
352 writeTag(streamWriter,"author",m_modelPartShared->author());
353 writeTag(streamWriter,"title",title());
354 writeTag(streamWriter,"label",m_modelPartShared->label());
355 writeTag(streamWriter,"date",m_modelPartShared->dateAsStr());
356
357 writeNestedTag(streamWriter,"tags",m_modelPartShared->tags(),"tag");
358 writeNestedTag(streamWriter,"properties",m_modelPartShared->properties(),"property","name");
359
360 writeTag(streamWriter,"taxonomy",m_modelPartShared->taxonomy());
361 writeTag(streamWriter,"description",m_modelPartShared->description());
362
363 QString spice = m_modelPartShared->spice();
364 if (!spice.isEmpty()) {
365 streamWriter.writeStartElement("spice");
366 QStringList lines = spice.split("\r",QString::SkipEmptyParts);
367 foreach (QString line, lines) {
368 writeTag(streamWriter, "line", line);
369 }
370 QString spiceModel = m_modelPartShared->spiceModel();
371 if (!spiceModel.isEmpty()) {
372 lines = spiceModel.split("\r",QString::SkipEmptyParts);
373 foreach (QString line, lines) {
374 writeTag(streamWriter, "model", line);
375 }
376 }
377 streamWriter.writeEndElement();
378 }
379
380
381 writeTag(streamWriter,"spice",m_modelPartShared->spice());
382 writeTag(streamWriter,"url",m_modelPartShared->url());
383 }
384
385 if (m_viewItems.size() > 0) {
386 if (startDocument) {
387 streamWriter.writeStartElement("views");
388 }
389 for (int i = 0; i < m_viewItems.size(); i++) {
390 ItemBase * item = m_viewItems[i];
391 item->writeXml(streamWriter);
392 }
393
394 if(startDocument) {
395 streamWriter.writeEndElement();
396 }
397
398 streamWriter.writeStartElement("connectors");
399 const QList< QPointer<ConnectorShared> > connectors = m_modelPartShared->connectorsShared();
400 for (int i = 0; i < connectors.count(); i++) {
401 Connector * connector = new Connector(connectors[i], this);
402 connector->saveAsPart(streamWriter);
403 delete connector;
404 }
405 streamWriter.writeEndElement();
406 }
407
408 QList<QObject *>::const_iterator i;
409 for (i = children().constBegin(); i != children().constEnd(); ++i) {
410 ModelPart * mp = qobject_cast<ModelPart *>(*i);
411 if (mp == NULL) continue;
412
413 mp->saveAsPart(streamWriter, false);
414 }
415
416 if (startDocument) {
417 streamWriter.writeEndElement();
418 streamWriter.writeEndElement();
419 streamWriter.writeEndDocument();
420 }
421 }
422
initConnectors(bool force)423 void ModelPart::initConnectors(bool force) {
424 if(m_modelPartShared == NULL) return;
425
426 if(force) {
427 foreach (Connector * connector, m_connectorHash.values()) {
428 // due to craziness in the parts editor
429 // m_deletedConnectors.append(connector);
430 delete connector;
431 }
432 m_connectorHash.clear();
433 clearBuses();
434 }
435 if(m_connectorHash.count() > 0) return; // already done
436
437 m_modelPartShared->initConnectors();
438 foreach (ConnectorShared * connectorShared, m_modelPartShared->connectorsShared()) {
439 Connector * connector = new Connector(connectorShared, this);
440 m_connectorHash.insert(connectorShared->id(), connector);
441 }
442 initBuses();
443 }
444
clearBuses()445 void ModelPart::clearBuses() {
446 foreach (Bus * bus, m_busHash.values()) {
447 delete bus;
448 }
449 m_busHash.clear();
450 }
451
initBuses()452 void ModelPart::initBuses() {
453 foreach (Connector * connector, m_connectorHash.values()) {
454 BusShared * busShared = connector->connectorShared()->bus();
455 if (busShared != NULL) {
456 Bus * bus = m_busHash.value(busShared->id());
457 if (bus == NULL) {
458 bus = new Bus(busShared, this);
459 m_busHash.insert(busShared->id(), bus);
460 }
461 connector->setBus(bus);
462 bus->addConnector(connector);
463 }
464 }
465 }
466
connectors()467 const QHash<QString, QPointer<Connector> > & ModelPart::connectors() {
468 return m_connectorHash;
469 }
470
modelIndex()471 long ModelPart::modelIndex() {
472 return m_index;
473 }
474
setModelIndex(long index)475 void ModelPart::setModelIndex(long index) {
476 m_index = index;
477 updateIndex(index);
478 }
479
setModelIndexFromMultiplied(long multiplied)480 void ModelPart::setModelIndexFromMultiplied(long multiplied) {
481 if (m_indexSynched) {
482 // this is gross. m_index should always be itemBase->id() / ModelPart::indexMultiplier
483 // but sometimes multiple parts reuse the same model part, so this makes sure we don't overwrite
484 // when temporarily reusing a modelpart. Eventually always create a new model part and get rid of modelIndex
485 if (m_index != multiplied / ModelPart::indexMultiplier) {
486 //DebugDialog::debug("temporary model part?");
487 }
488
489 return;
490 }
491
492 m_indexSynched = true;
493 setModelIndex(multiplied / ModelPart::indexMultiplier);
494 }
495
updateIndex(long index)496 void ModelPart::updateIndex(long index)
497 {
498 if (index >= m_nextIndex) {
499 m_nextIndex = index + 1;
500 }
501 }
502
nextIndex()503 long ModelPart::nextIndex() {
504 return m_nextIndex++;
505 }
506
setInstanceDomElement(const QDomElement & domElement)507 void ModelPart::setInstanceDomElement(const QDomElement & domElement) {
508 //DebugDialog::debug(QString("model part instance %1").arg((long) this, 0, 16));
509 m_instanceDomElement = domElement;
510 }
511
instanceDomElement()512 const QDomElement & ModelPart::instanceDomElement() {
513 return m_instanceDomElement;
514 }
515
fritzingVersion()516 const QString & ModelPart::fritzingVersion() {
517
518 if (m_modelPartShared != NULL) return m_modelPartShared->fritzingVersion();
519
520 return ___emptyString___;
521 }
522
title()523 const QString & ModelPart::title() {
524 if (!m_localTitle.isEmpty()) return m_localTitle;
525
526 if (m_modelPartShared != NULL) return m_modelPartShared->title();
527
528 return m_localTitle;
529 }
530
setLocalTitle(const QString & localTitle)531 void ModelPart::setLocalTitle(const QString & localTitle) {
532 m_localTitle = localTitle;
533 }
534
version()535 const QString & ModelPart::version() {
536 if (m_modelPartShared != NULL) return m_modelPartShared->version();
537
538 return ___emptyString___;
539 }
540
path()541 const QString & ModelPart::path() {
542 if (m_modelPartShared != NULL) return m_modelPartShared->path();
543
544 return ___emptyString___;
545 }
546
description()547 const QString & ModelPart::description() {
548 if (m_modelPartShared != NULL) return m_modelPartShared->description();
549
550 return ___emptyString___;
551 }
552
spice()553 const QString & ModelPart::spice() {
554 if (m_modelPartShared != NULL) return m_modelPartShared->spice();
555
556 return ___emptyString___;
557 }
558
spiceModel()559 const QString & ModelPart::spiceModel() {
560 if (m_modelPartShared != NULL) return m_modelPartShared->spiceModel();
561
562 return ___emptyString___;
563 }
564
url()565 const QString & ModelPart::url() {
566 if (m_modelPartShared != NULL) return m_modelPartShared->url();
567
568 return ___emptyString___;
569 }
570
tags()571 const QStringList & ModelPart::tags() {
572 if (m_modelPartShared != NULL) return m_modelPartShared->tags();
573
574 return ___emptyStringList___;
575 }
576
properties() const577 const QHash<QString,QString> & ModelPart::properties() const {
578 if (m_modelPartShared != NULL) return m_modelPartShared->properties();
579
580 return ___emptyStringHash___;
581 }
582
getConnector(const QString & id)583 Connector * ModelPart::getConnector(const QString & id) {
584 return m_connectorHash.value(id);
585 }
586
buses()587 const QHash<QString, QPointer<Bus> > & ModelPart::buses() {
588 return m_busHash;
589 }
590
bus(const QString & busID)591 Bus * ModelPart::bus(const QString & busID) {
592 return m_busHash.value(busID);
593 }
594
ignoreTerminalPoints()595 bool ModelPart::ignoreTerminalPoints() {
596 if (m_modelPartShared != NULL) return m_modelPartShared->ignoreTerminalPoints();
597
598 return true;
599 }
600
isCore()601 bool ModelPart::isCore() {
602 return (m_locationFlags & CoreFlag) != 0;
603 }
604
setCore(bool core)605 void ModelPart::setCore(bool core) {
606 setLocationFlag(core, CoreFlag);
607 }
608
isContrib()609 bool ModelPart::isContrib() {
610 return (m_locationFlags & ContribFlag) != 0;
611 }
612
setContrib(bool contrib)613 void ModelPart::setContrib(bool contrib) {
614 setLocationFlag(contrib, ContribFlag);
615 }
616
isAlien()617 bool ModelPart::isAlien() {
618 return (m_locationFlags & AlienFlag) != 0;;
619 }
620
setAlien(bool alien)621 void ModelPart::setAlien(bool alien) {
622 setLocationFlag(alien, AlienFlag);
623 }
isInBin()624 bool ModelPart::isInBin() {
625 return (m_locationFlags & InBinFlag) != 0;;
626 }
627
setInBin(bool inBin)628 void ModelPart::setInBin(bool inBin) {
629 setLocationFlag(inBin, InBinFlag);
630 }
631
isFzz()632 bool ModelPart::isFzz() {
633 return (m_locationFlags & FzzFlag) != 0;;
634 }
635
setFzz(bool fzz)636 void ModelPart::setFzz(bool fzz) {
637 setLocationFlag(fzz, FzzFlag);
638 }
639
setLocationFlag(bool setting,LocationFlag flag)640 void ModelPart::setLocationFlag(bool setting, LocationFlag flag) {
641 if (setting) {
642 m_locationFlags |= flag;
643 }
644 else {
645 m_locationFlags &= ~flag;
646 }
647 }
648
hasViewID(ViewLayer::ViewID viewID)649 bool ModelPart::hasViewID(ViewLayer::ViewID viewID) {
650 if (m_modelPartShared) return m_modelPartShared->hasViewID(viewID);
651
652 return false;
653
654 }
655
canFlipVertical(ViewLayer::ViewID viewID)656 bool ModelPart::canFlipVertical(ViewLayer::ViewID viewID) {
657 if (m_modelPartShared) return m_modelPartShared->canFlipVertical(viewID);
658
659 return false;
660
661 }
662
canFlipHorizontal(ViewLayer::ViewID viewID)663 bool ModelPart::canFlipHorizontal(ViewLayer::ViewID viewID) {
664 if (m_modelPartShared) return m_modelPartShared->canFlipHorizontal(viewID);
665
666 return false;
667 }
668
viewLayers(ViewLayer::ViewID viewID)669 LayerList ModelPart::viewLayers(ViewLayer::ViewID viewID) {
670 if (m_modelPartShared) return m_modelPartShared->viewLayers(viewID);
671
672 LayerList layerList;
673 return layerList;
674 }
675
imageFileName(ViewLayer::ViewID viewID)676 QString ModelPart::imageFileName(ViewLayer::ViewID viewID) {
677 if (m_modelPartShared) return m_modelPartShared->imageFileName(viewID);
678
679 return "";
680 }
681
imageFileName(ViewLayer::ViewID viewID,ViewLayer::ViewLayerID viewLayerID)682 QString ModelPart::imageFileName(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) {
683 if (m_modelPartShared) return m_modelPartShared->imageFileName(viewID, viewLayerID);
684
685 return "";
686 }
687
anySticky(ViewLayer::ViewID viewID)688 bool ModelPart::anySticky(ViewLayer::ViewID viewID) {
689 if (m_modelPartShared) return m_modelPartShared->anySticky(viewID);
690
691 return false;
692 }
693
getAllParts()694 QList<ModelPart*> ModelPart::getAllParts() {
695 QList<ModelPart*> retval;
696 QList<QObject *>::const_iterator i;
697 for (i = children().constBegin(); i != children().constEnd(); ++i) {
698 ModelPart* mp = qobject_cast<ModelPart *>(*i);
699 if (mp == NULL) continue;
700 retval << mp;
701 }
702
703 return retval;
704 }
705
getAllNonCoreParts()706 QList<ModelPart*> ModelPart::getAllNonCoreParts() {
707 QList<ModelPart*> retval;
708 QList<QObject *>::const_iterator i;
709 for (i = children().constBegin(); i != children().constEnd(); ++i) {
710 ModelPart* mp = qobject_cast<ModelPart *>(*i);
711 if (mp == NULL) continue;
712
713 if(!mp->isCore()) {
714 retval << mp;
715 }
716 }
717
718 return retval;
719 }
720
hasViewID(long id)721 bool ModelPart::hasViewID(long id) {
722 foreach (ItemBase * item, m_viewItems) {
723 if (item->id() == id) return true;
724 }
725
726 return false;
727 }
728
instanceTitle() const729 const QString & ModelPart::instanceTitle() const {
730 return m_instanceTitle;
731 }
732
instanceText()733 const QString & ModelPart::instanceText() {
734 return m_instanceText;
735 }
736
setInstanceText(QString text)737 void ModelPart::setInstanceText(QString text) {
738 m_instanceText = text;
739 }
740
clearOldInstanceTitle(const QString & title)741 void ModelPart::clearOldInstanceTitle(const QString & title)
742 {
743 InstanceTitleIncrementHash * itih = NULL;
744 if (parent() == NULL) {
745 itih = &NullInstanceTitleIncrements;
746 }
747 else {
748 itih = AllInstanceTitleIncrements.value(parent(), NULL);
749 }
750
751 if (itih == NULL) return;
752
753 //DebugDialog::debug(QString("clearing title:%1 ix:%2").arg(title).arg(modelPart->modelIndex()));
754 QString prefix = title;
755 int ix = InstanceTitleRegExp.indexIn(title);
756 if (ix >= 0) {
757 prefix = InstanceTitleRegExp.cap(1);
758 }
759 ModelPartList * modelParts = itih->value(prefix, NULL);
760 if (modelParts) {
761 modelParts->removeOne(this);
762 //DebugDialog::debug(QString("\tc:%1").arg(modelParts->count()));
763 }
764 }
765
ensureInstanceTitleIncrements(const QString & prefix)766 ModelPartList * ModelPart::ensureInstanceTitleIncrements(const QString & prefix)
767 {
768 InstanceTitleIncrementHash * itih = NULL;
769 if (parent() == NULL) {
770 itih = &NullInstanceTitleIncrements;
771 }
772 else {
773 itih = AllInstanceTitleIncrements.value(parent(), NULL);
774 if (itih == NULL) {
775 itih = new InstanceTitleIncrementHash;
776 AllInstanceTitleIncrements.insert(parent(), itih);
777 }
778 }
779
780 ModelPartList * modelParts = itih->value(prefix, NULL);
781 if (modelParts == NULL) {
782 modelParts = new ModelPartList;
783 itih->insert(prefix, modelParts);
784 }
785 return modelParts;
786 }
787
setInstanceTitle(QString title,bool initial)788 void ModelPart::setInstanceTitle(QString title, bool initial) {
789 if (initial) {
790 if (setSubpartInstanceTitle()) return;
791 }
792
793 if (title.compare(m_instanceTitle) == 0) return;
794
795 clearOldInstanceTitle(m_instanceTitle);
796
797 m_instanceTitle = title;
798
799 QString prefix = title;
800 int ix = InstanceTitleRegExp.indexIn(title);
801 if (ix >= 0) {
802 prefix = InstanceTitleRegExp.cap(1);
803 ModelPartList * modelParts = ensureInstanceTitleIncrements(prefix);
804 modelParts->append(this);
805 }
806 //DebugDialog::debug(QString("adding title:%1 ix:%2 c:%3").arg(title).arg(modelIndex()).arg(modelParts->count()));
807
808 if (m_modelPartShared && m_modelPartShared->hasSubparts()) {
809 if (m_viewItems.count() > 0) {
810 ItemBase * itemBase = m_viewItems.last();
811 if (itemBase) {
812 foreach (ItemBase * subpart, itemBase->subparts()) {
813 subpart->setInstanceTitle("", true); // will end up calling setSubpartInstanceTitle()
814 }
815 }
816 }
817 }
818 }
819
setSubpartInstanceTitle()820 bool ModelPart::setSubpartInstanceTitle() {
821 if (m_modelPartShared == NULL) return false;
822 if (m_modelPartShared->superpart() == NULL) return false;
823 if (m_viewItems.count() <= 0) return false;
824
825 ItemBase * itemBase = m_viewItems.last();
826 if (itemBase == NULL) return false;
827
828 itemBase = itemBase->superpart();
829 if (itemBase == NULL) return false;
830
831 QString superTitle = itemBase->instanceTitle();
832 if (superTitle.isEmpty()) return false;
833
834 QString label = m_modelPartShared->label();
835 if (label.isEmpty()) return false;
836
837 m_instanceTitle = superTitle + "_" + label;
838 return true;
839 }
840
getNextTitle(const QString & title)841 QString ModelPart::getNextTitle(const QString & title) {
842 QString prefix = title;
843 int ix = InstanceTitleRegExp.indexIn(title);
844 if (ix >= 0) {
845 prefix = InstanceTitleRegExp.cap(1);
846 }
847 else {
848 bool allDigits = true;
849 foreach (QChar c, title) {
850 if (!c.isDigit()) {
851 allDigits = false;
852 break;
853 }
854 }
855 if (allDigits) {
856 return title;
857 }
858 }
859
860 // TODO: if this were a sorted list,
861 ModelPartList * modelParts = ensureInstanceTitleIncrements(prefix);
862 int highestSoFar = 0;
863 bool gotNull = false;
864 foreach (ModelPart * modelPart, *modelParts) {
865 if (modelPart == NULL) {
866 gotNull = true;
867 continue;
868 }
869
870 QString title = modelPart->instanceTitle();
871 title.remove(0, prefix.length());
872 int count = title.toInt(); // returns zero on failure
873 if (count > highestSoFar) {
874 highestSoFar = count;
875 }
876 }
877
878 if (gotNull) {
879 modelParts->removeAll(NULL);
880 }
881
882 //DebugDialog::debug(QString("returning increment %1, %2").arg(prefix).arg(highestSoFar + 1));
883 return QString("%1%2").arg(prefix).arg(highestSoFar + 1);
884 }
885
setOrderedChildren(QList<QObject * > children)886 void ModelPart::setOrderedChildren(QList<QObject*> children) {
887 m_orderedChildren = children;
888 }
889
setLocalProp(const char * name,const QVariant & value)890 void ModelPart::setLocalProp(const char * name, const QVariant & value) {
891 //DebugDialog::debug(QString("mp set prop %1 %2").arg(name).arg(value.toString()));
892 QObject::setProperty(name, value);
893 }
894
localProp(const char * name) const895 QVariant ModelPart::localProp(const char * name) const {
896 return property(name);
897 }
898
setLocalProp(const QString & name,const QVariant & value)899 void ModelPart::setLocalProp(const QString & name, const QVariant & value) {
900 QByteArray b = name.toLatin1();
901 setLocalProp(b.data(), value);
902 }
903
localProp(const QString & name) const904 QVariant ModelPart::localProp(const QString & name) const {
905 QByteArray b = name.toLatin1();
906 return localProp(b.data());
907 }
908
possibleFolders()909 const QStringList & ModelPart::possibleFolders() {
910 if (m_possibleFolders.count() == 0) {
911 m_possibleFolders << "core" << "obsolete" << "contrib" << "user";
912 }
913
914 return m_possibleFolders;
915 }
916
replacedby()917 const QString & ModelPart::replacedby() {
918 if (m_modelPartShared != NULL) return m_modelPartShared->replacedby();
919
920 return ___emptyString___;
921 }
922
isObsolete()923 bool ModelPart::isObsolete() {
924 if (m_modelPartShared != NULL) return !m_modelPartShared->replacedby().isEmpty();
925
926 return false;
927 }
928
flippedSMD()929 bool ModelPart::flippedSMD() {
930 if (m_modelPartShared != NULL) {
931 return m_modelPartShared->flippedSMD();
932 }
933
934 return false;
935 }
936
needsCopper1()937 bool ModelPart::needsCopper1() {
938 if (m_modelPartShared != NULL) {
939 return m_modelPartShared->needsCopper1();
940 }
941
942 return false;
943 }
944
hasViewFor(ViewLayer::ViewID viewID)945 bool ModelPart::hasViewFor(ViewLayer::ViewID viewID) {
946 if (m_modelPartShared == NULL) return false;
947
948 return m_modelPartShared->hasViewFor(viewID);
949 }
950
hasViewFor(ViewLayer::ViewID viewID,ViewLayer::ViewLayerID viewLayerID)951 bool ModelPart::hasViewFor(ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID) {
952 if (m_modelPartShared == NULL) return false;
953
954 return m_modelPartShared->hasViewFor(viewID, viewLayerID);
955 }
956
hasBaseNameFor(ViewLayer::ViewID viewID)957 QString ModelPart::hasBaseNameFor(ViewLayer::ViewID viewID) {
958 if (m_modelPartShared == NULL) return ___emptyString___;
959
960 return m_modelPartShared->hasBaseNameFor(viewID);
961 }
962
displayKeys()963 const QStringList & ModelPart::displayKeys() {
964 if (m_modelPartShared == NULL) return ___emptyStringList___;
965
966 return m_modelPartShared->displayKeys();
967 }
968
itemType() const969 ModelPart::ItemType ModelPart::itemType() const
970 {
971 return m_type;
972 };
973
setConnectorLocalName(const QString & id,const QString & name)974 void ModelPart::setConnectorLocalName(const QString & id, const QString & name)
975 {
976 if (id.isEmpty()) return;
977 Connector * connector = m_connectorHash.value(id, NULL);
978 if (connector) {
979 connector->setConnectorLocalName(name);
980 }
981 }
982
connectorLocalName(const QString & id)983 QString ModelPart::connectorLocalName(const QString & id)
984 {
985 if (id.isEmpty()) return "";
986
987 Connector * connector = m_connectorHash.value(id, NULL);
988 if (connector) {
989 return connector->connectorLocalName();
990 }
991
992 return "";
993 }
994
family()995 QString ModelPart::family(){
996 if (m_modelPartShared) return m_modelPartShared->family();
997
998 return "";
999 }
1000
hasViewItems()1001 bool ModelPart::hasViewItems() {
1002 return (m_viewItems.count() > 0);
1003 }
1004
setDBID(qulonglong dbid)1005 void ModelPart::setDBID(qulonglong dbid) {
1006 if (m_modelPartShared) m_modelPartShared->setDBID(dbid);
1007 }
1008
dbid()1009 qulonglong ModelPart::dbid() {
1010 if (m_modelPartShared) return m_modelPartShared->dbid();
1011
1012 return 0;
1013 }
1014
viewImages()1015 const QList<ViewImage *> ModelPart::viewImages() {
1016 if (m_modelPartShared) return m_modelPartShared->viewImages();
1017
1018 return EmptyViewImages;
1019 }
1020
setViewImage(ViewImage * viewImage)1021 void ModelPart::setViewImage(ViewImage * viewImage) {
1022 if (m_modelPartShared) m_modelPartShared->setViewImage(viewImage);
1023 }
1024
setTag(const QString & tag)1025 void ModelPart::setTag(const QString & tag)
1026 {
1027 if (m_modelPartShared) m_modelPartShared->setTag(tag);
1028 }
1029
setProperty(const QString & name,const QString & value,bool showInLabel)1030 void ModelPart::setProperty(const QString & name, const QString &value, bool showInLabel)
1031 {
1032 if (m_modelPartShared) m_modelPartShared->setProperty(name, value, showInLabel);
1033 }
1034
showInLabel(const QString & propertyName)1035 bool ModelPart::showInLabel(const QString & propertyName) {
1036 if (m_modelPartShared) return m_modelPartShared->showInLabel(propertyName);
1037
1038 return false;
1039 }
1040
addConnector(Connector * connector)1041 void ModelPart::addConnector(Connector * connector) {
1042 m_connectorHash.insert(connector->connectorSharedID(), connector);
1043
1044 if (m_modelPartShared) m_modelPartShared->addConnector(connector->connectorShared());
1045 }
1046
flipSMDAnd()1047 void ModelPart::flipSMDAnd() {
1048 if (m_modelPartShared) m_modelPartShared->flipSMDAnd();
1049 }
1050
setImageFileName(ViewLayer::ViewID viewID,const QString & filename)1051 void ModelPart::setImageFileName(ViewLayer::ViewID viewID, const QString & filename) {
1052 if (m_modelPartShared) m_modelPartShared->setImageFileName(viewID, filename);
1053 }
1054
lookForZeroConnector()1055 void ModelPart::lookForZeroConnector() {
1056 if (m_modelPartShared) m_modelPartShared->lookForZeroConnector();
1057 }
1058
hasZeroConnector()1059 bool ModelPart::hasZeroConnector() {
1060 if (m_modelPartShared) return m_modelPartShared->hasZeroConnector();
1061
1062 return false;
1063 }
1064
killViewItems()1065 void ModelPart::killViewItems() {
1066 foreach (ItemBase * itemBase, m_viewItems) {
1067 if (itemBase) delete itemBase;
1068 }
1069
1070 m_viewItems.clear();
1071 }
1072
hasSubparts()1073 bool ModelPart::hasSubparts() {
1074 if (m_modelPartShared) return m_modelPartShared->hasSubparts();
1075
1076 return false;
1077 }
1078
setSubpartID(const QString & id)1079 void ModelPart::setSubpartID(const QString & id) {
1080 if (m_modelPartShared) m_modelPartShared->setSubpartID(id);
1081 }
1082