File indexing completed on 2024-04-28 05:49:30
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 "katemdi.h" 0012 #include "kateviewmanager.h" 0013 0014 #include <ktexteditor/document.h> 0015 #include <ktexteditor/mainwindow.h> 0016 #include <ktexteditor/view.h> 0017 0018 #include <KIO/UDSEntry> 0019 #include <KParts/Part> 0020 0021 #include <QDragEnterEvent> 0022 #include <QDropEvent> 0023 #include <QEvent> 0024 #include <QHash> 0025 #include <QStackedLayout> 0026 #include <QUrl> 0027 0028 class QMenu; 0029 0030 namespace KIO 0031 { 0032 class UDSEntry; 0033 typedef class QList<UDSEntry> UDSEntryList; 0034 } 0035 0036 class KFileItem; 0037 class KRecentFilesAction; 0038 0039 class KateOutputView; 0040 class KateViewManager; 0041 class KateMwModOnHdDialog; 0042 0043 // Helper layout class to always provide minimum size 0044 class KateContainerStackedLayout : public QStackedLayout 0045 { 0046 Q_OBJECT 0047 public: 0048 explicit KateContainerStackedLayout(QWidget *parent); 0049 QSize sizeHint() const override; 0050 QSize minimumSize() const override; 0051 }; 0052 0053 class KateMainWindow : public KateMDI::MainWindow, virtual public KParts::PartBase 0054 { 0055 Q_OBJECT 0056 0057 public: 0058 /** 0059 * Construct the window and restore its state from given config if any 0060 * @param sconfig session config for this window, 0 if none 0061 * @param sgroup session config group to use 0062 * @param userTriggered is the user creating this window or is it part of session restore / startup 0063 */ 0064 KateMainWindow(KConfig *sconfig, const QString &sgroup, bool userTriggered); 0065 0066 /** 0067 * Destruct the nice window 0068 */ 0069 ~KateMainWindow() override; 0070 0071 /** 0072 * Accessor methodes for interface and child objects 0073 */ 0074 public: 0075 KateViewManager *viewManager() 0076 { 0077 return m_viewManager; 0078 } 0079 0080 /** 0081 * KTextEditor::MainWindow wrapper 0082 * @return KTextEditor::MainWindow wrapper. 0083 */ 0084 KTextEditor::MainWindow *wrapper() 0085 { 0086 return m_wrapper; 0087 } 0088 0089 public: 0090 /** Returns the URL of the current document. 0091 * anders: I add this for use from the file selector. */ 0092 QUrl activeDocumentUrl(); 0093 0094 /** Enumeration to specify if files modified on disk should show up 0095 * in the reload dialog even if not edited in this instance. */ 0096 enum ModOnDiskMode { 0097 PromptEdited, ///< Do not list files that have not been edited 0098 PromptAll, ///< Include all files modified on disk 0099 }; 0100 0101 /** 0102 * Prompts the user for what to do with files that are modified on disk if any. 0103 * This is optionally run when the window receives focus, and when the last 0104 * window is closed. 0105 * @return true if no documents are modified on disk, or all documents were 0106 * handled by the dialog; otherwise (the dialog was canceled) false. 0107 */ 0108 bool showModOnDiskPrompt(ModOnDiskMode mode); 0109 0110 public: 0111 /*reimp*/ void readProperties(const KConfigGroup &config) override; 0112 /*reimp*/ void saveProperties(KConfigGroup &config) override 0113 { 0114 saveProperties(config, true); 0115 } 0116 /*reimp*/ void saveGlobalProperties(KConfig *sessionConfig) override; 0117 0118 void saveProperties(KConfigGroup &config, bool includeViewConfig); 0119 0120 void saveOpenRecent(KConfig *config); 0121 void loadOpenRecent(const KConfig *config); 0122 0123 public: 0124 bool queryClose_internal(KTextEditor::Document *doc = nullptr, KateMainWindow *win = nullptr); 0125 0126 /** 0127 * save the settings, size and state of this window in 0128 * the provided config group 0129 */ 0130 void saveWindowConfig(const KConfigGroup &); 0131 /** 0132 * restore the settings, size and state of this window from 0133 * the provided config group. 0134 */ 0135 void restoreWindowConfig(const KConfigGroup &); 0136 0137 /** 0138 * save some global options to katerc 0139 */ 0140 void saveOptions(); 0141 0142 /** 0143 * Called if focus should go to the important part of the central widget. 0144 */ 0145 void triggerFocusForCentralWidget() override 0146 { 0147 // just dispatch to view manager 0148 m_viewManager->triggerActiveViewFocus(); 0149 } 0150 0151 private: 0152 /** 0153 * Setup actions which pointers are needed already in setupMainWindow 0154 */ 0155 void setupImportantActions(); 0156 0157 void setupMainWindow(); 0158 void setupActions(); 0159 bool queryClose() override; 0160 0161 void setupDiagnosticsView(KConfig *); 0162 0163 /** 0164 * read some global options from katerc 0165 */ 0166 void readOptions(); 0167 0168 void dragEnterEvent(QDragEnterEvent *) override; 0169 void dropEvent(QDropEvent *) override; 0170 0171 public Q_SLOTS: 0172 void slotFileClose(); 0173 void slotFileQuit(); 0174 void queueModifiedOnDisc(KTextEditor::Document *doc); 0175 0176 void slotFocusPrevTab(); 0177 void slotFocusNextTab(); 0178 0179 /** 0180 * Show quick open 0181 */ 0182 void slotQuickOpen(); 0183 0184 /** 0185 * Overwrite size hint for better default window sizes 0186 * @return size hint 0187 */ 0188 QSize sizeHint() const override; 0189 0190 /** 0191 * Create a new window. 0192 * Inherit size from current one. 0193 * @return new window 0194 */ 0195 KateMainWindow *newWindow() const; 0196 0197 /** 0198 * slots used for actions in the menus/toolbars 0199 * or internal signal connections 0200 */ 0201 private Q_SLOTS: 0202 void slotConfigure(); 0203 0204 void slotOpenWithMenuAction(QAction *a); 0205 0206 void slotEditToolbars(); 0207 void slotNewToolbarConfig(); 0208 void slotUpdateActionsNeedingUrl(); 0209 void slotOpenDocument(const QUrl &); 0210 0211 void slotDropEvent(QDropEvent *); 0212 void editKeys(); 0213 void mSlotFixOpenWithMenu(); 0214 static void reloadXmlGui(); 0215 0216 /* to update the caption */ 0217 void slotDocumentCreated(KTextEditor::Document *doc); 0218 void updateCaption(KTextEditor::Document *doc); 0219 // calls updateCaption(doc) with the current document 0220 void updateCaption(); 0221 0222 static void pluginHelp(); 0223 void slotFullScreen(bool); 0224 0225 void slotListRecursiveEntries(KIO::Job *job, const KIO::UDSEntryList &list); 0226 0227 void onApplicationStateChanged(Qt::ApplicationState); 0228 0229 private Q_SLOTS: 0230 void toggleShowMenuBar(bool showMessage = true); 0231 void toggleShowStatusBar(); 0232 void toggleShowTabBar(); 0233 0234 public: 0235 bool showStatusBar(); 0236 bool showTabBar(); 0237 0238 Q_SIGNALS: 0239 void tabBarToggled(); 0240 void unhandledShortcutOverride(QEvent *e); 0241 0242 void widgetAdded(QWidget *); 0243 void widgetRemoved(QWidget *); 0244 0245 public: 0246 void openUrl(const QString &name = QString()); 0247 0248 QHash<KTextEditor::Plugin *, QObject *> &pluginViews() 0249 { 0250 return m_pluginViews; 0251 } 0252 0253 QWidget *bottomViewBarContainer() 0254 { 0255 return m_bottomViewBarContainer; 0256 } 0257 0258 void addToBottomViewBarContainer(KTextEditor::View *view, QWidget *bar) 0259 { 0260 m_bottomContainerStack->addWidget(bar); 0261 m_bottomViewBarMapping[view] = BarState(bar); 0262 } 0263 0264 void hideBottomViewBarForView(KTextEditor::View *view) 0265 { 0266 BarState &state = m_bottomViewBarMapping[view]; 0267 if (state.bar()) { 0268 m_bottomContainerStack->setCurrentWidget(state.bar()); 0269 state.bar()->hide(); 0270 state.setState(false); 0271 } 0272 m_bottomViewBarContainer->hide(); 0273 } 0274 0275 void showBottomViewBarForView(KTextEditor::View *view) 0276 { 0277 BarState &state = m_bottomViewBarMapping[view]; 0278 if (state.bar()) { 0279 m_bottomContainerStack->setCurrentWidget(state.bar()); 0280 state.bar()->show(); 0281 state.setState(true); 0282 m_bottomViewBarContainer->show(); 0283 } 0284 } 0285 0286 void deleteBottomViewBarForView(KTextEditor::View *view) 0287 { 0288 BarState state = m_bottomViewBarMapping.take(view); 0289 if (state.bar()) { 0290 if (m_bottomContainerStack->currentWidget() == state.bar()) { 0291 m_bottomViewBarContainer->hide(); 0292 } 0293 delete state.bar(); 0294 delete state.statusBar(); 0295 } 0296 } 0297 0298 bool modNotificationEnabled() const 0299 { 0300 return m_modNotification; 0301 } 0302 0303 void setModNotificationEnabled(bool e) 0304 { 0305 m_modNotification = e; 0306 } 0307 0308 bool modCloseAfterLast() const 0309 { 0310 return m_modCloseAfterLast; 0311 } 0312 0313 void setModCloseAfterLast(bool e) 0314 { 0315 m_modCloseAfterLast = e; 0316 } 0317 0318 /** 0319 * add given url to list of recently opened files 0320 * @param url url that got opened 0321 */ 0322 void addRecentOpenedFile(const QUrl &url); 0323 0324 KRecentFilesAction *recentFilesAction() 0325 { 0326 return m_fileOpenRecent; 0327 } 0328 0329 // 0330 // KTextEditor::MainWindow interface, get called by invokeMethod from our wrapper object! 0331 // 0332 public Q_SLOTS: 0333 /** 0334 * get the toplevel widget. 0335 * \return the real main window widget. 0336 */ 0337 QWidget *window() 0338 { 0339 return this; 0340 } 0341 0342 /** 0343 * Accessor to the XMLGUIFactory. 0344 * \return the mainwindow's KXMLGUIFactory. 0345 */ 0346 KXMLGUIFactory *guiFactory() override 0347 { 0348 return KateMDI::MainWindow::guiFactory(); 0349 } 0350 0351 /** 0352 * Get a list of all views for this main window. 0353 * @return all views 0354 */ 0355 QList<KTextEditor::View *> views() 0356 { 0357 return viewManager()->views(); 0358 } 0359 0360 /** 0361 * Access the active view. 0362 * \return active view 0363 */ 0364 KTextEditor::View *activeView() 0365 { 0366 return viewManager()->activeView(); 0367 } 0368 0369 /** 0370 * Activate the view with the corresponding \p document. 0371 * If none exist for this document, create one 0372 * \param document the document 0373 * \return activated view of this document 0374 */ 0375 KTextEditor::View *activateView(KTextEditor::Document *document) 0376 { 0377 return viewManager()->activateView(document); 0378 } 0379 0380 /** 0381 * Open the document \p url with the given \p encoding. 0382 * \param url the document's url 0383 * \param encoding the preferred encoding. If encoding is QString() the 0384 * encoding will be guessed or the default encoding will be used. 0385 * \return a pointer to the created view for the new document, if a document 0386 * with this url is already existing, its view will be activated 0387 */ 0388 KTextEditor::View *openUrl(const QUrl &url, const QString &encoding = QString()) 0389 { 0390 return viewManager()->openUrlWithView(url, encoding); 0391 } 0392 0393 /** 0394 * Close selected view 0395 * \param view the view 0396 * \return true if view was closed 0397 */ 0398 bool closeView(KTextEditor::View *view) 0399 { 0400 m_viewManager->closeView(view); 0401 return true; 0402 } 0403 0404 /** 0405 * Close the split view where the given view is contained. 0406 * \param view the view. 0407 * \return true if the split view was closed. 0408 */ 0409 bool closeSplitView(KTextEditor::View *view) 0410 { 0411 m_viewManager->closeViewSpace(view); 0412 return true; 0413 } 0414 0415 /** 0416 * @returns true if the two given views share the same split view, 0417 * false otherwise. 0418 */ 0419 bool viewsInSameSplitView(KTextEditor::View *view1, KTextEditor::View *view2) 0420 { 0421 return m_viewManager->viewsInSameViewSpace(view1, view2); 0422 } 0423 0424 /** 0425 * Split current view space according to \p orientation 0426 * \param orientation in which line split the view 0427 */ 0428 void splitView(Qt::Orientation orientation) 0429 { 0430 m_viewManager->splitViewSpace(nullptr, orientation); 0431 } 0432 0433 /** 0434 * Try to create a view bar for the given view. 0435 * Its parameter is the view for which we want a view bar 0436 * @return suitable widget that can host view bars widgets or nullptr 0437 */ 0438 QWidget *createViewBar(KTextEditor::View *) 0439 { 0440 return bottomViewBarContainer(); 0441 } 0442 0443 /** 0444 * Delete the view bar for the given view. 0445 * @param view view for which we want an view bar 0446 */ 0447 void deleteViewBar(KTextEditor::View *view) 0448 { 0449 deleteBottomViewBarForView(view); 0450 } 0451 0452 /** 0453 * Add a widget to the view bar. 0454 * @param view view for which the view bar is used 0455 * @param bar bar widget, shall have the viewBarParent() as parent widget 0456 */ 0457 void addWidgetToViewBar(KTextEditor::View *view, QWidget *bar) 0458 { 0459 addToBottomViewBarContainer(view, bar); 0460 } 0461 0462 /** 0463 * Show the view bar for the given view 0464 * @param view view for which the view bar is used 0465 */ 0466 void showViewBar(KTextEditor::View *view) 0467 { 0468 showBottomViewBarForView(view); 0469 } 0470 0471 /** 0472 * Hide the view bar for the given view 0473 * @param view view for which the view bar is used 0474 */ 0475 void hideViewBar(KTextEditor::View *view) 0476 { 0477 hideBottomViewBarForView(view); 0478 } 0479 0480 void insertWidgetInStatusbar(QWidget *w) 0481 { 0482 insertWidgetBeforeStatusbar(w); 0483 } 0484 0485 /** 0486 * Create a new toolview with unique \p identifier at side \p pos 0487 * with \p icon and caption \p text. Use the returned widget to embed 0488 * your widgets. 0489 * \param plugin which owns this tool view 0490 * \param identifier unique identifier for this toolview 0491 * \param pos position for the toolview, if we are in session restore, 0492 * this is only a preference 0493 * \param icon icon to use in the sidebar for the toolview 0494 * \param text translated text (i18n()) to use in addition to icon 0495 * \return created toolview on success, otherwise NULL 0496 */ 0497 QWidget *createToolView(KTextEditor::Plugin *plugin, 0498 const QString &identifier, 0499 KTextEditor::MainWindow::ToolViewPosition pos, 0500 const QIcon &icon, 0501 const QString &text); 0502 0503 /** 0504 * Find the toolview with the given \p identifier 0505 * \param identifier identifier as specified in createToolView() 0506 * \return pointer to the toolview, if found, otherwise NULL 0507 */ 0508 QWidget *toolviewForName(const QString &identifier) 0509 { 0510 return toolView(identifier); 0511 } 0512 0513 /** 0514 * Move the toolview \p widget to position \p pos. 0515 * \param widget the toolview to move, where the widget was constructed 0516 * by createToolView(). 0517 * \param pos new position to move widget to 0518 * \return \e true on success, otherwise \e false 0519 */ 0520 bool moveToolView(QWidget *widget, KTextEditor::MainWindow::ToolViewPosition pos); 0521 0522 /** 0523 * Show the toolview \p widget. 0524 * \param widget the toolview to show, where the widget was constructed 0525 * by createToolView(). 0526 * \return \e true on success, otherwise \e false 0527 * \todo add focus parameter: bool showToolView (QWidget *widget, bool giveFocus ); 0528 */ 0529 bool showToolView(QWidget *widget); 0530 0531 /** 0532 * Hide the toolview \p widget. 0533 * \param widget the toolview to hide, where the widget was constructed 0534 * by createToolView(). 0535 * \return \e true on success, otherwise \e false 0536 */ 0537 bool hideToolView(QWidget *widget); 0538 0539 /** 0540 * Shows the @p plugin's config page. The @p page specifies which 0541 * config page will be shown, see KTextEditor::Plugin::configPages(). 0542 * 0543 * \return \e true on success, otherwise \e false 0544 * \since 5.63 0545 */ 0546 bool showPluginConfigPage(KTextEditor::Plugin *configpageinterface, int id); 0547 0548 /** 0549 * Get a plugin view for the plugin with with identifier \p name. 0550 * \param name the plugin's name 0551 * \return pointer to the plugin view if a plugin with \p name is loaded and has a view for this mainwindow, 0552 * otherwise NULL 0553 */ 0554 QObject *pluginView(const QString &name); 0555 0556 /** 0557 * Add a widget to the main window. 0558 * This is useful to show non-KTextEditor::View widgets in the main window. 0559 * The host application should try to manage this like some KTextEditor::View (e.g. as a tab) and provide 0560 * the means to close it. 0561 * \param widget widget to add 0562 * \return success, if false, the plugin needs to take care to show the widget itself, otherwise 0563 * the main window will take ownership of the widget 0564 */ 0565 bool addWidget(QWidget *widget); 0566 0567 /** 0568 * \brief returns the list of non-KTextEditor::View widgets in this main window. 0569 * \see addWidget 0570 */ 0571 QWidgetList widgets() const; 0572 0573 /** 0574 * \brief remove this \p widget from this mainwindow. The widget will be deleted afterwards 0575 * \param widget the widget to be removed 0576 * \return true on success 0577 */ 0578 bool removeWidget(QWidget *widget); 0579 0580 /** 0581 * \brief returns the currently active widget. It can be a 0582 * non-KTextEditor::View widget or a KTextEditor::View 0583 */ 0584 QWidget *activeWidget(); 0585 0586 /** 0587 * \brief activate @p widget. If the widget is not present in the window, it will be added to the window 0588 * \param widget the widget to activate 0589 */ 0590 void activateWidget(QWidget *widget); 0591 0592 /** 0593 * @brief show a message in the output view. See KTextEditor::MainWindow::showMessage for details 0594 */ 0595 void showMessage(const QVariantMap &map); 0596 0597 void addPositionToHistory(const QUrl &url, KTextEditor::Cursor c); 0598 0599 private Q_SLOTS: 0600 void slotUpdateBottomViewBar(); 0601 void slotDocumentCloseAll(); 0602 void slotDocumentCloseOther(); 0603 void slotDocumentCloseOther(KTextEditor::Document *document); 0604 void slotDocumentCloseSelected(const QList<KTextEditor::Document *> &); 0605 0606 private: 0607 void ensureHamburgerBarSize(); 0608 0609 /** 0610 * Wrapper of main window for KTextEditor 0611 */ 0612 KTextEditor::MainWindow *m_wrapper; 0613 0614 /** 0615 * Notify about file modifications from other processes? 0616 */ 0617 bool m_modNotification = false; 0618 0619 /** 0620 * Shutdown Kate after last file is closed 0621 */ 0622 bool m_modCloseAfterLast = false; 0623 0624 /** 0625 * keeps track of views 0626 */ 0627 KateViewManager *m_viewManager = nullptr; 0628 0629 KRecentFilesAction *m_fileOpenRecent = nullptr; 0630 0631 KActionMenu *documentOpenWith = nullptr; 0632 0633 KToggleAction *settingsShowFileselector = nullptr; 0634 0635 KToggleAction *m_showFullScreenAction = nullptr; 0636 0637 bool m_modignore = false; 0638 0639 // all plugin views for this mainwindow, used by the pluginmanager 0640 QHash<KTextEditor::Plugin *, QObject *> m_pluginViews; 0641 0642 // options: show statusbar + show path 0643 KToggleAction *m_paShowPath = nullptr; 0644 KToggleAction *m_paShowMenuBar = nullptr; 0645 KToggleAction *m_paShowStatusBar = nullptr; 0646 KToggleAction *m_paShowTabBar = nullptr; 0647 KToggleAction *m_paShowUrlNavBar = nullptr; 0648 0649 QWidget *m_bottomViewBarContainer = nullptr; 0650 KateContainerStackedLayout *m_bottomContainerStack = nullptr; 0651 0652 class BarState 0653 { 0654 public: 0655 BarState() = default; 0656 explicit BarState(QWidget *bar) 0657 : m_bar(bar) 0658 , m_state(false) 0659 { 0660 } 0661 ~BarState() 0662 { 0663 } 0664 QWidget *bar() 0665 { 0666 return m_bar; 0667 } 0668 bool state() 0669 { 0670 return m_state; 0671 } 0672 void setState(bool state) 0673 { 0674 m_state = state; 0675 } 0676 QWidget *statusBar() 0677 { 0678 return m_statusBar; 0679 } 0680 void setStatusBar(QWidget *statusBar) 0681 { 0682 Q_ASSERT(statusBar); 0683 Q_ASSERT(!m_statusBar); 0684 m_statusBar = statusBar; 0685 } 0686 0687 private: 0688 QWidget *m_bar = nullptr; 0689 bool m_state = false; 0690 0691 /** 0692 * status bar widget 0693 * if already extracted from the bar itself 0694 * we can't extract this on creation of the bar widget, but do this lazy 0695 * later, as the construction order in KateView doesn't allow for that. 0696 */ 0697 QWidget *m_statusBar = nullptr; 0698 }; 0699 QHash<KTextEditor::View *, BarState> m_bottomViewBarMapping; 0700 0701 /** 0702 * generic output tool view 0703 */ 0704 QWidget *m_toolViewOutput = nullptr; 0705 0706 /** 0707 * output widget contained in above tool view 0708 */ 0709 KateOutputView *m_outputView = nullptr; 0710 0711 /** 0712 * Diagnostics view at the bottom 0713 */ 0714 class DiagnosticsView *m_diagView = nullptr; 0715 0716 public: 0717 /** 0718 * The available actions for the mouse back button, used as indexing 0719 * for the comboboxes of the config window 0720 */ 0721 enum MouseBackButtonAction { PreviousTab = 0, HistoryBack }; 0722 0723 /** 0724 * The available actions for the mouse forward button, used as indexing 0725 * for the comboboxes of the config window 0726 */ 0727 enum MouseForwardButtonAction { NextTab = 0, HistoryForward }; 0728 0729 private: 0730 MouseBackButtonAction m_mouseButtonBackAction = PreviousTab; 0731 MouseForwardButtonAction m_mouseButtonForwardAction = NextTab; 0732 void handleBackButtonAction(); 0733 void handleForwardButtonAction(); 0734 0735 public: 0736 /** 0737 * Accessor for unique output view per main window. 0738 * @return our output view, will always exist! 0739 */ 0740 KateOutputView *outputView() 0741 { 0742 return m_outputView; 0743 } 0744 0745 public: 0746 static void unsetModifiedOnDiscDialogIfIf(KateMwModOnHdDialog *diag) 0747 { 0748 if (s_modOnHdDialog == diag) { 0749 s_modOnHdDialog = nullptr; 0750 } 0751 } 0752 0753 private: 0754 static KateMwModOnHdDialog *s_modOnHdDialog; 0755 0756 public Q_SLOTS: 0757 void slotWindowActivated(); 0758 0759 protected: 0760 bool event(QEvent *e) override; 0761 void mousePressEvent(QMouseEvent *e) override; 0762 };