File indexing completed on 2025-02-16 11:40:51
0001 /*************************************************************************** 0002 * Copyright (C) 2003-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 "microsettingsdlg.h" 0012 #include "inputdialog.h" 0013 #include "microinfo.h" 0014 #include "micropackage.h" 0015 #include "microsettings.h" 0016 #include "pinmapping.h" 0017 #include "ui_microsettingswidget.h" 0018 0019 #include <KComboBox> 0020 #include <KLineEdit> 0021 #include <KLocalizedString> 0022 #include <KMessageBox> 0023 0024 #include <QDialogButtonBox> 0025 #include <QGroupBox> 0026 #include <QLabel> 0027 #include <QPushButton> 0028 #include <QRegExp> 0029 #include <QVBoxLayout> 0030 // #include <q3table.h> 0031 0032 #include <ui_newpinmappingwidget.h> 0033 #include <ktechlab_debug.h> 0034 0035 class MicroSettingsWidget : public QWidget, public Ui::MicroSettingsWidget 0036 { 0037 public: 0038 MicroSettingsWidget(QWidget *parent) 0039 : QWidget(parent) 0040 { 0041 setupUi(this); 0042 } 0043 }; 0044 0045 class NewPinMappingWidget : public QWidget, public Ui::NewPinMappingWidget 0046 { 0047 public: 0048 NewPinMappingWidget(QWidget *parent) 0049 : QWidget(parent) 0050 { 0051 setupUi(this); 0052 } 0053 }; 0054 0055 MicroSettingsDlg::MicroSettingsDlg(MicroSettings *microSettings, QWidget *parent) 0056 : QDialog(parent) 0057 { 0058 setModal(true); 0059 setWindowTitle(i18n("PIC Settings")); 0060 0061 QVBoxLayout *mainLayout = new QVBoxLayout; 0062 setLayout(mainLayout); 0063 0064 m_pMicroSettings = microSettings; 0065 m_pNewPinMappingWidget = nullptr; 0066 m_pNewPinMappingDlg = nullptr; 0067 m_pNewPinMappingOkButton = nullptr; 0068 m_pWidget = new MicroSettingsWidget(this); 0069 0070 setWhatsThis(i18n("This dialog allows editing of the initial properties of the PIC")); 0071 m_pWidget->portsGroupBox->setWhatsThis( 0072 i18n("Edit the initial value of the ports here. For each binary number, the order from right-to-left is pins 0 through 7.<br><br>The \"Type (TRIS)\" edit shows the initial input/output state of the ports; 1 represents an input, " 0073 "and 0 an output.<br><br>The \"State (PORT)\" edit shows the initial high/low state of the ports; 1 represents a high, and 0 a low.")); 0074 m_pWidget->variables->setWhatsThis( 0075 i18n("Edit the initial value of the variables here.<br><br>Note that the value of the variable can only be in the range 0->255. These variables will be initialized before any other code is executed.")); 0076 0077 // BEGIN Initialize initial port settings 0078 m_portNames = microSettings->microInfo()->package()->portNames(); 0079 0080 m_portTypeEdit.resize(m_portNames.size() /*, 0 - 2018.06.02 - initialized below */); 0081 m_portStateEdit.resize(m_portNames.size() /*, 0 - 2018.06.02 - initialized below */); 0082 0083 uint row = 0; 0084 QStringList::iterator end = m_portNames.end(); 0085 for (QStringList::iterator it = m_portNames.begin(); it != end; ++it, ++row) { 0086 // BEGIN Get current Type / State text 0087 QString portType = QString::number(microSettings->portType(*it), 2); 0088 QString portState = QString::number(microSettings->portState(*it), 2); 0089 0090 QString fill; 0091 fill.fill('0', 8 - portType.length()); 0092 portType.prepend(fill); 0093 fill.fill('0', 8 - portState.length()); 0094 portState.prepend(fill); 0095 // END Get current Type / State text 0096 0097 QGroupBox *groupBox = new QGroupBox(*it, m_pWidget->portsGroupBox); 0098 0099 // groupBox->setColumnLayout(0, Qt::Vertical ); // 2018.06.02 - not needed 0100 groupBox->setLayout(new QVBoxLayout); 0101 groupBox->layout()->setSpacing(6); 0102 groupBox->layout()->setMargin(11); 0103 QGridLayout *groupBoxLayout = new QGridLayout(groupBox /*groupBox->layout() */); 0104 groupBoxLayout->setAlignment(Qt::AlignTop); 0105 groupBoxLayout->setSpacing(groupBox->layout()->spacing()); 0106 groupBox->layout()->addItem(groupBoxLayout); 0107 0108 // TODO: replace this with i18n( "the type", "Type (TRIS register):" ); 0109 groupBoxLayout->addWidget(new QLabel(i18n("Type (TRIS register):"), groupBox), 0, 0); 0110 groupBoxLayout->addWidget(new QLabel(i18n("State (PORT register):"), groupBox), 1, 0); 0111 0112 m_portTypeEdit[row] = new KLineEdit(portType, groupBox); 0113 groupBoxLayout->addWidget(m_portTypeEdit[row], 0, 1); 0114 0115 m_portStateEdit[row] = new KLineEdit(portState, groupBox); 0116 groupBoxLayout->addWidget(m_portStateEdit[row], 1, 1); 0117 0118 // (dynamic_cast<QVBoxLayout*>(m_pWidget->portsGroupBox->layout()))->insertWidget( row, groupBox ); 0119 (dynamic_cast<QVBoxLayout *>(m_pWidget->portsGroupBox->layout()))->addWidget(groupBox); 0120 } 0121 // END Initialize initial port settings 0122 0123 // BEGIN Initialize initial variable settings 0124 // Hide row headers 0125 // m_pWidget->variables->setLeftMargin(0); // 2018.06.02 - fixed in UI file 0126 0127 // Make columns as thin as possible 0128 // m_pWidget->variables->setColumnStretchable( 0, true ); // 2018.06.02 - to be fixed 0129 // m_pWidget->variables->setColumnStretchable( 1, true ); // 2018.06.02 - to be fixed 0130 { 0131 QStringList headerLabels; 0132 headerLabels.append(i18n("Variable name")); 0133 headerLabels.append(i18n("Variable value")); 0134 m_pWidget->variables->setHorizontalHeaderLabels(headerLabels); 0135 } 0136 0137 QStringList variableNames = microSettings->variableNames(); 0138 row = 0; 0139 end = variableNames.end(); 0140 for (QStringList::iterator it = variableNames.begin(); it != end; ++it) { 0141 VariableInfo *info = microSettings->variableInfo(*it); 0142 if (info) { 0143 qCDebug(KTL_LOG) << "add var: " << *it << " val: " << info->valueAsString(); 0144 m_pWidget->variables->insertRow(row); 0145 QTableWidgetItem *varNameItem = new QTableWidgetItem(*it); 0146 m_pWidget->variables->setItem(row, 0, varNameItem); 0147 QTableWidgetItem *varValItem = new QTableWidgetItem(info->valueAsString()); 0148 m_pWidget->variables->setItem(row, 1, varValItem); 0149 ++row; 0150 } 0151 } 0152 m_pWidget->variables->insertRow(row); 0153 qCDebug(KTL_LOG) << "row count: " << m_pWidget->variables->rowCount(); 0154 0155 connect(m_pWidget->variables, &QTableWidget::cellChanged, this, &MicroSettingsDlg::checkAddVariableRow); 0156 // END Initialize initial variable settings 0157 0158 // BEGIN Initialize pin maps 0159 connect(m_pWidget->pinMapAdd, &QPushButton::clicked, this, &MicroSettingsDlg::slotCreatePinMap); 0160 connect(m_pWidget->pinMapModify, &QPushButton::clicked, this, &MicroSettingsDlg::slotModifyPinMap); 0161 connect(m_pWidget->pinMapRename, &QPushButton::clicked, this, &MicroSettingsDlg::slotRenamePinMap); 0162 connect(m_pWidget->pinMapRemove, &QPushButton::clicked, this, &MicroSettingsDlg::slotRemovePinMap); 0163 0164 m_pinMappings = microSettings->pinMappings(); 0165 m_pWidget->pinMapCombo->insertItems(m_pWidget->pinMapCombo->count(), m_pinMappings.keys()); 0166 0167 updatePinMapButtons(); 0168 // END Initialize pin maps 0169 0170 mainLayout->addWidget(m_pWidget); 0171 0172 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply); 0173 mainLayout->addWidget(buttonBox); 0174 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0175 okButton->setDefault(true); 0176 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0177 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 0178 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0179 connect(buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &MicroSettingsDlg::slotApplyClicked); 0180 0181 m_pWidget->adjustSize(); 0182 adjustSize(); 0183 } 0184 0185 MicroSettingsDlg::~MicroSettingsDlg() 0186 { 0187 } 0188 0189 void MicroSettingsDlg::accept() 0190 { 0191 slotSaveStuff(); 0192 QDialog::accept(); 0193 deleteLater(); 0194 } 0195 0196 void MicroSettingsDlg::slotApplyClicked() 0197 { 0198 slotSaveStuff(); 0199 emit applyClicked(); 0200 } 0201 0202 void MicroSettingsDlg::slotSaveStuff() 0203 { 0204 for (int i = 0; i < m_portNames.size(); i++) 0205 savePort(i); 0206 0207 m_pMicroSettings->removeAllVariables(); 0208 for (int i = 0; i < m_pWidget->variables->rowCount(); i++) 0209 saveVariable(i); 0210 0211 m_pMicroSettings->setPinMappings(m_pinMappings); 0212 } 0213 0214 void MicroSettingsDlg::reject() 0215 { 0216 QDialog::reject(); 0217 deleteLater(); 0218 } 0219 0220 QValidator::State MicroSettingsDlg::validatePinMapName(QString &name) const 0221 { 0222 name.replace(' ', '_'); 0223 0224 if (name.isEmpty()) 0225 return QValidator::Intermediate; 0226 0227 for (int i = 0; i < name.length(); ++i) { 0228 if (!name[i].isLetterOrNumber() && name[i] != '_') 0229 return QValidator::Invalid; 0230 } 0231 0232 if (name[0].isNumber()) 0233 return QValidator::Intermediate; 0234 0235 if (m_pWidget->pinMapCombo->contains(name)) 0236 return QValidator::Intermediate; 0237 0238 return QValidator::Acceptable; 0239 } 0240 0241 void MicroSettingsDlg::slotCheckNewPinMappingName(const QString &name) 0242 { 0243 // Validate name might change the name so that it is valid 0244 QString newName = name; 0245 0246 if (m_pNewPinMappingOkButton) { 0247 m_pNewPinMappingOkButton->setEnabled(validatePinMapName(newName) == QValidator::Acceptable); 0248 } 0249 0250 if (newName != name) 0251 m_pNewPinMappingWidget->nameEdit->setText(newName); 0252 } 0253 0254 void MicroSettingsDlg::slotCreatePinMap() 0255 { 0256 m_pNewPinMappingDlg = new QDialog(this); 0257 m_pNewPinMappingDlg->setObjectName("New Pin Mapping Dlg"); 0258 m_pNewPinMappingDlg->setModal(true); 0259 m_pNewPinMappingDlg->setWindowTitle(i18n("New Pin Mapping")); 0260 QVBoxLayout *mainLayout = new QVBoxLayout; 0261 m_pNewPinMappingDlg->setLayout(mainLayout); 0262 m_pNewPinMappingWidget = new NewPinMappingWidget(m_pNewPinMappingDlg); 0263 mainLayout->addWidget(m_pNewPinMappingWidget); 0264 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0265 m_pNewPinMappingOkButton = buttonBox->button(QDialogButtonBox::Ok); 0266 m_pNewPinMappingOkButton->setText(i18n("Create")); 0267 m_pNewPinMappingOkButton->setDefault(true); 0268 m_pNewPinMappingOkButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0269 connect(buttonBox, &QDialogButtonBox::accepted, m_pNewPinMappingDlg, &QDialog::accept); 0270 connect(buttonBox, &QDialogButtonBox::rejected, m_pNewPinMappingDlg, &QDialog::reject); 0271 mainLayout->addWidget(buttonBox); 0272 0273 PinMappingNameValidator *validator = new PinMappingNameValidator(this); 0274 m_pNewPinMappingWidget->nameEdit->setValidator(validator); 0275 0276 connect(m_pNewPinMappingWidget->nameEdit, &KLineEdit::textChanged, this, &MicroSettingsDlg::slotCheckNewPinMappingName); 0277 slotCheckNewPinMappingName(nullptr); 0278 0279 int accepted = m_pNewPinMappingDlg->exec(); 0280 unsigned selectedType = m_pNewPinMappingWidget->typeCombo->currentIndex(); 0281 QString name = m_pNewPinMappingWidget->nameEdit->text(); 0282 0283 delete m_pNewPinMappingDlg; 0284 delete validator; 0285 m_pNewPinMappingDlg = nullptr; 0286 m_pNewPinMappingWidget = nullptr; 0287 m_pNewPinMappingOkButton = nullptr; 0288 if (accepted != QDialog::Accepted) 0289 return; 0290 0291 PinMapping::Type type = PinMapping::Invalid; 0292 0293 switch (selectedType) { 0294 case 0: 0295 type = PinMapping::SevenSegment; 0296 break; 0297 0298 case 1: 0299 type = PinMapping::Keypad_4x3; 0300 break; 0301 0302 case 2: 0303 type = PinMapping::Keypad_4x4; 0304 break; 0305 0306 default: 0307 qCCritical(KTL_LOG) << "Unknown selected type " << type; 0308 break; 0309 } 0310 0311 m_pinMappings[name] = PinMapping(type); 0312 m_pWidget->pinMapCombo->insertItem(m_pWidget->pinMapCombo->count(), name); 0313 // m_pWidget->pinMapCombo->setCurrentItem( m_pWidget->pinMapCombo->count() - 1 ); 0314 m_pWidget->pinMapCombo->setCurrentItem(name); 0315 0316 updatePinMapButtons(); 0317 slotModifyPinMap(); 0318 } 0319 0320 void MicroSettingsDlg::slotRenamePinMap() 0321 { 0322 KComboBox *combo = m_pWidget->pinMapCombo; 0323 0324 QString oldName = combo->currentText(); 0325 if (oldName.isEmpty()) 0326 return; 0327 0328 PinMappingNameValidator *validator = new PinMappingNameValidator(this, oldName); 0329 0330 bool ok = false; 0331 QString newName = InputDialog::getText(i18n("New Pin Map Name"), i18n("Name"), oldName, &ok, this, /* 0, */ validator); 0332 0333 delete validator; 0334 0335 if (!ok) 0336 return; 0337 0338 if (newName == oldName) 0339 return; 0340 0341 m_pinMappings[newName] = m_pinMappings[oldName]; 0342 m_pinMappings.remove(oldName); 0343 0344 // combo->setCurrentText( newName ); // 2018.12.02 0345 combo->setItemText(combo->currentIndex(), newName); 0346 } 0347 0348 void MicroSettingsDlg::slotModifyPinMap() 0349 { 0350 QString name = m_pWidget->pinMapCombo->currentText(); 0351 PinMapping pinMapping = m_pinMappings[name]; 0352 0353 PinMapEditor *pinMapEditor = new PinMapEditor(&pinMapping, m_pMicroSettings->microInfo(), this); 0354 pinMapEditor->setObjectName("PinMapEditor"); 0355 int accepted = pinMapEditor->exec(); 0356 0357 delete pinMapEditor; 0358 0359 if (accepted != QDialog::Accepted) 0360 return; 0361 0362 m_pinMappings[name] = pinMapping; 0363 } 0364 0365 void MicroSettingsDlg::slotRemovePinMap() 0366 { 0367 KComboBox *combo = m_pWidget->pinMapCombo; 0368 0369 QString pinMapID = combo->currentText(); 0370 if (pinMapID.isEmpty()) 0371 return; 0372 0373 m_pinMappings.remove(pinMapID); 0374 combo->removeItem(combo->currentIndex()); 0375 0376 updatePinMapButtons(); 0377 } 0378 0379 void MicroSettingsDlg::updatePinMapButtons() 0380 { 0381 bool havePinMaps = (m_pWidget->pinMapCombo->count() != 0); 0382 0383 m_pWidget->pinMapModify->setEnabled(havePinMaps); 0384 m_pWidget->pinMapRename->setEnabled(havePinMaps); 0385 m_pWidget->pinMapRemove->setEnabled(havePinMaps); 0386 } 0387 0388 void MicroSettingsDlg::savePort(int row) 0389 { 0390 QString port = m_portNames[row]; 0391 0392 int type, state; 0393 0394 QString typeText = m_portTypeEdit[row]->text(); 0395 bool typeOk = true; 0396 if (typeText.startsWith("0x", Qt::CaseInsensitive)) 0397 type = typeText.remove(0, 2).toInt(&typeOk, 16); 0398 else if (typeText.contains(QRegExp("[^01]"))) 0399 type = typeText.toInt(&typeOk, 10); 0400 else 0401 type = typeText.toInt(&typeOk, 2); 0402 0403 if (!typeOk) { 0404 // KMessageBox::error( this, i18n("Unregnised Port Type: %1", typeText) ); 0405 return; 0406 } 0407 0408 QString stateText = m_portStateEdit[row]->text(); 0409 bool stateOk = true; 0410 if (stateText.startsWith("0x", Qt::CaseInsensitive)) 0411 state = stateText.remove(0, 2).toInt(&stateOk, 16); 0412 else if (stateText.contains(QRegExp("[^01]"))) 0413 state = stateText.toInt(&stateOk, 10); 0414 else 0415 state = stateText.toInt(&stateOk, 2); 0416 0417 if (!stateOk) { 0418 // KMessageBox::error( this, i18n("Unregnised Port State: %1", stateText) ); 0419 return; 0420 } 0421 0422 m_pMicroSettings->setPortState(port, state); 0423 m_pMicroSettings->setPortType(port, type); 0424 } 0425 0426 void MicroSettingsDlg::saveVariable(int row) 0427 { 0428 QTableWidgetItem *nameItem = m_pWidget->variables->item(row, 0); 0429 if (!nameItem) { 0430 return; 0431 } 0432 QString name = nameItem->text(); 0433 if (name.isEmpty()) 0434 return; 0435 0436 QTableWidgetItem *valueItem = m_pWidget->variables->item(row, 1); 0437 QString valueText; 0438 if (valueItem) { 0439 valueText = valueItem->text(); 0440 } 0441 int value; 0442 bool ok = true; 0443 if (valueText.startsWith("0x", Qt::CaseInsensitive)) 0444 value = valueText.remove(0, 2).toInt(&ok, 16); 0445 else 0446 value = valueText.toInt(&ok, 10); 0447 0448 if (!ok) { 0449 KMessageBox::error(this, i18n("Invalid variable value: %1", valueText)); 0450 return; 0451 } 0452 0453 qCDebug(KTL_LOG) << "save variable: " << name << " val: " << value; 0454 0455 m_pMicroSettings->setVariable(name, value, true); 0456 VariableInfo *info = m_pMicroSettings->variableInfo(name); 0457 if (info && info->valueAsString().toInt() != value) { 0458 // info->setValue(value); 0459 // info->permanent = true; 0460 info->initAtStart = true; 0461 } 0462 } 0463 0464 void MicroSettingsDlg::checkAddVariableRow() 0465 { 0466 int lastRow = m_pWidget->variables->rowCount() - 1; 0467 if (QTableWidgetItem *lastItem = m_pWidget->variables->item(lastRow, 0)) { 0468 if (!lastItem->text().isEmpty()) { 0469 m_pWidget->variables->insertRow(lastRow + 1); 0470 } 0471 } 0472 } 0473 0474 #include "moc_microsettingsdlg.cpp"