Commit 0728e78a authored by Thorbjørn Lindeijer's avatar Thorbjørn Lindeijer

Reintroduced a way to edit project dependencies

Dependencies between projects can now be edited in the Projects mode.
You can simply check for each project the projects that it depends on,
and they will be built first. A message box pops up when you try to
create a circular dependency.

Could use some testing.
parent d78d5f56
......@@ -563,7 +563,7 @@ TextEditor::ITextEditor *BookmarkManager::currentTextEditor() const
}
/* Returns the current session. */
SessionManager* BookmarkManager::sessionManager() const
SessionManager *BookmarkManager::sessionManager() const
{
ExtensionSystem::PluginManager *pm = m_core->pluginManager();
ProjectExplorerPlugin *pe = pm->getObject<ProjectExplorerPlugin>();
......
......@@ -215,11 +215,6 @@ ProjectExplorer::IProjectManager *CMakeProject::projectManager() const
return m_manager;
}
QList<Core::IFile *> CMakeProject::dependencies()
{
return QList<Core::IFile *>();
}
QList<ProjectExplorer::Project *> CMakeProject::dependsOn()
{
return QList<Project *>();
......
......@@ -73,7 +73,6 @@ public:
virtual Core::IFile *file() const;
virtual ProjectExplorer::IProjectManager *projectManager() const;
virtual QList<Core::IFile *> dependencies(); //NBS TODO remove
virtual QList<ProjectExplorer::Project *> dependsOn(); //NBS TODO implement dependsOn
virtual bool isApplication() const;
......
......@@ -66,7 +66,7 @@ class PROJECTEXPLORER_EXPORT IBuildParserFactory
Q_OBJECT
public:
IBuildParserFactory() {};
IBuildParserFactory() {}
virtual ~IBuildParserFactory();
virtual bool canCreate(const QString & name) const = 0;
virtual BuildParserInterface * create(const QString & name) const = 0;
......
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "dependenciesdialog.h"
#include "project.h"
#include "session.h"
#include <QtCore/QVector>
#include <QtCore/QDebug>
#include <QtCore/QAbstractTableModel>
#include <QtGui/QPushButton>
#include <QtGui/QHeaderView>
namespace ProjectExplorer {
namespace Internal {
// ------ DependencyModel
class DependencyModel : public QAbstractTableModel {
public:
typedef ProjectExplorer::Project Project;
typedef DependenciesDialog::ProjectList ProjectList;
DependencyModel(SessionManager *sln, const ProjectList &projectList, QObject * parent = 0);
virtual int rowCount(const QModelIndex&) const { return m_projects.size(); }
virtual int columnCount(const QModelIndex&) const { return m_projects.size(); }
virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
virtual Qt::ItemFlags flags ( const QModelIndex & index ) const;
QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
// Apply changed items
unsigned apply(SessionManager *sln) const;
void resetDependencies();
private:
struct Entry {
Entry(SessionManager *sln, Project *rootProject, Project *dependentProject);
Entry() : m_dependentProject(0), m_dependent(false), m_defaultValue(false), m_canAddDependency(false) {}
Project* m_dependentProject;
bool m_dependent;
bool m_defaultValue;
bool m_canAddDependency;
};
// column
typedef QVector<Entry> ProjectDependencies;
typedef QList<ProjectDependencies> Projects;
Projects m_projects;
ProjectList m_projectList;
};
DependencyModel::Entry::Entry(SessionManager *sln,
Project *rootProject,
Project *dependentProject) :
m_dependentProject(dependentProject),
m_dependent(sln->hasDependency(rootProject, dependentProject)),
m_defaultValue(m_dependent),
m_canAddDependency(sln->canAddDependency(rootProject, dependentProject))
{
}
DependencyModel::DependencyModel(SessionManager *sln,
const ProjectList &projectList,
QObject * parent) :
QAbstractTableModel(parent),
m_projectList(projectList)
{
const int count = projectList.size();
for (int p = 0; p < count; p++) {
Project *rootProject = projectList.at(p);
ProjectDependencies dependencies;
dependencies.reserve(count);
for (int d = 0; d < count ; d++)
dependencies.push_back(p == d ? Entry() : Entry(sln, rootProject, projectList.at(d)));
m_projects += dependencies;
}
}
QVariant DependencyModel::data ( const QModelIndex & index, int role ) const
{
static const QVariant empty = QVariant(QString());
// TO DO: find a checked icon
static const QVariant checked = QVariant(QString(QLatin1Char('x')));
const int p = index.column();
const int d = index.row();
switch (role) {
case Qt::EditRole:
return QVariant(m_projects[p][d].m_dependent);
case Qt::DisplayRole:
return m_projects[p][d].m_dependent ? checked : empty;
default:
break;
}
return QVariant();
}
bool DependencyModel::setData ( const QModelIndex & index, const QVariant & value, int role)
{
switch (role) {
case Qt::EditRole: {
const int p = index.column();
const int d = index.row();
if (d == p)
return false;
Entry &e(m_projects[p][d]);
e.m_dependent = value.toBool();
emit dataChanged(index, index);
}
return true;
default:
break;
}
return false;
}
Qt::ItemFlags DependencyModel::flags ( const QModelIndex & index ) const
{
const int p = index.column();
const int d = index.row();
if (d == p)
return 0;
const Entry &e(m_projects[p][d]);
Qt::ItemFlags rc = Qt::ItemIsEnabled|Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
if (e.m_canAddDependency)
rc |= Qt::ItemIsEditable;
return rc;
}
QVariant DependencyModel::headerData ( int section, Qt::Orientation , int role ) const
{
switch (role) {
case Qt::DisplayRole:
return QVariant(m_projectList.at(section)->name());
default:
break;
}
return QVariant();
}
void DependencyModel::resetDependencies()
{
if (const int count = m_projectList.size()) {
for (int p = 0; p < count; p++)
for (int d = 0; d < count; d++)
m_projects[p][d].m_dependent = false;
reset();
}
}
unsigned DependencyModel::apply(SessionManager *sln) const
{
unsigned rc = 0;
const int count = m_projectList.size();
for (int p = 0; p < count; p++) {
Project *rootProject = m_projectList.at(p);
for (int d = 0; d < count; d++) {
if (d != p) {
const Entry &e(m_projects[p][d]);
if (e.m_dependent != e. m_defaultValue) {
rc++;
if (e.m_dependent) {
sln->addDependency(rootProject, e.m_dependentProject);
} else {
sln->removeDependency(rootProject, e.m_dependentProject);
}
}
}
}
}
return rc;
}
// ------ DependenciesDialog
DependenciesDialog::DependenciesDialog(QWidget *parent, SessionManager *sln) :
QDialog(parent),
m_sln(sln),
m_projectList(m_sln->projects()),
m_model(new DependencyModel(sln, m_projectList))
{
m_ui.setupUi(this);
m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
QPushButton *resetButton = m_ui.buttonBox->addButton (QDialogButtonBox::Reset);
connect(resetButton, SIGNAL(clicked()), this, SLOT(reset()));
m_ui.dependencyTable->setModel(m_model);
}
void DependenciesDialog::accept()
{
m_model->apply(m_sln);
QDialog::accept();
}
void DependenciesDialog::reset()
{
m_model->resetDependencies();
}
DependenciesDialog::~DependenciesDialog()
{
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProjectExplorer::Internal::DependenciesDialog</class>
<widget class="QDialog" name="ProjectExplorer::Internal::DependenciesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>492</width>
<height>435</height>
</rect>
</property>
<property name="windowTitle">
<string>Project Dependencies</string>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QTableView" name="dependencyTable">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ProjectExplorer::Internal::DependenciesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>142</x>
<y>285</y>
</hint>
<hint type="destinationlabel">
<x>142</x>
<y>155</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ProjectExplorer::Internal::DependenciesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>142</x>
<y>285</y>
</hint>
<hint type="destinationlabel">
<x>142</x>
<y>155</y>
</hint>
</hints>
</connection>
</connections>
</ui>
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "dependenciespanel.h"
#include "project.h"
#include "session.h"
#include <coreplugin/fileiconprovider.h>
#include <QtCore/QVector>
#include <QtCore/QDebug>
#include <QtCore/QAbstractListModel>
#include <QtGui/QHeaderView>
#include <QtGui/QMessageBox>
#include <QtGui/QPushButton>
namespace ProjectExplorer {
namespace Internal {
///
/// DependenciesModel
///
class DependenciesModel : public QAbstractListModel
{
public:
DependenciesModel(SessionManager *session, Project *project, QObject *parent = 0);
int rowCount(const QModelIndex &index) const;
int columnCount(const QModelIndex &index) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
Qt::ItemFlags flags(const QModelIndex &index) const;
private:
SessionManager *m_session;
Project *m_project;
QList<Project *> m_projects;
};
DependenciesModel::DependenciesModel(SessionManager *session,
Project *project,
QObject *parent)
: QAbstractListModel(parent)
, m_session(session)
, m_project(project)
, m_projects(session->projects())
{
// We can't select ourselves as a dependency
m_projects.removeAll(m_project);
}
int DependenciesModel::rowCount(const QModelIndex &index) const
{
return index.isValid() ? 0 : m_projects.size();
}
int DependenciesModel::columnCount(const QModelIndex &index) const
{
return index.isValid() ? 0 : 1;
}
QVariant DependenciesModel::data(const QModelIndex &index, int role) const
{
const Project *p = m_projects.at(index.row());
switch (role) {
case Qt::DisplayRole:
return p->name();
case Qt::CheckStateRole:
return m_session->hasDependency(m_project, p) ? Qt::Checked : Qt::Unchecked;
case Qt::DecorationRole:
return Core::FileIconProvider::instance()->icon(QFileInfo(p->file()->fileName()));
default:
return QVariant();
}
}
bool DependenciesModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
qDebug() << index << value << role << value.toBool();
if (role == Qt::CheckStateRole) {
const Project *p = m_projects.at(index.row());
const Qt::CheckState c = static_cast<Qt::CheckState>(value.toInt());
if (c == Qt::Checked) {
if (m_session->addDependency(m_project, p)) {
emit dataChanged(index, index);
return true;
} else {
QMessageBox::warning(0, tr("Unable to add dependency"),
tr("This would create a circular dependency."));
}
} else if (c == Qt::Unchecked) {
if (m_session->hasDependency(m_project, p)) {
m_session->removeDependency(m_project, p);
emit dataChanged(index, index);
return true;
}
}
}
return false;
}
Qt::ItemFlags DependenciesModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags rc = QAbstractListModel::flags(index);
if (index.column() == 0)
rc |= Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
return rc;
}
///
/// DependenciesWidget
///
class DependenciesWidget : public QWidget
{
public:
DependenciesWidget(SessionManager *session, Project *project,
QWidget *parent = 0);
private:
Ui::DependenciesWidget m_ui;
SessionManager *m_session;
DependenciesModel *m_model;
};
DependenciesWidget::DependenciesWidget(SessionManager *session,
Project *project,
QWidget *parent)
: QWidget(parent)
, m_session(session)
, m_model(new DependenciesModel(session, project, this))
{
m_ui.setupUi(this);
m_ui.dependenciesView->setModel(m_model);
m_ui.dependenciesView->setHeaderHidden(true);
}
///
/// DependenciesPanel
///
DependenciesPanel::DependenciesPanel(SessionManager *session, Project *project)
: PropertiesPanel()
, m_widget(new DependenciesWidget(session, project))
{
}
DependenciesPanel::~DependenciesPanel()
{
delete m_widget;
}
QString DependenciesPanel::name() const
{
return tr("Dependencies");
}
QWidget *DependenciesPanel::widget()
{
return m_widget;
}
///
/// DependenciesPanelFactory
///
DependenciesPanelFactory::DependenciesPanelFactory(SessionManager *session)
: m_session(session)
{
}
bool DependenciesPanelFactory::supports(Project * /* project */)
{
return true;
}
PropertiesPanel *DependenciesPanelFactory::createPanel(Project *project)
{
return new DependenciesPanel(m_session, project);
}
} // namespace Internal
} // namespace ProjectExplorer
......@@ -34,9 +34,10 @@
#ifndef DEPENDENCIESDIALOG_H
#define DEPENDENCIESDIALOG_H