File indexing completed on 2024-04-14 05:36:41

0001 /***************************************************************************
0002  *   Copyright (C) 2004-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 "subcircuits.h"
0012 #include "circuitdocument.h"
0013 #include "ecsubcircuit.h"
0014 #include "itemdocumentdata.h"
0015 #include "itemlibrary.h"
0016 #include "itemselector.h"
0017 
0018 #include <KConfigGroup>
0019 #include <KLocalizedString>
0020 #include <KSharedConfig>
0021 
0022 #include <QDir>
0023 #include <QFile>
0024 #include <QStandardPaths>
0025 #include <QTextStream>
0026 
0027 #include <ktechlab_debug.h>
0028 
0029 Subcircuits::Subcircuits()
0030     : QObject()
0031 {
0032     connect(ComponentSelector::self(), &ComponentSelector::itemRemoved, this, &Subcircuits::slotItemRemoved);
0033 }
0034 
0035 Subcircuits::~Subcircuits()
0036 {
0037 }
0038 
0039 static QList<int> asIntList(const QString &string)
0040 {
0041     QList<QByteArray> entries = string.toLatin1().split(',');
0042     QList<int> list;
0043     for (const QByteArray &s : entries)
0044         list << s.toInt();
0045     return list;
0046 }
0047 
0048 void Subcircuits::initECSubcircuit(int subcircuitId, ECSubcircuit *ecSubcircuit)
0049 {
0050     const QString fileName = genFileName(subcircuitId);
0051     if (!QFile::exists(fileName)) {
0052         qCDebug(KTL_LOG) << "Subcircuits::createSubcircuit: Subcircuit \"" << fileName << "\" was not found.";
0053         return;
0054     }
0055 
0056     SubcircuitData subcircuit;
0057     if (!subcircuit.loadData(QUrl::fromLocalFile(genFileName(subcircuitId))))
0058         return;
0059 
0060     subcircuit.initECSubcircuit(ecSubcircuit);
0061 }
0062 
0063 ECSubcircuit *Subcircuits::createSubcircuit(int id, CircuitDocument *circuitDocument, bool newItem, const char *newId)
0064 {
0065     // I pass finishCreation = false here because the subcircuit was getting
0066     // finished twice, causing a segfault in CircuitDocument::assignCircuits()
0067     //--electronerd
0068     ECSubcircuit *ecSubcircuit = static_cast<ECSubcircuit *>(itemLibrary()->createItem("ec/subcircuit", circuitDocument, newItem, newId, false));
0069     ecSubcircuit->property("id")->setValue(id);
0070     return ecSubcircuit;
0071 }
0072 
0073 void Subcircuits::loadSubcircuits()
0074 {
0075     // KConfig *config = kapp->config();
0076     KSharedConfigPtr config = KSharedConfig::openConfig();
0077     // config->setGroup("Subcircuits");
0078     KConfigGroup configGrSubcirc = config->group("Subcircuits");
0079 
0080     QList<int> idList = asIntList(configGrSubcirc.readEntry<QString>(QString("Ids"), QString()));
0081     const QList<int>::iterator idListEnd = idList.end();
0082     for (QList<int>::iterator it = idList.begin(); it != idListEnd; ++it) {
0083         QFile file(genFileName(*it));
0084         if (file.open(QIODevice::ReadOnly) == false) {
0085             // File has mysteriously disappeared....
0086             *it = -1;
0087         } else {
0088             KConfigGroup configGrSubcNr = config->group("Subcircuit_" + QString::number(*it));
0089             updateComponentSelector(*it, configGrSubcNr.readEntry("Name"));
0090         }
0091         file.close();
0092     }
0093     idList.removeAll(-1);
0094 
0095     // Update the config file if any ids have been removed
0096     // config->setGroup("Subcircuits");
0097     configGrSubcirc.writeEntry("Ids", idList);
0098 }
0099 
0100 QString Subcircuits::genFileName(const int nextId)
0101 {
0102     return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/subcircuit_" + QString::number(nextId) + ".circuit";
0103 }
0104 
0105 void Subcircuits::updateComponentSelector(int id, const QString &name)
0106 {
0107     if (name.isEmpty())
0108         return;
0109 
0110     ComponentSelector::self()->addItem(name, "sc/" + QString::number(id), i18n("Subcircuits"), QIcon::fromTheme("application-x-circuit"), true);
0111 }
0112 
0113 void Subcircuits::addSubcircuit(const QString &name, const QString &subcircuitXml)
0114 {
0115     // KConfig *config = kapp->config();
0116     KSharedConfigPtr config = KSharedConfig::openConfig();
0117     KConfigGroup subcircGroup = config->group("Subcircuits");
0118 
0119     int nextId = subcircGroup.readEntry<int>("NextId", 0);
0120 
0121     // ensure dir exists
0122     QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
0123     while (QFile::exists(genFileName(nextId))) {
0124         nextId++;
0125     }
0126 
0127     const int id = nextId;
0128 
0129     const QString fileName = genFileName(id);
0130     QFile file(fileName);
0131 
0132     if (file.open(QIODevice::WriteOnly) == false) {
0133         qCCritical(KTL_LOG) << "Subcircuits::addSubcircuit: couldn't open subcircuit save file: " << fileName;
0134         return;
0135     }
0136 
0137     QTextStream stream(&file);
0138     stream << subcircuitXml;
0139     file.close();
0140 
0141     QList<int> idList = asIntList(subcircGroup.readEntry<QString>(QString("Ids"), QString()));
0142     idList += id;
0143     subcircGroup.writeEntry("Ids", idList);
0144     subcircGroup.writeEntry("NextId", ++nextId);
0145 
0146     KConfigGroup grSubcircNr = config->group("Subcircuit_" + QString::number(id));
0147     grSubcircNr.writeEntry("Name", name);
0148 
0149     // It's important that we write the configuration *now*, lest the subcircuits be lost
0150     grSubcircNr.sync();
0151 
0152     updateComponentSelector(id, name);
0153 }
0154 
0155 void Subcircuits::slotItemRemoved(const QString &id)
0156 {
0157     if (!id.startsWith("sc/")) {
0158         return;
0159     }
0160 
0161     QString temp = id;
0162     temp.remove("sc/");
0163     const int id_num = temp.toInt();
0164     const QString fileName = genFileName(id_num);
0165     QFile file(fileName);
0166     file.remove();
0167 
0168     // KConfig *config = kapp->config();
0169     KSharedConfigPtr config = KSharedConfig::openConfig();
0170     KConfigGroup grSc = config->group("Subcircuits");
0171     QList<int> idList = asIntList(grSc.readEntry<QString>(QString("Ids"), QString()));
0172     idList.removeAll(id_num);
0173     grSc.writeEntry("Ids", idList);
0174 }
0175 
0176 #include "moc_subcircuits.cpp"