File indexing completed on 2024-12-08 11:06:54
0001 /*************************************************************************** 0002 * Copyright (C) 2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "pinmapping.h" 0012 #include "canvasmanipulator.h" 0013 #include "cnitemgroup.h" 0014 #include "eckeypad.h" 0015 #include "ecsevensegment.h" 0016 #include "libraryitem.h" 0017 #include "microinfo.h" 0018 #include "micropackage.h" 0019 #include "node.h" 0020 #include "viewcontainer.h" 0021 0022 #include <KLocalizedString> 0023 #include <KStandardShortcut> 0024 0025 #include <QAction> 0026 #include <QApplication> 0027 #include <QDialogButtonBox> 0028 #include <QFrame> 0029 #include <QPushButton> 0030 #include <QVBoxLayout> 0031 0032 #include <ktechlab_debug.h> 0033 0034 // BEGIN class PinMapping 0035 PinMapping::PinMapping(Type type) 0036 { 0037 m_type = type; 0038 } 0039 0040 PinMapping::PinMapping() 0041 { 0042 m_type = Invalid; 0043 } 0044 0045 PinMapping::~PinMapping() 0046 { 0047 } 0048 // END class PinMapping 0049 0050 // BEGIN class PinMapEditor 0051 PinMapEditor::PinMapEditor(PinMapping *pinMapping, MicroInfo *picInfo, QWidget *parent) 0052 : QDialog(parent) 0053 { 0054 setModal(true); 0055 setWindowTitle(i18n("Pin Map Editor")); 0056 0057 QVBoxLayout *mainLayout = new QVBoxLayout; 0058 setLayout(mainLayout); 0059 0060 m_pPinMapping = pinMapping; 0061 0062 m_pPinMapDocument = new PinMapDocument(); 0063 0064 { 0065 QAction *actionDelSel = new QAction(this); 0066 actionDelSel->setShortcut(Qt::Key_Delete); 0067 connect(actionDelSel, &QAction::triggered, m_pPinMapDocument, &PinMapDocument::deleteSelection); 0068 addAction(actionDelSel); 0069 } 0070 { 0071 QAction *actionSelAll = new QAction(this); 0072 actionSelAll->setShortcut(KStandardShortcut::selectAll().first()); 0073 connect(actionSelAll, &QAction::triggered, m_pPinMapDocument, &PinMapDocument::selectAll); 0074 addAction(actionSelAll); 0075 } 0076 { 0077 QAction *actionUndo = new QAction(this); 0078 actionUndo->setShortcut(KStandardShortcut::undo().first()); 0079 connect(actionUndo, &QAction::triggered, m_pPinMapDocument, &PinMapDocument::undo); 0080 addAction(actionUndo); 0081 } 0082 { 0083 QAction *actionRedo = new QAction(this); 0084 actionRedo->setShortcut(KStandardShortcut::redo().first()); 0085 connect(actionRedo, &QAction::triggered, m_pPinMapDocument, &PinMapDocument::redo); 0086 addAction(actionRedo); 0087 } 0088 0089 QFrame *f = new QFrame(this); 0090 f->setMinimumWidth(480); 0091 f->setMinimumHeight(480); 0092 0093 f->setFrameShape(QFrame::Box); 0094 f->setFrameShadow(QFrame::Plain); 0095 QVBoxLayout *fLayout = new QVBoxLayout; // ( f, 1, 0, "fLayout" ); // 2018.08.18 - use non-deprected constructor 0096 fLayout->setContentsMargins(1, 1, 1, 1); 0097 fLayout->setSpacing(0); 0098 fLayout->setObjectName("fLayout"); 0099 0100 ViewContainer *vc = new ViewContainer(nullptr, f); 0101 fLayout->addWidget(vc); 0102 0103 m_pPinMapView = static_cast<PinMapView *>(m_pPinMapDocument->createView(vc, 0)); 0104 0105 // qApp->processEvents(); // 2015.07.07 - do not process events, if it is not urgently needed; might generate crashes? 0106 0107 m_pPinMapDocument->init(*m_pPinMapping, picInfo); 0108 0109 mainLayout->addWidget(f); 0110 0111 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply); 0112 mainLayout->addWidget(buttonBox); 0113 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0114 okButton->setDefault(true); 0115 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0116 connect(buttonBox, &QDialogButtonBox::accepted, this, &PinMapEditor::slotOk); 0117 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0118 connect(buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &PinMapEditor::slotApply); 0119 } 0120 0121 void PinMapEditor::slotApply() 0122 { 0123 savePinMapping(); 0124 } 0125 0126 void PinMapEditor::slotOk() 0127 { 0128 savePinMapping(); 0129 accept(); 0130 } 0131 0132 void PinMapEditor::savePinMapping() 0133 { 0134 *m_pPinMapping = m_pPinMapDocument->pinMapping(); 0135 } 0136 // END class PinMapEditor 0137 0138 // BEGIN class PinMapDocument 0139 PinMapDocument::PinMapDocument() 0140 : CircuitICNDocument(nullptr) 0141 { 0142 m_pPicComponent = nullptr; 0143 m_pKeypad = nullptr; 0144 m_pSevenSegment = nullptr; 0145 m_type = dt_pinMapEditor; 0146 0147 m_cmManager->addManipulatorInfo(CMSelect::manipulatorInfo()); 0148 } 0149 0150 PinMapDocument::~PinMapDocument() 0151 { 0152 } 0153 0154 void PinMapDocument::init(const PinMapping &pinMapping, MicroInfo *microInfo) 0155 { 0156 m_pinMappingType = pinMapping.type(); 0157 0158 m_pPicComponent = static_cast<PIC_IC *>(addItem("PIC_IC", QPoint(336, 224), true)); 0159 m_pPicComponent->initPackage(microInfo); 0160 0161 const QStringList pins = pinMapping.pins(); 0162 const QStringList::const_iterator end = pins.end(); 0163 0164 int keypadCols = -1; // -1 means no keypad 0165 0166 switch (m_pinMappingType) { 0167 case PinMapping::SevenSegment: { 0168 m_pSevenSegment = static_cast<ECSevenSegment *>(addItem("ec/seven_segment", QPoint(144, 232), true)); 0169 0170 char ssPin = 'a'; 0171 for (QStringList::const_iterator it = pins.begin(); it != end; ++it) { 0172 ICNDocument::createConnector(m_pSevenSegment->childNode(QChar(ssPin)), m_pPicComponent->childNode(*it)); 0173 ssPin++; 0174 } 0175 0176 break; 0177 } 0178 0179 case PinMapping::Keypad_4x3: 0180 m_pKeypad = static_cast<ECKeyPad *>(addItem("ec/keypad", QPoint(144, 232), true)); 0181 m_pKeypad->property("numCols")->setValue(3); 0182 keypadCols = 3; 0183 break; 0184 0185 case PinMapping::Keypad_4x4: 0186 m_pKeypad = static_cast<ECKeyPad *>(addItem("ec/keypad", QPoint(144, 232), true)); 0187 m_pKeypad->property("numCols")->setValue(4); 0188 keypadCols = 4; 0189 break; 0190 0191 case PinMapping::Invalid: 0192 qCDebug(KTL_LOG) << "m_pinMappingType == Invalid"; 0193 break; 0194 } 0195 0196 if (keypadCols != -1) { 0197 QStringList::const_iterator it = pins.begin(); 0198 for (unsigned row = 0; (row < 4) && (it != end); ++row, ++it) 0199 ICNDocument::createConnector(m_pKeypad->childNode(QString("row_%1").arg(row)), m_pPicComponent->childNode(*it)); 0200 0201 for (int col = 0; (col < keypadCols) && (it != end); ++col, ++it) 0202 ICNDocument::createConnector(m_pKeypad->childNode(QString("col_%1").arg(col)), m_pPicComponent->childNode(*it)); 0203 } 0204 0205 clearHistory(); // Don't allow undoing of initial creation of stuff 0206 } 0207 0208 bool PinMapDocument::isValidItem(Item *item) 0209 { 0210 return isValidItem(item->type()); 0211 } 0212 0213 bool PinMapDocument::isValidItem(const QString &id) 0214 { 0215 if (!m_pPicComponent && id == "PIC_IC") 0216 return true; 0217 0218 switch (m_pinMappingType) { 0219 case PinMapping::SevenSegment: 0220 return (!m_pSevenSegment && id == "ec/seven_segment"); 0221 0222 case PinMapping::Keypad_4x3: 0223 return (!m_pKeypad && id == "ec/keypad"); 0224 0225 case PinMapping::Keypad_4x4: 0226 return (!m_pKeypad && id == "ec/keypad"); 0227 0228 case PinMapping::Invalid: 0229 return false; 0230 } 0231 0232 return false; 0233 } 0234 0235 void PinMapDocument::deleteSelection() 0236 { 0237 m_selectList->removeQCanvasItem(m_pPicComponent); 0238 m_selectList->removeQCanvasItem(m_pSevenSegment); 0239 m_selectList->removeQCanvasItem(m_pKeypad); 0240 0241 ICNDocument::deleteSelection(); 0242 } 0243 0244 PinMapping PinMapDocument::pinMapping() const 0245 { 0246 const NodeInfoMap picNodeInfoMap = m_pPicComponent->nodeMap(); 0247 const NodeInfoMap::const_iterator picNodeInfoMapEnd = picNodeInfoMap.end(); 0248 0249 QStringList picPinIDs; 0250 QStringList attachedIDs; 0251 Component *attached = nullptr; 0252 0253 switch (m_pinMappingType) { 0254 case PinMapping::SevenSegment: 0255 for (unsigned i = 0; i < 7; ++i) 0256 attachedIDs << QChar('a' + i); 0257 attached = m_pSevenSegment; 0258 break; 0259 0260 case PinMapping::Keypad_4x3: 0261 for (unsigned i = 0; i < 4; ++i) 0262 attachedIDs << QString::fromLatin1("row_%1").arg(i); 0263 for (unsigned i = 0; i < 3; ++i) 0264 attachedIDs << QString::fromLatin1("col_%1").arg(i); 0265 attached = m_pKeypad; 0266 break; 0267 0268 case PinMapping::Keypad_4x4: 0269 for (unsigned i = 0; i < 4; ++i) 0270 attachedIDs << QString::fromLatin1("row_%1").arg(i); 0271 for (unsigned i = 0; i < 4; ++i) 0272 attachedIDs << QString::fromLatin1("col_%1").arg(i); 0273 attached = m_pKeypad; 0274 break; 0275 0276 case PinMapping::Invalid: 0277 break; 0278 } 0279 0280 if (!attached) 0281 return PinMapping(); 0282 0283 QStringList::iterator end = attachedIDs.end(); 0284 for (QStringList::iterator attachedIt = attachedIDs.begin(); attachedIt != end; ++attachedIt) { 0285 Node *node = attached->childNode(*attachedIt); 0286 QString pinID; 0287 0288 for (NodeInfoMap::const_iterator it = picNodeInfoMap.begin(); it != picNodeInfoMapEnd; ++it) { 0289 if (it.value().node->isConnected(node)) { 0290 pinID = it.key(); 0291 break; 0292 } 0293 } 0294 0295 picPinIDs << pinID; 0296 } 0297 0298 PinMapping pinMapping(m_pinMappingType); 0299 pinMapping.setPins(picPinIDs); 0300 0301 return pinMapping; 0302 } 0303 // END class PinMapDocument 0304 0305 // BEGIN class PinMapView 0306 PinMapView::PinMapView(PinMapDocument *pinMapDocument, ViewContainer *viewContainer, uint viewAreaId) 0307 : ICNView(pinMapDocument, viewContainer, viewAreaId) 0308 { 0309 } 0310 0311 PinMapView::~PinMapView() 0312 { 0313 } 0314 // END class PinMapView 0315 0316 // BEGIN class PIC_IC 0317 Item *PIC_IC::construct(ItemDocument *itemDocument, bool newItem, const char *id) 0318 { 0319 return new PIC_IC(static_cast<ICNDocument *>(itemDocument), newItem, id); 0320 } 0321 0322 LibraryItem *PIC_IC::libraryItem() 0323 { 0324 return new LibraryItem(QStringList(QString::fromLatin1("PIC_IC")), nullptr, nullptr, LibraryItem::lit_other, PIC_IC::construct); 0325 } 0326 0327 PIC_IC::PIC_IC(ICNDocument *icnDocument, bool newItem, const char *id) 0328 : Component(icnDocument, newItem, id ? id : "PIC_IC") 0329 { 0330 } 0331 0332 PIC_IC::~PIC_IC() 0333 { 0334 } 0335 0336 void PIC_IC::initPackage(MicroInfo *microInfo) 0337 { 0338 // The code in this function is a stripped down version of that in PICComponent::initPackage 0339 0340 if (!microInfo) 0341 return; 0342 0343 MicroPackage *microPackage = microInfo->package(); 0344 if (!microPackage) 0345 return; 0346 0347 // BEGIN Get pin IDs 0348 QStringList allPinIDs = microPackage->pinIDs(); 0349 QStringList ioPinIDs = microPackage->pinIDs(PicPin::type_bidir | PicPin::type_input | PicPin::type_open); 0350 0351 // Now, we make the unwanted pin ids blank, so a pin is not created for them 0352 const QStringList::iterator allPinIDsEnd = allPinIDs.end(); 0353 for (QStringList::iterator it = allPinIDs.begin(); it != allPinIDsEnd; ++it) { 0354 if (!ioPinIDs.contains(*it)) 0355 *it = ""; 0356 } 0357 // END Get pin IDs 0358 0359 // BEGIN Remove old stuff 0360 // Remove old text 0361 TextMap textMapCopy = m_textMap; 0362 const TextMap::iterator textMapEnd = textMapCopy.end(); 0363 for (TextMap::iterator it = textMapCopy.begin(); it != textMapEnd; ++it) 0364 removeDisplayText(it.key()); 0365 0366 // Remove old nodes 0367 NodeInfoMap nodeMapCopy = m_nodeMap; 0368 const NodeInfoMap::iterator nodeMapEnd = nodeMapCopy.end(); 0369 for (NodeInfoMap::iterator it = nodeMapCopy.begin(); it != nodeMapEnd; ++it) { 0370 if (!ioPinIDs.contains(it.key())) 0371 removeNode(it.key()); 0372 } 0373 // END Remove old stuff 0374 0375 // BEGIN Create new stuff 0376 initDIPSymbol(allPinIDs, 80); 0377 initDIP(allPinIDs); 0378 // END Create new stuff 0379 0380 addDisplayText("picid", QRect(offsetX(), offsetY() - 16, width(), 16), microInfo->id()); 0381 } 0382 // END class PIC_IC 0383 0384 #include "moc_pinmapping.cpp"