File indexing completed on 2024-04-28 04:38:55

0001 /*
0002     SPDX-FileCopyrightText: 2003, 2006 Adam Treat <treat@kde.org>
0003     SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "kdevkonsoleview.h"
0009 #include "debug.h"
0010 
0011 #include <QFrame>
0012 #include <QIcon>
0013 #include <QKeyEvent>
0014 #include <QUuid>
0015 #include <QVBoxLayout>
0016 
0017 #include <kde_terminal_interface.h>
0018 #include <KLocalizedString>
0019 #include <KPluginFactory>
0020 #include <KParts/ReadOnlyPart>
0021 
0022 #include <interfaces/icore.h>
0023 #include <interfaces/isession.h>
0024 #include <interfaces/idocumentcontroller.h>
0025 #include <interfaces/iprojectcontroller.h>
0026 #include <interfaces/iproject.h>
0027 #include <util/path.h>
0028 
0029 #include "kdevkonsoleviewplugin.h"
0030 
0031 class KDevKonsoleViewPrivate
0032 {
0033 public:
0034     KDevKonsoleViewPlugin* mplugin;
0035     KDevKonsoleView* m_view;
0036     KParts::ReadOnlyPart *konsolepart;
0037     QVBoxLayout *m_vbox;
0038     // TODO: remove this once we can depend on a Qt version that includes https://codereview.qt-project.org/#/c/83800/
0039     QMetaObject::Connection m_partDestroyedConnection;
0040 
0041     void _k_slotTerminalClosed();
0042 
0043     void init( KPluginFactory* factory )
0044     {
0045         Q_ASSERT( konsolepart == nullptr );
0046 
0047         Q_ASSERT( factory != nullptr );
0048 
0049         if ( ( konsolepart = factory->create<KParts::ReadOnlyPart>( m_view ) ) )
0050         {
0051             QObject::disconnect(m_partDestroyedConnection);
0052             m_partDestroyedConnection = QObject::connect(konsolepart, &KParts::ReadOnlyPart::destroyed,
0053                                                          m_view, [&] { _k_slotTerminalClosed(); });
0054 
0055             konsolepart->widget() ->setFocusPolicy( Qt::WheelFocus );
0056             konsolepart->widget() ->setFocus();
0057             konsolepart->widget() ->installEventFilter( m_view );
0058 
0059             if ( auto * frame = qobject_cast<QFrame*>( konsolepart->widget() ) )
0060                 frame->setFrameStyle( QFrame::Panel | QFrame::Sunken );
0061 
0062             m_vbox->addWidget( konsolepart->widget() );
0063             m_view->setFocusProxy( konsolepart->widget() );
0064             konsolepart->widget() ->show();
0065 
0066             TerminalInterface* interface = qobject_cast<TerminalInterface*>(konsolepart);
0067             Q_ASSERT(interface);
0068 
0069             QString dir;
0070             if (KDevelop::IDocument* activeDocument = KDevelop::ICore::self()->documentController()->activeDocument())
0071             {
0072                 KDevelop::IProject* project = KDevelop::ICore::self()->projectController()->findProjectForUrl(activeDocument->url());
0073                 if (project && project->path().isLocalFile())
0074                     dir = project->path().path();
0075                 else if (activeDocument->url().isLocalFile())
0076                     dir = activeDocument->url().adjusted(QUrl::RemoveFilename).path(QUrl::FullyDecoded);
0077             }
0078             interface->showShellInDir( dir );
0079 
0080             interface->sendInput(QLatin1String(" kdevelop! -s \"") + KDevelop::ICore::self()->activeSession()->id().toString() + QLatin1String("\"\n"));
0081 
0082         }else
0083         {
0084             qCDebug(PLUGIN_KONSOLE) << "Couldn't create KParts::ReadOnlyPart from konsole factory!";
0085         }
0086     }
0087 
0088     ~KDevKonsoleViewPrivate()
0089     {
0090         QObject::disconnect(m_partDestroyedConnection);
0091     }
0092 };
0093 
0094 void KDevKonsoleViewPrivate::_k_slotTerminalClosed()
0095 {
0096     konsolepart = nullptr;
0097     init( mplugin->konsoleFactory() );
0098 }
0099 
0100 KDevKonsoleView::KDevKonsoleView( KDevKonsoleViewPlugin *plugin, QWidget* parent )
0101         : QWidget( parent ), d(new KDevKonsoleViewPrivate)
0102 
0103 {
0104     d->mplugin = plugin;
0105     d->m_view = this;
0106     d->konsolepart = nullptr;
0107     setObjectName( i18n( "Terminal" ) );
0108 
0109     setWindowIcon( QIcon::fromTheme( QStringLiteral( "utilities-terminal" ), windowIcon() ) );
0110     setWindowTitle(i18nc("@title:window", "Terminal"));
0111 
0112     d->m_vbox = new QVBoxLayout( this );
0113     d->m_vbox->setContentsMargins(0, 0, 0, 0);
0114     d->m_vbox->setSpacing( 0 );
0115 
0116     d->init( d->mplugin->konsoleFactory() );
0117 
0118     //TODO Make this configurable in the future,
0119     // but by default the konsole shouldn't
0120     // automatically switch directories on you.
0121 
0122 //     connect( KDevelop::Core::documentController(), SIGNAL(documentActivated(KDevDocument*)),
0123 //              this, SLOT(documentActivated(KDevDocument*)) );
0124 }
0125 
0126 KDevKonsoleView::~KDevKonsoleView()
0127 {
0128     delete d;
0129 }
0130 
0131 void KDevKonsoleView::setDirectory( const QUrl &url )
0132 {
0133     if ( !url.isValid() || !url.isLocalFile() )
0134         return ;
0135 
0136     if ( d->konsolepart && url != d->konsolepart->url() )
0137         d->konsolepart->openUrl( url );
0138 }
0139 
0140 bool KDevKonsoleView::eventFilter( QObject* obj, QEvent *e )
0141 {
0142     switch( e->type() ) {
0143         case QEvent::ShortcutOverride: {
0144             auto *k = static_cast<QKeyEvent *>(e);
0145 
0146             // Don't propagate Esc to the top level, it should be used by konsole
0147             if (k->key() == Qt::Key_Escape) {
0148                 if (d->konsolepart && d->konsolepart->widget()) {
0149                     e->accept();
0150                     return true;
0151                 }
0152             }
0153             break;
0154         }
0155 
0156         default:
0157             break;
0158     }
0159 
0160     return QWidget::eventFilter( obj, e );
0161 }
0162 
0163 #include "moc_kdevkonsoleview.cpp"