├── .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 | 
13 |
14 | More screenshots:
15 |
16 | 
17 |
18 | 
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 |
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 |
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 |
--------------------------------------------------------------------------------