1 /*******************************************************************
2
3 Part of the Fritzing project - http://fritzing.org
4 Copyright (c) 2007-2015 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: 6998 $:
22 $Author: irascibl@gmail.com $:
23 $Date: 2013-04-28 13:51:10 +0200 (So, 28. Apr 2013) $
24
25 ********************************************************************/
26
27
28 #include "itembase.h"
29 #include "partfactory.h"
30 #include "../debugdialog.h"
31 #include "../model/modelpart.h"
32 #include "../connectors/connectoritem.h"
33 #include "../connectors/connectorshared.h"
34 #include "../sketch/infographicsview.h"
35 #include "../connectors/connector.h"
36 #include "../connectors/bus.h"
37 #include "partlabel.h"
38 #include "../layerattributes.h"
39 #include "../fsvgrenderer.h"
40 #include "../svg/svgfilesplitter.h"
41 #include "../svg/svgflattener.h"
42 #include "../utils/folderutils.h"
43 #include "../utils/textutils.h"
44 #include "../utils/graphicsutils.h"
45 #include "../utils/cursormaster.h"
46 #include "../utils/clickablelabel.h"
47 #include "../utils/familypropertycombobox.h"
48 #include "../referencemodel/referencemodel.h"
49
50 #include <QScrollBar>
51 #include <QTimer>
52 #include <QVector>
53 #include <QSet>
54 #include <QSettings>
55 #include <QComboBox>
56 #include <QBitmap>
57 #include <QApplication>
58 #include <QClipboard>
59 #include <qmath.h>
60
61 /////////////////////////////////
62
63 static QRegExp NumberMatcher;
64 static QHash<QString, double> NumberMatcherValues;
65
66 static const double InactiveOpacity = 0.4;
67
numberValueLessThan(QString v1,QString v2)68 bool numberValueLessThan(QString v1, QString v2)
69 {
70 return NumberMatcherValues.value(v1, 0) <= NumberMatcherValues.value(v2, 0);
71 }
72
73 static QSvgRenderer MoveLockRenderer;
74 static QSvgRenderer StickyRenderer;
75
76 /////////////////////////////////
77
78 class NameTriple {
79
80 public:
NameTriple(const QString & _xmlName,const QString & _viewName,const QString & _naturalName)81 NameTriple(const QString & _xmlName, const QString & _viewName, const QString & _naturalName) {
82 m_xmlName = _xmlName;
83 m_viewName = _viewName;
84 m_naturalName = _naturalName;
85 }
86
xmlName()87 QString & xmlName() {
88 return m_xmlName;
89 }
90
viewName()91 QString & viewName() {
92 return m_viewName;
93 }
94
naturalName()95 QString & naturalName() {
96 return m_naturalName;
97 }
98
99 protected:
100 QString m_xmlName;
101 QString m_naturalName;
102 QString m_viewName;
103 };
104
105 /////////////////////////////////
106
107 const QString ItemBase::ITEMBASE_FONT_PREFIX = "<font size='2'>";
108 const QString ItemBase::ITEMBASE_FONT_SUFFIX = "</font>";
109
110 QHash<QString, QString> ItemBase::TranslatedPropertyNames;
111
112 QPointer<ReferenceModel> ItemBase::TheReferenceModel = NULL;
113
114 QString ItemBase::PartInstanceDefaultTitle;
115 const QList<ItemBase *> ItemBase::EmptyList;
116
117 const QColor ItemBase::HoverColor(0,0,0);
118 const double ItemBase::HoverOpacity = .20;
119 const QColor ItemBase::ConnectorHoverColor(0,0,255);
120 const double ItemBase::ConnectorHoverOpacity = .40;
121
122 const QColor StandardConnectedColor(0, 255, 0);
123 const QColor StandardUnconnectedColor(255, 0, 0);
124
125 QPen ItemBase::NormalPen(QColor(255,0,0));
126 QPen ItemBase::HoverPen(QColor(0, 0, 255));
127 QPen ItemBase::ConnectedPen(StandardConnectedColor);
128 QPen ItemBase::UnconnectedPen(StandardUnconnectedColor);
129 QPen ItemBase::ChosenPen(QColor(255,0,0));
130 QPen ItemBase::EqualPotentialPen(QColor(255,255,0));
131
132 QBrush ItemBase::NormalBrush(QColor(255,0,0));
133 QBrush ItemBase::HoverBrush(QColor(0,0,255));
134 QBrush ItemBase::ConnectedBrush(StandardConnectedColor);
135 QBrush ItemBase::UnconnectedBrush(StandardUnconnectedColor);
136 QBrush ItemBase::ChosenBrush(QColor(255,0,0));
137 QBrush ItemBase::EqualPotentialBrush(QColor(255,255,0));
138
139 const double ItemBase::NormalConnectorOpacity = 0.4;
140
141 static QHash<QString, QStringList> CachedValues;
142
143 ///////////////////////////////////////////////////
144
ItemBase(ModelPart * modelPart,ViewLayer::ViewID viewID,const ViewGeometry & viewGeometry,long id,QMenu * itemMenu)145 ItemBase::ItemBase( ModelPart* modelPart, ViewLayer::ViewID viewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu )
146 : QGraphicsSvgItem()
147 {
148 m_fsvgRenderer = NULL;
149 m_superpart = NULL;
150 m_acceptsMousePressLegEvent = true;
151
152 m_squashShape = false;
153
154 //DebugDialog::debug(QString("itembase %1 %2").arg(id).arg((long) static_cast<QGraphicsItem *>(this), 0, 16));
155 m_hasRubberBandLeg = m_moveLock = m_hoverEnterSpaceBarWasPressed = m_spaceBarWasPressed = false;
156
157 m_moveLockItem = NULL;
158 m_stickyItem = NULL;
159
160 m_swappable = m_everVisible = true;
161
162 m_rightClickedConnector = NULL;
163
164 m_partLabel = NULL;
165 m_itemMenu = itemMenu;
166 m_hoverCount = m_connectorHoverCount = m_connectorHoverCount2 = 0;
167 m_viewID = viewID;
168 m_modelPart = modelPart;
169 if (m_modelPart) {
170 m_modelPart->addViewItem(this);
171 }
172 m_id = id;
173 m_canFlipHorizontal = m_canFlipVertical = m_sticky = m_inRotation = m_inactive = m_layerHidden = m_hidden = false;
174
175 setCursor(*CursorMaster::MoveCursor);
176
177 m_viewGeometry.set(viewGeometry);
178 setAcceptHoverEvents ( true );
179 m_zUninitialized = true;
180 }
181
~ItemBase()182 ItemBase::~ItemBase() {
183 //DebugDialog::debug(QString("deleting itembase %1 %2 %3").arg((long) this, 0, 16).arg(m_id).arg((long) m_modelPart, 0, 16));
184 if (m_partLabel) {
185 delete m_partLabel;
186 m_partLabel = NULL;
187 }
188
189 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
190 foreach (ConnectorItem * toConnectorItem, connectorItem->connectedToItems()) {
191 toConnectorItem->tempRemove(connectorItem, true);
192 }
193 }
194
195 foreach (ItemBase * itemBase, m_stickyList) {
196 itemBase->addSticky(this, false);
197 }
198
199 if (m_modelPart != NULL) {
200 m_modelPart->removeViewItem(this);
201 }
202
203 if (m_fsvgRenderer) {
204 delete m_fsvgRenderer;
205 }
206
207 }
208
setTooltip()209 void ItemBase::setTooltip() {
210 if(m_modelPart) {
211 QString title = instanceTitle();
212 if(!title.isNull() && !title.isEmpty()) {
213 setInstanceTitleTooltip(title);
214 } else {
215 setDefaultTooltip();
216 }
217 } else {
218 setDefaultTooltip();
219 }
220 }
221
removeTooltip()222 void ItemBase::removeTooltip() {
223 this->setToolTip(___emptyString___);
224 }
225
zLessThan(ItemBase * & p1,ItemBase * & p2)226 bool ItemBase::zLessThan(ItemBase * & p1, ItemBase * & p2)
227 {
228 return p1->z() < p2->z();
229 }
230
getNextID()231 qint64 ItemBase::getNextID() {
232 return ModelPart::nextIndex() * ModelPart::indexMultiplier; // make sure we leave room for layerkin inbetween
233 }
234
getNextID(qint64 index)235 qint64 ItemBase::getNextID(qint64 index) {
236
237 qint64 temp = index * ModelPart::indexMultiplier; // make sure we leave room for layerkin inbetween
238 ModelPart::updateIndex(index);
239 return temp;
240 }
241
size()242 QSizeF ItemBase::size() {
243 return m_size;
244 }
245
id() const246 qint64 ItemBase::id() const {
247 return m_id;
248 }
249
resetID()250 void ItemBase::resetID() {
251 m_id = m_modelPart->modelIndex() * ModelPart::indexMultiplier;
252 }
253
z()254 double ItemBase::z() {
255 return getViewGeometry().z();
256 }
257
modelPart()258 ModelPart * ItemBase::modelPart() {
259 return m_modelPart;
260 }
261
setModelPart(ModelPart * modelPart)262 void ItemBase::setModelPart(ModelPart * modelPart) {
263 m_modelPart = modelPart;
264 }
265
modelPartShared()266 ModelPartShared * ItemBase::modelPartShared() {
267 if (m_modelPart == NULL) return NULL;
268
269 return m_modelPart->modelPartShared();
270 }
271
initNames()272 void ItemBase::initNames() {
273 if (NumberMatcher.isEmpty()) {
274 NumberMatcher.setPattern(QString("(([0-9]+(\\.[0-9]*)?)|\\.[0-9]+)([\\s]*([") + TextUtils::PowerPrefixesString + "]))?");
275 }
276
277 if (TranslatedPropertyNames.count() == 0) {
278 TranslatedPropertyNames.insert("family", tr("family"));
279 TranslatedPropertyNames.insert("type", tr("type"));
280 TranslatedPropertyNames.insert("model", tr("model"));
281 TranslatedPropertyNames.insert("size", tr("size"));
282 TranslatedPropertyNames.insert("color", tr("color"));
283 TranslatedPropertyNames.insert("resistance", tr("resistance"));
284 TranslatedPropertyNames.insert("capacitance", tr("capacitance"));
285 TranslatedPropertyNames.insert("inductance", tr("inductance"));
286 TranslatedPropertyNames.insert("voltage", tr("voltage"));
287 TranslatedPropertyNames.insert("current", tr("current"));
288 TranslatedPropertyNames.insert("power", tr("power"));
289 TranslatedPropertyNames.insert("pin spacing", tr("pin spacing"));
290 TranslatedPropertyNames.insert("rated power", tr("rated power"));
291 TranslatedPropertyNames.insert("rated voltage", tr("rated voltage"));
292 TranslatedPropertyNames.insert("rated current", tr("rated current"));
293 TranslatedPropertyNames.insert("version", tr("version"));
294 TranslatedPropertyNames.insert("package", tr("package"));
295 TranslatedPropertyNames.insert("shape", tr("shape"));
296 TranslatedPropertyNames.insert("form", tr("form"));
297 TranslatedPropertyNames.insert("part number", tr("part number"));
298 TranslatedPropertyNames.insert("maximum resistance", tr("maximum resistance"));
299 TranslatedPropertyNames.insert("pins", tr("pins"));
300 TranslatedPropertyNames.insert("spacing", tr("spacing"));
301 TranslatedPropertyNames.insert("pin spacing", tr("pin spacing"));
302 TranslatedPropertyNames.insert("frequency", tr("frequency"));
303 TranslatedPropertyNames.insert("processor", tr("processor"));
304 TranslatedPropertyNames.insert("variant", tr("variant"));
305 TranslatedPropertyNames.insert("layers", tr("layers"));
306 TranslatedPropertyNames.insert("tolerance", tr("tolerance"));
307 TranslatedPropertyNames.insert("descr", tr("descr"));
308 TranslatedPropertyNames.insert("filename", tr("filename"));
309 TranslatedPropertyNames.insert("title", tr("title"));
310 TranslatedPropertyNames.insert("date", tr("date"));
311 TranslatedPropertyNames.insert("rev", tr("rev"));
312 TranslatedPropertyNames.insert("sheet", tr("sheet"));
313 TranslatedPropertyNames.insert("project", tr("project"));
314 TranslatedPropertyNames.insert("banded", tr("banded"));
315 TranslatedPropertyNames.insert("top", tr("top"));
316 TranslatedPropertyNames.insert("bottom", tr("bottom"));
317 TranslatedPropertyNames.insert("copper bottom", tr("copper bottom"));
318 TranslatedPropertyNames.insert("copper top", tr("copper top"));
319 TranslatedPropertyNames.insert("silkscreen bottom", tr("silkscreen bottom"));
320 TranslatedPropertyNames.insert("silkscreen top", tr("silkscreen top"));
321
322 // TODO: translate more known property names from fzp files and resource xml files
323
324 }
325
326 PartInstanceDefaultTitle = tr("Part");
327
328 QSettings settings;
329 QString colorName = settings.value("ConnectedColor").toString();
330 if (!colorName.isEmpty()) {
331 QColor color;
332 color.setNamedColor(colorName);
333 setConnectedColor(color);
334 }
335
336 colorName = settings.value("UnconnectedColor").toString();
337 if (!colorName.isEmpty()) {
338 QColor color;
339 color.setNamedColor(colorName);
340 setUnconnectedColor(color);
341 }
342
343 }
344
saveInstance(QXmlStreamWriter & streamWriter)345 void ItemBase::saveInstance(QXmlStreamWriter & streamWriter) {
346 streamWriter.writeStartElement(ViewLayer::viewIDXmlName(m_viewID));
347 streamWriter.writeAttribute("layer", ViewLayer::viewLayerXmlNameFromID(m_viewLayerID));
348 if (m_moveLock) {
349 streamWriter.writeAttribute("locked", "true");
350 }
351 if (m_superpart) {
352 streamWriter.writeAttribute("superpart", QString::number(m_superpart->modelPart()->modelIndex()));
353 }
354 if (m_viewLayerPlacement == ViewLayer::NewBottom && m_viewID == ViewLayer::PCBView) {
355 streamWriter.writeAttribute("bottom", "true");
356 }
357
358 this->saveGeometry();
359 writeGeometry(streamWriter);
360 if (m_partLabel) {
361 m_partLabel->saveInstance(streamWriter);
362 }
363
364 QList<ItemBase *> itemBases;
365 itemBases.append(this);
366 itemBases.append(layerKinChief()->layerKin());
367 foreach (ItemBase * itemBase, itemBases) {
368 if (itemBase->layerHidden()) {
369 streamWriter.writeStartElement("layerHidden");
370 streamWriter.writeAttribute("layer", ViewLayer::viewLayerXmlNameFromID(itemBase->viewLayerID()));
371 streamWriter.writeEndElement();
372 }
373 }
374
375
376 bool saveConnectorItems = false;
377 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
378 if (connectorItem->connectionsCount() > 0 || connectorItem->hasRubberBandLeg() || connectorItem->isGroundFillSeed()) {
379 saveConnectorItems = true;
380 break;
381 }
382 }
383
384 if (saveConnectorItems) {
385 streamWriter.writeStartElement("connectors");
386 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
387 connectorItem->saveInstance(streamWriter);
388 }
389 streamWriter.writeEndElement();
390 }
391
392
393 streamWriter.writeEndElement();
394 }
395
writeGeometry(QXmlStreamWriter & streamWriter)396 void ItemBase::writeGeometry(QXmlStreamWriter & streamWriter) {
397 streamWriter.writeStartElement("geometry");
398 streamWriter.writeAttribute("z", QString::number(z()));
399 this->saveInstanceLocation(streamWriter);
400 // do not write attributes here
401 streamWriter.writeEndElement();
402 }
403
getViewGeometry()404 ViewGeometry & ItemBase::getViewGeometry() {
405 return m_viewGeometry;
406 }
407
viewID()408 ViewLayer::ViewID ItemBase::viewID() {
409 return m_viewID;
410 }
411
viewIDName()412 QString & ItemBase::viewIDName() {
413 return ViewLayer::viewIDName(m_viewID);
414 }
415
viewLayerID() const416 ViewLayer::ViewLayerID ItemBase::viewLayerID() const {
417 return m_viewLayerID;
418 }
419
setViewLayerID(const QString & layerName,const LayerHash & viewLayers)420 void ItemBase::setViewLayerID(const QString & layerName, const LayerHash & viewLayers) {
421 //DebugDialog::debug(QString("using z %1").arg(layerName));
422 setViewLayerID(ViewLayer::viewLayerIDFromXmlString(layerName), viewLayers);
423 }
424
setViewLayerID(ViewLayer::ViewLayerID viewLayerID,const LayerHash & viewLayers)425 void ItemBase::setViewLayerID(ViewLayer::ViewLayerID viewLayerID, const LayerHash & viewLayers) {
426 m_viewLayerID = viewLayerID;
427 if (m_zUninitialized) {
428 ViewLayer * viewLayer = viewLayers.value(m_viewLayerID);
429 if (viewLayer != NULL) {
430 m_zUninitialized = false;
431 if (!viewLayer->alreadyInLayer(m_viewGeometry.z())) {
432 m_viewGeometry.setZ(viewLayer->nextZ());
433 }
434 }
435 }
436
437 //DebugDialog::debug(QString("using z: %1 z:%2 lid:%3").arg(title()).arg(m_viewGeometry.z()).arg(m_viewLayerID) );
438 }
439
removeLayerKin()440 void ItemBase::removeLayerKin() {
441 }
442
hoverEnterConnectorItem(QGraphicsSceneHoverEvent *,ConnectorItem *)443 void ItemBase::hoverEnterConnectorItem(QGraphicsSceneHoverEvent * , ConnectorItem * ) {
444 //DebugDialog::debug(QString("hover enter c %1").arg(instanceTitle()));
445 hoverEnterConnectorItem();
446 }
447
hoverEnterConnectorItem()448 void ItemBase::hoverEnterConnectorItem() {
449 //DebugDialog::debug(QString("hover enter c %1").arg(instanceTitle()));
450 m_connectorHoverCount++;
451 hoverUpdate();
452 }
453
hoverLeaveConnectorItem(QGraphicsSceneHoverEvent *,ConnectorItem *)454 void ItemBase::hoverLeaveConnectorItem(QGraphicsSceneHoverEvent * , ConnectorItem * ) {
455 hoverLeaveConnectorItem();
456 }
457
hoverMoveConnectorItem(QGraphicsSceneHoverEvent *,ConnectorItem *)458 void ItemBase::hoverMoveConnectorItem(QGraphicsSceneHoverEvent * , ConnectorItem * ) {
459 }
460
hoverLeaveConnectorItem()461 void ItemBase::hoverLeaveConnectorItem() {
462 //DebugDialog::debug(QString("hover leave c %1").arg(instanceTitle()));
463 m_connectorHoverCount--;
464 hoverUpdate();
465 }
466
clearConnectorHover()467 void ItemBase::clearConnectorHover()
468 {
469 m_connectorHoverCount2 = 0;
470 hoverUpdate();
471 }
472
connectorHover(ConnectorItem *,ItemBase *,bool hovering)473 void ItemBase::connectorHover(ConnectorItem *, ItemBase *, bool hovering) {
474 //DebugDialog::debug(QString("hover c %1 %2").arg(hovering).arg(instanceTitle()));
475
476 if (hovering) {
477 m_connectorHoverCount2++;
478 }
479 else {
480 m_connectorHoverCount2--;
481 }
482 // DebugDialog::debug(QString("m_connectorHoverCount2 %1 %2").arg(instanceTitle()).arg(m_connectorHoverCount2));
483 hoverUpdate();
484 }
485
hoverUpdate()486 void ItemBase::hoverUpdate() {
487 this->update();
488 }
489
mousePressConnectorEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)490 void ItemBase::mousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
491 }
492
mouseDoubleClickConnectorEvent(ConnectorItem *)493 void ItemBase::mouseDoubleClickConnectorEvent(ConnectorItem *) {
494 }
495
mouseMoveConnectorEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)496 void ItemBase::mouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
497 }
498
mouseReleaseConnectorEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)499 void ItemBase::mouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
500 }
501
filterMousePressConnectorEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)502 bool ItemBase::filterMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
503 return false;
504 }
505
acceptsMousePressConnectorEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)506 bool ItemBase::acceptsMousePressConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
507 return true;
508 }
509
acceptsMousePressLegEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)510 bool ItemBase::acceptsMousePressLegEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
511 return m_acceptsMousePressLegEvent;
512 }
513
setAcceptsMousePressLegEvent(bool b)514 void ItemBase::setAcceptsMousePressLegEvent(bool b) {
515 m_acceptsMousePressLegEvent = b;
516 }
517
acceptsMouseReleaseConnectorEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)518 bool ItemBase::acceptsMouseReleaseConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
519 return false;
520 }
521
acceptsMouseDoubleClickConnectorEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)522 bool ItemBase::acceptsMouseDoubleClickConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
523 return false;
524 }
525
acceptsMouseMoveConnectorEvent(ConnectorItem *,QGraphicsSceneMouseEvent *)526 bool ItemBase::acceptsMouseMoveConnectorEvent(ConnectorItem *, QGraphicsSceneMouseEvent *) {
527 return false;
528 }
529
connectionChange(ConnectorItem * onMe,ConnectorItem * onIt,bool connect)530 void ItemBase::connectionChange(ConnectorItem * onMe, ConnectorItem * onIt, bool connect) {
531 Q_UNUSED(onMe);
532 Q_UNUSED(onIt);
533 Q_UNUSED(connect);
534 }
535
connectedMoved(ConnectorItem * from,ConnectorItem * to,QList<ConnectorItem * > & already)536 void ItemBase::connectedMoved(ConnectorItem * from, ConnectorItem * to, QList<ConnectorItem *> & already) {
537 Q_UNUSED(from);
538 Q_UNUSED(to);
539 Q_UNUSED(already);
540 }
541
extractTopLevelItemBase(QGraphicsItem * item)542 ItemBase * ItemBase::extractTopLevelItemBase(QGraphicsItem * item) {
543 ItemBase * itemBase = dynamic_cast<ItemBase *>(item);
544 if (itemBase == NULL) return NULL;
545
546 if (itemBase->topLevel()) return itemBase;
547
548 return NULL;
549 }
550
topLevel()551 bool ItemBase::topLevel() {
552 return (this == this->layerKinChief());
553 }
554
setHidden(bool hide)555 void ItemBase::setHidden(bool hide) {
556
557 m_hidden = hide;
558 updateHidden();
559 foreach (QGraphicsItem * item, childItems()) {
560 NonConnectorItem * nonconnectorItem = dynamic_cast<NonConnectorItem *>(item);
561 if (nonconnectorItem == NULL) continue;
562
563 nonconnectorItem->setHidden(hide);
564 }
565 }
566
setInactive(bool inactivate)567 void ItemBase::setInactive(bool inactivate) {
568
569 m_inactive = inactivate;
570 updateHidden();
571 foreach (QGraphicsItem * item, childItems()) {
572 NonConnectorItem * nonconnectorItem = dynamic_cast<NonConnectorItem *>(item);
573 if (nonconnectorItem == NULL) continue;
574
575 nonconnectorItem->setInactive(inactivate);
576 }
577 }
578
setLayerHidden(bool layerHidden)579 void ItemBase::setLayerHidden(bool layerHidden) {
580
581 m_layerHidden = layerHidden;
582 updateHidden();
583 foreach (QGraphicsItem * item, childItems()) {
584 NonConnectorItem * nonconnectorItem = dynamic_cast<NonConnectorItem *>(item);
585 if (nonconnectorItem == NULL) continue;
586
587 nonconnectorItem->setLayerHidden(layerHidden);
588 }
589 }
590
updateHidden()591 void ItemBase::updateHidden() {
592 setAcceptedMouseButtons(m_hidden || m_inactive || m_layerHidden ? Qt::NoButton : ALLMOUSEBUTTONS);
593 setAcceptHoverEvents(!(m_hidden || m_inactive || m_layerHidden));
594 update();
595 }
596
hidden()597 bool ItemBase::hidden() {
598 return m_hidden;
599 }
600
layerHidden()601 bool ItemBase::layerHidden() {
602 return m_layerHidden;
603 }
604
inactive()605 bool ItemBase::inactive() {
606 return m_inactive;
607 }
608
collectConnectors(ConnectorPairHash & connectorHash,SkipCheckFunction skipCheckFunction)609 void ItemBase::collectConnectors(ConnectorPairHash & connectorHash, SkipCheckFunction skipCheckFunction) {
610 // Is this modelpart check obsolete?
611 ModelPart * modelPart = this->modelPart();
612 if (modelPart == NULL) return;
613
614 // collect all the connectorItem pairs
615
616 foreach (ConnectorItem * fromConnectorItem, cachedConnectorItems()) {
617 foreach (ConnectorItem * toConnectorItem, fromConnectorItem->connectedToItems()) {
618 if (skipCheckFunction && skipCheckFunction(toConnectorItem)) continue;
619
620 connectorHash.insert(fromConnectorItem, toConnectorItem);
621 }
622
623 ConnectorItem * crossConnectorItem = fromConnectorItem->getCrossLayerConnectorItem();
624 if (crossConnectorItem == NULL) continue;
625
626 foreach (ConnectorItem * toConnectorItem, crossConnectorItem->connectedToItems()) {
627 if (skipCheckFunction && skipCheckFunction(toConnectorItem)) continue;
628
629 connectorHash.insert(crossConnectorItem, toConnectorItem);
630 }
631 }
632 }
633
findConnectorItemWithSharedID(const QString & connectorID)634 ConnectorItem * ItemBase::findConnectorItemWithSharedID(const QString & connectorID) {
635 Connector * connector = modelPart()->getConnector(connectorID);
636 if (connector) {
637 return connector->connectorItem(m_viewID);
638 }
639
640 return NULL;
641 }
642
findConnectorItemWithSharedID(const QString & connectorID,ViewLayer::ViewLayerPlacement viewLayerPlacement)643 ConnectorItem * ItemBase::findConnectorItemWithSharedID(const QString & connectorID, ViewLayer::ViewLayerPlacement viewLayerPlacement) {
644 ConnectorItem * connectorItem = findConnectorItemWithSharedID(connectorID);
645 if (connectorItem) {
646 return connectorItem->chooseFromSpec(viewLayerPlacement);
647 }
648
649 return NULL;
650 }
651
hoverEnterEvent(QGraphicsSceneHoverEvent * event)652 void ItemBase::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) {
653 // debugInfo("itembase hover enter");
654 InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
655 if (infoGraphicsView != NULL && infoGraphicsView->spaceBarIsPressed()) {
656 m_hoverEnterSpaceBarWasPressed = true;
657 event->ignore();
658 return;
659 }
660
661 m_hoverEnterSpaceBarWasPressed = false;
662 m_hoverCount++;
663 //debugInfo(QString("inc hover %1").arg(m_hoverCount));
664 hoverUpdate();
665 if (infoGraphicsView != NULL) {
666 infoGraphicsView->hoverEnterItem(event, this);
667 }
668 }
669
hoverLeaveEvent(QGraphicsSceneHoverEvent * event)670 void ItemBase::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) {
671 //DebugDialog::debug(QString("hover leave %1").arg(instanceTitle()));
672 if (m_hoverEnterSpaceBarWasPressed) {
673 event->ignore();
674 return;
675 }
676
677 m_hoverCount--;
678 //debugInfo(QString("dec hover %1").arg(m_hoverCount));
679 hoverUpdate();
680
681
682 InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
683 if (infoGraphicsView != NULL) {
684 infoGraphicsView->hoverLeaveItem(event, this);
685 }
686 }
687
updateConnections(bool includeRatsnest,QList<ConnectorItem * > & already)688 void ItemBase::updateConnections(bool includeRatsnest, QList<ConnectorItem *> & already) {
689 Q_UNUSED(already)
690 Q_UNUSED(includeRatsnest);
691 }
692
updateConnections(ConnectorItem * connectorItem,bool includeRatsnest,QList<ConnectorItem * > & already)693 void ItemBase::updateConnections(ConnectorItem * connectorItem, bool includeRatsnest, QList<ConnectorItem *> & already) {
694 if (!already.contains(connectorItem)) {
695 already << connectorItem;
696 connectorItem->attachedMoved(includeRatsnest, already);
697 }
698 else {
699 connectorItem->debugInfo("already");
700 }
701 }
702
title()703 const QString & ItemBase::title() {
704 if (m_modelPart == NULL) return ___emptyString___;
705
706 return m_modelPart->title();
707 }
708
constTitle() const709 const QString & ItemBase::constTitle() const {
710 if (m_modelPart == NULL) return ___emptyString___;
711
712 return m_modelPart->title();
713 }
714
spice() const715 const QString & ItemBase::spice() const {
716 if (m_modelPart == NULL) return ___emptyString___;
717
718 return m_modelPart->spice();
719 }
720
spiceModel() const721 const QString & ItemBase::spiceModel() const {
722 if (m_modelPart == NULL) return ___emptyString___;
723
724 return m_modelPart->spiceModel();
725 }
726
getRatsnest()727 bool ItemBase::getRatsnest() {
728 return m_viewGeometry.getRatsnest();
729 }
730
buses()731 QList<Bus *> ItemBase::buses() {
732 QList<Bus *> busList;
733 if (m_modelPart == NULL) return busList;
734
735 foreach (Bus * bus, m_modelPart->buses().values()) {
736 busList.append(bus);
737 }
738
739 return busList;
740 }
741
busConnectorItems(class Bus * bus,ConnectorItem * fromConnectorItem,QList<class ConnectorItem * > & items)742 void ItemBase::busConnectorItems(class Bus * bus, ConnectorItem * fromConnectorItem, QList<class ConnectorItem *> & items) {
743 Q_UNUSED(fromConnectorItem)
744
745 if (bus == NULL) return;
746
747 foreach (Connector * connector, bus->connectors()) {
748 foreach (ConnectorItem * connectorItem, connector->viewItems()) {
749 if (connectorItem != NULL) {
750 //connectorItem->debugInfo(QString("on the bus %1").arg((long) connector, 0, 16));
751 if (connectorItem->attachedTo() == this) {
752 items.append(connectorItem);
753 }
754 }
755 }
756 }
757
758 if (m_superpart || m_subparts.count() > 0) {
759 Connector * connector = bus->subConnector();
760 if (connector) {
761 foreach (ConnectorItem * connectorItem, connector->viewItems()) {
762 if (connectorItem != NULL) {
763 //connectorItem->debugInfo(QString("on the bus %1").arg((long) connector, 0, 16));
764 if (connectorItem->attachedToViewID() == m_viewID) {
765 items.append(connectorItem);
766 }
767 }
768 }
769 }
770 }
771
772
773 /*
774 if (items.count() > 0) {
775 fromConnectorItem->debugInfo("bus");
776 foreach (ConnectorItem * ci, items) {
777 ci->debugInfo("\t");
778 }
779 }
780 */
781 }
782
itemType() const783 int ItemBase::itemType() const
784 {
785 if (m_modelPart == NULL) return ModelPart::Unknown;
786
787 return m_modelPart->itemType();
788 }
789
inHover()790 bool ItemBase::inHover() {
791 return (!m_inactive && (m_connectorHoverCount > 0 || m_hoverCount > 0 || m_connectorHoverCount2 > 0));
792 }
793
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)794 void ItemBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
795 if (inHover()) {
796 //DebugDialog::debug(QString("chc:%1 hc:%2 chc2:%3").arg(m_connectorHoverCount).arg(m_hoverCount).arg(m_connectorHoverCount2));
797 layerKinChief()->paintHover(painter, option, widget);
798 }
799 //else {
800 //DebugDialog::debug("no hover");
801 //}
802
803 if (m_inactive) {
804 painter->save();
805 painter->setOpacity(InactiveOpacity);
806 }
807
808 paintBody(painter, option, widget);
809
810 if (option->state & QStyle::State_Selected) {
811 layerKinChief()->paintSelected(painter, option, widget);
812 }
813
814 if (m_inactive) {
815 painter->restore();
816 }
817 }
818
paintBody(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)819 void ItemBase::paintBody(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
820 {
821 Q_UNUSED(option);
822 Q_UNUSED(widget);
823
824 // Qt's SVG renderer's defaultSize is not correct when the svg has a fractional pixel size
825 fsvgRenderer()->render(painter, boundingRectWithoutLegs());
826 }
827
paintHover(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)828 void ItemBase::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
829 {
830 paintHover(painter, option, widget, hoverShape());
831 }
832
paintSelected(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)833 void ItemBase::paintSelected(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
834 {
835 Q_UNUSED(widget);
836 GraphicsUtils::qt_graphicsItem_highlightSelected(painter, option, boundingRect(), hoverShape());
837 }
838
paintHover(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget,const QPainterPath & shape)839 void ItemBase::paintHover(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, const QPainterPath & shape)
840 {
841 Q_UNUSED(widget);
842 Q_UNUSED(option);
843 painter->save();
844 if (m_connectorHoverCount > 0 || m_connectorHoverCount2 > 0) {
845 painter->setOpacity(ConnectorHoverOpacity);
846 painter->fillPath(shape, QBrush(ConnectorHoverColor));
847 }
848 else {
849 painter->setOpacity(HoverOpacity);
850 painter->fillPath(shape, QBrush(HoverColor));
851 }
852 painter->restore();
853 }
854
mousePressEvent(QGraphicsSceneMouseEvent * event)855 void ItemBase::mousePressEvent(QGraphicsSceneMouseEvent *event) {
856 InfoGraphicsView *infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
857 if (infoGraphicsView != NULL && infoGraphicsView->spaceBarIsPressed()) {
858 event->ignore();
859 return;
860 }
861
862 //scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
863 //setCacheMode(QGraphicsItem::DeviceCoordinateCache);
864 QGraphicsSvgItem::mousePressEvent(event);
865 }
866
mouseReleaseEvent(QGraphicsSceneMouseEvent * event)867 void ItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
868 {
869 m_rightClickedConnector = NULL;
870 // calling parent class so that multiple selection will work
871 // haven't yet discovered any nasty side-effect
872 QGraphicsSvgItem::mouseReleaseEvent(event);
873
874 //scene()->setItemIndexMethod(QGraphicsScene::BspTreeIndex);
875 // setCacheMode(QGraphicsItem::NoCache);
876
877 }
878
mouseMoveEvent(QGraphicsSceneMouseEvent *)879 void ItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent *)
880 {
881 }
882
setItemPos(QPointF & loc)883 void ItemBase::setItemPos(QPointF & loc) {
884 setPos(loc);
885 }
886
stickyEnabled()887 bool ItemBase::stickyEnabled() {
888 return true;
889 }
890
isSticky()891 bool ItemBase::isSticky() {
892 return isBaseSticky() && isLocalSticky();
893 }
894
895
isBaseSticky()896 bool ItemBase::isBaseSticky() {
897 return m_sticky; // to cancel sticky return false;
898 }
899
setSticky(bool s)900 void ItemBase::setSticky(bool s)
901 {
902 m_sticky = s;
903 }
904
isLocalSticky()905 bool ItemBase::isLocalSticky() {
906 if (layerKinChief() != this) {
907 return layerKinChief()->isLocalSticky();
908 }
909 QString stickyVal = modelPart()->localProp("sticky").toString();
910 // return (stickyVal.compare("false") != 0); // defaults to true
911 return (stickyVal.compare("true") == 0); // defaults to false
912 }
913
setLocalSticky(bool s)914 void ItemBase::setLocalSticky(bool s)
915 {
916 // dirty the window?
917 // undo command?
918 if (layerKinChief() != this) {
919 layerKinChief()->setLocalSticky(s);
920 return;
921 }
922
923 modelPart()->setLocalProp("sticky", s ? "true" : "false");
924
925 if (s) {
926 if (m_stickyItem == NULL) {
927 if (!StickyRenderer.isValid()) {
928 QString fn(":resources/images/part_sticky.svg");
929 bool success = StickyRenderer.load(fn);
930 Q_UNUSED(success);
931 //DebugDialog::debug(QString("sticky load success %1").arg(success));
932 }
933
934 m_stickyItem = new QGraphicsSvgItem();
935 m_stickyItem->setAcceptHoverEvents(false);
936 m_stickyItem->setAcceptedMouseButtons(Qt::NoButton);
937 m_stickyItem->setSharedRenderer(&StickyRenderer);
938 m_stickyItem->setPos(m_moveLockItem == NULL ? 0 : m_moveLockItem->boundingRect().width() + 1, 0);
939 m_stickyItem->setZValue(-99999);
940 m_stickyItem->setParentItem(this);
941 m_stickyItem->setVisible(true);
942 }
943 }
944 else {
945 if (m_stickyItem) {
946 delete m_stickyItem;
947 m_stickyItem = NULL;
948 }
949 }
950
951 update();
952 }
953
addSticky(ItemBase * stickyBase,bool stickem)954 void ItemBase::addSticky(ItemBase * stickyBase, bool stickem) {
955 stickyBase = stickyBase->layerKinChief();
956 //this->debugInfo(QString("add sticky %1:").arg(stickem));
957 //sticky->debugInfo(QString(" to"));
958 if (stickem) {
959 if (!isBaseSticky()) {
960 foreach (ItemBase * oldstickingTo, m_stickyList.values()) {
961 if (oldstickingTo == stickyBase) continue;
962
963 oldstickingTo->addSticky(this, false);
964 }
965 m_stickyList.clear();
966 }
967 m_stickyList.insert(stickyBase->id(), stickyBase);
968 }
969 else {
970 m_stickyList.remove(stickyBase->id());
971 }
972 }
973
974
stickingTo()975 ItemBase * ItemBase::stickingTo() {
976 if (isBaseSticky()) return NULL;
977
978 if (m_stickyList.count() < 1) return NULL;
979
980 if (m_stickyList.count() > 1) {
981 DebugDialog::debug(QString("error: sticky list > 1 %1").arg(title()));
982 }
983
984 return *m_stickyList.begin();
985 }
986
stickyList()987 QList< QPointer<ItemBase> > ItemBase::stickyList() {
988 return m_stickyList.values();
989 }
990
alreadySticking(ItemBase * itemBase)991 bool ItemBase::alreadySticking(ItemBase * itemBase) {
992 return m_stickyList.value(itemBase->layerKinChief()->id(), NULL) != NULL;
993 }
994
newConnectorItem(Connector * connector)995 ConnectorItem* ItemBase::newConnectorItem(Connector *connector)
996 {
997 return newConnectorItem(this, connector);
998 }
999
newConnectorItem(ItemBase * layerKin,Connector * connector)1000 ConnectorItem* ItemBase::newConnectorItem(ItemBase * layerKin, Connector *connector)
1001 {
1002 return new ConnectorItem(connector, layerKin);
1003 }
1004
anyConnectorItem()1005 ConnectorItem * ItemBase::anyConnectorItem() {
1006 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
1007 return connectorItem;
1008 }
1009
1010 return NULL;
1011 }
1012
1013
instanceTitle() const1014 const QString & ItemBase::instanceTitle() const {
1015 if (m_modelPart) {
1016 return m_modelPart->instanceTitle();
1017 }
1018 return ___emptyString___;
1019 }
1020
setInstanceTitle(const QString & title,bool initial)1021 void ItemBase::setInstanceTitle(const QString &title, bool initial) {
1022 setInstanceTitleAux(title, initial);
1023 if (m_partLabel) {
1024 m_partLabel->setPlainText(title);
1025 }
1026 }
1027
updatePartLabelInstanceTitle()1028 void ItemBase::updatePartLabelInstanceTitle() {
1029 if (m_partLabel) {
1030 m_partLabel->setPlainText(instanceTitle());
1031 }
1032 }
1033
setInstanceTitleAux(const QString & title,bool initial)1034 void ItemBase::setInstanceTitleAux(const QString &title, bool initial)
1035 {
1036 if (m_modelPart) {
1037 m_modelPart->setInstanceTitle(title, initial);
1038 }
1039 setInstanceTitleTooltip(title);
1040
1041 // InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this);
1042 // if (infographics != NULL) {
1043 // infographics->setItemTooltip(this, title);
1044 // }
1045 }
1046
label()1047 QString ItemBase::label() {
1048 if(m_modelPart) {
1049 return m_modelPart->label();
1050 }
1051 return ___emptyString___;
1052 }
1053
updateTooltip()1054 void ItemBase::updateTooltip() {
1055 setInstanceTitleTooltip(instanceTitle());
1056 }
1057
setInstanceTitleTooltip(const QString & text)1058 void ItemBase::setInstanceTitleTooltip(const QString &text) {
1059 setToolTip("<b>"+text+"</b><br></br>" + ITEMBASE_FONT_PREFIX + title()+ ITEMBASE_FONT_SUFFIX);
1060 }
1061
setDefaultTooltip()1062 void ItemBase::setDefaultTooltip() {
1063 if (m_modelPart) {
1064 if (m_viewID == ViewLayer::IconView) {
1065 QString base = ITEMBASE_FONT_PREFIX + "%1" + ITEMBASE_FONT_SUFFIX;
1066 if(m_modelPart->itemType() != ModelPart::Wire) {
1067 this->setToolTip(base.arg(m_modelPart->title()));
1068 } else {
1069 this->setToolTip(base.arg(m_modelPart->title() + " (" + m_modelPart->moduleID() + ")"));
1070 }
1071 return;
1072 }
1073
1074 QString title = ItemBase::PartInstanceDefaultTitle;
1075 QString inst = instanceTitle();
1076 if(!inst.isNull() && !inst.isEmpty()) {
1077 title = inst;
1078 } else {
1079 QString defaultTitle = label();
1080 if(!defaultTitle.isNull() && !defaultTitle.isEmpty()) {
1081 title = defaultTitle;
1082 }
1083 }
1084 ensureUniqueTitle(title, false);
1085 setInstanceTitleTooltip(instanceTitle());
1086 }
1087 }
1088
contextMenuEvent(QGraphicsSceneContextMenuEvent * event)1089 void ItemBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
1090 {
1091 if ((acceptedMouseButtons() & Qt::RightButton) == 0) {
1092 event->ignore();
1093 return;
1094 }
1095
1096 if (m_hidden || m_inactive || m_layerHidden) {
1097 event->ignore();
1098 return;
1099 }
1100
1101 scene()->clearSelection();
1102 setSelected(true);
1103
1104 if (m_itemMenu != NULL) {
1105 m_rightClickedConnector = NULL;
1106 foreach (QGraphicsItem * item, scene()->items(event->scenePos())) {
1107 ConnectorItem * connectorItem = dynamic_cast<ConnectorItem *>(item);
1108 if (connectorItem == NULL) continue;
1109
1110 if (connectorItem->attachedTo() == this) {
1111 m_rightClickedConnector = connectorItem;
1112 break;
1113 }
1114 }
1115
1116 m_itemMenu->exec(event->screenPos());
1117 }
1118 }
1119
hasConnectors()1120 bool ItemBase::hasConnectors() {
1121 return cachedConnectorItems().count() > 0;
1122 }
1123
hasNonConnectors()1124 bool ItemBase::hasNonConnectors() {
1125 foreach (QGraphicsItem * childItem, childItems()) {
1126 if (dynamic_cast<NonConnectorItem *>(childItem) != NULL) return true;
1127 }
1128
1129 return false;
1130 }
1131
canFlip(Qt::Orientations orientations)1132 bool ItemBase::canFlip(Qt::Orientations orientations) {
1133 bool result = true;
1134 if (orientations & Qt::Horizontal) {
1135 result = result && m_canFlipHorizontal;
1136 }
1137 if (orientations & Qt::Vertical) {
1138 result = result && m_canFlipVertical;
1139 }
1140 return result;
1141 }
1142
canFlipHorizontal()1143 bool ItemBase::canFlipHorizontal() {
1144 return m_canFlipHorizontal && !m_moveLock;
1145 }
1146
setCanFlipHorizontal(bool cf)1147 void ItemBase::setCanFlipHorizontal(bool cf) {
1148 m_canFlipHorizontal = cf;
1149 }
1150
canFlipVertical()1151 bool ItemBase::canFlipVertical() {
1152 return m_canFlipVertical && !m_moveLock;
1153 }
1154
setCanFlipVertical(bool cf)1155 void ItemBase::setCanFlipVertical(bool cf) {
1156 m_canFlipVertical = cf;
1157 }
1158
rotationAllowed()1159 bool ItemBase::rotationAllowed() {
1160 return !m_moveLock;
1161 }
1162
rotation45Allowed()1163 bool ItemBase::rotation45Allowed() {
1164 return !m_moveLock;
1165 }
1166
freeRotationAllowed()1167 bool ItemBase::freeRotationAllowed() {
1168 return false;
1169 }
1170
clearModelPart()1171 void ItemBase::clearModelPart() {
1172 m_modelPart = NULL;
1173 }
1174
hidePartLabel()1175 void ItemBase::hidePartLabel()
1176 {
1177 InfoGraphicsView *infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
1178 if (infoGraphicsView) infoGraphicsView->hidePartLabel(this);
1179 }
1180
showPartLabel(bool showIt,ViewLayer * viewLayer)1181 void ItemBase::showPartLabel(bool showIt, ViewLayer* viewLayer) {
1182 if (m_partLabel) {
1183 m_partLabel->showLabel(showIt, viewLayer);
1184 }
1185 }
1186
partLabelChanged(const QString & newText)1187 void ItemBase::partLabelChanged(const QString & newText) {
1188 // sent from part label after inline edit
1189 InfoGraphicsView *infographics = InfoGraphicsView::getInfoGraphicsView(this);
1190 QString oldText = modelPart()->instanceTitle();
1191 setInstanceTitleAux(newText, false);
1192 if (infographics != NULL) {
1193 infographics->partLabelChanged(this, oldText, newText);
1194 }
1195 }
1196
isPartLabelVisible()1197 bool ItemBase::isPartLabelVisible() {
1198 if (m_partLabel == NULL) return false;
1199 if (!hasPartLabel()) return false;
1200 if (!m_partLabel->initialized()) return false;
1201
1202 return m_partLabel->isVisible();
1203 }
1204
clearPartLabel()1205 void ItemBase::clearPartLabel() {
1206 m_partLabel = NULL;
1207 }
1208
restorePartLabel(QDomElement & labelGeometry,ViewLayer::ViewLayerID viewLayerID)1209 void ItemBase::restorePartLabel(QDomElement & labelGeometry, ViewLayer::ViewLayerID viewLayerID)
1210 {
1211 if (m_partLabel) {
1212 m_partLabel->setPlainText(instanceTitle());
1213 if (!labelGeometry.isNull()) {
1214 m_partLabel->restoreLabel(labelGeometry, viewLayerID);
1215 //m_partLabel->setPlainText(instanceTitle());
1216 }
1217 }
1218 }
1219
movePartLabel(QPointF newPos,QPointF newOffset)1220 void ItemBase::movePartLabel(QPointF newPos, QPointF newOffset) {
1221 if (m_partLabel) {
1222 m_partLabel->moveLabel(newPos, newOffset);
1223 }
1224 }
1225
partLabelSetHidden(bool hide)1226 void ItemBase::partLabelSetHidden(bool hide) {
1227 if (m_partLabel) {
1228 m_partLabel->setHidden(hide);
1229 }
1230 }
1231
partLabelMoved(QPointF oldPos,QPointF oldOffset,QPointF newPos,QPointF newOffset)1232 void ItemBase::partLabelMoved(QPointF oldPos, QPointF oldOffset, QPointF newPos, QPointF newOffset) {
1233 InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
1234 if (infoGraphicsView != NULL) {
1235 infoGraphicsView->partLabelMoved(this, oldPos, oldOffset, newPos, newOffset);
1236 }
1237 }
1238
rotateFlipPartLabel(double degrees,Qt::Orientations orientation)1239 void ItemBase::rotateFlipPartLabel(double degrees, Qt::Orientations orientation)
1240 {
1241 InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
1242 if (infoGraphicsView != NULL) {
1243 infoGraphicsView->rotateFlipPartLabel(this, degrees, orientation);
1244 }
1245 }
1246
1247
doRotateFlipPartLabel(double degrees,Qt::Orientations orientation)1248 void ItemBase::doRotateFlipPartLabel(double degrees, Qt::Orientations orientation)
1249 {
1250 if (m_partLabel) {
1251 m_partLabel->rotateFlipLabel(degrees, orientation);
1252 }
1253 }
1254
isSwappable()1255 bool ItemBase::isSwappable() {
1256 return m_swappable;
1257 }
1258
setSwappable(bool swappable)1259 void ItemBase::setSwappable(bool swappable) {
1260 m_swappable = swappable;
1261 }
1262
ensureUniqueTitle(const QString & title,bool force)1263 void ItemBase::ensureUniqueTitle(const QString & title, bool force) {
1264 if (force || instanceTitle().isEmpty() || instanceTitle().isNull()) {
1265 setInstanceTitle(modelPart()->getNextTitle(title), true);
1266 }
1267 }
1268
itemChange(QGraphicsItem::GraphicsItemChange change,const QVariant & value)1269 QVariant ItemBase::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value)
1270 {
1271 switch (change) {
1272 case QGraphicsItem::ItemSelectedChange:
1273 if (m_partLabel) {
1274 m_partLabel->ownerSelected(value.toBool());
1275 }
1276
1277 break;
1278 default:
1279 break;
1280 }
1281
1282 return QGraphicsSvgItem::itemChange(change, value);
1283 }
1284
cleanup()1285 void ItemBase::cleanup() {
1286 }
1287
layerKin()1288 const QList<ItemBase *> & ItemBase::layerKin() {
1289 return EmptyList;
1290 }
1291
layerKinChief()1292 ItemBase * ItemBase::layerKinChief() {
1293 return this;
1294 }
1295
rotateItem(double degrees,bool includeRatsnest)1296 void ItemBase::rotateItem(double degrees, bool includeRatsnest) {
1297 //this->debugInfo(QString("\trotating item %1").arg(degrees));
1298 transformItem(QTransform().rotate(degrees), includeRatsnest);
1299 }
1300
flipItem(Qt::Orientations orientation)1301 void ItemBase::flipItem(Qt::Orientations orientation) {
1302 int xScale; int yScale;
1303 if(orientation == Qt::Vertical) {
1304 xScale = 1;
1305 yScale = -1;
1306 } else if(orientation == Qt::Horizontal) {
1307 xScale = -1;
1308 yScale = 1;
1309 }
1310 else {
1311 return;
1312 }
1313
1314 transformItem(QTransform().scale(xScale,yScale), false);
1315 }
1316
transformItem(const QTransform & currTransf,bool includeRatsnest)1317 void ItemBase::transformItem(const QTransform & currTransf, bool includeRatsnest) {
1318 //debugInfo("transform item " + TextUtils::svgMatrix(currTransf));
1319
1320 QTransform trns = getViewGeometry().transform();
1321 //debugInfo("\t" + TextUtils::svgMatrix(trns));
1322
1323
1324
1325 if (m_hasRubberBandLeg) {
1326 prepareGeometryChange();
1327 }
1328 QRectF rect = this->boundingRectWithoutLegs();
1329
1330 //debugInfo(QString("\t bounding rect w:%1, h:%2").arg(rect.width()).arg(rect.height()));
1331 double x = rect.width() / 2.0;
1332 double y = rect.height() / 2.0;
1333 QTransform transf = QTransform().translate(-x, -y) * currTransf * QTransform().translate(x, y);
1334 getViewGeometry().setTransform(getViewGeometry().transform()*transf);
1335 this->setTransform(getViewGeometry().transform());
1336 if (!m_hasRubberBandLeg) {
1337 QList<ConnectorItem *> already;
1338 updateConnections(includeRatsnest, already);
1339 }
1340
1341 trns = getViewGeometry().transform();
1342 //debugInfo("\t" + TextUtils::svgMatrix(trns));
1343
1344 update();
1345 }
1346
transformItem2(const QMatrix & matrix)1347 void ItemBase::transformItem2(const QMatrix & matrix) {
1348 QTransform transform(matrix);
1349 transformItem(transform, false);
1350 }
1351
collectWireConnectees(QSet<class Wire * > & wires)1352 void ItemBase::collectWireConnectees(QSet<class Wire *> & wires) {
1353 Q_UNUSED(wires);
1354 }
1355
collectFemaleConnectees(QSet<ItemBase * > & items)1356 bool ItemBase::collectFemaleConnectees(QSet<ItemBase *> & items) {
1357 Q_UNUSED(items);
1358 return false; // means no male connectors
1359 }
1360
prepareGeometryChange()1361 void ItemBase::prepareGeometryChange() {
1362 // made public so it can be invoked from outside ItemBase class
1363
1364 //debugInfo("itembase prepare geometry change");
1365 QGraphicsSvgItem::prepareGeometryChange();
1366 }
1367
saveLocAndTransform(QXmlStreamWriter & streamWriter)1368 void ItemBase::saveLocAndTransform(QXmlStreamWriter & streamWriter)
1369 {
1370 streamWriter.writeAttribute("x", QString::number(m_viewGeometry.loc().x()));
1371 streamWriter.writeAttribute("y", QString::number(m_viewGeometry.loc().y()));
1372 GraphicsUtils::saveTransform(streamWriter, m_viewGeometry.transform());
1373 }
1374
setUpImage(ModelPart * modelPart,LayerAttributes & layerAttributes)1375 FSvgRenderer * ItemBase::setUpImage(ModelPart * modelPart, LayerAttributes & layerAttributes)
1376 {
1377 // at this point "this" has not yet been added to the scene, so one cannot get back to the InfoGraphicsView
1378
1379 ModelPartShared * modelPartShared = modelPart->modelPartShared();
1380
1381 if (modelPartShared == NULL) {
1382 layerAttributes.error = tr("model part problem");
1383 return NULL;
1384 }
1385
1386 //if (modelPartShared->moduleID() == "df9d072afa2b594ac67b60b4153ff57b_29" && viewID == ViewLayer::PCBView) {
1387 // DebugDialog::debug("here i am now");
1388 //}
1389
1390 //DebugDialog::debug(QString("setting z %1 %2")
1391 //.arg(this->z())
1392 //.arg(ViewLayer::viewLayerNameFromID(viewLayerID)) );
1393
1394
1395 //DebugDialog::debug(QString("set up image elapsed (1) %1").arg(t.elapsed()) );
1396 QString filename = PartFactory::getSvgFilename(modelPart, modelPartShared->imageFileName(layerAttributes.viewID, layerAttributes.viewLayerID), true, true);
1397
1398 //#ifndef QT_NO_DEBUG
1399 //DebugDialog::debug(QString("set up image elapsed (2) %1").arg(t.elapsed()) );
1400 //#endif
1401
1402 if (filename.isEmpty()) {
1403 //QString deleteme = modelPartShared->domDocument()->toString();
1404 layerAttributes.error = tr("file for %1 %2 not found").arg(modelPartShared->title()).arg(modelPartShared->moduleID());
1405 return NULL;
1406 }
1407
1408 LoadInfo loadInfo;
1409 switch (layerAttributes.viewID) {
1410 case ViewLayer::PCBView:
1411 loadInfo.colorElementID = ViewLayer::viewLayerXmlNameFromID(layerAttributes.viewLayerID);
1412 switch (layerAttributes.viewLayerID) {
1413 case ViewLayer::Copper0:
1414 modelPartShared->connectorIDs(layerAttributes.viewID, layerAttributes.viewLayerID, loadInfo.connectorIDs, loadInfo.terminalIDs, loadInfo.legIDs);
1415 loadInfo.setColor = ViewLayer::Copper0Color;
1416 loadInfo.findNonConnectors = loadInfo.parsePaths = true;
1417 break;
1418 case ViewLayer::Copper1:
1419 modelPartShared->connectorIDs(layerAttributes.viewID, layerAttributes.viewLayerID, loadInfo.connectorIDs, loadInfo.terminalIDs, loadInfo.legIDs);
1420 loadInfo.setColor = ViewLayer::Copper1Color;
1421 loadInfo.findNonConnectors = loadInfo.parsePaths = true;
1422 break;
1423 case ViewLayer::Silkscreen1:
1424 loadInfo.setColor = ViewLayer::Silkscreen1Color;
1425 break;
1426 case ViewLayer::Silkscreen0:
1427 loadInfo.setColor = ViewLayer::Silkscreen0Color;
1428 break;
1429 default:
1430 break;
1431 }
1432 break;
1433 case ViewLayer::BreadboardView:
1434 modelPartShared->connectorIDs(layerAttributes.viewID, layerAttributes.viewLayerID, loadInfo.connectorIDs, loadInfo.terminalIDs, loadInfo.legIDs);
1435 break;
1436 default:
1437 // don't need connectorIDs() for schematic view since these parts do not have bendable legs or connectors with drill holes
1438 break;
1439 }
1440
1441 FSvgRenderer * newRenderer = new FSvgRenderer();
1442 QDomDocument flipDoc;
1443 getFlipDoc(modelPart, filename, layerAttributes.viewLayerID, layerAttributes.viewLayerPlacement, flipDoc, layerAttributes.orientation);
1444 QByteArray bytesToLoad;
1445 if (layerAttributes.viewLayerID == ViewLayer::Schematic) {
1446 bytesToLoad = SvgFileSplitter::hideText(filename);
1447 }
1448 else if (layerAttributes.viewLayerID == ViewLayer::SchematicText) {
1449 bool hasText = false;
1450 bytesToLoad = SvgFileSplitter::showText(filename, hasText);
1451 if (!hasText) {
1452 return NULL;
1453 }
1454 }
1455 else if ((layerAttributes.viewID != ViewLayer::IconView) && modelPartShared->hasMultipleLayers(layerAttributes.viewID)) {
1456 QString layerName = ViewLayer::viewLayerXmlNameFromID(layerAttributes.viewLayerID);
1457 // need to treat create "virtual" svg file for each layer
1458 SvgFileSplitter svgFileSplitter;
1459 bool result;
1460 if (flipDoc.isNull()) {
1461 result = svgFileSplitter.split(filename, layerName);
1462 }
1463 else {
1464 QString f = flipDoc.toString();
1465 result = svgFileSplitter.splitString(f, layerName);
1466 }
1467 if (result) {
1468 bytesToLoad = svgFileSplitter.byteArray();
1469 }
1470 }
1471 else {
1472 // only one layer, just load it directly
1473 if (flipDoc.isNull()) {
1474 QFile file(filename);
1475 file.open(QFile::ReadOnly);
1476 bytesToLoad = file.readAll();
1477 }
1478 else {
1479 bytesToLoad = flipDoc.toByteArray();
1480 }
1481 }
1482
1483 QByteArray resultBytes;
1484 if (!bytesToLoad.isEmpty()) {
1485 if (makeLocalModifications(bytesToLoad, filename)) {
1486 if (layerAttributes.viewLayerID == ViewLayer::Schematic) {
1487 bytesToLoad = SvgFileSplitter::hideText2(bytesToLoad);
1488 }
1489 else if (layerAttributes.viewLayerID == ViewLayer::SchematicText) {
1490 bool hasText;
1491 bytesToLoad = SvgFileSplitter::showText2(bytesToLoad, hasText);
1492 }
1493 }
1494
1495 loadInfo.filename = filename;
1496 resultBytes = newRenderer->loadSvg(bytesToLoad, loadInfo);
1497 }
1498
1499 layerAttributes.setLoaded(resultBytes);
1500
1501 #ifndef QT_NO_DEBUG
1502 // DebugDialog::debug(QString("set up image elapsed (2.3) %1").arg(t.elapsed()) );
1503 #endif
1504
1505 if (resultBytes.isEmpty()) {
1506 delete newRenderer;
1507 layerAttributes.error = tr("unable to create renderer for svg %1").arg(filename);
1508 newRenderer = NULL;
1509 }
1510 //DebugDialog::debug(QString("set up image elapsed (3) %1").arg(t.elapsed()) );
1511
1512 if (newRenderer) {
1513 layerAttributes.setFilename(newRenderer->filename());
1514 if (layerAttributes.createShape) {
1515 createShape(layerAttributes);
1516 }
1517 }
1518
1519 return newRenderer;
1520 }
1521
updateConnectionsAux(bool includeRatsnest,QList<ConnectorItem * > & already)1522 void ItemBase::updateConnectionsAux(bool includeRatsnest, QList<ConnectorItem *> & already) {
1523 //DebugDialog::debug("update connections");
1524 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
1525 updateConnections(connectorItem, includeRatsnest, already);
1526 }
1527 }
1528
figureHover()1529 void ItemBase::figureHover() {
1530 }
1531
retrieveSvg(ViewLayer::ViewLayerID viewLayerID,QHash<QString,QString> & svgHash,bool blackOnly,double dpi,double & factor)1532 QString ItemBase::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHash<QString, QString> & svgHash, bool blackOnly, double dpi, double & factor)
1533 {
1534 Q_UNUSED(viewLayerID);
1535 Q_UNUSED(svgHash);
1536 Q_UNUSED(blackOnly);
1537 Q_UNUSED(dpi);
1538 factor = 1;
1539 return "";
1540 }
1541
hasConnections()1542 bool ItemBase::hasConnections()
1543 {
1544 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
1545 if (connectorItem->connectionsCount() > 0) return true;
1546 }
1547
1548 return false;
1549 }
1550
getConnectedColor(ConnectorItem *,QBrush & brush,QPen & pen,double & opacity,double & negativePenWidth,bool & negativeOffsetRect)1551 void ItemBase::getConnectedColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) {
1552 brush = ConnectedBrush;
1553 pen = ConnectedPen;
1554 opacity = 0.2;
1555 negativePenWidth = 0;
1556 negativeOffsetRect = true;
1557 }
1558
getNormalColor(ConnectorItem *,QBrush & brush,QPen & pen,double & opacity,double & negativePenWidth,bool & negativeOffsetRect)1559 void ItemBase::getNormalColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) {
1560 brush = NormalBrush;
1561 pen = NormalPen;
1562 opacity = NormalConnectorOpacity;
1563 negativePenWidth = 0;
1564 negativeOffsetRect = true;
1565 }
1566
getUnconnectedColor(ConnectorItem *,QBrush & brush,QPen & pen,double & opacity,double & negativePenWidth,bool & negativeOffsetRect)1567 void ItemBase::getUnconnectedColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) {
1568 brush = UnconnectedBrush;
1569 pen = UnconnectedPen;
1570 opacity = 0.3;
1571 negativePenWidth = 0;
1572 negativeOffsetRect = true;
1573 }
1574
getHoverColor(ConnectorItem *,QBrush & brush,QPen & pen,double & opacity,double & negativePenWidth,bool & negativeOffsetRect)1575 void ItemBase::getHoverColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) {
1576 brush = HoverBrush;
1577 pen = HoverPen;
1578 opacity = NormalConnectorOpacity;
1579 negativePenWidth = 0;
1580 negativeOffsetRect = true;
1581 }
1582
getEqualPotentialColor(ConnectorItem *,QBrush & brush,QPen & pen,double & opacity,double & negativePenWidth,bool & negativeOffsetRect)1583 void ItemBase::getEqualPotentialColor(ConnectorItem *, QBrush &brush, QPen &pen, double & opacity, double & negativePenWidth, bool & negativeOffsetRect) {
1584 brush = EqualPotentialBrush;
1585 pen = EqualPotentialPen;
1586 opacity = 1.0;
1587 negativePenWidth = 0;
1588 negativeOffsetRect = true;
1589 }
1590
slamZ(double newZ)1591 void ItemBase::slamZ(double newZ) {
1592 double z = qFloor(m_viewGeometry.z()) + newZ;
1593 m_viewGeometry.setZ(z);
1594 setZValue(z);
1595 }
1596
isEverVisible()1597 bool ItemBase::isEverVisible() {
1598 return m_everVisible;
1599 }
1600
setEverVisible(bool v)1601 void ItemBase::setEverVisible(bool v) {
1602 m_everVisible = v;
1603 }
1604
connectionIsAllowed(ConnectorItem * other)1605 bool ItemBase::connectionIsAllowed(ConnectorItem * other) {
1606 return ViewLayer::canConnect(this->viewLayerID(), other->attachedToViewLayerID());
1607 }
1608
getProperty(const QString & key)1609 QString ItemBase::getProperty(const QString & key) {
1610 if (m_modelPart == NULL) return "";
1611
1612 QString result = m_modelPart->localProp(key).toString();
1613 if (!result.isEmpty()) return result;
1614
1615 return m_modelPart->properties().value(key, "");
1616 }
1617
rightClickedConnector()1618 ConnectorItem * ItemBase::rightClickedConnector() {
1619 return m_rightClickedConnector;
1620 }
1621
connectedColor()1622 QColor ItemBase::connectedColor() {
1623 return ConnectedPen.color();
1624 }
1625
unconnectedColor()1626 QColor ItemBase::unconnectedColor() {
1627 return UnconnectedPen.color();
1628 }
1629
standardConnectedColor()1630 QColor ItemBase::standardConnectedColor() {
1631 return StandardConnectedColor;
1632 }
1633
standardUnconnectedColor()1634 QColor ItemBase::standardUnconnectedColor() {
1635 return StandardUnconnectedColor;
1636 }
1637
setConnectedColor(QColor & c)1638 void ItemBase::setConnectedColor(QColor & c) {
1639 ConnectedPen.setColor(c);
1640 ConnectedBrush.setColor(c);
1641 }
1642
setUnconnectedColor(QColor & c)1643 void ItemBase::setUnconnectedColor(QColor & c) {
1644 UnconnectedPen.setColor(c);
1645 UnconnectedBrush.setColor(c);
1646 }
1647
translatePropertyName(const QString & key)1648 QString ItemBase::translatePropertyName(const QString & key) {
1649 return TranslatedPropertyNames.value(key.toLower(), key);
1650 }
1651
canEditPart()1652 bool ItemBase::canEditPart() {
1653 return false;
1654 }
1655
hasCustomSVG()1656 bool ItemBase::hasCustomSVG() {
1657 return false;
1658 }
1659
setProp(const QString & prop,const QString & value)1660 void ItemBase::setProp(const QString & prop, const QString & value) {
1661 if (!m_modelPart) return;
1662
1663 //DebugDialog::debug(QString("setting prop %1 %2").arg(prop).arg(value));
1664 m_modelPart->setLocalProp(prop, value);
1665 }
1666
prop(const QString & p)1667 QString ItemBase::prop(const QString & p)
1668 {
1669 if (m_modelPart == NULL) return "";
1670
1671 return m_modelPart->localProp(p).toString();
1672 }
1673
isObsolete()1674 bool ItemBase::isObsolete() {
1675 if (modelPart() == NULL) return false;
1676
1677 return modelPart()->isObsolete();
1678 }
1679
collectExtraInfo(QWidget * parent,const QString & family,const QString & prop,const QString & value,bool swappingEnabled,QString & returnProp,QString & returnValue,QWidget * & returnWidget,bool & hide)1680 bool ItemBase::collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide)
1681 {
1682 Q_UNUSED(hide); // assume this is set by the caller (HtmlInfoView)
1683 returnWidget = NULL;
1684 returnProp = ItemBase::translatePropertyName(prop);
1685 returnValue = value;
1686
1687 if (prop.compare("family", Qt::CaseInsensitive) == 0) {
1688 return true;
1689 }
1690 if (prop.compare("id", Qt::CaseInsensitive) == 0) {
1691 return true;
1692 }
1693 #ifndef QT_NO_DEBUG
1694 if (prop.compare("svg", Qt::CaseInsensitive) == 0 || prop.compare("fzp" , Qt::CaseInsensitive) == 0) {
1695 QFileInfo fileInfo(value);
1696 if (fileInfo.exists()) {
1697 ClickableLabel * label = new ClickableLabel(fileInfo.fileName(), parent);
1698 label->setProperty("path", value);
1699 label->setToolTip(value);
1700 connect(label, SIGNAL(clicked()), this, SLOT(showInFolder()));
1701 returnWidget = label;
1702 }
1703 return true;
1704 }
1705 #endif
1706
1707 QString tempValue = value;
1708 QStringList values = collectValues(family, prop, tempValue);
1709 if (values.count() > 1) {
1710 FamilyPropertyComboBox * comboBox = new FamilyPropertyComboBox(family, prop, parent);
1711 comboBox->setObjectName("infoViewComboBox");
1712
1713 comboBox->addItems(values);
1714 comboBox->setCurrentIndex(comboBox->findText(tempValue));
1715 comboBox->setEnabled(swappingEnabled);
1716 comboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
1717 connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(swapEntry(const QString &)));
1718
1719 returnWidget = comboBox;
1720 m_propsMap.insert(prop, tempValue);
1721 return true;
1722 }
1723
1724 return true;
1725 }
1726
swapEntry(const QString & text)1727 void ItemBase::swapEntry(const QString & text) {
1728 FamilyPropertyComboBox * comboBox = qobject_cast<FamilyPropertyComboBox *>(sender());
1729 if (comboBox == NULL) return;
1730
1731 m_propsMap.insert(comboBox->prop(), text);
1732
1733 InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
1734 if (infoGraphicsView != NULL) {
1735 infoGraphicsView->swap(comboBox->family(), comboBox->prop(), m_propsMap, this);
1736 }
1737 }
1738
setReferenceModel(ReferenceModel * rm)1739 void ItemBase::setReferenceModel(ReferenceModel * rm) {
1740 TheReferenceModel = rm;
1741 }
1742
collectValues(const QString & family,const QString & prop,QString & value)1743 QStringList ItemBase::collectValues(const QString & family, const QString & prop, QString & value) {
1744 Q_UNUSED(value);
1745
1746 if (TheReferenceModel == NULL) return ___emptyStringList___;
1747
1748 QStringList values = CachedValues.value(family + prop, QStringList());
1749 if (values.count() > 0) return values;
1750
1751 values = TheReferenceModel->propValues(family, prop, true);
1752
1753 // sort values numerically
1754 NumberMatcherValues.clear();
1755 bool ok = true;
1756 foreach(QString opt, values) {
1757 int ix = NumberMatcher.indexIn(opt);
1758 if (ix < 0) {
1759 ok = false;
1760 break;
1761 }
1762
1763 double n = TextUtils::convertFromPowerPrefix(NumberMatcher.cap(1) + NumberMatcher.cap(5), "");
1764 NumberMatcherValues.insert(opt, n);
1765 }
1766 if (ok) {
1767 qSort(values.begin(), values.end(), numberValueLessThan);
1768 }
1769
1770 CachedValues.insert(family + prop, values);
1771 //debugInfo("cached " + prop);
1772 //foreach(QString v, values) {
1773 // DebugDialog::debug("\t" + v);
1774 //}
1775 return values;
1776 }
1777
resetValues(const QString & family,const QString & prop)1778 void ItemBase::resetValues(const QString & family, const QString & prop) {
1779 CachedValues.remove(family + prop);
1780 }
1781
hasPartLabel()1782 bool ItemBase::hasPartLabel() {
1783 return true;
1784 }
1785
filename()1786 const QString & ItemBase::filename() {
1787 return m_filename;
1788 }
1789
setFilename(const QString & fn)1790 void ItemBase::setFilename(const QString & fn) {
1791 m_filename = fn;
1792 }
1793
isPlural()1794 ItemBase::PluralType ItemBase::isPlural() {
1795 return ItemBase::NotSure;
1796 }
1797
viewLayerPlacement() const1798 ViewLayer::ViewLayerPlacement ItemBase::viewLayerPlacement() const {
1799 return m_viewLayerPlacement;
1800 }
1801
setViewLayerPlacement(ViewLayer::ViewLayerPlacement viewLayerPlacement)1802 void ItemBase::setViewLayerPlacement(ViewLayer::ViewLayerPlacement viewLayerPlacement) {
1803 m_viewLayerPlacement = viewLayerPlacement;
1804 }
1805
partLabelViewLayerID()1806 ViewLayer::ViewLayerID ItemBase::partLabelViewLayerID() {
1807 if (m_partLabel == NULL) return ViewLayer::UnknownLayer;
1808 if (!m_partLabel->initialized()) return ViewLayer::UnknownLayer;
1809 return m_partLabel->viewLayerID();
1810 }
1811
makePartLabelSvg(bool blackOnly,double dpi,double printerScale)1812 QString ItemBase::makePartLabelSvg(bool blackOnly, double dpi, double printerScale) {
1813 if (m_partLabel == NULL) return "";
1814 if (!m_partLabel->initialized()) return "";
1815 return m_partLabel->makeSvg(blackOnly, dpi, printerScale, true);
1816 }
1817
partLabelScenePos()1818 QPointF ItemBase::partLabelScenePos() {
1819 if (m_partLabel == NULL) return QPointF();
1820 if (!m_partLabel->initialized()) return QPointF();
1821 return m_partLabel->scenePos();
1822 }
1823
partLabelSceneBoundingRect()1824 QRectF ItemBase::partLabelSceneBoundingRect() {
1825 if (m_partLabel == NULL) return QRectF();
1826 if (!m_partLabel->initialized()) return QRectF();
1827 return m_partLabel->sceneBoundingRect();
1828 }
1829
getFlipDoc(ModelPart * modelPart,const QString & filename,ViewLayer::ViewLayerID viewLayerID,ViewLayer::ViewLayerPlacement viewLayerPlacement,QDomDocument & flipDoc,Qt::Orientations orientation)1830 bool ItemBase::getFlipDoc(ModelPart * modelPart, const QString & filename, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement viewLayerPlacement, QDomDocument & flipDoc, Qt::Orientations orientation)
1831 {
1832 if (!modelPart->flippedSMD()) {
1833 // add copper1 layer to THT if it is missing
1834 fixCopper1(modelPart, filename, viewLayerID, viewLayerPlacement, flipDoc);
1835 }
1836
1837 if (viewLayerPlacement == ViewLayer::NewBottom) {
1838 if (modelPart->flippedSMD()) {
1839 if (viewLayerID == ViewLayer::Copper0) {
1840 SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), GraphicsUtils::SVGDPI, orientation);
1841 return true;
1842 }
1843 else if (viewLayerID == ViewLayer::Silkscreen0) {
1844 SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen0), GraphicsUtils::SVGDPI, orientation);
1845 return true;
1846 }
1847 return false;
1848 }
1849
1850 if (modelPart->itemType() == ModelPart::Part) {
1851 if (viewLayerID == ViewLayer::Copper0) {
1852 SvgFlattener::replaceElementID(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), "");
1853 //QString t1 = flipDoc.toString();
1854 SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), GraphicsUtils::SVGDPI, orientation);
1855 //QString t2 = flipDoc.toString();
1856 return true;
1857 }
1858 if (viewLayerID == ViewLayer::Copper1) {
1859 SvgFlattener::replaceElementID(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), "");
1860 //QString t1 = flipDoc.toString();
1861 SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1), GraphicsUtils::SVGDPI, orientation);
1862 //QString t2 = flipDoc.toString();
1863 return true;
1864 }
1865 else if (viewLayerID == ViewLayer::Silkscreen0) {
1866 SvgFlattener::flipSMDSvg(filename, "", flipDoc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen1), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Silkscreen0), GraphicsUtils::SVGDPI, orientation);
1867 return true;
1868 }
1869 }
1870 }
1871
1872 return false;
1873 }
1874
fixCopper1(ModelPart * modelPart,const QString & filename,ViewLayer::ViewLayerID viewLayerID,ViewLayer::ViewLayerPlacement viewLayerPlacement,QDomDocument & doc)1875 bool ItemBase::fixCopper1(ModelPart * modelPart, const QString & filename, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement viewLayerPlacement, QDomDocument & doc)
1876 {
1877 Q_UNUSED(viewLayerPlacement);
1878 if (viewLayerID != ViewLayer::Copper1) return false;
1879 if (!modelPart->needsCopper1()) return false;
1880
1881 return TextUtils::addCopper1(filename, doc, ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper0), ViewLayer::viewLayerXmlNameFromID(ViewLayer::Copper1));
1882 }
1883
calcRotation(QTransform & rotation,QPointF center,ViewGeometry & vg2)1884 void ItemBase::calcRotation(QTransform & rotation, QPointF center, ViewGeometry & vg2)
1885 {
1886 vg2.setLoc(GraphicsUtils::calcRotation(rotation, center, pos(), boundingRectWithoutLegs().center()));
1887 }
1888
updateConnectors()1889 void ItemBase::updateConnectors()
1890 {
1891 if (!isEverVisible()) return;
1892
1893 QList<ConnectorItem *> visited;
1894 foreach(ConnectorItem * connectorItem, cachedConnectorItems()) {
1895 connectorItem->restoreColor(visited);
1896 }
1897 //DebugDialog::debug(QString("set up connectors restore:%1").arg(count));
1898 }
1899
moduleID()1900 const QString & ItemBase::moduleID() {
1901 if (m_modelPart) return m_modelPart->moduleID();
1902
1903 return ___emptyString___;
1904 }
1905
moveLock()1906 bool ItemBase::moveLock() {
1907 return m_moveLock;
1908 }
1909
setMoveLock(bool moveLock)1910 void ItemBase::setMoveLock(bool moveLock)
1911 {
1912 m_moveLock = moveLock;
1913 if (moveLock) {
1914 if (m_moveLockItem == NULL) {
1915 if (!MoveLockRenderer.isValid()) {
1916 QString fn(":resources/images/part_lock.svg");
1917 bool success = MoveLockRenderer.load(fn);
1918 DebugDialog::debug(QString("movelock load success %1").arg(success));
1919 }
1920
1921 m_moveLockItem = new QGraphicsSvgItem();
1922 m_moveLockItem->setAcceptHoverEvents(false);
1923 m_moveLockItem->setAcceptedMouseButtons(Qt::NoButton);
1924 m_moveLockItem->setSharedRenderer(&MoveLockRenderer);
1925 m_moveLockItem->setPos(0,0);
1926 m_moveLockItem->setZValue(-99999);
1927 m_moveLockItem->setParentItem(this);
1928 m_moveLockItem->setVisible(true);
1929 }
1930
1931 }
1932 else {
1933 if (m_moveLockItem) {
1934 delete m_moveLockItem;
1935 m_moveLockItem = NULL;
1936 }
1937 }
1938
1939 if (m_stickyItem) {
1940 m_stickyItem->setPos(m_moveLockItem == NULL ? 0 : m_moveLockItem->boundingRect().width() + 1, 0);
1941 }
1942
1943 update();
1944 }
1945
debugInfo(const QString & msg) const1946 void ItemBase::debugInfo(const QString & msg) const
1947 {
1948
1949 #ifndef QT_NO_DEBUG
1950 debugInfo2(msg);
1951 #else
1952 Q_UNUSED(msg);
1953 #endif
1954 }
1955
debugInfo2(const QString & msg) const1956 void ItemBase::debugInfo2(const QString & msg) const
1957 {
1958 DebugDialog::debug(QString("%1 ti:'%2' id:%3 it:'%4' vid:%9 vlid:%5 spec:%6 x:%11 y:%12 z:%10 flg:%7 gi:%8")
1959 .arg(msg)
1960 .arg(this->constTitle())
1961 .arg(this->id())
1962 .arg(this->instanceTitle())
1963 .arg(this->viewLayerID())
1964 .arg(this->viewLayerPlacement())
1965 .arg(this->wireFlags())
1966 .arg((long) dynamic_cast<const QGraphicsItem *const>(this), 0, 16)
1967 .arg(m_viewID)
1968 .arg(this->zValue())
1969 .arg(this->pos().x())
1970 .arg(this->pos().y())
1971 );
1972
1973 /*
1974 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
1975 if (connectorItem) connectorItem->debugInfo("\t");
1976 }
1977 */
1978 }
1979
addedToScene(bool temporary)1980 void ItemBase::addedToScene(bool temporary) {
1981 if (this->scene() && instanceTitle().isEmpty() && !temporary) {
1982 setTooltip();
1983 if (isBaseSticky() && isLocalSticky()) {
1984 // ensure icon is visible
1985 setLocalSticky(true);
1986 }
1987 }
1988 }
1989
hasPartNumberProperty()1990 bool ItemBase::hasPartNumberProperty()
1991 {
1992 return true;
1993 }
1994
collectPropsMap(QString & family,QMap<QString,QString> & propsMap)1995 void ItemBase::collectPropsMap(QString & family, QMap<QString, QString> & propsMap) {
1996 QHash<QString, QString> properties;
1997 properties = m_modelPart->properties();
1998 family = properties.value("family", "");
1999 foreach (QString key, properties.keys()) {
2000 if (key.compare("family") == 0) continue;
2001 if (key.compare("id") == 0) continue;
2002
2003 QString value = properties.value(key,"");
2004 QString tempValue = value;
2005 QStringList values = collectValues(family, key, tempValue);
2006 propsMap.insert(key, tempValue);
2007 DebugDialog::debug(QString("props map %1 %2").arg(key).arg(tempValue));
2008 }
2009 }
2010
setDropOffset(QPointF)2011 void ItemBase::setDropOffset(QPointF)
2012 {
2013 }
2014
hasRubberBandLeg() const2015 bool ItemBase::hasRubberBandLeg() const
2016 {
2017 return m_hasRubberBandLeg;
2018 }
2019
sceneEvent(QEvent * event)2020 bool ItemBase::sceneEvent(QEvent *event)
2021 {
2022 return QGraphicsSvgItem::sceneEvent(event);
2023 }
2024
cachedConnectorItems()2025 const QList<ConnectorItem *> & ItemBase::cachedConnectorItems()
2026 {
2027 if (m_cachedConnectorItems.isEmpty()) {
2028 foreach (QGraphicsItem * childItem, childItems()) {
2029 ConnectorItem * connectorItem = dynamic_cast<ConnectorItem *>(childItem);
2030 if (connectorItem != NULL) m_cachedConnectorItems.append(connectorItem);
2031 }
2032 }
2033
2034 return m_cachedConnectorItems;
2035 }
2036
cachedConnectorItemsConst() const2037 const QList<ConnectorItem *> & ItemBase::cachedConnectorItemsConst() const
2038 {
2039 return m_cachedConnectorItems;
2040 }
2041
clearConnectorItemCache()2042 void ItemBase::clearConnectorItemCache()
2043 {
2044 m_cachedConnectorItems.clear();
2045 }
2046
killRubberBandLeg()2047 void ItemBase::killRubberBandLeg() {
2048 if (!hasRubberBandLeg()) return;
2049
2050 prepareGeometryChange();
2051
2052 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
2053 connectorItem->killRubberBandLeg();
2054 }
2055 }
2056
wireFlags() const2057 ViewGeometry::WireFlags ItemBase::wireFlags() const {
2058 return m_viewGeometry.wireFlags();
2059 }
2060
boundingRectWithoutLegs() const2061 QRectF ItemBase::boundingRectWithoutLegs() const
2062 {
2063 return boundingRect();
2064 }
2065
boundingRect() const2066 QRectF ItemBase::boundingRect() const
2067 {
2068 FSvgRenderer * frenderer = fsvgRenderer();
2069 if (frenderer == NULL) {
2070 return QGraphicsSvgItem::boundingRect();
2071 }
2072
2073 QSizeF s = frenderer->defaultSizeF();
2074 QRectF r(0,0, s.width(), s.height());
2075 return r;
2076 }
2077
hoverShape() const2078 QPainterPath ItemBase::hoverShape() const
2079 {
2080 return shape();
2081 }
2082
getCursor(Qt::KeyboardModifiers)2083 const QCursor * ItemBase::getCursor(Qt::KeyboardModifiers)
2084 {
2085 return CursorMaster::MoveCursor;
2086 }
2087
partLabel()2088 PartLabel * ItemBase::partLabel() {
2089 return m_partLabel;
2090 }
2091
doneLoading()2092 void ItemBase::doneLoading() {
2093 }
2094
family()2095 QString ItemBase::family() {
2096 return modelPart()->family();
2097 }
2098
getPixmap(QSize size)2099 QPixmap * ItemBase::getPixmap(QSize size) {
2100 return FSvgRenderer::getPixmap(renderer(), size);
2101 }
2102
fsvgRenderer() const2103 FSvgRenderer * ItemBase::fsvgRenderer() const {
2104 if (m_fsvgRenderer) return m_fsvgRenderer;
2105
2106 FSvgRenderer * f = qobject_cast<FSvgRenderer *>(renderer());
2107 if (f == NULL) {
2108 DebugDialog::debug("shouldn't happen: missing fsvgRenderer");
2109 }
2110 return f;
2111 }
2112
setSharedRendererEx(FSvgRenderer * newRenderer)2113 void ItemBase::setSharedRendererEx(FSvgRenderer * newRenderer) {
2114 if (newRenderer != m_fsvgRenderer) {
2115 setSharedRenderer(newRenderer); // original renderer is deleted if it is not shared
2116 if (m_fsvgRenderer) delete m_fsvgRenderer;
2117 m_fsvgRenderer = newRenderer;
2118 }
2119 else {
2120 update();
2121 }
2122 m_size = newRenderer->defaultSizeF();
2123 //debugInfo(QString("set size %1, %2").arg(m_size.width()).arg(m_size.height()));
2124 }
2125
reloadRenderer(const QString & svg,bool fastLoad)2126 bool ItemBase::reloadRenderer(const QString & svg, bool fastLoad) {
2127 if (!svg.isEmpty()) {
2128 //DebugDialog::debug(svg);
2129 prepareGeometryChange();
2130 bool result = fastLoad ? fsvgRenderer()->fastLoad(svg.toUtf8()) : fsvgRenderer()->loadSvgString(svg.toUtf8());
2131 if (result) {
2132 update();
2133 }
2134
2135 return result;
2136 }
2137
2138 return false;
2139 }
2140
resetRenderer(const QString & svg)2141 bool ItemBase::resetRenderer(const QString & svg) {
2142 // use resetRenderer instead of reloadRender because if the svg size changes, with reloadRenderer the new image seems to be scaled to the old bounds
2143 // what I don't understand is why the old renderer causes a crash if it is deleted here
2144
2145 QString nothing;
2146 return resetRenderer(svg, nothing);
2147 }
2148
resetRenderer(const QString & svg,QString & newSvg)2149 bool ItemBase::resetRenderer(const QString & svg, QString & newSvg) {
2150 // use resetRenderer instead of reloadRender because if the svg size changes, with reloadRenderer the new image seems to be scaled to the old bounds
2151 // what I don't understand is why the old renderer causes a crash if it is deleted here
2152
2153 FSvgRenderer * newRenderer = new FSvgRenderer();
2154 bool result = newRenderer->loadSvgString(svg, newSvg);
2155 if (result) {
2156 //DebugDialog::debug("reloaded");
2157 //DebugDialog::debug(newSvg);
2158 setSharedRendererEx(newRenderer);
2159 }
2160 else {
2161 delete newRenderer;
2162 }
2163 return result;
2164 }
2165
getPixmaps(QPixmap * & pixmap1,QPixmap * & pixmap2,QPixmap * & pixmap3,bool swappingEnabled,QSize size)2166 void ItemBase::getPixmaps(QPixmap * & pixmap1, QPixmap * & pixmap2, QPixmap * & pixmap3, bool swappingEnabled, QSize size)
2167 {
2168 pixmap1 = getPixmap(ViewLayer::BreadboardView, swappingEnabled, size);
2169 pixmap2 = getPixmap(ViewLayer::SchematicView, swappingEnabled, size);
2170 pixmap3 = getPixmap(ViewLayer::PCBView, swappingEnabled, size);
2171 }
2172
getPixmap(ViewLayer::ViewID vid,bool swappingEnabled,QSize size)2173 QPixmap * ItemBase::getPixmap(ViewLayer::ViewID vid, bool swappingEnabled, QSize size)
2174 {
2175 ItemBase * vItemBase = NULL;
2176
2177 if (viewID() == vid) {
2178 if (!isEverVisible()) return NULL;
2179 }
2180 else {
2181 vItemBase = modelPart()->viewItem(vid);
2182 if (vItemBase && !vItemBase->isEverVisible()) return NULL;
2183 }
2184
2185 vid = useViewIDForPixmap(vid, swappingEnabled);
2186 if (vid == ViewLayer::UnknownView) return NULL;
2187
2188 if (viewID() == vid) {
2189 return getPixmap(size);
2190 }
2191
2192 if (vItemBase) {
2193 return vItemBase->getPixmap(size);
2194 }
2195
2196
2197 if (!modelPart()->hasViewFor(vid)) return NULL;
2198
2199 QString baseName = modelPart()->hasBaseNameFor(vid);
2200 if (baseName.isEmpty()) return NULL;
2201
2202 QString filename = PartFactory::getSvgFilename(modelPart(), baseName, true, true);
2203 if (filename.isEmpty()) {
2204 return NULL;
2205 }
2206
2207 QSvgRenderer renderer(filename);
2208
2209 QPixmap * pixmap = new QPixmap(size);
2210 pixmap->fill(Qt::transparent);
2211 QPainter painter(pixmap);
2212 // preserve aspect ratio
2213 QSize def = renderer.defaultSize();
2214 double newW = size.width();
2215 double newH = newW * def.height() / def.width();
2216 if (newH > size.height()) {
2217 newH = size.height();
2218 newW = newH * def.width() / def.height();
2219 }
2220 QRectF bounds((size.width() - newW) / 2.0, (size.height() - newH) / 2.0, newW, newH);
2221 renderer.render(&painter, bounds);
2222 painter.end();
2223
2224 return pixmap;
2225 }
2226
useViewIDForPixmap(ViewLayer::ViewID vid,bool)2227 ViewLayer::ViewID ItemBase::useViewIDForPixmap(ViewLayer::ViewID vid, bool)
2228 {
2229 if (vid == ViewLayer::BreadboardView) {
2230 return ViewLayer::IconView;
2231 }
2232
2233 return vid;
2234 }
2235
makeLocalModifications(QByteArray &,const QString &)2236 bool ItemBase::makeLocalModifications(QByteArray &, const QString & ) {
2237 // a bottleneck for modifying part svg xml at setupImage time
2238 return false;
2239 }
2240
showConnectors(const QStringList & connectorIDs)2241 void ItemBase::showConnectors(const QStringList & connectorIDs) {
2242 foreach (ConnectorItem * connectorItem, cachedConnectorItems()) {
2243 if (connectorIDs.contains(connectorItem->connectorSharedID())) {
2244 connectorItem->setVisible(true);
2245 }
2246 }
2247 }
2248
setItemIsSelectable(bool selectable)2249 void ItemBase::setItemIsSelectable(bool selectable) {
2250 setFlag(QGraphicsItem::ItemIsSelectable, selectable);
2251 }
2252
inRotation()2253 bool ItemBase::inRotation() {
2254 return m_inRotation;
2255 }
2256
setInRotation(bool val)2257 void ItemBase::setInRotation(bool val) {
2258 m_inRotation = val;
2259 }
2260
addSubpart(ItemBase * sub)2261 void ItemBase::addSubpart(ItemBase * sub)
2262 {
2263 this->debugInfo("super");
2264 sub->debugInfo("\t");
2265 m_subparts.append(sub);
2266 sub->setSuperpart(this);
2267 foreach (ConnectorItem * connectorItem, sub->cachedConnectorItems()) {
2268 Bus * subbus = connectorItem->bus();
2269 Connector * subconnector = NULL;
2270 if (subbus == NULL) {
2271 subconnector = connectorItem->connector();
2272 if (subconnector) {
2273 subbus = new Bus(NULL, NULL);
2274 subconnector->setBus(subbus);
2275 }
2276 }
2277
2278 Connector * connector = modelPart()->getConnector(connectorItem->connectorSharedID());
2279 if (connector) {
2280 if (subbus) subbus->addSubConnector(connector);
2281 if (subconnector) {
2282 Bus * bus = connector->bus();
2283 if (bus == NULL) {
2284 bus = new Bus(NULL, NULL);
2285 connector->setBus(bus);
2286 }
2287
2288 bus->addSubConnector(subconnector);
2289 }
2290 }
2291 }
2292 }
2293
setSuperpart(ItemBase * super)2294 void ItemBase::setSuperpart(ItemBase * super) {
2295 m_superpart = super;
2296 }
2297
superpart()2298 ItemBase * ItemBase::superpart() {
2299 return m_superpart;
2300 }
2301
findSubpart(const QString & connectorID,ViewLayer::ViewLayerPlacement spec)2302 ItemBase * ItemBase::findSubpart(const QString & connectorID, ViewLayer::ViewLayerPlacement spec) {
2303 foreach (ItemBase * itemBase, m_subparts) {
2304 ConnectorItem * connectorItem = itemBase->findConnectorItemWithSharedID(connectorID, spec);
2305 if (connectorItem) return itemBase;
2306 }
2307
2308 return NULL;
2309 }
2310
subparts()2311 const QList< QPointer<ItemBase> > & ItemBase::subparts()
2312 {
2313 return m_subparts;
2314 }
2315
prepareProps(ModelPart * modelPart,bool wantDebug,QStringList & keys)2316 QHash<QString, QString> ItemBase::prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys)
2317 {
2318 m_propsMap.clear();
2319
2320 // TODO: someday get local props
2321 QHash<QString, QString> props = modelPart->properties();
2322 QString family = props.value("family", "").toLower();
2323
2324 // ensure family is first;
2325 keys = props.keys();
2326 keys.removeOne("family");
2327 keys.push_front("family");
2328
2329 // ensure part number is last
2330 QString partNumber = props.value(ModelPartShared::PartNumberPropertyName, "").toLower();
2331 keys.removeOne(ModelPartShared::PartNumberPropertyName);
2332
2333 if (wantDebug) {
2334 props.insert("id", QString("%1 %2 %3")
2335 .arg(QString::number(id()))
2336 .arg(modelPart->moduleID())
2337 .arg(ViewLayer::viewLayerNameFromID(viewLayerID()))
2338 );
2339 keys.insert(1, "id");
2340
2341 int insertAt = 2;
2342 PaletteItemBase * paletteItemBase = qobject_cast<PaletteItemBase *>(this);
2343 if (paletteItemBase != NULL) {
2344 props.insert("svg", paletteItemBase->filename());
2345 keys.insert(insertAt++, "svg");
2346 }
2347 props.insert("class", this->metaObject()->className());
2348 keys.insert(insertAt++, "class");
2349
2350 if (modelPart->modelPartShared()) {
2351 props.insert("fzp", modelPart->path());
2352 keys.insert(insertAt++, "fzp");
2353 }
2354 }
2355
2356 // ensure part number is last
2357 if (hasPartNumberProperty()) {
2358 keys.append(ModelPartShared::PartNumberPropertyName);
2359 }
2360
2361 return props;
2362 }
2363
setSquashShape(bool squashShape)2364 void ItemBase::setSquashShape(bool squashShape) {
2365 m_squashShape = squashShape;
2366 }
2367
createShape(LayerAttributes & layerAttributes)2368 void ItemBase::createShape(LayerAttributes & layerAttributes) {
2369 switch (layerAttributes.viewID) {
2370 case ViewLayer::SchematicView:
2371 case ViewLayer::PCBView:
2372 break;
2373 default:
2374 return;
2375 }
2376
2377 if (!isEverVisible()) return;
2378
2379 QString errorStr;
2380 int errorLine;
2381 int errorColumn;
2382 QDomDocument doc;
2383 if (!doc.setContent(layerAttributes.loaded(), &errorStr, &errorLine, &errorColumn)) {
2384 return;
2385 }
2386
2387 QDomElement root = doc.documentElement();
2388
2389 QRectF viewBox;
2390 double w, h;
2391 TextUtils::ensureViewBox(doc, 1, viewBox, true, w, h, true);
2392 double svgDPI = viewBox.width() / w;
2393 int selectionExtra = layerAttributes.viewID == ViewLayer::SchematicView ? 20 : 10;
2394 SvgFileSplitter::forceStrokeWidth(root, svgDPI * selectionExtra / GraphicsUtils::SVGDPI, "#000000", true, false);
2395
2396 double imageDPI = GraphicsUtils::SVGDPI;
2397 QRectF sourceRes(0, 0, w * imageDPI, h * imageDPI);
2398 QSize imgSize(qCeil(sourceRes.width()), qCeil(sourceRes.height()));
2399 QImage image(imgSize, QImage::Format_Mono);
2400 image.fill(0xffffffff);
2401 renderOne(&doc, &image, sourceRes);
2402 QBitmap bitmap = QBitmap::fromImage(image);
2403 QRegion region(bitmap);
2404 m_selectionShape.addRegion(region);
2405
2406 #ifndef QT_NODEBUG
2407 //QFileInfo info(layerAttributes.filename());
2408 //bitmap.save(FolderUtils::getUserDataStorePath("") + "/bitmap." + info.completeBaseName() + "." + QString::number(layerAttributes.viewLayerID) + ".png");
2409 //image.save(FolderUtils::getUserDataStorePath("") + "/image." + info.completeBaseName() + "." + QString::number(layerAttributes.viewLayerID) + ".png");
2410 #endif
2411 }
2412
selectionShape()2413 const QPainterPath & ItemBase::selectionShape() {
2414 return m_selectionShape;
2415 }
2416
setTransform2(const QTransform & transform)2417 void ItemBase::setTransform2(const QTransform & transform)
2418 {
2419 setTransform(transform);
2420 }
2421
renderOne(QDomDocument * masterDoc,QImage * image,const QRectF & renderRect)2422 void ItemBase::renderOne(QDomDocument * masterDoc, QImage * image, const QRectF & renderRect) {
2423 QByteArray byteArray = masterDoc->toByteArray();
2424 QSvgRenderer renderer(byteArray);
2425 QPainter painter;
2426 painter.begin(image);
2427 painter.setRenderHint(QPainter::Antialiasing, false);
2428 painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
2429 renderer.render(&painter, renderRect);
2430 painter.end();
2431 }
2432
2433
initLayerAttributes(LayerAttributes & layerAttributes,ViewLayer::ViewID viewID,ViewLayer::ViewLayerID viewLayerID,ViewLayer::ViewLayerPlacement viewLayerPlacement,bool doConnectors,bool doCreateShape)2434 void ItemBase::initLayerAttributes(LayerAttributes & layerAttributes, ViewLayer::ViewID viewID, ViewLayer::ViewLayerID viewLayerID, ViewLayer::ViewLayerPlacement viewLayerPlacement, bool doConnectors, bool doCreateShape) {
2435 layerAttributes.viewID = viewID;
2436 layerAttributes.viewLayerID = viewLayerID;
2437 layerAttributes.viewLayerPlacement = viewLayerPlacement;
2438 layerAttributes.doConnectors = doConnectors;
2439 layerAttributes.createShape = doCreateShape;
2440 InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
2441 if (infoGraphicsView != NULL) {
2442 layerAttributes.orientation = infoGraphicsView->smdOrientation();
2443 }
2444 }
2445
showInFolder()2446 void ItemBase::showInFolder() {
2447 QString path = sender()->property("path").toString();
2448 if (!path.isEmpty()) {
2449 FolderUtils::showInFolder(path);
2450 QClipboard *clipboard = QApplication::clipboard();
2451 if (clipboard != NULL) {
2452 clipboard->setText(path);
2453 }
2454 }
2455 }
2456
getInspectorTitle()2457 QString ItemBase::getInspectorTitle() {
2458 QString t = instanceTitle();
2459 if (!t.isEmpty()) return t;
2460
2461 return title();
2462 }
2463
setInspectorTitle(const QString & oldText,const QString & newText)2464 void ItemBase::setInspectorTitle(const QString & oldText, const QString & newText) {
2465 InfoGraphicsView * infoGraphicsView = InfoGraphicsView::getInfoGraphicsView(this);
2466 if (infoGraphicsView == NULL) return;
2467
2468 DebugDialog::debug(QString("set instance title to %1").arg(newText));
2469 infoGraphicsView->setInstanceTitle(id(), oldText, newText, true, false);
2470 }
2471