diff options
Diffstat (limited to 'src/itemlibrary.cpp')
-rw-r--r-- | src/itemlibrary.cpp | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/src/itemlibrary.cpp b/src/itemlibrary.cpp new file mode 100644 index 0000000..d749f7f --- /dev/null +++ b/src/itemlibrary.cpp @@ -0,0 +1,476 @@ +/*************************************************************************** + * Copyright (C) 2003-2005 by David Saxton * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "config.h" + +#include "cnitem.h" +#include "canvasitemparts.h" +#include "circuitdocument.h" +#include "component.h" +#include "ecsubcircuit.h" +#include "ecnode.h" +#include "itemlibrary.h" +#include "node.h" +#include "subcircuits.h" + +#ifdef MECHANICS +#include "chassiscircular2.h" +#endif + +#include "dptext.h" +#include "dpline.h" +#include "solidshape.h" + +#include "callsub.h" +#include "count.h" +#include "delay.h" +#include "embed.h" +#include "end.h" +#include "inputbutton.h" +#include "interrupt.h" +#include "forloop.h" +#include "keypad.h" +#include "pulse.h" +#include "readport.h" +#include "repeat.h" +#include "setpin.h" +#include "sevenseg.h" +#include "start.h" +#include "sub.h" +#include "testpin.h" +#include "unary.h" +#include "varassignment.h" +#include "varcomparison.h" +#include "while.h" +#include "writeport.h" + +#include "addac.h" +#include "bidirled.h" +#include "binarycounter.h" +#include "bussplitter.h" +#include "demultiplexer.h" +#include "dependentsource.h" +#include "discretelogic.h" +#include "externalconnection.h" +#include "flipflop.h" +#include "fulladder.h" +#include "inductor.h" +#include "magnitudecomparator.h" +#include "matrixdisplay.h" +#include "matrixdisplaydriver.h" +#include "meter.h" +#include "multiinputgate.h" +#include "multiplexer.h" +#include "parallelportcomponent.h" +#include "piccomponent.h" +#include "pushswitch.h" +#include "probe.h" +#include "ram.h" +#include "resistordip.h" +#include "rotoswitch.h" +#include "serialportcomponent.h" +#include "toggleswitch.h" + +#include "ec555.h" +#include "ecbcdto7segment.h" +#include "eccapacitor.h" +#include "ecclockinput.h" +#include "eccurrentsignal.h" +#include "eccurrentsource.h" +#include "ecdiode.h" +#include "ecfixedvoltage.h" +#include "ecground.h" +#include "eckeypad.h" +#include "ecled.h" +#include "ecbjt.h" +#include "ecopamp.h" +#include "ecpotentiometer.h" +#include "ecresistor.h" +#include "ecsevensegment.h" +#include "ecsignallamp.h" +#include "ecvoltagesignal.h" +#include "ecvoltagesource.h" + +#include "pinmapping.h" + +#include "libraryitem.h" + +#include "kdebug.h" +#include <kiconloader.h> +#include <qbitmap.h> +#include <qimage.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qregexp.h> + +#include <cassert> + +ItemLibrary::ItemLibrary() +{ + addFlowParts(); + addComponents(); + addMechanics(); + addDrawParts(); +} + + +ItemLibrary::~ItemLibrary() +{ + const LibraryItemList::iterator end = m_items.end(); + for ( LibraryItemList::iterator it = m_items.begin(); it != end; ++it ) + { + delete *it; + } + m_items.clear(); +} + + +void ItemLibrary::addFlowParts() +{ + // Container loops + addLibraryItem( Repeat::libraryItem() ); + addLibraryItem( While::libraryItem() ); + addLibraryItem( ForLoop::libraryItem() ); + + // Variable operations + addLibraryItem( Unary::libraryItem() ); + addLibraryItem( VarAssignment::libraryItem() ); + addLibraryItem( VarComparison::libraryItem() ); + + // I/O + addLibraryItem( SetPin::libraryItem() ); + addLibraryItem( TestPin::libraryItem() ); + addLibraryItem( WritePort::libraryItem() ); + addLibraryItem( ReadPort::libraryItem() ); + + // Functions + addLibraryItem( SevenSeg::libraryItem() ); +// addLibraryItem( Pulse::libraryItem() ); + addLibraryItem( Keypad::libraryItem() ); +// addLibraryItem( Count::libraryItem() ); +// addLibraryItem( InputButton::libraryItem() ); + addLibraryItem( Delay::libraryItem() ); + + // Common + addLibraryItem( Embed::libraryItem() ); + addLibraryItem( CallSub::libraryItem() ); +// addLibraryItem( Interrupt::libraryItem() ); + addLibraryItem( Sub::libraryItem() ); + addLibraryItem( End::libraryItem() ); + addLibraryItem( Start::libraryItem() ); +} + + +void ItemLibrary::addComponents() +{ + // Integrated Circuits + addLibraryItem( ECBCDTo7Segment::libraryItem() ); + addLibraryItem( MatrixDisplayDriver::libraryItem() ); + addLibraryItem( BinaryCounter::libraryItem() ); + addLibraryItem( DAC::libraryItem() ); + addLibraryItem( ADC::libraryItem() ); + addLibraryItem( ECOpAmp::libraryItem() ); + addLibraryItem( MagnitudeComparator::libraryItem() ); + addLibraryItem( Demultiplexer::libraryItem() ); + addLibraryItem( Multiplexer::libraryItem() ); + addLibraryItem( FullAdder::libraryItem() ); + addLibraryItem( RAM::libraryItem() ); + addLibraryItem( EC555::libraryItem() ); + addLibraryItem( ECDFlipFlop::libraryItem() ); + addLibraryItem( ECSRFlipFlop::libraryItem() ); + addLibraryItem( ECJKFlipFlop::libraryItem() ); +#ifndef NO_GPSIM + addLibraryItem( PICComponent::libraryItem() ); +#endif + + // Connections + addLibraryItem( ParallelPortComponent::libraryItem() ); + addLibraryItem( SerialPortComponent::libraryItem() ); + addLibraryItem( ExternalConnection::libraryItem() ); + addLibraryItem( BusSplitter::libraryItem() ); + + // Logic + addLibraryItem( ECXnor::libraryItem() ); + addLibraryItem( ECXor::libraryItem() ); + addLibraryItem( ECNor::libraryItem() ); + addLibraryItem( ECOr::libraryItem() ); + addLibraryItem( ECNand::libraryItem() ); + addLibraryItem( ECAnd::libraryItem() ); + addLibraryItem( Inverter::libraryItem() ); + addLibraryItem( Buffer::libraryItem() ); + addLibraryItem( ECClockInput::libraryItem() ); + addLibraryItem( ECLogicOutput::libraryItem() ); + addLibraryItem( ECLogicInput::libraryItem() ); + + + // Outputs +// addLibraryItem( FrequencyMeter::libraryItem() ); + addLibraryItem( CurrentProbe::libraryItem() ); + addLibraryItem( VoltageProbe::libraryItem() ); + addLibraryItem( LogicProbe::libraryItem() ); + addLibraryItem( ECAmmeter::libraryItem() ); + addLibraryItem( ECVoltMeter::libraryItem() ); + addLibraryItem( MatrixDisplay::libraryItem() ); + addLibraryItem( ECSevenSegment::libraryItem() ); + addLibraryItem( BiDirLED::libraryItem() ); + addLibraryItem( ECSignalLamp::libraryItem() ); + addLibraryItem( ECLed::libraryItem() ); + + // Switches + addLibraryItem( ECRotoSwitch::libraryItem() ); + addLibraryItem( ECDPDT::libraryItem() ); + addLibraryItem( ECSPDT::libraryItem() ); + addLibraryItem( ECDPST::libraryItem() ); + addLibraryItem( ECSPST::libraryItem() ); + addLibraryItem( ECKeyPad::libraryItem() ); + addLibraryItem( ECPTBSwitch::libraryItem() ); + addLibraryItem( ECPTMSwitch::libraryItem() ); + + + // Discrete + addLibraryItem( ECPotentiometer::libraryItem() ); + addLibraryItem( ResistorDIP::libraryItem() ); + addLibraryItem( ECBJT::libraryItemPNP() ); + addLibraryItem( ECBJT::libraryItemNPN() ); + addLibraryItem( Inductor::libraryItem() ); + addLibraryItem( ECDiode::libraryItem() ); + addLibraryItem( ECCapacitor::libraryItem() ); + addLibraryItem( ECResistor::libraryItem() ); + + // Dependent Sources + addLibraryItem( ECVCVS::libraryItem() ); + addLibraryItem( ECVCCS::libraryItem() ); + addLibraryItem( ECCCVS::libraryItem() ); + addLibraryItem( ECCCCS::libraryItem() ); + + // Independent Sources + addLibraryItem( ECCurrentSignal::libraryItem() ); + addLibraryItem( ECVoltageSignal::libraryItem() ); + addLibraryItem( ECCurrentSource::libraryItem() ); + addLibraryItem( ECGround::libraryItem() ); + addLibraryItem( ECFixedVoltage::libraryItem() ); + addLibraryItem( ECCell::libraryItem() ); + + // Other + addLibraryItem( ECSubcircuit::libraryItem() ); + addLibraryItem( PIC_IC::libraryItem() ); +} + + +void ItemLibrary::addDrawParts() +{ + addLibraryItem( DPText::libraryItem() ); + addLibraryItem( DPLine::libraryItem() ); + addLibraryItem( DPArrow::libraryItem() ); + addLibraryItem( DPRectangle::libraryItem() ); + addLibraryItem( DPEllipse::libraryItem() ); +} + + +void ItemLibrary::addMechanics() +{ +#ifdef MECHANICS + addLibraryItem( ChassisCircular2::libraryItem() ); +#endif +} + + +void ItemLibrary::addLibraryItem( LibraryItem *item ) +{ + m_items.append(item); +} + + +Item *ItemLibrary::createItem( const QString &id, ItemDocument *itemDocument, bool newItem, const char *newId, bool finishCreation ) +{ + Item * item = 0l; + if ( id.startsWith("sc/") ) + { + // Is a subcircuit... + + CircuitDocument * circuitDocument = dynamic_cast<CircuitDocument*>(itemDocument); + if (!circuitDocument) + { + kdWarning() << "Cannot create subcircuit without a circuit document" << endl; + return 0l; + } + + QString temp = id; + int numId = temp.remove("sc/").toInt(); + + item = subcircuits()->createSubcircuit( numId, /*id,*/ circuitDocument, newItem, newId ); + } + + else + { + const LibraryItemList::iterator end = m_items.end(); + LibraryItemList::iterator it = m_items.begin(); + for ( ; it != end; ++it ) + { + if ( (*it)->allIDs().contains(id) ) + { + item = (*it)->createItemFnPtr()( itemDocument, newItem, newId ); + item->m_type = (*it)->activeID(); + break; + } + } + + if ( it == end ) + kdWarning() << "Could not find the item constructor for id " << id << endl; + } + + if ( finishCreation && item ) + item->finishedCreation(); + + return item; +} + + +QImage ItemLibrary::itemImage( Item *item, const uint maxSize ) +{ + Component *component = dynamic_cast<Component*>(item); + + QRect bound = item->boundingRect().normalize(); + bound.setLeft( bound.left()-8 ); + bound.setRight( bound.right()+8 ); + bound.setTop( bound.top()-8 ); + bound.setBottom( bound.bottom()+8 ); + + // We want a nice square bounding rect + const int dy = bound.width() - bound.height(); + if ( dy > 0 ) + { + bound.setTop( bound.top()-(dy/2) ); + bound.setBottom( bound.bottom()+(dy/2) ); + } + else if ( dy < 0 ) + { + bound.setLeft( bound.left()+(dy/2) ); + bound.setRight( bound.right()-(dy/2) ); + } + + const bool cache = ((bound.width()*bound.height()) > (int)maxSize); + QString type; + if ( cache && m_imageMap.contains(item->type()) ) + return m_imageMap[item->type()]; + + // Create pixmap big enough to contain CNItem and surrounding nodes + // and copy the button grab to it + + QPixmap pm( bound.size() ); + + QBitmap mask( bound.size() ); + mask.fill( Qt::color0 ); + + QPainter maskPainter(&mask); + maskPainter.translate( -bound.x(), -bound.y() ); + maskPainter.setPen( Qt::color1 ); + maskPainter.setBrush( Qt::color1 ); + + + QPainter p(&pm); + p.translate( -bound.x(), -bound.y() ); + p.setPen( item->pen() ); + p.setBrush( item->brush() ); + + // Now draw the shape :-) + const bool sel = item->isSelected(); + if (sel) + { + // We block the signals as we end up in an infinite loop with cnitem emitting a selected signal + item->blockSignals(true); + item->setSelected(false); + item->blockSignals(false); + } + item->drawShape(p); + item->drawShape(maskPainter); + if (sel) + { + item->blockSignals(true); + item->setSelected(sel); + item->blockSignals(false); + } + + maskPainter.setPen( Qt::color1 ); + maskPainter.setBrush( Qt::color1 ); + + QWMatrix transMatrix; // Matrix to apply to the image + + CNItem *cnItem = dynamic_cast<CNItem*>(item); + if (cnItem) + { + NodeMap nodes = cnItem->nodeMap(); + const NodeMap::iterator nodesEnd = nodes.end(); + for ( NodeMap::iterator it = nodes.begin(); it != nodesEnd; ++it ) + { + Node *node = it.data().node; + const bool sel = node->isSelected(); + if (sel) + node->setSelected(false); + if ( ECNode *ecnode = dynamic_cast<ECNode*>(node) ) + { + const bool showVB = ecnode->showVoltageBars(); + ecnode->setShowVoltageBars(false); + ecnode->drawShape(p); + ecnode->drawShape(maskPainter); + ecnode->setShowVoltageBars(showVB); + } + else + { + node->drawShape(p); + node->drawShape(maskPainter); + } + if (sel) + node->setSelected(sel); + } + + p.setPen(Qt::black); + TextMap text = cnItem->textMap(); + const TextMap::iterator textEnd = text.end(); + for ( TextMap::iterator it = text.begin(); it != textEnd; ++it ) + { + it.data()->drawShape(p); + it.data()->drawShape(maskPainter); + } + +// maskPainter.setPen( Qt::color1 ); +// maskPainter.setBrush( Qt::color1 ); + cnItem->drawWidgets(p); +// cnItem->drawWidgets(maskPainter); + + transMatrix = Component::transMatrix( component->angleDegrees(), component->flipped(), bound.width()/2, bound.height()/2, true ); + } + + pm.setMask(mask); + + // Now, rotate the image so that it's the right way up, and scale it to size + QImage im = pm.convertToImage(); + im = im.xForm(transMatrix); + im = im.smoothScale( 50, 50, QImage::ScaleMin ); + + if (cache) + m_imageMap[item->type()] = im; + + return im; +} + +QPixmap ItemLibrary::itemIconFull( const QString &id ) +{ + LibraryItemList::iterator end = m_items.end(); + for ( LibraryItemList::iterator it = m_items.begin(); it != end; ++it ) + { + if ( *it && (*it)->allIDs().contains(id) ) + { + return (*it)->iconFull(); + } + } + return QPixmap(); +} |