File indexing completed on 2024-04-28 05:50:56

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 VIEWSPLITTER_H
0008 #define VIEWSPLITTER_H
0009 
0010 // Qt
0011 #include <QSplitter>
0012 #include <QSplitterHandle>
0013 
0014 // Konsole
0015 #include "konsoleprivate_export.h"
0016 
0017 class QDragMoveEvent;
0018 class QDragEnterEvent;
0019 class QDropEvent;
0020 class QDragLeaveEvent;
0021 
0022 namespace Konsole
0023 {
0024 class TerminalDisplay;
0025 
0026 class ViewSplitterHandle : public QSplitterHandle
0027 {
0028     Q_OBJECT
0029 public:
0030     ViewSplitterHandle(Qt::Orientation orientation, QSplitter *parent);
0031 
0032 protected:
0033     void mousePressEvent(QMouseEvent *ev) override;
0034     void mouseReleaseEvent(QMouseEvent *ev) override;
0035     void mouseMoveEvent(QMouseEvent *ev) override;
0036     void mouseDoubleClickEvent(QMouseEvent *ev) override;
0037 
0038 private:
0039     /* For some reason, the first time we double-click on the splitter handle
0040      * the second mouse press event is not fired, nor is the double click event.
0041      * We use this counter to detect a double click. */
0042     int mouseReleaseEventCounter;
0043 };
0044 
0045 /**
0046  * A splitter which holds a number of ViewContainer objects and allows
0047  * the user to control the size of each view container by dragging a splitter
0048  * bar between them.
0049  *
0050  * Each splitter can also contain child ViewSplitter widgets, allowing
0051  * for a hierarchy of view splitters and containers.
0052  *
0053  * The addContainer() method is used to split the existing view and
0054  * insert a new view container.
0055  * Containers can only be removed from the hierarchy by deleting them.
0056  */
0057 class KONSOLEPRIVATE_EXPORT ViewSplitter : public QSplitter
0058 {
0059     Q_OBJECT
0060 
0061 public:
0062     explicit ViewSplitter(QWidget *parent = nullptr);
0063 
0064     enum class AddBehavior {
0065         AddBefore,
0066         AddAfter,
0067     };
0068     /**
0069      * Locates the child ViewSplitter widget which currently has the focus
0070      * and inserts the container into it.
0071      *
0072      * @param terminalDisplay The container to insert
0073      * @param containerOrientation Specifies whether the view should be split
0074      *                    horizontally or vertically.  If the orientation
0075      *                    is the same as the ViewSplitter into which the
0076      *                    container is to be inserted, or if the splitter
0077      *                    has fewer than two child widgets then the container
0078      *                    will be added to that splitter.  If the orientation
0079      *                    is different, then a new child splitter
0080      *                    will be created, into which the container will
0081      *                    be inserted.
0082      * @param behavior Specifies whether to add new terminal after current
0083      *                 tab or at end.
0084      */
0085     void addTerminalDisplay(TerminalDisplay *terminalDisplay, Qt::Orientation containerOrientation, AddBehavior behavior = AddBehavior::AddAfter);
0086 
0087     void addTerminalDisplay(TerminalDisplay *terminalDisplay, int index = -1);
0088 
0089     void addSplitter(ViewSplitter *splitter, int index = -1);
0090 
0091     /** Returns the child ViewSplitter widget which currently has the focus */
0092     ViewSplitter *activeSplitter();
0093 
0094     /**
0095      * Returns the container which currently has the focus or 0 if none
0096      * of the immediate child containers have the focus.  This does not
0097      * search through child splitters.  activeSplitter() can be used
0098      * to search recursively through child splitters for the splitter
0099      * which currently has the focus.
0100      *
0101      * To find the currently active container, use
0102      * mySplitter->activeSplitter()->activeTerminalDisplay() where
0103      * mySplitter is the ViewSplitter widget at the top of the hierarchy.
0104      */
0105     TerminalDisplay *activeTerminalDisplay() const;
0106 
0107     /** Makes the current TerminalDisplay expanded to 100% of the view
0108      */
0109     void toggleMaximizeCurrentTerminal();
0110 
0111     /** Makes the current TerminalDisplay expanded to 100% of the view, while
0112      * scaling the font size
0113      */
0114     void toggleZoomMaximizeCurrentTerminal();
0115 
0116     /**
0117      * Can be called on any ViewSplitter to find the top level splitter and ensure
0118      * the active display isn't maximized. Do nothing if it's not maximized.
0119      *
0120      * Useful for ViewManager and TabbedViewContainer when removing or adding a
0121      * display to the hierarchy so that the layout is reflowed correctly.
0122      */
0123     void clearMaximized();
0124 
0125     /** returns the splitter that has no splitter as a parent. */
0126     ViewSplitter *getToplevelSplitter();
0127 
0128     ViewSplitter *getChildSplitter(int id);
0129 
0130     QString getChildWidgetsLayout();
0131 
0132     /**
0133      * Changes the size of the specified @p container by a given @p percentage.
0134      * @p percentage may be positive ( in which case the size of the container
0135      * is increased ) or negative ( in which case the size of the container
0136      * is decreased ).
0137      *
0138      * The sizes of the remaining containers are increased or decreased
0139      * uniformly to maintain the width of the splitter.
0140      */
0141     void adjustActiveTerminalDisplaySize(int percentage);
0142 
0143     void focusUp();
0144     void focusDown();
0145     void focusLeft();
0146     void focusRight();
0147 
0148     void handleFocusDirection(Qt::Orientation orientation, int direction);
0149 
0150     void childEvent(QChildEvent *event) override;
0151     bool terminalMaximized() const
0152     {
0153         return m_terminalMaximized;
0154     }
0155 
0156     QSplitterHandle *createHandle() override;
0157 
0158     QPoint mapToTopLevel(const QPoint &p);
0159     QPoint mapFromTopLevel(const QPoint &p);
0160 
0161     int id() const
0162     {
0163         return _id;
0164     }
0165 
0166 protected:
0167     void dragEnterEvent(QDragEnterEvent *ev) override;
0168     void dragMoveEvent(QDragMoveEvent *ev) override;
0169     void dragLeaveEvent(QDragLeaveEvent *event) override;
0170     void dropEvent(QDropEvent *ev) override;
0171     void showEvent(QShowEvent *) override;
0172 
0173 Q_SIGNALS:
0174     void terminalDisplayDropped(TerminalDisplay *terminalDisplay);
0175 
0176 private:
0177     /** recursively walks the object tree looking for Splitters and
0178      * TerminalDisplays, hiding the ones that should be hidden.
0179      * If a terminal display is not hidden in a subtree, we cannot
0180      * hide the whole tree.
0181      *
0182      * @p currentTerminalDisplay the only terminal display that will still be visible.
0183      */
0184     bool hideRecurse(TerminalDisplay *currentTerminalDisplay);
0185 
0186     /** other classes should use clearmMaximized() */
0187     void handleMinimizeMaximize(bool maximize, bool zoom);
0188 
0189     void updateSizes();
0190     bool m_terminalMaximized = false;
0191     qreal fontSizeBeforeMaximization = 0;
0192     bool m_blockPropagatedDeletion = false;
0193 
0194     int _id;
0195 
0196     static bool m_drawTopLevelHandler;
0197     static Qt::Orientation m_topLevelHandlerDrawnOrientation;
0198     static int lastSplitterId;
0199 };
0200 }
0201 #endif // VIEWSPLITTER_H