File indexing completed on 2024-05-12 04:39:40

0001 /*
0002     SPDX-FileCopyrightText: 2010 Andreas Pakulat <apaku@gmx.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-or-later
0005 */
0006 
0007 #include "includeswidget.h"
0008 
0009 #include <QAction>
0010 #include <KLocalizedString>
0011 
0012 #include <QFileInfo>
0013 
0014 #include <interfaces/iproject.h>
0015 #include <util/path.h>
0016 
0017 #include "../ui_includeswidget.h"
0018 #include "includesmodel.h"
0019 #include <debug.h>
0020 #include <QShortcut>
0021 
0022 IncludesWidget::IncludesWidget( QWidget* parent )
0023     : QWidget ( parent ), ui( new Ui::IncludesWidget )
0024     , includesModel( new IncludesModel( this ) )
0025 {
0026     ui->setupUi( this );
0027 
0028     // hack taken from kurlrequester, make the buttons a bit less in height so they better match the url-requester
0029     ui->addIncludePath->setFixedHeight( ui->includePathRequester->sizeHint().height() );
0030     ui->removeIncludePath->setFixedHeight( ui->includePathRequester->sizeHint().height() );
0031 
0032     ui->errorWidget->setHidden(true);
0033     ui->errorWidget->setMessageType(KMessageWidget::Warning);
0034 
0035     connect( ui->addIncludePath, &QPushButton::clicked, this, &IncludesWidget::addIncludePath );
0036     connect( ui->removeIncludePath, &QPushButton::clicked, this, &IncludesWidget::deleteIncludePath );
0037 
0038     // also let user choose a file as include path. This file will be "automatically included" in all files. See also -include command line option of clang/gcc
0039     ui->includePathRequester->setMode( KFile::File | KFile::Directory | KFile::LocalOnly | KFile::ExistingOnly );
0040 
0041     ui->includePaths->setModel( includesModel );
0042     connect( ui->includePaths->selectionModel(), &QItemSelectionModel::currentChanged, this, &IncludesWidget::includePathSelected );
0043     connect( ui->includePathRequester, &KUrlRequester::textChanged, this, &IncludesWidget::includePathEdited );
0044     connect( ui->includePathRequester, &KUrlRequester::urlSelected, this, &IncludesWidget::includePathUrlSelected );
0045     connect(includesModel, &IncludesModel::dataChanged, this, QOverload<>::of(&IncludesWidget::includesChanged));
0046     connect(includesModel, &IncludesModel::rowsInserted, this, QOverload<>::of(&IncludesWidget::includesChanged));
0047     connect(includesModel, &IncludesModel::rowsRemoved, this, QOverload<>::of(&IncludesWidget::includesChanged));
0048 
0049     auto* delIncAction = new QAction(i18nc("@action", "Delete Include Path"), this);
0050     delIncAction->setShortcut( QKeySequence( Qt::Key_Delete ) );
0051     delIncAction->setShortcutContext( Qt::WidgetWithChildrenShortcut );
0052     ui->includePaths->addAction( delIncAction );
0053     connect( delIncAction, &QAction::triggered, this, &IncludesWidget::deleteIncludePath );
0054 }
0055 
0056 void IncludesWidget::setIncludes( const QStringList& paths )
0057 {
0058     bool b = blockSignals( true );
0059     clear();
0060     includesModel->setIncludes( paths );
0061     blockSignals( b );
0062     updateEnablements();
0063     checkIfIncludePathExist();
0064 }
0065 void IncludesWidget::includesChanged()
0066 {
0067     qCDebug(DEFINESANDINCLUDES) << "includes changed";
0068     emit includesChanged( includesModel->includes() );
0069     checkIfIncludePathExist();
0070 }
0071 
0072 void IncludesWidget::includePathSelected( const QModelIndex& /*selected*/ )
0073 {
0074     updateEnablements();
0075 }
0076 
0077 void IncludesWidget::includePathEdited()
0078 {
0079     updateEnablements();
0080 }
0081 
0082 void IncludesWidget::clear()
0083 {
0084     includesModel->setIncludes( QStringList() );
0085     updateEnablements();
0086 }
0087 
0088 void IncludesWidget::addIncludePath()
0089 {
0090     includesModel->addInclude( makeIncludeDirAbsolute(ui->includePathRequester->url()) );
0091     ui->includePathRequester->clear();
0092     updateEnablements();
0093 }
0094 
0095 void IncludesWidget::deleteIncludePath()
0096 {
0097     qCDebug(DEFINESANDINCLUDES) << "deleting include path" << ui->includePaths->currentIndex();
0098     const QModelIndex curidx = ui->includePaths->currentIndex();
0099     if (curidx.isValid()) {
0100         includesModel->removeRows(curidx.row(), 1);
0101     }
0102     updateEnablements();
0103 }
0104 
0105 void IncludesWidget::includePathUrlSelected(const QUrl &url)
0106 {
0107     Q_UNUSED(url);
0108     updateEnablements();
0109 }
0110 
0111 void IncludesWidget::setProject(KDevelop::IProject* w_project)
0112 {
0113     ui->includePathRequester->setStartDir( w_project->path().toUrl() );
0114 }
0115 
0116 void IncludesWidget::updateEnablements() {
0117     // Disable removal of the project root entry which is always first in the list
0118     ui->addIncludePath->setEnabled( QFileInfo::exists(makeIncludeDirAbsolute(ui->includePathRequester->url())) && !ui->includePathRequester->text().isEmpty() );
0119     ui->removeIncludePath->setEnabled( ui->includePaths->currentIndex().isValid() );
0120 }
0121 
0122 QString IncludesWidget::makeIncludeDirAbsolute(const QUrl &url) const
0123 {
0124     QString localFile = url.toLocalFile();
0125     if( url.isRelative() ) {
0126         // Relative, make absolute based on startDir of the requester
0127         localFile = ui->includePathRequester->startDir().toLocalFile() + QLatin1Char('/') + url.path();
0128     }
0129     return localFile;
0130 }
0131 
0132 void IncludesWidget::checkIfIncludePathExist()
0133 {
0134     QFileInfo info;
0135     for (auto& include : includesModel->includes()) {
0136         info.setFile(include);
0137         if (!info.exists()) {
0138             ui->errorWidget->setText(i18nc("%1 is an include path", "%1 does not exist", include));
0139             ui->errorWidget->animatedShow();
0140             return;
0141         }
0142     }
0143     ui->errorWidget->animatedHide();
0144 }
0145 
0146 #include "moc_includeswidget.cpp"