File indexing completed on 2024-04-14 04:29:46
0001 /* 0002 * This file is part of KDevelop project 0003 * Copyright 2016 Patrick José Pereira <patrickelectric@gmail.com> 0004 * Copyright 2009 Andreas Pakulat <apaku@gmx.de> 0005 * Copyright 2010 Aleix Pol Gonzalez <aleixpol@kde.org> 0006 * 0007 * This program is free software; you can redistribute it and/or modify 0008 * it under the terms of the GNU Library General Public License as 0009 * published by the Free Software Foundation; either version 2 of the 0010 * License, or (at your option) any later version. 0011 * 0012 * This program is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public 0018 * License along with this program; if not, write to the 0019 * Free Software Foundation, Inc., 0020 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #include "embeddedlauncher.h" 0024 0025 #include <interfaces/icore.h> 0026 #include <interfaces/isession.h> 0027 #include <interfaces/iprojectcontroller.h> 0028 #include <interfaces/ilaunchconfiguration.h> 0029 0030 #include <project/projectmodel.h> 0031 0032 #include "launcherjob.h" 0033 #include <interfaces/iproject.h> 0034 #include <project/interfaces/iprojectfilemanager.h> 0035 #include <project/interfaces/ibuildsystemmanager.h> 0036 #include <project/interfaces/iprojectbuilder.h> 0037 #include <project/builderjob.h> 0038 #include <interfaces/iruncontroller.h> 0039 #include <interfaces/iuicontroller.h> 0040 #include <util/executecompositejob.h> 0041 0042 #include <interfaces/iplugincontroller.h> 0043 0044 #include "executeplugin.h" 0045 #include "toolkit.h" 0046 #include "debug.h" 0047 #include "board.h" 0048 0049 #include <util/kdevstringhandler.h> 0050 #include <project/projectitemlineedit.h> 0051 #include "projecttargetscombobox.h" 0052 0053 #include <QDebug> 0054 #include <QIcon> 0055 #include <QMenu> 0056 #include <QPixmap> 0057 #include <QPainter> 0058 #include <QMessageBox> 0059 #include <QItemSelection> 0060 0061 #include <QStandardPaths> 0062 0063 #include <KConfigGroup> 0064 #include <KLineEdit> 0065 #include <KLocalizedString> 0066 #include <KShell> 0067 0068 #include <solid/device.h> 0069 #include <solid/devicenotifier.h> 0070 0071 #include "firsttimewizard.h" 0072 0073 using namespace KDevelop; 0074 using namespace Solid; 0075 0076 Q_LOGGING_CATEGORY(ElMsg, "Kdev.embedded.el.msg") 0077 0078 QIcon EmbeddedLauncherConfigPage::icon() const 0079 { 0080 return QIcon::fromTheme(QStringLiteral("system-run")); 0081 } 0082 0083 static KDevelop::ProjectBaseItem* itemForPath(const QStringList& path, KDevelop::ProjectModel* model) 0084 { 0085 return model->itemFromIndex(model->pathToIndex(path)); 0086 } 0087 0088 void EmbeddedLauncherConfigPage::loadFromConfiguration(const KConfigGroup& cfg, KDevelop::IProject* project) 0089 { 0090 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::loadFromConfiguration" << cfg.groupList() << cfg.keyList() << cfg.entryMap(); 0091 0092 bool b = blockSignals(true); 0093 projectTarget->setBaseItem(project ? project->projectItem() : nullptr, true); 0094 projectTarget->setCurrentItemPath(cfg.readEntry(ExecutePlugin::projectTargetEntry, QStringList())); 0095 0096 QUrl exe = cfg.readEntry(ExecutePlugin::executableEntry, QUrl()); 0097 if (!exe.isEmpty() || project) 0098 { 0099 executablePath->setUrl(!exe.isEmpty() ? exe : project->path().toUrl()); 0100 } 0101 else 0102 { 0103 KDevelop::IProjectController* pc = KDevelop::ICore::self()->projectController(); 0104 if (pc) 0105 { 0106 executablePath->setUrl(pc->projects().isEmpty() ? QUrl() : pc->projects().at(0)->path().toUrl()); 0107 } 0108 } 0109 0110 executableRadio->setChecked(true); 0111 if (!cfg.readEntry(ExecutePlugin::isExecutableEntry, false) && projectTarget->count()) 0112 { 0113 projectTargetRadio->setChecked(true); 0114 } 0115 0116 const QString arg = cfg.readEntry(ExecutePlugin::argumentsEntry, QString()); 0117 if (argumentsCombo->findText(arg) == -1 && !arg.isEmpty()) 0118 { 0119 argumentsCombo->addItem(arg); 0120 } 0121 0122 workingDirectory->setUrl(cfg.readEntry(ExecutePlugin::workingDirEntry, QUrl())); 0123 commandCombo->setEditText(cfg.readEntry(ExecutePlugin::commandEntry, commandCombo->itemText(0))); 0124 0125 const int boardIndex = cfg.readEntry(ExecutePlugin::boardEntry, 0); 0126 const int mcuIndex = cfg.readEntry(ExecutePlugin::mcuEntry, 0); 0127 0128 qCDebug(ElMsg) << "Board index from cfg" << QString(cfg.readEntry(ExecutePlugin::boardEntry, 0)).toInt() << cfg.readEntry(ExecutePlugin::boardEntry, 0); 0129 qCDebug(ElMsg) << "BoardCombo size" << boardCombo->count(); 0130 0131 const int launcherIndex = cfg.readEntry(ExecutePlugin::launcherIndexEntry, 0); 0132 stackedWidget->setCurrentIndex(launcherIndex); 0133 presetsComboPage1->setCurrentIndex(launcherIndex); 0134 presetsComboPage2->setCurrentIndex(launcherIndex); 0135 0136 const QString openocdArg = cfg.readEntry(ExecutePlugin::openocdArgEntry, QString()); 0137 const QUrl openocdWork = cfg.readEntry(ExecutePlugin::openocdWorkEntry, QUrl()); 0138 const QString openocdComm = cfg.readEntry(ExecutePlugin::openocdCommEntry, QString()); 0139 0140 if (!openocdArg.isEmpty()) 0141 { 0142 openocdArgumentsCombo->setCurrentText(openocdArg); 0143 } 0144 if (!openocdWork.isEmpty()) 0145 { 0146 openocdWorkingDirectory->setUrl(openocdWork); 0147 } 0148 if (!openocdComm.isEmpty()) 0149 { 0150 openocdCommand->setCurrentText(openocdComm); 0151 } 0152 0153 if (boardIndex < boardCombo->count()) 0154 { 0155 boardCombo->setCurrentIndex(boardIndex); 0156 } 0157 if (mcuIndex < mcuCombo->count()) 0158 { 0159 mcuCombo->setCurrentIndex(mcuIndex); 0160 } 0161 0162 blockSignals(b); 0163 } 0164 0165 EmbeddedLauncherConfigPage::EmbeddedLauncherConfigPage(QWidget* parent) 0166 : LaunchConfigurationPage(parent), 0167 m_model(new ArduinoWindowModel(parent)) 0168 { 0169 setupUi(this); 0170 0171 m_boardImgsDir = QDir(QStandardPaths::locate( 0172 QStandardPaths::GenericDataLocation, 0173 QLatin1String("kdevembedded/boardsimg"), 0174 QStandardPaths::LocateDirectory 0175 ) + QChar::fromLatin1('/')); 0176 0177 //Set workingdirectory widget to ask for directories rather than files 0178 workingDirectory->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly); 0179 0180 Solid::DeviceNotifier *devices = Solid::DeviceNotifier::instance(); 0181 0182 Board::instance().update(); 0183 0184 // Populate model 0185 QVector<ArduinoWindowModelStruct> data; 0186 Q_ASSERT(Board::instance().m_boardList.size() == Board::instance().m_boardNameList.size()); 0187 for (int i = 0; i < Board::instance().m_boardNameList.size(); i++) 0188 data.push_back(ArduinoWindowModelStruct{Board::instance().m_boardList[i], Board::instance().m_boardNameList[i]}); 0189 m_model->populate(data); 0190 0191 // Start ComboBoxes 0192 boardCombo->clear(); 0193 boardCombo->setModel(m_model); 0194 boardComboChanged(boardCombo->currentText()); 0195 devicesChanged(QString()); 0196 0197 mcuCombo->setToolTip(mcuTooltip()); 0198 interfaceCombo->setToolTip(interfaceTooltip()); 0199 baudCombo->setToolTip(baudTooltip()); 0200 argumentsCombo->setToolTip(argumentsTooltip()); 0201 commandCombo->setToolTip(commandTooltip()); 0202 0203 // Start in the first widget and in the first preset 0204 stackedWidget->setCurrentIndex(0); 0205 presetsComboPage1->setCurrentIndex(0); 0206 presetsComboPage2->setCurrentIndex(0); 0207 0208 0209 //connect signals to changed signal 0210 connect(projectTarget, static_cast<void(ProjectTargetsComboBox::*)(const QString&)>(&ProjectTargetsComboBox::currentIndexChanged), this, &EmbeddedLauncherConfigPage::changed); 0211 connect(projectTargetRadio, &QRadioButton::toggled, this, &EmbeddedLauncherConfigPage::changed); 0212 connect(executableRadio, &QRadioButton::toggled, this, &EmbeddedLauncherConfigPage::changed); 0213 connect(executablePath->lineEdit(), &KLineEdit::textEdited, this, &EmbeddedLauncherConfigPage::changed); 0214 connect(executablePath, &KUrlRequester::urlSelected, this, &EmbeddedLauncherConfigPage::changed); 0215 connect(argumentsCombo->lineEdit(), &KLineEdit::textEdited, this, &EmbeddedLauncherConfigPage::changed); 0216 connect(workingDirectory, &KUrlRequester::urlSelected, this, &EmbeddedLauncherConfigPage::changed); 0217 connect(workingDirectory->lineEdit(), &KLineEdit::textEdited, this, &EmbeddedLauncherConfigPage::changed); 0218 connect(boardCombo, &QComboBox::currentTextChanged, this, &EmbeddedLauncherConfigPage::changed); 0219 connect(commandCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &EmbeddedLauncherConfigPage::changed); 0220 0221 connect(devices, &Solid::DeviceNotifier::deviceAdded, this, &EmbeddedLauncherConfigPage::devicesChanged); 0222 connect(devices, &Solid::DeviceNotifier::deviceRemoved, this, &EmbeddedLauncherConfigPage::devicesChanged); 0223 connect(boardCombo, &QComboBox::currentTextChanged, this, &EmbeddedLauncherConfigPage::boardComboChanged); 0224 connect(mcuCombo->lineEdit(), &KLineEdit::textEdited, this, &EmbeddedLauncherConfigPage::changed); 0225 connect(mcuCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &EmbeddedLauncherConfigPage::mcuComboChanged); 0226 connect(baudCombo->lineEdit(), &KLineEdit::textEdited, this, &EmbeddedLauncherConfigPage::changed); 0227 0228 connect(presetsComboPage1, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &EmbeddedLauncherConfigPage::presetsChanged); 0229 connect(presetsComboPage2, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &EmbeddedLauncherConfigPage::presetsChanged); 0230 0231 KConfigGroup settings = ICore::self()->activeSession()->config()->group("Embedded"); 0232 if (settings.readEntry("arduinoFolder", "").isEmpty()) 0233 { 0234 QMessageBox::warning(nullptr, i18n("kdev-embedded"), i18n("Please run the first time wizard.")); 0235 FirstTimeWizard *embeddedWindow = new FirstTimeWizard(parent); 0236 embeddedWindow->setAttribute(Qt::WA_DeleteOnClose); 0237 embeddedWindow->show(); 0238 } 0239 } 0240 0241 const QString EmbeddedLauncherConfigPage::mcuTooltip() 0242 { 0243 return i18n("Please add a microcontroller"); 0244 } 0245 0246 const QStringList EmbeddedLauncherConfigPage::mcuList() 0247 { 0248 return Toolkit::instance().avrdudeMcuList(); 0249 } 0250 const QString EmbeddedLauncherConfigPage::interfaceTooltip() 0251 { 0252 QString tooltip; 0253 tooltip += i18n("Please connect or select an interface, for example:\n" 0254 "/dev/ttyUSBx, /dev/ttyACMx, COMx, etc"); 0255 return tooltip; 0256 } 0257 0258 const QString EmbeddedLauncherConfigPage::baudTooltip() 0259 { 0260 QString tooltip; 0261 tooltip += i18n("Please choose or select a baudrate:\n" 0262 "19200, 57600, 115200, etc"); 0263 return tooltip; 0264 } 0265 0266 const QString EmbeddedLauncherConfigPage::argumentsTooltip() 0267 { 0268 QString tooltip; 0269 tooltip += i18n("Variables to programmer:\n") 0270 += i18n("%avrdudeconf\t- Specify location of configuration file.\n") 0271 += i18n("%mcu\t- Required. Specify AVR device.\n") 0272 += i18n("%interface\t- Specify connection port.\n") 0273 += i18n("%baud\t- Override RS-232 baud rate.\n") 0274 += i18n("%hex\t- Firmware."); 0275 return tooltip; 0276 } 0277 0278 const QString EmbeddedLauncherConfigPage::commandTooltip() 0279 { 0280 QString tooltip; 0281 tooltip += i18n("%avrdude - Avrdude is a program for downloading code and data to Atmel AVR microcontrollers."); 0282 return tooltip; 0283 } 0284 0285 void EmbeddedLauncherConfigPage::checkActions(const QItemSelection& selected, const QItemSelection& unselected) 0286 { 0287 Q_UNUSED(unselected); 0288 qCDebug(ElMsg) << "checkActions"; 0289 if (!selected.indexes().isEmpty()) 0290 { 0291 qCDebug(ElMsg) << "have selection"; 0292 Q_ASSERT(selected.indexes().count() == 1); 0293 QModelIndex idx = selected.indexes().at(0); 0294 qCDebug(ElMsg) << "index" << idx; 0295 } 0296 } 0297 0298 void EmbeddedLauncherConfigPage::selectItemDialog() 0299 { 0300 } 0301 0302 void EmbeddedLauncherConfigPage::saveToConfiguration(KConfigGroup cfg, KDevelop::IProject* project) const 0303 { 0304 Q_UNUSED(project); 0305 0306 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::saveToConfiguration" << cfg.config()->groupList(); 0307 cfg.writeEntry(ExecutePlugin::isExecutableEntry, executableRadio->isChecked()); 0308 cfg.writeEntry(ExecutePlugin::executableEntry, executablePath->text()); 0309 cfg.writeEntry(ExecutePlugin::projectTargetEntry, projectTarget->currentItemPath()); 0310 0311 cfg.writeEntry(ExecutePlugin::launcherIndexEntry, stackedWidget->currentIndex()); 0312 0313 cfg.writeEntry(ExecutePlugin::boardEntry, boardCombo->currentIndex()); 0314 cfg.writeEntry(ExecutePlugin::mcuEntry, mcuCombo->currentText()); 0315 // interface 0316 // interface baud rate 0317 cfg.writeEntry(ExecutePlugin::argumentsEntry, argumentsCombo->currentText()); 0318 cfg.writeEntry(ExecutePlugin::workingDirEntry, workingDirectory->url()); 0319 cfg.writeEntry(ExecutePlugin::commandEntry, commandCombo->currentText()); 0320 0321 cfg.writeEntry(ExecutePlugin::openocdArgEntry, openocdArgumentsCombo->currentText()); 0322 cfg.writeEntry(ExecutePlugin::openocdWorkEntry, openocdWorkingDirectory->url()); 0323 cfg.writeEntry(ExecutePlugin::openocdCommEntry, openocdCommand->currentText()); 0324 0325 // Arduino configuration 0326 const KConfigGroup settings = ICore::self()->activeSession()->config()->group("Embedded"); 0327 const QString avrdudeConf = Toolkit::instance().avrConfigFile(); 0328 0329 QStringList arduinoConf; 0330 arduinoConf 0331 << m_model->getData(boardCombo->currentIndex()).m_id 0332 << mcuCombo->currentText() 0333 << baudCombo->currentText() 0334 << interfaceCombo->currentText() 0335 << executablePath->text() 0336 << avrdudeConf; 0337 cfg.writeEntry(ExecutePlugin::arduinoEntry, arduinoConf); 0338 0339 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::saveToConfiguration" << cfg.groupList() << cfg.keyList() << cfg.entryMap(); 0340 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::saveToConfiguration" << "arduinoConf" << arduinoConf << m_mcu << m_baud << interfaceCombo->currentText(); 0341 } 0342 0343 QString EmbeddedLauncherConfigPage::title() const 0344 { 0345 return i18n("Configure Embedded Application"); 0346 } 0347 0348 EmbeddedLauncherConfigPage::~EmbeddedLauncherConfigPage() 0349 { 0350 } 0351 0352 QList< KDevelop::LaunchConfigurationPageFactory* > EmbeddedLauncher::configPages() const 0353 { 0354 return QList<KDevelop::LaunchConfigurationPageFactory*>(); 0355 } 0356 0357 QString EmbeddedLauncher::description() const 0358 { 0359 return i18n("Upload applications to embedded platforms"); 0360 } 0361 0362 QString EmbeddedLauncher::id() 0363 { 0364 return QStringLiteral("EmbeddedLauncher"); 0365 } 0366 0367 QString EmbeddedLauncher::name() const 0368 { 0369 return i18n("Embedded"); 0370 } 0371 0372 EmbeddedLauncher::EmbeddedLauncher() 0373 { 0374 } 0375 0376 KJob* EmbeddedLauncher::start(const QString& launchMode, KDevelop::ILaunchConfiguration* cfg) 0377 { 0378 qCDebug(ElMsg) << "EmbeddedLauncher::start" << launchMode << cfg->name() << cfg->config().groupList(); 0379 Q_ASSERT(cfg); 0380 if (!cfg) 0381 { 0382 return nullptr; 0383 } 0384 if (launchMode == QLatin1String("execute")) 0385 { 0386 IExecutePlugin* iface = KDevelop::ICore::self()->pluginController()->pluginForExtension(QStringLiteral("org.kdevelop.IExecutePlugin"), QStringLiteral("kdevembedded-launcher"))->extension<IExecutePlugin>(); 0387 Q_ASSERT(iface); 0388 0389 KJob* depjob = iface->dependencyJob(cfg); 0390 QList<KJob*> l; 0391 if (depjob) 0392 { 0393 l << depjob; 0394 } 0395 l << new LauncherJob(KDevelop::ICore::self()->runController(), cfg); 0396 return new KDevelop::ExecuteCompositeJob(KDevelop::ICore::self()->runController(), l); 0397 0398 } 0399 qWarning() << "Unknown launch mode " << launchMode << "for config:" << cfg->name(); 0400 return nullptr; 0401 } 0402 0403 QStringList EmbeddedLauncher::supportedModes() const 0404 { 0405 return QStringList() << QStringLiteral("execute"); 0406 } 0407 0408 KDevelop::LaunchConfigurationPage* NativeAppPageFactory::createWidget(QWidget* parent) 0409 { 0410 return new EmbeddedLauncherConfigPage(parent); 0411 } 0412 0413 NativeAppPageFactory::NativeAppPageFactory() 0414 { 0415 } 0416 0417 NativeAppConfigType::NativeAppConfigType() 0418 { 0419 factoryList.append(new NativeAppPageFactory()); 0420 } 0421 0422 NativeAppConfigType::~NativeAppConfigType() 0423 { 0424 qDeleteAll(factoryList); 0425 factoryList.clear(); 0426 } 0427 0428 QString NativeAppConfigType::name() const 0429 { 0430 return i18n("Embedded"); 0431 } 0432 0433 0434 QList<KDevelop::LaunchConfigurationPageFactory*> NativeAppConfigType::configPages() const 0435 { 0436 return factoryList; 0437 } 0438 0439 QString NativeAppConfigType::id() const 0440 { 0441 return ExecutePlugin::_nativeAppConfigTypeId; 0442 } 0443 0444 QIcon NativeAppConfigType::icon() const 0445 { 0446 return QIcon::fromTheme(QStringLiteral("application-x-executable")); 0447 } 0448 0449 bool NativeAppConfigType::canLaunch(KDevelop::ProjectBaseItem* item) const 0450 { 0451 if (item->target() && item->target()->executable()) 0452 { 0453 return canLaunch(item->target()->executable()->builtUrl()); 0454 } 0455 return false; 0456 } 0457 0458 bool NativeAppConfigType::canLaunch(const QUrl& file) const 0459 { 0460 return (file.isLocalFile() && QFileInfo(file.toLocalFile()).isExecutable()); 0461 } 0462 0463 void NativeAppConfigType::configureLaunchFromItem(KConfigGroup cfg, KDevelop::ProjectBaseItem* item) const 0464 { 0465 qCDebug(ElMsg) << "EmbeddedLauncher::configureLaunchFromItem" << cfg.config()->groupList(); 0466 cfg.writeEntry(ExecutePlugin::isExecutableEntry, false); 0467 KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel(); 0468 cfg.writeEntry(ExecutePlugin::projectTargetEntry, model->pathFromIndex(model->indexFromItem(item))); 0469 cfg.writeEntry(ExecutePlugin::workingDirEntry, item->executable()->builtUrl().adjusted(QUrl::RemoveFilename)); 0470 cfg.sync(); 0471 } 0472 0473 void NativeAppConfigType::configureLaunchFromCmdLineArguments(KConfigGroup cfg, const QStringList& args) const 0474 { 0475 qCDebug(ElMsg) << "EmbeddedLauncher::configureLaunchFromCmdLineArguments" << cfg.config()->groupList(); 0476 cfg.writeEntry(ExecutePlugin::isExecutableEntry, true); 0477 Q_ASSERT(QFile::exists(args.first())); 0478 0479 cfg.writeEntry(ExecutePlugin::executableEntry, QUrl::fromLocalFile(args.first())); 0480 QStringList a(args); 0481 a.removeFirst(); 0482 cfg.writeEntry(ExecutePlugin::argumentsEntry, KShell::joinArgs(a)); 0483 cfg.sync(); 0484 } 0485 0486 QList<KDevelop::ProjectTargetItem*> targetsInFolder(KDevelop::ProjectFolderItem* folder) 0487 { 0488 QList<KDevelop::ProjectTargetItem*> ret; 0489 foreach (KDevelop::ProjectFolderItem* f, folder->folderList()) 0490 ret += targetsInFolder(f); 0491 0492 ret += folder->targetList(); 0493 return ret; 0494 } 0495 0496 bool actionLess(QAction* a, QAction* b) 0497 { 0498 return a->text() < b->text(); 0499 } 0500 0501 bool menuLess(QMenu* a, QMenu* b) 0502 { 0503 return a->title() < b->title(); 0504 } 0505 0506 0507 QMenu* NativeAppConfigType::launcherSuggestions() 0508 { 0509 0510 QMenu* ret = new QMenu(i18n("Embedded Binary")); 0511 0512 KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel(); 0513 QList<KDevelop::IProject*> projects = KDevelop::ICore::self()->projectController()->projects(); 0514 0515 foreach (KDevelop::IProject* project, projects) 0516 { 0517 if (project->projectFileManager()->features() & KDevelop::IProjectFileManager::Targets) 0518 { 0519 QList<KDevelop::ProjectTargetItem*> targets=targetsInFolder(project->projectItem()); 0520 QHash<KDevelop::ProjectBaseItem*, QList<QAction*> > targetsContainer; 0521 QMenu* projectMenu = ret->addMenu(QIcon::fromTheme(QStringLiteral("project-development")), project->name()); 0522 foreach (KDevelop::ProjectTargetItem* target, targets) 0523 { 0524 if (target->executable()) 0525 { 0526 QStringList path = model->pathFromIndex(target->index()); 0527 if (!path.isEmpty()) 0528 { 0529 QAction* act = new QAction(projectMenu); 0530 act->setData(KDevelop::joinWithEscaping(path, QChar::fromLatin1('/'),QChar::fromLatin1('\\'))); 0531 act->setProperty("name", target->text()); 0532 path.removeFirst(); 0533 act->setText(path.join(QChar::fromLatin1('/'))); 0534 act->setIcon(QIcon::fromTheme(QStringLiteral("system-run"))); 0535 connect(act, &QAction::triggered, this, &NativeAppConfigType::suggestionTriggered); 0536 targetsContainer[target->parent()].append(act); 0537 } 0538 } 0539 } 0540 0541 QList<QAction*> separateActions; 0542 QList<QMenu*> submenus; 0543 foreach (KDevelop::ProjectBaseItem* folder, targetsContainer.keys()) 0544 { 0545 QList<QAction*> actions = targetsContainer.value(folder); 0546 if (actions.size()==1 || !folder->parent()) 0547 { 0548 separateActions += actions.first(); 0549 } 0550 else 0551 { 0552 foreach (QAction* a, actions) 0553 { 0554 a->setText(a->property("name").toString()); 0555 } 0556 QStringList path = model->pathFromIndex(folder->index()); 0557 path.removeFirst(); 0558 QMenu* submenu = new QMenu(path.join(QStringLiteral("/"))); 0559 std::sort(actions.begin(), actions.end(), actionLess); 0560 submenu->addActions(actions); 0561 submenus += submenu; 0562 } 0563 } 0564 std::sort(separateActions.begin(), separateActions.end(), actionLess); 0565 std::sort(submenus.begin(), submenus.end(), menuLess); 0566 foreach (QMenu* m, submenus) 0567 projectMenu->addMenu(m); 0568 projectMenu->addActions(separateActions); 0569 0570 projectMenu->setEnabled(!projectMenu->isEmpty()); 0571 } 0572 } 0573 0574 return ret; 0575 } 0576 0577 void NativeAppConfigType::suggestionTriggered() 0578 { 0579 QAction* action = qobject_cast<QAction*>(sender()); 0580 KDevelop::ProjectModel* model = KDevelop::ICore::self()->projectController()->projectModel(); 0581 KDevelop::ProjectTargetItem* pitem = 0582 dynamic_cast<KDevelop::ProjectTargetItem*> 0583 (itemForPath(KDevelop::splitWithEscaping(action->data().toString(),QChar::fromLatin1('/'),QChar::fromLatin1('\\')), model)); 0584 if (pitem) 0585 { 0586 QPair<QString,QString> launcher = qMakePair(launchers().at(0)->supportedModes().at(0), launchers().at(0)->id()); 0587 KDevelop::IProject* p = pitem->project(); 0588 0589 KDevelop::ILaunchConfiguration* config = KDevelop::ICore::self()->runController()->createLaunchConfiguration(this, launcher, p, pitem->text()); 0590 KConfigGroup cfg = config->config(); 0591 qCDebug(ElMsg) << "NativeAppConfigType::suggestionTriggered" << cfg.groupList(); 0592 QStringList splitPath = model->pathFromIndex(pitem->index()); 0593 cfg.writeEntry(ExecutePlugin::projectTargetEntry, splitPath); 0594 cfg.writeEntry(ExecutePlugin::dependencyActionEntry, "Build"); 0595 cfg.sync(); 0596 0597 emit signalAddLaunchConfiguration(config); 0598 } 0599 } 0600 0601 void EmbeddedLauncherConfigPage::devicesChanged(const QString& udi) 0602 { 0603 Q_UNUSED(udi); 0604 interfaceCombo->clear(); 0605 QStringList interface; 0606 // It's necessary to implement a better way to check the interface 0607 auto devices = Solid::Device::allDevices(); 0608 //auto devices = Solid::Device::listFromType(Solid::DeviceInterface::Type::Block); 0609 0610 qCDebug(ElMsg) << "devicesChanged"; 0611 foreach (const auto& device, devices) 0612 { 0613 if (device.product() != QStringLiteral("") && device.udi().contains(QStringLiteral("tty"))) 0614 { 0615 qCDebug(ElMsg) << "INTERFACE ############ INTERFACE"; 0616 qCDebug(ElMsg) << "Description\t:" << device.description(); 0617 qCDebug(ElMsg) << "Parent Udi\t:" << device.parentUdi(); 0618 qCDebug(ElMsg) << "Product\t:" << device.product(); 0619 qCDebug(ElMsg) << "Udi\t:" << device.udi(); 0620 qCDebug(ElMsg) << "Vendor\t:" << device.vendor(); 0621 qCDebug(ElMsg) << "Icon\t:" << device.icon(); 0622 qCDebug(ElMsg) << "Emblems\t:" << device.emblems(); 0623 qCDebug(ElMsg) << "Interface\t:" << device.udi().split(QStringLiteral("/")).takeLast(); 0624 interface << QString(QStringLiteral("/dev/") + device.udi().split(QStringLiteral("/")).takeLast()); 0625 } 0626 } 0627 0628 interface.removeDuplicates(); 0629 interfaceCombo->addItems(interface); 0630 0631 if (interfaceCombo->count() == 0) 0632 { 0633 interfaceCombo->clear(); 0634 interfaceCombo->lineEdit()->setPlaceholderText(i18n("Could not find interface")); 0635 } 0636 } 0637 0638 void EmbeddedLauncherConfigPage::boardComboChanged(const QString& text) 0639 { 0640 Q_UNUSED(text); 0641 QString id = m_model->getData(boardCombo->currentIndex()).m_id; 0642 Board::instance().m_boards[id].printData(); 0643 0644 m_mcu = Board::instance().m_boards[id].m_bMcu; 0645 m_baud = Board::instance().m_boards[id].m_upSpeed; 0646 m_mcu.removeDuplicates(); 0647 m_baud.removeDuplicates(); 0648 0649 mcuCombo->clear(); 0650 mcuCombo->addItems(m_mcu); 0651 mcuCombo->insertSeparator(mcuCombo->count()); 0652 mcuCombo->addItems(mcuList()); 0653 baudCombo->clear(); 0654 baudCombo->addItems(m_baud); 0655 qCDebug(ElMsg) << "SIZEOF MCUCOMBO" << sizeof(mcuCombo); 0656 qCDebug(ElMsg) << "SIZEOF BAUDCOMBO" << sizeof(baudCombo); 0657 0658 0659 // TODO: select image from board selection 0660 QPixmap pix(QStringLiteral("%1/%2.svg").arg(m_boardImgsDir.absolutePath(), id)); 0661 if (pix.isNull()) 0662 { 0663 pix = QPixmap(m_boardImgsDir.absolutePath() + QStringLiteral("/arduino.svg")); 0664 } 0665 0666 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::boardComboChanged Pixmap" << pix; 0667 0668 if (pix.width() > pix.height()) 0669 { 0670 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::boardComboChanged Start rotation" << id << pix; 0671 QTransform rotate_disc; 0672 pix = pix.transformed(QTransform().rotate(90)); 0673 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::boardComboChanged End rotation" << id << pix; 0674 } 0675 0676 if (pix.width() > image->width() || pix.height() > image->height()) 0677 { 0678 pix = pix.scaled(image->width(), image->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); 0679 } 0680 0681 m_pixBuffer = QPixmap(image->width(), image->height()); 0682 QPainter painter(&m_pixBuffer); 0683 painter.fillRect(QRect(0, 0, image->width(), image->height()), palette().background()); 0684 painter.drawPixmap(m_pixBuffer.width() / 2 - pix.width() / 2, m_pixBuffer.height() / 2 - pix.height() / 2, pix); 0685 painter.end(); 0686 0687 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::boardComboChanged Baord image path" << id << pix; 0688 image->setPixmap(m_pixBuffer); 0689 0690 mcuComboChanged(0); 0691 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::boardComboChanged" << "mcus" << m_mcu; 0692 qCDebug(ElMsg) << "EmbeddedLauncherConfigPage::boardComboChanged" << image->width() << image->height(); 0693 } 0694 0695 void EmbeddedLauncherConfigPage::mcuComboChanged(int index) 0696 { 0697 if (index < 0) 0698 { 0699 return; 0700 } 0701 0702 baudCombo->setCurrentIndex(index); 0703 0704 qCDebug(ElMsg) << "mcuComboBox Index: " << index; 0705 qCDebug(ElMsg) << "mcuComboBox Count: " << mcuCombo->count(); 0706 } 0707 0708 void EmbeddedLauncherConfigPage::presetsChanged(int index) 0709 { 0710 if (index < 0) 0711 { 0712 return; 0713 } 0714 0715 qCDebug(ElMsg) << "presetsCombo Index: " << index; 0716 0717 stackedWidget->setCurrentIndex(index); 0718 presetsComboPage1->setCurrentIndex(index); 0719 presetsComboPage2->setCurrentIndex(index); 0720 }