diff --git a/shell/launchconfigurationdialog.cpp b/shell/launchconfigurationdialog.cpp index 6f26880254..217d83139f 100644 --- a/shell/launchconfigurationdialog.cpp +++ b/shell/launchconfigurationdialog.cpp @@ -1,777 +1,776 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "core.h" #include "runcontroller.h" #include "launchconfiguration.h" -#include "ui_launchconfigtypepage.h" #include #include #include namespace KDevelop { //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() ); addConfig->setIcon( KIcon("list-add") ); addConfig->setEnabled( false ); deleteConfig->setIcon( KIcon("list-remove") ); deleteConfig->setEnabled( false ); 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() ); connect( addConfig, SIGNAL(clicked()), this, SLOT(createConfiguration())); connect( deleteConfig, SIGNAL(clicked()), this, SLOT(deleteConfiguration())); 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 ); setInitialSize( QSize( 700, 500 ) ); // 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(); } int width = qMax( tree->columnWidth( 0 ), level*tree->indentation() + tree->indentation() + tree->sizeHintForIndex( widthidx ).width() ); tree->setColumnWidth( 0, width ); connect( this, SIGNAL(okClicked()), SLOT(saveConfig()) ); connect( this, SIGNAL(applyClicked()), SLOT(saveConfig()) ); } void LaunchConfigurationDialog::selectionChanged(QItemSelection selected, QItemSelection deselected ) { if( !deselected.indexes().isEmpty() ) { LaunchConfiguration* l = model->configForIndex( deselected.indexes().first() ); if( l ) { disconnect(l, SIGNAL(nameChanged(QString)), this, SLOT(updateNameLabel(QString))); 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( stack->currentWidget() ); tab->setLaunchConfiguration( l ); currentPageChanged = false; } } } } updateNameLabel(""); if( !selected.indexes().isEmpty() ) { LaunchConfiguration* l = model->configForIndex( selected.indexes().first() ); ILaunchMode* lm = model->modeForIndex( selected.indexes().first() ); if( l ) { updateNameLabel( l->name() ); tree->expand( model->indexForConfig( l ) ); connect( l, SIGNAL(nameChanged(QString)), SLOT(updateNameLabel(QString)) ); if( lm ) { ILauncher* launcher = l->type()->launcherForId( l->launcherForMode( lm->id() ) ); if( launcher ) { LaunchConfigPagesContainer* tab; if( launcherWidgets.contains( launcher ) ) { tab = launcherWidgets.value( launcher ); } else { tab = new LaunchConfigPagesContainer( launcher->configPages(), stack ); connect( tab, SIGNAL(changed()), SLOT(pageChanged()) ); stack->addWidget( tab ); } tab->setLaunchConfiguration( l ); stack->setCurrentWidget( tab ); updateNameLabel( l->name() ); 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; if( typeWidgets.contains( type ) ) { tab = typeWidgets.value( type ); } else { 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 ); } } else { addConfig->setEnabled( true ); deleteConfig->setEnabled( false ); stack->setCurrentIndex( 0 ); } } else { addConfig->setEnabled( false ); deleteConfig->setEnabled( false ); stack->setCurrentIndex( 0 ); } } void LaunchConfigurationDialog::saveConfig( const QModelIndex& idx ) { LaunchConfigPagesContainer* tab = qobject_cast( 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::deleteConfiguration() { if( !tree->selectionModel()->selectedRows().isEmpty() ) { model->deleteConfiguration( tree->selectionModel()->selectedRows().first() ); tree->resizeColumnToContents( 0 ); } } void LaunchConfigurationDialog::updateNameLabel( const QString& name ) { configName->setText( i18n("%1", name ) ); } 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 ); } } 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()->launchConfigurations() ) { 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 ); QSet modes; foreach( ILauncher* launcher, l->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(); t->children.append( lmi ); } } } } LaunchConfigurationsModel::ProjectItem* LaunchConfigurationsModel::findItemForProject( IProject* p ) { foreach( TreeItem* t, topItems ) { ProjectItem* pi = dynamic_cast( t ); if( pi && pi->project == p ) { return pi; } } Q_ASSERT(false); return 0; } int LaunchConfigurationsModel::columnCount(const QModelIndex& parent) const { return 2; } QVariant LaunchConfigurationsModel::data(const QModelIndex& index, int role) const { if( index.isValid() && index.column() >= 0 && index.column() < 2 ) { TreeItem* t = static_cast( index.internalPointer() ); switch( role ) { case Qt::DisplayRole: { LaunchItem* li = dynamic_cast( 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( t ); if( pi && index.column() == 0 ) { return pi->project->name(); } GenericPageItem* gpi = dynamic_cast( t ); if( gpi && index.column() == 0 ) { return gpi->text; } LaunchModeItem* lmi = dynamic_cast( 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( t ); if( index.column() == 0 && li ) { return li->launch->type()->icon(); } LaunchModeItem* lmi = dynamic_cast( t ); if( lmi && index.column() == 0 ) { return lmi->mode->icon(); } } case Qt::EditRole: { LaunchItem* li = dynamic_cast( 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( 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( 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( 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( 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( index.internalPointer() ); if( t && ( dynamic_cast( t ) || ( dynamic_cast( 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( static_cast( index.internalPointer() ) ); if( t ) { if( index.column() == 0 ) { t->launch->setName( value.toString() ); return true; } else if( index.column() == 1 ) { t->launch->setType( value.toString() ); return true; } } LaunchModeItem* lmi = dynamic_cast( static_cast( index.internalPointer() ) ); if( lmi ) { if( index.column() == 1 ) { LaunchConfiguration* l = configForIndex( index ); l->setLauncherForMode( lmi->mode->id(), value.toString() ); return true; } } } } return false; } ILaunchMode* LaunchConfigurationsModel::modeForIndex( const QModelIndex& idx ) const { if( idx.isValid() ) { LaunchModeItem* item = dynamic_cast( static_cast( idx.internalPointer() ) ); if( item ) { return item->mode; } } return 0; } LaunchConfiguration* LaunchConfigurationsModel::configForIndex(const QModelIndex& idx ) const { if( idx.isValid() ) { LaunchItem* item = dynamic_cast( static_cast( idx.internalPointer() ) ); if( item ) { return item->launch; } LaunchModeItem* lmitem = dynamic_cast( static_cast( idx.internalPointer() ) ); if( lmitem ) { return dynamic_cast( 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( t ); if( pi && pi->project == l->project() ) { tparent = t; break; } } } if( tparent ) { foreach( TreeItem* c, tparent->children ) { LaunchItem* li = dynamic_cast( 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( static_cast( 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 ) { TreeItem* t = static_cast( parent.internalPointer() ); ProjectItem* ti = dynamic_cast( t ); if( parent.isValid() && t && !Core::self()->runController()->launchConfigurationTypes().isEmpty() ) { KConfigGroup launchGroup; if( ti ) { launchGroup = ti->project->projectConfiguration()->group( RunController::LaunchConfigurationsGroup ); } else if( !t->parent ) { launchGroup = Core::self()->activeSession()->config()->group( RunController::LaunchConfigurationsGroup ); } else { kWarning() << "Expected project or global item, but didn't find either"; return; } beginInsertRows( parent, rowCount( parent ), rowCount( parent ) ); QStringList configs = launchGroup.readEntry( RunController::LaunchConfigurationsListEntry, QStringList() ); uint num = 0; QString baseName = "Launch Configuration"; while( configs.contains( QString( "%1 %2" ).arg( baseName ).arg( num ) ) ) { num++; } QString groupName = QString( "%1 %2" ).arg( baseName ).arg( num ); KConfigGroup launchConfigGroup = launchGroup.group( groupName ); LaunchConfigurationType* type = Core::self()->runController()->launchConfigurationTypes().at(0); launchConfigGroup.writeEntry(LaunchConfiguration::LaunchConfigurationNameEntry, i18n( "New Configuration" ) ); launchConfigGroup.writeEntry(LaunchConfiguration::LaunchConfigurationTypeEntry, type->id() ); launchConfigGroup.sync(); configs << groupName; launchGroup.writeEntry( RunController::LaunchConfigurationsListEntry, configs ); launchGroup.sync(); LaunchConfiguration* l = new LaunchConfiguration( launchConfigGroup, ( ti ? ti->project : 0 ) ); l->setLauncherForMode( type->launchers().at( 0 )->supportedModes().at(0), type->launchers().at( 0 )->id() ); Core::self()->runControllerInternal()->addLaunchConfiguration( l ); addItemForLaunchConfig( l ); endInsertRows(); } } LaunchConfigPagesContainer::LaunchConfigPagesContainer( const QList& factories, QWidget* parent ) : QWidget(parent) { setLayout( new QVBoxLayout( this ) ); 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 ); 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( index.model() ); ILaunchMode* mode = model->modeForIndex( index ); LaunchConfiguration* config = model->configForIndex( index ); if( index.column() == 1 && mode && config ) { KComboBox* box = new KComboBox( parent ); QList launchers = config->type()->launchers(); for( QList::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 ); QList types = Core::self()->runController()->launchConfigurationTypes(); for( QList::const_iterator it = types.begin(); it != types.end(); it++ ) { box->addItem( (*it)->name(), (*it)->id() ); } return box; } return QItemDelegate::createEditor ( parent, option, index ); } LaunchConfigurationModelDelegate::LaunchConfigurationModelDelegate() { } void LaunchConfigurationModelDelegate::setEditorData ( QWidget* editor, const QModelIndex& index ) const { const LaunchConfigurationsModel* model = dynamic_cast( index.model() ); LaunchConfiguration* config = model->configForIndex( index ); if( index.column() == 1 && config ) { KComboBox* box = qobject_cast( editor ); box->setCurrentIndex( box->findData( index.data( Qt::EditRole ) ) ); } QItemDelegate::setEditorData ( editor, index ); } void LaunchConfigurationModelDelegate::setModelData ( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const { LaunchConfigurationsModel* lmodel = dynamic_cast( model ); LaunchConfiguration* config = lmodel->configForIndex( index ); if( index.column() == 1 && config ) { KComboBox* box = qobject_cast( editor ); lmodel->setData( index, box->itemData( box->currentIndex() ) ); } QItemDelegate::setModelData ( editor, model, index ); } } #include "launchconfigurationdialog.moc"