File indexing completed on 2024-04-28 05:49:35

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org>
0003    SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org>
0004    SPDX-FileCopyrightText: 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
0005 
0006    SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #pragma once
0010 
0011 #include <ktexteditor/document.h>
0012 #include <ktexteditor/view.h>
0013 
0014 #include "doc_or_widget.h"
0015 #include "kateprivate_export.h"
0016 #include "katetabbar.h"
0017 
0018 #include <QWidget>
0019 
0020 class KConfigBase;
0021 class KateViewManager;
0022 class QStackedWidget;
0023 class QToolButton;
0024 class LocationHistoryTest;
0025 class KToggleAction;
0026 
0027 class KATE_PRIVATE_EXPORT KateViewSpace : public QWidget
0028 {
0029     Q_OBJECT
0030 
0031     friend class LocationHistoryTest;
0032     friend class KateViewManagementTests;
0033 
0034 public:
0035     explicit KateViewSpace(KateViewManager *, QWidget *parent = nullptr, const char *name = nullptr);
0036 
0037     ~KateViewSpace() override;
0038 
0039     /**
0040      * Returns \e true, if this view space is currently the active view space.
0041      */
0042     bool isActiveSpace() const;
0043 
0044     /**
0045      * Depending on @p active, mark this view space as active or inactive.
0046      * Called from the view manager.
0047      */
0048     void setActive(bool active);
0049 
0050     /**
0051      * @return the view manager that this viewspace belongs to
0052      */
0053     KateViewManager *viewManager() const
0054     {
0055         return m_viewManager;
0056     }
0057 
0058     /**
0059      * Create new view for given document
0060      * @param doc document to create view for
0061      * @return new created view
0062      */
0063     KTextEditor::View *createView(KTextEditor::Document *doc);
0064     void removeView(KTextEditor::View *v);
0065 
0066     bool showView(KTextEditor::View *view)
0067     {
0068         return showView(view->document());
0069     }
0070     bool showView(DocOrWidget);
0071 
0072     // might be nullptr, if there is no view
0073     KTextEditor::View *currentView();
0074 
0075     void saveConfig(KConfigBase *config, int myIndex, const QString &viewConfGrp);
0076     void restoreConfig(KateViewManager *viewMan, const KConfigBase *config, const QString &group);
0077 
0078     /**
0079      * Returns the document list of this tab bar.
0080      * @return document list in order of tabs
0081      */
0082     QList<DocOrWidget> documentList() const
0083     {
0084         return m_tabBar->documentList();
0085     }
0086 
0087     int tabCount() const
0088     {
0089         return m_tabBar->count();
0090     }
0091 
0092     /**
0093      * How many documents are registered here?
0094      */
0095     int numberOfRegisteredDocuments() const
0096     {
0097         return m_registeredDocuments.size();
0098     }
0099 
0100     /**
0101      * Register one document for this view space.
0102      * Each registered document will get e.g. a tab bar button.
0103      */
0104     void registerDocument(KTextEditor::Document *doc);
0105 
0106     /**
0107      * closes the view of the provided doc in this viewspace
0108      */
0109     void closeDocument(KTextEditor::Document *doc);
0110 
0111     /*
0112      * Does this viewspace contain @p doc
0113      */
0114     bool hasDocument(DocOrWidget doc) const;
0115 
0116     bool hasViewForDocument(KTextEditor::Document *doc) const
0117     {
0118         return m_docToView.find(doc) != m_docToView.end();
0119     }
0120 
0121     /**
0122      * Removes @p doc from this space and returns the associated
0123      * view or a widget
0124      * Used for dnd
0125      */
0126     QWidget *takeView(DocOrWidget);
0127 
0128     /**
0129      * Adds @p view to this space
0130      * Used for dnd to add a view from another viewspace
0131      */
0132     void addView(QWidget *w);
0133 
0134     /**
0135      * Event filter to catch events from view space tool buttons.
0136      */
0137     bool eventFilter(QObject *obj, QEvent *event) override;
0138 
0139     /**
0140      * Focus the previous tab in the tabbar.
0141      */
0142     void focusPrevTab();
0143 
0144     /**
0145      * Focus the next tab in the tabbar.
0146      */
0147     void focusNextTab();
0148 
0149     /**
0150      * Add a non KTE-View as a tab
0151      */
0152     void addWidgetAsTab(QWidget *widget);
0153 
0154     /**
0155      * Does this viewspace contain any not KTextEditor::View widgets?
0156      */
0157     bool hasWidgets() const;
0158 
0159     /**
0160      * Does the current tab contains a widget
0161      * that is not a KTextEditor::View
0162      *
0163      * If the current active tab has a KTE::View
0164      * this will return nullptr
0165      */
0166     QWidget *currentWidget();
0167 
0168     /// Returns all non-KTE::View widgets
0169     QWidgetList widgets() const;
0170 
0171     bool closeTabWithWidget(QWidget *widget);
0172 
0173     bool activateWidget(QWidget *widget);
0174 
0175     // BEGIN Location History Stuff
0176 
0177     /**
0178      * go forward in location history
0179      */
0180     void goForward();
0181 
0182     /**
0183      * go back in location history
0184      */
0185     void goBack();
0186 
0187     /**
0188      * Is back history avail?
0189      */
0190     bool isHistoryBackEnabled() const;
0191 
0192     /**
0193      * Is forward history avail?
0194      */
0195     bool isHistoryForwardEnabled() const;
0196 
0197     /**
0198      * Add a jump location for jumping back and forth between history
0199      */
0200     void addPositionToHistory(const QUrl &url, KTextEditor::Cursor, bool calledExternally = false);
0201 
0202     // END Location History Stuff
0203 
0204     void focusNavigationBar();
0205 
0206     // ensure we have a view for the current document tab, e.g. after document closing
0207     void ensureViewForCurrentTab()
0208     {
0209         // just trigger change view, will do the needful
0210         changeView(m_tabBar->currentIndex());
0211     }
0212 
0213 protected:
0214     // DND
0215     void dragEnterEvent(QDragEnterEvent *e) override;
0216     void dragLeaveEvent(QDragLeaveEvent *e) override;
0217     void dropEvent(QDropEvent *e) override;
0218 
0219 Q_SIGNALS:
0220     void viewSpaceEmptied(KateViewSpace *vs);
0221 
0222 public Q_SLOTS:
0223     void documentDestroyed(QObject *doc);
0224     void updateDocumentName(KTextEditor::Document *doc);
0225     void updateDocumentUrl(KTextEditor::Document *doc);
0226 
0227 private Q_SLOTS:
0228     void tabBarToggled();
0229     void urlBarToggled(bool);
0230     void changeView(int buttonId);
0231 
0232     /**
0233      * Save @p v config
0234      * This function is called when closing the view
0235      * When the viewspace itself saves its config, it doesn't use this function
0236      */
0237     void saveViewConfig(KTextEditor::View *v);
0238 
0239     /**
0240      * Calls this slot to make this view space the currently active view space.
0241      * Making it active goes through the KateViewManager.
0242      * @param focusCurrentView if @e true, the current view will get focus
0243      */
0244     void makeActive(bool focusCurrentView = true);
0245 
0246     /**
0247      * This slot is called by the tabbar, if tab @p id was closed through the
0248      * context menu.
0249      */
0250     void closeTabRequest(int id);
0251 
0252     /**
0253      * This slot is called when the context menu is requested for button
0254      * @p id at position @p globalPos.
0255      * @param id the button, or -1 if the context menu was requested on
0256      *        at a place where no tab exists
0257      * @param globalPos the position of the context menu in global coordinates
0258      */
0259     void showContextMenu(int id, const QPoint &globalPos);
0260 
0261     /**
0262      * Called to create a new empty document.
0263      */
0264     void createNewDocument();
0265 
0266     /**
0267      * Read and apply the config for this view space.
0268      */
0269     void readConfig();
0270 
0271     /**
0272      * Document created or deleted, used to auto hide/show the tabs
0273      */
0274     void updateTabBar();
0275 
0276 private:
0277     bool acceptsDroppedTab(const class QMimeData *tabMimeData);
0278     /**
0279      * Returns the amount of documents in KateDocManager that currently
0280      * have no tab in this tab bar.
0281      */
0282     int hiddenDocuments() const;
0283 
0284     // The following functions are for unit-testing purposes
0285     size_t &currentLoc()
0286     {
0287         return currentLocation;
0288     }
0289 
0290     auto &locationHistoryBuffer()
0291     {
0292         return m_locations;
0293     }
0294 
0295     void removeWidget(QWidget *w);
0296 
0297 private:
0298     // Kate's view manager
0299     KateViewManager *m_viewManager;
0300 
0301     // config group string, used for restoring View session configuration
0302     QString m_group;
0303 
0304     // flag that indicates whether this view space is the active one.
0305     // correct setter: m_viewManager->setActiveSpace(this);
0306     bool m_isActiveSpace;
0307 
0308     // widget stack that contains all KTE::Views
0309     QStackedWidget *stack;
0310 
0311     // jump location history for this view-space
0312     struct Location {
0313         QUrl url;
0314         KTextEditor::Cursor cursor;
0315     };
0316 
0317     std::vector<Location> m_locations;
0318     size_t currentLocation = 0;
0319 
0320     /**
0321      * all documents this view space is aware of
0322      * depending on the limit of tabs, not all will have a corresponding
0323      * tab in the KateTabBar
0324      * these are stored in used order (MRU last)
0325      */
0326     QList<DocOrWidget> m_registeredDocuments;
0327 
0328     // the list of views that are contained in this view space,
0329     // mapped through a hash from Document to View.
0330     // note: the number of entries match stack->count();
0331     std::unordered_map<KTextEditor::Document *, KTextEditor::View *> m_docToView;
0332 
0333     // tab bar that contains viewspace tabs
0334     KateTabBar *m_tabBar;
0335 
0336     // split action
0337     QToolButton *m_split;
0338 
0339     // quick open action
0340     QToolButton *m_quickOpen;
0341 
0342     // go back in history button (only visible when the tab bar is visible)
0343     QToolButton *m_historyBack;
0344 
0345     // go forward in history button (only visible when the tab bar is visible)
0346     QToolButton *m_historyForward;
0347 
0348     // rubber band to indicate drag and drop
0349     std::unique_ptr<class QRubberBand> m_dropIndicator;
0350 
0351     class KateUrlBar *m_urlBar = nullptr;
0352 
0353     struct TopBarLayout {
0354         class QHBoxLayout *tabBarLayout = nullptr;
0355         class QVBoxLayout *mainLayout = nullptr;
0356     } m_layout;
0357 
0358     // should the tab bar be auto hidden if just one document is open?
0359     bool m_autoHideTabBar = false;
0360 
0361     // Block adding position to history if this is true
0362     bool m_blockAddHistory = false;
0363 
0364     // Option in Split Views toolButton menu to
0365     // Synchronise (vertical) scrollbars of the active view
0366     KToggleAction *m_toggleSynchronisedScrolling;
0367 };