Compare commits
68 Commits
fix-python
...
fix-python
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c76540b86 | ||
|
|
6cf527403e | ||
|
|
92843b4972 | ||
|
|
b2df16dcb0 | ||
|
|
8bb15f5447 | ||
|
|
2977f0b8c6 | ||
|
|
251423116f | ||
|
|
04e2a71b66 | ||
|
|
a06fec51c8 | ||
|
|
83eda81263 | ||
|
|
1bb476ca95 | ||
|
|
f0ac455ec1 | ||
|
|
44b2fc6944 | ||
|
|
113e6453ea | ||
|
|
283d814dc6 | ||
|
|
034dc25483 | ||
|
|
b1333b2c4c | ||
|
|
ff58ff72f9 | ||
|
|
00b4dbc821 | ||
|
|
35076bbdb6 | ||
|
|
2dc98804f4 | ||
|
|
961600fe74 | ||
|
|
7fdca76a4c | ||
|
|
32592f6ad1 | ||
|
|
1545e98e6d | ||
|
|
85b3feb10b | ||
|
|
d9fdd20caa | ||
|
|
9e2d001ac5 | ||
|
|
750f9b6142 | ||
|
|
1c3cf8cf2d | ||
|
|
db19cb40d7 | ||
|
|
037fa76fff | ||
|
|
caa2ece751 | ||
|
|
22f2975f3c | ||
|
|
d3323d824a | ||
|
|
41d1ea8f61 | ||
|
|
1e85b1e7fb | ||
|
|
75464708af | ||
|
|
f007451442 | ||
|
|
f591270d46 | ||
|
|
390423d0c1 | ||
|
|
1aed8c7429 | ||
|
|
0aee56114b | ||
|
|
b3ec7423e8 | ||
|
|
179cd4cf45 | ||
|
|
75d26c3cce | ||
|
|
9071664ef2 | ||
|
|
1980f9c42c | ||
|
|
2c917dcd7c | ||
|
|
5ccf15b9ed | ||
|
|
7eaac87640 | ||
|
|
5b9f08c754 | ||
|
|
02c165163a | ||
|
|
4bbc0f1d4f | ||
|
|
cf692797b6 | ||
|
|
0e4ec055b2 | ||
|
|
cf7c25cd88 | ||
|
|
60b5eb00a3 | ||
|
|
0705b4da72 | ||
|
|
09b3e685a9 | ||
|
|
64791eec82 | ||
|
|
dc3aa354ec | ||
|
|
890784ba5a | ||
|
|
c9468bef8a | ||
|
|
0b4c017f22 | ||
|
|
6de558773f | ||
|
|
94258abf43 | ||
|
|
10026ba191 |
@@ -61,11 +61,11 @@ else()
|
|||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(${PROJECT_NAME}_VERSION_MAJOR 0)
|
set(${PROJECT_NAME}_VERSION_MAJOR 1)
|
||||||
set(${PROJECT_NAME}_VERSION_MINOR 9)
|
set(${PROJECT_NAME}_VERSION_MINOR 0)
|
||||||
set(${PROJECT_NAME}_VERSION_PATCH 99)
|
set(${PROJECT_NAME}_VERSION_PATCH 95)
|
||||||
set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH})
|
set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH})
|
||||||
set(${PROJECT_NAME}_SOVERSION "1.0")
|
set(${PROJECT_NAME}_SOVERSION "1.1")
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
@@ -83,6 +83,8 @@ if(OPTION_DEVELOPER_MODE)
|
|||||||
set(${PROJECT_NAME}_TESTS ON)
|
set(${PROJECT_NAME}_TESTS ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# option(OPTION_QTQUICK "Build for QtQuick instead of QtWidgets" OFF)
|
||||||
|
|
||||||
find_package(Qt5Widgets 5.9 REQUIRED)
|
find_package(Qt5Widgets 5.9 REQUIRED)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|||||||
@@ -26,3 +26,12 @@
|
|||||||
- Static build support
|
- Static build support
|
||||||
- Namespaced Qt support
|
- Namespaced Qt support
|
||||||
- Dozens of crash fixes, bugs and much more...
|
- Dozens of crash fixes, bugs and much more...
|
||||||
|
|
||||||
|
* v1.1.0 (, 2020)
|
||||||
|
- New drop indicator style type: Segmented Indicators
|
||||||
|
- Added FocusScope support
|
||||||
|
- Added DockWidget::isFocused() and DockWidgetBase::isFocusedChanged()
|
||||||
|
- Added Config::Flag_AlwaysTitleBarWhenFloating, which complements Flag_HideTitleBarWhenTabsVisible
|
||||||
|
|
||||||
|
* Roadmap
|
||||||
|
- QtQuick support
|
||||||
|
|||||||
@@ -23,6 +23,19 @@ endif()
|
|||||||
if (NOT CMAKE_CXX_STANDARD)
|
if (NOT CMAKE_CXX_STANDARD)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# On macOS, check if Qt is a framework build. This affects how include paths should be handled.
|
||||||
|
get_target_property(QtCore_is_framework Qt5::Core FRAMEWORK)
|
||||||
|
if (QtCore_is_framework)
|
||||||
|
# Get the path to the framework dir.
|
||||||
|
get_filename_component(QT_FRAMEWORK_INCLUDE_DIR "${QT_INCLUDE_DIR}/../" ABSOLUTE)
|
||||||
|
|
||||||
|
list(GET Qt5Core_INCLUDE_DIRS 0 QT_INCLUDE_DIR)
|
||||||
|
# QT_INCLUDE_DIR points to the QtCore.framework directory, so we need to adjust this to point
|
||||||
|
# to the actual include directory, which has include files for non-framework parts of Qt.
|
||||||
|
get_filename_component(QT_INCLUDE_DIR "${QT_INCLUDE_DIR}/../../include" ABSOLUTE)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Flags that we will pass to shiboken-generator
|
# Flags that we will pass to shiboken-generator
|
||||||
# --generator-set=shiboken: tells the generator that we want to use shiboken to generate code,
|
# --generator-set=shiboken: tells the generator that we want to use shiboken to generate code,
|
||||||
# a doc generator is also available
|
# a doc generator is also available
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ public:
|
|||||||
{
|
{
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
QPen pen(Qt::black);
|
QPen pen(Qt::black);
|
||||||
QBrush brush(Qt::yellow);
|
const QColor focusedBackgroundColor = Qt::yellow;
|
||||||
|
const QColor backgroundColor = focusedBackgroundColor.darker(115);
|
||||||
|
QBrush brush(isFocused() ? focusedBackgroundColor : backgroundColor);
|
||||||
pen.setWidth(4);
|
pen.setWidth(4);
|
||||||
p.setPen(pen);
|
p.setPen(pen);
|
||||||
p.setBrush(brush);
|
p.setBrush(brush);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
static QHash<QString, QImage> s_images; /// clazy:exclude=non-pod-global-static
|
static QHash<QString, QImage> s_images; /// clazy:exclude=non-pod-global-static
|
||||||
|
|
||||||
@@ -33,6 +34,15 @@ MyWidget::MyWidget(const QString &backgroundFile, const QString &logoFile, QWidg
|
|||||||
it = s_images.insert(logoFile, QImage(logoFile));
|
it = s_images.insert(logoFile, QImage(logoFile));
|
||||||
m_logo = it.value();
|
m_logo = it.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
|
#if 0
|
||||||
|
// Uncomment to show focus propagation working
|
||||||
|
new QLineEdit(this);
|
||||||
|
auto l2 = new QLineEdit(this);
|
||||||
|
l2->move(0, 100);
|
||||||
|
setFocusProxy(l2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MyWidget::~MyWidget()
|
MyWidget::~MyWidget()
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ int main(int argc, char **argv)
|
|||||||
QCommandLineOption noTitleBars("t", QCoreApplication::translate("main", "Hide titlebars when tabs are visible"));
|
QCommandLineOption noTitleBars("t", QCoreApplication::translate("main", "Hide titlebars when tabs are visible"));
|
||||||
parser.addOption(noTitleBars);
|
parser.addOption(noTitleBars);
|
||||||
|
|
||||||
|
QCommandLineOption alwaysTitleBarWhenFloating("q", QCoreApplication::translate("main", "Don't hide title bars if floating, even if Flag_HideTitleBarWhenTabsVisible is specified."));
|
||||||
|
parser.addOption(alwaysTitleBarWhenFloating);
|
||||||
|
|
||||||
QCommandLineOption alwaysTabs("z", QCoreApplication::translate("main", "Show tabs even if there's only one"));
|
QCommandLineOption alwaysTabs("z", QCoreApplication::translate("main", "Show tabs even if there's only one"));
|
||||||
parser.addOption(alwaysTabs);
|
parser.addOption(alwaysTabs);
|
||||||
|
|
||||||
@@ -78,6 +81,9 @@ int main(int argc, char **argv)
|
|||||||
QCommandLineOption maximizeButton("b", QCoreApplication::translate("main", "DockWidgets have maximize/restore buttons instead of float/dock button"));
|
QCommandLineOption maximizeButton("b", QCoreApplication::translate("main", "DockWidgets have maximize/restore buttons instead of float/dock button"));
|
||||||
parser.addOption(maximizeButton);
|
parser.addOption(maximizeButton);
|
||||||
|
|
||||||
|
QCommandLineOption segmentedIndicators("y", QCoreApplication::translate("main", "Use segmented indicators instead of classical"));
|
||||||
|
parser.addOption(segmentedIndicators);
|
||||||
|
|
||||||
parser.addPositionalArgument("savedlayout", QCoreApplication::translate("main", "loads the specified json file at startup"));
|
parser.addPositionalArgument("savedlayout", QCoreApplication::translate("main", "loads the specified json file at startup"));
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
||||||
@@ -104,6 +110,9 @@ int main(int argc, char **argv)
|
|||||||
Config::self().setSeparatorThickness(10);
|
Config::self().setSeparatorThickness(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(segmentedIndicators))
|
||||||
|
KDDockWidgets::DefaultWidgetFactory::s_dropIndicatorType = KDDockWidgets::DropIndicatorType::Segmented;
|
||||||
|
|
||||||
MainWindowOptions options = MainWindowOption_None;
|
MainWindowOptions options = MainWindowOption_None;
|
||||||
#if defined(DOCKS_DEVELOPER_MODE)
|
#if defined(DOCKS_DEVELOPER_MODE)
|
||||||
options = parser.isSet(centralFrame) ? MainWindowOption_HasCentralFrame
|
options = parser.isSet(centralFrame) ? MainWindowOption_HasCentralFrame
|
||||||
@@ -117,6 +126,17 @@ int main(int argc, char **argv)
|
|||||||
if (parser.isSet(alwaysTabs))
|
if (parser.isSet(alwaysTabs))
|
||||||
flags |= KDDockWidgets::Config::Flag_AlwaysShowTabs;
|
flags |= KDDockWidgets::Config::Flag_AlwaysShowTabs;
|
||||||
|
|
||||||
|
if (parser.isSet(alwaysTitleBarWhenFloating)) {
|
||||||
|
flags |= KDDockWidgets::Config::Flag_AlwaysTitleBarWhenFloating;
|
||||||
|
if (!(flags & KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible)) {
|
||||||
|
qWarning() << "Flag_AlwaysTitleBarWhenFloating is unneeded if Flag_HideTitleBarWhenTabsVisible isn't used."
|
||||||
|
<< "As floating windows already have title bars by default.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(customStyle))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_TitleBarIsFocusable; // also showing title bar focus with -p, just to not introduce another switch
|
||||||
|
|
||||||
if (parser.isSet(reorderTabsOption))
|
if (parser.isSet(reorderTabsOption))
|
||||||
flags |= KDDockWidgets::Config::Flag_AllowReorderTabs;
|
flags |= KDDockWidgets::Config::Flag_AllowReorderTabs;
|
||||||
|
|
||||||
|
|||||||
34
examples/qtquick/CMakeLists.txt
Normal file
34
examples/qtquick/CMakeLists.txt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.7)
|
||||||
|
project(kddockwidgets_example_quick)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
||||||
|
|
||||||
|
if(NOT TARGET kddockwidgets)
|
||||||
|
# This will look for Qt, do find_package yourself manually before
|
||||||
|
# if you want to look for a specific Qt version for instance.
|
||||||
|
find_package(KDDockWidgets REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
qt5_add_resources(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/resources_example.qrc)
|
||||||
|
|
||||||
|
add_executable(kddockwidgets_example_quick
|
||||||
|
main.cpp
|
||||||
|
${RESOURCES_EXAMPLE_SRC}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(kddockwidgets_example_quick
|
||||||
|
PRIVATE
|
||||||
|
KDAB::kddockwidgets
|
||||||
|
)
|
||||||
20
examples/qtquick/Guest.qml
Normal file
20
examples/qtquick/Guest.qml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: "blue"
|
||||||
|
anchors.fill: parent
|
||||||
|
Text {
|
||||||
|
text: "Guest Widget!"
|
||||||
|
}
|
||||||
|
}
|
||||||
20
examples/qtquick/Guest1.qml
Normal file
20
examples/qtquick/Guest1.qml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: "lightblue"
|
||||||
|
anchors.fill: parent
|
||||||
|
Text {
|
||||||
|
text: "Guest Widget #1 !"
|
||||||
|
}
|
||||||
|
}
|
||||||
20
examples/qtquick/Guest2.qml
Normal file
20
examples/qtquick/Guest2.qml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: "pink"
|
||||||
|
anchors.fill: parent
|
||||||
|
Text {
|
||||||
|
text: "Guest Widget #2!"
|
||||||
|
}
|
||||||
|
}
|
||||||
20
examples/qtquick/Guest3.qml
Normal file
20
examples/qtquick/Guest3.qml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: "gray"
|
||||||
|
anchors.fill: parent
|
||||||
|
Text {
|
||||||
|
text: "Guest Widget #3!"
|
||||||
|
}
|
||||||
|
}
|
||||||
53
examples/qtquick/main.cpp
Normal file
53
examples/qtquick/main.cpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "private/DockRegistry_p.h"
|
||||||
|
#include "private/quick/DockWidgetQuick.h"
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include <QQuickView>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
QQuickView view;
|
||||||
|
KDDockWidgets::Config::self().setQmlEngine(view.engine());
|
||||||
|
view.resize(1000, 800);
|
||||||
|
view.show();
|
||||||
|
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||||
|
|
||||||
|
auto dw1 = new KDDockWidgets::DockWidgetQuick("Dock #1");
|
||||||
|
dw1->setWidget(QStringLiteral("qrc:/Guest1.qml"));
|
||||||
|
dw1->resize(QSize(800, 800));
|
||||||
|
dw1->show();
|
||||||
|
|
||||||
|
auto dw2 = new KDDockWidgets::DockWidgetQuick("Dock #2");
|
||||||
|
dw2->setWidget(QStringLiteral("qrc:/Guest2.qml"));
|
||||||
|
dw2->resize(QSize(800, 800));
|
||||||
|
dw2->show();
|
||||||
|
|
||||||
|
auto dw3 = new KDDockWidgets::DockWidgetQuick("Dock #3");
|
||||||
|
dw3->setWidget(QStringLiteral("qrc:/Guest3.qml"));
|
||||||
|
dw3->resize(QSize(800, 800));
|
||||||
|
dw3->show();
|
||||||
|
|
||||||
|
view.setSource(QUrl("qrc:/main.qml"));
|
||||||
|
|
||||||
|
dw1->addDockWidgetToContainingWindow(dw3, KDDockWidgets::Location_OnRight);
|
||||||
|
|
||||||
|
KDDockWidgets::MainWindowBase *mainWindow = KDDockWidgets::DockRegistry::self()->mainwindows().constFirst();
|
||||||
|
mainWindow->addDockWidget(dw2, KDDockWidgets::Location_OnTop);
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
23
examples/qtquick/main.qml
Normal file
23
examples/qtquick/main.qml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.6
|
||||||
|
import com.kdab.dockwidgets 1.0 as KDDW
|
||||||
|
|
||||||
|
KDDW.MainWindow {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.init("MyWindowName-1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
8
examples/qtquick/resources_example.qrc
Normal file
8
examples/qtquick/resources_example.qrc
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>main.qml</file>
|
||||||
|
<file>Guest1.qml</file>
|
||||||
|
<file>Guest2.qml</file>
|
||||||
|
<file>Guest3.qml</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
@@ -24,6 +24,7 @@ add_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS
|
|||||||
set(DOCKSLIBS_SRCS
|
set(DOCKSLIBS_SRCS
|
||||||
Config.cpp
|
Config.cpp
|
||||||
Qt5Qt6Compat_p.h
|
Qt5Qt6Compat_p.h
|
||||||
|
FocusScope.cpp
|
||||||
FrameworkWidgetFactory.cpp
|
FrameworkWidgetFactory.cpp
|
||||||
DockWidgetBase.cpp
|
DockWidgetBase.cpp
|
||||||
MainWindowBase.cpp
|
MainWindowBase.cpp
|
||||||
@@ -43,6 +44,8 @@ set(DOCKSLIBS_SRCS
|
|||||||
private/Frame.cpp
|
private/Frame.cpp
|
||||||
private/DropAreaWithCentralFrame.cpp
|
private/DropAreaWithCentralFrame.cpp
|
||||||
private/WidgetResizeHandler.cpp
|
private/WidgetResizeHandler.cpp
|
||||||
|
private/indicators/ClassicIndicators.cpp
|
||||||
|
private/indicators/ClassicIndicatorsWindow.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_INCLUDES
|
set(DOCKS_INSTALLABLE_INCLUDES
|
||||||
@@ -51,6 +54,7 @@ set(DOCKS_INSTALLABLE_INCLUDES
|
|||||||
FrameworkWidgetFactory.h
|
FrameworkWidgetFactory.h
|
||||||
DockWidgetBase.h
|
DockWidgetBase.h
|
||||||
KDDockWidgets.h
|
KDDockWidgets.h
|
||||||
|
FocusScope.h
|
||||||
QWidgetAdapter.h
|
QWidgetAdapter.h
|
||||||
LayoutSaver.h
|
LayoutSaver.h
|
||||||
LayoutSaver_p.h
|
LayoutSaver_p.h
|
||||||
@@ -99,7 +103,7 @@ else()
|
|||||||
private/widgets/TitleBarWidget.cpp
|
private/widgets/TitleBarWidget.cpp
|
||||||
private/widgets/DockWidget.cpp
|
private/widgets/DockWidget.cpp
|
||||||
private/widgets/QWidgetAdapter_widgets.cpp
|
private/widgets/QWidgetAdapter_widgets.cpp
|
||||||
private/indicators/ClassicIndicators.cpp
|
private/indicators/SegmentedIndicators.cpp
|
||||||
# private/indicators/AnimatedIndicators.cpp
|
# private/indicators/AnimatedIndicators.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -199,6 +203,9 @@ install(FILES private/multisplitter/Separator_qwidget.h DESTINATION include/kddo
|
|||||||
install(FILES private/multisplitter/multisplitter_export.h DESTINATION include/kddockwidgets/private/multisplitter)
|
install(FILES private/multisplitter/multisplitter_export.h DESTINATION include/kddockwidgets/private/multisplitter)
|
||||||
install(FILES ${DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES} DESTINATION include/kddockwidgets/private/widgets)
|
install(FILES ${DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES} DESTINATION include/kddockwidgets/private/widgets)
|
||||||
|
|
||||||
|
install(FILES private/indicators/ClassicIndicators_p.h DESTINATION include/kddockwidgets/private/indicators)
|
||||||
|
install(FILES private/indicators/SegmentedIndicators_p.h DESTINATION include/kddockwidgets/private/indicators)
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file(
|
||||||
KDDockWidgetsConfigVersion.cmake
|
KDDockWidgetsConfigVersion.cmake
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public:
|
|||||||
MainWindowFactoryFunc m_mainWindowFactoryFunc = nullptr;
|
MainWindowFactoryFunc m_mainWindowFactoryFunc = nullptr;
|
||||||
FrameworkWidgetFactory *m_frameworkWidgetFactory;
|
FrameworkWidgetFactory *m_frameworkWidgetFactory;
|
||||||
Flags m_flags = Flag_Default;
|
Flags m_flags = Flag_Default;
|
||||||
|
qreal m_draggedWindowOpacity = Q_QNAN;
|
||||||
};
|
};
|
||||||
|
|
||||||
Config::Config()
|
Config::Config()
|
||||||
@@ -142,6 +143,16 @@ void Config::setSeparatorThickness(int value)
|
|||||||
Layouting::Config::self().setSeparatorThickness(value);
|
Layouting::Config::self().setSeparatorThickness(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Config::setDraggedWindowOpacity(qreal opacity)
|
||||||
|
{
|
||||||
|
d->m_draggedWindowOpacity = opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal Config::draggedWindowOpacity() const
|
||||||
|
{
|
||||||
|
return d->m_draggedWindowOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
void Config::setQmlEngine(QQmlEngine *qmlEngine)
|
void Config::setQmlEngine(QQmlEngine *qmlEngine)
|
||||||
{
|
{
|
||||||
if (d->m_qmlEngine) {
|
if (d->m_qmlEngine) {
|
||||||
|
|||||||
10
src/Config.h
10
src/Config.h
@@ -56,12 +56,14 @@ public:
|
|||||||
Flag_None = 0, ///> No option set
|
Flag_None = 0, ///> No option set
|
||||||
Flag_NativeTitleBar = 1, ///> Enables the Native OS title bar on OSes that support it (Windows 10, macOS), ignored otherwise. This is mutually exclusive with Flag_AeroSnap
|
Flag_NativeTitleBar = 1, ///> Enables the Native OS title bar on OSes that support it (Windows 10, macOS), ignored otherwise. This is mutually exclusive with Flag_AeroSnap
|
||||||
Flag_AeroSnapWithClientDecos = 2, ///> Enables AeroSnap even if we're not using the native title bar. Only supported on Windows 10.
|
Flag_AeroSnapWithClientDecos = 2, ///> Enables AeroSnap even if we're not using the native title bar. Only supported on Windows 10.
|
||||||
|
Flag_AlwaysTitleBarWhenFloating = 4, ///> Floating windows will have a title bar even if Flag_HideTitleBarWhenTabsVisible is specified. Unneeded if Flag_HideTitleBarWhenTabsVisible isn't specified, as that's the default already.
|
||||||
Flag_HideTitleBarWhenTabsVisible = 8, ///> Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
|
Flag_HideTitleBarWhenTabsVisible = 8, ///> Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
|
||||||
Flag_AlwaysShowTabs = 16, ///> Always show tabs, even if there's only one,
|
Flag_AlwaysShowTabs = 16, ///> Always show tabs, even if there's only one,
|
||||||
Flag_AllowReorderTabs = 32, /// Allows user to re-order tabs by dragging them
|
Flag_AllowReorderTabs = 32, /// Allows user to re-order tabs by dragging them
|
||||||
Flag_TabsHaveCloseButton = 64, /// Tabs will have a close button. Equivalent to QTabWidget::setTabsClosable(true).
|
Flag_TabsHaveCloseButton = 64, /// Tabs will have a close button. Equivalent to QTabWidget::setTabsClosable(true).
|
||||||
Flag_DoubleClickMaximizes = 128, /// Double clicking the titlebar will maximize a floating window instead of re-docking it
|
Flag_DoubleClickMaximizes = 128, /// Double clicking the titlebar will maximize a floating window instead of re-docking it
|
||||||
Flag_TitleBarHasMaximizeButton = 256, /// The title bar will have a maximize/restore button when floating. This is mutually-exclusive with the floating button (since many apps behave that way).
|
Flag_TitleBarHasMaximizeButton = 256, /// The title bar will have a maximize/restore button when floating. This is mutually-exclusive with the floating button (since many apps behave that way).
|
||||||
|
Flag_TitleBarIsFocusable = 512, /// You can click the title bar and it will focus the last focused widget in the focus scope. If no previously focused widget then it focuses the user's dock widget guest, which should accept focus or use a focus proxy.
|
||||||
Flag_LazyResize = 1024, /// The dock widgets are resized in a lazy manner. The actual resize only happens when you release the mouse button.
|
Flag_LazyResize = 1024, /// The dock widgets are resized in a lazy manner. The actual resize only happens when you release the mouse button.
|
||||||
Flag_Default = Flag_AeroSnapWithClientDecos ///> The defaults
|
Flag_Default = Flag_AeroSnapWithClientDecos ///> The defaults
|
||||||
};
|
};
|
||||||
@@ -130,6 +132,14 @@ public:
|
|||||||
///Note: Only use this function at startup before creating any DockWidget or MainWindow.
|
///Note: Only use this function at startup before creating any DockWidget or MainWindow.
|
||||||
void setSeparatorThickness(int value);
|
void setSeparatorThickness(int value);
|
||||||
|
|
||||||
|
///@brief sets the dragged window opacity
|
||||||
|
///1.0 is fully opaque while 0.0 is fully transparent
|
||||||
|
void setDraggedWindowOpacity(qreal opacity);
|
||||||
|
|
||||||
|
///@brief returns the opacity to use when dragging dock widgets
|
||||||
|
///By default it's 1.0, fully opaque
|
||||||
|
qreal draggedWindowOpacity() const;
|
||||||
|
|
||||||
///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick.
|
///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick.
|
||||||
void setQmlEngine(QQmlEngine *);
|
void setQmlEngine(QQmlEngine *);
|
||||||
QQmlEngine* qmlEngine() const;
|
QQmlEngine* qmlEngine() const;
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ public:
|
|||||||
QPoint defaultCenterPosForFloating();
|
QPoint defaultCenterPosForFloating();
|
||||||
|
|
||||||
void updateTitle();
|
void updateTitle();
|
||||||
void updateIcon();
|
|
||||||
void toggle(bool enabled);
|
void toggle(bool enabled);
|
||||||
void updateToggleAction();
|
void updateToggleAction();
|
||||||
void updateFloatAction();
|
void updateFloatAction();
|
||||||
@@ -101,7 +100,8 @@ public:
|
|||||||
const QString name;
|
const QString name;
|
||||||
QStringList affinities;
|
QStringList affinities;
|
||||||
QString title;
|
QString title;
|
||||||
QIcon icon;
|
QIcon titleBarIcon;
|
||||||
|
QIcon tabBarIcon;
|
||||||
QWidgetOrQuick *widget = nullptr;
|
QWidgetOrQuick *widget = nullptr;
|
||||||
DockWidgetBase *const q;
|
DockWidgetBase *const q;
|
||||||
DockWidgetBase::Options options;
|
DockWidgetBase::Options options;
|
||||||
@@ -355,16 +355,26 @@ void DockWidgetBase::setAsCurrentTab()
|
|||||||
frame->setCurrentDockWidget(this);
|
frame->setCurrentDockWidget(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::setIcon(const QIcon &icon)
|
void DockWidgetBase::setIcon(const QIcon &icon, IconPlaces places)
|
||||||
{
|
{
|
||||||
d->icon = icon;
|
if (places & IconPlace::TitleBar)
|
||||||
d->updateIcon();
|
d->titleBarIcon = icon;
|
||||||
|
|
||||||
|
if (places & IconPlace::TabBar)
|
||||||
|
d->tabBarIcon = icon;
|
||||||
|
|
||||||
Q_EMIT iconChanged();
|
Q_EMIT iconChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon DockWidgetBase::icon() const
|
QIcon DockWidgetBase::icon(IconPlace place) const
|
||||||
{
|
{
|
||||||
return d->icon;
|
if (place == IconPlace::TitleBar)
|
||||||
|
return d->titleBarIcon;
|
||||||
|
|
||||||
|
if (place == IconPlace::TabBar)
|
||||||
|
return d->tabBarIcon;
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::forceClose()
|
void DockWidgetBase::forceClose()
|
||||||
@@ -420,6 +430,12 @@ bool DockWidgetBase::isMainWindow() const
|
|||||||
return qobject_cast<MainWindowBase*>(widget());
|
return qobject_cast<MainWindowBase*>(widget());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockWidgetBase::isFocused() const
|
||||||
|
{
|
||||||
|
auto f = this->frame();
|
||||||
|
return f && f->isFocused() && isCurrentTab();
|
||||||
|
}
|
||||||
|
|
||||||
void DockWidgetBase::setAffinityName(const QString &affinity)
|
void DockWidgetBase::setAffinityName(const QString &affinity)
|
||||||
{
|
{
|
||||||
setAffinities({ affinity });
|
setAffinities({ affinity });
|
||||||
@@ -514,6 +530,11 @@ void DockWidgetBase::saveLastFloatingGeometry()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockWidgetBase::updateFloatAction()
|
||||||
|
{
|
||||||
|
d->updateFloatAction();
|
||||||
|
}
|
||||||
|
|
||||||
QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
|
QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
|
||||||
{
|
{
|
||||||
MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
|
MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
|
||||||
@@ -534,10 +555,6 @@ void DockWidgetBase::Private::updateTitle()
|
|||||||
toggleAction->setText(title);
|
toggleAction->setText(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::updateIcon()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockWidgetBase::Private::toggle(bool enabled)
|
void DockWidgetBase::Private::toggle(bool enabled)
|
||||||
{
|
{
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ public:
|
|||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Options, Option)
|
Q_DECLARE_FLAGS(Options, Option)
|
||||||
|
|
||||||
|
enum class IconPlace {
|
||||||
|
TitleBar = 1,
|
||||||
|
TabBar = 2,
|
||||||
|
All = TitleBar | TabBar
|
||||||
|
};
|
||||||
|
Q_ENUM(IconPlace)
|
||||||
|
Q_DECLARE_FLAGS(IconPlaces, IconPlace)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief constructs a new DockWidget
|
* @brief constructs a new DockWidget
|
||||||
* @param uniqueName the name of the dockwidget, should be unique. Use title for user visible text.
|
* @param uniqueName the name of the dockwidget, should be unique. Use title for user visible text.
|
||||||
@@ -223,14 +231,22 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets an icon to show on title bars and tab bars.
|
* @brief Sets an icon to show on title bars and tab bars.
|
||||||
* By default none is shown.
|
* @param places Specifies where the icon will be shown (TitleBar, TabBar or both)
|
||||||
|
*
|
||||||
|
* By default there's no icon set.
|
||||||
|
*
|
||||||
|
* @sa icon()
|
||||||
*/
|
*/
|
||||||
void setIcon(const QIcon &icon);
|
void setIcon(const QIcon &icon, IconPlaces places = IconPlace::All);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the dock widget's icon.
|
* @brief Returns the dock widget's titlebar or tabbar icon (depending on the passed @p place)
|
||||||
|
*
|
||||||
|
* By default it's null.
|
||||||
|
*
|
||||||
|
* @sa setIcon()
|
||||||
*/
|
*/
|
||||||
QIcon icon() const;
|
QIcon icon(IconPlace place = IconPlace::TitleBar) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Like QWidget::close() but the hosted widget won't be asked if we
|
* @brief Like QWidget::close() but the hosted widget won't be asked if we
|
||||||
@@ -304,6 +320,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isMainWindow() const;
|
bool isMainWindow() const;
|
||||||
|
|
||||||
|
///@brief Returns whether This or any child of this dock widget is focused
|
||||||
|
///Not to be confused with QWidget::hasFocus(), which just refers to 1 widget. This includes
|
||||||
|
///variant includes children.
|
||||||
|
///@sa isFocusedChanged()
|
||||||
|
bool isFocused() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
///@brief signal emitted when the parent changed
|
///@brief signal emitted when the parent changed
|
||||||
void parentChanged();
|
void parentChanged();
|
||||||
@@ -327,6 +349,10 @@ Q_SIGNALS:
|
|||||||
///@sa setOptions(), options()
|
///@sa setOptions(), options()
|
||||||
void optionsChanged(KDDockWidgets::DockWidgetBase::Options);
|
void optionsChanged(KDDockWidgets::DockWidgetBase::Options);
|
||||||
|
|
||||||
|
///@brief emitted when isFocused changes
|
||||||
|
///@sa isFocused
|
||||||
|
void isFocusedChanged(bool);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onParentChanged();
|
void onParentChanged();
|
||||||
void onShown(bool spontaneous);
|
void onShown(bool spontaneous);
|
||||||
@@ -392,6 +418,9 @@ private:
|
|||||||
///@brief If this dock widget is floating, then it saves its geometry
|
///@brief If this dock widget is floating, then it saves its geometry
|
||||||
void saveLastFloatingGeometry();
|
void saveLastFloatingGeometry();
|
||||||
|
|
||||||
|
///@brief Updates the floatAction state
|
||||||
|
void updateFloatAction();
|
||||||
|
|
||||||
class Private;
|
class Private;
|
||||||
Private *const d;
|
Private *const d;
|
||||||
};
|
};
|
||||||
|
|||||||
130
src/FocusScope.cpp
Normal file
130
src/FocusScope.cpp
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief FocusScope
|
||||||
|
*
|
||||||
|
* @author Sérgio Martins \<sergio.martins@kdab.com\>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FocusScope.h"
|
||||||
|
#include "TitleBar_p.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
// Our Private inherits from QObject since FocusScope can't (Since Frame is already QObject)
|
||||||
|
class FocusScope::Private : public QObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Private(FocusScope *qq, QWidgetAdapter *thisWidget)
|
||||||
|
: q(qq)
|
||||||
|
, m_thisWidget(thisWidget)
|
||||||
|
{
|
||||||
|
connect(qApp, &QGuiApplication::focusObjectChanged,
|
||||||
|
this, &Private::onFocusObjectChanged);
|
||||||
|
|
||||||
|
onFocusObjectChanged(qApp->focusObject());
|
||||||
|
m_inCtor = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setIsFocused(bool);
|
||||||
|
void onFocusObjectChanged(QObject *);
|
||||||
|
bool isInFocusScope(WidgetType *) const;
|
||||||
|
|
||||||
|
FocusScope *const q;
|
||||||
|
QWidgetAdapter *const m_thisWidget;
|
||||||
|
bool m_isFocused = false;
|
||||||
|
bool m_inCtor = true;
|
||||||
|
QPointer<WidgetType> m_lastFocusedInScope;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
FocusScope::FocusScope(QWidgetAdapter *thisWidget)
|
||||||
|
: d(new Private(this, thisWidget))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FocusScope::~FocusScope()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FocusScope::isFocused() const
|
||||||
|
{
|
||||||
|
return d->m_isFocused;
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetType *FocusScope::focusedWidget() const
|
||||||
|
{
|
||||||
|
return d->m_lastFocusedInScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FocusScope::focus(Qt::FocusReason reason)
|
||||||
|
{
|
||||||
|
if (d->m_lastFocusedInScope) {
|
||||||
|
d->m_lastFocusedInScope->setFocus(reason);
|
||||||
|
} else {
|
||||||
|
if (auto frame = qobject_cast<Frame*>(d->m_thisWidget)) {
|
||||||
|
if (DockWidgetBase *dw = frame->currentDockWidget()) {
|
||||||
|
if (auto guest = dw->widget()) {
|
||||||
|
if (guest->focusPolicy() != Qt::NoFocus)
|
||||||
|
guest->setFocus(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Not a use case right now
|
||||||
|
d->m_thisWidget->setFocus(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FocusScope::Private::setIsFocused(bool is)
|
||||||
|
{
|
||||||
|
if (is != m_isFocused) {
|
||||||
|
m_isFocused = is;
|
||||||
|
|
||||||
|
if (!m_inCtor) // Hack so we don't call pure-virtual
|
||||||
|
Q_EMIT q->isFocusedChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FocusScope::Private::onFocusObjectChanged(QObject *obj)
|
||||||
|
{
|
||||||
|
auto widget = qobject_cast<WidgetType*>(obj);
|
||||||
|
if (!widget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const bool is = isInFocusScope(widget);
|
||||||
|
if (is && m_lastFocusedInScope != widget && !qobject_cast<TitleBar*>(obj)) {
|
||||||
|
m_lastFocusedInScope = widget;
|
||||||
|
Q_EMIT q->focusedWidgetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsFocused(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FocusScope::Private::isInFocusScope(WidgetType *widget) const
|
||||||
|
{
|
||||||
|
WidgetType *p = widget;
|
||||||
|
while (p) {
|
||||||
|
if (p == m_thisWidget)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
p = KDDockWidgets::Private::parentWidget(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
61
src/FocusScope.h
Normal file
61
src/FocusScope.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief FocusScope
|
||||||
|
*
|
||||||
|
* @author Sérgio Martins \<sergio.martins@kdab.com\>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KD_DOCKWIDGETS_FOCUSSCOPE_H
|
||||||
|
#define KD_DOCKWIDGETS_FOCUSSCOPE_H
|
||||||
|
|
||||||
|
#include "docks_export.h"
|
||||||
|
#include "QWidgetAdapter.h"
|
||||||
|
|
||||||
|
namespace KDDockWidgets
|
||||||
|
{
|
||||||
|
///@brief Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets
|
||||||
|
class FocusScope
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///@brief constructor
|
||||||
|
explicit FocusScope(QWidgetAdapter *thisWidget);
|
||||||
|
~FocusScope();
|
||||||
|
|
||||||
|
///@brief Returns true if this FocusScope is focused.
|
||||||
|
///This is similar to the QWidget::hasFocus(), except that it counts with the children being focused too.
|
||||||
|
///i.e: If any child is focused then this FocusScope has focus too.
|
||||||
|
bool isFocused() const;
|
||||||
|
|
||||||
|
///@brief Returns the widget that's focused in this scope
|
||||||
|
///The widget itself might not have focus as in QWidget::hasFocus(), but will get actual focus
|
||||||
|
///as soon as this scope is focused.
|
||||||
|
WidgetType* focusedWidget() const;
|
||||||
|
|
||||||
|
///@brief Sets focus on this scope.
|
||||||
|
///
|
||||||
|
/// This will call QWidget::focus() on the last QWidget that was focused in this scope.
|
||||||
|
void focus(Qt::FocusReason = Qt::OtherFocusReason);
|
||||||
|
|
||||||
|
/*Q_SIGNALS:*/
|
||||||
|
///@brief reimplement in the 1st QObject derived class
|
||||||
|
virtual void isFocusedChanged() = 0;
|
||||||
|
virtual void focusedWidgetChanged() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Private;
|
||||||
|
Private *const d;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "multisplitter/Separator_p.h"
|
#include "multisplitter/Separator_p.h"
|
||||||
#include "FloatingWindow_p.h"
|
#include "FloatingWindow_p.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "indicators/ClassicIndicators_p.h"
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
# include "indicators/ClassicIndicators_p.h"
|
# include "indicators/ClassicIndicators_p.h"
|
||||||
@@ -25,6 +26,8 @@
|
|||||||
# include "widgets/TabWidgetWidget_p.h"
|
# include "widgets/TabWidgetWidget_p.h"
|
||||||
# include "multisplitter/Separator_qwidget.h"
|
# include "multisplitter/Separator_qwidget.h"
|
||||||
# include "widgets/FloatingWindowWidget_p.h"
|
# include "widgets/FloatingWindowWidget_p.h"
|
||||||
|
# include "indicators/SegmentedIndicators_p.h"
|
||||||
|
# include <QRubberBand>
|
||||||
#else
|
#else
|
||||||
# include "quick/FrameQuick_p.h"
|
# include "quick/FrameQuick_p.h"
|
||||||
# include "quick/DockWidgetQuick.h"
|
# include "quick/DockWidgetQuick.h"
|
||||||
@@ -35,6 +38,8 @@
|
|||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
DropIndicatorType DefaultWidgetFactory::s_dropIndicatorType = DropIndicatorType::Classic;
|
||||||
|
|
||||||
FrameworkWidgetFactory::~FrameworkWidgetFactory()
|
FrameworkWidgetFactory::~FrameworkWidgetFactory()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -82,8 +87,21 @@ FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWin
|
|||||||
|
|
||||||
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
|
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
|
||||||
{
|
{
|
||||||
|
switch (s_dropIndicatorType) {
|
||||||
|
case DropIndicatorType::Classic:
|
||||||
|
return new ClassicIndicators(dropArea);
|
||||||
|
case DropIndicatorType::Segmented:
|
||||||
|
return new SegmentedIndicators(dropArea);
|
||||||
|
}
|
||||||
|
|
||||||
return new ClassicIndicators(dropArea);
|
return new ClassicIndicators(dropArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidgetOrQuick *DefaultWidgetFactory::createRubberBand(QWidgetOrQuick *parent) const
|
||||||
|
{
|
||||||
|
return new QRubberBand(QRubberBand::Rectangle, parent);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
Frame *DefaultWidgetFactory::createFrame(QWidgetOrQuick *parent, FrameOptions options) const
|
Frame *DefaultWidgetFactory::createFrame(QWidgetOrQuick *parent, FrameOptions options) const
|
||||||
@@ -116,9 +134,9 @@ FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWin
|
|||||||
return new FloatingWindowQuick(frame, parent);
|
return new FloatingWindowQuick(frame, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *) const
|
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
|
||||||
{
|
{
|
||||||
return nullptr;
|
return new ClassicIndicators(dropArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
TabBar *DefaultWidgetFactory::createTabBar(TabWidget *parent) const
|
TabBar *DefaultWidgetFactory::createTabBar(TabWidget *parent) const
|
||||||
@@ -140,4 +158,9 @@ Layouting::Separator *DefaultWidgetFactory::createSeparator(Layouting::Widget *p
|
|||||||
return new Layouting::SeparatorQuick(parent);
|
return new Layouting::SeparatorQuick(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidgetOrQuick *DefaultWidgetFactory::createRubberBand(QWidgetOrQuick *parent) const
|
||||||
|
{
|
||||||
|
return new QWidgetOrQuick(parent);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -117,6 +117,10 @@ public:
|
|||||||
/// Override to provide your own DropIndicatorOverlayInterface sub-class.
|
/// Override to provide your own DropIndicatorOverlayInterface sub-class.
|
||||||
///@param dropArea Just forward to DropIndicatorOverlayInterface's constructor.
|
///@param dropArea Just forward to DropIndicatorOverlayInterface's constructor.
|
||||||
virtual DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea *dropArea) const = 0;
|
virtual DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea *dropArea) const = 0;
|
||||||
|
|
||||||
|
///@brief Called internally by the framework to create a RubberBand to show as drop zone
|
||||||
|
///Returns a rubber band
|
||||||
|
virtual QWidgetOrQuick *createRubberBand(QWidgetOrQuick *parent) const = 0;
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(FrameworkWidgetFactory)
|
Q_DISABLE_COPY(FrameworkWidgetFactory)
|
||||||
};
|
};
|
||||||
@@ -137,6 +141,9 @@ public:
|
|||||||
FloatingWindow *createFloatingWindow(MainWindowBase *parent = nullptr) const override;
|
FloatingWindow *createFloatingWindow(MainWindowBase *parent = nullptr) const override;
|
||||||
FloatingWindow *createFloatingWindow(Frame *frame, MainWindowBase *parent = nullptr) const override;
|
FloatingWindow *createFloatingWindow(Frame *frame, MainWindowBase *parent = nullptr) const override;
|
||||||
DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea*) const override;
|
DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea*) const override;
|
||||||
|
QWidgetOrQuick *createRubberBand(QWidgetOrQuick *parent) const override;
|
||||||
|
|
||||||
|
static DropIndicatorType s_dropIndicatorType;
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(DefaultWidgetFactory)
|
Q_DISABLE_COPY(DefaultWidgetFactory)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ namespace KDDockWidgets
|
|||||||
SizePolicy, ///< Uses the item's sizeHint() and sizePolicy()
|
SizePolicy, ///< Uses the item's sizeHint() and sizePolicy()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class DropIndicatorType {
|
||||||
|
Classic, ///< The default
|
||||||
|
Segmented
|
||||||
|
};
|
||||||
|
|
||||||
///@internal
|
///@internal
|
||||||
inline QString locationStr(Location loc)
|
inline QString locationStr(Location loc)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
#include "../../../../private/indicators/ClassicIndicators_p.h"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#include "../../../../private/indicators/SegmentedIndicators_p.h"
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "Position_p.h"
|
#include "Position_p.h"
|
||||||
#include "MultiSplitter_p.h"
|
#include "MultiSplitter_p.h"
|
||||||
|
#include "QWidgetAdapter.h"
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -52,6 +53,9 @@ DockRegistry::DockRegistry(QObject *parent)
|
|||||||
KDDockWidgets::registerQmlTypes();
|
KDDockWidgets::registerQmlTypes();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
connect(qApp, &QGuiApplication::focusObjectChanged,
|
||||||
|
this, &DockRegistry::onFocusObjectChanged);
|
||||||
|
|
||||||
initKDDockWidgetResources();
|
initKDDockWidgetResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +69,35 @@ void DockRegistry::maybeDelete()
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockRegistry::onFocusObjectChanged(QObject *obj)
|
||||||
|
{
|
||||||
|
DockWidgetBase *const unfocusedDW = m_focusedDockWidget.data();
|
||||||
|
DockWidgetBase *newFocusedDockWidget = nullptr;
|
||||||
|
|
||||||
|
// Check if it's inside a dock widget:
|
||||||
|
auto p = qobject_cast<WidgetType*>(obj);
|
||||||
|
while (p) {
|
||||||
|
if (auto dw = qobject_cast<DockWidgetBase*>(p)) {
|
||||||
|
newFocusedDockWidget = dw;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = KDDockWidgets::Private::parentWidget(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing changed
|
||||||
|
if (m_focusedDockWidget.data() == newFocusedDockWidget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_focusedDockWidget = newFocusedDockWidget;
|
||||||
|
|
||||||
|
if (unfocusedDW)
|
||||||
|
Q_EMIT unfocusedDW->isFocusedChanged(false);
|
||||||
|
|
||||||
|
if (m_focusedDockWidget)
|
||||||
|
Q_EMIT m_focusedDockWidget->isFocusedChanged(true);
|
||||||
|
}
|
||||||
|
|
||||||
bool DockRegistry::isEmpty() const
|
bool DockRegistry::isEmpty() const
|
||||||
{
|
{
|
||||||
return m_dockWidgets.isEmpty() && m_mainWindows.isEmpty() && m_nestedWindows.isEmpty();
|
return m_dockWidgets.isEmpty() && m_mainWindows.isEmpty() && m_nestedWindows.isEmpty();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DockRegistry is a singleton that knows about all DockWidgets.
|
* DockRegistry is a singleton that knows about all DockWidgets.
|
||||||
@@ -48,6 +49,8 @@ public:
|
|||||||
void registerFrame(Frame *);
|
void registerFrame(Frame *);
|
||||||
void unregisterFrame(Frame *);
|
void unregisterFrame(Frame *);
|
||||||
|
|
||||||
|
DockWidgetBase *focusedDockWidget() const;
|
||||||
|
|
||||||
DockWidgetBase *dockByName(const QString &) const;
|
DockWidgetBase *dockByName(const QString &) const;
|
||||||
MainWindowBase *mainWindowByName(const QString &) const;
|
MainWindowBase *mainWindowByName(const QString &) const;
|
||||||
|
|
||||||
@@ -167,12 +170,14 @@ protected:
|
|||||||
private:
|
private:
|
||||||
explicit DockRegistry(QObject *parent = nullptr);
|
explicit DockRegistry(QObject *parent = nullptr);
|
||||||
void maybeDelete();
|
void maybeDelete();
|
||||||
|
void onFocusObjectChanged(QObject *);
|
||||||
bool m_isProcessingAppQuitEvent = false;
|
bool m_isProcessingAppQuitEvent = false;
|
||||||
DockWidgetBase::List m_dockWidgets;
|
DockWidgetBase::List m_dockWidgets;
|
||||||
MainWindowBase::List m_mainWindows;
|
MainWindowBase::List m_mainWindows;
|
||||||
Frame::List m_frames;
|
Frame::List m_frames;
|
||||||
QVector<FloatingWindow*> m_nestedWindows;
|
QVector<FloatingWindow*> m_nestedWindows;
|
||||||
QVector<MultiSplitter*> m_layouts;
|
QVector<MultiSplitter*> m_layouts;
|
||||||
|
QPointer<DockWidgetBase> m_focusedDockWidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -427,14 +427,16 @@ template <typename T>
|
|||||||
static WidgetType* qtTopLevelUnderCursor_impl(QPoint globalPos, const QVector<QWindow*> &windows, T windowBeingDragged)
|
static WidgetType* qtTopLevelUnderCursor_impl(QPoint globalPos, const QVector<QWindow*> &windows, T windowBeingDragged)
|
||||||
{
|
{
|
||||||
for (int i = windows.size() -1; i >= 0; --i) {
|
for (int i = windows.size() -1; i >= 0; --i) {
|
||||||
auto tl = KDDockWidgets::Private::widgetForWindow(windows.at(i));
|
QWindow *window = windows.at(i);
|
||||||
|
auto tl = KDDockWidgets::Private::widgetForWindow(window);
|
||||||
|
|
||||||
if (!tl->isVisible() || tl == windowBeingDragged || KDDockWidgets::Private::isMinimized(tl))
|
if (!tl->isVisible() || tl == windowBeingDragged || KDDockWidgets::Private::isMinimized(tl))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (windowBeingDragged && KDDockWidgets::Private::windowForWidget(windowBeingDragged) == KDDockWidgets::Private::windowForWidget(tl))
|
if (windowBeingDragged && KDDockWidgets::Private::windowForWidget(windowBeingDragged) == KDDockWidgets::Private::windowForWidget(tl))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (KDDockWidgets::Private::geometry(tl).contains(globalPos)) {
|
if (window->geometry().contains(globalPos)) {
|
||||||
qCDebug(toplevels) << Q_FUNC_INFO << "Found top-level" << tl;
|
qCDebug(toplevels) << Q_FUNC_INFO << "Found top-level" << tl;
|
||||||
return tl;
|
return tl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ DropIndicatorOverlayInterface::DropIndicatorOverlayInterface(DropArea *dropArea)
|
|||||||
|
|
||||||
void DropIndicatorOverlayInterface::setWindowBeingDragged(const FloatingWindow *window)
|
void DropIndicatorOverlayInterface::setWindowBeingDragged(const FloatingWindow *window)
|
||||||
{
|
{
|
||||||
if (window != m_windowBeingDragged) {
|
if (window == m_windowBeingDragged)
|
||||||
|
return;
|
||||||
|
|
||||||
m_windowBeingDragged = window;
|
m_windowBeingDragged = window;
|
||||||
if (m_windowBeingDragged) {
|
if (m_windowBeingDragged) {
|
||||||
setGeometry(m_dropArea->QWidgetAdapter::rect());
|
setGeometry(m_dropArea->QWidgetAdapter::rect());
|
||||||
@@ -36,24 +38,34 @@ void DropIndicatorOverlayInterface::setWindowBeingDragged(const FloatingWindow *
|
|||||||
setHoveredFrame(nullptr);
|
setHoveredFrame(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setVisible(m_windowBeingDragged != nullptr);
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect DropIndicatorOverlayInterface::hoveredFrameRect() const
|
||||||
|
{
|
||||||
|
return m_hoveredFrameRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropIndicatorOverlayInterface::setHoveredFrame(Frame *frame)
|
void DropIndicatorOverlayInterface::setHoveredFrame(Frame *frame)
|
||||||
{
|
{
|
||||||
if (frame != m_hoveredFrame) {
|
if (frame == m_hoveredFrame)
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_hoveredFrame)
|
if (m_hoveredFrame)
|
||||||
disconnect(m_hoveredFrame, &QObject::destroyed, this, &DropIndicatorOverlayInterface::onFrameDestroyed);
|
disconnect(m_hoveredFrame, &QObject::destroyed, this, &DropIndicatorOverlayInterface::onFrameDestroyed);
|
||||||
|
|
||||||
m_hoveredFrame = frame;
|
m_hoveredFrame = frame;
|
||||||
if (m_hoveredFrame)
|
if (m_hoveredFrame) {
|
||||||
connect(frame, &QObject::destroyed, this, &DropIndicatorOverlayInterface::onFrameDestroyed);
|
connect(frame, &QObject::destroyed, this, &DropIndicatorOverlayInterface::onFrameDestroyed);
|
||||||
|
setHoveredFrameRect(m_hoveredFrame->QWidgetAdapter::geometry());
|
||||||
|
} else {
|
||||||
|
setHoveredFrameRect(QRect());
|
||||||
|
}
|
||||||
|
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
Q_EMIT hoveredFrameChanged(m_hoveredFrame);
|
Q_EMIT hoveredFrameChanged(m_hoveredFrame);
|
||||||
onHoveredFrameChanged(m_hoveredFrame);
|
onHoveredFrameChanged(m_hoveredFrame);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DropIndicatorOverlayInterface::isHovered() const
|
bool DropIndicatorOverlayInterface::isHovered() const
|
||||||
@@ -61,6 +73,11 @@ bool DropIndicatorOverlayInterface::isHovered() const
|
|||||||
return m_windowBeingDragged != nullptr;
|
return m_windowBeingDragged != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DropIndicatorOverlayInterface::DropLocation DropIndicatorOverlayInterface::currentDropLocation() const
|
||||||
|
{
|
||||||
|
return m_currentDropLocation;
|
||||||
|
}
|
||||||
|
|
||||||
KDDockWidgets::Location DropIndicatorOverlayInterface::multisplitterLocationFor(DropIndicatorOverlayInterface::DropLocation dropLoc)
|
KDDockWidgets::Location DropIndicatorOverlayInterface::multisplitterLocationFor(DropIndicatorOverlayInterface::DropLocation dropLoc)
|
||||||
{
|
{
|
||||||
switch (dropLoc) {
|
switch (dropLoc) {
|
||||||
@@ -92,10 +109,25 @@ void DropIndicatorOverlayInterface::onFrameDestroyed()
|
|||||||
|
|
||||||
void DropIndicatorOverlayInterface::onHoveredFrameChanged(Frame *)
|
void DropIndicatorOverlayInterface::onHoveredFrameChanged(Frame *)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropIndicatorOverlayInterface::setCurrentDropLocation(DropIndicatorOverlayInterface::DropLocation location)
|
void DropIndicatorOverlayInterface::setCurrentDropLocation(DropIndicatorOverlayInterface::DropLocation location)
|
||||||
{
|
{
|
||||||
|
if (m_currentDropLocation != location) {
|
||||||
m_currentDropLocation = location;
|
m_currentDropLocation = location;
|
||||||
|
Q_EMIT currentDropLocationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DropIndicatorOverlayInterface::hover(QPoint globalPos)
|
||||||
|
{
|
||||||
|
hover_impl(globalPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DropIndicatorOverlayInterface::setHoveredFrameRect(QRect rect)
|
||||||
|
{
|
||||||
|
if (m_hoveredFrameRect != rect) {
|
||||||
|
m_hoveredFrameRect = rect;
|
||||||
|
Q_EMIT hoveredFrameRectChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,17 +22,12 @@ namespace KDDockWidgets {
|
|||||||
class FloatingWindow;
|
class FloatingWindow;
|
||||||
class DropArea;
|
class DropArea;
|
||||||
|
|
||||||
class DOCKS_EXPORT_FOR_UNIT_TESTS DropIndicatorOverlayInterface : public QWidgetAdapter
|
class DOCKS_EXPORT DropIndicatorOverlayInterface : public QWidgetAdapter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QRect hoveredFrameRect READ hoveredFrameRect NOTIFY hoveredFrameRectChanged)
|
||||||
|
Q_PROPERTY(KDDockWidgets::DropIndicatorOverlayInterface::DropLocation currentDropLocation READ currentDropLocation NOTIFY currentDropLocationChanged)
|
||||||
public:
|
public:
|
||||||
enum Type {
|
|
||||||
TypeNone = 0,
|
|
||||||
TypeClassic = 1,
|
|
||||||
TypeAnimated = 2
|
|
||||||
};
|
|
||||||
Q_ENUM(Type)
|
|
||||||
|
|
||||||
enum DropLocation {
|
enum DropLocation {
|
||||||
DropLocation_None = 0,
|
DropLocation_None = 0,
|
||||||
DropLocation_Left,
|
DropLocation_Left,
|
||||||
@@ -43,36 +38,45 @@ public:
|
|||||||
DropLocation_OutterLeft,
|
DropLocation_OutterLeft,
|
||||||
DropLocation_OutterTop,
|
DropLocation_OutterTop,
|
||||||
DropLocation_OutterRight,
|
DropLocation_OutterRight,
|
||||||
DropLocation_OutterBottom
|
DropLocation_OutterBottom,
|
||||||
|
|
||||||
|
DropLocation_First = DropLocation_Left,
|
||||||
|
DropLocation_Last = DropLocation_OutterBottom,
|
||||||
};
|
};
|
||||||
Q_ENUM(DropLocation)
|
Q_ENUM(DropLocation)
|
||||||
|
|
||||||
explicit DropIndicatorOverlayInterface(DropArea *dropArea);
|
explicit DropIndicatorOverlayInterface(DropArea *dropArea);
|
||||||
void setHoveredFrame(Frame *);
|
void setHoveredFrame(Frame *);
|
||||||
void setWindowBeingDragged(const FloatingWindow *);
|
void setWindowBeingDragged(const FloatingWindow *);
|
||||||
|
QRect hoveredFrameRect() const;
|
||||||
bool isHovered() const;
|
bool isHovered() const;
|
||||||
DropLocation currentDropLocation() const { return m_currentDropLocation; }
|
DropLocation currentDropLocation() const;
|
||||||
Frame *hoveredFrame() const { return m_hoveredFrame; }
|
Frame *hoveredFrame() const { return m_hoveredFrame; }
|
||||||
void setCurrentDropLocation(DropIndicatorOverlayInterface::DropLocation location);
|
void setCurrentDropLocation(DropIndicatorOverlayInterface::DropLocation location);
|
||||||
|
|
||||||
virtual Type indicatorType() const = 0;
|
void hover(QPoint globalPos);
|
||||||
virtual void hover(QPoint globalPos) = 0;
|
|
||||||
|
|
||||||
virtual QPoint posForIndicator(DropLocation) const = 0; // Used by unit-tests only
|
virtual QPoint posForIndicator(DropLocation) const { return {}; }; // Used by unit-tests only
|
||||||
|
|
||||||
static KDDockWidgets::Location multisplitterLocationFor(DropLocation);
|
static KDDockWidgets::Location multisplitterLocationFor(DropLocation);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void hoveredFrameChanged(KDDockWidgets::Frame *);
|
void hoveredFrameChanged(KDDockWidgets::Frame *);
|
||||||
|
void hoveredFrameRectChanged();
|
||||||
|
void currentDropLocationChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onFrameDestroyed();
|
void onFrameDestroyed();
|
||||||
|
void setHoveredFrameRect(QRect);
|
||||||
|
QRect m_hoveredFrameRect;
|
||||||
|
DropLocation m_currentDropLocation = DropLocation_None;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void hover_impl(QPoint globalPos) = 0;
|
||||||
virtual void onHoveredFrameChanged(Frame *);
|
virtual void onHoveredFrameChanged(Frame *);
|
||||||
virtual void updateVisibility() = 0;
|
virtual void updateVisibility() {};
|
||||||
|
|
||||||
Frame *m_hoveredFrame = nullptr;
|
Frame *m_hoveredFrame = nullptr;
|
||||||
DropLocation m_currentDropLocation = DropLocation_None;
|
|
||||||
QPointer<const FloatingWindow> m_windowBeingDragged;
|
QPointer<const FloatingWindow> m_windowBeingDragged;
|
||||||
DropArea *const m_dropArea;
|
DropArea *const m_dropArea;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -316,7 +316,8 @@ void FloatingWindow::updateTitleBarVisibility()
|
|||||||
if (KDDockWidgets::usesNativeTitleBar()) {
|
if (KDDockWidgets::usesNativeTitleBar()) {
|
||||||
visible = false;
|
visible = false;
|
||||||
} else {
|
} else {
|
||||||
if (Config::self().flags() & Config::Flag_HideTitleBarWhenTabsVisible) {
|
const auto flags = Config::self().flags();
|
||||||
|
if ((flags & Config::Flag_HideTitleBarWhenTabsVisible) && !(flags & Config::Flag_AlwaysTitleBarWhenFloating)) {
|
||||||
if (hasSingleFrame()) {
|
if (hasSingleFrame()) {
|
||||||
visible = !frames().first()->hasTabsVisible();
|
visible = !frames().first()->hasTabsVisible();
|
||||||
}
|
}
|
||||||
@@ -417,3 +418,14 @@ QRect FloatingWindow::dragRect() const
|
|||||||
|
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FloatingWindow::event(QEvent *ev)
|
||||||
|
{
|
||||||
|
if (ev->type() == QEvent::ActivationChange) {
|
||||||
|
// Since QWidget is missing a signal for window activation
|
||||||
|
Q_EMIT activatedChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QWidgetAdapter::event(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ public:
|
|||||||
QRect dragRect() const;
|
QRect dragRect() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void activatedChanged();
|
||||||
void numFramesChanged();
|
void numFramesChanged();
|
||||||
void windowStateChanged(QWindowStateChangeEvent *);
|
void windowStateChanged(QWindowStateChangeEvent *);
|
||||||
protected:
|
protected:
|
||||||
@@ -131,6 +132,7 @@ protected:
|
|||||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool event(QEvent *ev) override;
|
||||||
void onCloseEvent(QCloseEvent *) override;
|
void onCloseEvent(QCloseEvent *) override;
|
||||||
|
|
||||||
DropArea *const m_dropArea;
|
DropArea *const m_dropArea;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ static FrameOptions actualOptions(FrameOptions options)
|
|||||||
|
|
||||||
Frame::Frame(QWidgetOrQuick *parent, FrameOptions options)
|
Frame::Frame(QWidgetOrQuick *parent, FrameOptions options)
|
||||||
: LayoutGuestWidget(parent)
|
: LayoutGuestWidget(parent)
|
||||||
|
, FocusScope(this)
|
||||||
, m_titleBar(Config::self().frameworkWidgetFactory()->createTitleBar(this))
|
, m_titleBar(Config::self().frameworkWidgetFactory()->createTitleBar(this))
|
||||||
, m_options(actualOptions(options))
|
, m_options(actualOptions(options))
|
||||||
{
|
{
|
||||||
@@ -233,6 +234,10 @@ void Frame::onDockWidgetCountChanged()
|
|||||||
// We don't really keep track of the state, so emit even if the visibility didn't change. No biggie.
|
// We don't really keep track of the state, so emit even if the visibility didn't change. No biggie.
|
||||||
if (!(m_options & FrameOption_AlwaysShowsTabs))
|
if (!(m_options & FrameOption_AlwaysShowsTabs))
|
||||||
Q_EMIT hasTabsVisibleChanged();
|
Q_EMIT hasTabsVisibleChanged();
|
||||||
|
|
||||||
|
const DockWidgetBase::List docks = dockWidgets();
|
||||||
|
for (DockWidgetBase *dock : docks)
|
||||||
|
dock->updateFloatAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_EMIT numDockWidgetsChanged();
|
Q_EMIT numDockWidgetsChanged();
|
||||||
@@ -280,7 +285,7 @@ void Frame::updateTitleBarVisibility()
|
|||||||
|
|
||||||
bool Frame::containsMouse(QPoint globalPos) const
|
bool Frame::containsMouse(QPoint globalPos) const
|
||||||
{
|
{
|
||||||
return QWidgetAdapter::rect().contains(LayoutGuestWidgetBase::mapFromGlobal(globalPos));
|
return QWidgetAdapter::rect().contains(KDDockWidgets::QWidgetAdapter::mapFromGlobal(globalPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBar *Frame::titleBar() const
|
TitleBar *Frame::titleBar() const
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "LayoutSaver_p.h"
|
#include "LayoutSaver_p.h"
|
||||||
#include "multisplitter/Widget_qwidget.h"
|
#include "multisplitter/Widget_qwidget.h"
|
||||||
#include "multisplitter/Item_p.h"
|
#include "multisplitter/Item_p.h"
|
||||||
|
#include "FocusScope.h"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
@@ -47,7 +48,9 @@ class FloatingWindow;
|
|||||||
* inside a MultiSplitter (DropArea). Be it a MultiSplitter belonging to a MainWindow or belonging
|
* inside a MultiSplitter (DropArea). Be it a MultiSplitter belonging to a MainWindow or belonging
|
||||||
* to a FloatingWindow.
|
* to a FloatingWindow.
|
||||||
*/
|
*/
|
||||||
class DOCKS_EXPORT Frame : public LayoutGuestWidget
|
class DOCKS_EXPORT Frame
|
||||||
|
: public LayoutGuestWidget
|
||||||
|
, public FocusScope
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(KDDockWidgets::TitleBar* titleBar READ titleBar CONSTANT)
|
Q_PROPERTY(KDDockWidgets::TitleBar* titleBar READ titleBar CONSTANT)
|
||||||
@@ -223,6 +226,8 @@ Q_SIGNALS:
|
|||||||
void hasTabsVisibleChanged();
|
void hasTabsVisibleChanged();
|
||||||
void layoutInvalidated();
|
void layoutInvalidated();
|
||||||
void isInMainWindowChanged();
|
void isInMainWindowChanged();
|
||||||
|
void isFocusedChanged() override; // override from non-QObject
|
||||||
|
void focusedWidgetChanged() override;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -220,11 +220,10 @@ void MultiSplitter::addMultiSplitter(MultiSplitter *sourceMultiSplitter, Locatio
|
|||||||
|
|
||||||
void MultiSplitter::removeItem(Layouting::Item *item)
|
void MultiSplitter::removeItem(Layouting::Item *item)
|
||||||
{
|
{
|
||||||
if (!item)
|
if (!item) {
|
||||||
qWarning() << Q_FUNC_INFO << "nullptr item";
|
qWarning() << Q_FUNC_INFO << "nullptr item";
|
||||||
|
|
||||||
if (!item)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
item->parentContainer()->removeItem(item);
|
item->parentContainer()->removeItem(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,12 @@ TitleBar::TitleBar(Frame *parent)
|
|||||||
, m_floatingWindow(nullptr)
|
, m_floatingWindow(nullptr)
|
||||||
{
|
{
|
||||||
connect(m_frame, &Frame::numDockWidgetsChanged, this, &TitleBar::updateCloseButton);
|
connect(m_frame, &Frame::numDockWidgetsChanged, this, &TitleBar::updateCloseButton);
|
||||||
|
connect(m_frame, &Frame::isFocusedChanged, this, &TitleBar::isFocusedChanged);
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
if (Config::self().flags() & Config::Flag_TitleBarIsFocusable)
|
||||||
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBar::TitleBar(FloatingWindow *parent)
|
TitleBar::TitleBar(FloatingWindow *parent)
|
||||||
@@ -41,6 +46,7 @@ TitleBar::TitleBar(FloatingWindow *parent)
|
|||||||
connect(m_floatingWindow, &FloatingWindow::numFramesChanged, this, &TitleBar::updateFloatButton);
|
connect(m_floatingWindow, &FloatingWindow::numFramesChanged, this, &TitleBar::updateFloatButton);
|
||||||
connect(m_floatingWindow, &FloatingWindow::numFramesChanged, this, &TitleBar::updateMaximizeButton);
|
connect(m_floatingWindow, &FloatingWindow::numFramesChanged, this, &TitleBar::updateMaximizeButton);
|
||||||
connect(m_floatingWindow, &FloatingWindow::windowStateChanged, this, &TitleBar::updateMaximizeButton);
|
connect(m_floatingWindow, &FloatingWindow::windowStateChanged, this, &TitleBar::updateMaximizeButton);
|
||||||
|
connect(m_floatingWindow, &FloatingWindow::activatedChanged , this, &TitleBar::isFocusedChanged);
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +54,10 @@ void TitleBar::init()
|
|||||||
{
|
{
|
||||||
qCDebug(creation) << "TitleBar" << this;
|
qCDebug(creation) << "TitleBar" << this;
|
||||||
setFixedHeight(30);
|
setFixedHeight(30);
|
||||||
|
connect(this, &TitleBar::isFocusedChanged, this, [this] {
|
||||||
|
// repaint
|
||||||
|
update();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBar::~TitleBar()
|
TitleBar::~TitleBar()
|
||||||
@@ -79,6 +89,17 @@ void TitleBar::toggleMaximized()
|
|||||||
m_floatingWindow->showMaximized();
|
m_floatingWindow->showMaximized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TitleBar::focusInEvent(QFocusEvent *ev)
|
||||||
|
{
|
||||||
|
QWidgetAdapter::focusInEvent(ev);
|
||||||
|
|
||||||
|
if (!m_frame || !(Config::self().flags() & Config::Flag_TitleBarIsFocusable))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// For some reason QWidget::setFocusProxy() isn't working, so forward manually
|
||||||
|
m_frame->FocusScope::focus(ev->reason());
|
||||||
|
}
|
||||||
|
|
||||||
void TitleBar::setTitle(const QString &title)
|
void TitleBar::setTitle(const QString &title)
|
||||||
{
|
{
|
||||||
if (title != m_title) {
|
if (title != m_title) {
|
||||||
@@ -129,7 +150,7 @@ std::unique_ptr<WindowBeingDragged> TitleBar::makeWindow()
|
|||||||
|
|
||||||
QRect r = m_frame->QWidgetAdapter::geometry();
|
QRect r = m_frame->QWidgetAdapter::geometry();
|
||||||
qCDebug(hovering) << "TitleBar::makeWindow original geometry" << r;
|
qCDebug(hovering) << "TitleBar::makeWindow original geometry" << r;
|
||||||
r.moveTopLeft(static_cast<Layouting::Widget*>(m_frame)->mapToGlobal(QPoint(0, 0))); // TODO: Remove static_cast if it compiles. Ambiguous base for now
|
r.moveTopLeft(m_frame->mapToGlobal(QPoint(0, 0))); // TODO: Remove static_cast if it compiles. Ambiguous base for now
|
||||||
|
|
||||||
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(m_frame);
|
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(m_frame);
|
||||||
floatingWindow->setSuggestedGeometry(r);
|
floatingWindow->setSuggestedGeometry(r);
|
||||||
@@ -174,6 +195,16 @@ bool TitleBar::hasIcon() const
|
|||||||
return !m_icon.isNull();
|
return !m_icon.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TitleBar::isFocused() const
|
||||||
|
{
|
||||||
|
if (m_frame)
|
||||||
|
return m_frame->isFocused();
|
||||||
|
else if (m_floatingWindow)
|
||||||
|
return m_floatingWindow->isActiveWindow();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QIcon TitleBar::icon() const
|
QIcon TitleBar::icon() const
|
||||||
{
|
{
|
||||||
return m_icon;
|
return m_icon;
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ public:
|
|||||||
///@brief returns whether this title bar has an icon
|
///@brief returns whether this title bar has an icon
|
||||||
bool hasIcon() const;
|
bool hasIcon() const;
|
||||||
|
|
||||||
|
///@brief returns whether any of the DockWidgets this TitleBar controls has a child focus
|
||||||
|
///Not to be confused with QWidget::hasFocus(), which just refers to 1 widget. This works more
|
||||||
|
/// like QtQuick's FocusScope
|
||||||
|
bool isFocused() const;
|
||||||
|
|
||||||
///@brief the icon
|
///@brief the icon
|
||||||
QIcon icon() const;
|
QIcon icon() const;
|
||||||
|
|
||||||
@@ -86,6 +91,7 @@ public:
|
|||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void titleChanged();
|
void titleChanged();
|
||||||
void iconChanged();
|
void iconChanged();
|
||||||
|
void isFocusedChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Q_INVOKABLE void onCloseClicked();
|
Q_INVOKABLE void onCloseClicked();
|
||||||
@@ -102,6 +108,8 @@ protected:
|
|||||||
virtual bool isFloatButtonVisible() const { return true; }
|
virtual bool isFloatButtonVisible() const { return true; }
|
||||||
virtual bool isFloatButtonEnabled() const { return true; }
|
virtual bool isFloatButtonEnabled() const { return true; }
|
||||||
|
|
||||||
|
void focusInEvent(QFocusEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class TestDocks;
|
friend class TestDocks;
|
||||||
|
|
||||||
|
|||||||
@@ -47,11 +47,21 @@ WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw, Draggable *draggable)
|
|||||||
, m_draggable(bestDraggable(draggable)->asWidget())
|
, m_draggable(bestDraggable(draggable)->asWidget())
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
// Set opacity while dragging, if needed
|
||||||
|
const qreal opacity = Config::self().draggedWindowOpacity();
|
||||||
|
if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
|
||||||
|
fw->setWindowOpacity(opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowBeingDragged::~WindowBeingDragged()
|
WindowBeingDragged::~WindowBeingDragged()
|
||||||
{
|
{
|
||||||
grabMouse(false);
|
grabMouse(false);
|
||||||
|
|
||||||
|
// Restore opacity to fully opaque if needed
|
||||||
|
const qreal opacity = Config::self().draggedWindowOpacity();
|
||||||
|
if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
|
||||||
|
m_floatingWindow->setWindowOpacity(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowBeingDragged::init()
|
void WindowBeingDragged::init()
|
||||||
|
|||||||
@@ -14,245 +14,24 @@
|
|||||||
#include "DragController_p.h"
|
#include "DragController_p.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "Utils_p.h"
|
#include "Config.h"
|
||||||
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include <QPainter>
|
#include "ClassicIndicatorsWindow_p.h"
|
||||||
#include <QRubberBand>
|
|
||||||
|
|
||||||
#define INDICATOR_WIDTH 40
|
|
||||||
#define OUTTER_INDICATOR_MARGIN 10
|
|
||||||
//#define KDDOCKWIDGETS_RUBBERBAND_IS_TOPLEVEL 1
|
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
static IndicatorWindow* createIndicatorWindow(ClassicIndicators *classicIndicators)
|
||||||
class IndicatorWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Indicator::paintEvent(QPaintEvent *)
|
|
||||||
{
|
{
|
||||||
QPainter p(this);
|
auto window = new IndicatorWindow(classicIndicators);
|
||||||
if (m_hovered)
|
window->setObjectName(QStringLiteral("_docks_IndicatorWindow_Overlay"));
|
||||||
p.drawImage(rect(), m_imageActive, rect());
|
return window;
|
||||||
else
|
|
||||||
p.drawImage(rect(), m_image, rect());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Indicator::setHovered(bool hovered)
|
|
||||||
{
|
|
||||||
if (hovered != m_hovered) {
|
|
||||||
m_hovered = hovered;
|
|
||||||
update();
|
|
||||||
if (hovered) {
|
|
||||||
q->setDropLocation(m_dropLocation);
|
|
||||||
} else if (q->currentDropLocation() == m_dropLocation) {
|
|
||||||
q->setDropLocation(DropIndicatorOverlayInterface::DropLocation_None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Indicator::iconName(bool active) const
|
|
||||||
{
|
|
||||||
QString suffix = active ? QStringLiteral("_active")
|
|
||||||
: QString();
|
|
||||||
|
|
||||||
QString name;
|
|
||||||
switch (m_dropLocation) {
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Center:
|
|
||||||
name = QStringLiteral("center");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Left:
|
|
||||||
name = QStringLiteral("inner_left");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Right:
|
|
||||||
name = QStringLiteral("inner_right");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Bottom:
|
|
||||||
name = QStringLiteral("inner_bottom");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Top:
|
|
||||||
name = QStringLiteral("inner_top");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_OutterLeft:
|
|
||||||
name = QStringLiteral("outter_left");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_OutterBottom:
|
|
||||||
name = QStringLiteral("outter_bottom");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_OutterRight:
|
|
||||||
name = QStringLiteral("outter_right");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_OutterTop:
|
|
||||||
name = QStringLiteral("outter_top");
|
|
||||||
break;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_None:
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return name + suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Indicator::iconFileName(bool active) const
|
|
||||||
{
|
|
||||||
const QString name = iconName(active);
|
|
||||||
return KDDockWidgets::windowManagerHasTranslucency() ? QStringLiteral(":/img/classic_indicators/%1.png").arg(name)
|
|
||||||
: QStringLiteral(":/img/classic_indicators/opaque/%1.png").arg(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
IndicatorWindow::IndicatorWindow(ClassicIndicators *classicIndicators_, QWidget *)
|
|
||||||
: QWidget(nullptr, Qt::Tool | Qt::BypassWindowManagerHint)
|
|
||||||
, classicIndicators(classicIndicators_)
|
|
||||||
, m_center(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Center)) // Each indicator is not a top-level. Otherwise there's noticeable delay.
|
|
||||||
, m_left(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Left))
|
|
||||||
, m_right(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Right))
|
|
||||||
, m_bottom(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Bottom))
|
|
||||||
, m_top(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Top))
|
|
||||||
, m_outterLeft(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_OutterLeft))
|
|
||||||
, m_outterRight(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_OutterRight))
|
|
||||||
, m_outterBottom(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_OutterBottom))
|
|
||||||
, m_outterTop(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_OutterTop))
|
|
||||||
{
|
|
||||||
setWindowFlag(Qt::FramelessWindowHint, true);
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
updatePosition();
|
|
||||||
|
|
||||||
m_indicators << m_center << m_left << m_right << m_top << m_bottom
|
|
||||||
<< m_outterBottom << m_outterTop << m_outterLeft << m_outterRight;
|
|
||||||
|
|
||||||
setObjectName(QStringLiteral("_docks_IndicatorWindow_Overlay"));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IndicatorWindow::event(QEvent *e)
|
|
||||||
{
|
|
||||||
if (e->type() == QEvent::Show) {
|
|
||||||
updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
return QWidget::event(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Indicator *IndicatorWindow::indicatorForLocation(DropIndicatorOverlayInterface::DropLocation loc) const
|
|
||||||
{
|
|
||||||
switch (loc) {
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Center:
|
|
||||||
return m_center;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Left:
|
|
||||||
return m_left;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Right:
|
|
||||||
return m_right;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Bottom:
|
|
||||||
return m_bottom;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Top:
|
|
||||||
return m_top;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_OutterLeft:
|
|
||||||
return m_outterLeft;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_OutterBottom:
|
|
||||||
return m_outterBottom;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_OutterRight:
|
|
||||||
return m_outterRight;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_OutterTop:
|
|
||||||
return m_outterTop;
|
|
||||||
case DropIndicatorOverlayInterface::DropLocation_None:
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorWindow::updateMask()
|
|
||||||
{
|
|
||||||
QRegion region;
|
|
||||||
|
|
||||||
if (!KDDockWidgets::windowManagerHasTranslucency()) {
|
|
||||||
for (Indicator *indicator : qAsConst(m_indicators)) {
|
|
||||||
if (indicator->isVisible())
|
|
||||||
region = region.united(QRegion(indicator->geometry(), QRegion::Rectangle));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setMask(region);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorWindow::resizeEvent(QResizeEvent *ev)
|
|
||||||
{
|
|
||||||
QWidget::resizeEvent(ev);
|
|
||||||
updatePositions();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorWindow::updateIndicatorVisibility(bool visible)
|
|
||||||
{
|
|
||||||
Frame *hoveredFrame = classicIndicators->m_hoveredFrame;
|
|
||||||
const bool isTheOnlyFrame = hoveredFrame && hoveredFrame->isTheOnlyFrame();
|
|
||||||
|
|
||||||
const bool innerShouldBeVisible = visible && hoveredFrame;
|
|
||||||
const bool outterShouldBeVisible = visible && !isTheOnlyFrame;
|
|
||||||
|
|
||||||
for (Indicator *indicator : { m_center, m_left, m_right, m_bottom, m_top })
|
|
||||||
indicator->setVisible(innerShouldBeVisible);
|
|
||||||
|
|
||||||
for (Indicator *indicator : { m_outterTop, m_outterLeft, m_outterRight, m_outterBottom })
|
|
||||||
indicator->setVisible(outterShouldBeVisible);
|
|
||||||
|
|
||||||
updateMask();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorWindow::hover(QPoint globalPos)
|
|
||||||
{
|
|
||||||
for (Indicator *indicator : qAsConst(m_indicators)) {
|
|
||||||
if (indicator->isVisible())
|
|
||||||
indicator->setHovered(indicator->rect().contains(indicator->mapFromGlobal(globalPos)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorWindow::updatePosition()
|
|
||||||
{
|
|
||||||
QRect rect = classicIndicators->rect();
|
|
||||||
QPoint pos = classicIndicators->mapToGlobal(QPoint(0, 0));
|
|
||||||
rect.moveTo(pos);
|
|
||||||
setGeometry(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IndicatorWindow::updatePositions()
|
|
||||||
{
|
|
||||||
QRect r = rect();
|
|
||||||
const int indicatorWidth = m_outterBottom->width();
|
|
||||||
const int halfIndicatorWidth = m_outterBottom->width() / 2;
|
|
||||||
|
|
||||||
m_outterLeft->move(r.x() + OUTTER_INDICATOR_MARGIN, r.center().y() - halfIndicatorWidth);
|
|
||||||
m_outterBottom->move(r.center().x() - halfIndicatorWidth, r.y() + height() - indicatorWidth - OUTTER_INDICATOR_MARGIN);
|
|
||||||
m_outterTop->move(r.center().x() - halfIndicatorWidth, r.y() + OUTTER_INDICATOR_MARGIN);
|
|
||||||
m_outterRight->move(r.x() + width() - indicatorWidth - OUTTER_INDICATOR_MARGIN, r.center().y() - halfIndicatorWidth);
|
|
||||||
Frame *hoveredFrame = classicIndicators->m_hoveredFrame;
|
|
||||||
if (hoveredFrame) {
|
|
||||||
QRect hoveredRect = hoveredFrame->QWidget::geometry();
|
|
||||||
m_center->move(r.topLeft() + hoveredRect.center() - QPoint(halfIndicatorWidth, halfIndicatorWidth));
|
|
||||||
m_top->move(m_center->pos() - QPoint(0, indicatorWidth + OUTTER_INDICATOR_MARGIN));
|
|
||||||
m_right->move(m_center->pos() + QPoint(indicatorWidth + OUTTER_INDICATOR_MARGIN, 0));
|
|
||||||
m_bottom->move(m_center->pos() + QPoint(0, indicatorWidth + OUTTER_INDICATOR_MARGIN));
|
|
||||||
m_left->move(m_center->pos() - QPoint(indicatorWidth + OUTTER_INDICATOR_MARGIN, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Indicator::Indicator(ClassicIndicators *classicIndicators, IndicatorWindow *parent, ClassicIndicators::DropLocation location)
|
|
||||||
: QWidget(parent)
|
|
||||||
, q(classicIndicators)
|
|
||||||
, m_dropLocation(location)
|
|
||||||
{
|
|
||||||
m_image = QImage(iconFileName(/*active=*/ false)).scaled(INDICATOR_WIDTH, INDICATOR_WIDTH);
|
|
||||||
m_imageActive = QImage(iconFileName(/*active=*/ true)).scaled(INDICATOR_WIDTH, INDICATOR_WIDTH);
|
|
||||||
setFixedSize(m_image.size());
|
|
||||||
setVisible(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassicIndicators::ClassicIndicators(DropArea *dropArea)
|
ClassicIndicators::ClassicIndicators(DropArea *dropArea)
|
||||||
: DropIndicatorOverlayInterface(dropArea) // Is parented on the drop-area, not a toplevel.
|
: DropIndicatorOverlayInterface(dropArea) // Is parented on the drop-area, not a toplevel.
|
||||||
, m_rubberBand(new QRubberBand(QRubberBand::Rectangle, rubberBandIsTopLevel() ? nullptr : dropArea))
|
, m_rubberBand(Config::self().frameworkWidgetFactory()->createRubberBand(dropArea))
|
||||||
, m_indicatorWindow(new IndicatorWindow(this, /*parent=*/ nullptr)) // Top-level so the indicators can appear above the window being dragged.
|
, m_indicatorWindow(createIndicatorWindow(this))
|
||||||
{
|
{
|
||||||
setVisible(false);
|
|
||||||
if (rubberBandIsTopLevel())
|
|
||||||
m_rubberBand->setWindowOpacity(0.5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassicIndicators::~ClassicIndicators()
|
ClassicIndicators::~ClassicIndicators()
|
||||||
@@ -260,20 +39,30 @@ ClassicIndicators::~ClassicIndicators()
|
|||||||
delete m_indicatorWindow;
|
delete m_indicatorWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
DropIndicatorOverlayInterface::Type ClassicIndicators::indicatorType() const
|
void ClassicIndicators::hover_impl(QPoint globalPos)
|
||||||
{
|
|
||||||
return TypeClassic;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicIndicators::hover(QPoint globalPos)
|
|
||||||
{
|
{
|
||||||
m_indicatorWindow->hover(globalPos);
|
m_indicatorWindow->hover(globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint ClassicIndicators::posForIndicator(DropIndicatorOverlayInterface::DropLocation loc) const
|
QPoint ClassicIndicators::posForIndicator(DropIndicatorOverlayInterface::DropLocation loc) const
|
||||||
{
|
{
|
||||||
Indicator *indicator = m_indicatorWindow->indicatorForLocation(loc);
|
return m_indicatorWindow->posForIndicator(loc);
|
||||||
return indicator->mapToGlobal(indicator->rect().center());
|
}
|
||||||
|
|
||||||
|
bool ClassicIndicators::innerIndicatorsVisible() const
|
||||||
|
{
|
||||||
|
return m_innerIndicatorsVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassicIndicators::outterIndicatorsVisible() const
|
||||||
|
{
|
||||||
|
return m_outterIndicatorsVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassicIndicators::onResize(QSize)
|
||||||
|
{
|
||||||
|
m_indicatorWindow->resize(window()->size());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicIndicators::updateVisibility()
|
void ClassicIndicators::updateVisibility()
|
||||||
@@ -281,29 +70,26 @@ void ClassicIndicators::updateVisibility()
|
|||||||
if (isHovered()) {
|
if (isHovered()) {
|
||||||
m_indicatorWindow->updatePositions();
|
m_indicatorWindow->updatePositions();
|
||||||
m_indicatorWindow->setVisible(true);
|
m_indicatorWindow->setVisible(true);
|
||||||
m_indicatorWindow->updateIndicatorVisibility(true);
|
updateWindowPosition();
|
||||||
|
updateIndicatorsVisibility(true);
|
||||||
raiseIndicators();
|
raiseIndicators();
|
||||||
} else {
|
} else {
|
||||||
m_rubberBand->setVisible(false);
|
m_rubberBand->setVisible(false);
|
||||||
m_indicatorWindow->setVisible(false);
|
m_indicatorWindow->setVisible(false);
|
||||||
m_indicatorWindow->updateIndicatorVisibility(false);
|
updateIndicatorsVisibility(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicIndicators::showEvent(QShowEvent *e)
|
void ClassicIndicators::updateIndicatorsVisibility(bool visible)
|
||||||
{
|
{
|
||||||
QWidget::showEvent(e);
|
Frame *hoveredFrame = m_hoveredFrame;
|
||||||
}
|
const bool isTheOnlyFrame = hoveredFrame && hoveredFrame->isTheOnlyFrame();
|
||||||
|
|
||||||
void ClassicIndicators::hideEvent(QHideEvent *e)
|
m_innerIndicatorsVisible = visible && hoveredFrame;
|
||||||
{
|
m_outterIndicatorsVisible = visible && !isTheOnlyFrame;
|
||||||
QWidget::hideEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicIndicators::resizeEvent(QResizeEvent *ev)
|
Q_EMIT innerIndicatorsVisibleChanged();
|
||||||
{
|
Q_EMIT outterIndicatorsVisibleChanged();
|
||||||
QWidget::resizeEvent(ev);
|
|
||||||
m_indicatorWindow->resize(window()->size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicIndicators::raiseIndicators()
|
void ClassicIndicators::raiseIndicators()
|
||||||
@@ -346,12 +132,8 @@ void ClassicIndicators::setDropLocation(ClassicIndicators::DropLocation location
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (location == DropLocation_Center) {
|
if (location == DropLocation_Center) {
|
||||||
m_rubberBand->setGeometry(geometryForRubberband(m_hoveredFrame ? m_hoveredFrame->QWidget::geometry() : rect()));
|
m_rubberBand->setGeometry(m_hoveredFrame ? m_hoveredFrame->QWidgetAdapter::geometry() : rect());
|
||||||
m_rubberBand->setVisible(true);
|
m_rubberBand->setVisible(true);
|
||||||
if (rubberBandIsTopLevel()) {
|
|
||||||
m_rubberBand->raise();
|
|
||||||
raiseIndicators();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,32 +166,14 @@ void ClassicIndicators::setDropLocation(ClassicIndicators::DropLocation location
|
|||||||
QRect rect = m_dropArea->rectForDrop(m_windowBeingDragged, multisplitterLocation,
|
QRect rect = m_dropArea->rectForDrop(m_windowBeingDragged, multisplitterLocation,
|
||||||
m_dropArea->itemForFrame(relativeToFrame));
|
m_dropArea->itemForFrame(relativeToFrame));
|
||||||
|
|
||||||
m_rubberBand->setGeometry(geometryForRubberband(rect));
|
m_rubberBand->setGeometry(rect);
|
||||||
m_rubberBand->setVisible(true);
|
m_rubberBand->setVisible(true);
|
||||||
if (rubberBandIsTopLevel()) {
|
|
||||||
m_rubberBand->raise();
|
|
||||||
raiseIndicators();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect ClassicIndicators::geometryForRubberband(QRect localRect) const
|
void ClassicIndicators::updateWindowPosition()
|
||||||
{
|
{
|
||||||
if (!rubberBandIsTopLevel())
|
QRect rect = this->rect();
|
||||||
return localRect;
|
QPoint pos = mapToGlobal(QPoint(0, 0));
|
||||||
|
rect.moveTo(pos);
|
||||||
QPoint topLeftLocal = localRect.topLeft();
|
m_indicatorWindow->setGeometry(rect);
|
||||||
QPoint topLeftGlobal = m_dropArea->QWidget::mapToGlobal(topLeftLocal);
|
|
||||||
|
|
||||||
localRect.moveTopLeft(topLeftGlobal);
|
|
||||||
|
|
||||||
return localRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicIndicators::rubberBandIsTopLevel() const
|
|
||||||
{
|
|
||||||
#ifdef KDDOCKWIDGETS_RUBBERBAND_IS_TOPLEVEL
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
318
src/private/indicators/ClassicIndicatorsWindow.cpp
Normal file
318
src/private/indicators/ClassicIndicatorsWindow.cpp
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ClassicIndicatorsWindow_p.h"
|
||||||
|
#include "ClassicIndicators_p.h"
|
||||||
|
#include "Utils_p.h"
|
||||||
|
|
||||||
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
namespace KDDockWidgets
|
||||||
|
{
|
||||||
|
|
||||||
|
static QString iconName(DropIndicatorOverlayInterface::DropLocation loc, bool active)
|
||||||
|
{
|
||||||
|
QString suffix = active ? QStringLiteral("_active")
|
||||||
|
: QString();
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
switch (loc) {
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Center:
|
||||||
|
name = QStringLiteral("center");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Left:
|
||||||
|
name = QStringLiteral("inner_left");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Right:
|
||||||
|
name = QStringLiteral("inner_right");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Bottom:
|
||||||
|
name = QStringLiteral("inner_bottom");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Top:
|
||||||
|
name = QStringLiteral("inner_top");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_OutterLeft:
|
||||||
|
name = QStringLiteral("outter_left");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_OutterBottom:
|
||||||
|
name = QStringLiteral("outter_bottom");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_OutterRight:
|
||||||
|
name = QStringLiteral("outter_right");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_OutterTop:
|
||||||
|
name = QStringLiteral("outter_top");
|
||||||
|
break;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_None:
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return name + suffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#define INDICATOR_WIDTH 40
|
||||||
|
#define OUTTER_INDICATOR_MARGIN 10
|
||||||
|
|
||||||
|
void Indicator::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
if (m_hovered)
|
||||||
|
p.drawImage(rect(), m_imageActive, rect());
|
||||||
|
else
|
||||||
|
p.drawImage(rect(), m_image, rect());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Indicator::setHovered(bool hovered)
|
||||||
|
{
|
||||||
|
if (hovered != m_hovered) {
|
||||||
|
m_hovered = hovered;
|
||||||
|
update();
|
||||||
|
if (hovered) {
|
||||||
|
q->setDropLocation(m_dropLocation);
|
||||||
|
} else if (q->currentDropLocation() == m_dropLocation) {
|
||||||
|
q->setDropLocation(DropIndicatorOverlayInterface::DropLocation_None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Indicator::iconName(bool active) const
|
||||||
|
{
|
||||||
|
return KDDockWidgets::iconName(m_dropLocation, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Indicator::iconFileName(bool active) const
|
||||||
|
{
|
||||||
|
const QString name = iconName(active);
|
||||||
|
return KDDockWidgets::windowManagerHasTranslucency() ? QStringLiteral(":/img/classic_indicators/%1.png").arg(name)
|
||||||
|
: QStringLiteral(":/img/classic_indicators/opaque/%1.png").arg(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
IndicatorWindow::IndicatorWindow(ClassicIndicators *classicIndicators_)
|
||||||
|
: QWidget(nullptr, Qt::Tool | Qt::BypassWindowManagerHint)
|
||||||
|
, classicIndicators(classicIndicators_)
|
||||||
|
, m_center(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Center)) // Each indicator is not a top-level. Otherwise there's noticeable delay.
|
||||||
|
, m_left(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Left))
|
||||||
|
, m_right(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Right))
|
||||||
|
, m_bottom(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Bottom))
|
||||||
|
, m_top(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Top))
|
||||||
|
, m_outterLeft(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_OutterLeft))
|
||||||
|
, m_outterRight(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_OutterRight))
|
||||||
|
, m_outterBottom(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_OutterBottom))
|
||||||
|
, m_outterTop(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_OutterTop))
|
||||||
|
{
|
||||||
|
setWindowFlag(Qt::FramelessWindowHint, true);
|
||||||
|
setAttribute(Qt::WA_TranslucentBackground);
|
||||||
|
|
||||||
|
connect(classicIndicators, &ClassicIndicators::innerIndicatorsVisibleChanged,
|
||||||
|
this, &IndicatorWindow::updateIndicatorVisibility);
|
||||||
|
connect(classicIndicators, &ClassicIndicators::outterIndicatorsVisibleChanged,
|
||||||
|
this, &IndicatorWindow::updateIndicatorVisibility);
|
||||||
|
|
||||||
|
m_indicators << m_center << m_left << m_right << m_top << m_bottom
|
||||||
|
<< m_outterBottom << m_outterTop << m_outterLeft << m_outterRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
Indicator *IndicatorWindow::indicatorForLocation(DropIndicatorOverlayInterface::DropLocation loc) const
|
||||||
|
{
|
||||||
|
switch (loc) {
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Center:
|
||||||
|
return m_center;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Left:
|
||||||
|
return m_left;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Right:
|
||||||
|
return m_right;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Bottom:
|
||||||
|
return m_bottom;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_Top:
|
||||||
|
return m_top;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_OutterLeft:
|
||||||
|
return m_outterLeft;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_OutterBottom:
|
||||||
|
return m_outterBottom;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_OutterRight:
|
||||||
|
return m_outterRight;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_OutterTop:
|
||||||
|
return m_outterTop;
|
||||||
|
case DropIndicatorOverlayInterface::DropLocation_None:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndicatorWindow::updateMask()
|
||||||
|
{
|
||||||
|
QRegion region;
|
||||||
|
|
||||||
|
if (!KDDockWidgets::windowManagerHasTranslucency()) {
|
||||||
|
for (Indicator *indicator : qAsConst(m_indicators)) {
|
||||||
|
if (indicator->isVisible())
|
||||||
|
region = region.united(QRegion(indicator->geometry(), QRegion::Rectangle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setMask(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndicatorWindow::resizeEvent(QResizeEvent *ev)
|
||||||
|
{
|
||||||
|
QWidget::resizeEvent(ev);
|
||||||
|
updatePositions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndicatorWindow::updateIndicatorVisibility()
|
||||||
|
{
|
||||||
|
for (Indicator *indicator : { m_center, m_left, m_right, m_bottom, m_top })
|
||||||
|
indicator->setVisible(classicIndicators->innerIndicatorsVisible());
|
||||||
|
|
||||||
|
for (Indicator *indicator : { m_outterTop, m_outterLeft, m_outterRight, m_outterBottom })
|
||||||
|
indicator->setVisible(classicIndicators->outterIndicatorsVisible());
|
||||||
|
|
||||||
|
updateMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint IndicatorWindow::posForIndicator(DropIndicatorOverlayInterface::DropLocation loc) const
|
||||||
|
{
|
||||||
|
Indicator *indicator = indicatorForLocation(loc);
|
||||||
|
return indicator->mapToGlobal(indicator->rect().center());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndicatorWindow::hover(QPoint globalPos)
|
||||||
|
{
|
||||||
|
for (Indicator *indicator : qAsConst(m_indicators)) {
|
||||||
|
if (indicator->isVisible())
|
||||||
|
indicator->setHovered(indicator->rect().contains(indicator->mapFromGlobal(globalPos)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndicatorWindow::updatePositions()
|
||||||
|
{
|
||||||
|
QRect r = rect();
|
||||||
|
const int indicatorWidth = m_outterBottom->width();
|
||||||
|
const int halfIndicatorWidth = m_outterBottom->width() / 2;
|
||||||
|
|
||||||
|
m_outterLeft->move(r.x() + OUTTER_INDICATOR_MARGIN, r.center().y() - halfIndicatorWidth);
|
||||||
|
m_outterBottom->move(r.center().x() - halfIndicatorWidth, r.y() + height() - indicatorWidth - OUTTER_INDICATOR_MARGIN);
|
||||||
|
m_outterTop->move(r.center().x() - halfIndicatorWidth, r.y() + OUTTER_INDICATOR_MARGIN);
|
||||||
|
m_outterRight->move(r.x() + width() - indicatorWidth - OUTTER_INDICATOR_MARGIN, r.center().y() - halfIndicatorWidth);
|
||||||
|
Frame *hoveredFrame = classicIndicators->m_hoveredFrame;
|
||||||
|
if (hoveredFrame) {
|
||||||
|
QRect hoveredRect = hoveredFrame->QWidget::geometry();
|
||||||
|
m_center->move(r.topLeft() + hoveredRect.center() - QPoint(halfIndicatorWidth, halfIndicatorWidth));
|
||||||
|
m_top->move(m_center->pos() - QPoint(0, indicatorWidth + OUTTER_INDICATOR_MARGIN));
|
||||||
|
m_right->move(m_center->pos() + QPoint(indicatorWidth + OUTTER_INDICATOR_MARGIN, 0));
|
||||||
|
m_bottom->move(m_center->pos() + QPoint(0, indicatorWidth + OUTTER_INDICATOR_MARGIN));
|
||||||
|
m_left->move(m_center->pos() - QPoint(indicatorWidth + OUTTER_INDICATOR_MARGIN, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Indicator::Indicator(ClassicIndicators *classicIndicators, IndicatorWindow *parent, ClassicIndicators::DropLocation location)
|
||||||
|
: QWidget(parent)
|
||||||
|
, q(classicIndicators)
|
||||||
|
, m_dropLocation(location)
|
||||||
|
{
|
||||||
|
m_image = QImage(iconFileName(/*active=*/ false)).scaled(INDICATOR_WIDTH, INDICATOR_WIDTH);
|
||||||
|
m_imageActive = QImage(iconFileName(/*active=*/ true)).scaled(INDICATOR_WIDTH, INDICATOR_WIDTH);
|
||||||
|
setFixedSize(m_image.size());
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <QQmlContext>
|
||||||
|
|
||||||
|
IndicatorWindow::IndicatorWindow(KDDockWidgets::ClassicIndicators *classicIndicators)
|
||||||
|
: QQuickView()
|
||||||
|
, m_classicIndicators(classicIndicators)
|
||||||
|
{
|
||||||
|
setColor(Qt::transparent);
|
||||||
|
setFlags(flags() | Qt::FramelessWindowHint);
|
||||||
|
rootContext()->setContextProperty(QStringLiteral("_window"), QVariant::fromValue<QObject*>(this));
|
||||||
|
setSource(QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/ClassicIndicatorsOverlay.qml")));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndicatorWindow::hover(QPoint pt)
|
||||||
|
{
|
||||||
|
QQuickItem *item = indicatorForPos(pt);
|
||||||
|
if (item) {
|
||||||
|
const auto loc = DropIndicatorOverlayInterface::DropLocation(item->property("indicatorType").toInt());
|
||||||
|
classicIndicators()->setDropLocation(loc);
|
||||||
|
} else {
|
||||||
|
classicIndicators()->setDropLocation(DropIndicatorOverlayInterface::DropLocation_None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QQuickItem *IndicatorWindow::indicatorForPos(QPoint pt) const
|
||||||
|
{
|
||||||
|
const QVector<QQuickItem *> indicators = indicatorItems();
|
||||||
|
Q_ASSERT(indicators.size() == 9);
|
||||||
|
|
||||||
|
for (QQuickItem *item : indicators) {
|
||||||
|
QRect rect(0, 0, int(item->width()), int(item->height()));
|
||||||
|
rect.moveTopLeft(item->mapToGlobal(QPointF(0, 0)).toPoint());
|
||||||
|
if (rect.contains(pt))
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndicatorWindow::updatePositions()
|
||||||
|
{
|
||||||
|
// Not needed to implement, the Indicators use QML anchors
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint IndicatorWindow::posForIndicator(KDDockWidgets::DropIndicatorOverlayInterface::DropLocation) const
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IndicatorWindow::iconName(int loc, bool active) const
|
||||||
|
{
|
||||||
|
return KDDockWidgets::iconName(DropIndicatorOverlayInterface::DropLocation(loc), active);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassicIndicators *IndicatorWindow::classicIndicators() const
|
||||||
|
{
|
||||||
|
return m_classicIndicators;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QQuickItem *> IndicatorWindow::indicatorItems() const
|
||||||
|
{
|
||||||
|
QVector<QQuickItem *> indicators;
|
||||||
|
indicators.reserve(9);
|
||||||
|
|
||||||
|
QQuickItem *root = rootObject();
|
||||||
|
const QList<QQuickItem*> items = root->childItems();
|
||||||
|
for (QQuickItem *item : items) {
|
||||||
|
if (QString::fromLatin1(item->metaObject()->className()).startsWith(QLatin1String("ClassicIndicator_QMLTYPE"))) {
|
||||||
|
indicators.push_back(item);
|
||||||
|
} else if (item->objectName() == QLatin1String("innerIndicators")) {
|
||||||
|
const QList<QQuickItem*> innerIndicators = item->childItems();
|
||||||
|
for (QQuickItem *innerItem : innerIndicators) {
|
||||||
|
if (QString::fromLatin1(innerItem->metaObject()->className()).startsWith(QLatin1String("ClassicIndicator_QMLTYPE"))) {
|
||||||
|
indicators.push_back(innerItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return indicators;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QtQuick
|
||||||
108
src/private/indicators/ClassicIndicatorsWindow_p.h
Normal file
108
src/private/indicators/ClassicIndicatorsWindow_p.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KD_INDICATORS_CLASSICINDICATORS_WINDOW_P_H
|
||||||
|
#define KD_INDICATORS_CLASSICINDICATORS_WINDOW_P_H
|
||||||
|
|
||||||
|
#include "DropIndicatorOverlayInterface_p.h"
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
|
||||||
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
class Indicator;
|
||||||
|
class ClassicIndicators;
|
||||||
|
|
||||||
|
class IndicatorWindow : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit IndicatorWindow(ClassicIndicators *classicIndicators);
|
||||||
|
void hover(QPoint globalPos);
|
||||||
|
void updatePositions();
|
||||||
|
QPoint posForIndicator(DropIndicatorOverlayInterface::DropLocation) const;
|
||||||
|
private:
|
||||||
|
void updateIndicatorVisibility();
|
||||||
|
void resizeEvent(QResizeEvent *ev) override;
|
||||||
|
|
||||||
|
// When the compositor doesn't support translucency, we use a mask instead
|
||||||
|
// Only happens on Linux
|
||||||
|
void updateMask();
|
||||||
|
|
||||||
|
Indicator *indicatorForLocation(DropIndicatorOverlayInterface::DropLocation loc) const;
|
||||||
|
|
||||||
|
ClassicIndicators *const classicIndicators;
|
||||||
|
Indicator *const m_center;
|
||||||
|
Indicator *const m_left;
|
||||||
|
Indicator *const m_right;
|
||||||
|
Indicator *const m_bottom;
|
||||||
|
Indicator *const m_top;
|
||||||
|
Indicator *const m_outterLeft;
|
||||||
|
Indicator *const m_outterRight;
|
||||||
|
Indicator *const m_outterBottom;
|
||||||
|
Indicator *const m_outterTop;
|
||||||
|
QVector<Indicator *> m_indicators;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Indicator : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
typedef QList<Indicator *> List;
|
||||||
|
explicit Indicator(ClassicIndicators *classicIndicators, IndicatorWindow *parent,
|
||||||
|
DropIndicatorOverlayInterface::DropLocation location);
|
||||||
|
void paintEvent(QPaintEvent *) override;
|
||||||
|
|
||||||
|
void setHovered(bool hovered);
|
||||||
|
QString iconName(bool active) const;
|
||||||
|
QString iconFileName(bool active) const;
|
||||||
|
|
||||||
|
QImage m_image;
|
||||||
|
QImage m_imageActive;
|
||||||
|
ClassicIndicators *const q;
|
||||||
|
bool m_hovered = false;
|
||||||
|
const DropIndicatorOverlayInterface::DropLocation m_dropLocation;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <QQuickView>
|
||||||
|
|
||||||
|
namespace KDDockWidgets
|
||||||
|
{
|
||||||
|
class ClassicIndicators;
|
||||||
|
|
||||||
|
class IndicatorWindow : public QQuickView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(KDDockWidgets::ClassicIndicators* classicIndicators READ classicIndicators CONSTANT)
|
||||||
|
public:
|
||||||
|
explicit IndicatorWindow(ClassicIndicators *);
|
||||||
|
void hover(QPoint);
|
||||||
|
void updatePositions();
|
||||||
|
QPoint posForIndicator(DropIndicatorOverlayInterface::DropLocation) const;
|
||||||
|
Q_INVOKABLE QString iconName(int loc, bool active) const;
|
||||||
|
KDDockWidgets::ClassicIndicators* classicIndicators() const;
|
||||||
|
private:
|
||||||
|
QQuickItem *indicatorForPos(QPoint) const;
|
||||||
|
QVector<QQuickItem*> indicatorItems() const;
|
||||||
|
ClassicIndicators *const m_classicIndicators;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -12,92 +12,47 @@
|
|||||||
#ifndef KD_INDICATORS_CLASSICINDICATORS_P_H
|
#ifndef KD_INDICATORS_CLASSICINDICATORS_P_H
|
||||||
#define KD_INDICATORS_CLASSICINDICATORS_P_H
|
#define KD_INDICATORS_CLASSICINDICATORS_P_H
|
||||||
|
|
||||||
#include "DropIndicatorOverlayInterface_p.h"
|
#include "../DropIndicatorOverlayInterface_p.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QRubberBand;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class IndicatorWindow;
|
class IndicatorWindow;
|
||||||
class Indicator;
|
class Indicator;
|
||||||
|
|
||||||
class ClassicIndicators : public DropIndicatorOverlayInterface
|
class DOCKS_EXPORT ClassicIndicators : public DropIndicatorOverlayInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(bool innerIndicatorsVisible READ innerIndicatorsVisible NOTIFY innerIndicatorsVisibleChanged)
|
||||||
|
Q_PROPERTY(bool outterIndicatorsVisible READ outterIndicatorsVisible NOTIFY outterIndicatorsVisibleChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ClassicIndicators(DropArea *dropArea);
|
explicit ClassicIndicators(DropArea *dropArea);
|
||||||
~ClassicIndicators() override;
|
~ClassicIndicators() override;
|
||||||
Type indicatorType() const override;
|
void hover_impl(QPoint globalPos) override;
|
||||||
void hover(QPoint globalPos) override;
|
|
||||||
QPoint posForIndicator(DropLocation) const override;
|
QPoint posForIndicator(DropLocation) const override;
|
||||||
|
|
||||||
|
bool innerIndicatorsVisible() const;
|
||||||
|
bool outterIndicatorsVisible() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void showEvent(QShowEvent *) override;
|
bool onResize(QSize newSize) override;
|
||||||
void hideEvent(QHideEvent *) override;
|
|
||||||
void resizeEvent(QResizeEvent *) override;
|
|
||||||
void updateVisibility() override;
|
void updateVisibility() override;
|
||||||
|
Q_SIGNALS:
|
||||||
|
void innerIndicatorsVisibleChanged();
|
||||||
|
void outterIndicatorsVisibleChanged();
|
||||||
private:
|
private:
|
||||||
friend class KDDockWidgets::Indicator;
|
friend class KDDockWidgets::Indicator;
|
||||||
friend class KDDockWidgets::IndicatorWindow;
|
friend class KDDockWidgets::IndicatorWindow;
|
||||||
|
void updateIndicatorsVisibility(bool visible);
|
||||||
void raiseIndicators();
|
void raiseIndicators();
|
||||||
void setDropLocation(DropLocation);
|
void setDropLocation(DropLocation);
|
||||||
QRect geometryForRubberband(QRect localRect) const;
|
void updateWindowPosition();
|
||||||
bool rubberBandIsTopLevel() const;
|
|
||||||
|
|
||||||
QRubberBand *const m_rubberBand;
|
QWidgetOrQuick *const m_rubberBand;
|
||||||
IndicatorWindow *const m_indicatorWindow;
|
IndicatorWindow *const m_indicatorWindow;
|
||||||
};
|
bool m_innerIndicatorsVisible = false;
|
||||||
|
bool m_outterIndicatorsVisible = false;
|
||||||
class IndicatorWindow : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit IndicatorWindow(ClassicIndicators *classicIndicators, QWidget * = nullptr);
|
|
||||||
void hover(QPoint globalPos);
|
|
||||||
|
|
||||||
void updatePosition();
|
|
||||||
void updatePositions();
|
|
||||||
void updateIndicatorVisibility(bool visible);
|
|
||||||
void resizeEvent(QResizeEvent *ev) override;
|
|
||||||
bool event(QEvent *e) override;
|
|
||||||
|
|
||||||
Indicator *indicatorForLocation(DropIndicatorOverlayInterface::DropLocation loc) const;
|
|
||||||
|
|
||||||
// When the compositor doesn't support translucency, we use a mask instead
|
|
||||||
// Only happens on Linux
|
|
||||||
void updateMask();
|
|
||||||
|
|
||||||
ClassicIndicators *const classicIndicators;
|
|
||||||
Indicator *const m_center;
|
|
||||||
Indicator *const m_left;
|
|
||||||
Indicator *const m_right;
|
|
||||||
Indicator *const m_bottom;
|
|
||||||
Indicator *const m_top;
|
|
||||||
Indicator *const m_outterLeft;
|
|
||||||
Indicator *const m_outterRight;
|
|
||||||
Indicator *const m_outterBottom;
|
|
||||||
Indicator *const m_outterTop;
|
|
||||||
QVector<Indicator *> m_indicators;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Indicator : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
typedef QList<Indicator *> List;
|
|
||||||
explicit Indicator(ClassicIndicators *classicIndicators, IndicatorWindow *parent, ClassicIndicators::DropLocation location);
|
|
||||||
void paintEvent(QPaintEvent *) override;
|
|
||||||
|
|
||||||
void setHovered(bool hovered);
|
|
||||||
QString iconName(bool active) const;
|
|
||||||
QString iconFileName(bool active) const;
|
|
||||||
|
|
||||||
QImage m_image;
|
|
||||||
QImage m_imageActive;
|
|
||||||
ClassicIndicators *const q;
|
|
||||||
bool m_hovered = false;
|
|
||||||
const ClassicIndicators::DropLocation m_dropLocation;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
182
src/private/indicators/SegmentedIndicators.cpp
Normal file
182
src/private/indicators/SegmentedIndicators.cpp
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SegmentedIndicators_p.h"
|
||||||
|
#include "DropArea_p.h"
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPainterPath>
|
||||||
|
|
||||||
|
#define SEGMENT_GIRTH 50
|
||||||
|
#define SEGMENT_PEN_WIDTH 4
|
||||||
|
|
||||||
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
|
||||||
|
SegmentedIndicators::SegmentedIndicators(DropArea *dropArea)
|
||||||
|
: DropIndicatorOverlayInterface(dropArea)
|
||||||
|
{
|
||||||
|
// If the app didn't choose opacity then we choose a suitable default value.
|
||||||
|
// ClassicIndicators works fine with an opaque dragged window because the indicators have higher Z,
|
||||||
|
// However for SegmentedIndicators the indicators are in the main window, so lower Z. Make the
|
||||||
|
// dragged window translucent a bit, so we can see the indicators
|
||||||
|
const bool userChoseOpacity = !qIsNaN(Config::self().draggedWindowOpacity());
|
||||||
|
if (!userChoseOpacity)
|
||||||
|
Config::self().setDraggedWindowOpacity(0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
SegmentedIndicators::~SegmentedIndicators()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SegmentedIndicators::hover_impl(QPoint pt)
|
||||||
|
{
|
||||||
|
m_hoveredPt = mapFromGlobal(pt);
|
||||||
|
updateSegments();
|
||||||
|
setCurrentDropLocation(dropLocationForPos(m_hoveredPt));
|
||||||
|
}
|
||||||
|
|
||||||
|
DropIndicatorOverlayInterface::DropLocation SegmentedIndicators::dropLocationForPos(QPoint pos) const
|
||||||
|
{
|
||||||
|
for (auto it = m_segments.cbegin(), end = m_segments.cend(); it != end; ++it) {
|
||||||
|
if (it.value().containsPoint(pos, Qt::OddEvenFill)) {
|
||||||
|
return it.key();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DropLocation_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SegmentedIndicators::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
p.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
drawSegments(&p);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QPolygon> SegmentedIndicators::segmentsForRect(QRect r, QPolygon ¢er, bool useOffset) const
|
||||||
|
{
|
||||||
|
const int penWidth = SEGMENT_PEN_WIDTH;
|
||||||
|
const int halfPenWidth = penWidth / 2;
|
||||||
|
|
||||||
|
const int l = SEGMENT_GIRTH;
|
||||||
|
const int top = (r.y() == 0 && useOffset) ? l : r.y();
|
||||||
|
const int left = (r.x() == 0 && useOffset) ? l : r.x();
|
||||||
|
const int right = (rect().right() == r.right() && useOffset) ? r.right() - l : r.right();
|
||||||
|
const int bottom = (rect().bottom() == r.bottom() && useOffset) ? r.bottom() - l : r.bottom();
|
||||||
|
const QPoint topLeft = { left + halfPenWidth, top + halfPenWidth };
|
||||||
|
const QPoint topRight = { right, top + halfPenWidth };
|
||||||
|
const QPoint bottomLeft = { left + halfPenWidth, bottom };
|
||||||
|
const QPoint bottomRight = { right, bottom };
|
||||||
|
|
||||||
|
const QVector<QPoint> leftPoints = { topLeft, bottomLeft,
|
||||||
|
QPoint(left, bottom) + QPoint(l, -l),
|
||||||
|
topLeft + QPoint(l, l), topLeft
|
||||||
|
};
|
||||||
|
|
||||||
|
const QVector<QPoint> rightPoints = { topRight, bottomRight,
|
||||||
|
bottomRight + QPoint(-l, -l),
|
||||||
|
topRight + QPoint(-l, l)
|
||||||
|
};
|
||||||
|
|
||||||
|
const QVector<QPoint> topPoints = { topLeft, topRight,
|
||||||
|
topRight + QPoint(-l, l),
|
||||||
|
topLeft + QPoint(l, l)
|
||||||
|
};
|
||||||
|
|
||||||
|
const QVector<QPoint> bottomPoints = { bottomLeft, bottomRight,
|
||||||
|
bottomRight + QPoint(-l, -l),
|
||||||
|
bottomLeft + QPoint(l, -l)
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
QPolygon bounds = QVector<QPoint> { topLeft + QPoint(l, l),
|
||||||
|
topRight + QPoint(-l, l),
|
||||||
|
bottomRight + QPoint(-l, -l),
|
||||||
|
bottomLeft + QPoint(l, -l)
|
||||||
|
};
|
||||||
|
const int maxWidth = bounds.boundingRect().width();
|
||||||
|
const QPoint centerPos = bounds.boundingRect().center();
|
||||||
|
|
||||||
|
// Build the center
|
||||||
|
const int indicatorWidth = qMin(300, maxWidth - 100);
|
||||||
|
const int indicatorHeight = qMin(160, int(indicatorWidth * 0.60));
|
||||||
|
const int tabWidth = int(indicatorWidth * 0.267);
|
||||||
|
const int tabHeight = int(indicatorHeight * 0.187);
|
||||||
|
const int centerRectLeft = centerPos.x() - indicatorWidth / 2;
|
||||||
|
const int centerRectRight = centerPos.x() + indicatorWidth / 2;
|
||||||
|
const int centerRectBottom = centerPos.y() + indicatorHeight / 2;
|
||||||
|
const int centerRectTop = centerPos.y() - indicatorHeight / 2;
|
||||||
|
|
||||||
|
|
||||||
|
center = QVector<QPoint> { { centerRectLeft, centerRectTop },
|
||||||
|
{ centerRectLeft + tabWidth, centerRectTop },
|
||||||
|
{ centerRectLeft + tabWidth, centerRectTop + tabHeight },
|
||||||
|
{ centerRectRight, centerRectTop + tabHeight },
|
||||||
|
{ centerRectRight, centerRectBottom },
|
||||||
|
{ centerRectLeft, centerRectBottom },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { leftPoints, topPoints, rightPoints, bottomPoints };
|
||||||
|
}
|
||||||
|
|
||||||
|
void SegmentedIndicators::updateSegments()
|
||||||
|
{
|
||||||
|
m_segments.clear();
|
||||||
|
|
||||||
|
const bool hasMultipleFrames = m_dropArea->count() > 1;
|
||||||
|
const bool needsInnerIndicators = hoveredFrameRect().isValid();
|
||||||
|
const bool needsOutterIndicators = hasMultipleFrames || !needsInnerIndicators;
|
||||||
|
QPolygon center;
|
||||||
|
|
||||||
|
if (needsInnerIndicators) {
|
||||||
|
const bool useOffset = needsOutterIndicators;
|
||||||
|
auto segments = segmentsForRect(hoveredFrameRect(), /*by-ref*/center, useOffset);
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
m_segments.insert(DropLocation(DropLocation_Left + i), segments[i]);
|
||||||
|
|
||||||
|
m_segments.insert(DropLocation_Center, center);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsOutterIndicators) {
|
||||||
|
auto segments = segmentsForRect(rect(), /*unused*/center);
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
m_segments.insert(DropLocation(DropLocation_OutterLeft + i), segments[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SegmentedIndicators::drawSegments(QPainter *p)
|
||||||
|
{
|
||||||
|
for (int i = DropLocation_First; i <= DropLocation_Last; ++i)
|
||||||
|
drawSegment(p, m_segments.value(DropLocation(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SegmentedIndicators::drawSegment(QPainter *p, const QPolygon &segment)
|
||||||
|
{
|
||||||
|
if (segment.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPen pen(Qt::black);
|
||||||
|
pen.setWidth(SEGMENT_PEN_WIDTH);
|
||||||
|
p->setPen(pen);
|
||||||
|
QColor brush(0xbb, 0xd5, 0xee, 200);
|
||||||
|
|
||||||
|
if (segment.containsPoint(m_hoveredPt, Qt::OddEvenFill))
|
||||||
|
brush = QColor(0x3574c5);
|
||||||
|
|
||||||
|
p->setBrush(brush);
|
||||||
|
p->drawPolygon(segment);
|
||||||
|
}
|
||||||
46
src/private/indicators/SegmentedIndicators_p.h
Normal file
46
src/private/indicators/SegmentedIndicators_p.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KD_SEGMENTED_INDICATORS_P_H
|
||||||
|
#define KD_SEGMENTED_INDICATORS_P_H
|
||||||
|
|
||||||
|
#include "../DropIndicatorOverlayInterface_p.h"
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
#include <QPolygon>
|
||||||
|
|
||||||
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
class DOCKS_EXPORT SegmentedIndicators : public DropIndicatorOverlayInterface
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SegmentedIndicators(DropArea *dropArea);
|
||||||
|
~SegmentedIndicators() override;
|
||||||
|
void hover_impl(QPoint globalPos) override;
|
||||||
|
|
||||||
|
DropLocation dropLocationForPos(QPoint pos) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<QPolygon> segmentsForRect(QRect, QPolygon ¢er, bool useOffset = false) const;
|
||||||
|
void updateSegments();
|
||||||
|
void drawSegments(QPainter *p);
|
||||||
|
void drawSegment(QPainter *p, const QPolygon &segment);
|
||||||
|
QPoint m_hoveredPt = {};
|
||||||
|
QHash<DropLocation, QPolygon> m_segments;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -70,8 +70,6 @@ public:
|
|||||||
virtual void show() = 0;
|
virtual void show() = 0;
|
||||||
virtual void hide() = 0;
|
virtual void hide() = 0;
|
||||||
virtual void update() = 0;
|
virtual void update() = 0;
|
||||||
virtual QPoint mapFromGlobal(QPoint) const = 0;
|
|
||||||
virtual QPoint mapToGlobal(QPoint) const = 0;
|
|
||||||
|
|
||||||
QSize size() const {
|
QSize size() const {
|
||||||
return geometry().size();
|
return geometry().size();
|
||||||
|
|||||||
@@ -121,18 +121,6 @@ void Widget_quick::update()
|
|||||||
m_thisWidget->update();
|
m_thisWidget->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint Widget_quick::mapFromGlobal(QPoint p) const
|
|
||||||
{
|
|
||||||
qWarning() << Q_FUNC_INFO << "Implement me!";
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPoint Widget_quick::mapToGlobal(QPoint p) const
|
|
||||||
{
|
|
||||||
qWarning() << Q_FUNC_INFO << "Implement me!";
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
QQuickItem *Widget_quick::createQQuickItem(const QString &filename, QQuickItem *parent) const
|
QQuickItem *Widget_quick::createQQuickItem(const QString &filename, QQuickItem *parent) const
|
||||||
{
|
{
|
||||||
auto p = parent;
|
auto p = parent;
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
|
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
class QQuickItem;
|
class QQuickItem;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
///@file
|
///@file
|
||||||
///@brief A Layouting::Widget that's deals in QQuickItem
|
///@brief A Layouting::Widget that's deals in QQuickItem
|
||||||
@@ -52,8 +54,6 @@ public:
|
|||||||
void setWidth(int width) override;
|
void setWidth(int width) override;
|
||||||
void setHeight(int height) override;
|
void setHeight(int height) override;
|
||||||
void update() override;
|
void update() override;
|
||||||
QPoint mapFromGlobal(QPoint p) const override;
|
|
||||||
QPoint mapToGlobal(QPoint p) const override;
|
|
||||||
|
|
||||||
static QSize widgetMinSize(const QWidget *w);
|
static QSize widgetMinSize(const QWidget *w);
|
||||||
|
|
||||||
|
|||||||
@@ -121,13 +121,3 @@ void Widget_qwidget::update()
|
|||||||
{
|
{
|
||||||
m_thisWidget->update();
|
m_thisWidget->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint Widget_qwidget::mapFromGlobal(QPoint p) const
|
|
||||||
{
|
|
||||||
return m_thisWidget->mapFromGlobal(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPoint Widget_qwidget::mapToGlobal(QPoint p) const
|
|
||||||
{
|
|
||||||
return m_thisWidget->mapToGlobal(p);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -55,8 +55,6 @@ public:
|
|||||||
void setWidth(int width) override;
|
void setWidth(int width) override;
|
||||||
void setHeight(int height) override;
|
void setHeight(int height) override;
|
||||||
void update() override;
|
void update() override;
|
||||||
QPoint mapFromGlobal(QPoint p) const override;
|
|
||||||
QPoint mapToGlobal(QPoint p) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget *const m_thisWidget;
|
QWidget *const m_thisWidget;
|
||||||
|
|||||||
@@ -22,17 +22,36 @@
|
|||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
class QuickView : public QQuickView
|
||||||
|
{
|
||||||
|
using QQuickView::QQuickView;
|
||||||
|
|
||||||
|
bool event(QEvent *ev) override
|
||||||
|
{
|
||||||
|
if (ev->type() == QEvent::FocusAboutToChange) {
|
||||||
|
// qquickwindow.cpp::event(FocusAboutToChange) removes the item grabber. Inibit that
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QQuickView::event(ev);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FloatingWindowQuick::FloatingWindowQuick(MainWindowBase *parent)
|
FloatingWindowQuick::FloatingWindowQuick(MainWindowBase *parent)
|
||||||
: FloatingWindow(parent)
|
: FloatingWindow(parent)
|
||||||
, m_quickWindow(new QQuickView(Config::self().qmlEngine(), nullptr))
|
, m_quickWindow(new QuickView(Config::self().qmlEngine(), nullptr))
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingWindowQuick::FloatingWindowQuick(Frame *frame, MainWindowBase *parent)
|
FloatingWindowQuick::FloatingWindowQuick(Frame *frame, MainWindowBase *parent)
|
||||||
: FloatingWindow(frame, parent)
|
: FloatingWindow(frame, parent)
|
||||||
, m_quickWindow(new QQuickView(Config::self().qmlEngine(), nullptr))
|
, m_quickWindow(new QuickView(Config::self().qmlEngine(), nullptr))
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
MainWindowQuick::MainWindowQuick(const QString &uniqueName, QWidgetAdapter *parent)
|
MainWindowQuick::MainWindowQuick(const QString &uniqueName, MainWindowOptions options,
|
||||||
: MainWindowBase(uniqueName, MainWindowOption_None, parent)
|
QWidgetAdapter *parent)
|
||||||
|
: MainWindowBase(uniqueName, options, parent)
|
||||||
{
|
{
|
||||||
QWidgetAdapter::makeItemFillParent(this);
|
QWidgetAdapter::makeItemFillParent(this);
|
||||||
QWidgetAdapter::makeItemFillParent(dropArea());
|
QWidgetAdapter::makeItemFillParent(dropArea());
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ class DOCKS_EXPORT MainWindowQuick : public MainWindowBase
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit MainWindowQuick(const QString &uniqueName, QWidgetAdapter *parent);
|
explicit MainWindowQuick(const QString &uniqueName,
|
||||||
|
MainWindowOptions options = MainWindowOption_HasCentralFrame,
|
||||||
|
QWidgetAdapter *parent = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,5 +31,5 @@ void MainWindowWrapper::init(const QString &uniqueName)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mainWindow = new MainWindowQuick(uniqueName, this);
|
m_mainWindow = new MainWindowQuick(uniqueName, MainWindowOption_None, this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,12 @@ void QWidgetAdapter::raiseAndActivate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QWidgetAdapter::setWindowOpacity(qreal level)
|
||||||
|
{
|
||||||
|
if (QWindow *w = windowHandle())
|
||||||
|
w->setOpacity(level);
|
||||||
|
}
|
||||||
|
|
||||||
bool QWidgetAdapter::onResize(QSize) { return false; }
|
bool QWidgetAdapter::onResize(QSize) { return false; }
|
||||||
void QWidgetAdapter::onLayoutRequest() {}
|
void QWidgetAdapter::onLayoutRequest() {}
|
||||||
void QWidgetAdapter::onMousePress() {}
|
void QWidgetAdapter::onMousePress() {}
|
||||||
@@ -176,6 +182,14 @@ bool QWidgetAdapter::isMaximized() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KDDockWidgets::QWidgetAdapter::isActiveWindow() const
|
||||||
|
{
|
||||||
|
if (QWindow *w = windowHandle())
|
||||||
|
return w->isActive();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void QWidgetAdapter::showMaximized()
|
void QWidgetAdapter::showMaximized()
|
||||||
{
|
{
|
||||||
if (QWindow *w = windowHandle())
|
if (QWindow *w = windowHandle())
|
||||||
@@ -216,6 +230,28 @@ QWidgetAdapter *QWidgetAdapter::parentWidget() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPoint QWidgetAdapter::mapToGlobal(QPoint pt) const
|
||||||
|
{
|
||||||
|
return QQuickItem::mapToGlobal(pt).toPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint QWidgetAdapter::mapFromGlobal(QPoint pt) const
|
||||||
|
{
|
||||||
|
return QQuickItem::mapFromGlobal(pt).toPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWidgetAdapter::setWindowTitle(const QString &title)
|
||||||
|
{
|
||||||
|
if (QWindow *window = windowHandle())
|
||||||
|
window->setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWidgetAdapter::setWindowIcon(const QIcon &icon)
|
||||||
|
{
|
||||||
|
if (QWindow *window = windowHandle())
|
||||||
|
window->setIcon(icon);
|
||||||
|
}
|
||||||
|
|
||||||
void QWidgetAdapter::close()
|
void QWidgetAdapter::close()
|
||||||
{
|
{
|
||||||
QCloseEvent ev;
|
QCloseEvent ev;
|
||||||
@@ -323,6 +359,16 @@ void QWidgetAdapter::setFlag(Qt::WindowType f, bool on)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::FocusPolicy QWidgetAdapter::focusPolicy() const
|
||||||
|
{
|
||||||
|
return Qt::NoFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWidgetAdapter::setFocusProxy(QQuickItem *)
|
||||||
|
{
|
||||||
|
qWarning() << Q_FUNC_INFO << "Implement me";
|
||||||
|
}
|
||||||
|
|
||||||
QQuickItem* KDDockWidgets::Private::widgetForWindow(QWindow *window)
|
QQuickItem* KDDockWidgets::Private::widgetForWindow(QWindow *window)
|
||||||
{
|
{
|
||||||
if (!window)
|
if (!window)
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ public:
|
|||||||
QRect geometry() const;
|
QRect geometry() const;
|
||||||
QRect rect() const;
|
QRect rect() const;
|
||||||
void show();
|
void show();
|
||||||
void setEnabled(bool) {}
|
|
||||||
void setFixedHeight(int);
|
void setFixedHeight(int);
|
||||||
void setFixedWidth(int);
|
void setFixedWidth(int);
|
||||||
void raise();
|
void raise();
|
||||||
@@ -114,18 +113,19 @@ public:
|
|||||||
void resize(QSize);
|
void resize(QSize);
|
||||||
bool isWindow() const { return parentItem() == nullptr; }
|
bool isWindow() const { return parentItem() == nullptr; }
|
||||||
bool isMaximized() const;
|
bool isMaximized() const;
|
||||||
|
bool isActiveWindow() const;
|
||||||
void showMaximized();
|
void showMaximized();
|
||||||
void showNormal();
|
void showNormal();
|
||||||
|
|
||||||
QWindow *windowHandle() const;
|
QWindow *windowHandle() const;
|
||||||
QWidgetAdapter *window() const;
|
QWidgetAdapter *window() const;
|
||||||
QWidgetAdapter *parentWidget() const;
|
QWidgetAdapter *parentWidget() const;
|
||||||
QPoint mapToGlobal(QPoint) const { return {}; }
|
QPoint mapToGlobal(QPoint pt) const;
|
||||||
QPoint mapFromGlobal(QPoint) const { return {}; }
|
QPoint mapFromGlobal(QPoint) const;
|
||||||
bool testAttribute(Qt::WidgetAttribute) { return false; }
|
bool testAttribute(Qt::WidgetAttribute) { return false; }
|
||||||
|
|
||||||
void setWindowTitle(const QString &) {}
|
void setWindowTitle(const QString &);
|
||||||
void setWindowIcon(const QIcon &) {}
|
void setWindowIcon(const QIcon &);
|
||||||
void close();
|
void close();
|
||||||
QQuickItem *childAt(QPoint) const;
|
QQuickItem *childAt(QPoint) const;
|
||||||
void move(int x, int y);
|
void move(int x, int y);
|
||||||
@@ -134,9 +134,13 @@ public:
|
|||||||
void activateWindow();
|
void activateWindow();
|
||||||
void setSizePolicy(QSizePolicy);
|
void setSizePolicy(QSizePolicy);
|
||||||
QSizePolicy sizePolicy() const;
|
QSizePolicy sizePolicy() const;
|
||||||
|
Qt::FocusPolicy focusPolicy() const;
|
||||||
|
void setFocusPolicy(Qt::FocusPolicy) {}
|
||||||
|
void setFocusProxy(QQuickItem*);
|
||||||
virtual QSize sizeHint() const;
|
virtual QSize sizeHint() const;
|
||||||
|
|
||||||
Qt::WindowFlags windowFlags() const;
|
Qt::WindowFlags windowFlags() const;
|
||||||
|
void setWindowOpacity(qreal);
|
||||||
|
|
||||||
static QQuickItem *createItem(QQmlEngine *, const QString &filename);
|
static QQuickItem *createItem(QQmlEngine *, const QString &filename);
|
||||||
static void makeItemFillParent(QQuickItem *item);
|
static void makeItemFillParent(QQuickItem *item);
|
||||||
|
|||||||
@@ -12,7 +12,9 @@
|
|||||||
#include "QmlTypes.h"
|
#include "QmlTypes.h"
|
||||||
#include "DropAreaWithCentralFrame_p.h"
|
#include "DropAreaWithCentralFrame_p.h"
|
||||||
#include "quick/MainWindowWrapper_p.h"
|
#include "quick/MainWindowWrapper_p.h"
|
||||||
|
#include "DropIndicatorOverlayInterface_p.h"
|
||||||
#include "TitleBar_p.h"
|
#include "TitleBar_p.h"
|
||||||
|
#include "indicators/ClassicIndicators_p.h"
|
||||||
|
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -24,5 +26,8 @@ void KDDockWidgets::registerQmlTypes()
|
|||||||
qmlRegisterType<MainWindowWrapper>("com.kdab.dockwidgets", 1, 0, "MainWindow");
|
qmlRegisterType<MainWindowWrapper>("com.kdab.dockwidgets", 1, 0, "MainWindow");
|
||||||
|
|
||||||
qmlRegisterUncreatableType<TitleBar>("com.kdab.dockwidgets", 1, 0, "TitleBar", QStringLiteral("Enum access only"));
|
qmlRegisterUncreatableType<TitleBar>("com.kdab.dockwidgets", 1, 0, "TitleBar", QStringLiteral("Enum access only"));
|
||||||
|
qmlRegisterUncreatableType<DropIndicatorOverlayInterface>("com.kdab.dockwidgets", 1, 0, "DropIndicatorOverlayInterface", QStringLiteral("Enum access only"));
|
||||||
|
|
||||||
qRegisterMetaType<DropArea*>();
|
qRegisterMetaType<DropArea*>();
|
||||||
|
qRegisterMetaType<KDDockWidgets::ClassicIndicators*>();
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/private/quick/qml/ClassicIndicator.qml
Normal file
13
src/private/quick/qml/ClassicIndicator.qml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import com.kdab.dockwidgets 1.0
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int indicatorType: DropIndicatorOverlayInterface.DropLocation_None
|
||||||
|
readonly property bool isHovered: _window.classicIndicators.currentDropLocation === indicatorType
|
||||||
|
|
||||||
|
source: "qrc:/img/classic_indicators/" + _window.iconName(indicatorType, isHovered) + ".png";
|
||||||
|
width: 64
|
||||||
|
height: 64
|
||||||
|
}
|
||||||
115
src/private/quick/qml/ClassicIndicatorsOverlay.qml
Normal file
115
src/private/quick/qml/ClassicIndicatorsOverlay.qml
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
import com.kdab.dockwidgets 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
anchors.fill: parent
|
||||||
|
readonly property int outterMargin: 10
|
||||||
|
readonly property int innerMargin: 10
|
||||||
|
readonly property QtObject innerIndicators: innerIndicators
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
visible: _window.classicIndicators.outterIndicatorsVisible
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_OutterLeft
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: outterMargin
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
visible: _window.classicIndicators.outterIndicatorsVisible
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_OutterRight
|
||||||
|
anchors {
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: outterMargin
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
visible: _window.classicIndicators.outterIndicatorsVisible
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_OutterTop
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
topMargin: outterMargin
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
visible: _window.classicIndicators.outterIndicatorsVisible
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_OutterBottom
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: outterMargin
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: innerIndicators
|
||||||
|
objectName: "innerIndicators"
|
||||||
|
|
||||||
|
x: _window.classicIndicators.hoveredFrameRect.x + (_window.classicIndicators.hoveredFrameRect.width / 2)
|
||||||
|
y: _window.classicIndicators.hoveredFrameRect.y + (_window.classicIndicators.hoveredFrameRect.height / 2)
|
||||||
|
|
||||||
|
width: (centerIndicator * 3) + (2 * innerMargin)
|
||||||
|
height: width
|
||||||
|
visible: _window.classicIndicators.innerIndicatorsVisible
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_Left
|
||||||
|
anchors {
|
||||||
|
right: centerIndicator.left
|
||||||
|
rightMargin: innerMargin
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
id: centerIndicator
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_Center
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_Right
|
||||||
|
anchors {
|
||||||
|
left: centerIndicator.right
|
||||||
|
leftMargin: innerMargin
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_Top
|
||||||
|
anchors {
|
||||||
|
bottom: centerIndicator.top
|
||||||
|
bottomMargin: innerMargin
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassicIndicator {
|
||||||
|
indicatorType: DropIndicatorOverlayInterface.DropLocation_Bottom
|
||||||
|
anchors {
|
||||||
|
top: centerIndicator.bottom
|
||||||
|
topMargin: innerMargin
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -172,7 +172,7 @@ void TabWidget::insertDockWidget(DockWidgetBase *dock, int index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPointer<Frame> oldFrame = dock->frame();
|
QPointer<Frame> oldFrame = dock->frame();
|
||||||
insertDockWidget(index, dock, dock->icon(), dock->title());
|
insertDockWidget(index, dock, dock->icon(DockWidgetBase::IconPlace::TabBar), dock->title());
|
||||||
setCurrentDockWidget(index);
|
setCurrentDockWidget(index);
|
||||||
|
|
||||||
if (oldFrame && oldFrame->beingDeletedLater()) {
|
if (oldFrame && oldFrame->beingDeletedLater()) {
|
||||||
|
|||||||
@@ -7,5 +7,7 @@
|
|||||||
<file>private/quick/qml/Separator.qml</file>
|
<file>private/quick/qml/Separator.qml</file>
|
||||||
<file>private/quick/qml/TitleBarBase.qml</file>
|
<file>private/quick/qml/TitleBarBase.qml</file>
|
||||||
<file>private/quick/qml/TitleBar.qml</file>
|
<file>private/quick/qml/TitleBar.qml</file>
|
||||||
|
<file>private/quick/qml/ClassicIndicatorsOverlay.qml</file>
|
||||||
|
<file>private/quick/qml/ClassicIndicator.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Testing.h"
|
#include "Testing.h"
|
||||||
#include "MainWindow.h"
|
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|||||||
@@ -14,12 +14,15 @@
|
|||||||
|
|
||||||
#include "Testing.h"
|
#include "Testing.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "DockWidgetBase.h"
|
||||||
|
#include "private/MultiSplitter_p.h"
|
||||||
|
|
||||||
#include <QtTest/QtTest>
|
#include <QtTest/QtTest>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
using namespace KDDockWidgets::Tests;
|
||||||
|
|
||||||
class TestCommon : public QObject
|
class TestCommon : public QObject
|
||||||
{
|
{
|
||||||
@@ -43,7 +46,10 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
void TestCommon::tst_simple1()
|
void TestCommon::tst_simple1()
|
||||||
{
|
{
|
||||||
// TODO
|
// Simply create a MainWindow
|
||||||
|
EnsureTopLevelsDeleted e;
|
||||||
|
auto m = createMainWindow();
|
||||||
|
m->multiSplitter()->checkSanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QStyleFactory>
|
#include <QStyleFactory>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
# include <Windows.h>
|
# include <Windows.h>
|
||||||
@@ -266,42 +267,6 @@ static QWidget *createWidget(int minLength, const QString &objname = QString())
|
|||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EnsureTopLevelsDeleted
|
|
||||||
{
|
|
||||||
EnsureTopLevelsDeleted()
|
|
||||||
: m_originalFlags(Config::self().flags())
|
|
||||||
, m_originalSeparatorThickness(Config::self().separatorThickness())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~EnsureTopLevelsDeleted()
|
|
||||||
{
|
|
||||||
if (topLevels().size() != 0) {
|
|
||||||
qWarning() << "There's still top-level widgets present!" << topLevels();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other cleanup, since we use this class everywhere
|
|
||||||
Config::self().setDockWidgetFactoryFunc(nullptr);
|
|
||||||
Config::self().setFlags(m_originalFlags);
|
|
||||||
Config::self().setSeparatorThickness(m_originalSeparatorThickness);
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidgetList topLevels() const
|
|
||||||
{
|
|
||||||
QWidgetList result;
|
|
||||||
|
|
||||||
for (QWidget *w : qApp->topLevelWidgets()) {
|
|
||||||
if (!qobject_cast<QToolButton*>(w))
|
|
||||||
result << w;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Config::Flags m_originalFlags;
|
|
||||||
const int m_originalSeparatorThickness;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TestDocks : public QObject
|
class TestDocks : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -323,7 +288,6 @@ public:
|
|||||||
static void nestDockWidget(DockWidgetBase *dock, DropArea *dropArea, Frame *relativeTo, KDDockWidgets::Location location);
|
static void nestDockWidget(DockWidgetBase *dock, DropArea *dropArea, Frame *relativeTo, KDDockWidgets::Location location);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void tst_simple1();
|
|
||||||
void tst_simple2();
|
void tst_simple2();
|
||||||
void tst_shutdown();
|
void tst_shutdown();
|
||||||
void tst_mainWindowAlwaysHasCentralWidget();
|
void tst_mainWindowAlwaysHasCentralWidget();
|
||||||
@@ -463,7 +427,8 @@ private Q_SLOTS:
|
|||||||
void tst_maximumSizePolicy();
|
void tst_maximumSizePolicy();
|
||||||
void tst_tabsNotClickable();
|
void tst_tabsNotClickable();
|
||||||
void tst_stuckSeparator();
|
void tst_stuckSeparator();
|
||||||
void setWidget();
|
void tst_isFocused();
|
||||||
|
void tst_setWidget();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<MultiSplitter> createMultiSplitterFromSetup(MultiSplitterSetup setup, QHash<QWidget *, Frame *> &frameMap) const;
|
std::unique_ptr<MultiSplitter> createMultiSplitterFromSetup(MultiSplitterSetup setup, QHash<QWidget *, Frame *> &frameMap) const;
|
||||||
@@ -584,7 +549,7 @@ DockWidgetBase *createAndNestDockWidget(DropArea *dropArea, Frame *relativeTo, K
|
|||||||
return dock;
|
return dock;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<MainWindow> createSimpleNestedMainWindow(DockWidgetBase * *centralDock, DockWidgetBase * *leftDock, DockWidgetBase * *rightDock)
|
std::unique_ptr<MainWindowBase> createSimpleNestedMainWindow(DockWidgetBase * *centralDock, DockWidgetBase * *leftDock, DockWidgetBase * *rightDock)
|
||||||
{
|
{
|
||||||
auto window = createMainWindow({900, 500});
|
auto window = createMainWindow({900, 500});
|
||||||
*centralDock = createDockWidget("centralDock", Qt::green);
|
*centralDock = createDockWidget("centralDock", Qt::green);
|
||||||
@@ -661,7 +626,7 @@ void TestDocks::tst_dock2FloatingWidgetsTabbed()
|
|||||||
QTest::qWait(1000); // Test is flaky otherwise
|
QTest::qWait(1000); // Test is flaky otherwise
|
||||||
|
|
||||||
auto fw2 = dock2->floatingWindow();
|
auto fw2 = dock2->floatingWindow();
|
||||||
drag(fw2->titleBar(), static_cast<Layouting::Widget*>(frame2)->mapToGlobal(QPoint(10, 10)), dock3->window()->geometry().center());
|
drag(fw2->titleBar(), frame2->mapToGlobal(QPoint(10, 10)), dock3->window()->geometry().center());
|
||||||
|
|
||||||
QVERIFY(Testing::waitForDeleted(frame1));
|
QVERIFY(Testing::waitForDeleted(frame1));
|
||||||
QVERIFY(Testing::waitForDeleted(frame2));
|
QVERIFY(Testing::waitForDeleted(frame2));
|
||||||
@@ -810,7 +775,7 @@ void TestDocks::tst_close()
|
|||||||
// 2. Test that closing the single frame of a main window doesn't close the main window itself
|
// 2. Test that closing the single frame of a main window doesn't close the main window itself
|
||||||
{
|
{
|
||||||
auto m = createMainWindow(QSize(800, 500), MainWindowOption_None); // Remove central frame
|
auto m = createMainWindow(QSize(800, 500), MainWindowOption_None); // Remove central frame
|
||||||
QPointer<MainWindow> mainWindowPtr = m.get();
|
QPointer<MainWindowBase> mainWindowPtr = m.get();
|
||||||
dock1 = createDockWidget("hello", Qt::green);
|
dock1 = createDockWidget("hello", Qt::green);
|
||||||
m->addDockWidget(dock1, Location_OnLeft);
|
m->addDockWidget(dock1, Location_OnLeft);
|
||||||
|
|
||||||
@@ -823,7 +788,7 @@ void TestDocks::tst_close()
|
|||||||
// 2.1 Test closing the frame instead
|
// 2.1 Test closing the frame instead
|
||||||
{
|
{
|
||||||
auto m = createMainWindow(QSize(800, 500), MainWindowOption_None); // Remove central frame
|
auto m = createMainWindow(QSize(800, 500), MainWindowOption_None); // Remove central frame
|
||||||
QPointer<MainWindow> mainWindowPtr = m.get();
|
QPointer<MainWindowBase> mainWindowPtr = m.get();
|
||||||
dock1 = createDockWidget("hello", Qt::green);
|
dock1 = createDockWidget("hello", Qt::green);
|
||||||
m->addDockWidget(dock1, Location_OnLeft);
|
m->addDockWidget(dock1, Location_OnLeft);
|
||||||
|
|
||||||
@@ -837,7 +802,7 @@ void TestDocks::tst_close()
|
|||||||
// 2.2 Repeat, but with a central frame
|
// 2.2 Repeat, but with a central frame
|
||||||
{
|
{
|
||||||
auto m = createMainWindow(QSize(800, 500));
|
auto m = createMainWindow(QSize(800, 500));
|
||||||
QPointer<MainWindow> mainWindowPtr = m.get();
|
QPointer<MainWindowBase> mainWindowPtr = m.get();
|
||||||
dock1 = createDockWidget("hello", Qt::green);
|
dock1 = createDockWidget("hello", Qt::green);
|
||||||
m->addDockWidget(dock1, Location_OnLeft);
|
m->addDockWidget(dock1, Location_OnLeft);
|
||||||
|
|
||||||
@@ -2579,14 +2544,6 @@ void TestDocks::tst_setVisibleFalseWhenSideBySide()
|
|||||||
Testing::waitForDeleted(window);
|
Testing::waitForDeleted(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDocks::tst_simple1()
|
|
||||||
{
|
|
||||||
// Simply create a MainWindow
|
|
||||||
EnsureTopLevelsDeleted e;
|
|
||||||
auto m = createMainWindow();
|
|
||||||
m->multiSplitter()->checkSanity();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestDocks::tst_simple2()
|
void TestDocks::tst_simple2()
|
||||||
{
|
{
|
||||||
// Simply create a MainWindow, and dock something on top
|
// Simply create a MainWindow, and dock something on top
|
||||||
@@ -5259,6 +5216,50 @@ void TestDocks::tst_floatingAction()
|
|||||||
|
|
||||||
Testing::waitForDeleted(fw);
|
Testing::waitForDeleted(fw);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// 3. A floating window with two tabs
|
||||||
|
auto dock1 = createDockWidget("dock1", new QPushButton("one"));
|
||||||
|
auto dock2 = createDockWidget("dock2", new QPushButton("two"));
|
||||||
|
|
||||||
|
bool dock1IsFloating = dock1->floatAction()->isChecked();
|
||||||
|
bool dock2IsFloating = dock2->floatAction()->isChecked();
|
||||||
|
|
||||||
|
connect(dock1->floatAction(), &QAction::toggled, [&dock1IsFloating] (bool t) {
|
||||||
|
Q_ASSERT(dock1IsFloating != t);
|
||||||
|
dock1IsFloating = t;
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(dock2->floatAction(), &QAction::toggled, [&dock2IsFloating] (bool t) {
|
||||||
|
Q_ASSERT(dock2IsFloating != t);
|
||||||
|
dock2IsFloating = t;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto fw2 = dock2->floatingWindow();
|
||||||
|
QVERIFY(dock1->isFloating());
|
||||||
|
QVERIFY(dock2->isFloating());
|
||||||
|
QVERIFY(dock1->floatAction()->isChecked());
|
||||||
|
QVERIFY(dock2->floatAction()->isChecked());
|
||||||
|
|
||||||
|
dock1->addDockWidgetAsTab(dock2);
|
||||||
|
QVERIFY(!dock1->isFloating());
|
||||||
|
QVERIFY(!dock2->isFloating());
|
||||||
|
QVERIFY(!dock1->floatAction()->isChecked());
|
||||||
|
QVERIFY(!dock2->floatAction()->isChecked());
|
||||||
|
|
||||||
|
dock2->setFloating(true);
|
||||||
|
|
||||||
|
QVERIFY(dock1->isFloating());
|
||||||
|
QVERIFY(dock1->floatAction()->isChecked());
|
||||||
|
QVERIFY(dock2->isFloating());
|
||||||
|
QVERIFY(dock2->floatAction()->isChecked());
|
||||||
|
|
||||||
|
QVERIFY(dock1IsFloating);
|
||||||
|
QVERIFY(dock2IsFloating);
|
||||||
|
|
||||||
|
delete fw2;
|
||||||
|
delete dock1->window();
|
||||||
|
delete dock2->window();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDocks::tst_dockableMainWindows()
|
void TestDocks::tst_dockableMainWindows()
|
||||||
@@ -5751,7 +5752,65 @@ void TestDocks::tst_stuckSeparator()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDocks::setWidget()
|
void TestDocks::tst_isFocused()
|
||||||
|
{
|
||||||
|
EnsureTopLevelsDeleted e;
|
||||||
|
|
||||||
|
// 1. Create 2 floating windows
|
||||||
|
auto dock1 = createDockWidget(QStringLiteral("dock1"), new QLineEdit());
|
||||||
|
auto dock2 = createDockWidget(QStringLiteral("dock2"), new QLineEdit());
|
||||||
|
dock1->window()->move(400, 200);
|
||||||
|
|
||||||
|
// 2. Raise dock1 and focus its line edit
|
||||||
|
dock1->raise();
|
||||||
|
dock1->widget()->setFocus(Qt::OtherFocusReason);
|
||||||
|
Testing::waitForEvent(dock1->widget(), QEvent::FocusIn);
|
||||||
|
|
||||||
|
QVERIFY(dock1->isFocused());
|
||||||
|
QVERIFY(!dock2->isFocused());
|
||||||
|
|
||||||
|
// 3. Raise dock3 and focus its line edit
|
||||||
|
dock2->raise();
|
||||||
|
dock2->widget()->setFocus(Qt::OtherFocusReason);
|
||||||
|
Testing::waitForEvent(dock2->widget(), QEvent::FocusIn);
|
||||||
|
QVERIFY(!dock1->isFocused());
|
||||||
|
QVERIFY(dock2->isFocused());
|
||||||
|
|
||||||
|
// 4. Tab dock1, it's current tab now
|
||||||
|
auto oldFw1 = dock1->window();
|
||||||
|
dock2->addDockWidgetAsTab(dock1);
|
||||||
|
delete oldFw1;
|
||||||
|
QVERIFY(dock1->isFocused());
|
||||||
|
QVERIFY(!dock2->isFocused());
|
||||||
|
|
||||||
|
// 5. Set dock2 as current tab again
|
||||||
|
dock2->raise();
|
||||||
|
QVERIFY(!dock1->isFocused());
|
||||||
|
QVERIFY(dock2->isFocused());
|
||||||
|
|
||||||
|
// 6. Create dock3, focus it
|
||||||
|
auto dock3 = createDockWidget(QStringLiteral("dock3"), new QLineEdit());
|
||||||
|
auto oldFw3 = dock3->window();
|
||||||
|
dock3->raise();
|
||||||
|
dock3->widget()->setFocus(Qt::OtherFocusReason);
|
||||||
|
Testing::waitForEvent(dock2->widget(), QEvent::FocusIn);
|
||||||
|
QVERIFY(!dock1->isFocused());
|
||||||
|
QVERIFY(!dock2->isFocused());
|
||||||
|
QVERIFY(dock3->isFocused());
|
||||||
|
|
||||||
|
// 4. Add dock3 to the 1st window, nested, focus 2 again
|
||||||
|
dock2->addDockWidgetToContainingWindow(dock3, Location_OnLeft);
|
||||||
|
delete oldFw3;
|
||||||
|
dock2->raise();
|
||||||
|
dock2->widget()->setFocus(Qt::OtherFocusReason);
|
||||||
|
Testing::waitForEvent(dock2->widget(), QEvent::FocusIn);
|
||||||
|
QVERIFY(!dock1->isFocused());
|
||||||
|
QVERIFY(dock2->isFocused());
|
||||||
|
QVERIFY(!dock3->isFocused());
|
||||||
|
delete dock2->window();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestDocks::tst_setWidget()
|
||||||
{
|
{
|
||||||
EnsureTopLevelsDeleted e;
|
EnsureTopLevelsDeleted e;
|
||||||
auto dw = new DockWidget(QStringLiteral("FOO"));
|
auto dw = new DockWidget(QStringLiteral("FOO"));
|
||||||
|
|||||||
@@ -23,8 +23,10 @@
|
|||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTQUICK
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
# include "private/quick/DockWidgetQuick.h"
|
# include "private/quick/DockWidgetQuick.h"
|
||||||
|
# include "private/quick/MainWindowQuick_p.h"
|
||||||
#else
|
#else
|
||||||
# include "DockWidget.h"
|
# include "DockWidget.h"
|
||||||
|
# include "MainWindow.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
@@ -46,8 +48,7 @@ void NonClosableWidget::closeEvent(QCloseEvent *ev)
|
|||||||
ev->ignore(); // don't allow to close
|
ev->ignore(); // don't allow to close
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
std::unique_ptr<KDDockWidgets::MainWindowBase> KDDockWidgets::Tests::createMainWindow(QSize sz, KDDockWidgets::MainWindowOptions options, const QString &name)
|
||||||
std::unique_ptr<KDDockWidgets::MainWindow> KDDockWidgets::Tests::createMainWindow(QSize sz, KDDockWidgets::MainWindowOptions options, const QString &name)
|
|
||||||
{
|
{
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
count++;
|
count++;
|
||||||
@@ -55,17 +56,17 @@ std::unique_ptr<KDDockWidgets::MainWindow> KDDockWidgets::Tests::createMainWindo
|
|||||||
const QString mainWindowName = name.isEmpty() ? QStringLiteral("MyMainWindow%1").arg(count)
|
const QString mainWindowName = name.isEmpty() ? QStringLiteral("MyMainWindow%1").arg(count)
|
||||||
: name;
|
: name;
|
||||||
|
|
||||||
auto ptr = std::unique_ptr<MainWindow>(new MainWindow(mainWindowName, options));
|
auto ptr = std::unique_ptr<MainWindowType>(new MainWindowType(mainWindowName, options));
|
||||||
ptr->show();
|
ptr->show();
|
||||||
ptr->resize(sz);
|
ptr->resize(sz);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
DockWidgetBase *KDDockWidgets::Tests::createDockWidget(const QString &name, QWidgetOrQuick *w,
|
DockWidgetBase *KDDockWidgets::Tests::createDockWidget(const QString &name, QWidgetOrQuick *w,
|
||||||
DockWidgetBase::Options options, bool show,
|
DockWidgetBase::Options options, bool show,
|
||||||
const QString &affinityName)
|
const QString &affinityName)
|
||||||
{
|
{
|
||||||
|
w->setFocusPolicy(Qt::StrongFocus);
|
||||||
auto dock = new DockWidgetType(name, options);
|
auto dock = new DockWidgetType(name, options);
|
||||||
dock->setAffinityName(affinityName);
|
dock->setAffinityName(affinityName);
|
||||||
dock->DockWidgetBase::setWidget(w);
|
dock->DockWidgetBase::setWidget(w);
|
||||||
@@ -90,32 +91,41 @@ DockWidgetBase *KDDockWidgets::Tests::createDockWidget(const QString &name, QCol
|
|||||||
return createDockWidget(name, new MyWidget(name, color));
|
return createDockWidget(name, new MyWidget(name, color));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static QWidgetOrQuick *createGuestWidget(int i)
|
||||||
|
{
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
std::unique_ptr<MainWindow> KDDockWidgets::Tests::createMainWindow(QVector<DockDescriptor> &docks)
|
return new QPushButton(QStringLiteral("%1").arg(i));
|
||||||
|
#else
|
||||||
|
Q_UNUSED(i);
|
||||||
|
return new QWidgetAdapter();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MainWindowBase> KDDockWidgets::Tests::createMainWindow(QVector<DockDescriptor> &docks)
|
||||||
{
|
{
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
count++;
|
count++;
|
||||||
auto m = std::unique_ptr<MainWindow>(new MainWindow(QStringLiteral("MyMainWindow%1").arg(count), MainWindowOption_None));
|
auto m = std::unique_ptr<MainWindowType>(new MainWindowType(QStringLiteral("MyMainWindow%1").arg(count), MainWindowOption_None));
|
||||||
auto layout = m->multiSplitter();
|
auto layout = m->multiSplitter();
|
||||||
m->show();
|
m->show();
|
||||||
m->resize(QSize(700, 700));
|
m->resize(QSize(700, 700));
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (DockDescriptor &desc : docks) {
|
for (DockDescriptor &desc : docks) {
|
||||||
desc.createdDock = createDockWidget(QStringLiteral("%1-%2").arg(i).arg(count), new QPushButton(QStringLiteral("%1").arg(i)), {}, false);
|
desc.createdDock = createDockWidget(QStringLiteral("%1-%2").arg(i).arg(count), createGuestWidget(i), {}, false);
|
||||||
DockWidgetBase *relativeTo = nullptr;
|
DockWidgetBase *relativeTo = nullptr;
|
||||||
if (desc.relativeToIndex != -1)
|
if (desc.relativeToIndex != -1)
|
||||||
relativeTo = docks.at(desc.relativeToIndex).createdDock;
|
relativeTo = docks.at(desc.relativeToIndex).createdDock;
|
||||||
|
|
||||||
m->addDockWidget(desc.createdDock, desc.loc, relativeTo, desc.option);
|
m->addDockWidget(desc.createdDock, desc.loc, relativeTo, desc.option);
|
||||||
qDebug() << "Added" <<i;
|
|
||||||
layout->checkSanity();
|
layout->checkSanity();
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
MyWidget::MyWidget(const QString &, QColor c)
|
MyWidget::MyWidget(const QString &, QColor c)
|
||||||
: QWidgetOrQuick()
|
: QWidgetOrQuick()
|
||||||
, c(c)
|
, c(c)
|
||||||
|
|||||||
@@ -12,12 +12,16 @@
|
|||||||
#ifndef KDDOCKWIDGETS_TESTS_UTILS_H
|
#ifndef KDDOCKWIDGETS_TESTS_UTILS_H
|
||||||
#define KDDOCKWIDGETS_TESTS_UTILS_H
|
#define KDDOCKWIDGETS_TESTS_UTILS_H
|
||||||
|
|
||||||
#include "MainWindow.h"
|
|
||||||
#include "KDDockWidgets.h"
|
#include "KDDockWidgets.h"
|
||||||
#include "DropIndicatorOverlayInterface_p.h"
|
#include "DropIndicatorOverlayInterface_p.h"
|
||||||
#include "DockWidgetBase.h"
|
#include "DockWidgetBase.h"
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
# include <QWidget>
|
||||||
|
# include <QToolButton>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
@@ -45,16 +49,51 @@ struct DockDescriptor {
|
|||||||
KDDockWidgets::AddingOption option;
|
KDDockWidgets::AddingOption option;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct EnsureTopLevelsDeleted
|
||||||
|
{
|
||||||
|
EnsureTopLevelsDeleted()
|
||||||
|
: m_originalFlags(Config::self().flags())
|
||||||
|
, m_originalSeparatorThickness(Config::self().separatorThickness())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~EnsureTopLevelsDeleted()
|
||||||
|
{
|
||||||
|
if (topLevels().size() != 0) {
|
||||||
|
qWarning() << "There's still top-level widgets present!" << topLevels();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other cleanup, since we use this class everywhere
|
||||||
|
Config::self().setDockWidgetFactoryFunc(nullptr);
|
||||||
|
Config::self().setFlags(m_originalFlags);
|
||||||
|
Config::self().setSeparatorThickness(m_originalSeparatorThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidgetList topLevels() const
|
||||||
|
{
|
||||||
|
QWidgetList result;
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
for (QWidget *w : qApp->topLevelWidgets()) {
|
||||||
|
if (!qobject_cast<QToolButton*>(w))
|
||||||
|
result << w;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Config::Flags m_originalFlags;
|
||||||
|
const int m_originalSeparatorThickness;
|
||||||
|
};
|
||||||
|
|
||||||
bool shouldBlacklistWarning(const QString &msg, const QString &category = {});
|
bool shouldBlacklistWarning(const QString &msg, const QString &category = {});
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
std::unique_ptr<MainWindowBase> createMainWindow(QSize sz = {600, 600},
|
||||||
std::unique_ptr<KDDockWidgets::MainWindow> createMainWindow(QSize sz = {600, 600},
|
|
||||||
KDDockWidgets::MainWindowOptions options = MainWindowOption_HasCentralFrame, const QString &name = {});
|
KDDockWidgets::MainWindowOptions options = MainWindowOption_HasCentralFrame, const QString &name = {});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<KDDockWidgets::MainWindow> createMainWindow(QVector<DockDescriptor> &docks);
|
std::unique_ptr<KDDockWidgets::MainWindowBase> createMainWindow(QVector<DockDescriptor> &docks);
|
||||||
#endif
|
|
||||||
KDDockWidgets::DockWidgetBase *createDockWidget(const QString &name, QWidgetOrQuick *w,
|
KDDockWidgets::DockWidgetBase *createDockWidget(const QString &name, QWidgetOrQuick *w,
|
||||||
DockWidgetBase::Options options = {}, bool show = true,
|
DockWidgetBase::Options options = {}, bool show = true,
|
||||||
const QString &affinityName = {});
|
const QString &affinityName = {});
|
||||||
|
|||||||
Reference in New Issue
Block a user