/* SPDX-FileCopyrightText: 2011 Aaron Seigo SPDX-FileCopyrightText: 2020 Vlad Zahorodnii SPDX-License-Identifier: LGPL-2.0-or-later */ #include "debug_p.h" #include "dialogshadows_p.h" #include class DialogShadows::Private { public: Private(DialogShadows *shadows) : q(shadows) { } ~Private() { } void clearTiles(); void setupTiles(); void initTile(const QString &element); void updateShadow(QWindow *window, KSvg::FrameSvg::EnabledBorders); void clearShadow(QWindow *window); void updateShadows(); void windowDestroyed(QObject *deletedObject); DialogShadows *q; QHash m_windows; QHash m_shadows; QList m_tiles; }; typedef QHash DialogShadowHash; Q_GLOBAL_STATIC(DialogShadowHash, s_privateDialogShadowsInstances) DialogShadows *DialogShadows::instance(const QString &prefix) { DialogShadows *&shadow = (*s_privateDialogShadowsInstances)[prefix]; if (!shadow) { shadow = new DialogShadows(qApp, prefix); } return shadow; } DialogShadows::DialogShadows(QObject *parent, const QString &prefix) : KSvg::Svg(parent) , d(new Private(this)) { setImagePath(prefix); connect(this, SIGNAL(repaintNeeded()), this, SLOT(updateShadows())); } DialogShadows::~DialogShadows() { delete d; } void DialogShadows::addWindow(QWindow *window, KSvg::FrameSvg::EnabledBorders enabledBorders) { if (!window) { return; } d->m_windows[window] = enabledBorders; d->updateShadow(window, enabledBorders); connect(window, SIGNAL(destroyed(QObject *)), this, SLOT(windowDestroyed(QObject *)), Qt::UniqueConnection); } void DialogShadows::removeWindow(QWindow *window) { if (!d->m_windows.contains(window)) { return; } d->m_windows.remove(window); disconnect(window, nullptr, this, nullptr); d->clearShadow(window); if (d->m_windows.isEmpty()) { d->clearTiles(); } } void DialogShadows::setEnabledBorders(QWindow *window, KSvg::FrameSvg::EnabledBorders enabledBorders) { Q_ASSERT(d->m_windows.contains(window)); if (!window || !d->m_windows.contains(window)) { return; } d->updateShadow(window, enabledBorders); } void DialogShadows::Private::windowDestroyed(QObject *deletedObject) { QWindow *window = static_cast(deletedObject); m_windows.remove(window); clearShadow(window); if (m_windows.isEmpty()) { clearTiles(); } } void DialogShadows::Private::updateShadows() { setupTiles(); QHash::const_iterator i; for (i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) { updateShadow(i.key(), i.value()); } } void DialogShadows::Private::initTile(const QString &element) { const QImage image = q->pixmap(element).toImage(); KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); tile->setImage(image); m_tiles << tile; } void DialogShadows::Private::setupTiles() { clearTiles(); initTile(QStringLiteral("shadow-top")); initTile(QStringLiteral("shadow-topright")); initTile(QStringLiteral("shadow-right")); initTile(QStringLiteral("shadow-bottomright")); initTile(QStringLiteral("shadow-bottom")); initTile(QStringLiteral("shadow-bottomleft")); initTile(QStringLiteral("shadow-left")); initTile(QStringLiteral("shadow-topleft")); } void DialogShadows::Private::clearTiles() { m_tiles.clear(); } void DialogShadows::Private::updateShadow(QWindow *window, KSvg::FrameSvg::EnabledBorders enabledBorders) { if (m_tiles.isEmpty()) { setupTiles(); } KWindowShadow *&shadow = m_shadows[window]; if (!shadow) { shadow = new KWindowShadow(q); } if (shadow->isCreated()) { shadow->destroy(); } if (enabledBorders & KSvg::FrameSvg::TopBorder) { shadow->setTopTile(m_tiles.at(0)); } else { shadow->setTopTile(nullptr); } if (enabledBorders & KSvg::FrameSvg::TopBorder && enabledBorders & KSvg::FrameSvg::RightBorder) { shadow->setTopRightTile(m_tiles.at(1)); } else { shadow->setTopRightTile(nullptr); } if (enabledBorders & KSvg::FrameSvg::RightBorder) { shadow->setRightTile(m_tiles.at(2)); } else { shadow->setRightTile(nullptr); } if (enabledBorders & KSvg::FrameSvg::BottomBorder && enabledBorders & KSvg::FrameSvg::RightBorder) { shadow->setBottomRightTile(m_tiles.at(3)); } else { shadow->setBottomRightTile(nullptr); } if (enabledBorders & KSvg::FrameSvg::BottomBorder) { shadow->setBottomTile(m_tiles.at(4)); } else { shadow->setBottomTile(nullptr); } if (enabledBorders & KSvg::FrameSvg::BottomBorder && enabledBorders & KSvg::FrameSvg::LeftBorder) { shadow->setBottomLeftTile(m_tiles.at(5)); } else { shadow->setBottomLeftTile(nullptr); } if (enabledBorders & KSvg::FrameSvg::LeftBorder) { shadow->setLeftTile(m_tiles.at(6)); } else { shadow->setLeftTile(nullptr); } if (enabledBorders & KSvg::FrameSvg::TopBorder && enabledBorders & KSvg::FrameSvg::LeftBorder) { shadow->setTopLeftTile(m_tiles.at(7)); } else { shadow->setTopLeftTile(nullptr); } QMargins padding; if (enabledBorders & KSvg::FrameSvg::TopBorder) { const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin")).toSize(); if (marginHint.isValid()) { padding.setTop(marginHint.height()); } else { padding.setTop(m_tiles[0]->image().height()); } } if (enabledBorders & KSvg::FrameSvg::RightBorder) { const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin")).toSize(); if (marginHint.isValid()) { padding.setRight(marginHint.width()); } else { padding.setRight(m_tiles[2]->image().width()); } } if (enabledBorders & KSvg::FrameSvg::BottomBorder) { const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin")).toSize(); if (marginHint.isValid()) { padding.setBottom(marginHint.height()); } else { padding.setBottom(m_tiles[4]->image().height()); } } if (enabledBorders & KSvg::FrameSvg::LeftBorder) { const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin")).toSize(); if (marginHint.isValid()) { padding.setLeft(marginHint.width()); } else { padding.setLeft(m_tiles[6]->image().width()); } } shadow->setPadding(padding); shadow->setWindow(window); if (!shadow->create()) { qCWarning(LOG_PLASMAQUICK) << "Couldn't create KWindowShadow for" << window; } } void DialogShadows::Private::clearShadow(QWindow *window) { delete m_shadows.take(window); } bool DialogShadows::enabled() const { return hasElement(QStringLiteral("shadow-left")); } #include "moc_dialogshadows_p.cpp"