mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-26 20:03:10 +00:00
373 lines
14 KiB
C++
373 lines
14 KiB
C++
/* KDevelop CMake Support
|
|
*
|
|
* Copyright 2006 Matt Rogers <mattr@kde.org>
|
|
* Copyright 2007-2008 Aleix Pol <aleixpol@gmail.com>
|
|
*
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*/
|
|
|
|
#include "cmakepreferences.h"
|
|
|
|
#include <interfaces/icore.h>
|
|
|
|
#include <kpluginfactory.h>
|
|
#include <kpluginloader.h>
|
|
#include <KUrl>
|
|
#include <KMessageBox>
|
|
#include <kio/netaccess.h>
|
|
#include <kio/deletejob.h>
|
|
#include <KDebug>
|
|
|
|
#include <QFile>
|
|
#include <QDir>
|
|
#include <QHeaderView>
|
|
|
|
#include "ui_cmakebuildsettings.h"
|
|
#include "cmakecachedelegate.h"
|
|
#include "cmakebuilddirchooser.h"
|
|
#include <cmakeutils.h>
|
|
#include <interfaces/iprojectcontroller.h>
|
|
#include <interfaces/iproject.h>
|
|
#include <project/interfaces/ibuildsystemmanager.h>
|
|
#include <project/interfaces/iprojectbuilder.h>
|
|
#include <interfaces/iruncontroller.h>
|
|
#include <KStandardDirs>
|
|
#include <util/environmentgrouplist.h>
|
|
|
|
K_PLUGIN_FACTORY(CMakePreferencesFactory, registerPlugin<CMakePreferences>(); )
|
|
K_EXPORT_PLUGIN(CMakePreferencesFactory("kcm_kdevcmake_settings"))
|
|
|
|
|
|
CMakePreferences::CMakePreferences(QWidget* parent, const QVariantList& args)
|
|
: KCModule(CMakePreferencesFactory::componentData(), parent, args), m_currentModel(0)
|
|
{
|
|
Q_ASSERT( args.count() > 3 );
|
|
|
|
QString projectName = args.at(4).toString();
|
|
m_project = KDevelop::ICore::self()->projectController()->findProjectByName( projectName );
|
|
|
|
QVBoxLayout* l = new QVBoxLayout( this );
|
|
QWidget* w = new QWidget;
|
|
m_prefsUi = new Ui::CMakeBuildSettings;
|
|
m_prefsUi->setupUi( w );
|
|
l->addWidget( w );
|
|
|
|
m_prefsUi->addBuildDir->setIcon(KIcon( "list-add" ));
|
|
m_prefsUi->removeBuildDir->setIcon(KIcon( "list-remove" ));
|
|
|
|
m_prefsUi->addBuildDir->setText(QString());
|
|
m_prefsUi->removeBuildDir->setText(QString());
|
|
m_prefsUi->cacheList->setItemDelegate(new CMakeCacheDelegate(m_prefsUi->cacheList));
|
|
m_prefsUi->cacheList->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
m_prefsUi->cacheList->horizontalHeader()->setStretchLastSection(true);
|
|
m_prefsUi->cacheList->verticalHeader()->hide();
|
|
|
|
connect(m_prefsUi->buildDirs, SIGNAL(currentIndexChanged(int)),
|
|
this, SLOT(buildDirChanged(int)));
|
|
connect(m_prefsUi->showInternal, SIGNAL(stateChanged(int)),
|
|
this, SLOT(showInternal(int)));
|
|
connect(m_prefsUi->addBuildDir, SIGNAL(pressed()), this, SLOT(createBuildDir()));
|
|
connect(m_prefsUi->removeBuildDir, SIGNAL(pressed()), this, SLOT(removeBuildDir()));
|
|
connect(m_prefsUi->showAdvanced, SIGNAL(toggled(bool)), this, SLOT(showAdvanced(bool)));
|
|
connect(m_prefsUi->environment, SIGNAL(currentProfileChanged(QString)), this, SLOT(changed()));
|
|
|
|
showInternal(m_prefsUi->showInternal->checkState());
|
|
m_subprojFolder=KUrl(args[1].toString()).upUrl();
|
|
|
|
kDebug(9042) << "Source folder: " << m_srcFolder << args[1].toString();
|
|
// foreach(const QVariant &v, args)
|
|
// {
|
|
// kDebug(9042) << "arg: " << v.toString();
|
|
// }
|
|
|
|
m_prefsUi->configureEnvironment->setSelectionWidget(m_prefsUi->environment);
|
|
|
|
m_prefsUi->showAdvanced->setChecked(false);
|
|
showAdvanced(false);
|
|
}
|
|
|
|
CMakePreferences::~CMakePreferences()
|
|
{
|
|
CMake::removeOverrideBuildDirIndex(m_project);
|
|
delete m_prefsUi;
|
|
}
|
|
|
|
void CMakePreferences::load()
|
|
{
|
|
KCModule::load();
|
|
|
|
kDebug(9042) << "********loading";
|
|
m_prefsUi->buildDirs->clear();
|
|
m_prefsUi->buildDirs->addItems( CMake::allBuildDirs(m_project) );
|
|
CMake::removeOverrideBuildDirIndex(m_project); // addItems() triggers buildDirChanged(), compensate for it
|
|
m_prefsUi->buildDirs->setCurrentIndex( CMake::currentBuildDirIndex(m_project) );
|
|
m_prefsUi->environment->setCurrentProfile( CMake::currentEnvironment(m_project) );
|
|
|
|
m_srcFolder=m_subprojFolder;
|
|
m_srcFolder.cd( CMake::projectRootRelative(m_project) );
|
|
|
|
m_prefsUi->removeBuildDir->setEnabled(m_prefsUi->buildDirs->count()!=0);
|
|
// QString cmDir=group.readEntry("CMakeDirectory");
|
|
// m_prefsUi->kcfg_cmakeDir->setUrl(KUrl(cmDir));
|
|
// kDebug(9032) << "cmakedir" << cmDir;
|
|
}
|
|
|
|
void CMakePreferences::save()
|
|
{
|
|
kDebug(9042) << "*******saving";
|
|
|
|
// the build directory list is incrementally maintained through createBuildDir() and removeBuildDir().
|
|
// We won't rewrite it here based on the data from m_prefsUi->buildDirs.
|
|
CMake::removeOverrideBuildDirIndex( m_project, true ); // save current selection
|
|
int savedBuildDir = CMake::currentBuildDirIndex(m_project);
|
|
if( savedBuildDir < 0 )
|
|
{
|
|
// no build directory exists: skip any writing to config file as well as configuring
|
|
kDebug(9042) << "doing real save from KCModule";
|
|
KCModule::save();
|
|
return;
|
|
}
|
|
|
|
bool needReconfiguring = true;
|
|
if(m_currentModel)
|
|
{
|
|
if (!m_currentModel->writeDown()) {
|
|
KMessageBox::error(this, i18n("Could not write CMake settings to file '%1'.\nCheck that you have write access to it", m_currentModel->filePath().pathOrUrl()));
|
|
needReconfiguring = false;
|
|
}
|
|
CMake::setCurrentInstallDir(m_project, m_currentModel->value("CMAKE_INSTALL_PREFIX"));
|
|
}
|
|
|
|
CMake::setCurrentEnvironment( m_project, m_prefsUi->environment->currentProfile() );
|
|
KCModule::save();
|
|
|
|
kDebug(9042) << "writing to cmake config: using builddir " << CMake::currentBuildDirIndex(m_project);
|
|
kDebug(9042) << "writing to cmake config: builddir path " << CMake::currentBuildDir(m_project);
|
|
kDebug(9042) << "writing to cmake config: installdir " << CMake::currentInstallDir(m_project);
|
|
kDebug(9042) << "writing to cmake config: build type " << CMake::currentBuildType(m_project);
|
|
kDebug(9042) << "writing to cmake config: cmake binary " << CMake::currentCMakeBinary(m_project);
|
|
kDebug(9042) << "writing to cmake config: environment " << CMake::currentEnvironment(m_project);
|
|
|
|
//We run cmake on the builddir to generate it
|
|
if (needReconfiguring) {
|
|
configure();
|
|
}
|
|
}
|
|
|
|
void CMakePreferences::defaults()
|
|
{
|
|
KCModule::defaults();
|
|
// kDebug(9032) << "*********defaults!";
|
|
}
|
|
|
|
void CMakePreferences::configureCacheView()
|
|
{
|
|
// Sets up the cache view after model re-creation/reset.
|
|
// Emits changed(false) because model re-creation probably means
|
|
// mass programmatical invocation of itemChanged(), which invokes changed(true) - which is not what we want.
|
|
m_prefsUi->cacheList->setModel(m_currentModel);
|
|
m_prefsUi->cacheList->hideColumn(1);
|
|
m_prefsUi->cacheList->hideColumn(3);
|
|
m_prefsUi->cacheList->hideColumn(4);
|
|
m_prefsUi->cacheList->horizontalHeader()->resizeSection(0, 200);
|
|
|
|
if( m_currentModel ) {
|
|
m_prefsUi->cacheList->setEnabled( true );
|
|
foreach(const QModelIndex & idx, m_currentModel->persistentIndices()) {
|
|
m_prefsUi->cacheList->openPersistentEditor(idx);
|
|
}
|
|
} else {
|
|
m_prefsUi->cacheList->setEnabled( false );
|
|
}
|
|
|
|
showInternal(m_prefsUi->showInternal->checkState());
|
|
emit changed(false);
|
|
}
|
|
|
|
void CMakePreferences::updateCache(const KUrl& newBuildDir)
|
|
{
|
|
KUrl file(newBuildDir);
|
|
file.addPath("CMakeCache.txt");
|
|
if(QFile::exists(file.toLocalFile()))
|
|
{
|
|
m_currentModel->deleteLater();
|
|
m_currentModel=new CMakeCacheModel(this, file);
|
|
configureCacheView();
|
|
connect(m_currentModel, SIGNAL(itemChanged(QStandardItem*)),
|
|
this, SLOT(cacheEdited(QStandardItem*)));
|
|
connect(m_currentModel, SIGNAL(modelReset()),
|
|
this, SLOT(configureCacheView()));
|
|
connect(m_prefsUi->cacheList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
|
this, SLOT(listSelectionChanged(QModelIndex,QModelIndex)));
|
|
}
|
|
else
|
|
{
|
|
disconnect(m_prefsUi->cacheList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, 0);
|
|
m_currentModel->deleteLater();
|
|
m_currentModel=0;
|
|
configureCacheView();
|
|
}
|
|
|
|
if( !m_currentModel )
|
|
emit changed(true);
|
|
}
|
|
|
|
void CMakePreferences::listSelectionChanged(const QModelIndex & index, const QModelIndex& )
|
|
{
|
|
kDebug(9042) << "item " << index << " selected";
|
|
QModelIndex idx = index.sibling(index.row(), 3);
|
|
QModelIndex idxType = index.sibling(index.row(), 1);
|
|
QString comment=QString("%1. %2")
|
|
.arg(m_currentModel->itemFromIndex(idxType)->text())
|
|
.arg(m_currentModel->itemFromIndex(idx)->text());
|
|
m_prefsUi->commentText->setText(comment);
|
|
}
|
|
|
|
void CMakePreferences::showInternal(int state)
|
|
{
|
|
if(!m_currentModel)
|
|
return;
|
|
|
|
bool showAdv=(state == Qt::Checked);
|
|
for(int i=0; i<m_currentModel->rowCount(); i++)
|
|
{
|
|
bool hidden=m_currentModel->isInternal(i) || (!showAdv && m_currentModel->isAdvanced(i));
|
|
m_prefsUi->cacheList->setRowHidden(i, hidden);
|
|
}
|
|
}
|
|
|
|
void CMakePreferences::buildDirChanged(int index)
|
|
{
|
|
CMake::setOverrideBuildDirIndex( m_project, index );
|
|
KUrl str = CMake::currentBuildDir(m_project);
|
|
m_prefsUi->environment->setCurrentProfile( CMake::currentEnvironment( m_project ) );
|
|
updateCache(str);
|
|
kDebug(9042) << "builddir Changed" << str;
|
|
emit changed(true);
|
|
}
|
|
|
|
void CMakePreferences::cacheUpdated()
|
|
{
|
|
KUrl str = CMake::currentBuildDir(m_project);
|
|
updateCache(str);
|
|
kDebug(9042) << "cache updated for" << str;
|
|
}
|
|
|
|
void CMakePreferences::createBuildDir()
|
|
{
|
|
CMakeBuildDirChooser bdCreator;
|
|
bdCreator.setSourceFolder( m_srcFolder );
|
|
|
|
// NOTE: (on removing the trailing slashes)
|
|
// Generally, we have no clue about how shall a trailing slash look in the current system.
|
|
// Moreover, the slash may be a part of the filename.
|
|
// It may be '/' or '\', so maybe should we rely on CMake::allBuildDirs() for returning well-formed pathes?
|
|
QStringList used = CMake::allBuildDirs( m_project );
|
|
bdCreator.setAlreadyUsed(used);
|
|
bdCreator.setCMakeBinary(KStandardDirs::findExe("cmake"));
|
|
|
|
if(bdCreator.exec())
|
|
{
|
|
QString newbuilddir = bdCreator.buildFolder().toLocalFile(KUrl::RemoveTrailingSlash);
|
|
m_prefsUi->buildDirs->addItem(newbuilddir);
|
|
|
|
int buildDirCount = m_prefsUi->buildDirs->count();
|
|
int addedBuildDirIndex = buildDirCount - 1;
|
|
m_prefsUi->buildDirs->setCurrentIndex(addedBuildDirIndex);
|
|
m_prefsUi->removeBuildDir->setEnabled(true);
|
|
|
|
// Initialize the kconfig items with the values from the dialog, this ensures the settings
|
|
// end up in the config file once the changes are saved
|
|
kDebug(9042) << "adding to cmake config: new builddir index" << addedBuildDirIndex;
|
|
kDebug(9042) << "adding to cmake config: builddir path " << bdCreator.buildFolder().url();
|
|
kDebug(9042) << "adding to cmake config: installdir " << bdCreator.installPrefix().url();
|
|
kDebug(9042) << "adding to cmake config: extra args" << bdCreator.extraArguments();
|
|
kDebug(9042) << "adding to cmake config: build type " << bdCreator.buildType();
|
|
kDebug(9042) << "adding to cmake config: cmake binary " << bdCreator.cmakeBinary().url();
|
|
kDebug(9042) << "adding to cmake config: environment empty";
|
|
CMake::setBuildDirCount( m_project, buildDirCount );
|
|
CMake::setCurrentBuildDir( m_project, bdCreator.buildFolder() );
|
|
CMake::setCurrentInstallDir( m_project, bdCreator.installPrefix() );
|
|
CMake::setCurrentExtraArguments( m_project, bdCreator.extraArguments() );
|
|
CMake::setCurrentBuildType( m_project, bdCreator.buildType() );
|
|
CMake::setCurrentCMakeBinary( m_project, bdCreator.cmakeBinary() );
|
|
CMake::setCurrentEnvironment( m_project, QString() );
|
|
|
|
kDebug(9042) << "Emitting changed signal for cmake kcm";
|
|
emit changed(true);
|
|
}
|
|
//TODO: Save it for next runs
|
|
}
|
|
|
|
void CMakePreferences::removeBuildDir()
|
|
{
|
|
int curr=m_prefsUi->buildDirs->currentIndex();
|
|
if(curr < 0)
|
|
return;
|
|
|
|
KUrl removedUrl = CMake::currentBuildDir( m_project );
|
|
QString removed = removedUrl.toLocalFile();
|
|
if(QDir(removed).exists())
|
|
{
|
|
int ret=KMessageBox::warningYesNo(this,
|
|
i18n("The %1 directory is about to be removed in KDevelop's list.\n"
|
|
"Do you want KDevelop to remove it in the file system as well?", removed));
|
|
if(ret==KMessageBox::Yes)
|
|
{
|
|
bool correct=KIO::NetAccess::del(removedUrl, this);
|
|
if(!correct)
|
|
KMessageBox::error(this, i18n("Could not remove: %1.\n", removed));
|
|
}
|
|
}
|
|
|
|
kDebug(9042) << "removing from cmake config: using builddir " << curr;
|
|
kDebug(9042) << "removing from cmake config: builddir path " << removedUrl;
|
|
kDebug(9042) << "removing from cmake config: installdir " << CMake::currentInstallDir( m_project );
|
|
kDebug(9042) << "removing from cmake config: extra args" << CMake::currentExtraArguments( m_project );
|
|
kDebug(9042) << "removing from cmake config: buildtype " << CMake::currentBuildType( m_project );
|
|
kDebug(9042) << "removing from cmake config: cmake binary " << CMake::currentCMakeBinary( m_project );
|
|
kDebug(9042) << "removing from cmake config: environment " << CMake::currentEnvironment( m_project );
|
|
|
|
CMake::removeBuildDirConfig(m_project);
|
|
m_prefsUi->buildDirs->removeItem( curr ); // this triggers buildDirChanged()
|
|
if(m_prefsUi->buildDirs->count()==0)
|
|
m_prefsUi->removeBuildDir->setEnabled(false);
|
|
|
|
emit changed(true);
|
|
}
|
|
|
|
void CMakePreferences::configure()
|
|
{
|
|
KDevelop::IProjectBuilder *b=m_project->buildSystemManager()->builder();
|
|
KJob* job=b->configure(m_project);
|
|
if( m_currentModel ) {
|
|
connect(job, SIGNAL(finished(KJob*)), m_currentModel, SLOT(reset()));
|
|
} else {
|
|
connect(job, SIGNAL(finished(KJob*)), SLOT(cacheUpdated()));
|
|
}
|
|
|
|
connect(job, SIGNAL(finished(KJob*)), m_project, SLOT(reloadModel()));
|
|
KDevelop::ICore::self()->runController()->registerJob(job);
|
|
}
|
|
|
|
void CMakePreferences::showAdvanced(bool v)
|
|
{
|
|
kDebug(9042) << "toggle pressed: " << v;
|
|
m_prefsUi->advancedBox->setHidden(!v);
|
|
}
|
|
|
|
|
|
#include "moc_cmakepreferences.cpp"
|