├── .gitignore ├── doc ├── 0.gif ├── 1.png ├── 2.png ├── build.sh └── doxygen.css ├── example ├── qtwm_example.pro ├── toolwindowmanager.ui ├── main.cpp ├── toolwindowmanager.h └── toolwindowmanager.cpp ├── libqtoolwindowmanager ├── qtoolwindowmanager.pro ├── private │ ├── qtoolwindowmanagerwrapper_p.h │ ├── qtoolwindowmanagerarea_p.h │ └── qtoolwindowmanager_p.h ├── qabstracttoolwindowmanagerarea.h ├── qtoolwindowmanagerwrapper.cpp ├── qabstracttoolwindowmanagerarea.cpp ├── qtoolwindowmanager.h ├── qtoolwindowmanagerarea.cpp └── qtoolwindowmanager.cpp ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | *~ 3 | 4 | -------------------------------------------------------------------------------- /doc/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Riateche/toolwindowmanager/HEAD/doc/0.gif -------------------------------------------------------------------------------- /doc/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Riateche/toolwindowmanager/HEAD/doc/1.png -------------------------------------------------------------------------------- /doc/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Riateche/toolwindowmanager/HEAD/doc/2.png -------------------------------------------------------------------------------- /doc/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | doxygen 3 | mv html/class_q_*.html . 4 | rm -r html 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/qtwm_example.pro: -------------------------------------------------------------------------------- 1 | lessThan(QT_MAJOR_VERSION, 5) { 2 | QT += gui 3 | } else { 4 | QT += widgets 5 | } 6 | 7 | HEADERS = toolwindowmanager.h 8 | SOURCES = toolwindowmanager.cpp \ 9 | main.cpp 10 | 11 | FORMS = toolwindowmanager.ui 12 | 13 | LIBS += -lqtoolwindowmanager -L../build-libqtoolwindowmanager 14 | 15 | INCLUDEPATH += ../libqtoolwindowmanager 16 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/qtoolwindowmanager.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = lib 2 | 3 | QT += widgets 4 | 5 | OTHER_FILES += \ 6 | qtoolwindowmanager.pro.user 7 | 8 | HEADERS += \ 9 | qabstracttoolwindowmanagerarea.h \ 10 | qtoolwindowmanager.h \ 11 | private/qtoolwindowmanagerarea_p.h \ 12 | private/qtoolwindowmanager_p.h \ 13 | private/qtoolwindowmanagerwrapper_p.h 14 | 15 | SOURCES += \ 16 | qabstracttoolwindowmanagerarea.cpp \ 17 | qtoolwindowmanager.cpp \ 18 | qtoolwindowmanagerarea.cpp \ 19 | qtoolwindowmanagerwrapper.cpp 20 | 21 | DEFINES += QTOOLWINDOWMANAGER_BUILD_LIB 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ToolWindowManager 2 | ================= 3 | 4 | ToolWindowManager is a Qt based tool window manager. 5 | 6 | This project implements docking tool behavior that is similar to tool windows mechanism in Visual Studio or Eclipse. User can arrange tool windows in tabs, dock it to any border, split with vertical and horizontal splitters, tabify them together and detach to floating windows. 7 | 8 | [API documentation](http://riateche.github.io/toolwindowmanager/doc/class_q_tool_window_manager.html) 9 | 10 | Demo (animated GIF): 11 | 12 | ![demo](doc/0.gif) 13 | 14 | More screenshots: 15 | 16 | ![screenshot](doc/1.png) 17 | 18 | ![screenshot](doc/2.png) 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Pavel Strakhov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /example/toolwindowmanager.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ToolWindowManager 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | ToolWindowManager 15 | 16 | 17 | 18 | 19 | 0 20 | 21 | 22 | 0 23 | 24 | 25 | 0 26 | 27 | 28 | 0 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 0 39 | 0 40 | 400 41 | 23 42 | 43 | 44 | 45 | 46 | Tool windows 47 | 48 | 49 | 50 | 51 | Storage 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Config 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | Save state 71 | 72 | 73 | 74 | 75 | Restore state 76 | 77 | 78 | 79 | 80 | Clear state and exit 81 | 82 | 83 | 84 | 85 | true 86 | 87 | 88 | true 89 | 90 | 91 | Closable tabs 92 | 93 | 94 | 95 | 96 | 97 | 98 | QToolWindowManager 99 | QWidget 100 |
qtoolwindowmanager.h
101 | 1 102 |
103 |
104 | 105 | 106 |
107 | -------------------------------------------------------------------------------- /example/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the examples of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:BSD$ 29 | ** You may use this file under the terms of the BSD license as follows: 30 | ** 31 | ** "Redistribution and use in source and binary forms, with or without 32 | ** modification, are permitted provided that the following conditions are 33 | ** met: 34 | ** * Redistributions of source code must retain the above copyright 35 | ** notice, this list of conditions and the following disclaimer. 36 | ** * Redistributions in binary form must reproduce the above copyright 37 | ** notice, this list of conditions and the following disclaimer in 38 | ** the documentation and/or other materials provided with the 39 | ** distribution. 40 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 41 | ** of its contributors may be used to endorse or promote products derived 42 | ** from this software without specific prior written permission. 43 | ** 44 | ** 45 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 46 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 47 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 48 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 49 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 51 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 55 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 56 | ** 57 | ** $QT_END_LICENSE$ 58 | ** 59 | ****************************************************************************/ 60 | 61 | #include 62 | 63 | #include "toolwindowmanager.h" 64 | 65 | int main(int argc, char *argv[]) 66 | { 67 | QApplication app(argc, argv); 68 | app.setOrganizationName("QtProject"); 69 | app.setApplicationName("ToolWindowManagerTest"); 70 | ToolWindowManager manager; 71 | manager.show(); 72 | return app.exec(); 73 | } 74 | -------------------------------------------------------------------------------- /example/toolwindowmanager.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the examples of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:BSD$ 29 | ** You may use this file under the terms of the BSD license as follows: 30 | ** 31 | ** "Redistribution and use in source and binary forms, with or without 32 | ** modification, are permitted provided that the following conditions are 33 | ** met: 34 | ** * Redistributions of source code must retain the above copyright 35 | ** notice, this list of conditions and the following disclaimer. 36 | ** * Redistributions in binary form must reproduce the above copyright 37 | ** notice, this list of conditions and the following disclaimer in 38 | ** the documentation and/or other materials provided with the 39 | ** distribution. 40 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 41 | ** of its contributors may be used to endorse or promote products derived 42 | ** from this software without specific prior written permission. 43 | ** 44 | ** 45 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 46 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 47 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 48 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 49 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 51 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 55 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 56 | ** 57 | ** $QT_END_LICENSE$ 58 | ** 59 | ****************************************************************************/ 60 | 61 | #ifndef TOOLWINDOWMANAGER_H 62 | #define TOOLWINDOWMANAGER_H 63 | 64 | #include 65 | 66 | namespace Ui { 67 | class ToolWindowManager; 68 | } 69 | 70 | class ToolWindowManager : public QMainWindow 71 | { 72 | Q_OBJECT 73 | public: 74 | explicit ToolWindowManager(QWidget *parent = 0); 75 | ~ToolWindowManager(); 76 | 77 | private: 78 | Ui::ToolWindowManager *ui; 79 | QList actions; 80 | 81 | private slots: 82 | void toolWindowActionToggled(bool state); 83 | void toolWindowVisibilityChanged(QWidget *toolWindow, bool visible); 84 | void on_actionSaveState_triggered(); 85 | void on_actionRestoreState_triggered(); 86 | void on_actionClearState_triggered(); 87 | void on_actionClosableTabs_toggled(bool checked); 88 | }; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/private/qtoolwindowmanagerwrapper_p.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #ifndef QTOOLWINDOWMANAGERWRAPPER_P_H 63 | #define QTOOLWINDOWMANAGERWRAPPER_P_H 64 | 65 | #include 66 | #if QT_VERSION >= 0x050000 67 | #include 68 | #else 69 | #include 70 | #define Q_DECL_OVERRIDE 71 | #endif 72 | 73 | #include 74 | 75 | QT_BEGIN_NAMESPACE 76 | 77 | #ifndef QT_NO_TOOLWINDOWMANAGER 78 | 79 | class QToolWindowManager; 80 | 81 | /*! 82 | * The ToolWindowManagerWrapper class is used by ToolWindowManager to wrap its content. 83 | * One wrapper is a direct child of the manager and contains tool windows that are inside its window. 84 | * All other wrappers are top level floating windows that contain detached tool windows. 85 | * 86 | */ 87 | class QToolWindowManagerWrapper : public QWidget 88 | { 89 | Q_OBJECT 90 | public: 91 | explicit QToolWindowManagerWrapper(QToolWindowManager *manager); 92 | virtual ~QToolWindowManagerWrapper(); 93 | 94 | protected: 95 | // Reimplemented to register hiding of contained tool windows when user closes the floating window. 96 | void closeEvent(QCloseEvent *) Q_DECL_OVERRIDE; 97 | 98 | private: 99 | Q_DISABLE_COPY(QToolWindowManagerWrapper) 100 | QToolWindowManager *m_manager; 101 | 102 | //dump content's layout to variable 103 | QVariantMap saveState() const; 104 | 105 | //construct layout based on given dump 106 | void restoreState(const QVariantMap& data); 107 | 108 | friend class QToolWindowManager; 109 | }; 110 | 111 | #endif // QT_NO_TOOLWINDOWMANAGER 112 | 113 | QT_END_NAMESPACE 114 | 115 | #endif // QTOOLWINDOWMANAGERWRAPPER_P_H 116 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/qabstracttoolwindowmanagerarea.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #ifndef QABSTRACTTOOLWINDOWMANAGERAREA_H 63 | #define QABSTRACTTOOLWINDOWMANAGERAREA_H 64 | 65 | #include 66 | 67 | #if defined QTOOLWINDOWMANAGER_BUILD_LIB 68 | #define QTOOLWINDOWMANAGER_EXPORT Q_DECL_EXPORT 69 | #else 70 | #define QTOOLWINDOWMANAGER_EXPORT Q_DECL_IMPORT 71 | #endif 72 | 73 | QT_BEGIN_NAMESPACE 74 | 75 | #ifndef QT_NO_TOOLWINDOWMANAGER 76 | 77 | class QToolWindowManager; 78 | 79 | class QTOOLWINDOWMANAGER_EXPORT QAbstractToolWindowManagerArea : public QWidget 80 | { 81 | Q_OBJECT 82 | public: 83 | explicit QAbstractToolWindowManagerArea(QToolWindowManager *manager); 84 | QToolWindowManager *manager() const; 85 | virtual QWidgetList toolWindows() const = 0; 86 | virtual void activateToolWindow(QWidget *toolWindow) = 0; 87 | //todo: add API for adding tool windows here for user 88 | 89 | protected: 90 | virtual void addToolWindows(const QWidgetList &toolWindows) = 0; 91 | virtual void removeToolWindow(QWidget *toolWindow) = 0; 92 | virtual QVariant saveState() const; 93 | virtual void restoreState(const QVariant &state); 94 | virtual void beforeTabButtonChanged(QWidget *toolWindow); 95 | virtual void tabButtonChanged(QWidget *toolWindow); 96 | 97 | 98 | void updateDragPosition(); 99 | void startDrag(const QWidgetList &toolWindows); 100 | 101 | QToolWindowManager *m_manager; 102 | friend class QToolWindowManager; 103 | friend class QToolWindowManagerPrivate; 104 | 105 | private: 106 | Q_DISABLE_COPY(QAbstractToolWindowManagerArea) 107 | }; 108 | 109 | #endif // QT_NO_TOOLWINDOWMANAGER 110 | 111 | QT_END_NAMESPACE 112 | 113 | #endif // QABSTRACTTOOLWINDOWMANAGERAREA_H 114 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/private/qtoolwindowmanagerarea_p.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #ifndef QTOOLWINDOWMANAGERAREA_H 63 | #define QTOOLWINDOWMANAGERAREA_H 64 | 65 | #include 66 | #if QT_VERSION >= 0x050000 67 | #include 68 | #else 69 | #include 70 | #endif 71 | 72 | #include 73 | #include "qabstracttoolwindowmanagerarea.h" 74 | 75 | QT_BEGIN_NAMESPACE 76 | 77 | #ifndef QT_NO_TOOLWINDOWMANAGER 78 | 79 | class QToolWindowManager; 80 | class QToolWindowManagerAreaPrivate; 81 | 82 | class QToolWindowManagerArea : public QAbstractToolWindowManagerArea 83 | { 84 | Q_OBJECT 85 | public: 86 | explicit QToolWindowManagerArea(QToolWindowManager *manager); 87 | virtual ~QToolWindowManagerArea(); 88 | QWidgetList toolWindows() const; 89 | void activateToolWindow(QWidget *toolWindow); 90 | 91 | protected: 92 | void addToolWindows(const QWidgetList &toolWindows); 93 | void removeToolWindow(QWidget *toolWindow); 94 | QVariant saveState() const; 95 | void restoreState(const QVariant &state); 96 | void beforeTabButtonChanged(QWidget *toolWindow); 97 | void tabButtonChanged(QWidget *toolWindow); 98 | 99 | virtual void mousePressEvent(QMouseEvent *); 100 | virtual void mouseReleaseEvent(QMouseEvent *); 101 | virtual void mouseMoveEvent(QMouseEvent *); 102 | virtual bool eventFilter(QObject *object, QEvent *event); 103 | 104 | private: 105 | Q_DISABLE_COPY(QToolWindowManagerArea) 106 | Q_DECLARE_PRIVATE(QToolWindowManagerArea) 107 | QToolWindowManagerAreaPrivate* d_ptr; 108 | 109 | void releaseTabButtons(QWidget *toolWindow); 110 | void applyTabButtons(QWidget *toolWindow); 111 | 112 | friend class QToolWindowManager; 113 | friend class QToolWindowManagerPrivate; 114 | friend class QToolWindowManagerWrapper; 115 | 116 | private slots: 117 | void managerTabsClosableChanged(bool enabled); 118 | }; 119 | 120 | #endif // QT_NO_TOOLWINDOWMANAGER 121 | 122 | QT_END_NAMESPACE 123 | 124 | 125 | #endif // QTOOLWINDOWMANAGERAREA_H 126 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/qtoolwindowmanagerwrapper.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | 71 | QT_BEGIN_NAMESPACE 72 | 73 | #ifndef QT_NO_TOOLWINDOWMANAGER 74 | 75 | 76 | QToolWindowManagerWrapper::QToolWindowManagerWrapper(QToolWindowManager *manager) : 77 | QWidget(manager) 78 | , m_manager(manager) 79 | { 80 | setWindowFlags(windowFlags() | Qt::Tool); 81 | setWindowTitle(QLatin1String(" ")); 82 | 83 | QVBoxLayout *mainLayout = new QVBoxLayout(this); 84 | mainLayout->setContentsMargins(0, 0, 0, 0); 85 | QToolWindowManagerPrivate * const manager_d = m_manager->d_func(); 86 | manager_d->m_wrappers << this; 87 | } 88 | 89 | QToolWindowManagerWrapper::~QToolWindowManagerWrapper() 90 | { 91 | QToolWindowManagerPrivate * const manager_d = m_manager->d_func(); 92 | manager_d->m_wrappers.removeOne(this); 93 | } 94 | 95 | void QToolWindowManagerWrapper::closeEvent(QCloseEvent *) 96 | { 97 | QList toolWindows; 98 | foreach (QAbstractToolWindowManagerArea *tabWidget, findChildren()) 99 | toolWindows << tabWidget->toolWindows(); 100 | m_manager->moveToolWindows(toolWindows, QToolWindowManager::NoArea); 101 | } 102 | 103 | QVariantMap QToolWindowManagerWrapper::saveState() const 104 | { 105 | if (layout()->count() > 1) { 106 | qWarning("too many children for wrapper"); 107 | return QVariantMap(); 108 | } 109 | if (isWindow() && layout()->count() == 0) { 110 | qWarning("empty top level wrapper"); 111 | return QVariantMap(); 112 | } 113 | QVariantMap result; 114 | result[QLatin1String("geometry")] = saveGeometry(); 115 | QSplitter *splitter = findChild(); 116 | QToolWindowManagerPrivate * const manager_d = m_manager->d_func(); 117 | if (splitter) { 118 | result[QLatin1String("splitter")] = manager_d->saveSplitterState(splitter); 119 | } else { 120 | QAbstractToolWindowManagerArea *area = findChild(); 121 | if (area) { 122 | result[QLatin1String("area")] = manager_d->saveAreaState(area); 123 | } else if (layout()->count() > 0) { 124 | qWarning("unknown child"); 125 | return QVariantMap(); 126 | } 127 | } 128 | return result; 129 | } 130 | 131 | void QToolWindowManagerWrapper::restoreState(const QVariantMap &data) 132 | { 133 | restoreGeometry(data[QLatin1String("geometry")].toByteArray()); 134 | if (layout()->count() > 0) { 135 | qWarning("wrapper is not empty"); 136 | return; 137 | } 138 | QToolWindowManagerPrivate * const manager_d = m_manager->d_func(); 139 | if (data.contains(QLatin1String("splitter"))) { 140 | layout()->addWidget(manager_d->restoreSplitterState(data[QLatin1String("splitter")].toMap())); 141 | } else if (data.contains(QLatin1String("area"))) { 142 | layout()->addWidget(manager_d->restoreAreaState(data[QLatin1String("area")].toMap())); 143 | } 144 | } 145 | 146 | #endif // QT_NO_TOOLWINDOWMANAGER 147 | 148 | QT_END_NAMESPACE 149 | -------------------------------------------------------------------------------- /example/toolwindowmanager.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the examples of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:BSD$ 29 | ** You may use this file under the terms of the BSD license as follows: 30 | ** 31 | ** "Redistribution and use in source and binary forms, with or without 32 | ** modification, are permitted provided that the following conditions are 33 | ** met: 34 | ** * Redistributions of source code must retain the above copyright 35 | ** notice, this list of conditions and the following disclaimer. 36 | ** * Redistributions in binary form must reproduce the above copyright 37 | ** notice, this list of conditions and the following disclaimer in 38 | ** the documentation and/or other materials provided with the 39 | ** distribution. 40 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 41 | ** of its contributors may be used to endorse or promote products derived 42 | ** from this software without specific prior written permission. 43 | ** 44 | ** 45 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 46 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 47 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 48 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 49 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 51 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 55 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 56 | ** 57 | ** $QT_END_LICENSE$ 58 | ** 59 | ****************************************************************************/ 60 | 61 | #include 62 | #if QT_VERSION >= 0x050000 63 | #include 64 | #else 65 | #include 66 | #endif 67 | 68 | #include "toolwindowmanager.h" 69 | #include "ui_toolwindowmanager.h" 70 | 71 | ToolWindowManager::ToolWindowManager(QWidget *parent) : 72 | QMainWindow(parent), 73 | ui(new Ui::ToolWindowManager) 74 | { 75 | ui->setupUi(this); 76 | connect(ui->toolWindowManager, SIGNAL(toolWindowVisibilityChanged(QWidget*,bool)), 77 | this, SLOT(toolWindowVisibilityChanged(QWidget*,bool))); 78 | 79 | QList toolWindows; 80 | for (int i = 0; i < 6; i++) { 81 | QPushButton *b1 = new QPushButton(QString("tool%1").arg(i + 1)); 82 | b1->setWindowTitle(b1->text()); 83 | b1->setObjectName(b1->text()); 84 | QAction *action = ui->menuToolWindows->addAction(b1->text()); 85 | action->setData(i); 86 | action->setCheckable(true); 87 | action->setChecked(true); 88 | connect(action, SIGNAL(triggered(bool)), this, SLOT(toolWindowActionToggled(bool))); 89 | actions << action; 90 | toolWindows << b1; 91 | } 92 | ui->toolWindowManager->addToolWindow(toolWindows[0], QToolWindowManager::EmptySpaceArea); 93 | ui->toolWindowManager->addToolWindow(toolWindows[1], QToolWindowManager::LastUsedArea); 94 | ui->toolWindowManager->addToolWindow(toolWindows[2], QToolWindowManager::LastUsedArea); 95 | ui->toolWindowManager->addToolWindow(toolWindows[3], 96 | QToolWindowManager::ReferenceLeftOf, ui->toolWindowManager->areaFor(toolWindows[2])); 97 | ui->toolWindowManager->addToolWindow(toolWindows[4], QToolWindowManager::LastUsedArea); 98 | ui->toolWindowManager->addToolWindow(toolWindows[5], 99 | QToolWindowManager::ReferenceTopOf, ui->toolWindowManager->areaFor(toolWindows[4])); 100 | 101 | QToolButton* tabButton1 = new QToolButton(); 102 | tabButton1->setText(tr("t1")); 103 | ui->toolWindowManager->setTabButton(toolWindows[2], QTabBar::LeftSide, tabButton1); 104 | 105 | QToolButton* tabButton2 = new QToolButton(); 106 | tabButton2->setText(tr("t2")); 107 | 108 | ui->toolWindowManager->setTabButton(toolWindows[3], QTabBar::LeftSide, tabButton2); 109 | 110 | resize(600, 400); 111 | on_actionRestoreState_triggered(); 112 | } 113 | 114 | ToolWindowManager::~ToolWindowManager() 115 | { 116 | delete ui; 117 | } 118 | 119 | void ToolWindowManager::toolWindowActionToggled(bool state) 120 | { 121 | int index = static_cast(sender())->data().toInt(); 122 | QWidget *toolWindow = ui->toolWindowManager->toolWindows()[index]; 123 | ui->toolWindowManager->moveToolWindow(toolWindow, state ? 124 | QToolWindowManager::LastUsedArea : 125 | QToolWindowManager::NoArea); 126 | 127 | } 128 | 129 | void ToolWindowManager::toolWindowVisibilityChanged(QWidget *toolWindow, bool visible) 130 | { 131 | int index = ui->toolWindowManager->toolWindows().indexOf(toolWindow); 132 | actions[index]->blockSignals(true); 133 | actions[index]->setChecked(visible); 134 | actions[index]->blockSignals(false); 135 | } 136 | 137 | void ToolWindowManager::on_actionSaveState_triggered() 138 | { 139 | QSettings settings; 140 | settings.setValue("toolWindowManagerState", ui->toolWindowManager->saveState()); 141 | settings.setValue("geometry", saveGeometry()); 142 | } 143 | 144 | void ToolWindowManager::on_actionRestoreState_triggered() 145 | { 146 | QSettings settings; 147 | restoreGeometry(settings.value("geometry").toByteArray()); 148 | ui->toolWindowManager->restoreState(settings.value("toolWindowManagerState")); 149 | } 150 | 151 | void ToolWindowManager::on_actionClearState_triggered() 152 | { 153 | QSettings settings; 154 | settings.remove("geometry"); 155 | settings.remove("toolWindowManagerState"); 156 | QApplication::quit(); 157 | } 158 | 159 | void ToolWindowManager::on_actionClosableTabs_toggled(bool checked) 160 | { 161 | ui->toolWindowManager->setTabsClosable(checked); 162 | } 163 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/qabstracttoolwindowmanagerarea.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #include "qabstracttoolwindowmanagerarea.h" 63 | #include "qtoolwindowmanager.h" 64 | #include 65 | 66 | 67 | QT_BEGIN_NAMESPACE 68 | 69 | #ifndef QT_NO_TOOLWINDOWMANAGER 70 | 71 | 72 | 73 | /*! 74 | \class QAbstractToolWindowManagerArea 75 | 76 | \brief The QAbstractToolWindowManagerArea class is the base class for widgets 77 | used by QToolWindowManager to display one or several tool windows in its layout 78 | or floating windows. 79 | 80 | To customize appearance and behavior of areas, subclass QAbstractToolWindowManagerArea 81 | and implement its virtual functions. Also subclass QToolWindowManager and reimplement 82 | QToolWindowManager::createArea to return new object of created subclass. 83 | 84 | A subclass of QAbstractToolWindowManagerArea should implement displaying one or multiple 85 | tool windows, ability to switch between them, drag one tool window or entire area out of 86 | its place using mouse. 87 | 88 | \inmodule QtWidgets 89 | 90 | \since 5.4 91 | 92 | */ 93 | /*! 94 | \fn QAbstractToolWindowManagerArea::toolWindows() const 95 | 96 | Implement this function to return list of tool windows in this area in actual order. 97 | */ 98 | /*! 99 | \fn QAbstractToolWindowManagerArea::activateToolWindow(QWidget *toolWindow) 100 | 101 | Implement this function to activate (show, raise) \a toolWindow in the area. \a toolWindow 102 | must be a member of the area. 103 | */ 104 | /*! 105 | \fn QAbstractToolWindowManagerArea::addToolWindows(const QWidgetList &toolWindows) 106 | 107 | Implement this function to add \a toolWindows to the area. The area may become a parent 108 | of tool windows to display them. \a toolWindows should appear 109 | in the end of QAbstractToolWindowManagerArea::toolWindows list immediately after this action. 110 | However if the area implementation provides a way to change tool windows order and user has 111 | changed it, QAbstractToolWindowManagerArea::toolWindow order should change accordingly. 112 | */ 113 | /*! 114 | \fn QAbstractToolWindowManagerArea::removeToolWindow(QWidget *toolWindow) 115 | 116 | Implement this function to remove \a toolWindow from the area. Ownership and visibility 117 | of \a toolWindow should not be changed, as it's a responsibility of the manager to adjust them. 118 | */ 119 | 120 | /*! Creates new area for the \a manager. */ 121 | QAbstractToolWindowManagerArea::QAbstractToolWindowManagerArea(QToolWindowManager *manager) : 122 | QWidget(manager), 123 | m_manager(manager) 124 | { 125 | } 126 | 127 | /*! Returns the manager for this area. */ 128 | QToolWindowManager *QAbstractToolWindowManagerArea::manager() const 129 | { 130 | return m_manager; 131 | } 132 | 133 | /*! 134 | * This virtual function should be reimplemented to return additional state data specific 135 | * to this area, e.g. current tool window (if applicable). Default implementation returns 136 | * invalid QVariant. 137 | */ 138 | QVariant QAbstractToolWindowManagerArea::saveState() const 139 | { 140 | return QVariant(); 141 | } 142 | 143 | /*! 144 | * This virtual function should be reimplemented to restore state based on \a state data 145 | * obtained earlier from QAbstractToolWindowManagerArea::saveState function. Default implementation 146 | * does nothing. 147 | */ 148 | void QAbstractToolWindowManagerArea::restoreState(const QVariant &state) 149 | { 150 | Q_UNUSED(state); 151 | } 152 | 153 | void QAbstractToolWindowManagerArea::beforeTabButtonChanged(QWidget* toolWindow) 154 | { 155 | Q_UNUSED(toolWindow); 156 | } 157 | 158 | void QAbstractToolWindowManagerArea::tabButtonChanged(QWidget* toolWindow) 159 | { 160 | Q_UNUSED(toolWindow); 161 | } 162 | 163 | /*! 164 | * When user starts dragging tool windows from the area, it continues to receive mouse events 165 | * even if the mouse pointer leaves its boundaries. Call this function on every mouse move or 166 | * release event to update manager's state according to new mouse state. 167 | * 168 | * TODO: we should try to implement this internally using event filters. 169 | */ 170 | void QAbstractToolWindowManagerArea::updateDragPosition() 171 | { 172 | QToolWindowManagerPrivate * const manager_d = m_manager->d_func(); 173 | manager_d->updateDragPosition(); 174 | } 175 | 176 | /*! 177 | * Call this function to notify the manager that a drag operation on \a toolWindows has begun. 178 | * The manager will take control of this process and move \a toolWindows to new position when 179 | * the drag operation ends successfully. 180 | */ 181 | void QAbstractToolWindowManagerArea::startDrag(const QWidgetList &toolWindows) { 182 | QToolWindowManagerPrivate * const manager_d = m_manager->d_func(); 183 | manager_d->startDrag(toolWindows); 184 | } 185 | 186 | #endif // QT_NO_TOOLWINDOWMANAGER 187 | 188 | QT_END_NAMESPACE 189 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/qtoolwindowmanager.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #ifndef QTOOLWINDOWMANAGER_H 63 | #define QTOOLWINDOWMANAGER_H 64 | 65 | #include 66 | 67 | #if defined QTOOLWINDOWMANAGER_BUILD_LIB 68 | #define QTOOLWINDOWMANAGER_EXPORT Q_DECL_EXPORT 69 | #else 70 | #define QTOOLWINDOWMANAGER_EXPORT Q_DECL_IMPORT 71 | #endif 72 | 73 | #include 74 | #include 75 | 76 | #include 77 | #if QT_VERSION >= 0x050000 78 | #include 79 | #else 80 | #include 81 | #endif 82 | 83 | 84 | 85 | QT_BEGIN_NAMESPACE 86 | 87 | #ifndef QT_NO_TOOLWINDOWMANAGER 88 | 89 | class QAbstractToolWindowManagerArea; 90 | class QToolWindowManagerPrivate; 91 | class QSplitter; 92 | class QRubberBand; 93 | 94 | class QTOOLWINDOWMANAGER_EXPORT QToolWindowManager : public QWidget 95 | { 96 | Q_OBJECT 97 | Q_ENUMS(AreaType ReferenceType) 98 | Q_PROPERTY(int suggestionSwitchInterval READ suggestionSwitchInterval 99 | WRITE setSuggestionSwitchInterval 100 | NOTIFY suggestionSwitchIntervalChanged) 101 | Q_PROPERTY(int borderSensitivity READ borderSensitivity 102 | WRITE setBorderSensitivity 103 | NOTIFY borderSensitivityChanged) 104 | Q_PROPERTY(int rubberBandLineWidth READ rubberBandLineWidth 105 | WRITE setRubberBandLineWidth 106 | NOTIFY rubberBandLineWidthChanged) 107 | Q_PROPERTY(bool tabsClosable READ tabsClosable 108 | WRITE setTabsClosable 109 | NOTIFY tabsClosableChanged) 110 | 111 | public: 112 | explicit QToolWindowManager(QWidget *parent = 0); 113 | ~QToolWindowManager(); 114 | 115 | enum AreaType { 116 | LastUsedArea, 117 | NewFloatingArea, 118 | EmptySpaceArea, 119 | NoArea 120 | }; 121 | 122 | enum ReferenceType { 123 | ReferenceAddTo, 124 | ReferenceLeftOf, 125 | ReferenceRightOf, 126 | ReferenceTopOf, 127 | ReferenceBottomOf 128 | }; 129 | 130 | void addToolWindow(QWidget *toolWindow, AreaType area = LastUsedArea); 131 | void addToolWindow(QWidget *toolWindow, ReferenceType reference, 132 | QAbstractToolWindowManagerArea *area); 133 | void addToolWindows(const QWidgetList &toolWindows, AreaType area = LastUsedArea); 134 | void addToolWindows(const QWidgetList &toolWindows, ReferenceType reference, 135 | QAbstractToolWindowManagerArea *area); 136 | 137 | void moveToolWindow(QWidget *toolWindow, AreaType area = LastUsedArea); 138 | void moveToolWindow(QWidget *toolWindow, ReferenceType reference, 139 | QAbstractToolWindowManagerArea *area); 140 | void moveToolWindows(const QWidgetList &toolWindows, AreaType area = LastUsedArea); 141 | void moveToolWindows(const QWidgetList &toolWindows, ReferenceType reference, 142 | QAbstractToolWindowManagerArea *area); 143 | 144 | QAbstractToolWindowManagerArea *areaFor(QWidget *toolWindow) const; 145 | void removeToolWindow(QWidget *toolWindow); 146 | QWidgetList toolWindows() const; 147 | void hideToolWindow(QWidget *toolWindow); 148 | QVariant saveState() const; 149 | void restoreState(const QVariant& data); 150 | 151 | int suggestionSwitchInterval() const; 152 | void setSuggestionSwitchInterval(int msec); 153 | 154 | int borderSensitivity() const; 155 | void setBorderSensitivity(int pixels); 156 | 157 | int rubberBandLineWidth() const; 158 | void setRubberBandLineWidth(int pixels); 159 | 160 | bool tabsClosable() const; 161 | void setTabsClosable(bool enabled); 162 | 163 | QRubberBand *rectRubberBand() const; 164 | QRubberBand *lineRubberBand() const; 165 | 166 | void setTabButton(QWidget *toolWindow, QTabBar::ButtonPosition position, QWidget *widget); 167 | 168 | Q_SIGNALS: 169 | void toolWindowVisibilityChanged(QWidget *toolWindow, bool visible); 170 | void suggestionSwitchIntervalChanged(int suggestionSwitchInterval); 171 | void borderSensitivityChanged(int borderSensitivity); 172 | void rubberBandLineWidthChanged(int rubberBandLineWidth); 173 | void tabsClosableChanged(bool tabsClosable); 174 | 175 | protected: 176 | virtual QSplitter * createSplitter(); 177 | virtual QAbstractToolWindowManagerArea * createArea(); 178 | virtual QPixmap generateDragPixmap(const QWidgetList &toolWindows); 179 | bool event(QEvent *e); 180 | 181 | private: 182 | Q_DISABLE_COPY(QToolWindowManager) 183 | Q_DECLARE_PRIVATE(QToolWindowManager) 184 | QToolWindowManagerPrivate* d_ptr; 185 | 186 | friend class QToolWindowManagerWrapper; 187 | friend class QAbstractToolWindowManagerArea; 188 | friend class QToolWindowManagerArea; 189 | }; 190 | 191 | #endif // QT_NO_TOOLWINDOWMANAGER 192 | 193 | QT_END_NAMESPACE 194 | 195 | #endif // QTOOLWINDOWMANAGER_H 196 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/private/qtoolwindowmanager_p.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #ifndef QTOOLWINDOWMANAGER_P_H 63 | #define QTOOLWINDOWMANAGER_P_H 64 | 65 | #include 66 | #if QT_VERSION >= 0x050000 67 | #include 68 | #else 69 | #include 70 | #endif 71 | #include 72 | #include 73 | 74 | QT_BEGIN_NAMESPACE 75 | 76 | #ifndef QT_NO_TOOLWINDOWMANAGER 77 | 78 | class QToolWindowManagerAreaReference 79 | { 80 | public: 81 | QToolWindowManagerAreaReference(QToolWindowManager::AreaType type = QToolWindowManager::NoArea); 82 | QToolWindowManagerAreaReference(QToolWindowManager::ReferenceType type, QWidget *widget); 83 | QToolWindowManager::AreaType areaType() const { return m_areaType; } 84 | QToolWindowManager::ReferenceType referenceType() const { return m_referenceType; } 85 | bool isReference() const { return m_widget != 0; } 86 | QWidget *widget() const { return m_widget; } 87 | 88 | private: 89 | QToolWindowManager::AreaType m_areaType; 90 | QToolWindowManager::ReferenceType m_referenceType; 91 | QWidget *m_widget; 92 | }; 93 | 94 | class QSplitter; 95 | class QTabWidget; 96 | class QTabBar; 97 | class QLabel; 98 | class QToolWindowManagerWrapper; 99 | class QToolWindowManagerPrivate; 100 | 101 | class QToolWindowManagerPrivateSlots : public QObject { 102 | Q_OBJECT 103 | public: 104 | QToolWindowManagerPrivate* d; 105 | public Q_SLOTS: 106 | void showNextDropSuggestion(); 107 | //void tabCloseRequested(int index); 108 | void areaDestroyed(QObject *object); 109 | }; 110 | 111 | 112 | class QToolWindowManagerPrivate 113 | { 114 | Q_DECLARE_PUBLIC(QToolWindowManager) 115 | public: 116 | void addToolWindows(QList toolWindows, const QToolWindowManagerAreaReference& area); 117 | void moveToolWindows(const QWidgetList &toolWindows, const QToolWindowManagerAreaReference& area); 118 | 119 | // all added tool windows 120 | QList m_toolWindows; 121 | // all areas for this manager 122 | QList m_areas; 123 | // all wrappers for this manager 124 | QList m_wrappers; 125 | int m_borderSensitivity; 126 | int m_rubberBandLineWidth; 127 | bool m_tabsClosable; 128 | // list of tool windows that are currently dragged, or empty list if there is no current drag 129 | QList m_draggedToolWindows; 130 | // label used to display dragged content 131 | QLabel *m_dragIndicator; 132 | 133 | // placeholder objects used for displaying drop suggestions 134 | QRubberBand *m_rectRubberBand; 135 | QRubberBand *m_lineRubberBand; 136 | // full list of suggestions for current cursor position 137 | QList m_suggestions; 138 | // index of currently displayed drop suggestion 139 | // (e.g. always 0 if there is only one possible drop location) 140 | int m_dropCurrentSuggestionIndex; 141 | // used for switching drop suggestions 142 | QTimer m_dropSuggestionSwitchTimer; 143 | // last widget used for adding tool windows, or 0 if there isn't one 144 | // (warning: may contain pointer to deleted object) 145 | QAbstractToolWindowManagerArea *m_lastUsedArea; 146 | void handleNoSuggestions(); 147 | // remove tool window from its area (if any) and set parent to 0 148 | void releaseToolWindow(QWidget *toolWindow); 149 | // remove constructions that became useless 150 | void simplifyLayout(); 151 | void startDrag(const QWidgetList &toolWindows); 152 | 153 | QVariantMap saveAreaState(QAbstractToolWindowManagerArea *area); 154 | QAbstractToolWindowManagerArea *restoreAreaState(const QVariantMap& data); 155 | 156 | QVariantMap saveSplitterState(QSplitter *splitter); 157 | QSplitter *restoreSplitterState(const QVariantMap& data); 158 | void findSuggestions(QToolWindowManagerWrapper *wrapper); 159 | QRect sideSensitiveArea(QWidget *widget, QToolWindowManager::ReferenceType side); 160 | QRect sidePlaceHolderRect(QWidget *widget, QToolWindowManager::ReferenceType side); 161 | 162 | QSplitter *createAndSetupSplitter(); 163 | 164 | void updateDragPosition(); 165 | void finishDrag(); 166 | bool dragInProgress() { return !m_draggedToolWindows.isEmpty(); } 167 | 168 | QToolWindowManagerPrivateSlots slots_object; 169 | void showNextDropSuggestion(); 170 | //void tabCloseRequested(int index, QObject *sender); 171 | 172 | QAbstractToolWindowManagerArea * createAndSetupArea(); 173 | 174 | struct ToolWindowData { 175 | ToolWindowData() : leftButtonWidget(0), rightButtonWidget(0) {} 176 | QWidget *leftButtonWidget; 177 | QWidget *rightButtonWidget; 178 | }; 179 | 180 | QHash m_toolWindowData; 181 | 182 | QToolWindowManager *q_ptr; 183 | 184 | }; 185 | 186 | class QToolWindowManagerAreaPrivateSlots : public QObject { 187 | Q_OBJECT 188 | public: 189 | QToolWindowManagerAreaPrivate *d; 190 | public Q_SLOTS: 191 | void tabCloseRequested(int index); 192 | }; 193 | 194 | #if QT_VERSION < 0x050000 195 | class TweakedTabWidget; 196 | #endif 197 | 198 | class QToolWindowManagerAreaPrivate 199 | { 200 | Q_DECLARE_PUBLIC(QToolWindowManagerArea) 201 | public: 202 | QToolWindowManager *m_manager; 203 | QToolWindowManagerPrivate *m_d_manager; 204 | 205 | #if QT_VERSION >= 0x050000 206 | QTabWidget *m_tabWidget; 207 | #else 208 | TweakedTabWidget *m_tabWidget; 209 | #endif 210 | // indicates that user has started mouse movement on QTabWidget 211 | // that can be considered as dragging it if the cursor will leave 212 | // its area 213 | bool m_dragCanStart; 214 | 215 | // indicates that user has started mouse movement on QTabWidget 216 | // that can be considered as dragging current tab 217 | // if the cursor will leave the tab bar area 218 | bool m_tabDragCanStart; 219 | 220 | QToolWindowManagerAreaPrivateSlots slots_object; 221 | 222 | void addToolWindow(QWidget *toolWindow); 223 | void addToolWindows(const QList& toolWindows); 224 | 225 | // check if mouse left tab widget area so that dragging should start 226 | void check_mouse_move(); 227 | 228 | void tabCloseRequested(int index); 229 | 230 | QToolWindowManagerArea* q_ptr; 231 | }; 232 | 233 | 234 | #endif // QT_NO_TOOLWINDOWMANAGER 235 | 236 | QT_END_NAMESPACE 237 | 238 | #endif // QTOOLWINDOWMANAGER_P_H 239 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/qtoolwindowmanagerarea.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | QT_BEGIN_NAMESPACE 71 | 72 | #ifndef QT_NO_TOOLWINDOWMANAGER 73 | 74 | #if QT_VERSION < 0x050000 75 | class TweakedTabWidget : public QTabWidget { 76 | public: 77 | QTabBar * tabBar() const { return QTabWidget::tabBar(); } 78 | }; 79 | 80 | #endif 81 | 82 | QToolWindowManagerArea::QToolWindowManagerArea(QToolWindowManager *manager) : 83 | QAbstractToolWindowManagerArea(manager) 84 | { 85 | d_ptr = new QToolWindowManagerAreaPrivate(); 86 | d_ptr->q_ptr = this; 87 | Q_D(QToolWindowManagerArea); 88 | d->m_manager = manager; 89 | d->m_d_manager = d->m_manager->d_func(); 90 | #if QT_VERSION >= 0x050000 91 | d->m_tabWidget = new QTabWidget(); 92 | #else 93 | d->m_tabWidget = new TweakedTabWidget(); 94 | #endif 95 | d->slots_object.d = d; 96 | connect(d->m_tabWidget, SIGNAL(tabCloseRequested(int)), 97 | &(d->slots_object), SLOT(tabCloseRequested(int))); 98 | QVBoxLayout *mainLayout = new QVBoxLayout(this); 99 | mainLayout->setContentsMargins(0, 0, 0, 0); 100 | mainLayout->addWidget(d->m_tabWidget); 101 | d->m_dragCanStart = false; 102 | d->m_tabDragCanStart = false; 103 | d->m_tabWidget->setMovable(true); 104 | d->m_tabWidget->setTabsClosable(d->m_d_manager->m_tabsClosable); 105 | connect(d->m_manager, SIGNAL(tabsClosableChanged(bool)), 106 | this, SLOT(managerTabsClosableChanged(bool))); 107 | d->m_tabWidget->setDocumentMode(true); 108 | d->m_tabWidget->tabBar()->installEventFilter(this); 109 | } 110 | 111 | QToolWindowManagerArea::~QToolWindowManagerArea() 112 | { 113 | delete d_ptr; 114 | } 115 | 116 | void QToolWindowManagerArea::mousePressEvent(QMouseEvent *) 117 | { 118 | Q_D(QToolWindowManagerArea); 119 | if (qApp->mouseButtons() == Qt::LeftButton) 120 | d->m_dragCanStart = true; 121 | } 122 | 123 | void QToolWindowManagerArea::mouseReleaseEvent(QMouseEvent *) 124 | { 125 | Q_D(QToolWindowManagerArea); 126 | d->m_dragCanStart = false; 127 | updateDragPosition(); 128 | } 129 | 130 | void QToolWindowManagerArea::mouseMoveEvent(QMouseEvent *) 131 | { 132 | Q_D(QToolWindowManagerArea); 133 | d->check_mouse_move(); 134 | } 135 | 136 | bool QToolWindowManagerArea::eventFilter(QObject *object, QEvent *event) 137 | { 138 | Q_D(QToolWindowManagerArea); 139 | if (object == d->m_tabWidget->tabBar()) { 140 | switch (event->type()) { 141 | case QEvent::MouseButtonPress: 142 | if (qApp->mouseButtons() == Qt::LeftButton) { 143 | // can start tab drag only if mouse is at some tab, not at empty tabbar space 144 | if (d->m_tabWidget->tabBar()->tabAt(static_cast(event)->pos()) >= 0 ) 145 | d->m_tabDragCanStart = true; 146 | else 147 | d->m_dragCanStart = true; 148 | } 149 | break; 150 | case QEvent::MouseButtonRelease: 151 | d->m_tabDragCanStart = false; 152 | d->m_dragCanStart = false; 153 | updateDragPosition(); 154 | break; 155 | case QEvent::MouseMove: 156 | updateDragPosition(); 157 | if (d->m_tabDragCanStart) { 158 | if (d->m_tabWidget->tabBar()->rect().contains(static_cast(event)->pos())) 159 | return false; 160 | if (qApp->mouseButtons() != Qt::LeftButton) 161 | return false; 162 | QWidget *toolWindow = d->m_tabWidget->currentWidget(); 163 | if (!toolWindow || !d->m_manager->toolWindows().contains(toolWindow)) 164 | return false; 165 | d->m_tabDragCanStart = false; 166 | //stop internal tab drag in QTabBar 167 | QMouseEvent *releaseEvent = new QMouseEvent(QEvent::MouseButtonRelease, 168 | static_cast(event)->pos(), 169 | Qt::LeftButton, Qt::LeftButton, 0); 170 | qApp->sendEvent(d->m_tabWidget->tabBar(), releaseEvent); 171 | startDrag(QWidgetList() << toolWindow); 172 | } else if (d->m_dragCanStart) { 173 | d->check_mouse_move(); 174 | } 175 | break; 176 | default: 177 | break; 178 | } 179 | } 180 | if (event->type() == QEvent::WindowTitleChange) { 181 | int index = d->m_tabWidget->indexOf(static_cast(object)); 182 | if (index >= 0) { 183 | d->m_tabWidget->setTabText(index, d->m_tabWidget->widget(index)->windowTitle()); 184 | } 185 | } 186 | return QAbstractToolWindowManagerArea::eventFilter(object, event); 187 | } 188 | 189 | void QToolWindowManagerArea::releaseTabButtons(QWidget* toolWindow) { 190 | Q_D(QToolWindowManagerArea); 191 | int index = d->m_tabWidget->indexOf(toolWindow); 192 | if (index < 0) { 193 | qWarning("unexpected indexOf fail"); 194 | return; 195 | } 196 | if (d->m_d_manager->m_toolWindowData[toolWindow].leftButtonWidget) { 197 | d->m_tabWidget->tabBar()->setTabButton( 198 | index, 199 | QTabBar::LeftSide, 200 | 0); 201 | d->m_d_manager->m_toolWindowData[toolWindow].leftButtonWidget->setParent(d->m_manager); 202 | } 203 | if (d->m_d_manager->m_toolWindowData[toolWindow].rightButtonWidget) { 204 | d->m_tabWidget->tabBar()->setTabButton( 205 | index, 206 | QTabBar::RightSide, 207 | 0); 208 | d->m_d_manager->m_toolWindowData[toolWindow].rightButtonWidget->setParent(d->m_manager); 209 | } 210 | 211 | } 212 | 213 | void QToolWindowManagerArea::applyTabButtons(QWidget* toolWindow) 214 | { 215 | Q_D(QToolWindowManagerArea); 216 | int index = d->m_tabWidget->indexOf(toolWindow); 217 | if (index < 0) { 218 | qWarning("unexpected indexOf fail"); 219 | return; 220 | } 221 | if (d->m_d_manager->m_toolWindowData[toolWindow].leftButtonWidget) { 222 | d->m_tabWidget->tabBar()->setTabButton( 223 | index, 224 | QTabBar::LeftSide, 225 | d->m_d_manager->m_toolWindowData[toolWindow].leftButtonWidget); 226 | } 227 | if (d->m_d_manager->m_toolWindowData[toolWindow].rightButtonWidget) { 228 | d->m_tabWidget->tabBar()->setTabButton( 229 | index, 230 | QTabBar::RightSide, 231 | d->m_d_manager->m_toolWindowData[toolWindow].rightButtonWidget); 232 | } 233 | } 234 | 235 | void QToolWindowManagerArea::managerTabsClosableChanged(bool enabled) 236 | { 237 | Q_D(QToolWindowManagerArea); 238 | d->m_tabWidget->setTabsClosable(enabled); 239 | } 240 | 241 | void QToolWindowManagerAreaPrivate::check_mouse_move() 242 | { 243 | Q_Q(QToolWindowManagerArea); 244 | q->updateDragPosition(); 245 | if (qApp->mouseButtons() == Qt::LeftButton && 246 | !q->rect().contains(q->mapFromGlobal(QCursor::pos())) && 247 | m_dragCanStart) { 248 | m_dragCanStart = false; 249 | q->startDrag(q->toolWindows()); 250 | } 251 | } 252 | 253 | void QToolWindowManagerAreaPrivate::tabCloseRequested(int index) 254 | { 255 | QWidget *toolWindow = m_tabWidget->widget(index); 256 | if (toolWindow) { 257 | m_manager->hideToolWindow(toolWindow); 258 | } 259 | } 260 | 261 | #endif // QT_NO_TOOLWINDOWMANAGER 262 | 263 | QT_END_NAMESPACE 264 | 265 | QWidgetList QToolWindowManagerArea::toolWindows() const 266 | { 267 | const Q_D(QToolWindowManagerArea); 268 | QWidgetList result; 269 | for (int i = 0; i < d->m_tabWidget->count(); i++) 270 | result << d->m_tabWidget->widget(i); 271 | return result; 272 | } 273 | 274 | void QToolWindowManagerArea::activateToolWindow(QWidget *toolWindow) 275 | { 276 | const Q_D(QToolWindowManagerArea); 277 | d->m_tabWidget->setCurrentWidget(toolWindow); 278 | } 279 | 280 | 281 | void QToolWindowManagerArea::addToolWindows(const QWidgetList &toolWindows) 282 | { 283 | Q_D(QToolWindowManagerArea); 284 | int index = 0; 285 | foreach (QWidget *toolWindow, toolWindows) { 286 | index = d->m_tabWidget->addTab(toolWindow, toolWindow->windowIcon(), toolWindow->windowTitle()); 287 | applyTabButtons(toolWindow); 288 | toolWindow->installEventFilter(this); 289 | } 290 | d->m_tabWidget->setCurrentIndex(index); 291 | } 292 | 293 | void QToolWindowManagerArea::removeToolWindow(QWidget *toolWindow) 294 | { 295 | Q_D(QToolWindowManagerArea); 296 | int index = d->m_tabWidget->indexOf(toolWindow); 297 | if (index < 0) { 298 | qWarning("QToolWindowManagerArea::removeToolWindow: no such tool window"); 299 | return; 300 | } 301 | releaseTabButtons(toolWindow); 302 | d->m_tabWidget->removeTab(index); 303 | toolWindow->removeEventFilter(this); 304 | } 305 | 306 | QVariant QToolWindowManagerArea::saveState() const 307 | { 308 | const Q_D(QToolWindowManagerArea); 309 | QVariantMap map; 310 | map[QLatin1String("currentIndex")] = d->m_tabWidget->currentIndex(); 311 | return map; 312 | } 313 | 314 | void QToolWindowManagerArea::restoreState(const QVariant &state) 315 | { 316 | Q_D(QToolWindowManagerArea); 317 | d->m_tabWidget->setCurrentIndex(state.toMap()[QLatin1String("currentIndex")].toInt()); 318 | } 319 | 320 | void QToolWindowManagerArea::beforeTabButtonChanged(QWidget* toolWindow) 321 | { 322 | releaseTabButtons(toolWindow); 323 | } 324 | 325 | void QToolWindowManagerArea::tabButtonChanged(QWidget* toolWindow) 326 | { 327 | applyTabButtons(toolWindow); 328 | } 329 | -------------------------------------------------------------------------------- /doc/doxygen.css: -------------------------------------------------------------------------------- 1 | /* The standard CSS for doxygen 1.8.4 */ 2 | 3 | body, table, div, p, dl { 4 | font: 400 14px/22px Roboto,sans-serif; 5 | } 6 | 7 | /* @group Heading Levels */ 8 | 9 | h1.groupheader { 10 | font-size: 150%; 11 | } 12 | 13 | .title { 14 | font: 400 14px/28px Roboto,sans-serif; 15 | font-size: 150%; 16 | font-weight: bold; 17 | margin: 10px 2px; 18 | } 19 | 20 | h2.groupheader { 21 | border-bottom: 1px solid #879ECB; 22 | color: #354C7B; 23 | font-size: 150%; 24 | font-weight: normal; 25 | margin-top: 1.75em; 26 | padding-top: 8px; 27 | padding-bottom: 4px; 28 | width: 100%; 29 | } 30 | 31 | h3.groupheader { 32 | font-size: 100%; 33 | } 34 | 35 | h1, h2, h3, h4, h5, h6 { 36 | -webkit-transition: text-shadow 0.5s linear; 37 | -moz-transition: text-shadow 0.5s linear; 38 | -ms-transition: text-shadow 0.5s linear; 39 | -o-transition: text-shadow 0.5s linear; 40 | transition: text-shadow 0.5s linear; 41 | margin-right: 15px; 42 | } 43 | 44 | h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { 45 | text-shadow: 0 0 15px cyan; 46 | } 47 | 48 | dt { 49 | font-weight: bold; 50 | } 51 | 52 | div.multicol { 53 | -moz-column-gap: 1em; 54 | -webkit-column-gap: 1em; 55 | -moz-column-count: 3; 56 | -webkit-column-count: 3; 57 | } 58 | 59 | p.startli, p.startdd, p.starttd { 60 | margin-top: 2px; 61 | } 62 | 63 | p.endli { 64 | margin-bottom: 0px; 65 | } 66 | 67 | p.enddd { 68 | margin-bottom: 4px; 69 | } 70 | 71 | p.endtd { 72 | margin-bottom: 2px; 73 | } 74 | 75 | /* @end */ 76 | 77 | caption { 78 | font-weight: bold; 79 | } 80 | 81 | span.legend { 82 | font-size: 70%; 83 | text-align: center; 84 | } 85 | 86 | h3.version { 87 | font-size: 90%; 88 | text-align: center; 89 | } 90 | 91 | div.qindex, div.navtab{ 92 | background-color: #EBEFF6; 93 | border: 1px solid #A3B4D7; 94 | text-align: center; 95 | } 96 | 97 | div.qindex, div.navpath { 98 | width: 100%; 99 | line-height: 140%; 100 | } 101 | 102 | div.navtab { 103 | margin-right: 15px; 104 | } 105 | 106 | /* @group Link Styling */ 107 | 108 | a { 109 | color: #3D578C; 110 | font-weight: normal; 111 | text-decoration: none; 112 | } 113 | 114 | .contents a:visited { 115 | color: #4665A2; 116 | } 117 | 118 | a:hover { 119 | text-decoration: underline; 120 | } 121 | 122 | a.qindex { 123 | font-weight: bold; 124 | } 125 | 126 | a.qindexHL { 127 | font-weight: bold; 128 | background-color: #9CAFD4; 129 | color: #ffffff; 130 | border: 1px double #869DCA; 131 | } 132 | 133 | .contents a.qindexHL:visited { 134 | color: #ffffff; 135 | } 136 | 137 | a.el { 138 | font-weight: bold; 139 | } 140 | 141 | a.elRef { 142 | } 143 | 144 | a.code, a.code:visited { 145 | color: #4665A2; 146 | } 147 | 148 | a.codeRef, a.codeRef:visited { 149 | color: #4665A2; 150 | } 151 | 152 | /* @end */ 153 | 154 | dl.el { 155 | margin-left: -1cm; 156 | } 157 | 158 | pre.fragment { 159 | border: 1px solid #C4CFE5; 160 | background-color: #FBFCFD; 161 | padding: 4px 6px; 162 | margin: 4px 8px 4px 2px; 163 | overflow: auto; 164 | word-wrap: break-word; 165 | font-size: 9pt; 166 | line-height: 125%; 167 | font-family: monospace, fixed; 168 | font-size: 105%; 169 | } 170 | 171 | div.fragment { 172 | padding: 0px; 173 | margin: 0px; 174 | background-color: #FBFCFD; 175 | border: 1px solid #C4CFE5; 176 | } 177 | 178 | div.line { 179 | font-family: monospace, fixed; 180 | font-size: 13px; 181 | min-height: 13px; 182 | line-height: 1.0; 183 | text-wrap: unrestricted; 184 | white-space: -moz-pre-wrap; /* Moz */ 185 | white-space: -pre-wrap; /* Opera 4-6 */ 186 | white-space: -o-pre-wrap; /* Opera 7 */ 187 | white-space: pre-wrap; /* CSS3 */ 188 | word-wrap: break-word; /* IE 5.5+ */ 189 | text-indent: -53px; 190 | padding-left: 53px; 191 | padding-bottom: 0px; 192 | margin: 0px; 193 | -webkit-transition-property: background-color, box-shadow; 194 | -webkit-transition-duration: 0.5s; 195 | -moz-transition-property: background-color, box-shadow; 196 | -moz-transition-duration: 0.5s; 197 | -ms-transition-property: background-color, box-shadow; 198 | -ms-transition-duration: 0.5s; 199 | -o-transition-property: background-color, box-shadow; 200 | -o-transition-duration: 0.5s; 201 | transition-property: background-color, box-shadow; 202 | transition-duration: 0.5s; 203 | } 204 | 205 | div.line.glow { 206 | background-color: cyan; 207 | box-shadow: 0 0 10px cyan; 208 | } 209 | 210 | 211 | span.lineno { 212 | padding-right: 4px; 213 | text-align: right; 214 | border-right: 2px solid #0F0; 215 | background-color: #E8E8E8; 216 | white-space: pre; 217 | } 218 | span.lineno a { 219 | background-color: #D8D8D8; 220 | } 221 | 222 | span.lineno a:hover { 223 | background-color: #C8C8C8; 224 | } 225 | 226 | div.ah { 227 | background-color: black; 228 | font-weight: bold; 229 | color: #ffffff; 230 | margin-bottom: 3px; 231 | margin-top: 3px; 232 | padding: 0.2em; 233 | border: solid thin #333; 234 | border-radius: 0.5em; 235 | -webkit-border-radius: .5em; 236 | -moz-border-radius: .5em; 237 | box-shadow: 2px 2px 3px #999; 238 | -webkit-box-shadow: 2px 2px 3px #999; 239 | -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; 240 | background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); 241 | background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); 242 | } 243 | 244 | div.groupHeader { 245 | margin-left: 16px; 246 | margin-top: 12px; 247 | font-weight: bold; 248 | } 249 | 250 | div.groupText { 251 | margin-left: 16px; 252 | font-style: italic; 253 | } 254 | 255 | body { 256 | background-color: white; 257 | color: black; 258 | margin: 0; 259 | } 260 | 261 | div.contents { 262 | margin-top: 10px; 263 | margin-left: 12px; 264 | margin-right: 8px; 265 | } 266 | 267 | td.indexkey { 268 | background-color: #EBEFF6; 269 | font-weight: bold; 270 | border: 1px solid #C4CFE5; 271 | margin: 2px 0px 2px 0; 272 | padding: 2px 10px; 273 | white-space: nowrap; 274 | vertical-align: top; 275 | } 276 | 277 | td.indexvalue { 278 | background-color: #EBEFF6; 279 | border: 1px solid #C4CFE5; 280 | padding: 2px 10px; 281 | margin: 2px 0px; 282 | } 283 | 284 | tr.memlist { 285 | background-color: #EEF1F7; 286 | } 287 | 288 | p.formulaDsp { 289 | text-align: center; 290 | } 291 | 292 | img.formulaDsp { 293 | 294 | } 295 | 296 | img.formulaInl { 297 | vertical-align: middle; 298 | } 299 | 300 | div.center { 301 | text-align: center; 302 | margin-top: 0px; 303 | margin-bottom: 0px; 304 | padding: 0px; 305 | } 306 | 307 | div.center img { 308 | border: 0px; 309 | } 310 | 311 | address.footer { 312 | text-align: right; 313 | padding-right: 12px; 314 | } 315 | 316 | img.footer { 317 | border: 0px; 318 | vertical-align: middle; 319 | } 320 | 321 | /* @group Code Colorization */ 322 | 323 | span.keyword { 324 | color: #008000 325 | } 326 | 327 | span.keywordtype { 328 | color: #604020 329 | } 330 | 331 | span.keywordflow { 332 | color: #e08000 333 | } 334 | 335 | span.comment { 336 | color: #800000 337 | } 338 | 339 | span.preprocessor { 340 | color: #806020 341 | } 342 | 343 | span.stringliteral { 344 | color: #002080 345 | } 346 | 347 | span.charliteral { 348 | color: #008080 349 | } 350 | 351 | span.vhdldigit { 352 | color: #ff00ff 353 | } 354 | 355 | span.vhdlchar { 356 | color: #000000 357 | } 358 | 359 | span.vhdlkeyword { 360 | color: #700070 361 | } 362 | 363 | span.vhdllogic { 364 | color: #ff0000 365 | } 366 | 367 | blockquote { 368 | background-color: #F7F8FB; 369 | border-left: 2px solid #9CAFD4; 370 | margin: 0 24px 0 4px; 371 | padding: 0 12px 0 16px; 372 | } 373 | 374 | /* @end */ 375 | 376 | /* 377 | .search { 378 | color: #003399; 379 | font-weight: bold; 380 | } 381 | 382 | form.search { 383 | margin-bottom: 0px; 384 | margin-top: 0px; 385 | } 386 | 387 | input.search { 388 | font-size: 75%; 389 | color: #000080; 390 | font-weight: normal; 391 | background-color: #e8eef2; 392 | } 393 | */ 394 | 395 | td.tiny { 396 | font-size: 75%; 397 | } 398 | 399 | .dirtab { 400 | padding: 4px; 401 | border-collapse: collapse; 402 | border: 1px solid #A3B4D7; 403 | } 404 | 405 | th.dirtab { 406 | background: #EBEFF6; 407 | font-weight: bold; 408 | } 409 | 410 | hr { 411 | height: 0px; 412 | border: none; 413 | border-top: 1px solid #4A6AAA; 414 | } 415 | 416 | hr.footer { 417 | height: 1px; 418 | } 419 | 420 | /* @group Member Descriptions */ 421 | 422 | table.memberdecls { 423 | border-spacing: 0px; 424 | padding: 0px; 425 | } 426 | 427 | .memberdecls td, .fieldtable tr { 428 | -webkit-transition-property: background-color, box-shadow; 429 | -webkit-transition-duration: 0.5s; 430 | -moz-transition-property: background-color, box-shadow; 431 | -moz-transition-duration: 0.5s; 432 | -ms-transition-property: background-color, box-shadow; 433 | -ms-transition-duration: 0.5s; 434 | -o-transition-property: background-color, box-shadow; 435 | -o-transition-duration: 0.5s; 436 | transition-property: background-color, box-shadow; 437 | transition-duration: 0.5s; 438 | } 439 | 440 | .memberdecls td.glow, .fieldtable tr.glow { 441 | background-color: cyan; 442 | box-shadow: 0 0 15px cyan; 443 | } 444 | 445 | .mdescLeft, .mdescRight, 446 | .memItemLeft, .memItemRight, 447 | .memTemplItemLeft, .memTemplItemRight, .memTemplParams { 448 | background-color: #F9FAFC; 449 | border: none; 450 | margin: 4px; 451 | padding: 1px 0 0 8px; 452 | } 453 | 454 | .mdescLeft, .mdescRight { 455 | padding: 0px 8px 4px 8px; 456 | color: #555; 457 | } 458 | 459 | .memSeparator { 460 | border-bottom: 1px solid #DEE4F0; 461 | line-height: 1px; 462 | margin: 0px; 463 | padding: 0px; 464 | } 465 | 466 | .memItemLeft, .memTemplItemLeft { 467 | white-space: nowrap; 468 | } 469 | 470 | .memItemRight { 471 | width: 100%; 472 | } 473 | 474 | .memTemplParams { 475 | color: #4665A2; 476 | white-space: nowrap; 477 | font-size: 80%; 478 | } 479 | 480 | /* @end */ 481 | 482 | /* @group Member Details */ 483 | 484 | /* Styles for detailed member documentation */ 485 | 486 | .memtemplate { 487 | font-size: 80%; 488 | color: #4665A2; 489 | font-weight: normal; 490 | margin-left: 9px; 491 | } 492 | 493 | .memnav { 494 | background-color: #EBEFF6; 495 | border: 1px solid #A3B4D7; 496 | text-align: center; 497 | margin: 2px; 498 | margin-right: 15px; 499 | padding: 2px; 500 | } 501 | 502 | .mempage { 503 | width: 100%; 504 | } 505 | 506 | .memitem { 507 | padding: 0; 508 | margin-bottom: 10px; 509 | margin-right: 5px; 510 | -webkit-transition: box-shadow 0.5s linear; 511 | -moz-transition: box-shadow 0.5s linear; 512 | -ms-transition: box-shadow 0.5s linear; 513 | -o-transition: box-shadow 0.5s linear; 514 | transition: box-shadow 0.5s linear; 515 | display: table !important; 516 | width: 100%; 517 | } 518 | 519 | .memitem.glow { 520 | box-shadow: 0 0 15px cyan; 521 | } 522 | 523 | .memname { 524 | font-weight: bold; 525 | margin-left: 6px; 526 | } 527 | 528 | .memname td { 529 | vertical-align: bottom; 530 | } 531 | 532 | .memproto, dl.reflist dt { 533 | border-top: 1px solid #A8B8D9; 534 | border-left: 1px solid #A8B8D9; 535 | border-right: 1px solid #A8B8D9; 536 | padding: 6px 0px 6px 0px; 537 | color: #253555; 538 | font-weight: bold; 539 | text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); 540 | background-image:url('nav_f.png'); 541 | background-repeat:repeat-x; 542 | background-color: #E2E8F2; 543 | /* opera specific markup */ 544 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 545 | border-top-right-radius: 4px; 546 | border-top-left-radius: 4px; 547 | /* firefox specific markup */ 548 | -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; 549 | -moz-border-radius-topright: 4px; 550 | -moz-border-radius-topleft: 4px; 551 | /* webkit specific markup */ 552 | -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 553 | -webkit-border-top-right-radius: 4px; 554 | -webkit-border-top-left-radius: 4px; 555 | 556 | } 557 | 558 | .memdoc, dl.reflist dd { 559 | border-bottom: 1px solid #A8B8D9; 560 | border-left: 1px solid #A8B8D9; 561 | border-right: 1px solid #A8B8D9; 562 | padding: 6px 10px 2px 10px; 563 | background-color: #FBFCFD; 564 | border-top-width: 0; 565 | background-image:url('nav_g.png'); 566 | background-repeat:repeat-x; 567 | background-color: #FFFFFF; 568 | /* opera specific markup */ 569 | border-bottom-left-radius: 4px; 570 | border-bottom-right-radius: 4px; 571 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 572 | /* firefox specific markup */ 573 | -moz-border-radius-bottomleft: 4px; 574 | -moz-border-radius-bottomright: 4px; 575 | -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; 576 | /* webkit specific markup */ 577 | -webkit-border-bottom-left-radius: 4px; 578 | -webkit-border-bottom-right-radius: 4px; 579 | -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 580 | } 581 | 582 | dl.reflist dt { 583 | padding: 5px; 584 | } 585 | 586 | dl.reflist dd { 587 | margin: 0px 0px 10px 0px; 588 | padding: 5px; 589 | } 590 | 591 | .paramkey { 592 | text-align: right; 593 | } 594 | 595 | .paramtype { 596 | white-space: nowrap; 597 | } 598 | 599 | .paramname { 600 | color: #602020; 601 | white-space: nowrap; 602 | } 603 | .paramname em { 604 | font-style: normal; 605 | } 606 | .paramname code { 607 | line-height: 14px; 608 | } 609 | 610 | .params, .retval, .exception, .tparams { 611 | margin-left: 0px; 612 | padding-left: 0px; 613 | } 614 | 615 | .params .paramname, .retval .paramname { 616 | font-weight: bold; 617 | vertical-align: top; 618 | } 619 | 620 | .params .paramtype { 621 | font-style: italic; 622 | vertical-align: top; 623 | } 624 | 625 | .params .paramdir { 626 | font-family: "courier new",courier,monospace; 627 | vertical-align: top; 628 | } 629 | 630 | table.mlabels { 631 | border-spacing: 0px; 632 | } 633 | 634 | td.mlabels-left { 635 | width: 100%; 636 | padding: 0px; 637 | } 638 | 639 | td.mlabels-right { 640 | vertical-align: bottom; 641 | padding: 0px; 642 | white-space: nowrap; 643 | } 644 | 645 | span.mlabels { 646 | margin-left: 8px; 647 | } 648 | 649 | span.mlabel { 650 | background-color: #728DC1; 651 | border-top:1px solid #5373B4; 652 | border-left:1px solid #5373B4; 653 | border-right:1px solid #C4CFE5; 654 | border-bottom:1px solid #C4CFE5; 655 | text-shadow: none; 656 | color: white; 657 | margin-right: 4px; 658 | padding: 2px 3px; 659 | border-radius: 3px; 660 | font-size: 7pt; 661 | white-space: nowrap; 662 | vertical-align: middle; 663 | } 664 | 665 | 666 | 667 | /* @end */ 668 | 669 | /* these are for tree view when not used as main index */ 670 | 671 | div.directory { 672 | margin: 10px 0px; 673 | border-top: 1px solid #A8B8D9; 674 | border-bottom: 1px solid #A8B8D9; 675 | width: 100%; 676 | } 677 | 678 | .directory table { 679 | border-collapse:collapse; 680 | } 681 | 682 | .directory td { 683 | margin: 0px; 684 | padding: 0px; 685 | vertical-align: top; 686 | } 687 | 688 | .directory td.entry { 689 | white-space: nowrap; 690 | padding-right: 6px; 691 | padding-top: 3px; 692 | } 693 | 694 | .directory td.entry a { 695 | outline:none; 696 | } 697 | 698 | .directory td.entry a img { 699 | border: none; 700 | } 701 | 702 | .directory td.desc { 703 | width: 100%; 704 | padding-left: 6px; 705 | padding-right: 6px; 706 | padding-top: 3px; 707 | border-left: 1px solid rgba(0,0,0,0.05); 708 | } 709 | 710 | .directory tr.even { 711 | padding-left: 6px; 712 | background-color: #F7F8FB; 713 | } 714 | 715 | .directory img { 716 | vertical-align: -30%; 717 | } 718 | 719 | .directory .levels { 720 | white-space: nowrap; 721 | width: 100%; 722 | text-align: right; 723 | font-size: 9pt; 724 | } 725 | 726 | .directory .levels span { 727 | cursor: pointer; 728 | padding-left: 2px; 729 | padding-right: 2px; 730 | color: #3D578C; 731 | } 732 | 733 | div.dynheader { 734 | margin-top: 8px; 735 | -webkit-touch-callout: none; 736 | -webkit-user-select: none; 737 | -khtml-user-select: none; 738 | -moz-user-select: none; 739 | -ms-user-select: none; 740 | user-select: none; 741 | } 742 | 743 | address { 744 | font-style: normal; 745 | color: #2A3D61; 746 | } 747 | 748 | table.doxtable { 749 | border-collapse:collapse; 750 | margin-top: 4px; 751 | margin-bottom: 4px; 752 | } 753 | 754 | table.doxtable td, table.doxtable th { 755 | border: 1px solid #2D4068; 756 | padding: 3px 7px 2px; 757 | } 758 | 759 | table.doxtable th { 760 | background-color: #374F7F; 761 | color: #FFFFFF; 762 | font-size: 110%; 763 | padding-bottom: 4px; 764 | padding-top: 5px; 765 | } 766 | 767 | table.fieldtable { 768 | /*width: 100%;*/ 769 | margin-bottom: 10px; 770 | border: 1px solid #A8B8D9; 771 | border-spacing: 0px; 772 | -moz-border-radius: 4px; 773 | -webkit-border-radius: 4px; 774 | border-radius: 4px; 775 | -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; 776 | -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); 777 | box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); 778 | } 779 | 780 | .fieldtable td, .fieldtable th { 781 | padding: 3px 7px 2px; 782 | } 783 | 784 | .fieldtable td.fieldtype, .fieldtable td.fieldname { 785 | white-space: nowrap; 786 | border-right: 1px solid #A8B8D9; 787 | border-bottom: 1px solid #A8B8D9; 788 | vertical-align: top; 789 | } 790 | 791 | .fieldtable td.fieldname { 792 | padding-top: 3px; 793 | } 794 | 795 | .fieldtable td.fielddoc { 796 | border-bottom: 1px solid #A8B8D9; 797 | /*width: 100%;*/ 798 | } 799 | 800 | .fieldtable td.fielddoc p:first-child { 801 | margin-top: 0px; 802 | } 803 | 804 | .fieldtable td.fielddoc p:last-child { 805 | margin-bottom: 2px; 806 | } 807 | 808 | .fieldtable tr:last-child td { 809 | border-bottom: none; 810 | } 811 | 812 | .fieldtable th { 813 | background-image:url('nav_f.png'); 814 | background-repeat:repeat-x; 815 | background-color: #E2E8F2; 816 | font-size: 90%; 817 | color: #253555; 818 | padding-bottom: 4px; 819 | padding-top: 5px; 820 | text-align:left; 821 | -moz-border-radius-topleft: 4px; 822 | -moz-border-radius-topright: 4px; 823 | -webkit-border-top-left-radius: 4px; 824 | -webkit-border-top-right-radius: 4px; 825 | border-top-left-radius: 4px; 826 | border-top-right-radius: 4px; 827 | border-bottom: 1px solid #A8B8D9; 828 | } 829 | 830 | 831 | .tabsearch { 832 | top: 0px; 833 | left: 10px; 834 | height: 36px; 835 | background-image: url('tab_b.png'); 836 | z-index: 101; 837 | overflow: hidden; 838 | font-size: 13px; 839 | } 840 | 841 | .navpath ul 842 | { 843 | font-size: 11px; 844 | background-image:url('tab_b.png'); 845 | background-repeat:repeat-x; 846 | background-position: 0 -5px; 847 | height:30px; 848 | line-height:30px; 849 | color:#8AA0CC; 850 | border:solid 1px #C2CDE4; 851 | overflow:hidden; 852 | margin:0px; 853 | padding:0px; 854 | } 855 | 856 | .navpath li 857 | { 858 | list-style-type:none; 859 | float:left; 860 | padding-left:10px; 861 | padding-right:15px; 862 | background-image:url('bc_s.png'); 863 | background-repeat:no-repeat; 864 | background-position:right; 865 | color:#364D7C; 866 | } 867 | 868 | .navpath li.navelem a 869 | { 870 | height:32px; 871 | display:block; 872 | text-decoration: none; 873 | outline: none; 874 | color: #283A5D; 875 | font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 876 | text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); 877 | text-decoration: none; 878 | } 879 | 880 | .navpath li.navelem a:hover 881 | { 882 | color:#6884BD; 883 | } 884 | 885 | .navpath li.footer 886 | { 887 | list-style-type:none; 888 | float:right; 889 | padding-left:10px; 890 | padding-right:15px; 891 | background-image:none; 892 | background-repeat:no-repeat; 893 | background-position:right; 894 | color:#364D7C; 895 | font-size: 8pt; 896 | } 897 | 898 | 899 | div.summary 900 | { 901 | float: right; 902 | font-size: 8pt; 903 | padding-right: 5px; 904 | width: 50%; 905 | text-align: right; 906 | } 907 | 908 | div.summary a 909 | { 910 | white-space: nowrap; 911 | } 912 | 913 | div.ingroups 914 | { 915 | font-size: 8pt; 916 | width: 50%; 917 | text-align: left; 918 | } 919 | 920 | div.ingroups a 921 | { 922 | white-space: nowrap; 923 | } 924 | 925 | div.header 926 | { 927 | background-image:url('nav_h.png'); 928 | background-repeat:repeat-x; 929 | background-color: #F9FAFC; 930 | margin: 0px; 931 | border-bottom: 1px solid #C4CFE5; 932 | } 933 | 934 | div.headertitle 935 | { 936 | padding: 5px 5px 5px 10px; 937 | } 938 | 939 | dl 940 | { 941 | padding: 0 0 0 10px; 942 | } 943 | 944 | /* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ 945 | dl.section 946 | { 947 | margin-left: 0px; 948 | padding-left: 0px; 949 | } 950 | 951 | dl.note 952 | { 953 | margin-left:-7px; 954 | padding-left: 3px; 955 | border-left:4px solid; 956 | border-color: #D0C000; 957 | } 958 | 959 | dl.warning, dl.attention 960 | { 961 | margin-left:-7px; 962 | padding-left: 3px; 963 | border-left:4px solid; 964 | border-color: #FF0000; 965 | } 966 | 967 | dl.pre, dl.post, dl.invariant 968 | { 969 | margin-left:-7px; 970 | padding-left: 3px; 971 | border-left:4px solid; 972 | border-color: #00D000; 973 | } 974 | 975 | dl.deprecated 976 | { 977 | margin-left:-7px; 978 | padding-left: 3px; 979 | border-left:4px solid; 980 | border-color: #505050; 981 | } 982 | 983 | dl.todo 984 | { 985 | margin-left:-7px; 986 | padding-left: 3px; 987 | border-left:4px solid; 988 | border-color: #00C0E0; 989 | } 990 | 991 | dl.test 992 | { 993 | margin-left:-7px; 994 | padding-left: 3px; 995 | border-left:4px solid; 996 | border-color: #3030E0; 997 | } 998 | 999 | dl.bug 1000 | { 1001 | margin-left:-7px; 1002 | padding-left: 3px; 1003 | border-left:4px solid; 1004 | border-color: #C08050; 1005 | } 1006 | 1007 | dl.section dd { 1008 | margin-bottom: 6px; 1009 | } 1010 | 1011 | 1012 | #projectlogo 1013 | { 1014 | text-align: center; 1015 | vertical-align: bottom; 1016 | border-collapse: separate; 1017 | } 1018 | 1019 | #projectlogo img 1020 | { 1021 | border: 0px none; 1022 | } 1023 | 1024 | #projectname 1025 | { 1026 | font: 300% Tahoma, Arial,sans-serif; 1027 | margin: 0px; 1028 | padding: 2px 0px; 1029 | } 1030 | 1031 | #projectbrief 1032 | { 1033 | font: 120% Tahoma, Arial,sans-serif; 1034 | margin: 0px; 1035 | padding: 0px; 1036 | } 1037 | 1038 | #projectnumber 1039 | { 1040 | font: 50% Tahoma, Arial,sans-serif; 1041 | margin: 0px; 1042 | padding: 0px; 1043 | } 1044 | 1045 | #titlearea 1046 | { 1047 | padding: 0px; 1048 | margin: 0px; 1049 | width: 100%; 1050 | border-bottom: 1px solid #5373B4; 1051 | } 1052 | 1053 | .image 1054 | { 1055 | text-align: center; 1056 | } 1057 | 1058 | .dotgraph 1059 | { 1060 | text-align: center; 1061 | } 1062 | 1063 | .mscgraph 1064 | { 1065 | text-align: center; 1066 | } 1067 | 1068 | .caption 1069 | { 1070 | font-weight: bold; 1071 | } 1072 | 1073 | div.zoom 1074 | { 1075 | border: 1px solid #90A5CE; 1076 | } 1077 | 1078 | dl.citelist { 1079 | margin-bottom:50px; 1080 | } 1081 | 1082 | dl.citelist dt { 1083 | color:#334975; 1084 | float:left; 1085 | font-weight:bold; 1086 | margin-right:10px; 1087 | padding:5px; 1088 | } 1089 | 1090 | dl.citelist dd { 1091 | margin:2px 0; 1092 | padding:5px 0; 1093 | } 1094 | 1095 | div.toc { 1096 | padding: 14px 25px; 1097 | background-color: #F4F6FA; 1098 | border: 1px solid #D8DFEE; 1099 | border-radius: 7px 7px 7px 7px; 1100 | float: right; 1101 | height: auto; 1102 | margin: 0 20px 10px 10px; 1103 | width: 200px; 1104 | } 1105 | 1106 | div.toc li { 1107 | background: url("bdwn.png") no-repeat scroll 0 5px transparent; 1108 | font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; 1109 | margin-top: 5px; 1110 | padding-left: 10px; 1111 | padding-top: 2px; 1112 | } 1113 | 1114 | div.toc h3 { 1115 | font: bold 12px/1.2 Arial,FreeSans,sans-serif; 1116 | color: #4665A2; 1117 | border-bottom: 0 none; 1118 | margin: 0; 1119 | } 1120 | 1121 | div.toc ul { 1122 | list-style: none outside none; 1123 | border: medium none; 1124 | padding: 0px; 1125 | } 1126 | 1127 | div.toc li.level1 { 1128 | margin-left: 0px; 1129 | } 1130 | 1131 | div.toc li.level2 { 1132 | margin-left: 15px; 1133 | } 1134 | 1135 | div.toc li.level3 { 1136 | margin-left: 30px; 1137 | } 1138 | 1139 | div.toc li.level4 { 1140 | margin-left: 45px; 1141 | } 1142 | 1143 | .inherit_header { 1144 | font-weight: bold; 1145 | color: gray; 1146 | cursor: pointer; 1147 | -webkit-touch-callout: none; 1148 | -webkit-user-select: none; 1149 | -khtml-user-select: none; 1150 | -moz-user-select: none; 1151 | -ms-user-select: none; 1152 | user-select: none; 1153 | } 1154 | 1155 | .inherit_header td { 1156 | padding: 6px 0px 2px 5px; 1157 | } 1158 | 1159 | .inherit { 1160 | display: none; 1161 | } 1162 | 1163 | tr.heading h2 { 1164 | margin-top: 12px; 1165 | margin-bottom: 4px; 1166 | } 1167 | 1168 | @media print 1169 | { 1170 | #top { display: none; } 1171 | #side-nav { display: none; } 1172 | #nav-path { display: none; } 1173 | body { overflow:visible; } 1174 | h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } 1175 | .summary { display: none; } 1176 | .memitem { page-break-inside: avoid; } 1177 | #doc-content 1178 | { 1179 | margin-left:0 !important; 1180 | height:auto !important; 1181 | width:auto !important; 1182 | overflow:inherit; 1183 | display:inline; 1184 | } 1185 | } 1186 | 1187 | -------------------------------------------------------------------------------- /libqtoolwindowmanager/qtoolwindowmanager.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2014 Pavel Strakhov 4 | ** 5 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ** of this software and associated documentation files (the "Software"), to deal 7 | ** in the Software without restriction, including without limitation the rights 8 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ** copies of the Software, and to permit persons to whom the Software is 10 | ** furnished to do so, subject to the following conditions: 11 | ** 12 | ** The above copyright notice and this permission notice shall be included in all 13 | ** copies or substantial portions of the Software. 14 | ** 15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ** SOFTWARE. 22 | ** 23 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). 24 | ** Contact: http://www.qt-project.org/legal 25 | ** 26 | ** This file is part of the QtWidgets module of the Qt Toolkit. 27 | ** 28 | ** $QT_BEGIN_LICENSE:LGPL$ 29 | ** Commercial License Usage 30 | ** Licensees holding valid commercial Qt licenses may use this file in 31 | ** accordance with the commercial license agreement provided with the 32 | ** Software or, alternatively, in accordance with the terms contained in 33 | ** a written agreement between you and Digia. For licensing terms and 34 | ** conditions see http://qt.digia.com/licensing. For further information 35 | ** use the contact form at http://qt.digia.com/contact-us. 36 | ** 37 | ** GNU Lesser General Public License Usage 38 | ** Alternatively, this file may be used under the terms of the GNU Lesser 39 | ** General Public License version 2.1 as published by the Free Software 40 | ** Foundation and appearing in the file LICENSE.LGPL included in the 41 | ** packaging of this file. Please review the following information to 42 | ** ensure the GNU Lesser General Public License version 2.1 requirements 43 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 44 | ** 45 | ** In addition, as a special exception, Digia gives you certain additional 46 | ** rights. These rights are described in the Digia Qt LGPL Exception 47 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 48 | ** 49 | ** GNU General Public License Usage 50 | ** Alternatively, this file may be used under the terms of the GNU 51 | ** General Public License version 3.0 as published by the Free Software 52 | ** Foundation and appearing in the file LICENSE.GPL included in the 53 | ** packaging of this file. Please review the following information to 54 | ** ensure the GNU General Public License version 3.0 requirements will be 55 | ** met: http://www.gnu.org/copyleft/gpl.html. 56 | ** 57 | ** 58 | ** $QT_END_LICENSE$ 59 | ** 60 | ****************************************************************************/ 61 | 62 | #include 63 | 64 | QT_BEGIN_NAMESPACE 65 | 66 | #ifndef QT_NO_TOOLWINDOWMANAGER 67 | 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | #include 81 | #include 82 | 83 | template 84 | T findClosestParent(QWidget *widget) 85 | { 86 | while (widget) { 87 | if (T result = qobject_cast(widget)) 88 | return result; 89 | widget = widget->parentWidget(); 90 | } 91 | return 0; 92 | } 93 | 94 | /*! 95 | \class QToolWindowManager 96 | 97 | \brief The QToolWindowManager class provides docking tool behavior. 98 | 99 | \inmodule QtWidgets 100 | 101 | \since 5.4 102 | 103 | The behavior provided by QToolWindowManager is similar to tool windows mechanism 104 | in Visual Studio or Eclipse. 105 | User can arrange tool windows in tabs, dock it to any border, split with vertical 106 | and horizontal splitters, tabify them together and detach to floating windows. 107 | QToolWindowManager can be used to implement ability for user to setup an 108 | environment with customized tool windows layout. 109 | 110 | QToolWindowManager is in many ways similar to QMainWindow that also provides ability to 111 | pin dock widgets and toolbars to its borders, tabify or detach them. However, 112 | QToolWindowManager has extended abilities to manage tool windows. 113 | It has no canonic central area. Each and every area can be used 114 | to tabify several tool windows. Each area can be divided to display many 115 | tool windows at once. Dropping tool windows is not limited to the borders 116 | of QToolWindowManager. A tool window can be dropped at any border between areas. 117 | These features also applies to the floating areas. They can be split up and/or 118 | contain tabified tool windows. 119 | 120 | QToolWindowManager also provides API to setup an arbitrary environment programmatically. 121 | This can be used to create presets of environments for quick start. 122 | 123 | Each tool window can be dragged individually by pressing left mouse button at 124 | its tab button at the tab bar and dragging away. Each area containing multiple tabified 125 | tool window can be dragged as a whole by pressing left mouse button at the empty space 126 | at the tab bar and dragging away. When an item is dragged and mouse is over a suitable 127 | drop area (i.e. QToolWindowManager itself or one of the floating windows created by it), 128 | a drop suggestion appears indicating where the item will be put to if it's 129 | dropped. It can be either a line indicating that the item will be inserted between its 130 | neighbor areas, or a rectangle indicating that the dragged tool window(s) will be added 131 | to the highlighted area as tabs. When an item is dropped to space that is not managed by 132 | the QToolWindowManager, it becomes a floating window. 133 | 134 | */ 135 | /*! 136 | \property QToolWindowManager::suggestionSwitchInterval 137 | \brief The delay between showing the next suggestion of drop location in milliseconds. 138 | 139 | When user starts a tool window drag and moves mouse pointer to a position, there can be 140 | an ambiguity in new position of the tool window. If user holds the left mouse button and 141 | stops mouse movements, all possible suggestions will be indicated periodically, one at a time. 142 | 143 | Default value is 1000 (i.e. 1 second). 144 | */ 145 | /*! 146 | \property QToolWindowManager::borderSensitivity 147 | \brief Maximal distance in pixels between mouse position and area border that allows 148 | to display a suggestion. 149 | 150 | Default value is 12. 151 | */ 152 | /*! 153 | \property QToolWindowManager::rubberBandLineWidth 154 | \brief Visible width of rubber band line that is used to display drop suggestions. 155 | 156 | Default value is the same as QSplitter::handleWidth default value on current platform. 157 | */ 158 | /*! 159 | \enum QToolWindowManager::AreaType 160 | 161 | Describes where to place a tool window. 162 | 163 | \value LastUsedArea The area tool windows has been added to most recently. 164 | \value NewFloatingArea New area in a detached window. 165 | \value EmptySpaceArea Area inside the manager widget (only available when there is 166 | no tool windows in it). 167 | \value NoArea Tool window is hidden. 168 | */ 169 | /*! 170 | \enum QToolWindowManager::ReferenceType 171 | 172 | Describes where to place a tool window relative to an existing area. 173 | 174 | \value ReferenceAddTo Add to existing QToolWindowManagerArea as new tab. 175 | \value ReferenceLeftOf Add to new area to the left of the QToolWindowManagerArea. 176 | \value ReferenceRightOf Add to new area to the right of the QToolWindowManagerArea. 177 | \value ReferenceTopOf Add to new area to the top of the QToolWindowManagerArea. 178 | \value ReferenceBottomOf Add to new area to the bottom of the QToolWindowManagerArea. 179 | 180 | */ 181 | /*! 182 | \fn void QToolWindowManager::toolWindowVisibilityChanged(QWidget* toolWindow, bool visible) 183 | 184 | This signal is emitted when \a toolWindow may be hidden or shown. 185 | \a visible indicates new visibility state of the tool window. 186 | */ 187 | 188 | /*! 189 | * \brief Creates a manager with given \a parent. 190 | */ 191 | QToolWindowManager::QToolWindowManager(QWidget *parent) : 192 | QWidget(parent, 0) 193 | { 194 | d_ptr = new QToolWindowManagerPrivate(); 195 | d_ptr->q_ptr = this; 196 | Q_D(QToolWindowManager); 197 | d->slots_object.d = d; 198 | d->m_lastUsedArea = 0; 199 | d->m_borderSensitivity = 12; 200 | d->m_tabsClosable = true; 201 | QSplitter *testSplitter = new QSplitter(); 202 | d->m_rubberBandLineWidth = testSplitter->handleWidth(); 203 | delete testSplitter; 204 | d->m_dragIndicator = new QLabel(0, Qt::ToolTip ); 205 | d->m_dragIndicator->setAttribute(Qt::WA_ShowWithoutActivating); 206 | QVBoxLayout* mainLayout = new QVBoxLayout(this); 207 | mainLayout->setContentsMargins(0, 0, 0, 0); 208 | QToolWindowManagerWrapper* wrapper = new QToolWindowManagerWrapper(this); 209 | wrapper->setWindowFlags(wrapper->windowFlags() & ~Qt::Tool); 210 | mainLayout->addWidget(wrapper); 211 | connect(&(d->m_dropSuggestionSwitchTimer), SIGNAL(timeout()), 212 | &(d->slots_object), SLOT(showNextDropSuggestion())); 213 | d->m_dropSuggestionSwitchTimer.setInterval(1000); 214 | d->m_dropCurrentSuggestionIndex = 0; 215 | 216 | d->m_rectRubberBand = new QRubberBand(QRubberBand::Rectangle, this); 217 | d->m_lineRubberBand = new QRubberBand(QRubberBand::Line, this); 218 | } 219 | 220 | /*! 221 | * \brief Destroys the widget. Additionally all tool windows and all floating windows 222 | * created by this widget are destroyed. 223 | */ 224 | QToolWindowManager::~QToolWindowManager() 225 | { 226 | Q_D(QToolWindowManager); 227 | qDeleteAll(d->m_areas); 228 | d->m_areas.clear(); 229 | qDeleteAll(d->m_wrappers); 230 | d->m_wrappers.clear(); 231 | delete d_ptr; 232 | } 233 | 234 | /*! 235 | * Adds \a toolWindow to the manager and moves it to the position specified in 236 | * \a area. This function is a shortcut for QToolWindowManager::addToolWindows. 237 | */ 238 | void QToolWindowManager::addToolWindow(QWidget *toolWindow, 239 | QToolWindowManager::AreaType area) 240 | { 241 | Q_D(QToolWindowManager); 242 | d->addToolWindows(QWidgetList() << toolWindow, 243 | QToolWindowManagerAreaReference(area)); 244 | } 245 | 246 | /*! 247 | \overload 248 | 249 | Adds \a toolWindow to the manager and moves it to the position specified by 250 | a \a reference relative to \a area. 251 | This function is a shortcut for QToolWindowManager::addToolWindows. 252 | */ 253 | void QToolWindowManager::addToolWindow(QWidget *toolWindow, 254 | QToolWindowManager::ReferenceType reference, 255 | QAbstractToolWindowManagerArea *area) 256 | { 257 | Q_D(QToolWindowManager); 258 | d->addToolWindows(QWidgetList() << toolWindow, 259 | QToolWindowManagerAreaReference(reference, area)); 260 | } 261 | 262 | /*! 263 | * \brief Adds \a toolWindows to the manager and moves it to the position specified in \a area. 264 | * The manager takes ownership of the tool windows and will delete them upon destruction. 265 | * 266 | * toolWindow->windowIcon() and toolWindow->windowTitle() will be used as the icon and title 267 | * of the tab that represents the tool window. 268 | * 269 | * If you intend to use QToolWindowManager::saveState 270 | * and QToolWindowManager::restoreState functions, you must set objectName() of each added 271 | * tool window to a non-empty unique string. 272 | */ 273 | void QToolWindowManager::addToolWindows(const QWidgetList &toolWindows, 274 | QToolWindowManager::AreaType area) 275 | { 276 | Q_D(QToolWindowManager); 277 | d->addToolWindows(toolWindows, 278 | QToolWindowManagerAreaReference(area)); 279 | } 280 | 281 | /*! 282 | \overload 283 | 284 | Adds \a toolWindows to the manager and moves it to the position specified by 285 | a \a reference relative to \a area. 286 | */ 287 | void QToolWindowManager::addToolWindows(const QWidgetList &toolWindows, 288 | QToolWindowManager::ReferenceType reference, 289 | QAbstractToolWindowManagerArea *area) 290 | { 291 | Q_D(QToolWindowManager); 292 | d->addToolWindows(toolWindows, 293 | QToolWindowManagerAreaReference(reference, area)); 294 | } 295 | 296 | /*! 297 | * \brief Moves \a toolWindow to the position specified in \a area. 298 | * 299 | * \a toolWindow must be added to the manager prior to calling this function. 300 | */ 301 | void QToolWindowManager::moveToolWindow(QWidget *toolWindow, 302 | QToolWindowManager::AreaType area) 303 | { 304 | Q_D(QToolWindowManager); 305 | d->moveToolWindows(QWidgetList() << toolWindow, 306 | QToolWindowManagerAreaReference(area)); 307 | } 308 | 309 | /*! 310 | \overload 311 | 312 | \brief Moves \a toolWindow to the position specified by a \a reference relative to \a area. 313 | */ 314 | void QToolWindowManager::moveToolWindow(QWidget *toolWindow, 315 | QToolWindowManager::ReferenceType reference, 316 | QAbstractToolWindowManagerArea *area) 317 | { 318 | Q_D(QToolWindowManager); 319 | d->moveToolWindows(QWidgetList() << toolWindow, 320 | QToolWindowManagerAreaReference(reference, area)); 321 | } 322 | /*! 323 | * \brief Moves \a toolWindows to the position specified in \a area. 324 | * 325 | * \a toolWindows must be added to the manager prior to calling this function. 326 | */ 327 | void QToolWindowManager::moveToolWindows(const QWidgetList &toolWindows, 328 | QToolWindowManager::AreaType area) 329 | { 330 | Q_D(QToolWindowManager); 331 | d->moveToolWindows(toolWindows, 332 | QToolWindowManagerAreaReference(area)); 333 | } 334 | 335 | /*! 336 | \overload 337 | 338 | \brief Moves \a toolWindows to the position specified by a \a reference relative to \a area. 339 | */ 340 | void QToolWindowManager::moveToolWindows(const QWidgetList &toolWindows, 341 | QToolWindowManager::ReferenceType reference, 342 | QAbstractToolWindowManagerArea *area) 343 | { 344 | Q_D(QToolWindowManager); 345 | d->moveToolWindows(toolWindows, 346 | QToolWindowManagerAreaReference(reference, area)); 347 | } 348 | 349 | void QToolWindowManagerPrivate::addToolWindows(QList toolWindows, 350 | const QToolWindowManagerAreaReference &area) 351 | { 352 | foreach (QWidget* toolWindow, toolWindows) { 353 | if (!toolWindow) { 354 | qWarning("cannot add null widget"); 355 | continue; 356 | } 357 | if (m_toolWindows.contains(toolWindow)) { 358 | qWarning("this tool window has already been added"); 359 | continue; 360 | } 361 | toolWindow->hide(); 362 | toolWindow->setParent(0); 363 | m_toolWindows << toolWindow; 364 | } 365 | moveToolWindows(toolWindows, area); 366 | } 367 | 368 | /*! 369 | * Returns the area that contains \a toolWindow, or 0 if \a toolWindow is hidden. 370 | */ 371 | QAbstractToolWindowManagerArea *QToolWindowManager::areaFor(QWidget *toolWindow) const 372 | { 373 | return findClosestParent(toolWindow); 374 | } 375 | 376 | void QToolWindowManagerPrivate::moveToolWindows(const QWidgetList &toolWindows, 377 | const QToolWindowManagerAreaReference& area_param) 378 | { 379 | Q_Q(QToolWindowManager); 380 | QToolWindowManagerAreaReference area = area_param; 381 | foreach (QWidget *toolWindow, toolWindows) { 382 | if (!m_toolWindows.contains(toolWindow)) { 383 | qWarning("unknown tool window"); 384 | return; 385 | } 386 | if (toolWindow->parentWidget() != 0) 387 | releaseToolWindow(toolWindow); 388 | } 389 | if (!area.isReference() && area.areaType() == QToolWindowManager::LastUsedArea && !m_lastUsedArea) { 390 | QAbstractToolWindowManagerArea *foundArea = q->findChild(); 391 | if (foundArea) 392 | area = QToolWindowManagerAreaReference(QToolWindowManager::ReferenceAddTo, foundArea); 393 | else 394 | area = QToolWindowManager::EmptySpaceArea; 395 | } 396 | 397 | if (!area.isReference() && area.areaType() == QToolWindowManager::NoArea) { 398 | //do nothing 399 | } else if (!area.isReference() && area.areaType() == QToolWindowManager::NewFloatingArea) { 400 | QAbstractToolWindowManagerArea *area = createAndSetupArea(); 401 | area->addToolWindows(toolWindows); 402 | m_lastUsedArea = area; 403 | QToolWindowManagerWrapper *wrapper = new QToolWindowManagerWrapper(q); 404 | wrapper->layout()->addWidget(area); 405 | wrapper->move(QCursor::pos()); 406 | wrapper->show(); 407 | } else if (area.isReference() && area.referenceType() == QToolWindowManager::ReferenceAddTo) { 408 | QAbstractToolWindowManagerArea *area2 = 409 | static_cast(area.widget()); 410 | area2->addToolWindows(toolWindows); 411 | m_lastUsedArea = area2; 412 | } else if (area.isReference()) { 413 | QSplitter *parentSplitter = qobject_cast(area.widget()->parentWidget()); 414 | QToolWindowManagerWrapper *wrapper = 415 | qobject_cast(area.widget()->parentWidget()); 416 | if (!parentSplitter && !wrapper) { 417 | qWarning("unknown parent type"); 418 | return; 419 | } 420 | bool useParentSplitter = false; 421 | int indexInParentSplitter = 0; 422 | if (parentSplitter) { 423 | indexInParentSplitter = parentSplitter->indexOf(area.widget()); 424 | if (parentSplitter->orientation() == Qt::Vertical) 425 | useParentSplitter = area.referenceType() == QToolWindowManager::ReferenceTopOf || 426 | area.referenceType() == QToolWindowManager::ReferenceBottomOf; 427 | else 428 | useParentSplitter = area.referenceType() == QToolWindowManager::ReferenceLeftOf || 429 | area.referenceType() == QToolWindowManager::ReferenceRightOf; 430 | } 431 | if (useParentSplitter) { 432 | if (area.referenceType() == QToolWindowManager::ReferenceBottomOf || 433 | area.referenceType() == QToolWindowManager::ReferenceRightOf) 434 | indexInParentSplitter++; 435 | QAbstractToolWindowManagerArea *newArea = createAndSetupArea(); 436 | newArea->addToolWindows(toolWindows); 437 | m_lastUsedArea = newArea; 438 | parentSplitter->insertWidget(indexInParentSplitter, newArea); 439 | } else { 440 | area.widget()->hide(); 441 | area.widget()->setParent(0); 442 | QSplitter *splitter = createAndSetupSplitter(); 443 | if (area.referenceType() == QToolWindowManager::ReferenceTopOf || 444 | area.referenceType() == QToolWindowManager::ReferenceBottomOf) 445 | splitter->setOrientation(Qt::Vertical); 446 | else 447 | splitter->setOrientation(Qt::Horizontal); 448 | splitter->addWidget(area.widget()); 449 | area.widget()->show(); 450 | QAbstractToolWindowManagerArea *newArea = createAndSetupArea(); 451 | if (area.referenceType() == QToolWindowManager::ReferenceTopOf || 452 | area.referenceType() == QToolWindowManager::ReferenceLeftOf) 453 | splitter->insertWidget(0, newArea); 454 | else 455 | splitter->addWidget(newArea); 456 | if (parentSplitter) 457 | parentSplitter->insertWidget(indexInParentSplitter, splitter); 458 | else 459 | wrapper->layout()->addWidget(splitter); 460 | newArea->addToolWindows(toolWindows); 461 | m_lastUsedArea = newArea; 462 | } 463 | } else if (!area.isReference() && area.areaType() == QToolWindowManager::EmptySpaceArea) { 464 | QAbstractToolWindowManagerArea *newArea = createAndSetupArea(); 465 | q->findChild()->layout()->addWidget(newArea); 466 | newArea->addToolWindows(toolWindows); 467 | m_lastUsedArea = newArea; 468 | } else if (!area.isReference() && area.areaType() == QToolWindowManager::LastUsedArea) { 469 | m_lastUsedArea->addToolWindows(toolWindows); 470 | } else { 471 | qWarning("invalid type"); 472 | } 473 | simplifyLayout(); 474 | foreach (QWidget *toolWindow, toolWindows) 475 | emit q->toolWindowVisibilityChanged(toolWindow, toolWindow->parent() != 0); 476 | } 477 | 478 | /*! 479 | * \brief Removes \a toolWindow from the manager. \a toolWindow becomes a hidden 480 | * top level widget. The ownership of \a toolWindow is returned to the caller. 481 | */ 482 | void QToolWindowManager::removeToolWindow(QWidget *toolWindow) 483 | { 484 | Q_D(QToolWindowManager); 485 | if (!d->m_toolWindows.contains(toolWindow)) { 486 | qWarning("unknown tool window"); 487 | return; 488 | } 489 | moveToolWindow(toolWindow, NoArea); 490 | d->m_toolWindows.removeOne(toolWindow); 491 | } 492 | 493 | /*! 494 | * \brief Returns all tool window added to the manager. 495 | */ 496 | QWidgetList QToolWindowManager::toolWindows() const 497 | { 498 | const Q_D(QToolWindowManager); 499 | return d->m_toolWindows; 500 | } 501 | 502 | /*! 503 | * Hides \a toolWindow. 504 | * 505 | * \a toolWindow must be added to the manager prior to calling this function. 506 | */ 507 | void QToolWindowManager::hideToolWindow(QWidget *toolWindow) 508 | { 509 | moveToolWindow(toolWindow, NoArea); 510 | } 511 | 512 | void QToolWindowManager::setSuggestionSwitchInterval(int msec) 513 | { 514 | Q_D(QToolWindowManager); 515 | d->m_dropSuggestionSwitchTimer.setInterval(msec); 516 | emit suggestionSwitchIntervalChanged(msec); 517 | } 518 | 519 | int QToolWindowManager::suggestionSwitchInterval() const 520 | { 521 | const Q_D(QToolWindowManager); 522 | return d->m_dropSuggestionSwitchTimer.interval(); 523 | } 524 | 525 | int QToolWindowManager::borderSensitivity() const 526 | { 527 | const Q_D(QToolWindowManager); 528 | return d->m_borderSensitivity; 529 | } 530 | 531 | void QToolWindowManager::setBorderSensitivity(int pixels) 532 | { 533 | Q_D(QToolWindowManager); 534 | d->m_borderSensitivity = pixels; 535 | emit borderSensitivityChanged(pixels); 536 | } 537 | 538 | void QToolWindowManager::setRubberBandLineWidth(int pixels) 539 | { 540 | Q_D(QToolWindowManager); 541 | d->m_rubberBandLineWidth = pixels; 542 | emit rubberBandLineWidthChanged(pixels); 543 | } 544 | 545 | bool QToolWindowManager::tabsClosable() const 546 | { 547 | const Q_D(QToolWindowManager); 548 | return d->m_tabsClosable; 549 | } 550 | 551 | void QToolWindowManager::setTabsClosable(bool enabled) 552 | { 553 | Q_D(QToolWindowManager); 554 | if (d->m_tabsClosable != enabled) { 555 | d->m_tabsClosable = enabled; 556 | emit tabsClosableChanged(enabled); 557 | } 558 | } 559 | 560 | int QToolWindowManager::rubberBandLineWidth() const 561 | { 562 | const Q_D(QToolWindowManager); 563 | return d->m_rubberBandLineWidth; 564 | } 565 | 566 | /*! 567 | * Returns the widget that is used to display rectangular drop suggestions. 568 | */ 569 | QRubberBand *QToolWindowManager::rectRubberBand() const 570 | { 571 | const Q_D(QToolWindowManager); 572 | return d->m_rectRubberBand; 573 | } 574 | 575 | /*! 576 | * Returns the widget that is used to display line drop suggestions. 577 | */ 578 | QRubberBand *QToolWindowManager::lineRubberBand() const 579 | { 580 | const Q_D(QToolWindowManager); 581 | return d->m_lineRubberBand; 582 | } 583 | 584 | void QToolWindowManager::setTabButton(QWidget* toolWindow, QTabBar::ButtonPosition position, QWidget* widget) { 585 | Q_D(QToolWindowManager); 586 | QAbstractToolWindowManagerArea *area = areaFor(toolWindow); 587 | if (area) 588 | area->beforeTabButtonChanged(toolWindow); 589 | switch(position) { 590 | case QTabBar::LeftSide: 591 | d->m_toolWindowData[toolWindow].leftButtonWidget = widget; 592 | break; 593 | case QTabBar::RightSide: 594 | d->m_toolWindowData[toolWindow].rightButtonWidget = widget; 595 | break; 596 | } 597 | if (area) 598 | area->tabButtonChanged(toolWindow); 599 | } 600 | 601 | /*! 602 | * Create a splitter. Reimplement this function if you want to use your own splitter subclass. 603 | */ 604 | QSplitter *QToolWindowManager::createSplitter() 605 | { 606 | QSplitter *splitter = new QSplitter(); 607 | splitter->setChildrenCollapsible(false); 608 | return splitter; 609 | } 610 | 611 | /*! 612 | * Dumps the state and position of all tool windows to a variable. It can be stored in application settings 613 | * using QSettings. Stored state can be restored by calling QToolWindowManager::restoreState 614 | * with the same value. 615 | */ 616 | QVariant QToolWindowManager::saveState() const 617 | { 618 | const Q_D(QToolWindowManager); 619 | QVariantMap result; 620 | result[QLatin1String("QToolWindowManagerStateFormat")] = 1; 621 | QToolWindowManagerWrapper *mainWrapper = findChild(); 622 | if (!mainWrapper) { 623 | qWarning("can't find main wrapper"); 624 | return QVariant(); 625 | } 626 | result[QLatin1String("mainWrapper")] = mainWrapper->saveState(); 627 | QVariantList floatingWindowsData; 628 | foreach (QToolWindowManagerWrapper *wrapper, d->m_wrappers) { 629 | if (!wrapper->isWindow()) 630 | continue; 631 | floatingWindowsData << wrapper->saveState(); 632 | } 633 | result[QLatin1String("floatingWindows")] = floatingWindowsData; 634 | return result; 635 | } 636 | 637 | /*! 638 | Restores state and position of tool windows stored in \a data. 639 | */ 640 | void QToolWindowManager::restoreState(const QVariant &data) 641 | { 642 | Q_D(QToolWindowManager); 643 | if (!data.isValid()) 644 | return; 645 | QVariantMap dataMap = data.toMap(); 646 | if (dataMap[QLatin1String("QToolWindowManagerStateFormat")].toInt() != 1) { 647 | qWarning("state format is not recognized"); 648 | return; 649 | } 650 | moveToolWindows(d->m_toolWindows, NoArea); 651 | QToolWindowManagerWrapper *mainWrapper = findChild(); 652 | if (!mainWrapper) { 653 | qWarning("can't find main wrapper"); 654 | return; 655 | } 656 | mainWrapper->restoreState(dataMap[QLatin1String("mainWrapper")].toMap()); 657 | foreach (QVariant windowData, dataMap[QLatin1String("floatingWindows")].toList()) { 658 | QToolWindowManagerWrapper *wrapper = new QToolWindowManagerWrapper(this); 659 | wrapper->restoreState(windowData.toMap()); 660 | wrapper->show(); 661 | } 662 | d->simplifyLayout(); 663 | foreach (QWidget *toolWindow, d->m_toolWindows) 664 | emit toolWindowVisibilityChanged(toolWindow, toolWindow->parentWidget() != 0); 665 | } 666 | 667 | 668 | void QToolWindowManagerPrivate::handleNoSuggestions() 669 | { 670 | Q_Q(QToolWindowManager); 671 | m_rectRubberBand->hide(); 672 | m_lineRubberBand->hide(); 673 | m_lineRubberBand->setParent(q); 674 | m_rectRubberBand->setParent(q); 675 | m_suggestions.clear(); 676 | m_dropCurrentSuggestionIndex = 0; 677 | if (m_dropSuggestionSwitchTimer.isActive()) 678 | m_dropSuggestionSwitchTimer.stop(); 679 | } 680 | 681 | void QToolWindowManagerPrivate::releaseToolWindow(QWidget *toolWindow) 682 | { 683 | QAbstractToolWindowManagerArea *previousArea = 684 | findClosestParent(toolWindow); 685 | if (!previousArea) { 686 | qWarning("cannot find tab widget for tool window"); 687 | return; 688 | } 689 | previousArea->removeToolWindow(toolWindow); 690 | toolWindow->hide(); 691 | toolWindow->setParent(0); 692 | } 693 | 694 | void QToolWindowManagerPrivate::simplifyLayout() 695 | { 696 | foreach (QAbstractToolWindowManagerArea *area, m_areas) { 697 | if (area->parentWidget() == 0) { 698 | if (area->toolWindows().isEmpty()) { 699 | area->deleteLater(); 700 | } 701 | continue; 702 | } 703 | QSplitter *splitter = qobject_cast(area->parentWidget()); 704 | QSplitter *validSplitter = 0; // least top level splitter that should remain 705 | QSplitter *invalidSplitter = 0; //most top level splitter that should be deleted 706 | while (splitter) { 707 | if (splitter->count() > 1) { 708 | validSplitter = splitter; 709 | break; 710 | } 711 | invalidSplitter = splitter; 712 | splitter = qobject_cast(splitter->parentWidget()); 713 | } 714 | if (!validSplitter) { 715 | QToolWindowManagerWrapper *wrapper = 716 | findClosestParent(area); 717 | if (!wrapper) { 718 | qWarning("can't find wrapper"); 719 | return; 720 | } 721 | if (area->toolWindows().isEmpty() && wrapper->isWindow()) { 722 | wrapper->hide(); 723 | wrapper->deleteLater(); 724 | } else if (area->parent() != wrapper) { 725 | wrapper->layout()->addWidget(area); 726 | } 727 | } else if (!area->toolWindows().isEmpty() && 728 | validSplitter && 729 | area->parent() != validSplitter) { 730 | int index = validSplitter->indexOf(invalidSplitter); 731 | validSplitter->insertWidget(index, area); 732 | } 733 | if (invalidSplitter) { 734 | invalidSplitter->hide(); 735 | invalidSplitter->setParent(0); 736 | invalidSplitter->deleteLater(); 737 | } 738 | if (area->toolWindows().isEmpty()) { 739 | area->hide(); 740 | area->setParent(0); 741 | area->deleteLater(); 742 | } 743 | } 744 | } 745 | 746 | void QToolWindowManagerPrivate::startDrag(const QWidgetList &toolWindows) 747 | { 748 | Q_Q(QToolWindowManager); 749 | if (dragInProgress()) { 750 | qWarning("QToolWindowManager::execDrag: drag is already in progress"); 751 | return; 752 | } 753 | if (toolWindows.isEmpty()) 754 | return; 755 | m_draggedToolWindows = toolWindows; 756 | m_dragIndicator->setPixmap(q->generateDragPixmap(toolWindows)); 757 | updateDragPosition(); 758 | m_dragIndicator->show(); 759 | } 760 | 761 | QVariantMap QToolWindowManagerPrivate::saveAreaState(QAbstractToolWindowManagerArea *area) { 762 | QVariantMap result; 763 | result[QLatin1String("type")] = QLatin1String("area"); 764 | QStringList objectNames; 765 | foreach (QWidget *widget, area->toolWindows()) { 766 | QString name = widget->objectName(); 767 | if (name.isEmpty()) 768 | qWarning("cannot save state of tool window without object name"); 769 | else 770 | objectNames << name; 771 | } 772 | result[QLatin1String("objectNames")] = objectNames; 773 | result[QLatin1String("customData")] = area->saveState(); 774 | return result; 775 | } 776 | 777 | QAbstractToolWindowManagerArea *QToolWindowManagerPrivate::restoreAreaState(const QVariantMap &data) { 778 | QWidgetList toolWindows; 779 | foreach (QVariant objectNameValue, data[QLatin1String("objectNames")].toList()) { 780 | QString objectName = objectNameValue.toString(); 781 | if (objectName.isEmpty()) { continue; } 782 | bool found = false; 783 | foreach (QWidget *toolWindow, m_toolWindows) { 784 | if (toolWindow->objectName() == objectName) { 785 | toolWindows << toolWindow; 786 | found = true; 787 | break; 788 | } 789 | } 790 | if (!found) 791 | qWarning("tool window with name '%s' not found", objectName.toLocal8Bit().constData()); 792 | } 793 | QAbstractToolWindowManagerArea *area = createAndSetupArea(); 794 | area->addToolWindows(toolWindows); 795 | area->restoreState(data[QLatin1String("customData")]); 796 | return area; 797 | } 798 | 799 | QVariantMap QToolWindowManagerPrivate::saveSplitterState(QSplitter *splitter) 800 | { 801 | QVariantMap result; 802 | result[QLatin1String("state")] = splitter->saveState(); 803 | result[QLatin1String("type")] = QLatin1String("splitter"); 804 | QVariantList items; 805 | for (int i = 0; i < splitter->count(); i++) { 806 | QWidget *item = splitter->widget(i); 807 | QVariantMap itemValue; 808 | QAbstractToolWindowManagerArea *area = qobject_cast(item); 809 | if (area) { 810 | itemValue = saveAreaState(area); 811 | } else { 812 | QSplitter *childSplitter = qobject_cast(item); 813 | if (childSplitter) 814 | itemValue = saveSplitterState(childSplitter); 815 | else 816 | qWarning("unknown splitter item"); 817 | } 818 | items << itemValue; 819 | } 820 | result[QLatin1String("items")] = items; 821 | return result; 822 | } 823 | 824 | QSplitter *QToolWindowManagerPrivate::restoreSplitterState(const QVariantMap &data) 825 | { 826 | //Q_Q(QToolWindowManager); 827 | if (data[QLatin1String("items")].toList().count() < 2) 828 | qWarning("invalid splitter encountered"); 829 | 830 | QSplitter *splitter = createAndSetupSplitter(); 831 | foreach (QVariant itemData, data[QLatin1String("items")].toList()) { 832 | QVariantMap itemValue = itemData.toMap(); 833 | QString itemType = itemValue[QLatin1String("type")].toString(); 834 | if (itemType == QLatin1String("splitter")) { 835 | splitter->addWidget(restoreSplitterState(itemValue)); 836 | } else if (itemType == QLatin1String("area")) { 837 | splitter->addWidget(restoreAreaState(itemValue)); 838 | } else { 839 | qWarning("unknown item type"); 840 | } 841 | } 842 | splitter->restoreState(data[QLatin1String("state")].toByteArray()); 843 | return splitter; 844 | } 845 | 846 | /*! 847 | * Generates a pixmap for \a toolWindows that is used to represent the data 848 | * in a drag and drop operation near the mouse cursor. 849 | * You may reimplement this function to use different pixmaps. 850 | */ 851 | QPixmap QToolWindowManager::generateDragPixmap(const QList &toolWindows) 852 | { 853 | QTabBar widget; 854 | widget.setDocumentMode(true); 855 | foreach (QWidget *toolWindow, toolWindows) { 856 | widget.addTab(toolWindow->windowIcon(), toolWindow->windowTitle()); 857 | } 858 | #if QT_VERSION >= 0x050000 // Qt5 859 | return widget.grab(); 860 | #else //Qt4 861 | return QPixmap::grabWidget(&widget); 862 | #endif 863 | } 864 | 865 | void QToolWindowManagerPrivate::showNextDropSuggestion() 866 | { 867 | Q_Q(QToolWindowManager); 868 | if (m_suggestions.isEmpty()) { 869 | qWarning("showNextDropSuggestion called but no suggestions"); 870 | return; 871 | } 872 | m_dropCurrentSuggestionIndex++; 873 | if (m_dropCurrentSuggestionIndex >= m_suggestions.count()) 874 | m_dropCurrentSuggestionIndex = 0; 875 | const QToolWindowManagerAreaReference& suggestion = 876 | m_suggestions[m_dropCurrentSuggestionIndex]; 877 | if ( (suggestion.isReference() && suggestion.referenceType() == QToolWindowManager::ReferenceAddTo) || 878 | (!suggestion.isReference() && suggestion.areaType() == QToolWindowManager::EmptySpaceArea) ) { 879 | QWidget *widget; 880 | if (!suggestion.isReference() && 881 | suggestion.areaType() == QToolWindowManager::EmptySpaceArea) 882 | widget = q->findChild(); 883 | else 884 | widget = suggestion.widget(); 885 | QWidget *placeHolderParent; 886 | if (widget->topLevelWidget() == q->topLevelWidget()) 887 | placeHolderParent = q; 888 | else 889 | placeHolderParent = widget->topLevelWidget(); 890 | QRect placeHolderGeometry = widget->rect(); 891 | placeHolderGeometry.moveTopLeft(widget->mapTo(placeHolderParent, 892 | placeHolderGeometry.topLeft())); 893 | m_rectRubberBand->setGeometry(placeHolderGeometry); 894 | m_rectRubberBand->setParent(placeHolderParent); 895 | m_rectRubberBand->show(); 896 | m_lineRubberBand->hide(); 897 | } else if (suggestion.isReference() && 898 | suggestion.referenceType() != QToolWindowManager::ReferenceAddTo) { 899 | QWidget *placeHolderParent; 900 | if (suggestion.widget()->topLevelWidget() == q->topLevelWidget()) 901 | placeHolderParent = q; 902 | else 903 | placeHolderParent = suggestion.widget()->topLevelWidget(); 904 | QRect placeHolderGeometry = sidePlaceHolderRect(suggestion.widget(), 905 | suggestion.referenceType()); 906 | placeHolderGeometry.moveTopLeft(suggestion.widget()->mapTo(placeHolderParent, 907 | placeHolderGeometry.topLeft())); 908 | 909 | m_lineRubberBand->setGeometry(placeHolderGeometry); 910 | m_lineRubberBand->setParent(placeHolderParent); 911 | m_lineRubberBand->show(); 912 | m_rectRubberBand->hide(); 913 | } else { 914 | qWarning("unsupported suggestion type"); 915 | } 916 | } 917 | 918 | void QToolWindowManagerPrivate::findSuggestions(QToolWindowManagerWrapper *wrapper) 919 | { 920 | m_suggestions.clear(); 921 | m_dropCurrentSuggestionIndex = -1; 922 | QPoint globalPos = QCursor::pos(); 923 | QWidgetList candidates; 924 | foreach (QSplitter *splitter, wrapper->findChildren()) 925 | candidates << splitter; 926 | foreach (QAbstractToolWindowManagerArea *area, m_areas) 927 | if (area->topLevelWidget() == wrapper->topLevelWidget()) 928 | candidates << area; 929 | foreach (QWidget *widget, candidates) { 930 | QSplitter *splitter = qobject_cast(widget); 931 | QAbstractToolWindowManagerArea *area = qobject_cast(widget); 932 | if (!splitter && !area) { 933 | qWarning("unexpected widget type"); 934 | continue; 935 | } 936 | QSplitter *parentSplitter = qobject_cast(widget->parentWidget()); 937 | bool lastInSplitter = parentSplitter && 938 | parentSplitter->indexOf(widget) == parentSplitter->count() - 1; 939 | 940 | QList allowedSides; 941 | if (!splitter || splitter->orientation() == Qt::Vertical) 942 | allowedSides << QToolWindowManager::ReferenceLeftOf; 943 | if (!splitter || splitter->orientation() == Qt::Horizontal) 944 | allowedSides << QToolWindowManager::ReferenceTopOf; 945 | if (!parentSplitter || parentSplitter->orientation() == Qt::Vertical || lastInSplitter) 946 | if (!splitter || splitter->orientation() == Qt::Vertical) 947 | allowedSides << QToolWindowManager::ReferenceRightOf; 948 | if (!parentSplitter || parentSplitter->orientation() == Qt::Horizontal || lastInSplitter) 949 | if (!splitter || splitter->orientation() == Qt::Horizontal) 950 | allowedSides << QToolWindowManager::ReferenceBottomOf; 951 | foreach (QToolWindowManager::ReferenceType side, allowedSides) 952 | if (sideSensitiveArea(widget, side).contains(widget->mapFromGlobal(globalPos))) 953 | m_suggestions << QToolWindowManagerAreaReference(side, widget); 954 | if (area && area->rect().contains(area->mapFromGlobal(globalPos))) 955 | m_suggestions << QToolWindowManagerAreaReference(QToolWindowManager::ReferenceAddTo, area); 956 | } 957 | if (candidates.isEmpty()) 958 | m_suggestions << QToolWindowManager::EmptySpaceArea; 959 | 960 | if (m_suggestions.isEmpty()) 961 | handleNoSuggestions(); 962 | else 963 | showNextDropSuggestion(); 964 | } 965 | 966 | QRect QToolWindowManagerPrivate::sideSensitiveArea(QWidget *widget, 967 | QToolWindowManager::ReferenceType side) 968 | { 969 | QRect widgetRect = widget->rect(); 970 | if (side == QToolWindowManager::ReferenceTopOf) 971 | return QRect(QPoint(widgetRect.left(), widgetRect.top() - m_borderSensitivity), 972 | QSize(widgetRect.width(), m_borderSensitivity * 2)); 973 | if (side == QToolWindowManager::ReferenceLeftOf) 974 | return QRect(QPoint(widgetRect.left() - m_borderSensitivity, widgetRect.top()), 975 | QSize(m_borderSensitivity * 2, widgetRect.height())); 976 | 977 | if (side == QToolWindowManager::ReferenceBottomOf) 978 | return QRect(QPoint(widgetRect.left(), 979 | widgetRect.top() + widgetRect.height() - m_borderSensitivity), 980 | QSize(widgetRect.width(), m_borderSensitivity * 2)); 981 | if (side == QToolWindowManager::ReferenceRightOf) 982 | return QRect(QPoint(widgetRect.left() + widgetRect.width() - m_borderSensitivity, 983 | widgetRect.top()), 984 | QSize(m_borderSensitivity * 2, widgetRect.height())); 985 | 986 | qWarning("invalid side"); 987 | return QRect(); 988 | } 989 | 990 | QRect QToolWindowManagerPrivate::sidePlaceHolderRect(QWidget *widget, 991 | QToolWindowManager::ReferenceType side) 992 | { 993 | QRect widgetRect = widget->rect(); 994 | QSplitter *parentSplitter = qobject_cast(widget->parentWidget()); 995 | if (parentSplitter && parentSplitter->indexOf(widget) > 0) { 996 | int delta = parentSplitter->handleWidth() / 2 + m_rubberBandLineWidth / 2; 997 | if (side == QToolWindowManager::ReferenceTopOf && parentSplitter->orientation() == Qt::Vertical) 998 | return QRect(QPoint(widgetRect.left(), widgetRect.top() - delta), 999 | QSize(widgetRect.width(), m_rubberBandLineWidth)); 1000 | if (side == QToolWindowManager::ReferenceLeftOf && parentSplitter->orientation() == Qt::Horizontal) 1001 | return QRect(QPoint(widgetRect.left() - delta, widgetRect.top()), 1002 | QSize(m_rubberBandLineWidth, widgetRect.height())); 1003 | } 1004 | if (side == QToolWindowManager::ReferenceTopOf) 1005 | return QRect(QPoint(widgetRect.left(), widgetRect.top()), 1006 | QSize(widgetRect.width(), m_rubberBandLineWidth)); 1007 | if (side == QToolWindowManager::ReferenceLeftOf) 1008 | return QRect(QPoint(widgetRect.left(), widgetRect.top()), 1009 | QSize(m_rubberBandLineWidth, widgetRect.height())); 1010 | if (side == QToolWindowManager::ReferenceBottomOf) 1011 | return QRect(QPoint(widgetRect.left(), 1012 | widgetRect.top() + widgetRect.height() - m_rubberBandLineWidth), 1013 | QSize(widgetRect.width(), m_rubberBandLineWidth)); 1014 | if (side == QToolWindowManager::ReferenceRightOf) 1015 | return QRect(QPoint(widgetRect.left() + widgetRect.width() - m_rubberBandLineWidth, 1016 | widgetRect.top()), 1017 | QSize(m_rubberBandLineWidth, widgetRect.height())); 1018 | qWarning("invalid side"); 1019 | return QRect(); 1020 | } 1021 | 1022 | void QToolWindowManagerPrivate::updateDragPosition() 1023 | { 1024 | if (!dragInProgress()) 1025 | return; 1026 | if (!(qApp->mouseButtons() & Qt::LeftButton)) { 1027 | finishDrag(); 1028 | return; 1029 | } 1030 | 1031 | QPoint pos = QCursor::pos(); 1032 | m_dragIndicator->move(pos + QPoint(1, 1)); 1033 | bool foundWrapper = false; 1034 | 1035 | QWidget *window = qApp->topLevelAt(pos); 1036 | foreach (QToolWindowManagerWrapper *wrapper, m_wrappers) { 1037 | if (wrapper->window() == window) { 1038 | if (wrapper->rect().contains(wrapper->mapFromGlobal(pos))) { 1039 | findSuggestions(wrapper); 1040 | if (!m_suggestions.isEmpty()) { 1041 | //starting or restarting timer 1042 | if (m_dropSuggestionSwitchTimer.isActive()) 1043 | m_dropSuggestionSwitchTimer.stop(); 1044 | m_dropSuggestionSwitchTimer.start(); 1045 | foundWrapper = true; 1046 | } 1047 | } 1048 | break; 1049 | } 1050 | } 1051 | if (!foundWrapper) 1052 | handleNoSuggestions(); 1053 | } 1054 | 1055 | void QToolWindowManagerPrivate::finishDrag() 1056 | { 1057 | if (!dragInProgress()) { 1058 | qWarning("unexpected finishDrag"); 1059 | return; 1060 | } 1061 | if (m_suggestions.isEmpty()) { 1062 | moveToolWindows(m_draggedToolWindows, QToolWindowManager::NewFloatingArea); 1063 | } else { 1064 | if (m_dropCurrentSuggestionIndex >= m_suggestions.count()) { 1065 | qWarning("invalid m_dropCurrentSuggestionIndex"); 1066 | return; 1067 | } 1068 | QToolWindowManagerAreaReference suggestion = m_suggestions[m_dropCurrentSuggestionIndex]; 1069 | handleNoSuggestions(); 1070 | moveToolWindows(m_draggedToolWindows, suggestion); 1071 | } 1072 | m_dragIndicator->hide(); 1073 | m_draggedToolWindows.clear(); 1074 | } 1075 | 1076 | 1077 | QAbstractToolWindowManagerArea *QToolWindowManagerPrivate::createAndSetupArea() { 1078 | Q_Q(QToolWindowManager); 1079 | QAbstractToolWindowManagerArea *area = q->createArea(); 1080 | QObject::connect(area, SIGNAL(destroyed(QObject*)), 1081 | &slots_object, SLOT(areaDestroyed(QObject*))); 1082 | m_areas << area; 1083 | return area; 1084 | } 1085 | 1086 | /*! 1087 | * Create an area object. Reimplement this function if you want to use your own area subclass. 1088 | */ 1089 | QAbstractToolWindowManagerArea *QToolWindowManager::createArea() { 1090 | return new QToolWindowManagerArea(this); 1091 | } 1092 | 1093 | QSplitter *QToolWindowManagerPrivate::createAndSetupSplitter() 1094 | { 1095 | Q_Q(QToolWindowManager); 1096 | //currently no setup here 1097 | return q->createSplitter(); 1098 | } 1099 | 1100 | QToolWindowManagerAreaReference::QToolWindowManagerAreaReference(QToolWindowManager::AreaType type) 1101 | { 1102 | m_areaType = type; 1103 | m_referenceType = static_cast(-1); 1104 | m_widget = 0; 1105 | } 1106 | 1107 | QToolWindowManagerAreaReference::QToolWindowManagerAreaReference(QToolWindowManager::ReferenceType type, 1108 | QWidget *widget) 1109 | { 1110 | m_referenceType = type; 1111 | m_areaType = static_cast(-1); 1112 | m_widget = widget; 1113 | if ( !qobject_cast(widget) && 1114 | !qobject_cast(widget)) { 1115 | qWarning("only QAbstractToolWindowManagerArea or splitter can be used with this type"); 1116 | } 1117 | } 1118 | 1119 | 1120 | 1121 | 1122 | /*! 1123 | \reimp 1124 | */ 1125 | bool QToolWindowManager::event(QEvent *e) 1126 | { 1127 | return QWidget::event(e); 1128 | } 1129 | 1130 | 1131 | void QToolWindowManagerPrivateSlots::showNextDropSuggestion() 1132 | { 1133 | d->showNextDropSuggestion(); 1134 | } 1135 | 1136 | 1137 | 1138 | void QToolWindowManagerPrivateSlots::areaDestroyed(QObject *object) 1139 | { 1140 | QAbstractToolWindowManagerArea *area = static_cast(object); 1141 | if (area == d->m_lastUsedArea) 1142 | d->m_lastUsedArea = 0; 1143 | d->m_areas.removeOne(area); 1144 | } 1145 | 1146 | #endif // QT_NO_TOOLWINDOWMANAGER 1147 | 1148 | QT_END_NAMESPACE 1149 | 1150 | 1151 | void QToolWindowManagerAreaPrivateSlots::tabCloseRequested(int index) 1152 | { 1153 | d->tabCloseRequested(index); 1154 | } 1155 | --------------------------------------------------------------------------------