Added support for stylesheet styling of overlay cross icons, fixed problem when dragging a floating widget that was maximized, removed som std::cout debug output

This commit is contained in:
Uwe Kindler 2018-08-28 13:25:44 +02:00
parent 9cd2584de5
commit 0b963d1540
6 changed files with 369 additions and 162 deletions

View File

@ -180,6 +180,7 @@ void DockAreaWidgetPrivate::createTabBar()
TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width()); TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width());
TabsMenuButton->setMenu(new QMenu(TabsMenuButton)); TabsMenuButton->setMenu(new QMenu(TabsMenuButton));
TopLayout->addWidget(TabsMenuButton, 0); TopLayout->addWidget(TabsMenuButton, 0);
TabsMenuButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
SLOT(onTabsMenuActionTriggered(QAction*))); SLOT(onTabsMenuActionTriggered(QAction*)));

View File

@ -993,7 +993,6 @@ bool CDockContainerWidget::restoreState(QXmlStreamReader& s, bool Testing)
QByteArray GeometryString = s.readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).toLocal8Bit(); QByteArray GeometryString = s.readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).toLocal8Bit();
QByteArray Geometry = QByteArray::fromHex(GeometryString); QByteArray Geometry = QByteArray::fromHex(GeometryString);
std::cout << "Geometry: " << Geometry.toHex(' ').toStdString() << std::endl;
if (Geometry.isEmpty()) if (Geometry.isEmpty())
{ {
return false; return false;

View File

@ -312,7 +312,6 @@ QByteArray CDockManager::saveState(int version) const
s.writeEndElement(); s.writeEndElement();
s.writeEndDocument(); s.writeEndDocument();
std::cout << xmldata.toStdString() << std::endl;
return xmldata; return xmldata;
} }
@ -408,14 +407,12 @@ QStringList CDockManager::perspectiveNames() const
//============================================================================ //============================================================================
void CDockManager::openPerspective(const QString& PerspectiveName) void CDockManager::openPerspective(const QString& PerspectiveName)
{ {
std::cout << "CDockManager::openPerspective " << PerspectiveName.toStdString() << std::endl;
const auto Iterator = d->Perspectives.find(PerspectiveName); const auto Iterator = d->Perspectives.find(PerspectiveName);
if (d->Perspectives.end() == Iterator) if (d->Perspectives.end() == Iterator)
{ {
return; return;
} }
std::cout << "CDockManager::openPerspective - restoring state" << std::endl;
restoreState(Iterator.value()); restoreState(Iterator.value());
} }

View File

