File indexing completed on 2024-04-28 04:39:09

0001 /*
0002     SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "projectbuildsetwidget.h"
0008 
0009 #include <QTreeView>
0010 #include <QToolButton>
0011 #include <QItemSelectionModel>
0012 #include <QModelIndex>
0013 #include <QIcon>
0014 #include <QMenu>
0015 
0016 #include <KLocalizedString>
0017 
0018 #include <project/projectmodel.h>
0019 #include <interfaces/iproject.h>
0020 #include <interfaces/icore.h>
0021 #include <interfaces/iprojectcontroller.h>
0022 #include <project/projectbuildsetmodel.h>
0023 
0024 #include "projectmanagerviewplugin.h"
0025 #include "projectmanagerview.h"
0026 
0027 #include "ui_projectbuildsetwidget.h"
0028 #include "debug.h"
0029 
0030 #include <interfaces/contextmenuextension.h>
0031 #include <interfaces/context.h>
0032 #include <interfaces/iplugincontroller.h>
0033 
0034 ProjectBuildSetWidget::ProjectBuildSetWidget( QWidget* parent )
0035     : QWidget( parent ),
0036      m_ui( new Ui::ProjectBuildSetWidget )
0037 {
0038     m_ui->setupUi( this );
0039 
0040     connect( m_ui->addItemButton, &QToolButton::clicked,
0041              this, &ProjectBuildSetWidget::addItems );
0042 
0043     connect( m_ui->removeItemButton, &QToolButton::clicked,
0044              this, &ProjectBuildSetWidget::removeItems );
0045 
0046     connect( m_ui->upButton, &QToolButton::clicked,
0047              this, &ProjectBuildSetWidget::moveUp );
0048 
0049     connect( m_ui->downButton, &QToolButton::clicked,
0050              this, &ProjectBuildSetWidget::moveDown );
0051 
0052     connect( m_ui->topButton, &QToolButton::clicked,
0053              this, &ProjectBuildSetWidget::moveToTop );
0054 
0055     connect( m_ui->bottomButton, &QToolButton::clicked,
0056              this, &ProjectBuildSetWidget::moveToBottom );
0057 
0058     m_ui->itemView->setContextMenuPolicy( Qt::CustomContextMenu );
0059     connect( m_ui->itemView, &QTreeView::customContextMenuRequested,
0060              this, &ProjectBuildSetWidget::showContextMenu );
0061     layout()->setContentsMargins(0, 0, 0, 0);
0062 }
0063 
0064 void ProjectBuildSetWidget::setProjectView( ProjectManagerView* view )
0065 {
0066     m_view = view;
0067     m_ui->itemView->setModel( KDevelop::ICore::self()->projectController()->buildSetModel() );
0068     connect( m_ui->itemView->selectionModel(), &QItemSelectionModel::selectionChanged,
0069              this, &ProjectBuildSetWidget::selectionChanged );
0070 }
0071 
0072 void ProjectBuildSetWidget::selectionChanged()
0073 {
0074     QModelIndexList selectedRows = m_ui->itemView->selectionModel()->selectedRows();
0075     qCDebug(PLUGIN_PROJECTMANAGERVIEW) << "checking selectionmodel:" << selectedRows;
0076     m_ui->removeItemButton->setEnabled( !selectedRows.isEmpty() );
0077     m_ui->addItemButton->setEnabled( !m_view->selectedItems().isEmpty() );
0078 
0079     bool enableUp = selectedRows.count() > 0 && selectedRows.first().row() != 0;
0080     bool enableDown = selectedRows.count() > 0 && selectedRows.last().row() != m_ui->itemView->model()->rowCount() - 1;
0081     m_ui->upButton->setEnabled( enableUp );
0082     m_ui->downButton->setEnabled( enableDown );
0083     m_ui->bottomButton->setEnabled( enableDown );
0084     m_ui->topButton->setEnabled( enableUp );
0085 }
0086 
0087 ProjectBuildSetWidget::~ProjectBuildSetWidget()
0088 {
0089     delete m_ui;
0090 }
0091 
0092 //TODO test whether this could be replaced by projecttreeview.cpp::popupContextMenu_appendActions
0093 void showContextMenu_appendActions(QMenu& menu, const QList<QAction*>& actions)
0094 {
0095     menu.addSeparator();
0096     for (QAction* act : actions) {
0097         menu.addAction(act);
0098     }
0099 }
0100 
0101 void ProjectBuildSetWidget::showContextMenu( const QPoint& p )
0102 {
0103     if( m_ui->itemView->selectionModel()->selectedRows().isEmpty() )
0104         return;
0105 
0106     QList<KDevelop::ProjectBaseItem*> itemlist;
0107 
0108     if(m_ui->itemView->selectionModel()->selectedRows().count() == 1)
0109     {
0110         KDevelop::ProjectBuildSetModel* buildSet = KDevelop::ICore::self()->projectController()->buildSetModel();
0111 
0112         int row = m_ui->itemView->selectionModel()->selectedRows()[0].row();
0113         if(row < buildSet->items().size())
0114         {
0115             KDevelop::ProjectBaseItem* item = buildSet->items().at(row).findItem();
0116             if(item)
0117                 itemlist << item;
0118         }
0119     }
0120 
0121 
0122     QMenu m(this);
0123     m.setTitle(i18nc("@title:menu", "Build Set"));
0124     m.addAction(QIcon::fromTheme(QStringLiteral("list-remove")), i18nc("@action:inmenu", "Remove from Build Set"), this, SLOT(removeItems()) );
0125 
0126     if( !itemlist.isEmpty() )
0127     {
0128         KDevelop::ProjectItemContextImpl context(itemlist);
0129         const QList<KDevelop::ContextMenuExtension> extensions = KDevelop::ICore::self()->pluginController()->queryPluginsForContextMenuExtensions(&context, &m);
0130 
0131         QList<QAction*> buildActions;
0132         QList<QAction*> vcsActions;
0133         QList<QAction*> extActions;
0134         QList<QAction*> projectActions;
0135         QList<QAction*> fileActions;
0136         QList<QAction*> runActions;
0137         for (const KDevelop::ContextMenuExtension& ext : extensions) {
0138             buildActions += ext.actions(KDevelop::ContextMenuExtension::BuildGroup);
0139             fileActions += ext.actions(KDevelop::ContextMenuExtension::FileGroup);
0140             projectActions += ext.actions(KDevelop::ContextMenuExtension::ProjectGroup);
0141             vcsActions += ext.actions(KDevelop::ContextMenuExtension::VcsGroup);
0142             extActions += ext.actions(KDevelop::ContextMenuExtension::ExtensionGroup);
0143             runActions += ext.actions(KDevelop::ContextMenuExtension::RunGroup);
0144         }
0145 
0146         showContextMenu_appendActions(m, buildActions);
0147         showContextMenu_appendActions(m, runActions);
0148         showContextMenu_appendActions(m, fileActions);
0149 
0150         showContextMenu_appendActions(m, vcsActions);
0151         showContextMenu_appendActions(m, extActions);
0152 
0153         showContextMenu_appendActions(m, projectActions);
0154     }
0155 
0156     m.exec( m_ui->itemView->viewport()->mapToGlobal( p ) );
0157 }
0158 
0159 void ProjectBuildSetWidget::addItems()
0160 {
0161     const auto selectedItems = m_view->selectedItems();
0162     for (KDevelop::ProjectBaseItem* item : selectedItems) {
0163         KDevelop::ICore::self()->projectController()->buildSetModel()->addProjectItem( item );
0164     }
0165 }
0166 
0167 void ProjectBuildSetWidget::removeItems()
0168 {
0169     // We only support contiguous selection, so we only need to remove the first range
0170     QItemSelectionRange range = m_ui->itemView->selectionModel()->selection().first();
0171     int top = range.top();
0172     qCDebug(PLUGIN_PROJECTMANAGERVIEW) << "removing:" << range.top() << range.height();
0173     KDevelop::ProjectBuildSetModel* buildSet = KDevelop::ICore::self()->projectController()->buildSetModel();
0174     buildSet->removeRows( range.top(), range.height() );
0175     top = qMin( top, buildSet->rowCount() - 1 );
0176     QModelIndex sidx = buildSet->index( top, 0 );
0177     QModelIndex eidx = buildSet->index( top, buildSet->columnCount() - 1 );
0178     m_ui->itemView->selectionModel()->select( QItemSelection( sidx, eidx ),
0179                                               QItemSelectionModel::ClearAndSelect );
0180     m_ui->itemView->selectionModel()->setCurrentIndex( sidx,  QItemSelectionModel::Current );
0181 }
0182 
0183 void ProjectBuildSetWidget::moveDown()
0184 {
0185     // We only support contiguous selection, so we only need to remove the first range
0186     QItemSelectionRange range = m_ui->itemView->selectionModel()->selection().first();
0187     int top = range.top(), height = range.height();
0188     KDevelop::ProjectBuildSetModel* buildSet = KDevelop::ICore::self()->projectController()->buildSetModel();
0189     buildSet->moveRowsDown( top, height );
0190     int columnCount = buildSet->columnCount();
0191     QItemSelection newrange( buildSet->index( top + 1, 0 ),
0192                              buildSet->index( top + height, columnCount - 1 ) );
0193     m_ui->itemView->selectionModel()->select( newrange, QItemSelectionModel::ClearAndSelect );
0194     m_ui->itemView->selectionModel()->setCurrentIndex( newrange.first().topLeft(),
0195                                                        QItemSelectionModel::Current );
0196 }
0197 
0198 void ProjectBuildSetWidget::moveToBottom()
0199 {
0200     // We only support contiguous selection, so we only need to remove the first range
0201     QItemSelectionRange range = m_ui->itemView->selectionModel()->selection().first();
0202     int top = range.top(), height = range.height();
0203     KDevelop::ProjectBuildSetModel* buildSet = KDevelop::ICore::self()->projectController()->buildSetModel();
0204     buildSet->moveRowsToBottom( top, height );
0205     int rowCount = buildSet->rowCount();
0206     int columnCount = buildSet->columnCount();
0207     QItemSelection newrange( buildSet->index( rowCount - height, 0 ),
0208                              buildSet->index( rowCount - 1, columnCount - 1 ) );
0209     m_ui->itemView->selectionModel()->select( newrange, QItemSelectionModel::ClearAndSelect );
0210     m_ui->itemView->selectionModel()->setCurrentIndex( newrange.first().topLeft(),
0211                                                        QItemSelectionModel::Current );
0212 }
0213 
0214 void ProjectBuildSetWidget::moveUp()
0215 {
0216     // We only support contiguous selection, so we only need to remove the first range
0217     QItemSelectionRange range = m_ui->itemView->selectionModel()->selection().first();
0218     int top = range.top(), height = range.height();
0219     KDevelop::ProjectBuildSetModel* buildSet = KDevelop::ICore::self()->projectController()->buildSetModel();
0220     buildSet->moveRowsUp( top, height );
0221     int columnCount = buildSet->columnCount();
0222     QItemSelection newrange( buildSet->index( top - 1, 0 ),
0223                              buildSet->index( top - 2 + height, columnCount - 1 ) );
0224     m_ui->itemView->selectionModel()->select( newrange, QItemSelectionModel::ClearAndSelect );
0225     m_ui->itemView->selectionModel()->setCurrentIndex( newrange.first().topLeft(),
0226                                                        QItemSelectionModel::Current );
0227 }
0228 
0229 
0230 void ProjectBuildSetWidget::moveToTop()
0231 {
0232     // We only support contiguous selection, so we only need to remove the first range
0233     QItemSelectionRange range = m_ui->itemView->selectionModel()->selection().first();
0234     int top = range.top(), height = range.height();
0235     KDevelop::ProjectBuildSetModel* buildSet = KDevelop::ICore::self()->projectController()->buildSetModel();
0236     buildSet->moveRowsToTop( top, height );
0237     int columnCount = buildSet->columnCount();
0238     QItemSelection newrange( buildSet->index( 0, 0 ),
0239                              buildSet->index( height - 1, columnCount - 1 ) );
0240     m_ui->itemView->selectionModel()->select( newrange, QItemSelectionModel::ClearAndSelect );
0241     m_ui->itemView->selectionModel()->setCurrentIndex( newrange.first().topLeft(),
0242                                                        QItemSelectionModel::Current );
0243 }
0244 
0245 #include "moc_projectbuildsetwidget.cpp"