File indexing completed on 2024-04-21 05:51:12

0001 /*
0002     SPDX-FileCopyrightText: 2006-2008 Robert Knight <robertknight@gmail.com>
0003     SPDX-FileCopyrightText: 2009 Thomas Dreibholz <dreibh@iem.uni-due.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef SESSIONCONTROLLER_H
0009 #define SESSIONCONTROLLER_H
0010 
0011 // Qt
0012 #include <QPointer>
0013 #include <QRegularExpression>
0014 #include <QSet>
0015 #include <QString>
0016 
0017 // KDE
0018 #include <KXMLGUIClient>
0019 
0020 #include <memory>
0021 
0022 // Konsole
0023 #include "Enumeration.h"
0024 #include "Session.h"
0025 #include "SessionDisplayConnection.h"
0026 #include "ViewProperties.h"
0027 #include "konsoleprivate_export.h"
0028 
0029 class QAction;
0030 class QTextCodec;
0031 class QKeyEvent;
0032 class QTimer;
0033 class QUrl;
0034 
0035 class KCodecAction;
0036 class QAction;
0037 class KActionMenu;
0038 class KSelectAction;
0039 
0040 namespace Konsole
0041 {
0042 class EditProfileDialog;
0043 class EscapeSequenceUrlFilter;
0044 class FileFilter;
0045 class IncrementalSearchBar;
0046 class Profile;
0047 class ProfileList;
0048 class RegExpFilter;
0049 class ScreenWindow;
0050 class Session;
0051 class SessionGroup;
0052 class TerminalDisplay;
0053 class UrlFilter;
0054 class ColorFilter;
0055 class HotSpot;
0056 
0057 /**
0058  * Provides the menu actions to manipulate a single terminal session and view pair.
0059  * The actions provided by this class are defined in the sessionui.rc XML file.
0060  *
0061  * SessionController monitors the session and provides access to basic information
0062  * about the session such as title(), icon() and currentDir().  SessionController
0063  * provides notifications of activity in the session via the activity() signal.
0064  *
0065  * When the controlled view receives the focus, the focused() signal is emitted
0066  * with a pointer to the controller.  This can be used by main application window
0067  * which contains the view to plug the controller's actions into the menu when
0068  * the view is focused.
0069  */
0070 class KONSOLEPRIVATE_EXPORT SessionController : public ViewProperties, public KXMLGUIClient
0071 {
0072     Q_OBJECT
0073 
0074 public:
0075     enum CopyInputToEnum {
0076         /** Copy keyboard input to all the other tabs in current window */
0077         CopyInputToAllTabsMode = 0,
0078 
0079         /** Copy keyboard input to user selected tabs in current window */
0080         CopyInputToSelectedTabsMode = 1,
0081 
0082         /** Do not copy keyboard input to other tabs */
0083         CopyInputToNoneMode = 2,
0084     };
0085 
0086     /**
0087      * Constructs a new SessionController which operates on @p session and @p view.
0088      */
0089     SessionController(Session *session, TerminalDisplay *view, QObject *parent);
0090     ~SessionController() override;
0091 
0092     /** Returns the session associated with this controller */
0093     QPointer<Session> session() const
0094     {
0095         return _sessionDisplayConnection->session();
0096     }
0097 
0098     /** Returns the view associated with this controller */
0099     QPointer<TerminalDisplay> view() const
0100     {
0101         return _sessionDisplayConnection->view();
0102     }
0103 
0104     /**
0105      * Returns the "window title" of the associated session.
0106      */
0107     QString userTitle() const;
0108 
0109     /**
0110      * Returns true if the controller is valid.
0111      * A valid controller is one which has a non-null session() and view().
0112      *
0113      * Equivalent to "!session().isNull() && !view().isNull()"
0114      */
0115     bool isValid() const;
0116 
0117     /** Set the start line from which the next search will be done **/
0118     void setSearchStartTo(int line);
0119 
0120     /** set start line to the first or last line (depending on the reverse search
0121      * setting) in the terminal display **/
0122     void setSearchStartToWindowCurrentLine();
0123 
0124     /**
0125      * Sets the action displayed in the session's context menu to hide or
0126      * show the menu bar.
0127      */
0128     void setShowMenuAction(QAction *action);
0129 
0130     // reimplemented
0131     QUrl url() const override;
0132     QString currentDir() const override;
0133     void rename() override;
0134     bool confirmClose() const override;
0135     virtual bool confirmForceClose() const;
0136 
0137     /** Returns the set of all controllers that exist. */
0138     static QSet<SessionController *> allControllers()
0139     {
0140         return _allControllers;
0141     }
0142 
0143     /* Returns true if called within a KPart; false if called within Konsole. */
0144     bool isKonsolePart() const;
0145     bool isReadOnly() const;
0146     bool isCopyInputActive() const;
0147 
0148     /* Set/reset selection mode */
0149     void setSelectMode(bool mode);
0150 
0151     /* Send notification when a shell prompt is displayed */
0152     void notifyPrompt();
0153 
0154     void setVisible(QString name, bool visible);
0155 
0156     bool isMonitorOnce() const
0157     {
0158         return _monitorOnce;
0159     };
0160 
0161     const SessionGroup *copyToGroup() const
0162     {
0163         return _copyToGroup;
0164     }
0165 
0166     KSelectAction *copyInputActions();
0167 
0168 Q_SIGNALS:
0169     /**
0170      * Emitted when the view associated with the controller is focused.
0171      * This can be used by other classes to plug the controller's actions into a window's
0172      * menus.
0173      */
0174     void viewFocused(SessionController *controller);
0175 
0176     void rawTitleChanged();
0177 
0178     /*
0179      * Emitted when the user requests to split the view from the context menu.
0180      */
0181 
0182     void requestSplitViewLeftRight();
0183     void requestSplitViewTopBotton();
0184 
0185     /**
0186      * Emitted when the current working directory of the session associated with
0187      * the controller is changed.
0188      */
0189     void currentDirectoryChanged(const QString &dir);
0190 
0191     /**
0192      * Emitted when the user changes the tab title.
0193      */
0194     void tabRenamedByUser(bool renamed) const;
0195 
0196     /**
0197      * Emitted when the user changes the tab color.
0198      */
0199     void tabColoredByUser(bool set) const;
0200 
0201     /**
0202      * Emitted when the user request print screen.
0203      */
0204     void requestPrint();
0205 
0206     /**
0207      * Emitted when the TerminalDisplay is drag-and-dropped to a new window.
0208      */
0209     void viewDragAndDropped(SessionController *controller);
0210 
0211 public Q_SLOTS:
0212     /**
0213      * Issues a command to the session to navigate to the specified URL.
0214      * This may not succeed if the foreground program does not understand
0215      * the command sent to it ( 'cd path' for local URLs ) or is not
0216      * responding to input.
0217      *
0218      * openUrl() currently supports urls for local paths and those
0219      * using the 'ssh' protocol ( eg. "ssh://joebloggs@hostname" )
0220      */
0221     void openUrl(const QUrl &url);
0222 
0223     /**
0224      * update actions which are meaningful only when primary screen is in use.
0225      */
0226     void setupPrimaryScreenSpecificActions(bool use);
0227 
0228     /**
0229      * update actions which are closely related with the selected text.
0230      */
0231     void selectionChanged(const bool selectionEmpty);
0232 
0233     /**
0234      * close the associated session. This might involve user interaction for
0235      * confirmation.
0236      */
0237     void closeSession();
0238 
0239     /**  Increase font size */
0240     void increaseFontSize();
0241 
0242     /**  Decrease font size */
0243     void decreaseFontSize();
0244 
0245     /** Reset font size */
0246     void resetFontSize();
0247 
0248     /** Close the incremental search */
0249     void searchClosed(); // called when the user clicks on the
0250 
0251     void copyInputToAllTabs();
0252     void copyInputToSelectedTabs(QList<Session *> *sessions = nullptr);
0253     void copyInputToNone();
0254 
0255 private Q_SLOTS:
0256     // menu item handlers
0257     void openBrowser();
0258     void copy();
0259     void copyInput();
0260     void copyOutput();
0261     void copyInputOutput();
0262     void paste();
0263     void selectAll();
0264     void selectMode();
0265     void selectLine();
0266     void pasteFromX11Selection(); // shortcut only
0267     void copyInputActionsTriggered(QAction *action);
0268     void editCurrentProfile();
0269     void changeCodec(QTextCodec *codec);
0270     void enableSearchBar(bool showSearchBar);
0271     void searchHistory(bool showSearchBar);
0272     void searchBarEvent();
0273     void searchFrom();
0274     void findNextInHistory();
0275     void findPreviousInHistory();
0276     void updateMenuIconsAccordingToReverseSearchSetting();
0277     void changeSearchMatch();
0278     void saveHistory();
0279     void showHistoryOptions();
0280     void clearHistory();
0281     void clearHistoryAndReset();
0282     void monitorOnce(bool once);
0283     void monitorPrompt(bool monitor);
0284     void monitorActivity(bool monitor);
0285     void monitorSilence(bool monitor);
0286     void monitorProcessFinish(bool monitor);
0287     void renameSession();
0288     void switchProfile(const QExplicitlySharedDataPointer<Profile> &profile);
0289 
0290     // Set the action text to either "Edit" or "Create New" Profile
0291     void setEditProfileActionText(const QExplicitlySharedDataPointer<Profile> &profile);
0292     void handleWebShortcutAction(QAction *action);
0293     void configureWebShortcuts();
0294     void sendSignal(QAction *action);
0295     void sendForegroundColor(uint terminator);
0296     void sendBackgroundColor(uint terminator);
0297     void toggleReadOnly(QAction *action);
0298     void toggleAllowMouseTracking(QAction *action);
0299 
0300     // other
0301     void setupSearchBar();
0302     void prepareSwitchProfileMenu();
0303     void updateCodecAction(QTextCodec *codec);
0304     void showDisplayContextMenu(const QPoint &position);
0305     void movementKeyFromSearchBarReceived(QKeyEvent *event);
0306     void sessionNotificationsChanged(Session::Notification notification, bool enabled);
0307     void sessionAttributeChanged();
0308     void sessionReadOnlyChanged();
0309     void searchTextChanged(const QString &text);
0310     void searchCompleted(bool success);
0311 
0312     void updateFilterList(
0313         const QExplicitlySharedDataPointer<Profile> &profile); // Called when the profile has changed, so we might need to change the list of filters
0314 
0315     void viewFocusChangeHandler(bool focused);
0316     void interactionHandler();
0317     void snapshot(); // called periodically as the user types
0318     // to take a snapshot of the state of the
0319     // foreground process in the terminal
0320 
0321     void highlightMatches(bool highlight);
0322     void scrollBackOptionsChanged(int mode, int lines);
0323     void sessionResizeRequest(const QSize &size);
0324     void trackOutput(QKeyEvent *event); // move view to end of current output
0325     // when a key press occurs in the
0326     // display area
0327 
0328     void updateSearchFilter();
0329 
0330     void zmodemDownload();
0331     void zmodemUpload();
0332 
0333     // update actions related with selected text
0334     void updateCopyAction(const bool selectionEmpty);
0335     void updateWebSearchMenu();
0336 
0337 private:
0338     Q_DISABLE_COPY(SessionController)
0339 
0340     // begins the search
0341     // text - pattern to search for
0342     // direction - value from SearchHistoryTask::SearchDirection enum to specify
0343     //             the search direction
0344     void beginSearch(const QString &text, Enum::SearchDirection direction);
0345     QRegularExpression regexpFromSearchBarOptions() const;
0346     bool reverseSearchChecked() const;
0347     void setupCommonActions();
0348     void setupExtraActions();
0349     void removeSearchFilter(); // remove and delete the current search filter if set
0350     void setFindNextPrevEnabled(bool enabled);
0351     void listenForScreenWindowUpdates();
0352 
0353 private:
0354     void updateSessionIcon();
0355     void updateReadOnlyActionStates();
0356 
0357     SessionGroup *_copyToGroup;
0358 
0359     SessionDisplayConnection *_sessionDisplayConnection;
0360 
0361     ProfileList *_profileList;
0362 
0363     QIcon _sessionIcon;
0364     QString _sessionIconName;
0365 
0366     RegExpFilter *_searchFilter;
0367     UrlFilter *_urlFilter;
0368     FileFilter *_fileFilter;
0369     ColorFilter *_colorFilter;
0370 
0371     QAction *_copyInputToAllTabsAction;
0372     KSelectAction *_copyInputActions;
0373 
0374     QAction *_findAction;
0375     QAction *_findNextAction;
0376     QAction *_findPreviousAction;
0377 
0378     QTimer *_interactionTimer;
0379 
0380     int _searchStartLine;
0381     int _prevSearchResultLine;
0382 
0383     KCodecAction *_codecAction;
0384 
0385     KActionMenu *_switchProfileMenu;
0386     KActionMenu *_webSearchMenu;
0387 
0388     bool _listenForScreenWindowUpdates;
0389     bool _preventClose;
0390 
0391     bool _selectionEmpty;
0392     bool _selectionChanged;
0393     QString _selectedText;
0394 
0395     QAction *_showMenuAction;
0396 
0397     static QSet<SessionController *> _allControllers;
0398     static int _lastControllerId;
0399 
0400     QStringList _bookmarkValidProgramsToClear;
0401 
0402     bool _isSearchBarEnabled;
0403 
0404     QString _searchText;
0405     QPointer<IncrementalSearchBar> _searchBar;
0406 
0407     QString _previousForegroundProcessName;
0408     bool _monitorProcessFinish;
0409     bool _monitorOnce;
0410     EscapeSequenceUrlFilter *_escapedUrlFilter;
0411 
0412     std::unique_ptr<KXMLGUIBuilder> _clientBuilder;
0413 
0414     QSharedPointer<HotSpot> _currentHotSpot;
0415 };
0416 
0417 }
0418 
0419 #endif // SESSIONCONTROLLER_H