@ -33,17 +33,127 @@
#include <QLabel> #include <QLabel>
#include <QtGlobal> #include <QtGlobal>
#include <QDebug> #include <QDebug>
#include <QMap>
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
#include <iostream>
namespace ads namespace ads
{ {
//============================================================================
static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size, DockWidgetArea DockWidgetArea, /**
CDockOverlay::eMode Mode) * Private data class of CDockOverlay
*/
struct DockOverlayPrivate
{ {
QColor borderColor = pal.color(QPalette::Active, QPalette::Highlight); CDockOverlay* _this;
QColor backgroundColor = pal.color(QPalette::Active, QPalette::Base); DockWidgetAreas AllowedAreas = InvalidDockWidgetArea;
CDockOverlayCross* Cross;
QPointer<QWidget> TargetWidget;
QRect TargetRect;
DockWidgetArea LastLocation = InvalidDockWidgetArea;
bool DropPreviewEnabled = true;
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
QRect DropAreaRect;
/**
* Private data constructor
*/
DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {}
};
/**
* Private data of CDockOverlayCross class
*/
struct DockOverlayCrossPrivate
{
CDockOverlayCross* _this;
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
CDockOverlay* DockOverlay;
QHash<DockWidgetArea, QWidget*> DropIndicatorWidgets;
QGridLayout* GridLayout;
QColor IconColors[5];
bool UpdateRequired = false;
/**
* Private data constructor
*/
DockOverlayCrossPrivate(CDockOverlayCross* _public) : _this(_public) {}
/**
*
* @param area
* @return
*/
QPoint areaGridPosition(const DockWidgetArea area);
/**
* Palette based default icon colors
*/
QColor defaultIconColor(CDockOverlayCross::eIconColor ColorIndex)
{
QPalette pal = _this->palette();
switch (ColorIndex)
{
case CDockOverlayCross::FrameColor: return pal.color(QPalette::Active, QPalette::Highlight);
case CDockOverlayCross::WindowBackgroundColor: return pal.color(QPalette::Active, QPalette::Base);
case CDockOverlayCross::OverlayColor:
{
QColor Color = pal.color(QPalette::Active, QPalette::Highlight);
Color.setAlpha(64);
return Color;
}
break;
case CDockOverlayCross::ArrowColor: return pal.color(QPalette::Active, QPalette::Base);
case CDockOverlayCross::ShadowColor: return QColor(0, 0, 0, 64);
default:
return QColor();
}
return QColor();
}
/**
* Stylehseet based icon colors
*/
QColor iconColor(CDockOverlayCross::eIconColor ColorIndex)
{
QColor Color = IconColors[ColorIndex];
if (!Color.isValid())
{
Color = defaultIconColor(ColorIndex);
IconColors[ColorIndex] = Color;
}
return Color;
}
//============================================================================
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
CDockOverlay::eMode Mode)
{
QLabel* l = new QLabel();
l->setObjectName("DockWidgetAreaLabel");
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 3.f;
const QSizeF size(metric, metric);
l->setPixmap(createDropIndicatorPixmap(size, DockWidgetArea, Mode));
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
l->setAttribute(Qt::WA_TranslucentBackground);
return l;
}
//============================================================================
QPixmap createDropIndicatorPixmap(const QSizeF& size, DockWidgetArea DockWidgetArea,
CDockOverlay::eMode Mode)
{
QColor borderColor = iconColor(CDockOverlayCross::FrameColor);
QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor);
QPixmap pm(size.width(), size.height()); QPixmap pm(size.width(), size.height());
pm.fill(QColor(0, 0, 0, 0)); pm.fill(QColor(0, 0, 0, 0));
@ -56,7 +166,12 @@ static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size
baseRect.moveCenter(ShadowRect.center()); baseRect.moveCenter(ShadowRect.center());
// Fill // Fill
p.fillRect(ShadowRect, QColor(0, 0, 0, 64)); QColor ShadowColor = iconColor(CDockOverlayCross::ShadowColor);
if (ShadowColor.alpha() == 255)
{
ShadowColor.setAlpha(64);
}
p.fillRect(ShadowRect, ShadowColor);
// Drop area rect. // Drop area rect.
p.save(); p.save();
@ -100,8 +215,11 @@ static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size
{ {
pen = p.pen(); pen = p.pen();
pen.setColor(borderColor); pen.setColor(borderColor);
QColor Color = borderColor; QColor Color = iconColor(CDockOverlayCross::OverlayColor);
if (Color.alpha() == 255)
{
Color.setAlpha(64); Color.setAlpha(64);
}
p.setBrush(Color); p.setBrush(Color);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.drawRect(areaRect); p.drawRect(areaRect);
@ -142,7 +260,7 @@ static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size
<< QPointF( ArrowRect.right(), ArrowRect.center().y()) << QPointF( ArrowRect.right(), ArrowRect.center().y())
<< ArrowRect.bottomLeft(); << ArrowRect.bottomLeft();
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush(backgroundColor); p.setBrush(iconColor(CDockOverlayCross::ArrowColor));
p.setRenderHint(QPainter::Antialiasing, true); p.setRenderHint(QPainter::Antialiasing, true);
p.translate(nonAreaRect.center().x(), nonAreaRect.center().y()); p.translate(nonAreaRect.center().x(), nonAreaRect.center().y());
@ -167,70 +285,8 @@ static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size
} }
return pm; return pm;
} }
//============================================================================
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
CDockOverlay::eMode Mode)
{
QLabel* l = new QLabel();
l->setObjectName("DockWidgetAreaLabel");
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 3.f;
const QSizeF size(metric, metric);
l->setPixmap(createDropIndicatorPixmap(l->palette(), size, DockWidgetArea,
Mode));
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
l->setAttribute(Qt::WA_TranslucentBackground);
return l;
}
/**
* Private data class of CDockOverlay
*/
struct DockOverlayPrivate
{
CDockOverlay* _this;
DockWidgetAreas AllowedAreas = InvalidDockWidgetArea;
CDockOverlayCross* Cross;
QPointer<QWidget> TargetWidget;
QRect TargetRect;
DockWidgetArea LastLocation = InvalidDockWidgetArea;
bool DropPreviewEnabled = true;
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
QRect DropAreaRect;
/**
* Private data constructor
*/
DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {}
};
/**
* Private data of CDockOverlayCross class
*/
struct DockOverlayCrossPrivate
{
CDockOverlayCross* _this;
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
CDockOverlay* DockOverlay;
QHash<DockWidgetArea, QWidget*> DropIndicatorWidgets;
QGridLayout* GridLayout;
/**
* Private data constructor
*/
DockOverlayCrossPrivate(CDockOverlayCross* _public) : _this(_public) {}
/**
*
* @param area
* @return
*/
QPoint areaGridPosition(const DockWidgetArea area);
}; };
@ -247,7 +303,6 @@ CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) :
setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_TranslucentBackground);
d->Cross->setupOverlayCross(Mode);
d->Cross->setVisible(false); d->Cross->setVisible(false);
setVisible(false); setVisible(false);
} }
@ -405,6 +460,18 @@ void CDockOverlay::hideEvent(QHideEvent* e)
} }
//============================================================================
bool CDockOverlay::event(QEvent *e)
{
bool Result = Super::event(e);
if (e->type() == QEvent::Polish)
{
d->Cross->setupOverlayCross(d->Mode);
}
return Result;
}
//============================================================================ //============================================================================
static int areaAlignment(const DockWidgetArea area) static int areaAlignment(const DockWidgetArea area)
{ {
@ -480,13 +547,29 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
d->Mode = Mode; d->Mode = Mode;
QHash<DockWidgetArea, QWidget*> areaWidgets; QHash<DockWidgetArea, QWidget*> areaWidgets;
areaWidgets.insert(TopDockWidgetArea, createDropIndicatorWidget(TopDockWidgetArea, Mode)); areaWidgets.insert(TopDockWidgetArea, d->createDropIndicatorWidget(TopDockWidgetArea, Mode));
areaWidgets.insert(RightDockWidgetArea, createDropIndicatorWidget(RightDockWidgetArea, Mode)); areaWidgets.insert(RightDockWidgetArea, d->createDropIndicatorWidget(RightDockWidgetArea, Mode));
areaWidgets.insert(BottomDockWidgetArea, createDropIndicatorWidget(BottomDockWidgetArea, Mode)); areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode));
areaWidgets.insert(LeftDockWidgetArea, createDropIndicatorWidget(LeftDockWidgetArea, Mode)); areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode));
areaWidgets.insert(CenterDockWidgetArea, createDropIndicatorWidget(CenterDockWidgetArea, Mode)); areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode));
setAreaWidgets(areaWidgets); setAreaWidgets(areaWidgets);
d->UpdateRequired = false;
}
//============================================================================
void CDockOverlayCross::setIconColor(eIconColor ColorIndex, const QColor& Color)
{
d->IconColors[ColorIndex] = Color;
d->UpdateRequired = true;
}
//============================================================================
QColor CDockOverlayCross::iconColor(eIconColor ColorIndex) const
{
return d->IconColors[ColorIndex];
} }
@ -573,6 +656,10 @@ DockWidgetArea CDockOverlayCross::cursorLocation() const
//============================================================================ //============================================================================
void CDockOverlayCross::showEvent(QShowEvent*) void CDockOverlayCross::showEvent(QShowEvent*)
{ {
if (d->UpdateRequired)
{
setupOverlayCross(d->Mode);
}
this->updatePosition(); this->updatePosition();
} }
@ -611,6 +698,38 @@ void CDockOverlayCross::reset()
} }
//============================================================================
void CDockOverlayCross::setIconColors(const QString& Colors)
{
static const QMap<QString, int> ColorCompenentStringMap{
{"Frame", CDockOverlayCross::FrameColor},
{"Background", CDockOverlayCross::WindowBackgroundColor},
{"Overlay", CDockOverlayCross::OverlayColor},
{"Arrow", CDockOverlayCross::ArrowColor},
{"Shadow", CDockOverlayCross::ShadowColor}};
auto ColorList = Colors.split(' ', QString::SkipEmptyParts);
for (const auto& ColorListEntry : ColorList)
{
auto ComponentColor = ColorListEntry.split('=', QString::SkipEmptyParts);
int Component = ColorCompenentStringMap.value(ComponentColor[0], -1);
if (Component < 0)
{
continue;
}
d->IconColors[Component] = QColor(ComponentColor[1]);
}
d->UpdateRequired = true;
}
//============================================================================
QString CDockOverlayCross::iconColors() const
{
return QString();
}
} // namespace ads } // namespace ads
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -48,6 +48,8 @@ private:
friend class DockOverlayCross; friend class DockOverlayCross;
public: public:
using Super = QFrame;
enum eMode enum eMode
{ {
ModeDockAreaOverlay, ModeDockAreaOverlay,
@ -100,6 +102,11 @@ public:
*/ */
QRect dropOverlayRect() const; QRect dropOverlayRect() const;
/**
* Handle polish events
*/
virtual bool event(QEvent *e) override;
protected: protected:
virtual void paintEvent(QPaintEvent *e) override; virtual void paintEvent(QPaintEvent *e) override;
virtual void showEvent(QShowEvent* e) override; virtual void showEvent(QShowEvent* e) override;
@ -112,18 +119,71 @@ struct DockOverlayCrossPrivate;
* DockOverlayCross shows a cross with 5 different drop area possibilities. * DockOverlayCross shows a cross with 5 different drop area possibilities.
* I could have handled everything inside DockOverlay, but because of some * I could have handled everything inside DockOverlay, but because of some
* styling issues it's better to have a separate class for the cross. * styling issues it's better to have a separate class for the cross.
* You can style the cross icon using the property system.
* \code
* ads--CDockOverlayCross
{
qproperty-iconFrameColor: palette(highlight);
qproperty-iconBackgroundColor: palette(base);
qproperty-iconOverlayColor: palette(highlight);
qproperty-iconArrowColor: rgb(227, 227, 227);
qproperty-iconShadowColor: rgb(0, 0, 0);
}
* \endcode
* Or you can use the iconColors property to pass in AARRGGBB values as
* hex string like shown in the example below.
* \code
* ads--CDockOverlayCross
* {
* qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
* }
* \endcode
*/ */
class CDockOverlayCross : public QWidget class CDockOverlayCross : public QWidget
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString iconColors READ iconColors WRITE setIconColors)
Q_PROPERTY(QColor iconFrameColor READ iconColor WRITE setIconFrameColor)
Q_PROPERTY(QColor iconBackgroundColor READ iconColor WRITE setIconBackgroundColor)
Q_PROPERTY(QColor iconOverlayColor READ iconColor WRITE setIconOverlayColor)
Q_PROPERTY(QColor iconArrowColor READ iconColor WRITE setIconArrowColor)
Q_PROPERTY(QColor iconShadowColor READ iconColor WRITE setIconShadowColor)
public:
enum eIconColor
{
FrameColor,///< the color of the frame of the small window icon
WindowBackgroundColor,///< the background color of the small window in the icon
OverlayColor,///< the color that shows the overlay (the dock side) in the icon
ArrowColor,///< the arrow that points into the direction
ShadowColor///< the color of the shadow rectangle that is painted below the icons
};
private: private:
DockOverlayCrossPrivate* d; DockOverlayCrossPrivate* d;
friend struct DockOverlayCrossPrivate; friend struct DockOverlayCrossPrivate;
friend class CDockOverlay; friend class CDockOverlay;
protected:
/**
* This function returns an empty string and is only here to silence
* moc
*/
QString iconColors() const;
/**
* This is a dummy function for the property system
*/
QColor iconColor() const {return QColor();}
void setIconFrameColor(const QColor& Color) {setIconColor(FrameColor, Color);}
void setIconBackgroundColor(const QColor& Color) {setIconColor(WindowBackgroundColor, Color);}
void setIconOverlayColor(const QColor& Color) {setIconColor(OverlayColor, Color);}
void setIconArrowColor(const QColor& Color) {setIconColor(ArrowColor, Color);}
void setIconShadowColor(const QColor& Color) {setIconColor(ShadowColor, Color);}
public: public:
/** /**
* Creates an overlay corss for the given overlay * Creates an overlay cross for the given overlay
*/ */
CDockOverlayCross(CDockOverlay* overlay); CDockOverlayCross(CDockOverlay* overlay);
@ -132,6 +192,16 @@ public:
*/ */
virtual ~CDockOverlayCross(); virtual ~CDockOverlayCross();
/**
* Sets a certain icon color
*/
void setIconColor(eIconColor ColorIndex, const QColor& Color);
/**
* Returns the icon color given by ColorIndex
*/
QColor iconColor(eIconColor ColorIndex) const;
/** /**
* Returns the dock widget area depending on the current cursor location. * Returns the dock widget area depending on the current cursor location.
* The function checks, if the mouse cursor is inside of any drop indicator * The function checks, if the mouse cursor is inside of any drop indicator
@ -154,6 +224,19 @@ public:
*/ */
void updatePosition(); void updatePosition();
/**
* A string with all icon colors to set.
* You can use this property to style the overly icon via CSS stylesheet
* file. The colors are set via a color identifier and a hex AARRGGBB value like
* in the example below.
* \code
* ads--CDockOverlayCross
* {
* qproperty-iconColors: "Frame=#ff3d3d3d Background=#ff929292 Overlay=#1f3d3d3d Arrow=#ffb4b4b4 Shadow=#40474747";
* }
*/
void setIconColors(const QString& Colors);
protected: protected:
virtual void showEvent(QShowEvent* e) override; virtual void showEvent(QShowEvent* e) override;
void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets); void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets);

View File

@ -367,9 +367,17 @@ bool CFloatingDockContainer::event(QEvent *e)
else if (d->NonClientAreaMouseButtonPress && (e->type() == QEvent::Resize)) else if (d->NonClientAreaMouseButtonPress && (e->type() == QEvent::Resize))
{ {
// If user resizes the floating widget, we do not want to show any // If user resizes the floating widget, we do not want to show any
// drop overlays or drop overlay icons // drop overlays or drop overlay icons. If the window is maximized,
// then dragging the window via title bar will cause the widget to
// leave the maximized state. This in turn will trigger a resize event.
// To know, if the resize event was triggered by user via moving a
// corner of the window frame or if it was caused by a windows state
// change, we check, if we are not in maximized state.
if (!isMaximized())
{
d->setDraggingActive(false); d->setDraggingActive(false);
} }
}
return QWidget::event(e); return QWidget::event(e);
} }