File indexing completed on 2024-04-14 05:44:15
0001 /* 0002 SPDX-FileCopyrightText: 2006-2008 Robert Knight <robertknight@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef VIEWMANAGER_H 0008 #define VIEWMANAGER_H 0009 0010 // Qt 0011 #include <QAction> 0012 #include <QHash> 0013 #include <QObject> 0014 #include <QPointer> 0015 0016 #include "konsoleprivate_export.h" 0017 // Konsole 0018 0019 class KActionCollection; 0020 class KConfigGroup; 0021 0022 namespace Konsole 0023 { 0024 class ColorScheme; 0025 class Profile; 0026 class Session; 0027 class SessionController; 0028 class TabbedViewContainer; 0029 class TabbedViewContainer; 0030 class TerminalDisplay; 0031 class ViewProperties; 0032 class ViewSplitter; 0033 0034 /** 0035 * Manages the terminal display widgets in a Konsole window or part. 0036 * 0037 * When a view manager is created, it constructs a tab widget ( accessed via 0038 * widget() ) to hold one or more view splitters. Each view splitter holds 0039 * one or more terminal displays and splitters. 0040 * 0041 * The view manager provides menu actions ( defined in the 'konsoleui.rc' XML file ) 0042 * to manipulate the views and view containers - for example, actions to split the view 0043 * left/right or top/bottom, detach a view from the current window and navigate between 0044 * views and containers. These actions are added to the collection specified in the 0045 * ViewManager's constructor. 0046 * 0047 * The view manager provides facilities to construct display widgets for a terminal 0048 * session and also to construct the SessionController which provides the menus and other 0049 * user interface elements specific to each display/session pair. 0050 * 0051 */ 0052 class KONSOLEPRIVATE_EXPORT ViewManager : public QObject 0053 { 0054 Q_OBJECT 0055 Q_CLASSINFO("D-Bus Interface", "org.kde.konsole.Window") 0056 0057 public: 0058 /** 0059 * Constructs a new view manager with the specified @p parent. 0060 * View-related actions defined in 'konsoleui.rc' are created 0061 * and added to the specified @p collection. 0062 */ 0063 ViewManager(QObject *parent, KActionCollection *collection); 0064 ~ViewManager() override; 0065 0066 /** 0067 * Creates a new view to display the output from and deliver input to @p session. 0068 * Constructs a new container to hold the views if no container has yet been created. 0069 */ 0070 void createView(TabbedViewContainer *tabWidget, Session *session); 0071 0072 /* 0073 * Applies the view-specific settings associated with specified @p profile 0074 * to the terminal display @p view. 0075 */ 0076 void applyProfileToView(TerminalDisplay *view, const QExplicitlySharedDataPointer<Profile> &profile); 0077 0078 void toggleActionsBasedOnState(); 0079 /** 0080 * Return the main widget for the view manager which 0081 * holds all of the views managed by this ViewManager instance. 0082 */ 0083 QWidget *widget() const; 0084 0085 /** 0086 * Returns the view manager's active view. 0087 */ 0088 QWidget *activeView() const; 0089 0090 /** 0091 * Returns the list of view properties for views in the active container. 0092 * Each view widget is associated with a ViewProperties instance which 0093 * provides access to basic information about the session being 0094 * displayed in the view, such as title, current directory and 0095 * associated icon. 0096 */ 0097 QList<ViewProperties *> viewProperties() const; 0098 0099 /** 0100 * This enum describes the available types of navigation widget 0101 * which newly created containers can provide to allow navigation 0102 * between open sessions. 0103 */ 0104 enum NavigationMethod { 0105 /** 0106 * Each container has a row of tabs (one per session) which the user 0107 * can click on to navigate between open sessions. 0108 */ 0109 TabbedNavigation, 0110 /** The container has no navigation widget. */ 0111 NoNavigation, 0112 }; 0113 0114 /** 0115 * Describes the options for showing or hiding the container's navigation widget. 0116 */ 0117 enum NavigationVisibility { 0118 NavigationNotSet, // Don't rely on this information, Only use the settings. 0119 AlwaysShowNavigation, 0120 ShowNavigationAsNeeded, 0121 AlwaysHideNavigation, 0122 }; 0123 0124 /** 0125 * Sets the visibility of the view container's navigation widget. 0126 * The ViewContainer subclass is responsible for ensuring that this 0127 * setting is respected as views are dded or removed from the container 0128 */ 0129 void setNavigationVisibility(NavigationVisibility navigationVisibility); 0130 0131 /** Returns the current mode for controlling the visibility of the 0132 * view container's navigation widget. 0133 */ 0134 NavigationVisibility navigationVisibility() const; 0135 0136 /** 0137 * Sets the type of widget provided to navigate between open sessions 0138 * in a container. The changes will only apply to newly created containers. 0139 * 0140 * The default method is TabbedNavigation. To disable navigation widgets, call 0141 * setNavigationMethod(ViewManager::NoNavigation) before creating any sessions. 0142 */ 0143 void setNavigationMethod(NavigationMethod method); 0144 0145 /** 0146 * Returns the type of navigation widget created in new containers. 0147 * See setNavigationMethod() 0148 */ 0149 NavigationMethod navigationMethod() const; 0150 0151 /** 0152 * Returns the controller for the active view. activeViewChanged() is 0153 * emitted when this changes. 0154 */ 0155 SessionController *activeViewController() const; 0156 0157 /** 0158 * Session management 0159 */ 0160 void saveSessions(KConfigGroup &group); 0161 void restoreSessions(const KConfigGroup &group); 0162 0163 int managerId() const; 0164 0165 /** Returns a list of sessions in this ViewManager */ 0166 QList<Session *> sessions() 0167 { 0168 return _sessionMap.values(); 0169 } 0170 0171 /** 0172 * Returns whether the @p profile has the blur setting enabled 0173 */ 0174 static bool profileHasBlurEnabled(const QExplicitlySharedDataPointer<Profile> &profile); 0175 0176 /** returns the active tab from the view 0177 */ 0178 TabbedViewContainer *activeContainer(); 0179 TerminalDisplay *createView(Session *session); 0180 void attachView(TerminalDisplay *terminal, Session *session); 0181 0182 static std::shared_ptr<const ColorScheme> colorSchemeForProfile(const QExplicitlySharedDataPointer<Profile> &profile); 0183 /** Reorder the terminal display history list */ 0184 void updateTerminalDisplayHistory(TerminalDisplay *terminalDisplay = nullptr, bool remove = false); 0185 0186 QHash<TerminalDisplay *, Session *> forgetAll(ViewSplitter *splitter); 0187 Session *forgetTerminal(TerminalDisplay *terminal); 0188 0189 /** 0190 * Creates and returns new session 0191 * 0192 * The session has specified @p profile, working @p directory 0193 * and configured environment. 0194 */ 0195 Session *createSession(const QExplicitlySharedDataPointer<Profile> &profile, const QString &directory = QString()); 0196 0197 Q_SIGNALS: 0198 /** Emitted when the last view is removed from the view manager */ 0199 void empty(); 0200 0201 /** Emitted when a session is detached from a view owned by this ViewManager */ 0202 void terminalsDetached(ViewSplitter *splitter, QHash<TerminalDisplay *, Session *> sessionsMap); 0203 0204 /** 0205 * Emitted when the active view changes. 0206 * @param controller The controller associated with the active view 0207 */ 0208 void activeViewChanged(SessionController *controller); 0209 0210 /** 0211 * Emitted when the current session needs unplugged from factory(). 0212 * @param controller The controller associated with the active view 0213 */ 0214 void unplugController(SessionController *controller); 0215 0216 /** 0217 * Emitted when the list of view properties ( as returned by viewProperties() ) changes. 0218 * This occurs when views are added to or removed from the active container, or 0219 * if the active container is changed. 0220 */ 0221 void viewPropertiesChanged(const QList<ViewProperties *> &propertiesList); 0222 0223 /** 0224 * Emitted when menu bar visibility changes because a profile that requires so is 0225 * activated. 0226 */ 0227 void setMenuBarVisibleRequest(bool); 0228 void updateWindowIcon(); 0229 0230 void blurSettingChanged(bool); 0231 0232 /** Requests creation of a new view with the default profile. */ 0233 void newViewRequest(); 0234 /** Requests creation of a new view, with the selected profile. */ 0235 void newViewWithProfileRequest(const QExplicitlySharedDataPointer<Profile> &profile); 0236 0237 void activationRequest(const QString &xdgActivationToken); 0238 0239 public Q_SLOTS: 0240 /** DBus slot that returns the number of sessions in the current view. */ 0241 Q_SCRIPTABLE int sessionCount(); 0242 0243 /** 0244 * DBus slot that returns the unique ids of the sessions in the 0245 * current view. The returned list is ordered by tab. 0246 * QList<int> is not printable by qdbus so we use QStringList 0247 * Example: 0248 * A) create tab, create tab 2, create tab 3, go to tab 2, split view 0249 * sessionList() returns 1 4 2 3 0250 * B) create tab, create tab 2, split view, create tab 3 0251 * sessionList() returns 1 3 2 4 0252 */ 0253 Q_SCRIPTABLE QStringList sessionList(); 0254 0255 /** DBus slot that returns the current (active) session window */ 0256 Q_SCRIPTABLE int currentSession(); 0257 0258 /** DBus slot that sets the current (active) session window */ 0259 Q_SCRIPTABLE void setCurrentSession(int sessionId); 0260 0261 /** DBus slot that creates a new session in the current view with the associated 0262 * default profile and the default working directory 0263 */ 0264 Q_SCRIPTABLE int newSession(); 0265 0266 /** DBus slot that creates a new session in the current view. 0267 * @param profile the name of the profile to be used 0268 * started. 0269 */ 0270 Q_SCRIPTABLE int newSession(const QString &profile); 0271 0272 /** DBus slot that creates a new session in the current view. 0273 * @param profile the name of the profile to be used 0274 * @param directory the working directory where the session is 0275 * started. 0276 */ 0277 Q_SCRIPTABLE int newSession(const QString &profile, const QString &directory); 0278 0279 // TODO: its semantic is application-wide. Move it to more appropriate place 0280 // DBus slot that returns the name of default profile 0281 Q_SCRIPTABLE QString defaultProfile(); 0282 0283 // TODO: its semantic is application-wide. Move it to more appropriate place 0284 // DBus slot that sets the default profile 0285 Q_SCRIPTABLE void setDefaultProfile(const QString &profile); 0286 0287 // TODO: its semantic is application-wide. Move it to more appropriate place 0288 // DBus slot that returns a string list of defined (known) profiles 0289 Q_SCRIPTABLE QStringList profileList(); 0290 0291 /** DBus slot that changes the view port to the next session */ 0292 Q_SCRIPTABLE void nextSession(); 0293 0294 /** DBus slot that changes the view port to the previous session */ 0295 Q_SCRIPTABLE void prevSession(); 0296 0297 /** DBus slot that switches the current session (as returned by 0298 * currentSession()) with the left (or previous) one in the 0299 * navigation tab. 0300 */ 0301 Q_SCRIPTABLE void moveSessionLeft(); 0302 0303 /** DBus slot that Switches the current session (as returned by 0304 * currentSession()) with the right (or next) one in the navigation 0305 * tab. 0306 */ 0307 Q_SCRIPTABLE void moveSessionRight(); 0308 0309 /** DBus slot that sets ALL tabs' width to match their text */ 0310 Q_SCRIPTABLE void setTabWidthToText(bool); 0311 0312 // Creates json file with split config 0313 Q_SCRIPTABLE void saveLayoutFile(); 0314 Q_SCRIPTABLE void loadLayoutFile(); 0315 Q_SCRIPTABLE void loadLayout(QString File); 0316 0317 /** DBus slot that returns a description of the layout hierarchy 0318 * in each tab. 0319 * 0320 * A ViewSplitter is described by its id enclosed in round brackets, 0321 * followed by square (horizontal split) or curly (vertical split) 0322 * brackets. Format: (%id)[...] OR (%id){...} 0323 * 0324 * A TerminalDisplay is simply described by its id. 0325 * 0326 * The child widgets of a ViewSplitter are described in the square or 0327 * curly brackets using their ids and are separated by '|'. The 0328 * order which they are described in is top to bottom for vertical 0329 * split or left to right for horizontal split. 0330 */ 0331 Q_SCRIPTABLE QStringList viewHierarchy(); 0332 0333 /** DBus slot that returns the sizes of the direct child widgets as 0334 * percentages of the size of the ViewSplitter in the form of a 0335 * list. Will return an empty list if a splitter with id splitterId 0336 * cannot be found. 0337 */ 0338 Q_SCRIPTABLE QList<double> getSplitProportions(int splitterId); 0339 0340 /** DBus slot that splits an existing view in the current tab **/ 0341 Q_SCRIPTABLE bool createSplit(int viewId, bool horizontalSplit); 0342 0343 /** DBus slot that creates a splitter containing a series of 0344 * existing widgets and inserts it at an index in an existing splitter. 0345 * 0346 * Each element in widgetInfos is QString of format "x-y", describing 0347 * each moved widget. Regarding the to-be-created splitter, the first 0348 * QString will represent the leftmost widget (horizontal split) 0349 * or the topmost widget (vertical split). x is either 's' 0350 * for a ViewSplitter or 'v' for a TerminalDisplay. y is the id of 0351 * the widget. 0352 */ 0353 Q_SCRIPTABLE bool createSplitWithExisting(int targetSplitterId, QStringList widgetInfos, int idx, bool horizontalSplit); 0354 0355 /** DBus slot that focuses a view. **/ 0356 Q_SCRIPTABLE bool setCurrentView(int viewId); 0357 0358 /** DBus slot that allows setting of the relative sizes of widgets 0359 * in a splitter by specifying their percentages. 0360 */ 0361 /* NOTE: not all ways of calling dbus can handle "ad" QList<double> 0362 Does not work AFAIK: qdbus6, qdbusviewer6, busctl 0363 Works: dbus-send, gdbus 0364 Example: 0365 dbus-send --session --print-reply=literal --type=method_call --dest=org.kde.konsole-16710 /Windows/1 org.kde.konsole.Window.resizeSplits int32:0 array:double:40.0,60.0 0366 gdbus call --session --dest org.kde.konsole-16710 --object-path /Windows/1 --method org.kde.konsole.Window.resizeSplits 0 "[10.5, 89.5]" 0367 */ 0368 Q_SCRIPTABLE bool resizeSplits(int splitterId, QList<double> percentages); 0369 0370 /** DBus slot that moves a splitter to a different position under a specified splitter**/ 0371 Q_SCRIPTABLE bool moveSplitter(int splitterId, int targetSplitterId, int idx); 0372 0373 /** DBus slot that move a view to a different position under a specified splitter**/ 0374 Q_SCRIPTABLE bool moveView(int viewId, int targetSplitterId, int idx); 0375 0376 private Q_SLOTS: 0377 // called when the "Split View Left/Right" menu item is selected 0378 void splitLeftRight(); 0379 void splitTopBottom(); 0380 void splitAuto(bool fromNextTab = false); 0381 void splitLeftRightNextTab(); 0382 void splitTopBottomNextTab(); 0383 void splitAutoNextTab(); 0384 void expandActiveContainer(); 0385 void shrinkActiveContainer(); 0386 void equalSizeAllContainers(); 0387 0388 // called when the "Detach View" menu item is selected 0389 void detachActiveView(); 0390 void detachActiveTab(); 0391 0392 // called when a session terminates - the view manager will delete any 0393 // views associated with the session 0394 void sessionFinished(Session *session); 0395 // called when one view has been destroyed 0396 void viewDestroyed(QWidget *view); 0397 0398 // controller detects when an associated view is given the focus 0399 // and emits a signal. ViewManager listens for that signal 0400 // and then plugs the action into the UI 0401 // void viewFocused( SessionController* controller ); 0402 0403 // called when the active view in a ViewContainer changes, so 0404 // that we can plug the appropriate actions into the UI 0405 void activateView(TerminalDisplay *view); 0406 0407 void focusUp(); 0408 void focusDown(); 0409 void focusLeft(); 0410 void focusRight(); 0411 0412 // called when "Next View" shortcut is activated 0413 void nextView(); 0414 0415 // called when "Previous View" shortcut is activated 0416 void previousView(); 0417 0418 // called when "Switch to last tab" shortcut is activated 0419 void lastView(); 0420 0421 // called when "Switch to last used tab" shortcut is activated 0422 void lastUsedView(); 0423 0424 // called when "Switch to last used tab (reverse)" shortcut is activated 0425 void lastUsedViewReverse(); 0426 0427 // called when "Next View Container" shortcut is activated 0428 void nextContainer(); 0429 0430 // called when "Toggle Two tabs" shortcut is activated 0431 void toggleTwoViews(); 0432 0433 // called when the views in a container owned by this view manager 0434 // changes 0435 void containerViewsChanged(TabbedViewContainer *container); 0436 0437 // called when a profile changes 0438 void profileChanged(const QExplicitlySharedDataPointer<Profile> &profile); 0439 0440 void updateViewsForSession(Session *session); 0441 0442 // moves active view to the left 0443 void moveActiveViewLeft(); 0444 // moves active view to the right 0445 void moveActiveViewRight(); 0446 // switches to the view at visual position 'index' 0447 // in the current container 0448 void switchToView(int index); 0449 // gives focus and switches the terminal display, changing tab if needed 0450 void switchToTerminalDisplay(TerminalDisplay *terminalDisplay); 0451 0452 // called when a SessionController gains focus 0453 void controllerChanged(SessionController *controller); 0454 0455 /** 0456 * Disconnect this ViewManager and MainWindow from @p controller 0457 * and its associated view/session pair such as after a split-view 0458 * has been drag-and-dropped to a new window. 0459 */ 0460 void forgetController(SessionController *controller); 0461 0462 /* Detaches the tab at index tabIdx */ 0463 void detachTab(int tabIdx); 0464 0465 void semanticSetupBash(); 0466 0467 void toggleSemanticHints(); 0468 0469 void toggleLineNumbers(); 0470 0471 private: 0472 Q_DISABLE_COPY(ViewManager) 0473 0474 TerminalDisplay *findTerminalDisplay(int viewId); 0475 0476 void setCurrentView(TerminalDisplay *view); 0477 0478 void createView(Session *session, TabbedViewContainer *container, int index); 0479 0480 void setupActions(); 0481 0482 // takes a view from a view container owned by a different manager and places it in 0483 // newContainer owned by this manager 0484 void takeView(ViewManager *otherManager, TabbedViewContainer *otherContainer, TabbedViewContainer *newContainer, TerminalDisplay *view); 0485 void splitView(Qt::Orientation orientation, bool fromNextTab = false); 0486 0487 // creates a new container which can hold terminal displays 0488 TabbedViewContainer *createContainer(); 0489 0490 // creates a new terminal display 0491 // the 'session' is used so that the terminal display's random seed 0492 // can be set to something which depends uniquely on that session 0493 TerminalDisplay *createTerminalDisplay(Session *session = nullptr); 0494 0495 // creates a new controller for a session/display pair which provides the menu 0496 // actions associated with that view, and exposes basic information 0497 // about the session ( such as title and associated icon ) to the display. 0498 SessionController *createController(Session *session, TerminalDisplay *view); 0499 void removeController(SessionController *controller); 0500 0501 // Activates a different terminal when the TerminalDisplay 0502 // closes or is detached and another one should be focused. 0503 // It will activate the last used terminal within the same splitView 0504 // if possible otherwise it will focus the last used tab 0505 void focusAnotherTerminal(ViewSplitter *toplevelSplitter); 0506 0507 void activateLastUsedView(bool reverse); 0508 0509 void registerTerminal(TerminalDisplay *terminal); 0510 void unregisterTerminal(TerminalDisplay *terminal); 0511 0512 private: 0513 QPointer<TabbedViewContainer> _viewContainer; 0514 QPointer<SessionController> _pluggedController; 0515 0516 QHash<TerminalDisplay *, Session *> _sessionMap; 0517 0518 KActionCollection *_actionCollection; 0519 0520 NavigationMethod _navigationMethod; 0521 NavigationVisibility _navigationVisibility; 0522 int _managerId; 0523 static int lastManagerId; 0524 QList<TerminalDisplay *> _terminalDisplayHistory; 0525 int _terminalDisplayHistoryIndex; 0526 0527 // List of actions that should only be enabled when there are multiple view 0528 // containers open 0529 QList<QAction *> _multiTabOnlyActions; 0530 QList<QAction *> _multiSplitterOnlyActions; 0531 }; 0532 } 0533 0534 #endif