1 /* This file is part of the KDE project 2 SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org> 3 SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org> 4 SPDX-FileCopyrightText: 2001 Anders Lund <anders.lund@lund.tdcadsl.dk> 5 6 SPDX-License-Identifier: LGPL-2.0-only 7 */ 8 9 #ifndef __KATE_MAINWINDOW_H__ 10 #define __KATE_MAINWINDOW_H__ 11 12 #include "katemdi.h" 13 #include "kateviewmanager.h" 14 15 #include <ktexteditor/document.h> 16 #include <ktexteditor/mainwindow.h> 17 #include <ktexteditor/view.h> 18 19 #include <KParts/Part> 20 21 #include <QDragEnterEvent> 22 #include <QDropEvent> 23 #include <QEvent> 24 #include <QHash> 25 #include <QModelIndex> 26 #include <QStackedLayout> 27 #include <QStackedWidget> 28 #include <QUrl> 29 #include <QVBoxLayout> 30 31 class QMenu; 32 33 namespace KIO 34 { 35 class UDSEntry; 36 typedef class QList<UDSEntry> UDSEntryList; 37 } 38 39 class KFileItem; 40 class KRecentFilesAction; 41 42 class KateOutputView; 43 class KateViewManager; 44 class KateMwModOnHdDialog; 45 46 // Helper layout class to always provide minimum size 47 class KateContainerStackedLayout : public QStackedLayout 48 { 49 Q_OBJECT 50 public: 51 KateContainerStackedLayout(QWidget *parent); 52 QSize sizeHint() const override; 53 QSize minimumSize() const override; 54 }; 55 56 class KateMainWindow : public KateMDI::MainWindow, virtual public KParts::PartBase 57 { 58 Q_OBJECT 59 60 public: 61 /** 62 * Construct the window and restore its state from given config if any 63 * @param sconfig session config for this window, 0 if none 64 * @param sgroup session config group to use 65 */ 66 KateMainWindow(KConfig *sconfig, const QString &sgroup); 67 68 /** 69 * Destruct the nice window 70 */ 71 ~KateMainWindow() override; 72 73 /** 74 * Accessor methodes for interface and child objects 75 */ 76 public: viewManager()77 KateViewManager *viewManager() 78 { 79 return m_viewManager; 80 } 81 82 /** 83 * KTextEditor::MainWindow wrapper 84 * @return KTextEditor::MainWindow wrapper. 85 */ wrapper()86 KTextEditor::MainWindow *wrapper() 87 { 88 return m_wrapper; 89 } 90 91 public: 92 /** Returns the URL of the current document. 93 * anders: I add this for use from the file selector. */ 94 QUrl activeDocumentUrl(); 95 96 /** Enumeration to specify if files modified on disk should show up 97 * in the reload dialog even if not edited in this instance. */ 98 enum ModOnDiskMode { 99 PromptEdited, ///< Do not list files that have not been edited 100 PromptAll, ///< Include all files modified on disk 101 }; 102 103 /** 104 * Prompts the user for what to do with files that are modified on disk if any. 105 * This is optionally run when the window receives focus, and when the last 106 * window is closed. 107 * @return true if no documents are modified on disk, or all documents were 108 * handled by the dialog; otherwise (the dialog was canceled) false. 109 */ 110 bool showModOnDiskPrompt(ModOnDiskMode mode); 111 112 public: 113 /*reimp*/ void readProperties(const KConfigGroup &config) override; 114 /*reimp*/ void saveProperties(KConfigGroup &config) override; 115 /*reimp*/ void saveGlobalProperties(KConfig *sessionConfig) override; 116 117 void saveOpenRecent(KConfig *config); 118 void loadOpenRecent(const KConfig *config); 119 120 public: 121 bool queryClose_internal(KTextEditor::Document *doc = nullptr); 122 123 /** 124 * save the settings, size and state of this window in 125 * the provided config group 126 */ 127 void saveWindowConfig(const KConfigGroup &); 128 /** 129 * restore the settings, size and state of this window from 130 * the provided config group. 131 */ 132 void restoreWindowConfig(const KConfigGroup &); 133 134 /** 135 * save some global options to katerc 136 */ 137 void saveOptions(); 138 139 private: 140 /** 141 * Setup actions which pointers are needed already in setupMainWindow 142 */ 143 void setupImportantActions(); 144 145 void setupMainWindow(); 146 void setupActions(); 147 bool queryClose() override; 148 149 /** 150 * read some global options from katerc 151 */ 152 void readOptions(); 153 154 void dragEnterEvent(QDragEnterEvent *) override; 155 void dropEvent(QDropEvent *) override; 156 157 public Q_SLOTS: 158 void slotFileClose(); 159 void slotFileQuit(); 160 void queueModifiedOnDisc(KTextEditor::Document *doc); 161 162 void slotFocusPrevTab(); 163 void slotFocusNextTab(); 164 165 /** 166 * Show quick open 167 */ 168 void slotQuickOpen(); 169 170 void slotCommandBarOpen(); 171 172 /** 173 * Overwrite size hint for better default window sizes 174 * @return size hint 175 */ 176 QSize sizeHint() const override; 177 178 /** 179 * slots used for actions in the menus/toolbars 180 * or internal signal connections 181 */ 182 private Q_SLOTS: 183 void newWindow(); 184 185 void slotConfigure(); 186 187 void slotOpenWithMenuAction(QAction *a); 188 189 void slotEditToolbars(); 190 void slotNewToolbarConfig(); 191 void slotUpdateOpenWith(); 192 void slotUpdateActionsNeedingUrl(); 193 void slotOpenDocument(const QUrl &); 194 195 void slotDropEvent(QDropEvent *); 196 void editKeys(); 197 void mSlotFixOpenWithMenu(); 198 void reloadXmlGui(); 199 200 /* to update the caption */ 201 void slotDocumentCreated(KTextEditor::Document *doc); 202 void updateCaption(KTextEditor::Document *doc); 203 // calls updateCaption(doc) with the current document 204 void updateCaption(); 205 206 void pluginHelp(); 207 void slotFullScreen(bool); 208 209 void slotListRecursiveEntries(KIO::Job *job, const KIO::UDSEntryList &list); 210 211 private Q_SLOTS: 212 void toggleShowMenuBar(bool showMessage = true); 213 void toggleShowStatusBar(); 214 void toggleShowTabBar(); 215 216 public: 217 bool showStatusBar(); 218 bool showTabBar(); 219 220 Q_SIGNALS: 221 void statusBarToggled(); 222 void tabBarToggled(); 223 void unhandledShortcutOverride(QEvent *e); 224 225 public: 226 void openUrl(const QString &name = QString()); 227 pluginViews()228 QHash<KTextEditor::Plugin *, QObject *> &pluginViews() 229 { 230 return m_pluginViews; 231 } 232 bottomViewBarContainer()233 QWidget *bottomViewBarContainer() 234 { 235 return m_bottomViewBarContainer; 236 } 237 addToBottomViewBarContainer(KTextEditor::View * view,QWidget * bar)238 void addToBottomViewBarContainer(KTextEditor::View *view, QWidget *bar) 239 { 240 m_bottomContainerStack->addWidget(bar); 241 m_bottomViewBarMapping[view] = BarState(bar); 242 } 243 hideBottomViewBarForView(KTextEditor::View * view)244 void hideBottomViewBarForView(KTextEditor::View *view) 245 { 246 BarState &state = m_bottomViewBarMapping[view]; 247 if (state.bar()) { 248 m_bottomContainerStack->setCurrentWidget(state.bar()); 249 state.bar()->hide(); 250 state.setState(false); 251 } 252 m_bottomViewBarContainer->hide(); 253 } 254 showBottomViewBarForView(KTextEditor::View * view)255 void showBottomViewBarForView(KTextEditor::View *view) 256 { 257 BarState &state = m_bottomViewBarMapping[view]; 258 if (state.bar()) { 259 m_bottomContainerStack->setCurrentWidget(state.bar()); 260 state.bar()->show(); 261 state.setState(true); 262 m_bottomViewBarContainer->show(); 263 } 264 } 265 deleteBottomViewBarForView(KTextEditor::View * view)266 void deleteBottomViewBarForView(KTextEditor::View *view) 267 { 268 BarState state = m_bottomViewBarMapping.take(view); 269 if (state.bar()) { 270 if (m_bottomContainerStack->currentWidget() == state.bar()) { 271 m_bottomViewBarContainer->hide(); 272 } 273 delete state.bar(); 274 } 275 } 276 modNotificationEnabled()277 bool modNotificationEnabled() const 278 { 279 return m_modNotification; 280 } 281 setModNotificationEnabled(bool e)282 void setModNotificationEnabled(bool e) 283 { 284 m_modNotification = e; 285 } 286 modCloseAfterLast()287 bool modCloseAfterLast() const 288 { 289 return m_modCloseAfterLast; 290 } 291 setModCloseAfterLast(bool e)292 void setModCloseAfterLast(bool e) 293 { 294 m_modCloseAfterLast = e; 295 } 296 297 /** 298 * add given url to list of recently opened files 299 * @param url url that got opened 300 */ 301 void addRecentOpenedFile(const QUrl &url); 302 303 // 304 // KTextEditor::MainWindow interface, get called by invokeMethod from our wrapper object! 305 // 306 public Q_SLOTS: 307 /** 308 * get the toplevel widget. 309 * \return the real main window widget. 310 */ window()311 QWidget *window() 312 { 313 return this; 314 } 315 316 /** 317 * Accessor to the XMLGUIFactory. 318 * \return the mainwindow's KXMLGUIFactory. 319 */ guiFactory()320 KXMLGUIFactory *guiFactory() override 321 { 322 return KateMDI::MainWindow::guiFactory(); 323 } 324 325 /** 326 * Get a list of all views for this main window. 327 * @return all views 328 */ views()329 QList<KTextEditor::View *> views() 330 { 331 return viewManager()->views(); 332 } 333 334 /** 335 * Access the active view. 336 * \return active view 337 */ activeView()338 KTextEditor::View *activeView() 339 { 340 return viewManager()->activeView(); 341 } 342 343 /** 344 * Activate the view with the corresponding \p document. 345 * If none exist for this document, create one 346 * \param document the document 347 * \return activated view of this document 348 */ activateView(KTextEditor::Document * document)349 KTextEditor::View *activateView(KTextEditor::Document *document) 350 { 351 return viewManager()->activateView(document); 352 } 353 354 /** 355 * Open the document \p url with the given \p encoding. 356 * \param url the document's url 357 * \param encoding the preferred encoding. If encoding is QString() the 358 * encoding will be guessed or the default encoding will be used. 359 * \return a pointer to the created view for the new document, if a document 360 * with this url is already existing, its view will be activated 361 */ 362 KTextEditor::View *openUrl(const QUrl &url, const QString &encoding = QString()) 363 { 364 return viewManager()->openUrlWithView(url, encoding); 365 } 366 367 /** 368 * Close selected view 369 * \param view the view 370 * \return true if view was closed 371 */ closeView(KTextEditor::View * view)372 bool closeView(KTextEditor::View *view) 373 { 374 m_viewManager->closeView(view); 375 return true; 376 } 377 378 /** 379 * Close the split view where the given view is contained. 380 * \param view the view. 381 * \return true if the split view was closed. 382 */ closeSplitView(KTextEditor::View * view)383 bool closeSplitView(KTextEditor::View *view) 384 { 385 m_viewManager->closeViewSpace(view); 386 return true; 387 } 388 389 /** 390 * @returns true if the two given views share the same split view, 391 * false otherwise. 392 */ viewsInSameSplitView(KTextEditor::View * view1,KTextEditor::View * view2)393 bool viewsInSameSplitView(KTextEditor::View *view1, KTextEditor::View *view2) 394 { 395 return m_viewManager->viewsInSameViewSpace(view1, view2); 396 } 397 398 /** 399 * Split current view space according to \p orientation 400 * \param orientation in which line split the view 401 */ splitView(Qt::Orientation orientation)402 void splitView(Qt::Orientation orientation) 403 { 404 m_viewManager->splitViewSpace(nullptr, orientation); 405 } 406 407 /** 408 * Try to create a view bar for the given view. 409 * Its parameter is the view for which we want a view bar 410 * @return suitable widget that can host view bars widgets or nullptr 411 */ createViewBar(KTextEditor::View *)412 QWidget *createViewBar(KTextEditor::View *) 413 { 414 return bottomViewBarContainer(); 415 } 416 417 /** 418 * Delete the view bar for the given view. 419 * @param view view for which we want an view bar 420 */ deleteViewBar(KTextEditor::View * view)421 void deleteViewBar(KTextEditor::View *view) 422 { 423 deleteBottomViewBarForView(view); 424 } 425 426 /** 427 * Add a widget to the view bar. 428 * @param view view for which the view bar is used 429 * @param bar bar widget, shall have the viewBarParent() as parent widget 430 */ addWidgetToViewBar(KTextEditor::View * view,QWidget * bar)431 void addWidgetToViewBar(KTextEditor::View *view, QWidget *bar) 432 { 433 addToBottomViewBarContainer(view, bar); 434 } 435 436 /** 437 * Show the view bar for the given view 438 * @param view view for which the view bar is used 439 */ showViewBar(KTextEditor::View * view)440 void showViewBar(KTextEditor::View *view) 441 { 442 showBottomViewBarForView(view); 443 } 444 445 /** 446 * Hide the view bar for the given view 447 * @param view view for which the view bar is used 448 */ hideViewBar(KTextEditor::View * view)449 void hideViewBar(KTextEditor::View *view) 450 { 451 hideBottomViewBarForView(view); 452 } 453 454 /** 455 * Create a new toolview with unique \p identifier at side \p pos 456 * with \p icon and caption \p text. Use the returned widget to embed 457 * your widgets. 458 * \param plugin which owns this tool view 459 * \param identifier unique identifier for this toolview 460 * \param pos position for the toolview, if we are in session restore, 461 * this is only a preference 462 * \param icon icon to use in the sidebar for the toolview 463 * \param text translated text (i18n()) to use in addition to icon 464 * \return created toolview on success, otherwise NULL 465 */ 466 QWidget *createToolView(KTextEditor::Plugin *plugin, 467 const QString &identifier, 468 KTextEditor::MainWindow::ToolViewPosition pos, 469 const QIcon &icon, 470 const QString &text); 471 472 /** 473 * Move the toolview \p widget to position \p pos. 474 * \param widget the toolview to move, where the widget was constructed 475 * by createToolView(). 476 * \param pos new position to move widget to 477 * \return \e true on success, otherwise \e false 478 */ 479 bool moveToolView(QWidget *widget, KTextEditor::MainWindow::ToolViewPosition pos); 480 481 /** 482 * Show the toolview \p widget. 483 * \param widget the toolview to show, where the widget was constructed 484 * by createToolView(). 485 * \return \e true on success, otherwise \e false 486 * \todo add focus parameter: bool showToolView (QWidget *widget, bool giveFocus ); 487 */ 488 bool showToolView(QWidget *widget); 489 490 /** 491 * Hide the toolview \p widget. 492 * \param widget the toolview to hide, where the widget was constructed 493 * by createToolView(). 494 * \return \e true on success, otherwise \e false 495 */ 496 bool hideToolView(QWidget *widget); 497 498 /** 499 * Shows the @p plugin's config page. The @p page specifies which 500 * config page will be shown, see KTextEditor::Plugin::configPages(). 501 * 502 * \return \e true on success, otherwise \e false 503 * \since 5.63 504 */ 505 bool showPluginConfigPage(KTextEditor::Plugin *configpageinterface, int id); 506 507 /** 508 * Get a plugin view for the plugin with with identifier \p name. 509 * \param name the plugin's name 510 * \return pointer to the plugin view if a plugin with \p name is loaded and has a view for this mainwindow, 511 * otherwise NULL 512 */ 513 QObject *pluginView(const QString &name); 514 515 void addWidgetAsTab(QWidget *widget); 516 517 private Q_SLOTS: 518 void slotUpdateBottomViewBar(); 519 520 private Q_SLOTS: 521 void slotDocumentCloseAll(); 522 void slotDocumentCloseOther(); 523 void slotDocumentCloseOther(KTextEditor::Document *document); 524 void slotDocumentCloseSelected(const QList<KTextEditor::Document *> &); 525 526 private: 527 /** 528 * Notify about file modifications from other processes? 529 */ 530 bool m_modNotification = false; 531 532 /** 533 * Shutdown Kate after last file is closed 534 */ 535 bool m_modCloseAfterLast = false; 536 537 /** 538 * stacked widget containing the central area, aka view manager, quickopen, ... 539 */ 540 QStackedWidget *m_mainStackedWidget = nullptr; 541 542 /** 543 * keeps track of views 544 */ 545 KateViewManager *m_viewManager = nullptr; 546 547 KRecentFilesAction *m_fileOpenRecent = nullptr; 548 549 KActionMenu *documentOpenWith = nullptr; 550 551 KToggleAction *settingsShowFileselector = nullptr; 552 553 KToggleAction *m_showFullScreenAction = nullptr; 554 555 bool m_modignore; 556 557 // all plugin views for this mainwindow, used by the pluginmanager 558 QHash<KTextEditor::Plugin *, QObject *> m_pluginViews; 559 560 // options: show statusbar + show path 561 KToggleAction *m_paShowPath = nullptr; 562 KToggleAction *m_paShowMenuBar = nullptr; 563 KToggleAction *m_paShowStatusBar = nullptr; 564 KToggleAction *m_paShowTabBar = nullptr; 565 566 QWidget *m_bottomViewBarContainer = nullptr; 567 KateContainerStackedLayout *m_bottomContainerStack = nullptr; 568 569 QVector<QString> m_lastUsedCmdBarActions; 570 571 class BarState 572 { 573 public: 574 BarState() = default; BarState(QWidget * bar)575 BarState(QWidget *bar) 576 : m_bar(bar) 577 , m_state(false) 578 { 579 } ~BarState()580 ~BarState() 581 { 582 } bar()583 QWidget *bar() 584 { 585 return m_bar; 586 } state()587 bool state() 588 { 589 return m_state; 590 } setState(bool state)591 void setState(bool state) 592 { 593 m_state = state; 594 } 595 596 private: 597 QWidget *m_bar = nullptr; 598 bool m_state = false; 599 }; 600 QHash<KTextEditor::View *, BarState> m_bottomViewBarMapping; 601 602 /** 603 * generic output tool view 604 */ 605 QWidget *m_toolViewOutput = nullptr; 606 607 /** 608 * output widget contained in above tool view 609 */ 610 KateOutputView *m_outputView = nullptr; 611 612 public: 613 /** 614 * Accessor for unique output view per main window. 615 * @return our output view, will always exist! 616 */ outputView()617 KateOutputView *outputView() 618 { 619 return m_outputView; 620 } 621 622 public: unsetModifiedOnDiscDialogIfIf(KateMwModOnHdDialog * diag)623 static void unsetModifiedOnDiscDialogIfIf(KateMwModOnHdDialog *diag) 624 { 625 if (s_modOnHdDialog == diag) { 626 s_modOnHdDialog = nullptr; 627 } 628 } 629 630 private: 631 static KateMwModOnHdDialog *s_modOnHdDialog; 632 633 /** 634 * Wrapper of main window for KTextEditor 635 */ 636 KTextEditor::MainWindow *m_wrapper; 637 638 public Q_SLOTS: 639 void slotWindowActivated(); 640 641 protected: 642 bool event(QEvent *e) override; 643 void mousePressEvent(QMouseEvent *e) override; 644 }; 645 646 #endif 647