diff --git a/plugins/meson/CMakeLists.txt b/plugins/meson/CMakeLists.txt index afa76ddf42..792fb3f80b 100644 --- a/plugins/meson/CMakeLists.txt +++ b/plugins/meson/CMakeLists.txt @@ -1,69 +1,67 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kdevmesonmanager\") set(mesonbuilder_SRCS mesonbuilder.cpp mesonconfig.cpp mesonjob.cpp mesonjobprune.cpp mesonmanager.cpp mintro/mesonintrospectjob.cpp mintro/mesonoptions.cpp mintro/mesonprojectinfo.cpp mintro/mesontargets.cpp mintro/mesontests.cpp rewriter/mesonactionbase.cpp rewriter/mesondefaultopts.cpp rewriter/mesonkwargsinfo.cpp rewriter/mesonkwargsmodify.cpp rewriter/mesonrewriterjob.cpp settings/mesonadvancedsettings.cpp settings/mesonconfigpage.cpp settings/mesonlisteditor.cpp settings/mesonnewbuilddir.cpp settings/mesonoptionbaseview.cpp settings/mesonoptionsview.cpp settings/mesonrewriterinput.cpp settings/mesonrewriterpage.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) ki18n_wrap_ui(mesonbuilder_SRCS settings/mesonadvancedsettings.ui settings/mesonconfigpage.ui settings/mesonlisteditor.ui settings/mesonnewbuilddir.ui settings/mesonoptionbaseview.ui settings/mesonoptionsview.ui settings/mesonrewriterinput.ui settings/mesonrewriteroptioncontainer.ui settings/mesonrewriterpage.ui ) ecm_qt_declare_logging_category(mesonbuilder_SRCS HEADER debug.h IDENTIFIER KDEV_Meson CATEGORY_NAME "kdevelop.plugins.meson" ) kdevplatform_add_plugin(kdevmesonmanager JSON kdevmesonmanager.json SOURCES ${mesonbuilder_SRCS}) -add_subdirectory(icons) - target_link_libraries(kdevmesonmanager Qt5::Concurrent KDev::Interfaces KDev::Language KDev::Project KDev::Util KDev::OutputView ) set_target_properties(kdevmesonmanager PROPERTIES CXX_STANDARD 14 CXX_STANDARD_REQUIRED YES ) diff --git a/plugins/meson/icons/128-apps-meson.png b/plugins/meson/icons/128-apps-meson.png deleted file mode 100644 index f09f8fd3c4..0000000000 Binary files a/plugins/meson/icons/128-apps-meson.png and /dev/null differ diff --git a/plugins/meson/icons/16-apps-meson.png b/plugins/meson/icons/16-apps-meson.png deleted file mode 100644 index 00f73111ce..0000000000 Binary files a/plugins/meson/icons/16-apps-meson.png and /dev/null differ diff --git a/plugins/meson/icons/256-apps-meson.png b/plugins/meson/icons/256-apps-meson.png deleted file mode 100644 index 03868d680e..0000000000 Binary files a/plugins/meson/icons/256-apps-meson.png and /dev/null differ diff --git a/plugins/meson/icons/32-apps-meson.png b/plugins/meson/icons/32-apps-meson.png deleted file mode 100644 index 9e188071c9..0000000000 Binary files a/plugins/meson/icons/32-apps-meson.png and /dev/null differ diff --git a/plugins/meson/icons/64-apps-meson.png b/plugins/meson/icons/64-apps-meson.png deleted file mode 100644 index a80d901deb..0000000000 Binary files a/plugins/meson/icons/64-apps-meson.png and /dev/null differ diff --git a/plugins/meson/icons/CMakeLists.txt b/plugins/meson/icons/CMakeLists.txt deleted file mode 100644 index 4dd530f40a..0000000000 --- a/plugins/meson/icons/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -ecm_install_icons(ICONS - 256-apps-meson.png - 128-apps-meson.png - 64-apps-meson.png - 32-apps-meson.png - 16-apps-meson.png - DESTINATION ${KDE_INSTALL_ICONDIR}) - diff --git a/plugins/meson/icons/meson_logo.svg b/plugins/meson/icons/meson_logo.svg deleted file mode 100644 index b8dd59371b..0000000000 --- a/plugins/meson/icons/meson_logo.svg +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/plugins/meson/kdevmesonmanager.json b/plugins/meson/kdevmesonmanager.json index 5affaeeeab..57dcfe117f 100644 --- a/plugins/meson/kdevmesonmanager.json +++ b/plugins/meson/kdevmesonmanager.json @@ -1,60 +1,60 @@ { "KPlugin": { "Category": "Project Management", "Description": "Imports and edits Meson projects", "Description[ca@valencia]": "Importa i edita projectes del Meson", "Description[ca]": "Importa i edita projectes del Meson", "Description[cs]": "Importuje a upravuje vlastní projekty Meson", "Description[de]": "Import und Bearbeitung von benutzerdefinierten Meson-Projekten", "Description[en_GB]": "Imports and edits Meson projects", "Description[es]": "Importa y edita proyectos Meson", "Description[fr]": "Importe et édite des projets Meson", "Description[gl]": "Importa e edita proxectos Meson", "Description[it]": "Importa e modifica i progetti Meson", "Description[nl]": "Importeert en bewerkt Meson-projecten", "Description[pl]": "Importuje i edytuje projekty Meson", "Description[pt]": "Importa e edita os projectos do Meson", "Description[pt_BR]": "Importa e edita os projetos do Meson", "Description[sv]": "Importerar och redigerar Meson-projekt", "Description[uk]": "Імпортує і дає змогу редагувати проєкти Meson", "Description[x-test]": "xxImports and edits Meson projectsxx", "Description[zh_CN]": "倒入并编辑 Meson 工程", - "Icon": "meson", + "Icon": "run-build", "Id": "KDevMesonManager", "Name": "Meson Project Manager", "Name[ca@valencia]": "Gestor de projectes Meson", "Name[ca]": "Gestor de projectes Meson", "Name[cs]": "Správce projektů Meson", "Name[de]": "Meson-Projektverwaltung", "Name[en_GB]": "Meson Project Manager", "Name[es]": "Gestor de proyectos Meson", "Name[fr]": "Gestionnaire de projet Meson", "Name[gl]": "Xestor de proxectos Meson", "Name[it]": "Gestore progetto Meson", "Name[nl]": "Meson projectbeheerder", "Name[pl]": "Zarządzanie projektem Meson", "Name[pt]": "Gestor de Projectos do Meson", "Name[pt_BR]": "Gerenciador de projetos do Meson", "Name[sv]": "Meson projekthanterare", "Name[uk]": "Керування проєктами Meson", "Name[x-test]": "xxMeson Project Managerxx", "Name[zh_CN]": "Meson 工程管理器", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Category": "Project", "X-KDevelop-FileManager": "Meson", "X-KDevelop-IRequired": [ "org.kdevelop.IProjectBuilder" ], "X-KDevelop-Interfaces": [ "org.kdevelop.IBuildSystemManager", "org.kdevelop.IProjectFileManager" ], "X-KDevelop-Mode": "NoGUI", "X-KDevelop-ProjectFilesFilter": [ "meson.build" ], "X-KDevelop-ProjectFilesFilterDescription": "Meson Project Files" } diff --git a/plugins/meson/settings/mesonconfigpage.cpp b/plugins/meson/settings/mesonconfigpage.cpp index 0752516172..db9bad059f 100644 --- a/plugins/meson/settings/mesonconfigpage.cpp +++ b/plugins/meson/settings/mesonconfigpage.cpp @@ -1,356 +1,356 @@ /* This file is part of KDevelop Copyright 2018 Daniel Mensinger This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mesonconfigpage.h" #include "mesonbuilder.h" #include "mesonjob.h" #include "mesonmanager.h" #include "mesonnewbuilddir.h" #include "mintro/mesonintrospectjob.h" #include "ui_mesonconfigpage.h" #include #include #include #include #include #include using namespace KDevelop; MesonConfigPage::MesonConfigPage(IPlugin* plugin, IProject* project, QWidget* parent) : ConfigPage(plugin, nullptr, parent) , m_project(project) { Q_ASSERT(project); // Catch errors early MesonManager* mgr = dynamic_cast(m_project->buildSystemManager()); Q_ASSERT(mgr); // This dialog only works with the MesonManager m_ui = new Ui::MesonConfigPage; m_ui->setupUi(this); m_ui->advanced->setSupportedBackends(mgr->supportedMesonBackends()); m_config = Meson::getMesonConfig(m_project); if (m_config.buildDirs.isEmpty()) { m_config.currentIndex = -1; reset(); return; } else if (m_config.currentIndex < 0 || m_config.currentIndex >= m_config.buildDirs.size()) { m_config.currentIndex = 0; } QStringList buildPathList; for (auto& i : m_config.buildDirs) { buildPathList << i.buildDir.toLocalFile(); } m_ui->i_buildDirs->blockSignals(true); m_ui->i_buildDirs->clear(); m_ui->i_buildDirs->addItems(buildPathList); m_ui->i_buildDirs->setCurrentIndex(m_config.currentIndex); m_ui->i_buildDirs->blockSignals(false); reset(); } void MesonConfigPage::writeConfig() { qCDebug(KDEV_Meson) << "Writing config to file"; if (m_config.currentIndex >= 0) { m_config.buildDirs[m_config.currentIndex] = m_current; } if (m_config.buildDirs.isEmpty()) { m_config.currentIndex = -1; } else if (m_config.currentIndex < 0 || m_config.currentIndex >= m_config.buildDirs.size()) { m_config.currentIndex = 0; } Meson::writeMesonConfig(m_project, m_config); } void MesonConfigPage::apply() { qCDebug(KDEV_Meson) << "Applying meson config for build dir " << m_current.buildDir; readUI(); writeConfig(); if (m_config.currentIndex >= 0 && m_configChanged) { QList joblist; auto options = m_ui->options->options(); if (!options) { qCWarning(KDEV_Meson) << "Options is nullptr. Can not update meson config"; return; } QStringList mesonArgs = options->getMesonArgs(); if (mesonArgs.empty()) { qCDebug(KDEV_Meson) << "Config has not changed --> nothing has to be updated"; return; } // Check if a configuration is required auto status = MesonBuilder::evaluateBuildDirectory(m_current.buildDir, m_current.mesonBackend); if (status != MesonBuilder::MESON_CONFIGURED) { joblist << new MesonJob(m_current, m_project, MesonJob::CONFIGURE, mesonArgs, nullptr); } joblist << new MesonJob(m_current, m_project, MesonJob::SET_CONFIG, mesonArgs, nullptr); joblist << m_ui->options->repopulateFromBuildDir(m_project, m_current); KJob* job = new ExecuteCompositeJob(nullptr, joblist); connect(job, &KJob::result, this, [this]() { setDisabled(false); updateUI(); }); setDisabled(true); m_configChanged = false; job->start(); } } void MesonConfigPage::defaults() { qCDebug(KDEV_Meson) << "Restoring build dir " << m_current.buildDir << " to it's default values"; MesonManager* mgr = dynamic_cast(m_project->buildSystemManager()); Q_ASSERT(mgr); m_current.mesonArgs.clear(); m_current.mesonBackend = mgr->defaultMesonBackend(); m_current.mesonExecutable = mgr->findMeson(); m_ui->options->resetAll(); updateUI(); } void MesonConfigPage::reset() { if (m_config.buildDirs.isEmpty()) { m_config.currentIndex = -1; m_ui->i_buildDirs->clear(); setWidgetsDisabled(true); m_ui->b_addDir->setDisabled(false); // Allow adding a new build dir when there are none return; } else if (m_config.currentIndex < 0 || m_config.currentIndex >= m_config.buildDirs.size()) { m_config.currentIndex = 0; m_ui->i_buildDirs->blockSignals(true); m_ui->i_buildDirs->setCurrentIndex(m_config.currentIndex); m_ui->i_buildDirs->blockSignals(false); } setWidgetsDisabled(false); qCDebug(KDEV_Meson) << "Resetting changes for build dir " << m_current.buildDir; m_current = m_config.buildDirs[m_config.currentIndex]; m_ui->options->repopulateFromBuildDir(m_project, m_current)->start(); updateUI(); } void MesonConfigPage::checkStatus() { // Get the config build dir status auto status = MesonBuilder::evaluateBuildDirectory(m_current.buildDir, m_current.mesonBackend); auto setStatus = [this](const QString& msg, int color) -> void { KColorScheme scheme(QPalette::Normal); KColorScheme::ForegroundRole role; switch (color) { case 0: role = KColorScheme::PositiveText; break; case 1: role = KColorScheme::NeutralText; break; case 2: default: role = KColorScheme::NegativeText; break; } QPalette pal = m_ui->l_status->palette(); pal.setColor(QPalette::Foreground, scheme.foreground(role).color()); m_ui->l_status->setPalette(pal); m_ui->l_status->setText(i18n("Status: %1", msg)); }; switch (status) { case MesonBuilder::DOES_NOT_EXIST: setStatus(i18n("The current build directory does not exist"), 1); break; case MesonBuilder::CLEAN: setStatus(i18n("The current build directory is empty"), 1); break; case MesonBuilder::MESON_CONFIGURED: setStatus(i18n("Build directory configured"), 0); break; case MesonBuilder::MESON_FAILED_CONFIGURATION: setStatus(i18n("This meson build directory is not fully configured"), 1); break; case MesonBuilder::INVALID_BUILD_DIR: setStatus(i18n("The current build directory is invalid"), 2); break; case MesonBuilder::DIR_NOT_EMPTY: setStatus(i18n("This directory does not seem to be a meson build directory"), 2); break; case MesonBuilder::EMPTY_STRING: setStatus(i18n("Invalid build directory configuration (empty build directory string)"), 2); break; case MesonBuilder::___UNDEFINED___: setStatus(i18n("Something went very wrong. This is a bug"), 2); break; } KColorScheme scheme(QPalette::Normal); KColorScheme::ForegroundRole role; int numChanged = 0; auto options = m_ui->options->options(); if (options) { numChanged = options->numChanged(); } if (numChanged == 0) { role = KColorScheme::NormalText; m_ui->l_changed->setText(i18n("No changes")); } else { role = KColorScheme::NeutralText; m_ui->l_changed->setText(i18n("%1 options changed", numChanged)); } QPalette pal = m_ui->l_changed->palette(); pal.setColor(QPalette::Foreground, scheme.foreground(role).color()); m_ui->l_changed->setPalette(pal); } void MesonConfigPage::updateUI() { auto aConf = m_ui->advanced->getConfig(); aConf.args = m_current.mesonArgs; aConf.backend = m_current.mesonBackend; aConf.meson = m_current.mesonExecutable; m_ui->advanced->setConfig(aConf); checkStatus(); } void MesonConfigPage::readUI() { qCDebug(KDEV_Meson) << "Reading current build configuration from the UI " << m_current.buildDir.toLocalFile(); auto aConf = m_ui->advanced->getConfig(); m_current.mesonArgs = aConf.args; m_current.mesonBackend = aConf.backend; m_current.mesonExecutable = aConf.meson; } void MesonConfigPage::setWidgetsDisabled(bool disabled) { m_ui->advanced->setDisabled(disabled); m_ui->i_buildDirs->setDisabled(disabled); m_ui->b_addDir->setDisabled(disabled); m_ui->b_rmDir->setDisabled(disabled); m_ui->options->setDisabled(disabled); } void MesonConfigPage::addBuildDir() { qCDebug(KDEV_Meson) << "Adding build directory"; MesonManager* mgr = dynamic_cast(m_project->buildSystemManager()); MesonBuilder* bld = dynamic_cast(mgr->builder()); Q_ASSERT(mgr); Q_ASSERT(bld); MesonNewBuildDir newBD(m_project); if (!newBD.exec() || !newBD.isConfigValid()) { qCDebug(KDEV_Meson) << "Failed to create a new build directory"; return; } m_current = newBD.currentConfig(); m_current.canonicalizePaths(); m_config.currentIndex = m_config.addBuildDir(m_current); m_ui->i_buildDirs->blockSignals(true); m_ui->i_buildDirs->addItem(m_current.buildDir.toLocalFile()); m_ui->i_buildDirs->setCurrentIndex(m_config.currentIndex); m_ui->i_buildDirs->blockSignals(false); setWidgetsDisabled(true); writeConfig(); KJob* job = bld->configure(m_project, m_current, newBD.mesonArgs()); connect(job, &KJob::result, this, [this]() { reset(); }); job->start(); } void MesonConfigPage::removeBuildDir() { qCDebug(KDEV_Meson) << "Removing current build directory"; m_ui->i_buildDirs->blockSignals(true); m_ui->i_buildDirs->removeItem(m_config.currentIndex); m_config.removeBuildDir(m_config.currentIndex); if (m_config.buildDirs.isEmpty()) { m_config.currentIndex = -1; } else if (m_config.currentIndex < 0 || m_config.currentIndex >= m_config.buildDirs.size()) { m_config.currentIndex = 0; } m_ui->i_buildDirs->setCurrentIndex(m_config.currentIndex); m_ui->i_buildDirs->blockSignals(false); reset(); writeConfig(); } void MesonConfigPage::changeBuildDirIndex(int index) { if (index == m_config.currentIndex || m_config.buildDirs.isEmpty()) { return; } if (index < 0 || index >= m_config.buildDirs.size()) { qCWarning(KDEV_Meson) << "Invalid build dir index " << index; return; } qCDebug(KDEV_Meson) << "Changing build directory to index " << index; m_config.currentIndex = index; reset(); writeConfig(); } void MesonConfigPage::emitChanged() { m_configChanged = true; checkStatus(); emit changed(); } QString MesonConfigPage::name() const { return i18n("Meson"); } QString MesonConfigPage::fullName() const { return i18n("Meson project configuration"); } QIcon MesonConfigPage::icon() const { - return QIcon::fromTheme(QStringLiteral("meson")); + return QIcon::fromTheme(QStringLiteral("run-build")); } diff --git a/plugins/meson/settings/mesonrewriterpage.cpp b/plugins/meson/settings/mesonrewriterpage.cpp index 9c77c516af..2963812fd8 100644 --- a/plugins/meson/settings/mesonrewriterpage.cpp +++ b/plugins/meson/settings/mesonrewriterpage.cpp @@ -1,462 +1,462 @@ /* This file is part of KDevelop Copyright 2019 Daniel Mensinger This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mesonrewriterpage.h" #include "mesonconfig.h" #include "mesonmanager.h" #include "mesonoptionbaseview.h" #include "mesonrewriterinput.h" #include "mintro/mesonintrospectjob.h" #include "mintro/mesonprojectinfo.h" #include "rewriter/mesondefaultopts.h" #include "rewriter/mesonkwargsinfo.h" #include "rewriter/mesonkwargsmodify.h" #include "rewriter/mesonrewriterjob.h" #include "ui_mesonrewriterpage.h" #include #include #include #include #include #include #include #include using namespace KDevelop; using namespace std; class JobDeleter { public: explicit JobDeleter(QList jobs) : m_jobs(jobs) { } ~JobDeleter() { for (KJob* i : m_jobs) { delete i; } } private: QList m_jobs; }; MesonRewriterPage::MesonRewriterPage(IPlugin* plugin, IProject* project, QWidget* parent) : ConfigPage(plugin, nullptr, parent) , m_project(project) { Q_ASSERT(m_project); m_ui = new Ui::MesonRewriterPage; m_ui->setupUi(this); m_projectKwargs = constructPojectInputs(); // Initialize widgets for (auto* i : m_projectKwargs) { m_ui->c_project->addWidget(i); connect(i, &MesonRewriterInputBase::configChanged, this, &MesonRewriterPage::emitChanged); } recalculateLengths(); reset(); } #define STRING_INPUT(name, id) new MesonRewriterInputString(QStringLiteral(name), QStringLiteral(id), this) QVector MesonRewriterPage::constructPojectInputs() { return { STRING_INPUT("Version", "version"), STRING_INPUT("License", "license"), STRING_INPUT("Meson version", "meson_version"), STRING_INPUT("Subprojects directory", "subproject_dir"), }; } MesonOptContainerPtr MesonRewriterPage::constructDefaultOpt(const QString& name, const QString& value) { if (!m_opts) { return nullptr; } for (auto& i : m_opts->options()) { if (i->name() != name) { continue; } if (!value.isNull()) { i->setFromString(value); } auto optView = MesonOptionBaseView::fromOption(i, this); if (!optView) { continue; } auto opt = std::make_shared(optView, this); if (!opt) { continue; } connect(opt.get(), &MesonRewriterOptionContainer::configChanged, this, &MesonRewriterPage::emitChanged); return opt; } return nullptr; } void MesonRewriterPage::setWidgetsDisabled(bool disabled) { m_ui->c_tabs->setDisabled(disabled); } void MesonRewriterPage::recalculateLengths() { // Calculate the maximum name width to align all widgets vector lengths; int maxWidth = 50; lengths.reserve(m_projectKwargs.size() + m_defaultOpts.size()); auto input_op = [](MesonRewriterInputBase* x) -> int { return x->nameWidth(); }; auto optCont_op = [](MesonOptContainerPtr x) -> int { return x->view()->nameWidth(); }; transform(begin(m_projectKwargs), end(m_projectKwargs), back_inserter(lengths), input_op); transform(begin(m_defaultOpts), end(m_defaultOpts), back_inserter(lengths), optCont_op); maxWidth = accumulate(begin(lengths), end(lengths), maxWidth, [](int a, int b) -> int { return max(a, b); }); // Set widgets width for (auto* i : m_projectKwargs) { i->setMinNameWidth(maxWidth); } for (auto& i : m_defaultOpts) { i->view()->setMinNameWidth(maxWidth); } m_ui->l_dispProject->setMinimumWidth(maxWidth); } void MesonRewriterPage::checkStatus() { // Get the config build dir status auto setStatus = [this](const QString& msg, int color) -> void { KColorScheme scheme(QPalette::Normal); KColorScheme::ForegroundRole role; switch (color) { case 0: role = KColorScheme::PositiveText; setDisabled(false); break; case 1: role = KColorScheme::NeutralText; setDisabled(true); break; case 2: default: role = KColorScheme::NegativeText; setDisabled(true); break; } QPalette pal = m_ui->l_status->palette(); pal.setColor(QPalette::Foreground, scheme.foreground(role).color()); m_ui->l_status->setPalette(pal); m_ui->l_status->setText(i18n("Status: %1", msg)); }; switch (m_state) { case START: setStatus(i18n("Initializing GUI"), 1); break; case LOADING: setStatus(i18n("Loading project data..."), 1); break; case WRITING: setStatus(i18n("Writing project data..."), 1); break; case READY: setStatus(i18n("Initializing GUI"), 0); break; case ERROR: setStatus(i18n("Loading meson rewriter data failed"), 2); break; } // Remove old default options m_defaultOpts.erase(remove_if(begin(m_defaultOpts), end(m_defaultOpts), [](auto x) { return x->shouldDelete(); }), end(m_defaultOpts)); KColorScheme scheme(QPalette::Normal); KColorScheme::ForegroundRole role; int numChanged = 0; numChanged += count_if(begin(m_projectKwargs), end(m_projectKwargs), [](auto* x) { return x->hasChanged(); }); numChanged += count_if(begin(m_defaultOpts), end(m_defaultOpts), [](auto x) { return x->hasChanged(); }); if (numChanged == 0) { role = KColorScheme::NormalText; m_ui->l_changed->setText(i18n("No changes")); } else { role = KColorScheme::NeutralText; m_ui->l_changed->setText(i18n("%1 options changed", numChanged)); } QPalette pal = m_ui->l_changed->palette(); pal.setColor(QPalette::Foreground, scheme.foreground(role).color()); m_ui->l_changed->setPalette(pal); } void MesonRewriterPage::setStatus(MesonRewriterPage::State s) { m_state = s; checkStatus(); } void MesonRewriterPage::apply() { qCDebug(KDEV_Meson) << "REWRITER GUI: APPLY"; auto projectSet = make_shared(MesonKWARGSProjectModify::SET); auto projectDel = make_shared(MesonKWARGSProjectModify::DELETE); auto defOptsSet = make_shared(MesonRewriterDefaultOpts::SET); auto defOptsDel = make_shared(MesonRewriterDefaultOpts::DELETE); auto writer = [](MesonRewriterInputBase* widget, MesonKWARGSModifyPtr set, MesonKWARGSModifyPtr del) { if (!widget->hasChanged()) { return; } if (widget->isEnabled()) { widget->writeToAction(set.get()); } else { widget->writeToAction(del.get()); } }; for_each(begin(m_projectKwargs), end(m_projectKwargs), [&](auto* w) { writer(w, projectSet, projectDel); }); QStringList deletedOptions = m_initialDefaultOpts; for (auto& i : m_defaultOpts) { auto opt = i->view()->option(); // Detect deleted options by removing all current present options from the initial option list deletedOptions.removeAll(opt->name()); if (opt->isUpdated() || !m_initialDefaultOpts.contains(opt->name())) { defOptsSet->set(opt->name(), opt->value()); } } for (auto i : deletedOptions) { defOptsDel->set(i, QString()); } QVector actions = { projectSet, projectDel, defOptsSet, defOptsDel }; KJob* rewriterJob = new MesonRewriterJob(m_project, actions, this); // Reload the GUI once the data has been written connect(rewriterJob, &KJob::result, this, &MesonRewriterPage::reset); setStatus(WRITING); rewriterJob->start(); } void MesonRewriterPage::reset() { qCDebug(KDEV_Meson) << "REWRITER GUI: RESET"; Meson::BuildDir buildDir = Meson::currentBuildDir(m_project); if (!buildDir.isValid()) { setStatus(ERROR); return; } auto projectInfo = std::make_shared(); QVector actions = { projectInfo }; QVector types = { MesonIntrospectJob::PROJECTINFO, MesonIntrospectJob::BUILDOPTIONS }; MesonIntrospectJob::Mode mode = MesonIntrospectJob::MESON_FILE; auto introspectJob = new MesonIntrospectJob(m_project, buildDir, types, mode, this); auto rewriterJob = new MesonRewriterJob(m_project, actions, this); QList jobs = { introspectJob, rewriterJob }; // Don't automatically delete jobs beause they are used in the lambda below for (KJob* i : jobs) { i->setAutoDelete(false); } KJob* job = new ExecuteCompositeJob(this, jobs); connect(job, &KJob::result, this, [=]() -> void { JobDeleter deleter(jobs); // Make sure to free all jobs with RAII auto prInfo = introspectJob->projectInfo(); m_opts = introspectJob->buildOptions(); if (!prInfo || !m_opts) { setStatus(ERROR); return; } m_ui->l_project->setText(QStringLiteral("

") + prInfo->name() + QStringLiteral("

")); auto setter = [](MesonRewriterInputBase* w, MesonKWARGSInfoPtr i) { w->resetFromAction(i.get()); }; for_each(begin(m_projectKwargs), end(m_projectKwargs), [=](auto* x) { setter(x, projectInfo); }); // Updated the default options m_defaultOpts.clear(); m_initialDefaultOpts.clear(); if (projectInfo->hasKWARG(QStringLiteral("default_options"))) { auto rawValues = projectInfo->getArray(QStringLiteral("default_options")); auto options = m_opts->options(); for (auto i : rawValues) { int idx = i.indexOf(QLatin1Char('=')); if (idx < 0) { continue; } QString name = i.left(idx); QString val = i.mid(idx + 1); auto opt = constructDefaultOpt(name, val); if (!opt) { continue; } m_defaultOpts += opt; m_initialDefaultOpts += name; m_ui->c_defOpts->addWidget(opt.get()); } } recalculateLengths(); setStatus(READY); return; }); setStatus(LOADING); job->start(); } void MesonRewriterPage::newOption() { // Sort by section QStringList core; QStringList backend; QStringList base; QStringList compiler; QStringList directory; QStringList user; QStringList test; for (auto& i : m_opts->options()) { switch (i->section()) { case MesonOptionBase::CORE: core += i->name(); break; case MesonOptionBase::BACKEND: backend += i->name(); break; case MesonOptionBase::BASE: base += i->name(); break; case MesonOptionBase::COMPILER: compiler += i->name(); break; case MesonOptionBase::DIRECTORY: directory += i->name(); break; case MesonOptionBase::USER: user += i->name(); break; case MesonOptionBase::TEST: test += i->name(); break; } } QStringList total = core + backend + base + compiler + directory + user + test; // Remove already existing options for (auto& i : m_defaultOpts) { total.removeAll(i->view()->option()->name()); } QInputDialog dialog(this); dialog.setOption(QInputDialog::UseListViewForComboBoxItems, true); dialog.setInputMode(QInputDialog::TextInput); dialog.setWindowTitle(i18n("Select meson option to add")); dialog.setLabelText(i18n("Select one new meson option to add")); dialog.setComboBoxItems(total); if (dialog.exec() != QDialog::Accepted) { return; } auto opt = constructDefaultOpt(dialog.textValue(), QString()); if (!opt) { return; } m_defaultOpts += opt; m_ui->c_defOpts->addWidget(opt.get()); recalculateLengths(); } void MesonRewriterPage::defaults() { reset(); } void MesonRewriterPage::emitChanged() { m_configChanged = true; checkStatus(); emit changed(); } QString MesonRewriterPage::name() const { return i18n("Project"); } QString MesonRewriterPage::fullName() const { return i18n("Meson project settings"); } QIcon MesonRewriterPage::icon() const { - return QIcon::fromTheme(QStringLiteral("meson")); + return QIcon::fromTheme(QStringLiteral("run-build")); }