mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 19:02:53 +00:00
1019 lines
36 KiB
C++
1019 lines
36 KiB
C++
/* This file is part of KDevelop
|
|
Copyright 2009 Andreas Pakulat <apaku@gmx.de>
|
|
|
|
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 "launchconfigurationdialog.h"
|
|
#include <QtGui/QSplitter>
|
|
#include <QtGui/QTreeView>
|
|
#include <QtGui/QStackedWidget>
|
|
#include <QtGui/QGridLayout>
|
|
#include <QtGui/QToolButton>
|
|
|
|
#include <klocale.h>
|
|
#include <klineedit.h>
|
|
#include <kcombobox.h>
|
|
#include <kdebug.h>
|
|
#include <kpushbutton.h>
|
|
#include <ktabwidget.h>
|
|
#include <kmessagebox.h>
|
|
|
|
#include <interfaces/launchconfigurationpage.h>
|
|
#include <interfaces/iproject.h>
|
|
#include <interfaces/iprojectcontroller.h>
|
|
#include <interfaces/isession.h>
|
|
|
|
#include "core.h"
|
|
#include "runcontroller.h"
|
|
#include "launchconfiguration.h"
|
|
|
|
#include <interfaces/ilauncher.h>
|
|
#include <interfaces/ilaunchmode.h>
|
|
#include <interfaces/launchconfigurationtype.h>
|
|
#include <QLayout>
|
|
#include <QMenu>
|
|
#include <QLabel>
|
|
|
|
namespace KDevelop
|
|
{
|
|
|
|
bool launchConfigGreaterThan(KDevelop::LaunchConfigurationType* a, KDevelop::LaunchConfigurationType* b)
|
|
{
|
|
return a->name()>b->name();
|
|
}
|
|
|
|
//TODO: Maybe use KPageDialog instead, might make the model stuff easier and the default-size stuff as well
|
|
LaunchConfigurationDialog::LaunchConfigurationDialog(QWidget* parent): KDialog(parent), currentPageChanged( false )
|
|
{
|
|
setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Apply );
|
|
setButtonFocus( KDialog::Ok );
|
|
setWindowTitle( i18n( "Launch Configurations" ) );
|
|
button( KDialog::Apply )->setEnabled( false );
|
|
|
|
setupUi( mainWidget() );
|
|
mainWidget()->layout()->setContentsMargins( 0, 0, 0, 0 );
|
|
splitter->setSizes(QList<int>() << 260 << 620);
|
|
|
|
addConfig->setIcon( KIcon("list-add") );
|
|
addConfig->setEnabled( false );
|
|
addConfig->setToolTip(i18nc("@info:tooltip", "Add a new launch configuration."));
|
|
deleteConfig->setIcon( KIcon("list-remove") );
|
|
deleteConfig->setEnabled( false );
|
|
deleteConfig->setToolTip(i18nc("@info:tooltip", "Delete selected launch configuration."));
|
|
|
|
model = new LaunchConfigurationsModel( tree );
|
|
tree->setModel( model );
|
|
tree->setExpandsOnDoubleClick( true );
|
|
tree->setSelectionBehavior( QAbstractItemView::SelectRows );
|
|
tree->setSelectionMode( QAbstractItemView::SingleSelection );
|
|
tree->setUniformRowHeights( true );
|
|
tree->setItemDelegate( new LaunchConfigurationModelDelegate() );
|
|
tree->setColumnHidden(1, true);
|
|
for(int row=0; row<model->rowCount(); row++) {
|
|
tree->setExpanded(model->index(row, 0), true);
|
|
}
|
|
|
|
tree->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect( tree, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(doTreeContextMenu(QPoint)) );
|
|
connect( deleteConfig, SIGNAL(clicked()), this, SLOT(deleteConfiguration()));
|
|
connect( model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(modelChanged(QModelIndex,QModelIndex)) );
|
|
connect( tree->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged(QItemSelection,QItemSelection)));
|
|
QModelIndex idx = model->indexForConfig( Core::self()->runControllerInternal()->defaultLaunch() );
|
|
kDebug() << "selecting index:" << idx;
|
|
if( !idx.isValid() )
|
|
{
|
|
for( int i = 0; i < model->rowCount(); i++ )
|
|
{
|
|
if( model->rowCount( model->index( i, 0, QModelIndex() ) ) > 0 )
|
|
{
|
|
idx = model->index( 1, 0, model->index( i, 0, QModelIndex() ) );
|
|
break;
|
|
}
|
|
}
|
|
if( !idx.isValid() )
|
|
{
|
|
idx = model->index( 0, 0, QModelIndex() );
|
|
}
|
|
}
|
|
tree->selectionModel()->select( QItemSelection( idx, idx ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
|
|
tree->selectionModel()->setCurrentIndex( idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
|
|
|
|
// Unfortunately tree->resizeColumnToContents() only looks at the top-level
|
|
// items, instead of all open ones. Hence we're calculating it ourselves like
|
|
// this:
|
|
// Take the selected index, check if it has childs, if so take the first child
|
|
// Then count the level by going up, then let the tree calculate the width
|
|
// for the selected or its first child index and add indentation*level
|
|
//
|
|
// If Qt Software ever fixes resizeColumnToContents, the following line
|
|
// can be enabled and the rest be removed
|
|
// tree->resizeColumnToContents( 0 );
|
|
int level = 0;
|
|
QModelIndex widthidx = idx;
|
|
if( model->rowCount( idx ) > 0 )
|
|
{
|
|
widthidx = idx.child( 0, 0 );
|
|
}
|
|
QModelIndex parentidx = widthidx.parent();
|
|
while( parentidx.isValid() )
|
|
{
|
|
level++;
|
|
parentidx = parentidx.parent();
|
|
}
|
|
// make sure the base column width is honored, e.g. when no launch configs exist
|
|
tree->resizeColumnToContents(0);
|
|
int width = tree->columnWidth( 0 );
|
|
while ( widthidx.isValid() )
|
|
{
|
|
width = qMax( width, level*tree->indentation() + tree->indentation() + tree->sizeHintForIndex( widthidx ).width() );
|
|
widthidx = widthidx.parent();
|
|
}
|
|
tree->setColumnWidth( 0, width );
|
|
|
|
QMenu* m = new QMenu(this);
|
|
QList<LaunchConfigurationType*> types = Core::self()->runController()->launchConfigurationTypes();
|
|
qSort(types.begin(), types.end(), launchConfigGreaterThan); //we want it in reverse order
|
|
foreach(LaunchConfigurationType* type, types)
|
|
{
|
|
connect(type, SIGNAL(signalAddLaunchConfiguration(KDevelop::ILaunchConfiguration*)), SLOT(addConfiguration(KDevelop::ILaunchConfiguration*)));
|
|
QMenu* suggestionsMenu = type->launcherSuggestions();
|
|
|
|
if(suggestionsMenu) {
|
|
m->addMenu(suggestionsMenu);
|
|
}
|
|
}
|
|
// Simplify menu structure to get rid of 1-entry levels
|
|
while (m->actions().count() == 1) {
|
|
QMenu* subMenu = m->actions().first()->menu();
|
|
if (subMenu && subMenu->isEnabled() && subMenu->actions().count()<5) {
|
|
m = subMenu;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if(!m->isEmpty()) {
|
|
QAction* separator = new QAction(m);
|
|
separator->setSeparator(true);
|
|
m->insertAction(m->actions().first(), separator);
|
|
}
|
|
|
|
foreach(LaunchConfigurationType* type, types) {
|
|
QAction* action = new QAction(type->icon(), type->name(), m);
|
|
action->setProperty("configtype", qVariantFromValue<QObject*>(type));
|
|
connect(action, SIGNAL(triggered(bool)), SLOT(createEmptyLauncher()));
|
|
|
|
if(!m->actions().isEmpty())
|
|
m->insertAction(m->actions().first(), action);
|
|
else
|
|
m->addAction(action);
|
|
}
|
|
addConfig->setMenu(m);
|
|
|
|
connect(debugger, SIGNAL(currentIndexChanged(int)), SLOT(launchModeChanged(int)));
|
|
|
|
connect( this, SIGNAL(okClicked()), SLOT(saveConfig()) );
|
|
connect( this, SIGNAL(applyClicked()), SLOT(saveConfig()) );
|
|
|
|
setInitialSize( QSize(qMax(700, sizeHint().width()), qMax(500, sizeHint().height())) );
|
|
}
|
|
|
|
void LaunchConfigurationDialog::doTreeContextMenu(QPoint point)
|
|
{
|
|
if ( ! tree->selectionModel()->selectedRows().isEmpty() ) {
|
|
QModelIndex selected = tree->selectionModel()->selectedRows().first();
|
|
if ( selected.parent().isValid() && ! selected.parent().parent().isValid() ) {
|
|
// only display the menu if a launch config is clicked
|
|
QMenu menu;
|
|
QAction* rename = new QAction(KIcon("edit-rename"), i18n("Rename configuration"), &menu);
|
|
QAction* delete_ = new QAction(KIcon("edit-delete"), i18n("Delete configuration"), &menu);
|
|
connect(rename, SIGNAL(triggered(bool)), this, SLOT(renameSelected()));
|
|
connect(delete_, SIGNAL(triggered(bool)), this, SLOT(deleteConfiguration()));
|
|
menu.addAction(rename);
|
|
menu.addAction(delete_);
|
|
menu.exec(tree->mapToGlobal(point));
|
|
}
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationDialog::renameSelected()
|
|
{
|
|
if( !tree->selectionModel()->selectedRows().isEmpty() )
|
|
{
|
|
QModelIndex parent = tree->selectionModel()->selectedRows().first();
|
|
if( parent.parent().isValid() )
|
|
{
|
|
parent = parent.parent();
|
|
}
|
|
QModelIndex index = model->index(tree->selectionModel()->selectedRows().first().row(), 0, parent);
|
|
tree->edit( index );
|
|
}
|
|
}
|
|
|
|
QSize LaunchConfigurationDialog::sizeHint() const
|
|
{
|
|
QSize s = KDialog::sizeHint();
|
|
return s.expandedTo(QSize(880, 520));
|
|
}
|
|
|
|
void LaunchConfigurationDialog::createEmptyLauncher()
|
|
{
|
|
QAction* action = qobject_cast<QAction*>(sender());
|
|
Q_ASSERT(action);
|
|
|
|
LaunchConfigurationType* type = qobject_cast<LaunchConfigurationType*>(action->property("configtype").value<QObject*>());
|
|
Q_ASSERT(type);
|
|
|
|
IProject* p = model->projectForIndex(tree->currentIndex());
|
|
QPair< QString, QString > launcher( type->launchers().at( 0 )->supportedModes().at(0), type->launchers().at( 0 )->id() );
|
|
ILaunchConfiguration* l = ICore::self()->runController()->createLaunchConfiguration(type, launcher, p);
|
|
addConfiguration(l);
|
|
}
|
|
|
|
void LaunchConfigurationDialog::selectionChanged(QItemSelection selected, QItemSelection deselected )
|
|
{
|
|
if( !deselected.indexes().isEmpty() )
|
|
{
|
|
LaunchConfiguration* l = model->configForIndex( deselected.indexes().first() );
|
|
if( l )
|
|
{
|
|
disconnect(l, SIGNAL(nameChanged(LaunchConfiguration*)), this, SLOT(updateNameLabel(LaunchConfiguration*)));
|
|
if( currentPageChanged )
|
|
{
|
|
if( KMessageBox::questionYesNo( this, i18n("Selected Launch Configuration has unsaved changes. Do you want to save it?"), i18n("Unsaved Changes") ) == KMessageBox::Yes )
|
|
{
|
|
saveConfig( deselected.indexes().first() );
|
|
} else {
|
|
LaunchConfigPagesContainer* tab = qobject_cast<LaunchConfigPagesContainer*>( stack->currentWidget() );
|
|
tab->setLaunchConfiguration( l );
|
|
button( KDialog::Apply )->setEnabled( false );
|
|
currentPageChanged = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
updateNameLabel(0);
|
|
|
|
for( int i = 1; i < stack->count(); i++ )
|
|
{
|
|
QWidget* w = stack->widget(i);
|
|
stack->removeWidget(w);
|
|
delete w;
|
|
}
|
|
|
|
debugger->clear();
|
|
if( !selected.indexes().isEmpty() )
|
|
{
|
|
QModelIndex idx = selected.indexes().first();
|
|
LaunchConfiguration* l = model->configForIndex( idx );
|
|
ILaunchMode* lm = model->modeForIndex( idx );
|
|
|
|
if( l )
|
|
{
|
|
updateNameLabel( l );
|
|
tree->expand( model->indexForConfig( l ) );
|
|
connect( l, SIGNAL(nameChanged(LaunchConfiguration*)), SLOT(updateNameLabel(LaunchConfiguration*)) );
|
|
if( lm )
|
|
{
|
|
bool b = debugger->blockSignals(true);
|
|
QList<ILauncher*> launchers = l->type()->launchers();
|
|
for( QList<ILauncher*>::const_iterator it = launchers.constBegin(); it != launchers.constEnd(); it++ )
|
|
{
|
|
if( ((*it)->supportedModes().contains( lm->id() ) ) ) {
|
|
debugger->addItem( (*it)->name(), (*it)->id() );
|
|
}
|
|
}
|
|
debugger->blockSignals(b);
|
|
|
|
debugger->setVisible(debugger->count()>0);
|
|
debugLabel->setVisible(debugger->count()>0);
|
|
|
|
QVariant currentLaunchMode = idx.sibling(idx.row(), 1).data(Qt::EditRole);
|
|
debugger->setCurrentIndex(debugger->findData(currentLaunchMode));
|
|
|
|
ILauncher* launcher = l->type()->launcherForId( currentLaunchMode.toString() );
|
|
if( launcher )
|
|
{
|
|
LaunchConfigPagesContainer* tab = launcherWidgets.value( launcher );
|
|
if(!tab)
|
|
{
|
|
QList<KDevelop::LaunchConfigurationPageFactory*> pages = launcher->configPages();
|
|
if(!pages.isEmpty()) {
|
|
tab = new LaunchConfigPagesContainer( launcher->configPages(), stack );
|
|
connect( tab, SIGNAL(changed()), SLOT(pageChanged()) );
|
|
stack->addWidget( tab );
|
|
}
|
|
}
|
|
|
|
if(tab) {
|
|
tab->setLaunchConfiguration( l );
|
|
stack->setCurrentWidget( tab );
|
|
} else {
|
|
QLabel* label = new QLabel(i18nc("%1 is a launcher name",
|
|
"No configuration is needed for '%1'",
|
|
launcher->name()), stack);
|
|
label->setAlignment(Qt::AlignCenter);
|
|
QFont font = label->font();
|
|
font.setItalic(true);
|
|
label->setFont(font);
|
|
stack->addWidget(label);
|
|
stack->setCurrentWidget(label);
|
|
}
|
|
|
|
updateNameLabel( l );
|
|
addConfig->setEnabled( false );
|
|
deleteConfig->setEnabled( false );
|
|
} else
|
|
{
|
|
addConfig->setEnabled( false );
|
|
deleteConfig->setEnabled( false );
|
|
stack->setCurrentIndex( 0 );
|
|
}
|
|
} else
|
|
{
|
|
//TODO: enable removal button
|
|
LaunchConfigurationType* type = l->type();
|
|
LaunchConfigPagesContainer* tab = typeWidgets.value( type );
|
|
if( !tab )
|
|
{
|
|
tab = new LaunchConfigPagesContainer( type->configPages(), stack );
|
|
connect( tab, SIGNAL(changed()), SLOT(pageChanged()) );
|
|
stack->addWidget( tab );
|
|
}
|
|
kDebug() << "created pages, setting config up";
|
|
tab->setLaunchConfiguration( l );
|
|
stack->setCurrentWidget( tab );
|
|
|
|
addConfig->setEnabled( true );
|
|
deleteConfig->setEnabled( true );
|
|
debugger->setVisible( false );
|
|
debugLabel->setVisible( false );
|
|
}
|
|
} else
|
|
{
|
|
addConfig->setEnabled( true );
|
|
deleteConfig->setEnabled( false );
|
|
stack->setCurrentIndex( 0 );
|
|
QLabel* l = new QLabel(i18n("<i>Select a configuration to edit from the left,<br>"
|
|
"or click the \"Add New\" button to add a new one.</i>"), stack);
|
|
l->setAlignment(Qt::AlignCenter);
|
|
stack->addWidget(l);
|
|
stack->setCurrentWidget(l);
|
|
debugger->setVisible( false );
|
|
debugLabel->setVisible( false );
|
|
}
|
|
} else
|
|
{
|
|
debugger->setVisible( false );
|
|
debugLabel->setVisible( false );
|
|
addConfig->setEnabled( false );
|
|
deleteConfig->setEnabled( false );
|
|
stack->setCurrentIndex( 0 );
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationDialog::saveConfig( const QModelIndex& idx )
|
|
{
|
|
Q_UNUSED( idx );
|
|
LaunchConfigPagesContainer* tab = qobject_cast<LaunchConfigPagesContainer*>( stack->currentWidget() );
|
|
if( tab )
|
|
{
|
|
tab->save();
|
|
button( KDialog::Apply )->setEnabled( false );
|
|
currentPageChanged = false;
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationDialog::saveConfig()
|
|
{
|
|
if( !tree->selectionModel()->selectedRows().isEmpty() )
|
|
{
|
|
saveConfig( tree->selectionModel()->selectedRows().first() );
|
|
}
|
|
}
|
|
|
|
|
|
void LaunchConfigurationDialog::pageChanged()
|
|
{
|
|
currentPageChanged = true;
|
|
button( KDialog::Apply )->setEnabled( true );
|
|
}
|
|
|
|
void LaunchConfigurationDialog::modelChanged(QModelIndex topLeft, QModelIndex bottomRight)
|
|
{
|
|
if (tree->selectionModel())
|
|
{
|
|
QModelIndex index = tree->selectionModel()->selectedRows().first();
|
|
if (index.row() >= topLeft.row() && index.row() <= bottomRight.row() && bottomRight.column() == 1)
|
|
selectionChanged(tree->selectionModel()->selection(), tree->selectionModel()->selection());
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationDialog::deleteConfiguration()
|
|
{
|
|
if( !tree->selectionModel()->selectedRows().isEmpty() )
|
|
{
|
|
model->deleteConfiguration( tree->selectionModel()->selectedRows().first() );
|
|
tree->resizeColumnToContents( 0 );
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationDialog::updateNameLabel( LaunchConfiguration* l )
|
|
{
|
|
if( l )
|
|
{
|
|
configName->setText( i18n("Editing %2: <b>%1</b>", l->name(), l->type()->name() ) );
|
|
} else
|
|
{
|
|
configName->clear();
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationDialog::createConfiguration()
|
|
{
|
|
if( !tree->selectionModel()->selectedRows().isEmpty() )
|
|
{
|
|
QModelIndex idx = tree->selectionModel()->selectedRows().first();
|
|
if( idx.parent().isValid() )
|
|
{
|
|
idx = idx.parent();
|
|
}
|
|
model->createConfiguration( idx );
|
|
QModelIndex newindex = model->index( model->rowCount( idx ) - 1, 0, idx );
|
|
tree->selectionModel()->select( newindex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
|
|
tree->selectionModel()->setCurrentIndex( newindex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
|
|
tree->edit( newindex );
|
|
tree->resizeColumnToContents( 0 );
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationDialog::addConfiguration(ILaunchConfiguration* _launch)
|
|
{
|
|
LaunchConfiguration* launch = dynamic_cast<LaunchConfiguration*>(_launch);
|
|
Q_ASSERT(launch);
|
|
int row = launch->project() ? model->findItemForProject(launch->project())->row : 0;
|
|
QModelIndex idx = model->index(row, 0);
|
|
|
|
model->addConfiguration(launch, idx);
|
|
|
|
QModelIndex newindex = model->index( model->rowCount( idx ) - 1, 0, idx );
|
|
tree->selectionModel()->select( newindex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
|
|
tree->selectionModel()->setCurrentIndex( newindex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
|
|
tree->edit( newindex );
|
|
tree->resizeColumnToContents( 0 );
|
|
}
|
|
|
|
LaunchConfigurationsModel::LaunchConfigurationsModel(QObject* parent): QAbstractItemModel(parent)
|
|
{
|
|
GenericPageItem* global = new GenericPageItem;
|
|
global->text = i18n("Global");
|
|
global->row = 0;
|
|
topItems << global;
|
|
foreach( IProject* p, Core::self()->projectController()->projects() )
|
|
{
|
|
ProjectItem* t = new ProjectItem;
|
|
t->project = p;
|
|
t->row = topItems.count();
|
|
topItems << t;
|
|
}
|
|
foreach( LaunchConfiguration* l, Core::self()->runControllerInternal()->launchConfigurationsInternal() )
|
|
{
|
|
addItemForLaunchConfig( l );
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationsModel::addItemForLaunchConfig( LaunchConfiguration* l )
|
|
{
|
|
LaunchItem* t = new LaunchItem;
|
|
t->launch = l;
|
|
TreeItem* parent;
|
|
if( l->project() ) {
|
|
parent = findItemForProject( l->project() );
|
|
} else {
|
|
parent = topItems.at(0);
|
|
}
|
|
t->parent = parent;
|
|
t->row = parent->children.count();
|
|
parent->children.append( t );
|
|
addLaunchModeItemsForLaunchConfig ( t );
|
|
}
|
|
|
|
void LaunchConfigurationsModel::addLaunchModeItemsForLaunchConfig ( LaunchItem* t )
|
|
{
|
|
QList<TreeItem*> items;
|
|
QSet<QString> modes;
|
|
foreach( ILauncher* launcher, t->launch->type()->launchers() )
|
|
{
|
|
foreach( const QString& mode, launcher->supportedModes() )
|
|
{
|
|
if( !modes.contains( mode ) && launcher->configPages().count() > 0 )
|
|
{
|
|
modes.insert( mode );
|
|
LaunchModeItem* lmi = new LaunchModeItem;
|
|
lmi->mode = Core::self()->runController()->launchModeForId( mode );
|
|
lmi->parent = t;
|
|
lmi->row = t->children.count();
|
|
items.append( lmi );
|
|
}
|
|
}
|
|
}
|
|
if( !items.isEmpty() )
|
|
{
|
|
QModelIndex p = indexForConfig( t->launch );
|
|
beginInsertRows( p, t->children.count(), t->children.count() + items.count() - 1 );
|
|
t->children.append( items );
|
|
endInsertRows();
|
|
}
|
|
}
|
|
|
|
LaunchConfigurationsModel::ProjectItem* LaunchConfigurationsModel::findItemForProject( IProject* p )
|
|
{
|
|
foreach( TreeItem* t, topItems )
|
|
{
|
|
ProjectItem* pi = dynamic_cast<ProjectItem*>( t );
|
|
if( pi && pi->project == p )
|
|
{
|
|
return pi;
|
|
}
|
|
}
|
|
Q_ASSERT(false);
|
|
return 0;
|
|
}
|
|
|
|
int LaunchConfigurationsModel::columnCount(const QModelIndex& parent) const
|
|
{
|
|
Q_UNUSED( parent );
|
|
return 2;
|
|
}
|
|
|
|
QVariant LaunchConfigurationsModel::data(const QModelIndex& index, int role) const
|
|
{
|
|
if( index.isValid() && index.column() >= 0 && index.column() < 2 )
|
|
{
|
|
TreeItem* t = static_cast<TreeItem*>( index.internalPointer() );
|
|
switch( role )
|
|
{
|
|
case Qt::DisplayRole:
|
|
{
|
|
LaunchItem* li = dynamic_cast<LaunchItem*>( t );
|
|
if( li )
|
|
{
|
|
if( index.column() == 0 )
|
|
{
|
|
return li->launch->name();
|
|
} else if( index.column() == 1 )
|
|
{
|
|
return li->launch->type()->name();
|
|
}
|
|
}
|
|
ProjectItem* pi = dynamic_cast<ProjectItem*>( t );
|
|
if( pi && index.column() == 0 )
|
|
{
|
|
return pi->project->name();
|
|
}
|
|
GenericPageItem* gpi = dynamic_cast<GenericPageItem*>( t );
|
|
if( gpi && index.column() == 0 )
|
|
{
|
|
return gpi->text;
|
|
}
|
|
LaunchModeItem* lmi = dynamic_cast<LaunchModeItem*>( t );
|
|
if( lmi )
|
|
{
|
|
if( index.column() == 0 )
|
|
{
|
|
return lmi->mode->name();
|
|
} else if( index.column() == 1 )
|
|
{
|
|
LaunchConfiguration* l = configForIndex( index );
|
|
return l->type()->launcherForId( l->launcherForMode( lmi->mode->id() ) )->name();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case Qt::DecorationRole:
|
|
{
|
|
LaunchItem* li = dynamic_cast<LaunchItem*>( t );
|
|
if( index.column() == 0 && li )
|
|
{
|
|
return li->launch->type()->icon();
|
|
}
|
|
LaunchModeItem* lmi = dynamic_cast<LaunchModeItem*>( t );
|
|
if( lmi && index.column() == 0 )
|
|
{
|
|
return lmi->mode->icon();
|
|
}
|
|
if ( index.column() == 0 && !index.parent().isValid() ) {
|
|
if (index.row() == 0) {
|
|
// global item
|
|
return KIcon("folder");
|
|
} else {
|
|
// project item
|
|
return KIcon("folder-development");
|
|
}
|
|
}
|
|
}
|
|
case Qt::EditRole:
|
|
{
|
|
LaunchItem* li = dynamic_cast<LaunchItem*>( t );
|
|
if( li )
|
|
{
|
|
if( index.column() == 0 )
|
|
{
|
|
return li->launch->name();
|
|
} else if ( index.column() == 1 )
|
|
{
|
|
return li->launch->type()->id();
|
|
}
|
|
}
|
|
LaunchModeItem* lmi = dynamic_cast<LaunchModeItem*>( t );
|
|
if( lmi && index.column() == 1 )
|
|
{
|
|
return configForIndex( index )->launcherForMode( lmi->mode->id() );
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
QModelIndex LaunchConfigurationsModel::index(int row, int column, const QModelIndex& parent) const
|
|
{
|
|
if( !hasIndex( row, column, parent ) )
|
|
return QModelIndex();
|
|
TreeItem* tree;
|
|
|
|
if( !parent.isValid() )
|
|
{
|
|
tree = topItems.at( row );
|
|
} else
|
|
{
|
|
TreeItem* t = static_cast<TreeItem*>( parent.internalPointer() );
|
|
tree = t->children.at( row );
|
|
}
|
|
if( tree )
|
|
{
|
|
return createIndex( row, column, tree );
|
|
}
|
|
return QModelIndex();
|
|
}
|
|
|
|
QModelIndex LaunchConfigurationsModel::parent(const QModelIndex& child) const
|
|
{
|
|
if( child.isValid() )
|
|
{
|
|
TreeItem* t = static_cast<TreeItem*>( child.internalPointer() );
|
|
if( t->parent )
|
|
{
|
|
return createIndex( t->parent->row, 0, t->parent );
|
|
}
|
|
}
|
|
return QModelIndex();
|
|
}
|
|
|
|
int LaunchConfigurationsModel::rowCount(const QModelIndex& parent) const
|
|
{
|
|
if( parent.column() > 0 )
|
|
return 0;
|
|
if( parent.isValid() )
|
|
{
|
|
TreeItem* t = static_cast<TreeItem*>( parent.internalPointer() );
|
|
return t->children.count();
|
|
} else
|
|
{
|
|
return topItems.count();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
QVariant LaunchConfigurationsModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if( orientation == Qt::Horizontal && role == Qt::DisplayRole )
|
|
{
|
|
if( section == 0 )
|
|
{
|
|
return i18nc("Name of the Launch Configurations", "Name");
|
|
} else if( section == 1 )
|
|
{
|
|
return i18nc("The type of the Launch Configurations (i.e. Python Application, C++ Application)", "Type");
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
Qt::ItemFlags LaunchConfigurationsModel::flags(const QModelIndex& index) const
|
|
{
|
|
if( index.isValid() && index.column() >= 0
|
|
&& index.column() < columnCount( QModelIndex() ) )
|
|
{
|
|
TreeItem* t = static_cast<TreeItem*>( index.internalPointer() );
|
|
if( t && ( dynamic_cast<LaunchItem*>( t ) || ( dynamic_cast<LaunchModeItem*>( t ) && index.column() == 1 ) ) )
|
|
{
|
|
return Qt::ItemFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );
|
|
} else if( t )
|
|
{
|
|
return Qt::ItemFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
|
|
}
|
|
}
|
|
return Qt::NoItemFlags;
|
|
}
|
|
|
|
bool LaunchConfigurationsModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
|
{
|
|
if( index.isValid() && index.parent().isValid() && role == Qt::EditRole )
|
|
{
|
|
if( index.row() >= 0 && index.row() < rowCount( index.parent() ) )
|
|
{
|
|
LaunchItem* t = dynamic_cast<LaunchItem*>( static_cast<TreeItem*>( index.internalPointer() ) );
|
|
if( t )
|
|
{
|
|
if( index.column() == 0 )
|
|
{
|
|
t->launch->setName( value.toString() );
|
|
} else if( index.column() == 1 )
|
|
{
|
|
if (t->launch->type()->id() != value.toString()) {
|
|
t->launch->setType( value.toString() );
|
|
QModelIndex p = indexForConfig(t->launch);
|
|
kDebug() << data(p);
|
|
beginRemoveRows( p, 0, t->children.count() );
|
|
qDeleteAll( t->children );
|
|
t->children.clear();
|
|
endRemoveRows();
|
|
addLaunchModeItemsForLaunchConfig( t );
|
|
}
|
|
}
|
|
emit dataChanged(index, index);
|
|
return true;
|
|
}
|
|
LaunchModeItem* lmi = dynamic_cast<LaunchModeItem*>( static_cast<TreeItem*>( index.internalPointer() ) );
|
|
if( lmi )
|
|
{
|
|
if( index.column() == 1 && index.data(Qt::EditRole)!=value)
|
|
{
|
|
LaunchConfiguration* l = configForIndex( index );
|
|
l->setLauncherForMode( lmi->mode->id(), value.toString() );
|
|
emit dataChanged(index, index);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ILaunchMode* LaunchConfigurationsModel::modeForIndex( const QModelIndex& idx ) const
|
|
{
|
|
if( idx.isValid() )
|
|
{
|
|
LaunchModeItem* item = dynamic_cast<LaunchModeItem*>( static_cast<TreeItem*>( idx.internalPointer() ) );
|
|
if( item )
|
|
{
|
|
return item->mode;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
LaunchConfiguration* LaunchConfigurationsModel::configForIndex(const QModelIndex& idx ) const
|
|
{
|
|
if( idx.isValid() )
|
|
{
|
|
LaunchItem* item = dynamic_cast<LaunchItem*>( static_cast<TreeItem*>( idx.internalPointer() ) );
|
|
if( item )
|
|
{
|
|
return item->launch;
|
|
}
|
|
LaunchModeItem* lmitem = dynamic_cast<LaunchModeItem*>( static_cast<TreeItem*>( idx.internalPointer() ) );
|
|
if( lmitem )
|
|
{
|
|
return dynamic_cast<LaunchItem*>( lmitem->parent )->launch;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
QModelIndex LaunchConfigurationsModel::indexForConfig( LaunchConfiguration* l ) const
|
|
{
|
|
if( l )
|
|
{
|
|
TreeItem* tparent = topItems.at( 0 );
|
|
if( l->project() )
|
|
{
|
|
foreach( TreeItem* t, topItems )
|
|
{
|
|
ProjectItem* pi = dynamic_cast<ProjectItem*>( t );
|
|
if( pi && pi->project == l->project() )
|
|
{
|
|
tparent = t;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( tparent )
|
|
{
|
|
foreach( TreeItem* c, tparent->children )
|
|
{
|
|
LaunchItem* li = dynamic_cast<LaunchItem*>( c );
|
|
if( li->launch && li->launch == l )
|
|
{
|
|
return index( c->row, 0, index( tparent->row, 0, QModelIndex() ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return QModelIndex();
|
|
}
|
|
|
|
|
|
void LaunchConfigurationsModel::deleteConfiguration( const QModelIndex& index )
|
|
{
|
|
LaunchItem* t = dynamic_cast<LaunchItem*>( static_cast<TreeItem*>( index.internalPointer() ) );
|
|
if( !t )
|
|
return;
|
|
beginRemoveRows( parent( index ), index.row(), index.row() );
|
|
t->parent->children.removeAll( t );
|
|
Core::self()->runControllerInternal()->removeLaunchConfiguration( t->launch );
|
|
endRemoveRows();
|
|
}
|
|
|
|
void LaunchConfigurationsModel::createConfiguration(const QModelIndex& parent )
|
|
{
|
|
if(!Core::self()->runController()->launchConfigurationTypes().isEmpty())
|
|
{
|
|
TreeItem* t = static_cast<TreeItem*>( parent.internalPointer() );
|
|
ProjectItem* ti = dynamic_cast<ProjectItem*>( t );
|
|
|
|
LaunchConfigurationType* type = Core::self()->runController()->launchConfigurationTypes().at(0);
|
|
QPair<QString,QString> launcher = qMakePair( type->launchers().at( 0 )->supportedModes().at(0), type->launchers().at( 0 )->id() );
|
|
IProject* p = ( ti ? ti->project : 0 );
|
|
ILaunchConfiguration* l = Core::self()->runController()->createLaunchConfiguration( type, launcher, p );
|
|
|
|
addConfiguration(l, parent);
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationsModel::addConfiguration(ILaunchConfiguration* l, const QModelIndex& parent)
|
|
{
|
|
if( parent.isValid() )
|
|
{
|
|
beginInsertRows( parent, rowCount( parent ), rowCount( parent ) );
|
|
addItemForLaunchConfig( dynamic_cast<LaunchConfiguration*>( l ) );
|
|
endInsertRows();
|
|
}
|
|
else
|
|
{
|
|
delete l;
|
|
Q_ASSERT(false && "could not add the configuration");
|
|
}
|
|
}
|
|
|
|
IProject* LaunchConfigurationsModel::projectForIndex(const QModelIndex& idx)
|
|
{
|
|
if(idx.parent().isValid()) {
|
|
return projectForIndex(idx.parent());
|
|
} else {
|
|
const ProjectItem* item = dynamic_cast<const ProjectItem*>(topItems[idx.row()]);
|
|
return item ? item->project : 0;
|
|
}
|
|
}
|
|
|
|
LaunchConfigPagesContainer::LaunchConfigPagesContainer( const QList<LaunchConfigurationPageFactory*>& factories, QWidget* parent )
|
|
: QWidget(parent)
|
|
{
|
|
setLayout( new QVBoxLayout( this ) );
|
|
layout()->setContentsMargins( 0, 0, 0, 0 );
|
|
QWidget* parentwidget = this;
|
|
KTabWidget* tab = 0;
|
|
if( factories.count() > 1 )
|
|
{
|
|
tab = new KTabWidget( this );
|
|
parentwidget = tab;
|
|
layout()->addWidget( tab );
|
|
}
|
|
foreach( LaunchConfigurationPageFactory* fac, factories )
|
|
{
|
|
LaunchConfigurationPage* page = fac->createWidget( parentwidget );
|
|
if ( page->layout() ) {
|
|
page->layout()->setContentsMargins( 0, 0, 0, 0 );
|
|
}
|
|
pages.append( page );
|
|
connect( page, SIGNAL(changed()), SIGNAL(changed()) );
|
|
if( tab ) {
|
|
tab->addTab( page, page->icon(), page->title() );
|
|
} else
|
|
{
|
|
layout()->addWidget( page );
|
|
}
|
|
}
|
|
}
|
|
|
|
void LaunchConfigPagesContainer::setLaunchConfiguration( KDevelop::LaunchConfiguration* l )
|
|
{
|
|
config = l;
|
|
foreach( LaunchConfigurationPage* p, pages )
|
|
{
|
|
p->loadFromConfiguration( config->config(), config->project() );
|
|
}
|
|
}
|
|
|
|
void LaunchConfigPagesContainer::save()
|
|
{
|
|
foreach( LaunchConfigurationPage* p, pages )
|
|
{
|
|
p->saveToConfiguration( config->config() );
|
|
}
|
|
config->config().sync();
|
|
}
|
|
|
|
|
|
QWidget* LaunchConfigurationModelDelegate::createEditor ( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
|
{
|
|
const LaunchConfigurationsModel* model = dynamic_cast<const LaunchConfigurationsModel*>( index.model() );
|
|
ILaunchMode* mode = model->modeForIndex( index );
|
|
LaunchConfiguration* config = model->configForIndex( index );
|
|
if( index.column() == 1 && mode && config )
|
|
{
|
|
KComboBox* box = new KComboBox( parent );
|
|
QList<ILauncher*> launchers = config->type()->launchers();
|
|
for( QList<ILauncher*>::const_iterator it = launchers.constBegin(); it != launchers.constEnd(); it++ )
|
|
{
|
|
if( ((*it)->supportedModes().contains( mode->id() ) ) )
|
|
{
|
|
box->addItem( (*it)->name(), (*it)->id() );
|
|
}
|
|
}
|
|
return box;
|
|
} else if( !mode && config && index.column() == 1 )
|
|
{
|
|
KComboBox* box = new KComboBox( parent );
|
|
const QList<LaunchConfigurationType*> types = Core::self()->runController()->launchConfigurationTypes();
|
|
for( QList<LaunchConfigurationType*>::const_iterator it = types.begin(); it != types.end(); it++ )
|
|
{
|
|
box->addItem( (*it)->name(), (*it)->id() );
|
|
}
|
|
return box;
|
|
}
|
|
return QStyledItemDelegate::createEditor ( parent, option, index );
|
|
}
|
|
|
|
LaunchConfigurationModelDelegate::LaunchConfigurationModelDelegate()
|
|
{
|
|
}
|
|
|
|
void LaunchConfigurationModelDelegate::setEditorData ( QWidget* editor, const QModelIndex& index ) const
|
|
{
|
|
const LaunchConfigurationsModel* model = dynamic_cast<const LaunchConfigurationsModel*>( index.model() );
|
|
LaunchConfiguration* config = model->configForIndex( index );
|
|
if( index.column() == 1 && config )
|
|
{
|
|
KComboBox* box = qobject_cast<KComboBox*>( editor );
|
|
box->setCurrentIndex( box->findData( index.data( Qt::EditRole ) ) );
|
|
}
|
|
else
|
|
{
|
|
QStyledItemDelegate::setEditorData ( editor, index );
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationModelDelegate::setModelData ( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const
|
|
{
|
|
LaunchConfigurationsModel* lmodel = dynamic_cast<LaunchConfigurationsModel*>( model );
|
|
LaunchConfiguration* config = lmodel->configForIndex( index );
|
|
if( index.column() == 1 && config )
|
|
{
|
|
KComboBox* box = qobject_cast<KComboBox*>( editor );
|
|
lmodel->setData( index, box->itemData( box->currentIndex() ) );
|
|
}
|
|
else
|
|
{
|
|
QStyledItemDelegate::setModelData ( editor, model, index );
|
|
}
|
|
}
|
|
|
|
void LaunchConfigurationDialog::launchModeChanged(int item)
|
|
{
|
|
QModelIndex index = tree->currentIndex();
|
|
if(debugger->isVisible() && item>=0)
|
|
tree->model()->setData(index.sibling(index.row(), 1), debugger->itemData(item), Qt::EditRole);
|
|
}
|
|
|
|
}
|
|
|
|
#include "moc_launchconfigurationdialog.cpp"
|