File indexing completed on 2024-05-19 09:39:39

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 "flowcodedocument.h"
0012 #include "canvasmanipulator.h"
0013 #include "documentiface.h"
0014 #include "drawpart.h"
0015 #include "flowcode.h"
0016 #include "flowcodeview.h"
0017 #include "flowpart.h"
0018 #include "itemdocumentdata.h"
0019 #include "ktechlab.h"
0020 #include "languagemanager.h"
0021 #include "microinfo.h"
0022 #include "microlibrary.h"
0023 #include "outputmethoddlg.h"
0024 #include "picitem.h"
0025 #include "programmerdlg.h"
0026 #include "textdocument.h"
0027 #include "filefilters.h"
0028 
0029 #include <KLocalizedString>
0030 
0031 #include <ktechlab_debug.h>
0032 
0033 FlowCodeDocument::FlowCodeDocument(const QString &caption)
0034     : FlowICNDocument(caption)
0035 {
0036     m_pDocumentIface = new FlowCodeDocumentIface(this);
0037     m_type = Document::dt_flowcode;
0038     m_microInfo = nullptr;
0039     m_microSettings = nullptr;
0040     m_picItem = nullptr;
0041     m_pLastTextOutputTarget = nullptr;
0042 
0043     m_cmManager->addManipulatorInfo(CMSelect::manipulatorInfo());
0044     m_cmManager->addManipulatorInfo(CMDraw::manipulatorInfo());
0045     m_cmManager->addManipulatorInfo(CMRightClick::manipulatorInfo());
0046     m_cmManager->addManipulatorInfo(CMRepeatedItemAdd::manipulatorInfo());
0047     m_cmManager->addManipulatorInfo(CMItemResize::manipulatorInfo());
0048     m_cmManager->addManipulatorInfo(CMItemDrag::manipulatorInfo());
0049 
0050     m_fileExtensionInfo = QString("*.flowcode|FlowCode (*.flowcode)\n*|%1").arg(i18n("All Files"));
0051     m_fileExtensionValue = QString(".flowcode");
0052     requestStateSave();
0053 }
0054 
0055 FlowCodeDocument::~FlowCodeDocument()
0056 {
0057     m_bDeleted = true;
0058     if (m_picItem)
0059         m_picItem->removeItem();
0060 
0061     delete m_microSettings;
0062     delete m_pDocumentIface;
0063 }
0064 
0065 View *FlowCodeDocument::createView(ViewContainer *viewContainer, uint viewAreaId)
0066 {
0067     View *view = new FlowCodeView(this, viewContainer, viewAreaId);
0068     handleNewView(view);
0069     return view;
0070 }
0071 
0072 void FlowCodeDocument::setPicType(const QString &id)
0073 {
0074     if (m_microSettings && m_microSettings->microInfo() && m_microSettings->microInfo()->id() == id)
0075         return;
0076 
0077     MicroInfo *microInfo = MicroLibrary::self()->microInfoWithID(id);
0078 
0079     if (!microInfo) {
0080         qCWarning(KTL_LOG) << "FlowCodeDocument::setPicType: Could not set the pic type to PIC \"" << id << "\"";
0081         return;
0082     }
0083 
0084     m_microInfo = microInfo;
0085 
0086     if (m_microSettings) {
0087         // TODO write the pic settings to somewhere temporary and then restore them
0088         delete m_microSettings;
0089     }
0090 
0091     m_microSettings = new MicroSettings(m_microInfo);
0092     connect(m_microSettings, &MicroSettings::pinMappingsChanged, this, &FlowCodeDocument::pinMappingsChangedFlowCode);
0093     // TODO restore pic settings from temporary location if appropriate
0094 
0095     delete m_picItem;
0096     m_picItem = new PicItem(this, true, "picItem", m_microSettings);
0097     m_picItem->show();
0098 
0099     emit picTypeChanged();
0100 }
0101 
0102 bool FlowCodeDocument::isValidItem(const QString &itemId)
0103 {
0104     return itemId.startsWith("flow/") || itemId.startsWith("dp/");
0105 }
0106 
0107 bool FlowCodeDocument::isValidItem(Item *item)
0108 {
0109     if (!dynamic_cast<FlowPart *>(item) && !dynamic_cast<DrawPart *>(item))
0110         return false;
0111 
0112     if (!item->id().startsWith("START") && !item->id().startsWith("PPEND"))
0113         return true;
0114 
0115     const ItemMap::iterator ciEnd = m_itemList.end();
0116 
0117     if (item->id().startsWith("START")) {
0118         int count = 0;
0119 
0120         for (ItemMap::iterator it = m_itemList.begin(); it != ciEnd; ++it) {
0121             if ((*it)->id().startsWith("START"))
0122                 count++;
0123         }
0124         if (count > 1)
0125             return false;
0126     } else if (item->id().startsWith("PPEND")) {
0127         int count = 0;
0128         for (ItemMap::iterator it = m_itemList.begin(); it != ciEnd; ++it) {
0129             if ((*it)->id().startsWith("PPEND"))
0130                 count++;
0131         }
0132 
0133         if (count > 1)
0134             return false;
0135     }
0136 
0137     return true;
0138 }
0139 
0140 void FlowCodeDocument::setLastTextOutputTarget(TextDocument *target)
0141 {
0142     m_pLastTextOutputTarget = target;
0143 }
0144 
0145 void FlowCodeDocument::slotConvertTo(QAction *action)
0146 {
0147     int target = action->data().toInt();
0148     switch (ConvertToTarget(target)) {
0149     case FlowCodeDocument::MicrobeOutput:
0150         convertToMicrobe();
0151         break;
0152 
0153     case FlowCodeDocument::AssemblyOutput:
0154         convertToAssembly();
0155         break;
0156 
0157     case FlowCodeDocument::HexOutput:
0158         convertToHex();
0159         break;
0160 
0161     case FlowCodeDocument::PICOutput:
0162         convertToPIC();
0163         break;
0164     }
0165 }
0166 
0167 void FlowCodeDocument::convertToMicrobe()
0168 {
0169     OutputMethodDlg *dlg = new OutputMethodDlg(i18n("Microbe Code Output"), url(), false, activeView());
0170     dlg->setOutputExtension(".microbe");
0171     dlg->setFileFilters({
0172         {i18n("Microbe") + QLatin1String(" (*.microbe)"), QStringLiteral("*.microbe")},
0173         {i18n("All Files"), QStringLiteral("*")},
0174     });
0175 
0176     const int accepted = dlg->exec();
0177     if (accepted != QDialog::Accepted) {
0178         delete dlg;
0179         return;
0180     }
0181 
0182     ProcessOptions o(dlg->info());
0183     o.setTextOutputTarget(m_pLastTextOutputTarget, this, SLOT(setLastTextOutputTarget(TextDocument *)));
0184     o.p_flowCodeDocument = this;
0185     o.setProcessPath(ProcessOptions::ProcessPath::FlowCode_Microbe);
0186     LanguageManager::self()->compile(o);
0187 
0188     delete dlg;
0189 }
0190 
0191 void FlowCodeDocument::convertToAssembly()
0192 {
0193     OutputMethodDlg *dlg = new OutputMethodDlg(i18n("Assembly Code Output"), url(), false, activeView());
0194     dlg->setOutputExtension(".asm");
0195     dlg->setFileFilters({
0196         {i18n("Assembly Code") + QLatin1String(" (*.asm, *.src, *.inc)"), QStringLiteral("*.asm *.src *.inc")},
0197         {i18n("All Files"), QStringLiteral("*")},
0198     });
0199 
0200     const int accepted = dlg->exec();
0201     if (accepted != QDialog::Accepted) {
0202         delete dlg;
0203         return;
0204     }
0205 
0206     ProcessOptions o(dlg->info());
0207     o.setTextOutputTarget(m_pLastTextOutputTarget, this, SLOT(setLastTextOutputTarget(TextDocument *)));
0208     o.p_flowCodeDocument = this;
0209     o.setProcessPath(ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute);
0210     LanguageManager::self()->compile(o);
0211 
0212     delete dlg;
0213 }
0214 
0215 void FlowCodeDocument::convertToHex()
0216 {
0217     OutputMethodDlg *dlg = new OutputMethodDlg(i18n("Hex Code Output"), url(), false, KTechlab::self());
0218     dlg->setOutputExtension(".hex");
0219     dlg->setFileFilters({
0220         {i18n("Hex Code") + QLatin1String(" (*.hex)"), QStringLiteral("*.hex")},
0221         {i18n("All Files"), QStringLiteral("*")},
0222     });
0223 
0224     const int accepted = dlg->exec();
0225     if (accepted != QDialog::Accepted) {
0226         delete dlg;
0227         return;
0228     }
0229 
0230     ProcessOptions o(dlg->info());
0231     o.setTextOutputTarget(m_pLastTextOutputTarget, this, SLOT(setLastTextOutputTarget(TextDocument *)));
0232     o.p_flowCodeDocument = this;
0233     o.setProcessPath(ProcessOptions::ProcessPath::FlowCode_Program);
0234     LanguageManager::self()->compile(o);
0235 
0236     delete dlg;
0237 }
0238 
0239 void FlowCodeDocument::convertToPIC()
0240 {
0241     ProgrammerDlg *dlg = new ProgrammerDlg(microSettings()->microInfo()->id(), static_cast<QWidget *>(KTechlab::self()));
0242     dlg->setObjectName("Programmer Dlg");
0243 
0244     const int accepted = dlg->exec();
0245     if (accepted != QDialog::Accepted) {
0246         dlg->deleteLater();
0247         return;
0248     }
0249 
0250     ProcessOptions o;
0251     dlg->initOptions(&o);
0252     o.p_flowCodeDocument = this;
0253     o.setProcessPath(ProcessOptions::ProcessPath::FlowCode_PIC);
0254     LanguageManager::self()->compile(o);
0255 
0256     dlg->deleteLater();
0257 }
0258 
0259 void FlowCodeDocument::varNameChanged(const QString &newValue, const QString &oldValue)
0260 {
0261     if (m_bDeleted)
0262         return;
0263 
0264     // Decrease the old variable count
0265     // If none are left after, remove it from microsettings
0266     StringIntMap::iterator it = m_varNames.find(oldValue);
0267     if (it != m_varNames.end()) {
0268         --(it.value());
0269         if (it.value() <= 0) {
0270             VariableInfo *info = microSettings()->variableInfo(it.key());
0271             if (info && !info->permanent)
0272                 microSettings()->deleteVariable(oldValue);
0273             m_varNames.erase(it);
0274         }
0275     }
0276 
0277     // Add the new variable to a count, tell microsettings about it if it is new
0278     if (!newValue.isEmpty()) {
0279         it = m_varNames.find(newValue);
0280         if (it != m_varNames.end()) {
0281             ++it.value();
0282         } else {
0283             m_varNames[newValue] = 1;
0284             microSettings()->setVariable(newValue, QVariant(), false);
0285         }
0286     }
0287 
0288     // Tell all FlowParts to update their variable lists
0289     const ItemMap::iterator end = m_itemList.end();
0290     for (ItemMap::iterator it = m_itemList.begin(); it != end; ++it) {
0291         if (FlowPart *flowPart = dynamic_cast<FlowPart *>(*it))
0292             flowPart->updateVarNames();
0293     }
0294 }
0295 
0296 #include "moc_flowcodedocument.cpp"