File indexing completed on 2024-05-19 12:54:52
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003 Lucijan Busch <lucijan@kde.org> 0003 Copyright (C) 2003-2018 Jarosław Staniek <staniek@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #ifndef KEXIMAINWINDOW_P_H 0022 #define KEXIMAINWINDOW_P_H 0023 0024 #include <QKeyEvent> 0025 #include <QScopedPointer> 0026 #include <QTabWidget> 0027 #include <QGraphicsOpacityEffect> 0028 #include <QPropertyAnimation> 0029 #include <QStackedLayout> 0030 #include <QProxyStyle> 0031 #include <QTabBar> 0032 #include <QTimer> 0033 #include <QDockWidget> 0034 #include <QShortcut> 0035 #include <QStackedWidget> 0036 #include <QMenu> 0037 0038 #include <KToolBar> 0039 #include <KHelpMenu> 0040 #include <KAboutData> 0041 #include <KActionCollection> 0042 #include <KMultiTabBar> 0043 #include <KActionMenu> 0044 #include <KSharedConfig> 0045 0046 #include "KexiMainWindow.h" 0047 #include "KexiSearchLineEdit.h" 0048 #include "KexiUserFeedbackAgent.h" 0049 #include "KexiMenuWidget.h" 0050 #include "kexifinddialog.h" 0051 #include "KexiStartup.h" 0052 #include "KexiGlobalViewModeSelector.h" 0053 #include <kexiutils/utils.h> 0054 #include <widget/utils/KexiDockableWidget.h> 0055 #include <widget/KexiNameDialog.h> 0056 #include <core/kexi.h> 0057 #include <core/KexiWindow.h> 0058 #include <core/kexipartinfo.h> 0059 #include <KexiFadeWidgetEffect.h> 0060 0061 #define KEXI_NO_PROCESS_EVENTS 0062 0063 #ifdef KEXI_NO_PROCESS_EVENTS 0064 # define KEXI_NO_PENDING_DIALOGS 0065 #endif 0066 0067 #define PROJECT_NAVIGATOR_TABBAR_ID 0 0068 #define PROPERTY_EDITOR_TABBAR_ID 1 0069 #define KEXITABBEDTOOLBAR_SPACER_TAB_INDEX 1 0070 0071 class QPainter; 0072 class KexiAssistantPage; 0073 class KexiProjectNavigator; 0074 class KPropertyEditorView; 0075 0076 //! @short Main application's tabbed toolbar 0077 class KexiTabbedToolBar : public QTabWidget 0078 { 0079 Q_OBJECT 0080 public: 0081 explicit KexiTabbedToolBar(QWidget *parent); 0082 virtual ~KexiTabbedToolBar(); 0083 0084 KToolBar *createWidgetToolBar() const; 0085 0086 KToolBar *toolBar(const QString& name) const; 0087 0088 void appendWidgetToToolbar(const QString& name, QWidget* widget); 0089 0090 void setWidgetVisibleInToolbar(QWidget* widget, bool visible); 0091 0092 //! @todo replace with the final Actions API 0093 void addAction(const QString& toolBarName, QAction *action); 0094 0095 bool mainMenuVisible() const; 0096 0097 QRect tabRect(int index) const; 0098 0099 void addSearchableModel(KexiSearchableModel *model); 0100 0101 void removeSearchableModel(KexiSearchableModel *model); 0102 0103 KToolBar *createToolBar(const char *name, const QString& caption); 0104 0105 void setCurrentTab(const QString& name); 0106 0107 //! Sets current tab to @a index, counting from first visible (non-Kexi) tab. 0108 //! In non-user mode, the first visible tab is "create" tab. 0109 void setCurrentTab(int index); 0110 0111 void hideTab(const QString& name); 0112 0113 void showTab(const QString& name); 0114 0115 bool isTabVisible(const QString& name) const; 0116 0117 bool isRolledUp(); 0118 0119 const QWidget* mainMenuContent(); 0120 0121 public Q_SLOTS: 0122 void setMainMenuContent(QWidget *w); 0123 void selectMainMenuItem(const char *actionName); 0124 void showMainMenu(const char* actionName = 0); 0125 void hideMainMenu(); 0126 void toggleMainMenu(); 0127 void activateSearchLineEdit(); 0128 void toggleRollDown(); 0129 0130 protected: 0131 virtual void mouseMoveEvent(QMouseEvent* event) override; 0132 virtual void leaveEvent(QEvent* event) override; 0133 virtual bool eventFilter(QObject* watched, QEvent* event) override; 0134 0135 protected Q_SLOTS: 0136 void slotCurrentChanged(int index); 0137 void slotDelayedTabRaise(); 0138 void slotSettingsChanged(int category); 0139 //! Used for delayed loading of the "create" toolbar. Called only once. 0140 void setupCreateWidgetToolbar(); 0141 void slotTabDoubleClicked(int index); 0142 void tabBarAnimationFinished(); 0143 0144 private: 0145 void addAction(KToolBar *tbar, const char* actionName); 0146 void addSeparatorAndAction(KToolBar *tbar, const char* actionName); 0147 0148 class Private; 0149 Private * const d; 0150 }; 0151 0152 class EmptyMenuContentWidget : public QWidget 0153 { 0154 Q_OBJECT 0155 public: 0156 explicit EmptyMenuContentWidget(QWidget* parent = 0); 0157 0158 void alterBackground(); 0159 0160 virtual void changeEvent(QEvent *e) override; 0161 }; 0162 0163 //! @todo KEXI3 is KexiMenuWidgetStyle needed? 0164 #if 0 0165 //! A style proxy for KexiMenuWidget 0166 class KexiMenuWidgetStyle : public KexiUtils::StyleProxy 0167 { 0168 public: 0169 explicit KexiMenuWidgetStyle(QStyle *style, QObject *parent = 0); 0170 0171 virtual ~KexiMenuWidgetStyle(); 0172 0173 virtual void drawControl(ControlElement element, const QStyleOption *option, 0174 QPainter *painter, const QWidget *widget = 0) const; 0175 }; 0176 #endif 0177 0178 //! Main menu 0179 class KexiMainMenu : public QWidget 0180 { 0181 Q_OBJECT 0182 public: 0183 explicit KexiMainMenu(KexiTabbedToolBar *toolBar, QWidget* parent = 0); 0184 0185 ~KexiMainMenu(); 0186 0187 virtual bool eventFilter(QObject * watched, QEvent* event) override; 0188 0189 void setContent(QWidget *contentWidget); 0190 0191 const QWidget *contentWidget() const; 0192 0193 void setPersistentlySelectedAction(KexiMenuWidgetAction* action, bool set); 0194 0195 /* void setActiveAction(QAction* action = 0);*/ 0196 0197 void selectFirstItem(); 0198 0199 tristate showProjectMigrationWizard( 0200 const QString& mimeType, const QString& databaseName, const KDbConnectionData *cdata); 0201 0202 Q_SIGNALS: 0203 void contentAreaPressed(); 0204 void hideContentsRequested(); 0205 0206 protected Q_SLOTS: 0207 //void contentWidgetDestroyed(); 0208 0209 protected: 0210 virtual void showEvent(QShowEvent * event) override; 0211 0212 private: 0213 QPointer<KexiMenuWidget> m_menuWidget; 0214 KexiTabbedToolBar* m_toolBar; 0215 bool m_initialized; 0216 EmptyMenuContentWidget *m_content; 0217 QStackedLayout *m_contentLayout = nullptr; 0218 QPointer<QWidget> m_contentWidget; 0219 QVBoxLayout* m_mainContentLayout = nullptr; 0220 QPointer<KexiMenuWidgetAction> m_persistentlySelectedAction; 0221 bool m_selectFirstItem; 0222 }; 0223 0224 class KexiTabbedToolBarTabBar; 0225 0226 //! @internal 0227 class Q_DECL_HIDDEN KexiTabbedToolBar::Private : public QObject 0228 { 0229 Q_OBJECT 0230 public: 0231 explicit Private(KexiTabbedToolBar *t); 0232 0233 KToolBar *createToolBar(const char *name, const QString& caption); 0234 0235 int tabIndex; 0236 0237 public Q_SLOTS: 0238 void showMainMenu(const char* actionName = 0); 0239 void hideMainMenu(); 0240 void hideContentsOrMainMenu(); 0241 void toggleMainMenu(); 0242 void updateMainMenuGeometry(); 0243 0244 //! Initializes global search line edit. If it is enabled, it's created, if disabled, it's deleted. 0245 void initSearchLineEdit(); 0246 0247 public: 0248 KexiTabbedToolBarTabBar *customTabBar; 0249 QPointer<KexiMainMenu> mainMenu; 0250 0251 KexiTabbedToolBar *q; 0252 KActionCollection *ac; 0253 int createId; 0254 KToolBar *createWidgetToolBar; 0255 QHBoxLayout *helpLayer; 0256 #ifdef KEXI_AUTORISE_TABBED_TOOLBAR 0257 //! Used for delayed tab raising 0258 int tabToRaise; 0259 //! Used for delayed tab raising 0260 QTimer tabRaiseTimer; 0261 #endif 0262 //! Toolbars for name 0263 QHash<QString, KToolBar*> toolbarsForName; 0264 QHash<QString, int> toolbarsIndexForName; 0265 QHash<QString, QString> toolbarsCaptionForName; 0266 QVector<bool> toolbarsVisibleForIndex; 0267 QHash<QWidget*, QAction*> extraActions; 0268 bool rolledUp; 0269 QPropertyAnimation tabBarAnimation; 0270 QGraphicsOpacityEffect tabBarOpacityEffect; 0271 int rolledUpIndex; 0272 KexiSearchLineEdit *searchLineEdit = nullptr; 0273 void setCurrentTab(const QString& name); 0274 void hideTab(const QString& name); 0275 void showTab(const QString& name); 0276 bool isTabVisible(const QString& name) const; 0277 #ifndef NDEBUG 0278 void debugToolbars() const; 0279 #endif 0280 int lowestIndex; 0281 }; 0282 0283 class KexiTabbedToolBarStyle; 0284 0285 //! Tab bar reimplementation for KexiTabbedToolBar. 0286 /*! The main its purpose is to alter the width of "Kexi" tab. 0287 */ 0288 class KexiTabbedToolBarTabBar : public QTabBar 0289 { 0290 Q_OBJECT 0291 public: 0292 explicit KexiTabbedToolBarTabBar(QWidget *parent = 0); 0293 virtual QSize originalTabSizeHint(int index) const; 0294 virtual QSize tabSizeHint(int index) const override; 0295 0296 KexiTabbedToolBarStyle* customStyle; 0297 }; 0298 0299 //! Style proxy for KexiTabbedToolBar, to get the "Kexi" tab style right. 0300 class KexiTabbedToolBarStyle : public QProxyStyle 0301 { 0302 Q_OBJECT 0303 public: 0304 explicit KexiTabbedToolBarStyle(const QString &baseStyleName); 0305 0306 virtual ~KexiTabbedToolBarStyle(); 0307 0308 virtual void drawControl(ControlElement element, const QStyleOption *option, 0309 QPainter *painter, const QWidget *widget = 0) const override; 0310 0311 virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, 0312 QPainter *painter, const QWidget *widget = 0) const override; 0313 0314 virtual int pixelMetric(PixelMetric metric, const QStyleOption* option = 0, 0315 const QWidget* widget = 0) const override; 0316 }; 0317 0318 //! Style proxy for KexiTabbedToolBar, to fix the hardcoded margins (e.g. for Breeze). 0319 class KexiDockWidgetStyle : public QProxyStyle 0320 { 0321 Q_OBJECT 0322 public: 0323 explicit KexiDockWidgetStyle(const QString &baseStyleName); 0324 0325 virtual ~KexiDockWidgetStyle(); 0326 0327 using QProxyStyle::polish; 0328 void polish(QWidget* widget) override; 0329 }; 0330 0331 //------------------------------------------ 0332 0333 //! @internal Dock widget with floating disabled but still collapsible 0334 class KexiDockWidget : public QDockWidget 0335 { 0336 Q_OBJECT 0337 public: 0338 KexiDockWidget(const QString &tabText, QWidget *parent); 0339 0340 virtual ~KexiDockWidget(); 0341 0342 virtual void setSizeHint(const QSize& hint); 0343 0344 virtual QSize sizeHint() const override; 0345 0346 const QString tabText; //!< for tab bar tabs 0347 0348 protected: 0349 virtual void paintEvent(QPaintEvent *pe) override; 0350 0351 private: 0352 class Private; 0353 Private * const d; 0354 }; 0355 0356 //------------------------------------------ 0357 0358 //! @internal safer dictionary 0359 typedef QMap< int, KexiWindow* > KexiWindowDict; 0360 0361 //! @internal 0362 class Q_DECL_HIDDEN KexiMainWindow::Private 0363 { 0364 public: 0365 explicit Private(KexiMainWindow* w); 0366 0367 ~Private(); 0368 0369 #ifndef KEXI_NO_PENDING_DIALOGS 0370 //! Job type. Currently used for marking items as being opened or closed. 0371 enum PendingJobType { 0372 NoJob = 0, 0373 WindowOpeningJob, 0374 WindowClosingJob 0375 }; 0376 0377 KexiWindow *openedWindowFor(const KexiPart::Item* item, PendingJobType &pendingType); 0378 0379 KexiWindow *openedWindowFor(int identifier, PendingJobType &pendingType); 0380 0381 void addItemToPendingWindows(const KexiPart::Item* item, PendingJobType jobType); 0382 0383 bool pendingWindowsExist(); 0384 0385 void removePendingWindow(int identifier); 0386 #else 0387 KexiWindow *openedWindowFor(int identifier); 0388 #endif 0389 0390 void insertWindow(KexiWindow *window); 0391 0392 bool windowContainerExistsFor(int identifier) const; 0393 0394 void setWindowContainerExistsFor(int identifier, bool set); 0395 0396 void updateWindowId(KexiWindow *window, int oldItemID); 0397 0398 void removeWindow(int identifier); 0399 0400 int openedWindowsCount(); 0401 0402 //! Used in KexiMainWindowe::closeProject() 0403 void clearWindows(); 0404 0405 void showStartProcessMsg(const QStringList& args); 0406 0407 //! Updates Property Editor Pane's visibility for the current window and the @a viewMode view mode. 0408 /*! @a info can be provided to hadle cases when current window is not yet defined (in openObject()). */ 0409 void updatePropEditorVisibility(Kexi::ViewMode viewMode, KexiPart::Info *info = 0); 0410 0411 //void setTabBarVisible(KMultiTabBar::KMultiTabBarPosition position, int id, 0412 // KexiDockWidget *dockWidget, bool visible); 0413 0414 //void setPropertyEditorTabBarVisible(bool visible); 0415 0416 QObject *openedCustomObjectsForItem(KexiPart::Item* item, const char* name); 0417 0418 void addOpenedCustomObjectForItem(KexiPart::Item* item, QObject* object, const char* name); 0419 0420 KexiFindDialog *findDialog(); 0421 0422 /*! Updates the find/replace dialog depending on the active view. 0423 Nothing is performed if the dialog is not instantiated yet or is invisible. */ 0424 void updateFindDialogContents(bool createIfDoesNotExist = false); 0425 0426 //! \return the current view if it supports \a actionName, otherwise returns 0. 0427 KexiView *currentViewSupportingAction(const char* actionName) const; 0428 0429 //! \return the current view if it supports KexiSearchAndReplaceViewInterface. 0430 KexiSearchAndReplaceViewInterface* currentViewSupportingSearchAndReplaceInterface() const; 0431 0432 tristate showProjectMigrationWizard( 0433 const QString& mimeType, const QString& databaseName, const KDbConnectionData *cdata); 0434 0435 KPropertyEditorView *propertyEditor() const; 0436 0437 //! Show mode for panes 0438 enum ShowMode { 0439 ShowImmediately, 0440 ShowAnimated 0441 }; 0442 0443 //! Sets visibility of the project navigator without or without animating it. 0444 //! Related action is checked/unchecked accordingly. 0445 void setProjectNavigatorVisible(bool set, ShowMode mode = ShowImmediately); 0446 0447 inline void addAction(QMenu *menu, const char* actionName) { 0448 menu->addAction(actionCollection->action(QLatin1String(actionName))); 0449 } 0450 0451 /** 0452 * Returns current page of active visible main menu widget or @c nullptr if there is no visible 0453 * menu widget or menu widget contains no page. 0454 */ 0455 KexiAssistantPage *visibleMainMenuWidgetPage(); 0456 0457 KexiMainWindow *wnd; 0458 QStackedWidget *globalViewStack; 0459 KexiObjectViewWidget *objectViewWidget; 0460 QPointer<KexiFadeWidgetEffect> propertyPaneAnimation; 0461 KActionCollection *actionCollection; 0462 KexiGlobalViewModeSelector *modeSelector; 0463 KHelpMenu *helpMenu; 0464 KexiProject *prj; 0465 KSharedConfig::Ptr config; 0466 #ifdef KEXI_SHOW_CONTEXT_HELP 0467 KexiContextHelp *ctxHelp; 0468 #endif 0469 KexiTabbedToolBar *tabbedToolBar; 0470 QMap<int, QString> tabsToActivateOnShow; 0471 //! poits to kexi part which has been previously used to setup proppanel's tabs using 0472 //! KexiPart::setupCustomPropertyPanelTabs(), in updateCustomPropertyPanelTabs(). 0473 QPointer<KexiPart::Part> partForPreviouslySetupPropertyPanelTabs; 0474 QMap<KexiPart::Part*, int> recentlySelectedPropertyPanelPages; 0475 QPointer<KPropertySet> propertySet; 0476 0477 KexiNameDialog *nameDialog; 0478 QTimer timer; //!< helper timer 0479 QString appCaptionPrefix; //<! application's caption prefix - prj name (if opened), else: null 0480 0481 #ifndef KEXI_SHOW_UNIMPLEMENTED 0482 KActionMenu *dummy_action; 0483 #endif 0484 0485 //! Kexi menu 0486 QAction *action_save, *action_save_as, 0487 *action_project_import_export_send, *action_close, 0488 *action_project_properties, 0489 *action_project_relations, *action_project_import_data_table, 0490 *action_project_export_data_table; 0491 QAction *action_project_print, *action_project_print_preview, 0492 *action_project_print_setup; 0493 QAction *action_project_welcome; 0494 QAction *action_settings; 0495 0496 //! edit menu 0497 QAction *action_edit_delete, *action_edit_delete_row, 0498 *action_edit_cut, *action_edit_copy, *action_edit_paste, 0499 *action_edit_find, *action_edit_findnext, *action_edit_findprev, 0500 *action_edit_replace, *action_edit_replace_all, 0501 *action_edit_select_all, 0502 *action_edit_undo, *action_edit_redo, 0503 *action_edit_insert_empty_row, 0504 *action_edit_edititem, *action_edit_clear_table, 0505 *action_edit_paste_special_data_table, 0506 *action_edit_copy_special_data_table; 0507 0508 //! data menu 0509 QAction *action_data_save_row; 0510 QAction *action_data_cancel_row_changes; 0511 QAction *action_data_execute; 0512 0513 //! format menu 0514 QAction *action_format_font; 0515 0516 //! tools menu 0517 QAction *action_tools_import_project, *action_tools_compact_database, *action_tools_data_import; 0518 QAction *action_tools_locate; 0519 0520 //! window menu 0521 KToggleAction *action_show_nav; 0522 KToggleAction *action_show_propeditor; 0523 QAction *action_activate_nav; 0524 QAction *action_activate_mainarea; 0525 QAction *action_activate_propeditor; 0526 QAction *action_window_next, *action_window_previous, *action_window_fullscreen; 0527 QAction *action_close_tab, *action_close_all_tabs; 0528 QAction *action_tab_next, *action_tab_previous; 0529 0530 //! for dock windows 0531 0532 QPointer<QWidget> focus_before_popup; 0533 0534 //! Set to true only in destructor, used by closeWindow() to know if 0535 //! user can cancel window closing. If true user even doesn't see any messages 0536 //! before closing a window. This is for extremely sanity... and shouldn't be even needed. 0537 bool forceWindowClosing; 0538 0539 //! Indicates that we're inside closeWindow() method - to avoid inf. recursion 0540 //! on window removing 0541 bool insideCloseWindow; 0542 0543 #ifndef KEXI_NO_PENDING_DIALOGS 0544 //! Used in executeActionWhenPendingJobsAreFinished(). 0545 enum ActionToExecuteWhenPendingJobsAreFinished { 0546 NoAction, 0547 QuitAction, 0548 CloseProjectAction 0549 }; 0550 ActionToExecuteWhenPendingJobsAreFinished actionToExecuteWhenPendingJobsAreFinished; 0551 0552 void executeActionWhenPendingJobsAreFinished(); 0553 #endif 0554 0555 //! Used for delayed windows closing for 'close all' 0556 QList<KexiWindow*> windowsToClose; 0557 0558 #ifdef KEXI_QUICK_PRINTING_SUPPORT 0559 //! Opened page setup dialogs, used by printOrPrintPreviewForItem(). 0560 QHash<int, KexiWindow*> pageSetupWindows; 0561 0562 /*! A map from Kexi dialog to "print setup" part item's ID of the data item 0563 used by closeWindow() to find an ID of the data item, so the entry 0564 can be removed from pageSetupWindows dictionary. */ 0565 QMap<int, int> pageSetupWindowItemID2dataItemID_map; 0566 #endif 0567 0568 //! Indicates if project is started in User Mode 0569 bool userMode; 0570 0571 //! Indicates if project navigator should be visible 0572 bool isProjectNavigatorVisible; 0573 0574 //! Indicates if the main menu should be visible 0575 bool isMainMenuVisible; 0576 0577 //! Set in restoreSettings() and used in initNavigator() 0578 //! to customize navigator visibility on startup 0579 bool forceShowProjectNavigatorOnCreation; 0580 bool forceHideProjectNavigatorOnCreation; 0581 0582 bool navWasVisibleBeforeProjectClosing; 0583 bool saveSettingsForShowProjectNavigator; 0584 0585 //! Used by openedCustomObjectsForItem() and addOpenedCustomObjectForItem() 0586 QHash<QByteArray, QObject*> m_openedCustomObjectsForItem; 0587 0588 int propEditorDockSeparatorPos, navDockSeparatorPos; 0589 0590 bool wasAutoOpen; 0591 bool windowExistedBeforeCloseProject; 0592 0593 bool propertyEditorCollapsed; 0594 0595 bool enable_slotPropertyEditorVisibilityChanged; 0596 0597 KexiUserFeedbackAgent userFeedback; 0598 0599 KexiMigrateManagerInterface* migrateManager; 0600 0601 private: 0602 //! @todo move to KexiProject 0603 KexiWindowDict windows; 0604 //! A set of item identifiers for whose there are KexiWindowContainer instances already. 0605 //! This lets to verify that KexiWindow is about to be constructed and opened so multiple 0606 //! opening can be avoided. 0607 QSet<int> windowContainers; 0608 #ifndef KEXI_NO_PROCESS_EVENTS 0609 QHash<int, PendingJobType> pendingWindows; //!< part item identifiers for windows whoose opening has been started 0610 //! @todo QMutex dialogsMutex; //!< used for locking windows and pendingWindows dicts 0611 #endif 0612 KexiFindDialog *m_findDialog; 0613 }; 0614 0615 //------------------------------------------ 0616 0617 //! Action shortcut used by KexiMainWindow::setupMainMenuActionShortcut(QAction *) 0618 //! Activates action only if enabled. 0619 class KexiMainMenuActionShortcut : public QShortcut 0620 { 0621 Q_OBJECT 0622 public: 0623 KexiMainMenuActionShortcut(const QKeySequence& key, QAction *action, QWidget *parent); 0624 0625 virtual ~KexiMainMenuActionShortcut(); 0626 0627 protected Q_SLOTS: 0628 //! Triggers associated action only when this action is enabled 0629 void slotActivated(); 0630 0631 private: 0632 QPointer<QAction> m_action; 0633 }; 0634 0635 #endif