diff --git a/plugins/custom-definesandincludes/kcm_widget/defineswidget.cpp b/plugins/custom-definesandincludes/kcm_widget/defineswidget.cpp index 0213e3f94c..ff25651ff9 100644 --- a/plugins/custom-definesandincludes/kcm_widget/defineswidget.cpp +++ b/plugins/custom-definesandincludes/kcm_widget/defineswidget.cpp @@ -1,77 +1,81 @@ /************************************************************************ * * * Copyright 2010 Andreas Pakulat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 or version 3 of the License, or * * (at your option) any later version. * * * * This program 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 * * General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, see . * ************************************************************************/ #include "defineswidget.h" #include #include #include "../ui_defineswidget.h" #include "definesmodel.h" #include using namespace KDevelop; DefinesWidget::DefinesWidget( QWidget* parent ) : QWidget ( parent ), ui( new Ui::DefinesWidget ) , definesModel( new DefinesModel( this ) ) { ui->setupUi( this ); ui->defines->setModel( definesModel ); ui->defines->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch ); connect( definesModel, &DefinesModel::dataChanged, this, static_cast(&DefinesWidget::definesChanged) ); connect( definesModel, &DefinesModel::rowsInserted, this, static_cast(&DefinesWidget::definesChanged) ); connect( definesModel, &DefinesModel::rowsRemoved, this, static_cast(&DefinesWidget::definesChanged) ); QAction* delDefAction = new QAction( i18n("Delete Define"), this ); delDefAction->setShortcut( QKeySequence(Qt::Key_Delete) ); delDefAction->setShortcutContext( Qt::WidgetWithChildrenShortcut ); delDefAction->setIcon( QIcon::fromTheme(QStringLiteral("edit-delete")) ); ui->defines->addAction( delDefAction ); ui->defines->setContextMenuPolicy( Qt::ActionsContextMenu ); connect( delDefAction, &QAction::triggered, this, &DefinesWidget::deleteDefine ); } +DefinesWidget::~DefinesWidget() +{ +} + void DefinesWidget::setDefines( const Defines& defines ) { bool b = blockSignals( true ); clear(); definesModel->setDefines( defines ); blockSignals( b ); } void DefinesWidget::definesChanged() { qCDebug(DEFINESANDINCLUDES) << "defines changed"; emit definesChanged( definesModel->defines() ); } void DefinesWidget::clear() { definesModel->setDefines( {} ); } void DefinesWidget::deleteDefine() { qCDebug(DEFINESANDINCLUDES) << "Deleting defines"; const QModelIndexList selection = ui->defines->selectionModel()->selectedRows(); for (const QModelIndex& row : selection) { definesModel->removeRow( row.row() ); } } diff --git a/plugins/custom-definesandincludes/kcm_widget/defineswidget.h b/plugins/custom-definesandincludes/kcm_widget/defineswidget.h index af2a26816d..d1aee20652 100644 --- a/plugins/custom-definesandincludes/kcm_widget/defineswidget.h +++ b/plugins/custom-definesandincludes/kcm_widget/defineswidget.h @@ -1,58 +1,60 @@ /************************************************************************ * * * Copyright 2010 Andreas Pakulat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 or version 3 of the License, or * * (at your option) any later version. * * * * This program 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 * * General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, see . * ************************************************************************/ #ifndef KDEVELOP_PROJECTMANAGERS_CUSTOM_BUILDSYSTEM_DEFINESWIDGET_H #define KDEVELOP_PROJECTMANAGERS_CUSTOM_BUILDSYSTEM_DEFINESWIDGET_H #include #include "idefinesandincludesmanager.h" namespace Ui { class DefinesWidget; } namespace KDevelop { class IProject; } class DefinesModel; class DefinesWidget : public QWidget { Q_OBJECT public: explicit DefinesWidget( QWidget* parent = nullptr ); + ~DefinesWidget() override; + void setDefines( const KDevelop::Defines& defines ); void clear(); Q_SIGNALS: void definesChanged( const KDevelop::Defines& defines ); private Q_SLOTS: // Forward defines model changes void definesChanged(); // Handle Del key in defines list void deleteDefine(); private: - Ui::DefinesWidget* ui; + QScopedPointer ui; DefinesModel* definesModel; }; #endif diff --git a/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.cpp b/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.cpp index cfa419575e..8e869eb1cf 100644 --- a/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.cpp +++ b/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.cpp @@ -1,307 +1,311 @@ /************************************************************************ * * * Copyright 2010 Andreas Pakulat * * Copyright 2014 Sergey Kalinichev * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 * * General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, see . * ************************************************************************/ #include "projectpathswidget.h" #include #include #include #include #include "../compilerprovider/compilerprovider.h" #include "../compilerprovider/settingsmanager.h" #include "ui_projectpathswidget.h" #include "ui_batchedit.h" #include "projectpathsmodel.h" #include #include #include using namespace KDevelop; namespace { enum PageType { IncludesPage, DefinesPage, ParserArgumentsPage }; } ProjectPathsWidget::ProjectPathsWidget( QWidget* parent ) : QWidget(parent), ui(new Ui::ProjectPathsWidget), pathsModel(new ProjectPathsModel(this)) { ui->setupUi( this ); // hack taken from kurlrequester, make the buttons a bit less in height so they better match the url-requester ui->addPath->setFixedHeight( ui->projectPaths->sizeHint().height() ); ui->removePath->setFixedHeight( ui->projectPaths->sizeHint().height() ); connect( ui->addPath, &QPushButton::clicked, this, &ProjectPathsWidget::addProjectPath ); connect( ui->removePath, &QPushButton::clicked, this, &ProjectPathsWidget::deleteProjectPath ); connect( ui->batchEdit, &QPushButton::clicked, this, &ProjectPathsWidget::batchEdit ); ui->projectPaths->setModel( pathsModel ); connect( ui->projectPaths, static_cast(&KComboBox::currentIndexChanged), this, &ProjectPathsWidget::projectPathSelected ); connect( pathsModel, &ProjectPathsModel::dataChanged, this, &ProjectPathsWidget::changed ); connect( pathsModel, &ProjectPathsModel::rowsInserted, this, &ProjectPathsWidget::changed ); connect( pathsModel, &ProjectPathsModel::rowsRemoved, this, &ProjectPathsWidget::changed ); connect( ui->compiler, static_cast(&QComboBox::activated), this, &ProjectPathsWidget::changed ); connect( ui->compiler, static_cast(&QComboBox::activated), this, &ProjectPathsWidget::changeCompilerForPath ); connect( ui->includesWidget, static_cast(&IncludesWidget::includesChanged), this, &ProjectPathsWidget::includesChanged ); connect( ui->definesWidget, static_cast(&DefinesWidget::definesChanged), this, &ProjectPathsWidget::definesChanged ); connect(ui->languageParameters, &QTabWidget::currentChanged, this, &ProjectPathsWidget::tabChanged); connect(ui->parserWidget, &ParserWidget::changed, this, &ProjectPathsWidget::parserArgumentsChanged); tabChanged(IncludesPage); } +ProjectPathsWidget::~ProjectPathsWidget() +{ +} + QVector ProjectPathsWidget::paths() const { return pathsModel->paths(); } void ProjectPathsWidget::setPaths( const QVector& paths ) { bool b = blockSignals( true ); clear(); pathsModel->setPaths( paths ); blockSignals( b ); ui->projectPaths->setCurrentIndex(0); // at least a project root item is present ui->languageParameters->setCurrentIndex(0); // Set compilers ui->compiler->clear(); auto settings = SettingsManager::globalInstance(); auto compilers = settings->provider()->compilers(); for (int i = 0 ; i < compilers.count(); ++i) { Q_ASSERT(compilers[i]); if (!compilers[i]) { continue; } ui->compiler->addItem(compilers[i]->name()); QVariant val; val.setValue(compilers[i]); ui->compiler->setItemData(i, val); } projectPathSelected(0); updateEnablements(); } void ProjectPathsWidget::definesChanged( const Defines& defines ) { qCDebug(DEFINESANDINCLUDES) << "defines changed"; updatePathsModel( QVariant::fromValue(defines), ProjectPathsModel::DefinesDataRole ); } void ProjectPathsWidget::includesChanged( const QStringList& includes ) { qCDebug(DEFINESANDINCLUDES) << "includes changed"; updatePathsModel( includes, ProjectPathsModel::IncludesDataRole ); } void ProjectPathsWidget::parserArgumentsChanged() { updatePathsModel(QVariant::fromValue(ui->parserWidget->parserArguments()), ProjectPathsModel::ParserArgumentsRole); } void ProjectPathsWidget::updatePathsModel(const QVariant& newData, int role) { QModelIndex idx = pathsModel->index( ui->projectPaths->currentIndex(), 0, QModelIndex() ); if( idx.isValid() ) { bool b = pathsModel->setData( idx, newData, role ); if( b ) { emit changed(); } } } void ProjectPathsWidget::projectPathSelected( int index ) { if( index < 0 && pathsModel->rowCount() > 0 ) { index = 0; } Q_ASSERT(index >= 0); const QModelIndex midx = pathsModel->index( index, 0 ); ui->includesWidget->setIncludes( pathsModel->data( midx, ProjectPathsModel::IncludesDataRole ).toStringList() ); ui->definesWidget->setDefines( pathsModel->data( midx, ProjectPathsModel::DefinesDataRole ).value() ); Q_ASSERT(pathsModel->data(midx, ProjectPathsModel::CompilerDataRole).value()); ui->compiler->setCurrentText(pathsModel->data(midx, ProjectPathsModel::CompilerDataRole).value()->name()); ui->parserWidget->setParserArguments(pathsModel->data(midx, ProjectPathsModel::ParserArgumentsRole).value()); updateEnablements(); } void ProjectPathsWidget::clear() { bool sigDisabled = ui->projectPaths->blockSignals( true ); pathsModel->setPaths({}); ui->includesWidget->clear(); ui->definesWidget->clear(); updateEnablements(); ui->projectPaths->blockSignals( sigDisabled ); } void ProjectPathsWidget::addProjectPath() { const QUrl directory = pathsModel->data(pathsModel->index(0, 0), ProjectPathsModel::FullUrlDataRole).toUrl(); QPointer dlg = new QFileDialog(this, i18n("Select Project Path"), directory.toLocalFile()); dlg->setFileMode(QFileDialog::Directory); dlg->setOption(QFileDialog::ShowDirsOnly); if (dlg->exec()) { pathsModel->addPath(dlg->selectedUrls().value(0)); ui->projectPaths->setCurrentIndex(pathsModel->rowCount() - 1); updateEnablements(); } delete dlg; } void ProjectPathsWidget::deleteProjectPath() { const QModelIndex idx = pathsModel->index( ui->projectPaths->currentIndex(), 0 ); if( KMessageBox::questionYesNo( this, i18n("Are you sure you want to remove the configuration for the path '%1'?", pathsModel->data( idx, Qt::DisplayRole ).toString() ), QStringLiteral("Remove Path Configuration") ) == KMessageBox::Yes ) { pathsModel->removeRows( ui->projectPaths->currentIndex(), 1 ); } updateEnablements(); } void ProjectPathsWidget::setProject(KDevelop::IProject* w_project) { pathsModel->setProject( w_project ); ui->includesWidget->setProject( w_project ); } void ProjectPathsWidget::updateEnablements() { // Disable removal of the project root entry which is always first in the list ui->removePath->setEnabled( ui->projectPaths->currentIndex() > 0 ); } void ProjectPathsWidget::batchEdit() { Ui::BatchEdit be; QPointer dialog = new QDialog(this); be.setupUi(dialog); const int index = qMax(ui->projectPaths->currentIndex(), 0); const QModelIndex midx = pathsModel->index(index, 0); if (!midx.isValid()) { return; } bool includesTab = ui->languageParameters->currentIndex() == 0; if (includesTab) { auto includes = pathsModel->data(midx, ProjectPathsModel::IncludesDataRole).toStringList(); be.textEdit->setPlainText(includes.join(QLatin1Char('\n'))); dialog->setWindowTitle(i18n("Edit include directories/files")); } else { auto defines = pathsModel->data(midx, ProjectPathsModel::DefinesDataRole).value(); for (auto it = defines.constBegin(); it != defines.constEnd(); it++) { be.textEdit->appendPlainText(it.key() + QLatin1Char('=') + it.value()); } dialog->setWindowTitle(i18n("Edit defined macros")); } if (dialog->exec() != QDialog::Accepted) { delete dialog; return; } if (includesTab) { auto includes = be.textEdit->toPlainText().split(QLatin1Char('\n'), QString::SkipEmptyParts); for (auto& s : includes) { s = s.trimmed(); } pathsModel->setData(midx, includes, ProjectPathsModel::IncludesDataRole); } else { auto list = be.textEdit->toPlainText().split(QLatin1Char('\n'), QString::SkipEmptyParts); Defines defines; for (auto& d : list) { //This matches: a=b, a=, a QRegExp r(QStringLiteral("^([^=]+)(=(.*))?$")); if (!r.exactMatch(d)) { continue; } defines[r.cap(1).trimmed()] = r.cap(3).trimmed(); } pathsModel->setData(midx, QVariant::fromValue(defines), ProjectPathsModel::DefinesDataRole); } projectPathSelected(index); delete dialog; } void ProjectPathsWidget::setCurrentCompiler(const QString& name) { for (int i = 0 ; i < ui->compiler->count(); ++i) { if(ui->compiler->itemText(i) == name) { ui->compiler->setCurrentIndex(i); } } } CompilerPointer ProjectPathsWidget::currentCompiler() const { return ui->compiler->itemData(ui->compiler->currentIndex()).value(); } void ProjectPathsWidget::tabChanged(int idx) { if (idx == ParserArgumentsPage) { ui->batchEdit->setVisible(false); ui->compilerBox->setVisible(true); ui->configureLabel->setText(i18n("Configure C/C++ parser")); } else { ui->batchEdit->setVisible(true); ui->compilerBox->setVisible(false); ui->configureLabel->setText(i18n("Configure which macros and include directories/files will be added to the parser during project parsing:")); } } void ProjectPathsWidget::changeCompilerForPath() { for (int idx = 0; idx < pathsModel->rowCount(); idx++) { const QModelIndex midx = pathsModel->index(idx, 0); if (pathsModel->data(midx, Qt::DisplayRole) == ui->projectPaths->currentText()) { pathsModel->setData(midx, QVariant::fromValue(currentCompiler()), ProjectPathsModel::CompilerDataRole); break; } } } diff --git a/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.h b/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.h index c897076bca..76edd3aeb8 100644 --- a/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.h +++ b/plugins/custom-definesandincludes/kcm_widget/projectpathswidget.h @@ -1,83 +1,86 @@ /************************************************************************ * * * Copyright 2010 Andreas Pakulat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 or version 3 of the License, or * * (at your option) any later version. * * * * This program 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 * * General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, see . * ************************************************************************/ #ifndef KDEVELOP_PROJECTMANAGERS_CUSTOM_BUILDSYSTEM_PROJECTPATHSWIDGET_H #define KDEVELOP_PROJECTMANAGERS_CUSTOM_BUILDSYSTEM_PROJECTPATHSWIDGET_H +#include #include #include "../compilerprovider/icompiler.h" #include "../compilerprovider/settingsmanager.h" namespace Ui { class ProjectPathsWidget; } namespace KDevelop { class IProject; } class ProjectPathsModel; class ProjectPathsWidget : public QWidget { Q_OBJECT public: explicit ProjectPathsWidget( QWidget* parent = nullptr ); + ~ProjectPathsWidget() override; + void setProject(KDevelop::IProject* w_project); void setPaths( const QVector& ); QVector paths() const; void clear(); Q_SIGNALS: void changed(); private: void setCurrentCompiler(const QString& name); CompilerPointer currentCompiler() const; private Q_SLOTS: // Handling of project-path combobox, add and remove buttons void projectPathSelected( int index ); void addProjectPath(); void deleteProjectPath(); void batchEdit(); void tabChanged(int); void changeCompilerForPath(); // Forward includes model changes into the pathsModel void includesChanged( const QStringList& includes ); // Forward defines model changes into the pathsModel void definesChanged( const KDevelop::Defines& defines ); void parserArgumentsChanged(); private: - Ui::ProjectPathsWidget* ui; + QScopedPointer ui; ProjectPathsModel* pathsModel; // Enables/Disables widgets based on UI state/selection void updateEnablements(); void updatePathsModel( const QVariant& newData, int role ); }; #endif