Move kwin themes to a separate package
This commit is contained in:
parent
913168e7fb
commit
4827a44c35
@ -1,14 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
|
||||
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
|
||||
find_package(KDecoration2 REQUIRED)
|
||||
|
||||
add_subdirectory(kdecoration)
|
||||
add_subdirectory(libbreezecommon)
|
||||
@ -1,13 +0,0 @@
|
||||
.PHONY: build clean install
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
|
||||
build:
|
||||
cmake -B build
|
||||
cmake --build build
|
||||
|
||||
install:
|
||||
DESTDIR=$(DESTDIR) cmake --install build
|
||||
|
||||
include ../Makefile.inc
|
||||
@ -1,96 +0,0 @@
|
||||
add_definitions(-DTRANSLATION_DOMAIN="breeze_kwin_deco")
|
||||
|
||||
find_package(KF5 REQUIRED COMPONENTS CoreAddons GuiAddons ConfigWidgets WindowSystem I18n IconThemes)
|
||||
find_package(Qt5 CONFIG REQUIRED COMPONENTS DBus)
|
||||
|
||||
### XCB
|
||||
find_package(XCB COMPONENTS XCB)
|
||||
set_package_properties(XCB PROPERTIES
|
||||
DESCRIPTION "X protocol C-language Binding"
|
||||
URL "https://xcb.freedesktop.org"
|
||||
TYPE OPTIONAL
|
||||
PURPOSE "Required to pass style properties to native Windows on X11 Platform"
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
|
||||
set(BREEZE_HAVE_X11 ${XCB_XCB_FOUND})
|
||||
if (XCB_XCB_FOUND)
|
||||
find_package(Qt5 REQUIRED CONFIG COMPONENTS X11Extras)
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
||||
set(BREEZE_HAVE_X11 FALSE)
|
||||
|
||||
endif()
|
||||
|
||||
################# configuration #################
|
||||
configure_file(config-breeze.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-breeze.h )
|
||||
|
||||
################# includes #################
|
||||
include_directories(${CMAKE_SOURCE_DIR}/libbreezecommon)
|
||||
include_directories(${CMAKE_BINARY_DIR}/libbreezecommon)
|
||||
|
||||
################# newt target #################
|
||||
### plugin classes
|
||||
set(breezedecoration_SRCS
|
||||
breezebutton.cpp
|
||||
../libbreezecommon/breezeboxshadowrenderer.cpp
|
||||
breezedecoration.cpp
|
||||
breezeexceptionlist.cpp
|
||||
breezesettingsprovider.cpp
|
||||
breezesizegrip.cpp)
|
||||
|
||||
kconfig_add_kcfg_files(breezedecoration_SRCS breezesettings.kcfgc)
|
||||
|
||||
### config classes
|
||||
### they are kept separately because they might move in a separate library in the future
|
||||
set(breezedecoration_config_SRCS
|
||||
config/breezeconfigwidget.cpp
|
||||
config/breezedetectwidget.cpp
|
||||
config/breezeexceptiondialog.cpp
|
||||
config/breezeexceptionlistwidget.cpp
|
||||
config/breezeexceptionmodel.cpp
|
||||
config/breezeitemmodel.cpp
|
||||
)
|
||||
|
||||
set(breezedecoration_config_PART_FORMS
|
||||
config/ui/breezeconfigurationui.ui
|
||||
config/ui/breezedetectwidget.ui
|
||||
config/ui/breezeexceptiondialog.ui
|
||||
config/ui/breezeexceptionlistwidget.ui
|
||||
)
|
||||
|
||||
ki18n_wrap_ui(breezedecoration_config_PART_FORMS_HEADERS ${breezedecoration_config_PART_FORMS})
|
||||
|
||||
### build library
|
||||
add_library(kali-breezedecoration MODULE
|
||||
${breezedecoration_SRCS}
|
||||
${breezedecoration_config_SRCS}
|
||||
${breezedecoration_config_PART_FORMS_HEADERS})
|
||||
|
||||
target_link_libraries(kali-breezedecoration
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::DBus
|
||||
PRIVATE
|
||||
KDecoration2::KDecoration
|
||||
KF5::ConfigCore
|
||||
KF5::CoreAddons
|
||||
KF5::ConfigWidgets
|
||||
KF5::GuiAddons
|
||||
KF5::I18n
|
||||
KF5::IconThemes
|
||||
KF5::WindowSystem)
|
||||
|
||||
if(BREEZE_HAVE_X11)
|
||||
target_link_libraries(kali-breezedecoration
|
||||
PUBLIC
|
||||
Qt5::X11Extras
|
||||
XCB::XCB)
|
||||
endif()
|
||||
|
||||
|
||||
install(TARGETS kali-breezedecoration DESTINATION ${PLUGIN_INSTALL_DIR}/org.kde.kdecoration2)
|
||||
@ -1,4 +0,0 @@
|
||||
#!bin/sh
|
||||
$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp
|
||||
$XGETTEXT `find . -name \*.cc -o -name \*.cpp -o -name \*.h` -o $podir/breeze_kwin_deco.pot
|
||||
rm -f rc.cpp
|
||||
@ -1,61 +0,0 @@
|
||||
#ifndef breeze_h
|
||||
#define breeze_h
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include "breezesettings.h"
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <QList>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
//* convenience typedefs
|
||||
using InternalSettingsPtr = QSharedPointer<InternalSettings>;
|
||||
using InternalSettingsList = QList<InternalSettingsPtr>;
|
||||
using InternalSettingsListIterator = QListIterator<InternalSettingsPtr>;
|
||||
|
||||
//* metrics
|
||||
enum Metrics
|
||||
{
|
||||
|
||||
//* corner radius (pixels)
|
||||
Frame_FrameRadius = 4,
|
||||
|
||||
//* titlebar metrics, in units of small spacing
|
||||
TitleBar_TopMargin = 3,
|
||||
TitleBar_BottomMargin = 3,
|
||||
TitleBar_SideMargin = 1,
|
||||
TitleBar_ButtonSpacing = 2,
|
||||
|
||||
Frame_BorderSize = 2,
|
||||
|
||||
// shadow dimensions (pixels)
|
||||
Shadow_Overlap = 3,
|
||||
|
||||
};
|
||||
|
||||
//* standard pen widths
|
||||
namespace PenWidth
|
||||
{
|
||||
/* Using 1 instead of slightly more than 1 causes symbols drawn with
|
||||
* pen strokes to look skewed. The exact amount added does not matter
|
||||
* as long as it isn't too visible.
|
||||
*/
|
||||
// The standard pen stroke width for symbols.
|
||||
static constexpr qreal Symbol = 1.01;
|
||||
}
|
||||
|
||||
//* exception
|
||||
enum ExceptionMask
|
||||
{
|
||||
None = 0,
|
||||
BorderSize = 1<<4
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,16 +0,0 @@
|
||||
{
|
||||
"KPlugin": {
|
||||
"Description": "Window decoration using Kali's visual style for the Plasma Desktop",
|
||||
"EnabledByDefault": true,
|
||||
"Id": "org.kali.kali",
|
||||
"Name": "Kali",
|
||||
"ServiceTypes": [
|
||||
"org.kde.kdecoration2"
|
||||
]
|
||||
},
|
||||
"org.kde.kdecoration2": {
|
||||
"blur": false,
|
||||
"kcmodule": true,
|
||||
"recommendedBorderSize": "None"
|
||||
}
|
||||
}
|
||||
@ -1,471 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
#include "breezebutton.h"
|
||||
|
||||
#include <KDecoration2/DecoratedClient>
|
||||
#include <KColorUtils>
|
||||
#include <KIconLoader>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QVariantAnimation>
|
||||
#include <QPainterPath>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
using KDecoration2::ColorRole;
|
||||
using KDecoration2::ColorGroup;
|
||||
using KDecoration2::DecorationButtonType;
|
||||
|
||||
|
||||
//__________________________________________________________________
|
||||
Button::Button(DecorationButtonType type, Decoration* decoration, QObject* parent)
|
||||
: DecorationButton(type, decoration, parent)
|
||||
, m_animation( new QVariantAnimation( this ) )
|
||||
{
|
||||
|
||||
// setup animation
|
||||
// It is important start and end value are of the same type, hence 0.0 and not just 0
|
||||
m_animation->setStartValue( 0.0 );
|
||||
m_animation->setEndValue( 1.0 );
|
||||
m_animation->setEasingCurve( QEasingCurve::InOutQuad );
|
||||
connect(m_animation, &QVariantAnimation::valueChanged, this, [this](const QVariant &value) {
|
||||
setOpacity(value.toReal());
|
||||
});
|
||||
|
||||
// setup default geometry
|
||||
const int height = decoration->buttonHeight();
|
||||
setGeometry(QRect(0, 0, height, height));
|
||||
setIconSize(QSize( height, height ));
|
||||
|
||||
// connections
|
||||
connect(decoration->client().data(), SIGNAL(iconChanged(QIcon)), this, SLOT(update()));
|
||||
connect(decoration->settings().data(), &KDecoration2::DecorationSettings::reconfigured, this, &Button::reconfigure);
|
||||
connect( this, &KDecoration2::DecorationButton::hoveredChanged, this, &Button::updateAnimationState );
|
||||
|
||||
reconfigure();
|
||||
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
Button::Button(QObject *parent, const QVariantList &args)
|
||||
: Button(args.at(0).value<DecorationButtonType>(), args.at(1).value<Decoration*>(), parent)
|
||||
{
|
||||
m_flag = FlagStandalone;
|
||||
//! icon size must return to !valid because it was altered from the default constructor,
|
||||
//! in Standalone mode the button is not using the decoration metrics but its geometry
|
||||
m_iconSize = QSize(-1, -1);
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
Button *Button::create(DecorationButtonType type, KDecoration2::Decoration *decoration, QObject *parent)
|
||||
{
|
||||
if (auto d = qobject_cast<Decoration*>(decoration))
|
||||
{
|
||||
Button *b = new Button(type, d, parent);
|
||||
switch( type )
|
||||
{
|
||||
|
||||
case DecorationButtonType::Close:
|
||||
b->setVisible( d->client().data()->isCloseable() );
|
||||
QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::closeableChanged, b, &Breeze::Button::setVisible );
|
||||
break;
|
||||
|
||||
case DecorationButtonType::Maximize:
|
||||
b->setVisible( d->client().data()->isMaximizeable() );
|
||||
QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::maximizeableChanged, b, &Breeze::Button::setVisible );
|
||||
break;
|
||||
|
||||
case DecorationButtonType::Minimize:
|
||||
b->setVisible( d->client().data()->isMinimizeable() );
|
||||
QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::minimizeableChanged, b, &Breeze::Button::setVisible );
|
||||
break;
|
||||
|
||||
case DecorationButtonType::ContextHelp:
|
||||
b->setVisible( d->client().data()->providesContextHelp() );
|
||||
QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::providesContextHelpChanged, b, &Breeze::Button::setVisible );
|
||||
break;
|
||||
|
||||
case DecorationButtonType::Shade:
|
||||
b->setVisible( d->client().data()->isShadeable() );
|
||||
QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::shadeableChanged, b, &Breeze::Button::setVisible );
|
||||
break;
|
||||
|
||||
case DecorationButtonType::Menu:
|
||||
QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::iconChanged, b, [b]() { b->update(); });
|
||||
break;
|
||||
|
||||
default: break;
|
||||
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
void Button::paint(QPainter *painter, const QRect &repaintRegion)
|
||||
{
|
||||
Q_UNUSED(repaintRegion)
|
||||
|
||||
if (!decoration()) return;
|
||||
|
||||
painter->save();
|
||||
|
||||
// translate from offset
|
||||
if( m_flag == FlagFirstInList ) painter->translate( m_offset );
|
||||
else painter->translate( 0, m_offset.y() );
|
||||
|
||||
if( !m_iconSize.isValid() ) m_iconSize = geometry().size().toSize();
|
||||
|
||||
// menu button
|
||||
if (type() == DecorationButtonType::Menu)
|
||||
{
|
||||
|
||||
const QRectF iconRect( geometry().topLeft(), m_iconSize );
|
||||
if (auto deco = qobject_cast<Decoration*>(decoration())) {
|
||||
const QPalette activePalette = KIconLoader::global()->customPalette();
|
||||
QPalette palette = decoration()->client().data()->palette();
|
||||
palette.setColor(QPalette::Foreground, deco->fontColor());
|
||||
KIconLoader::global()->setCustomPalette(palette);
|
||||
decoration()->client().data()->icon().paint(painter, iconRect.toRect());
|
||||
if (activePalette == QPalette()) {
|
||||
KIconLoader::global()->resetPalette();
|
||||
} else {
|
||||
KIconLoader::global()->setCustomPalette(palette);
|
||||
}
|
||||
} else {
|
||||
decoration()->client().data()->icon().paint(painter, iconRect.toRect());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
drawIcon( painter );
|
||||
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
void Button::drawIcon( QPainter *painter ) const
|
||||
{
|
||||
|
||||
painter->setRenderHints( QPainter::Antialiasing );
|
||||
|
||||
/*
|
||||
scale painter so that its window matches QRect( -1, -1, 20, 20 )
|
||||
this makes all further rendering and scaling simpler
|
||||
all further rendering is preformed inside QRect( 0, 0, 18, 18 )
|
||||
*/
|
||||
painter->translate( geometry().topLeft() );
|
||||
|
||||
const qreal width( m_iconSize.width() );
|
||||
painter->scale( width/20, width/20 );
|
||||
painter->translate( 1, 1 );
|
||||
|
||||
// render background
|
||||
const QColor backgroundColor( this->backgroundColor() );
|
||||
if( backgroundColor.isValid() )
|
||||
{
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( backgroundColor );
|
||||
painter->drawEllipse( QRectF( 0, 0, 18, 18 ) );
|
||||
}
|
||||
|
||||
// render mark
|
||||
const QColor foregroundColor( this->foregroundColor() );
|
||||
if( foregroundColor.isValid() )
|
||||
{
|
||||
|
||||
// setup painter
|
||||
QPen pen( foregroundColor );
|
||||
pen.setCapStyle( Qt::RoundCap );
|
||||
pen.setJoinStyle( Qt::MiterJoin );
|
||||
pen.setWidthF( PenWidth::Symbol*qMax((qreal)2.0, 20/width ) );
|
||||
|
||||
painter->setPen( pen );
|
||||
painter->setBrush( Qt::NoBrush );
|
||||
|
||||
switch( type() )
|
||||
{
|
||||
|
||||
case DecorationButtonType::Close:
|
||||
{
|
||||
painter->drawLine( QPointF( 6, 6 ), QPointF( 12, 12 ) );
|
||||
painter->drawLine( QPointF( 6, 12 ), QPointF( 12, 6 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case DecorationButtonType::Maximize:
|
||||
{
|
||||
pen.setJoinStyle( Qt::RoundJoin );
|
||||
painter->setPen( pen );
|
||||
|
||||
painter->drawPolygon( QVector<QPointF>{
|
||||
QPointF( 6, 6 ),
|
||||
QPointF( 6, 12 ),
|
||||
QPointF( 12, 12 ),
|
||||
QPointF( 12, 6 )} );
|
||||
break;
|
||||
}
|
||||
|
||||
case DecorationButtonType::Minimize:
|
||||
{
|
||||
painter->drawLine( QPointF( 6, 12 ), QPointF( 12, 12 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case DecorationButtonType::OnAllDesktops:
|
||||
{
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( foregroundColor );
|
||||
|
||||
if( isChecked())
|
||||
{
|
||||
|
||||
// outer ring
|
||||
painter->drawEllipse( QRectF( 3, 3, 12, 12 ) );
|
||||
|
||||
// center dot
|
||||
QColor backgroundColor( this->backgroundColor() );
|
||||
auto d = qobject_cast<Decoration*>( decoration() );
|
||||
if( !backgroundColor.isValid() && d ) backgroundColor = d->titleBarColor();
|
||||
|
||||
if( backgroundColor.isValid() )
|
||||
{
|
||||
painter->setBrush( backgroundColor );
|
||||
painter->drawEllipse( QRectF( 8, 8, 2, 2 ) );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
painter->drawPolygon( QVector<QPointF> {
|
||||
QPointF( 6.5, 8.5 ),
|
||||
QPointF( 12, 3 ),
|
||||
QPointF( 15, 6 ),
|
||||
QPointF( 9.5, 11.5 )} );
|
||||
|
||||
painter->setPen( pen );
|
||||
painter->drawLine( QPointF( 5.5, 7.5 ), QPointF( 10.5, 12.5 ) );
|
||||
painter->drawLine( QPointF( 12, 6 ), QPointF( 4.5, 13.5 ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DecorationButtonType::Shade:
|
||||
{
|
||||
|
||||
if (isChecked())
|
||||
{
|
||||
|
||||
painter->drawLine( QPointF( 4, 5.5 ), QPointF( 14, 5.5 ) );
|
||||
painter->drawPolyline( QVector<QPointF> {
|
||||
QPointF( 4, 8 ),
|
||||
QPointF( 9, 13 ),
|
||||
QPointF( 14, 8 )} );
|
||||
|
||||
} else {
|
||||
|
||||
painter->drawLine( QPointF( 4, 5.5 ), QPointF( 14, 5.5 ) );
|
||||
painter->drawPolyline( QVector<QPointF> {
|
||||
QPointF( 4, 13 ),
|
||||
QPointF( 9, 8 ),
|
||||
QPointF( 14, 13 ) });
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case DecorationButtonType::KeepBelow:
|
||||
{
|
||||
|
||||
painter->drawPolyline( QVector<QPointF> {
|
||||
QPointF( 4, 5 ),
|
||||
QPointF( 9, 10 ),
|
||||
QPointF( 14, 5 ) });
|
||||
|
||||
painter->drawPolyline( QVector<QPointF> {
|
||||
QPointF( 4, 9 ),
|
||||
QPointF( 9, 14 ),
|
||||
QPointF( 14, 9 ) });
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case DecorationButtonType::KeepAbove:
|
||||
{
|
||||
painter->drawPolyline( QVector<QPointF> {
|
||||
QPointF( 4, 9 ),
|
||||
QPointF( 9, 4 ),
|
||||
QPointF( 14, 9 ) });
|
||||
|
||||
painter->drawPolyline( QVector<QPointF> {
|
||||
QPointF( 4, 13 ),
|
||||
QPointF( 9, 8 ),
|
||||
QPointF( 14, 13 ) });
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case DecorationButtonType::ApplicationMenu:
|
||||
{
|
||||
painter->drawRect( QRectF( 3.5, 4.5, 11, 1 ) );
|
||||
painter->drawRect( QRectF( 3.5, 8.5, 11, 1 ) );
|
||||
painter->drawRect( QRectF( 3.5, 12.5, 11, 1 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case DecorationButtonType::ContextHelp:
|
||||
{
|
||||
QPainterPath path;
|
||||
path.moveTo( 5, 6 );
|
||||
path.arcTo( QRectF( 5, 3.5, 8, 5 ), 180, -180 );
|
||||
path.cubicTo( QPointF(12.5, 9.5), QPointF( 9, 7.5 ), QPointF( 9, 11.5 ) );
|
||||
painter->drawPath( path );
|
||||
|
||||
painter->drawRect( QRectF( 9, 15, 0.5, 0.5 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
QColor Button::foregroundColor() const
|
||||
{
|
||||
auto d = qobject_cast<Decoration*>( decoration() );
|
||||
if( !d ) {
|
||||
|
||||
return QColor();
|
||||
|
||||
} else if( isPressed() ) {
|
||||
|
||||
return d->titleBarColor();
|
||||
|
||||
} else if( type() == DecorationButtonType::Close && d->internalSettings()->outlineCloseButton() ) {
|
||||
|
||||
return d->titleBarColor();
|
||||
|
||||
} else if( ( type() == DecorationButtonType::KeepBelow || type() == DecorationButtonType::KeepAbove || type() == DecorationButtonType::Shade ) && isChecked() ) {
|
||||
|
||||
return d->titleBarColor();
|
||||
|
||||
} else if( m_animation->state() == QAbstractAnimation::Running ) {
|
||||
|
||||
return KColorUtils::mix( d->fontColor(), d->titleBarColor(), m_opacity );
|
||||
|
||||
} else if( isHovered() ) {
|
||||
|
||||
return d->titleBarColor();
|
||||
|
||||
} else {
|
||||
|
||||
return d->fontColor();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
QColor Button::backgroundColor() const
|
||||
{
|
||||
auto d = qobject_cast<Decoration*>( decoration() );
|
||||
if( !d ) {
|
||||
|
||||
return QColor();
|
||||
|
||||
}
|
||||
|
||||
auto c = d->client().data();
|
||||
QColor blueColor( c->palette().color( QPalette::Highlight ) );
|
||||
|
||||
if( isPressed() ) {
|
||||
|
||||
if( type() == DecorationButtonType::Close ) return blueColor.darker();
|
||||
else return KColorUtils::mix( d->titleBarColor(), d->fontColor(), 0.3 );
|
||||
|
||||
} else if( ( type() == DecorationButtonType::KeepBelow || type() == DecorationButtonType::KeepAbove || type() == DecorationButtonType::Shade ) && isChecked() ) {
|
||||
|
||||
return d->fontColor();
|
||||
|
||||
} else if( m_animation->state() == QAbstractAnimation::Running ) {
|
||||
|
||||
if( type() == DecorationButtonType::Close )
|
||||
{
|
||||
if( d->internalSettings()->outlineCloseButton() )
|
||||
{
|
||||
|
||||
return c->isActive() ? KColorUtils::mix( blueColor, blueColor.lighter(), m_opacity ) : KColorUtils::mix( blueColor.lighter(), blueColor, m_opacity );
|
||||
|
||||
} else {
|
||||
|
||||
QColor color( blueColor.lighter() );
|
||||
color.setAlpha( color.alpha()*m_opacity );
|
||||
return color;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
QColor color( d->fontColor() );
|
||||
color.setAlpha( color.alpha()*m_opacity );
|
||||
return color;
|
||||
|
||||
}
|
||||
|
||||
} else if( isHovered() ) {
|
||||
|
||||
if( type() == DecorationButtonType::Close ) return c->isActive() ? blueColor.lighter() : blueColor;
|
||||
else return d->fontColor();
|
||||
|
||||
} else if( type() == DecorationButtonType::Close && d->internalSettings()->outlineCloseButton() ) {
|
||||
|
||||
return c->isActive() ? blueColor : d->fontColor();
|
||||
|
||||
} else {
|
||||
|
||||
return QColor();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Button::reconfigure()
|
||||
{
|
||||
|
||||
// animation
|
||||
auto d = qobject_cast<Decoration*>(decoration());
|
||||
if( d ) m_animation->setDuration( d->animationsDuration() );
|
||||
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
void Button::updateAnimationState( bool hovered )
|
||||
{
|
||||
|
||||
auto d = qobject_cast<Decoration*>(decoration());
|
||||
if( !(d && d->animationsDuration() > 0 ) ) return;
|
||||
|
||||
m_animation->setDirection( hovered ? QAbstractAnimation::Forward : QAbstractAnimation::Backward );
|
||||
if( m_animation->state() != QAbstractAnimation::Running ) m_animation->start();
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -1,124 +0,0 @@
|
||||
#ifndef BREEZE_BUTTONS_H
|
||||
#define BREEZE_BUTTONS_H
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
#include <KDecoration2/DecorationButton>
|
||||
#include "breezedecoration.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QImage>
|
||||
|
||||
class QVariantAnimation;
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
class Button : public KDecoration2::DecorationButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit Button(QObject *parent, const QVariantList &args);
|
||||
|
||||
//* destructor
|
||||
virtual ~Button() = default;
|
||||
|
||||
//* button creation
|
||||
static Button *create(KDecoration2::DecorationButtonType type, KDecoration2::Decoration *decoration, QObject *parent);
|
||||
|
||||
//* render
|
||||
virtual void paint(QPainter *painter, const QRect &repaintRegion) override;
|
||||
|
||||
//* flag
|
||||
enum Flag
|
||||
{
|
||||
FlagNone,
|
||||
FlagStandalone,
|
||||
FlagFirstInList,
|
||||
FlagLastInList
|
||||
};
|
||||
|
||||
//* flag
|
||||
void setFlag( Flag value )
|
||||
{ m_flag = value; }
|
||||
|
||||
//* standalone buttons
|
||||
bool isStandAlone() const { return m_flag == FlagStandalone; }
|
||||
|
||||
//* offset
|
||||
void setOffset( const QPointF& value )
|
||||
{ m_offset = value; }
|
||||
|
||||
//* horizontal offset, for rendering
|
||||
void setHorizontalOffset( qreal value )
|
||||
{ m_offset.setX( value ); }
|
||||
|
||||
//* vertical offset, for rendering
|
||||
void setVerticalOffset( qreal value )
|
||||
{ m_offset.setY( value ); }
|
||||
|
||||
//* set icon size
|
||||
void setIconSize( const QSize& value )
|
||||
{ m_iconSize = value; }
|
||||
|
||||
//*@name active state change animation
|
||||
//@{
|
||||
void setOpacity( qreal value )
|
||||
{
|
||||
if( m_opacity == value ) return;
|
||||
m_opacity = value;
|
||||
update();
|
||||
}
|
||||
|
||||
qreal opacity() const
|
||||
{ return m_opacity; }
|
||||
|
||||
//@}
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
//* apply configuration changes
|
||||
void reconfigure();
|
||||
|
||||
//* animation state
|
||||
void updateAnimationState(bool);
|
||||
|
||||
private:
|
||||
|
||||
//* private constructor
|
||||
explicit Button(KDecoration2::DecorationButtonType type, Decoration *decoration, QObject *parent = nullptr);
|
||||
|
||||
//* draw button icon
|
||||
void drawIcon( QPainter *) const;
|
||||
|
||||
//*@name colors
|
||||
//@{
|
||||
QColor foregroundColor() const;
|
||||
QColor backgroundColor() const;
|
||||
//@}
|
||||
|
||||
Flag m_flag = FlagNone;
|
||||
|
||||
//* active state change animation
|
||||
QVariantAnimation *m_animation;
|
||||
|
||||
//* vertical offset (for rendering)
|
||||
QPointF m_offset;
|
||||
|
||||
//* icon size
|
||||
QSize m_iconSize;
|
||||
|
||||
//* active state change opacity
|
||||
qreal m_opacity = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@ -1,817 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
* SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include "breezedecoration.h"
|
||||
|
||||
#include "breezesettingsprovider.h"
|
||||
#include "config-breeze.h"
|
||||
#include "config/breezeconfigwidget.h"
|
||||
|
||||
#include "breezebutton.h"
|
||||
#include "breezesizegrip.h"
|
||||
|
||||
#include "breezeboxshadowrenderer.h"
|
||||
|
||||
#include <KDecoration2/DecorationButtonGroup>
|
||||
#include <KDecoration2/DecorationShadow>
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KColorUtils>
|
||||
#include <KSharedConfig>
|
||||
#include <KPluginFactory>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QTextStream>
|
||||
#include <QTimer>
|
||||
#include <QDBusConnection>
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(
|
||||
BreezeDecoFactory,
|
||||
"breeze.json",
|
||||
registerPlugin<Breeze::Decoration>();
|
||||
registerPlugin<Breeze::Button>(QStringLiteral("button"));
|
||||
registerPlugin<Breeze::ConfigWidget>(QStringLiteral("kcmodule"));
|
||||
)
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ShadowParams {
|
||||
ShadowParams()
|
||||
: offset(QPoint(0, 0))
|
||||
, radius(0)
|
||||
, opacity(0) {}
|
||||
|
||||
ShadowParams(const QPoint &offset, int radius, qreal opacity)
|
||||
: offset(offset)
|
||||
, radius(radius)
|
||||
, opacity(opacity) {}
|
||||
|
||||
QPoint offset;
|
||||
int radius;
|
||||
qreal opacity;
|
||||
};
|
||||
|
||||
struct CompositeShadowParams {
|
||||
CompositeShadowParams() = default;
|
||||
|
||||
CompositeShadowParams(
|
||||
const QPoint &offset,
|
||||
const ShadowParams &shadow1,
|
||||
const ShadowParams &shadow2)
|
||||
: offset(offset)
|
||||
, shadow1(shadow1)
|
||||
, shadow2(shadow2) {}
|
||||
|
||||
bool isNone() const {
|
||||
return qMax(shadow1.radius, shadow2.radius) == 0;
|
||||
}
|
||||
|
||||
QPoint offset;
|
||||
ShadowParams shadow1;
|
||||
ShadowParams shadow2;
|
||||
};
|
||||
|
||||
const CompositeShadowParams s_shadowParams[] = {
|
||||
// None
|
||||
CompositeShadowParams(),
|
||||
// Small
|
||||
CompositeShadowParams(
|
||||
QPoint(0, 4),
|
||||
ShadowParams(QPoint(0, 0), 16, 1),
|
||||
ShadowParams(QPoint(0, -2), 8, 0.4)),
|
||||
// Medium
|
||||
CompositeShadowParams(
|
||||
QPoint(0, 8),
|
||||
ShadowParams(QPoint(0, 0), 32, 0.9),
|
||||
ShadowParams(QPoint(0, -4), 16, 0.3)),
|
||||
// Large
|
||||
CompositeShadowParams(
|
||||
QPoint(0, 12),
|
||||
ShadowParams(QPoint(0, 0), 48, 0.8),
|
||||
ShadowParams(QPoint(0, -6), 24, 0.2)),
|
||||
// Very large
|
||||
CompositeShadowParams(
|
||||
QPoint(0, 16),
|
||||
ShadowParams(QPoint(0, 0), 64, 0.7),
|
||||
ShadowParams(QPoint(0, -8), 32, 0.1)),
|
||||
};
|
||||
|
||||
inline CompositeShadowParams lookupShadowParams(int size)
|
||||
{
|
||||
switch (size) {
|
||||
case Breeze::InternalSettings::ShadowNone:
|
||||
return s_shadowParams[0];
|
||||
case Breeze::InternalSettings::ShadowSmall:
|
||||
return s_shadowParams[1];
|
||||
case Breeze::InternalSettings::ShadowMedium:
|
||||
return s_shadowParams[2];
|
||||
case Breeze::InternalSettings::ShadowLarge:
|
||||
return s_shadowParams[3];
|
||||
case Breeze::InternalSettings::ShadowVeryLarge:
|
||||
return s_shadowParams[4];
|
||||
default:
|
||||
// Fallback to the Large size.
|
||||
return s_shadowParams[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
using KDecoration2::ColorRole;
|
||||
using KDecoration2::ColorGroup;
|
||||
|
||||
//________________________________________________________________
|
||||
static int g_sDecoCount = 0;
|
||||
static int g_shadowSizeEnum = InternalSettings::ShadowLarge;
|
||||
static int g_shadowStrength = 255;
|
||||
static QColor g_shadowColor = Qt::black;
|
||||
static QSharedPointer<KDecoration2::DecorationShadow> g_sShadow;
|
||||
static QSharedPointer<KDecoration2::DecorationShadow> g_sShadowInactive;
|
||||
|
||||
//________________________________________________________________
|
||||
Decoration::Decoration(QObject *parent, const QVariantList &args)
|
||||
: KDecoration2::Decoration(parent, args)
|
||||
, m_animation( new QVariantAnimation( this ) )
|
||||
, m_shadowAnimation( new QVariantAnimation( this ) )
|
||||
{
|
||||
g_sDecoCount++;
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
Decoration::~Decoration()
|
||||
{
|
||||
g_sDecoCount--;
|
||||
if (g_sDecoCount == 0) {
|
||||
// last deco destroyed, clean up shadow
|
||||
g_sShadow.clear();
|
||||
}
|
||||
|
||||
deleteSizeGrip();
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::setOpacity( qreal value )
|
||||
{
|
||||
if( m_opacity == value ) return;
|
||||
m_opacity = value;
|
||||
update();
|
||||
|
||||
if( m_sizeGrip ) m_sizeGrip->update();
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
QColor Decoration::titleBarColor() const
|
||||
{
|
||||
|
||||
auto c = client().data();
|
||||
if( hideTitleBar() ) return c->color( ColorGroup::Inactive, ColorRole::TitleBar );
|
||||
else if( m_animation->state() == QAbstractAnimation::Running )
|
||||
{
|
||||
return KColorUtils::mix(
|
||||
c->color( ColorGroup::Inactive, ColorRole::TitleBar ),
|
||||
c->color( ColorGroup::Active, ColorRole::TitleBar ),
|
||||
m_opacity );
|
||||
} else return c->color( c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::TitleBar );
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
QColor Decoration::outlineColor() const
|
||||
{
|
||||
|
||||
auto c( client().data() );
|
||||
if( !m_internalSettings->drawTitleBarSeparator() ) return QColor();
|
||||
if( m_animation->state() == QAbstractAnimation::Running )
|
||||
{
|
||||
QColor color( c->palette().color( QPalette::Highlight ) );
|
||||
color.setAlpha( color.alpha()*m_opacity );
|
||||
return color;
|
||||
} else if( c->isActive() ) return c->palette().color( QPalette::Highlight );
|
||||
else return QColor();
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
QColor Decoration::fontColor() const
|
||||
{
|
||||
|
||||
auto c = client().data();
|
||||
if( m_animation->state() == QAbstractAnimation::Running )
|
||||
{
|
||||
return KColorUtils::mix(
|
||||
c->color( ColorGroup::Inactive, ColorRole::Foreground ),
|
||||
c->color( ColorGroup::Active, ColorRole::Foreground ),
|
||||
m_opacity );
|
||||
} else return c->color( c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::Foreground );
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::init()
|
||||
{
|
||||
auto c = client().data();
|
||||
|
||||
// active state change animation
|
||||
// It is important start and end value are of the same type, hence 0.0 and not just 0
|
||||
m_animation->setStartValue( 0.0 );
|
||||
m_animation->setEndValue( 1.0 );
|
||||
// Linear to have the same easing as Breeze animations
|
||||
m_animation->setEasingCurve( QEasingCurve::Linear );
|
||||
connect(m_animation, &QVariantAnimation::valueChanged, this, [this](const QVariant &value) {
|
||||
setOpacity(value.toReal());
|
||||
});
|
||||
|
||||
m_shadowAnimation->setStartValue( 0.0 );
|
||||
m_shadowAnimation->setEndValue( 1.0 );
|
||||
m_shadowAnimation->setEasingCurve( QEasingCurve::InCubic );
|
||||
connect(m_shadowAnimation, &QVariantAnimation::valueChanged, this, [this](const QVariant& value) {
|
||||
m_shadowOpacity = value.toReal();
|
||||
updateShadow();
|
||||
});
|
||||
|
||||
// use DBus connection to update on breeze configuration change
|
||||
auto dbus = QDBusConnection::sessionBus();
|
||||
dbus.connect( QString(),
|
||||
QStringLiteral( "/KGlobalSettings" ),
|
||||
QStringLiteral( "org.kde.KGlobalSettings" ),
|
||||
QStringLiteral( "notifyChange" ), this, SLOT(reconfigure()) );
|
||||
|
||||
reconfigure();
|
||||
updateTitleBar();
|
||||
auto s = settings();
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::borderSizeChanged, this, &Decoration::recalculateBorders);
|
||||
|
||||
// a change in font might cause the borders to change
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::fontChanged, this, &Decoration::recalculateBorders);
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::spacingChanged, this, &Decoration::recalculateBorders);
|
||||
|
||||
// buttons
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::spacingChanged, this, &Decoration::updateButtonsGeometryDelayed);
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::decorationButtonsLeftChanged, this, &Decoration::updateButtonsGeometryDelayed);
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::decorationButtonsRightChanged, this, &Decoration::updateButtonsGeometryDelayed);
|
||||
|
||||
// full reconfiguration
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::reconfigured, this, &Decoration::reconfigure);
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::reconfigured, SettingsProvider::self(), &SettingsProvider::reconfigure, Qt::UniqueConnection );
|
||||
connect(s.data(), &KDecoration2::DecorationSettings::reconfigured, this, &Decoration::updateButtonsGeometryDelayed);
|
||||
|
||||
connect(c, &KDecoration2::DecoratedClient::adjacentScreenEdgesChanged, this, &Decoration::recalculateBorders);
|
||||
connect(c, &KDecoration2::DecoratedClient::maximizedHorizontallyChanged, this, &Decoration::recalculateBorders);
|
||||
connect(c, &KDecoration2::DecoratedClient::maximizedVerticallyChanged, this, &Decoration::recalculateBorders);
|
||||
connect(c, &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::recalculateBorders);
|
||||
connect(c, &KDecoration2::DecoratedClient::captionChanged, this,
|
||||
[this]()
|
||||
{
|
||||
// update the caption area
|
||||
update(titleBar());
|
||||
}
|
||||
);
|
||||
|
||||
connect(c, &KDecoration2::DecoratedClient::activeChanged, this, &Decoration::updateAnimationState);
|
||||
connect(c, &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateTitleBar);
|
||||
connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateTitleBar);
|
||||
connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::setOpaque);
|
||||
|
||||
connect(c, &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateButtonsGeometry);
|
||||
connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateButtonsGeometry);
|
||||
connect(c, &KDecoration2::DecoratedClient::adjacentScreenEdgesChanged, this, &Decoration::updateButtonsGeometry);
|
||||
connect(c, &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::updateButtonsGeometry);
|
||||
|
||||
createButtons();
|
||||
updateShadow();
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::updateTitleBar()
|
||||
{
|
||||
auto s = settings();
|
||||
auto c = client().data();
|
||||
const bool maximized = isMaximized();
|
||||
const int width = maximized ? c->width() : c->width() - 2*s->largeSpacing()*Metrics::TitleBar_SideMargin;
|
||||
const int height = maximized ? borderTop() : borderTop() - s->smallSpacing()*Metrics::TitleBar_TopMargin;
|
||||
const int x = maximized ? 0 : s->largeSpacing()*Metrics::TitleBar_SideMargin;
|
||||
const int y = maximized ? 0 : s->smallSpacing()*Metrics::TitleBar_TopMargin;
|
||||
setTitleBar(QRect(x, y, width, height));
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::updateAnimationState()
|
||||
{
|
||||
if( m_shadowAnimation->duration() > 0 )
|
||||
{
|
||||
|
||||
auto c = client().data();
|
||||
m_shadowAnimation->setDirection( c->isActive() ? QAbstractAnimation::Forward : QAbstractAnimation::Backward );
|
||||
if( m_shadowAnimation->state() != QAbstractAnimation::Running ) m_shadowAnimation->start();
|
||||
|
||||
} else {
|
||||
|
||||
updateShadow();
|
||||
|
||||
}
|
||||
|
||||
if( m_animation->duration() > 0 )
|
||||
{
|
||||
|
||||
auto c = client().data();
|
||||
m_animation->setDirection( c->isActive() ? QAbstractAnimation::Forward : QAbstractAnimation::Backward );
|
||||
if( m_animation->state() != QAbstractAnimation::Running ) m_animation->start();
|
||||
|
||||
} else {
|
||||
|
||||
update();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::updateSizeGripVisibility()
|
||||
{
|
||||
auto c = client().data();
|
||||
if( m_sizeGrip )
|
||||
{ m_sizeGrip->setVisible( c->isResizeable() && !isMaximized() && !c->isShaded() ); }
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
int Decoration::borderSize(bool bottom) const
|
||||
{
|
||||
const int baseSize = settings()->smallSpacing();
|
||||
return baseSize*Metrics::Frame_BorderSize;
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::reconfigure()
|
||||
{
|
||||
|
||||
m_internalSettings = SettingsProvider::self()->internalSettings( this );
|
||||
|
||||
// animation
|
||||
|
||||
KSharedConfig::Ptr config = KSharedConfig::openConfig();
|
||||
const KConfigGroup cg(config, QStringLiteral("KDE"));
|
||||
|
||||
m_animation->setDuration(0);
|
||||
// Syncing anis between client and decoration is troublesome, so we're not using
|
||||
// any animations right now.
|
||||
// m_animation->setDuration( cg.readEntry("AnimationDurationFactor", 1.0f) * 100.0f );
|
||||
|
||||
// But the shadow is fine to animate like this!
|
||||
m_shadowAnimation->setDuration( cg.readEntry("AnimationDurationFactor", 1.0f) * 100.0f );
|
||||
|
||||
// borders
|
||||
recalculateBorders();
|
||||
|
||||
// shadow
|
||||
updateShadow();
|
||||
|
||||
// size grip
|
||||
deleteSizeGrip();
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::recalculateBorders()
|
||||
{
|
||||
auto c = client().data();
|
||||
auto s = settings();
|
||||
|
||||
// left, right and bottom borders
|
||||
const int left = borderSize();
|
||||
const int right = borderSize();
|
||||
const int bottom = c->isShaded() ? 0 : borderSize();
|
||||
|
||||
int top = 0;
|
||||
if( hideTitleBar() ) top = bottom;
|
||||
else {
|
||||
|
||||
QFontMetrics fm(s->font());
|
||||
top += qMax(fm.height(), buttonHeight() );
|
||||
|
||||
// padding below
|
||||
// extra pixel is used for the active window outline
|
||||
const int baseSize = s->smallSpacing();
|
||||
top += baseSize*Metrics::TitleBar_BottomMargin + 1;
|
||||
|
||||
// padding above
|
||||
top += baseSize*TitleBar_TopMargin;
|
||||
|
||||
}
|
||||
|
||||
setBorders(QMargins(left, top, right, bottom));
|
||||
|
||||
// extended sizes
|
||||
const int extSize = s->largeSpacing();
|
||||
int extSides = 0;
|
||||
int extBottom = 0;
|
||||
|
||||
setResizeOnlyBorders(QMargins(extSides, 0, extSides, extBottom));
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::createButtons()
|
||||
{
|
||||
m_leftButtons = new KDecoration2::DecorationButtonGroup(KDecoration2::DecorationButtonGroup::Position::Left, this, &Button::create);
|
||||
m_rightButtons = new KDecoration2::DecorationButtonGroup(KDecoration2::DecorationButtonGroup::Position::Right, this, &Button::create);
|
||||
updateButtonsGeometry();
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::updateButtonsGeometryDelayed()
|
||||
{ QTimer::singleShot( 0, this, &Decoration::updateButtonsGeometry ); }
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::updateButtonsGeometry()
|
||||
{
|
||||
const auto s = settings();
|
||||
|
||||
// adjust button position
|
||||
const int bHeight = captionHeight() + (isTopEdge() ? s->smallSpacing()*Metrics::TitleBar_TopMargin:0);
|
||||
const int bWidth = buttonHeight();
|
||||
const int verticalOffset = (isTopEdge() ? s->smallSpacing()*Metrics::TitleBar_TopMargin:0) + (captionHeight()-buttonHeight())/2;
|
||||
foreach( const QPointer<KDecoration2::DecorationButton>& button, m_leftButtons->buttons() + m_rightButtons->buttons() )
|
||||
{
|
||||
button.data()->setGeometry( QRectF( QPoint( 0, 0 ), QSizeF( bWidth, bHeight ) ) );
|
||||
static_cast<Button*>( button.data() )->setOffset( QPointF( 0, verticalOffset ) );
|
||||
static_cast<Button*>( button.data() )->setIconSize( QSize( bWidth, bWidth ) );
|
||||
}
|
||||
|
||||
// padding
|
||||
const int vPadding = isTopEdge() ? 0 : s->smallSpacing()*Metrics::TitleBar_TopMargin;
|
||||
const int hPadding = s->smallSpacing()*Metrics::TitleBar_SideMargin;
|
||||
|
||||
// left buttons
|
||||
if( !m_leftButtons->buttons().isEmpty() )
|
||||
{
|
||||
// spacing
|
||||
m_leftButtons->setSpacing(s->smallSpacing()*Metrics::TitleBar_ButtonSpacing);
|
||||
m_leftButtons->setPos(QPointF(hPadding + borderLeft(), vPadding));
|
||||
|
||||
}
|
||||
|
||||
// right buttons
|
||||
if( !m_rightButtons->buttons().isEmpty() )
|
||||
{
|
||||
// spacing
|
||||
m_rightButtons->setSpacing(s->smallSpacing()*Metrics::TitleBar_ButtonSpacing);
|
||||
m_rightButtons->setPos(QPointF(size().width() - m_rightButtons->geometry().width() - hPadding - borderRight(), vPadding));
|
||||
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::paint(QPainter *painter, const QRect &repaintRegion)
|
||||
{
|
||||
// TODO: optimize based on repaintRegion
|
||||
auto c = client().data();
|
||||
auto s = settings();
|
||||
const int radius = s->smallSpacing()*Metrics::Frame_FrameRadius;
|
||||
|
||||
// paint background
|
||||
if( !c->isShaded() )
|
||||
{
|
||||
painter->fillRect(rect(), Qt::transparent);
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush( c->color( c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::Frame ) );
|
||||
|
||||
// clip away the top part
|
||||
if( !hideTitleBar() ) painter->setClipRect(0, borderTop(), size().width(), size().height() - borderTop(), Qt::IntersectClip);
|
||||
|
||||
if( s->isAlphaChannelSupported() ) painter->drawRoundedRect(rect(),
|
||||
isBottomEdge() ? 0:radius,
|
||||
isBottomEdge() ? 0:radius);
|
||||
else painter->drawRect( rect() );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
if( !hideTitleBar() ) paintTitleBar(painter, repaintRegion);
|
||||
|
||||
if( !s->isAlphaChannelSupported() )
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
painter->setBrush( Qt::NoBrush );
|
||||
painter->setPen( c->isActive() ?
|
||||
c->color( ColorGroup::Active, ColorRole::TitleBar ):
|
||||
c->color( ColorGroup::Inactive, ColorRole::Foreground ) );
|
||||
|
||||
painter->drawRect( rect().adjusted( 0, 0, -1, -1 ) );
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::paintTitleBar(QPainter *painter, const QRect &repaintRegion)
|
||||
{
|
||||
const auto c = client().data();
|
||||
const QRect titleRect(QPoint(0, 0), QSize(size().width(), borderTop()));
|
||||
|
||||
if ( !titleRect.intersects(repaintRegion) ) return;
|
||||
|
||||
painter->save();
|
||||
painter->setPen(Qt::NoPen);
|
||||
|
||||
// render a linear gradient on title area
|
||||
if( c->isActive() && m_internalSettings->drawBackgroundGradient() )
|
||||
{
|
||||
|
||||
const QColor titleBarColor( this->titleBarColor() );
|
||||
QLinearGradient gradient( 0, 0, 0, titleRect.height() );
|
||||
gradient.setColorAt(0.0, titleBarColor.lighter( 120 ) );
|
||||
gradient.setColorAt(0.8, titleBarColor);
|
||||
painter->setBrush(gradient);
|
||||
|
||||
} else {
|
||||
|
||||
painter->setBrush( titleBarColor() );
|
||||
|
||||
}
|
||||
|
||||
auto s = settings();
|
||||
const int radius = s->smallSpacing()*Metrics::Frame_FrameRadius;
|
||||
if( isMaximized() || !s->isAlphaChannelSupported() )
|
||||
{
|
||||
|
||||
painter->drawRect(titleRect);
|
||||
|
||||
} else if( c->isShaded() ) {
|
||||
|
||||
painter->drawRoundedRect(titleRect, radius, radius);
|
||||
|
||||
} else {
|
||||
|
||||
painter->setClipRect(titleRect, Qt::IntersectClip);
|
||||
|
||||
// the rect is made a little bit larger to be able to clip away the rounded corners at the bottom and sides
|
||||
painter->drawRoundedRect(titleRect.adjusted(
|
||||
isLeftEdge() ? -radius:0,
|
||||
isTopEdge() ? -radius:0,
|
||||
isRightEdge() ? radius:0,
|
||||
radius),
|
||||
radius, radius);
|
||||
|
||||
}
|
||||
|
||||
const QColor outlineColor( this->outlineColor() );
|
||||
if( !c->isShaded() && outlineColor.isValid() )
|
||||
{
|
||||
// outline
|
||||
painter->setRenderHint( QPainter::Antialiasing, false );
|
||||
painter->setBrush( Qt::NoBrush );
|
||||
painter->setPen( outlineColor );
|
||||
painter->drawLine( titleRect.bottomLeft(), titleRect.bottomRight() );
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
|
||||
// draw caption
|
||||
painter->setFont(s->font());
|
||||
painter->setPen( fontColor() );
|
||||
const auto cR = captionRect();
|
||||
const QString caption = painter->fontMetrics().elidedText(c->caption(), Qt::ElideMiddle, cR.first.width());
|
||||
painter->drawText(cR.first, cR.second | Qt::TextSingleLine, caption);
|
||||
|
||||
// draw all buttons
|
||||
m_leftButtons->paint(painter, repaintRegion);
|
||||
m_rightButtons->paint(painter, repaintRegion);
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
int Decoration::buttonHeight() const
|
||||
{
|
||||
const int baseSize = settings()->gridUnit();
|
||||
switch( m_internalSettings->buttonSize() )
|
||||
{
|
||||
case InternalSettings::ButtonTiny: return baseSize;
|
||||
case InternalSettings::ButtonSmall: return baseSize*1.5;
|
||||
default:
|
||||
case InternalSettings::ButtonDefault: return baseSize*2;
|
||||
case InternalSettings::ButtonLarge: return baseSize*2.5;
|
||||
case InternalSettings::ButtonVeryLarge: return baseSize*3.5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
int Decoration::captionHeight() const
|
||||
{ return hideTitleBar() ? borderTop() : borderTop() - settings()->smallSpacing()*(Metrics::TitleBar_BottomMargin + Metrics::TitleBar_TopMargin ) - 1; }
|
||||
|
||||
//________________________________________________________________
|
||||
QPair<QRect,Qt::Alignment> Decoration::captionRect() const
|
||||
{
|
||||
if( hideTitleBar() ) return qMakePair( QRect(), Qt::AlignCenter );
|
||||
else {
|
||||
|
||||
auto c = client().data();
|
||||
const int leftOffset = m_leftButtons->buttons().isEmpty() ?
|
||||
Metrics::TitleBar_SideMargin*settings()->smallSpacing():
|
||||
m_leftButtons->geometry().x() + m_leftButtons->geometry().width() + Metrics::TitleBar_SideMargin*settings()->smallSpacing();
|
||||
|
||||
const int rightOffset = m_rightButtons->buttons().isEmpty() ?
|
||||
Metrics::TitleBar_SideMargin*settings()->smallSpacing() :
|
||||
size().width() - m_rightButtons->geometry().x() + Metrics::TitleBar_SideMargin*settings()->smallSpacing();
|
||||
|
||||
const int yOffset = settings()->smallSpacing()*Metrics::TitleBar_TopMargin;
|
||||
const QRect maxRect( leftOffset, yOffset, size().width() - leftOffset - rightOffset, captionHeight() );
|
||||
|
||||
switch( m_internalSettings->titleAlignment() )
|
||||
{
|
||||
case InternalSettings::AlignLeft:
|
||||
return qMakePair( maxRect, Qt::AlignVCenter|Qt::AlignLeft );
|
||||
|
||||
case InternalSettings::AlignRight:
|
||||
return qMakePair( maxRect, Qt::AlignVCenter|Qt::AlignRight );
|
||||
|
||||
case InternalSettings::AlignCenter:
|
||||
return qMakePair( maxRect, Qt::AlignCenter );
|
||||
|
||||
default:
|
||||
case InternalSettings::AlignCenterFullWidth:
|
||||
{
|
||||
|
||||
// full caption rect
|
||||
const QRect fullRect = QRect( 0, yOffset, size().width(), captionHeight() );
|
||||
QRect boundingRect( settings()->fontMetrics().boundingRect( c->caption()).toRect() );
|
||||
|
||||
// text bounding rect
|
||||
boundingRect.setTop( yOffset );
|
||||
boundingRect.setHeight( captionHeight() );
|
||||
boundingRect.moveLeft( ( size().width() - boundingRect.width() )/2 );
|
||||
|
||||
if( boundingRect.left() < leftOffset ) return qMakePair( maxRect, Qt::AlignVCenter|Qt::AlignLeft );
|
||||
else if( boundingRect.right() > size().width() - rightOffset ) return qMakePair( maxRect, Qt::AlignVCenter|Qt::AlignRight );
|
||||
else return qMakePair(fullRect, Qt::AlignCenter);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
void Decoration::updateShadow()
|
||||
{
|
||||
const auto s = Decoration::settings();
|
||||
|
||||
// Animated case, no cached shadow object
|
||||
if ( (m_shadowAnimation->state() == QAbstractAnimation::Running) && (m_shadowOpacity != 0.0) && (m_shadowOpacity != 1.0) )
|
||||
{
|
||||
setShadow(createShadowObject(m_internalSettings, 0.5 + m_shadowOpacity * 0.5, s->smallSpacing()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_shadowSizeEnum != m_internalSettings->shadowSize()
|
||||
|| g_shadowStrength != m_internalSettings->shadowStrength()
|
||||
|| g_shadowColor != m_internalSettings->shadowColor())
|
||||
{
|
||||
g_sShadow.clear();
|
||||
g_sShadowInactive.clear();
|
||||
g_shadowSizeEnum = m_internalSettings->shadowSize();
|
||||
g_shadowStrength = m_internalSettings->shadowStrength();
|
||||
g_shadowColor = m_internalSettings->shadowColor();
|
||||
}
|
||||
|
||||
auto c = client().toStrongRef();
|
||||
auto& shadow = (c->isActive()) ? g_sShadow : g_sShadowInactive;
|
||||
if ( !shadow )
|
||||
{
|
||||
shadow = createShadowObject(m_internalSettings, c->isActive() ? 1.0 : 0.5, s->smallSpacing());
|
||||
}
|
||||
setShadow(shadow);
|
||||
}
|
||||
|
||||
//________________________________________________________________
|
||||
QSharedPointer<KDecoration2::DecorationShadow> Decoration::createShadowObject(const InternalSettingsPtr& internalSettings, const float strengthScale, const int scale)
|
||||
{
|
||||
const CompositeShadowParams params = lookupShadowParams(internalSettings->shadowSize());
|
||||
if (params.isNone())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto withOpacity = [](const QColor& color, qreal opacity) -> QColor {
|
||||
QColor c(color);
|
||||
c.setAlphaF(opacity);
|
||||
return c;
|
||||
};
|
||||
|
||||
const int radius = scale*Metrics::Frame_FrameRadius;
|
||||
|
||||
const QSize boxSize = BoxShadowRenderer::calculateMinimumBoxSize(params.shadow1.radius)
|
||||
.expandedTo(BoxShadowRenderer::calculateMinimumBoxSize(params.shadow2.radius));
|
||||
|
||||
BoxShadowRenderer shadowRenderer;
|
||||
shadowRenderer.setBorderRadius(radius + 0.5);
|
||||
shadowRenderer.setBoxSize(boxSize);
|
||||
shadowRenderer.setDevicePixelRatio(1.0); // TODO: Create HiDPI shadows?
|
||||
|
||||
const qreal strength = internalSettings->shadowStrength() / 255.0 * strengthScale;
|
||||
shadowRenderer.addShadow(params.shadow1.offset, params.shadow1.radius,
|
||||
withOpacity(internalSettings->shadowColor(), params.shadow1.opacity * strength));
|
||||
shadowRenderer.addShadow(params.shadow2.offset, params.shadow2.radius,
|
||||
withOpacity(internalSettings->shadowColor(), params.shadow2.opacity * strength));
|
||||
|
||||
QImage shadowTexture = shadowRenderer.render();
|
||||
|
||||
QPainter painter(&shadowTexture);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
const QRect outerRect = shadowTexture.rect();
|
||||
|
||||
QRect boxRect(QPoint(0, 0), boxSize);
|
||||
boxRect.moveCenter(outerRect.center());
|
||||
|
||||
// Mask out inner rect.
|
||||
const QMargins padding = QMargins(
|
||||
boxRect.left() - outerRect.left() - Metrics::Shadow_Overlap - params.offset.x(),
|
||||
boxRect.top() - outerRect.top() - Metrics::Shadow_Overlap - params.offset.y(),
|
||||
outerRect.right() - boxRect.right() - Metrics::Shadow_Overlap + params.offset.x(),
|
||||
outerRect.bottom() - boxRect.bottom() - Metrics::Shadow_Overlap + params.offset.y());
|
||||
const QRect innerRect = outerRect - padding;
|
||||
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(Qt::black);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
|
||||
painter.drawRoundedRect(
|
||||
innerRect,
|
||||
radius + 0.5,
|
||||
radius + 0.5);
|
||||
|
||||
// Draw outline.
|
||||
painter.setPen(withOpacity(internalSettings->shadowColor(), 0.2 * strength));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
painter.drawRoundedRect(
|
||||
innerRect,
|
||||
radius - 0.5,
|
||||
radius - 0.5);
|
||||
|
||||
painter.end();
|
||||
|
||||
auto ret = QSharedPointer<KDecoration2::DecorationShadow>::create();
|
||||
ret->setPadding(padding);
|
||||
ret->setInnerShadowRect(QRect(outerRect.center(), QSize(1, 1)));
|
||||
ret->setShadow(shadowTexture);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//_________________________________________________________________
|
||||
void Decoration::createSizeGrip()
|
||||
{
|
||||
|
||||
// do nothing if size grip already exist
|
||||
if( m_sizeGrip ) return;
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
if( !QX11Info::isPlatformX11() ) return;
|
||||
|
||||
// access client
|
||||
auto c = client().data();
|
||||
if( !c ) return;
|
||||
|
||||
if( c->windowId() != 0 )
|
||||
{
|
||||
m_sizeGrip = new SizeGrip( this );
|
||||
connect( c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateSizeGripVisibility );
|
||||
connect( c, &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::updateSizeGripVisibility );
|
||||
connect( c, &KDecoration2::DecoratedClient::resizeableChanged, this, &Decoration::updateSizeGripVisibility );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//_________________________________________________________________
|
||||
void Decoration::deleteSizeGrip()
|
||||
{
|
||||
if( m_sizeGrip )
|
||||
{
|
||||
m_sizeGrip->deleteLater();
|
||||
m_sizeGrip = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#include "breezedecoration.moc"
|
||||
@ -1,170 +0,0 @@
|
||||
#ifndef BREEZE_DECORATION_H
|
||||
#define BREEZE_DECORATION_H
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include "breeze.h"
|
||||
#include "breezesettings.h"
|
||||
|
||||
#include <KDecoration2/Decoration>
|
||||
#include <KDecoration2/DecoratedClient>
|
||||
#include <KDecoration2/DecorationSettings>
|
||||
|
||||
#include <QPalette>
|
||||
#include <QVariant>
|
||||
#include <QVariantAnimation>
|
||||
|
||||
class QVariantAnimation;
|
||||
|
||||
namespace KDecoration2
|
||||
{
|
||||
class DecorationButton;
|
||||
class DecorationButtonGroup;
|
||||
}
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
class SizeGrip;
|
||||
class Decoration : public KDecoration2::Decoration
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit Decoration(QObject *parent = nullptr, const QVariantList &args = QVariantList());
|
||||
|
||||
//* destructor
|
||||
virtual ~Decoration();
|
||||
|
||||
//* paint
|
||||
void paint(QPainter *painter, const QRect &repaintRegion) override;
|
||||
|
||||
//* internal settings
|
||||
InternalSettingsPtr internalSettings() const
|
||||
{ return m_internalSettings; }
|
||||
|
||||
qreal animationsDuration() const
|
||||
{ return m_animation->duration();}
|
||||
|
||||
//* caption height
|
||||
int captionHeight() const;
|
||||
|
||||
//* button height
|
||||
int buttonHeight() const;
|
||||
|
||||
//*@name active state change animation
|
||||
//@{
|
||||
void setOpacity( qreal );
|
||||
|
||||
qreal opacity() const
|
||||
{ return m_opacity; }
|
||||
|
||||
//@}
|
||||
|
||||
//*@name colors
|
||||
//@{
|
||||
QColor titleBarColor() const;
|
||||
QColor outlineColor() const;
|
||||
QColor fontColor() const;
|
||||
//@}
|
||||
|
||||
//*@name maximization modes
|
||||
//@{
|
||||
inline bool isMaximized() const;
|
||||
inline bool isMaximizedHorizontally() const;
|
||||
inline bool isMaximizedVertically() const;
|
||||
|
||||
inline bool isLeftEdge() const;
|
||||
inline bool isRightEdge() const;
|
||||
inline bool isTopEdge() const;
|
||||
inline bool isBottomEdge() const;
|
||||
|
||||
inline bool hideTitleBar() const;
|
||||
//@}
|
||||
|
||||
public Q_SLOTS:
|
||||
void init() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void reconfigure();
|
||||
void recalculateBorders();
|
||||
void updateButtonsGeometry();
|
||||
void updateButtonsGeometryDelayed();
|
||||
void updateTitleBar();
|
||||
void updateAnimationState();
|
||||
void updateSizeGripVisibility();
|
||||
|
||||
private:
|
||||
|
||||
//* return the rect in which caption will be drawn
|
||||
QPair<QRect,Qt::Alignment> captionRect() const;
|
||||
|
||||
void createButtons();
|
||||
void paintTitleBar(QPainter *painter, const QRect &repaintRegion);
|
||||
void updateShadow();
|
||||
static QSharedPointer<KDecoration2::DecorationShadow> createShadowObject(const InternalSettingsPtr& internalSettings, const float strengthScale, const int scale);
|
||||
|
||||
//*@name border size
|
||||
//@{
|
||||
int borderSize(bool bottom = false) const;
|
||||
//@}
|
||||
|
||||
//*@name size grip
|
||||
//@{
|
||||
void createSizeGrip();
|
||||
void deleteSizeGrip();
|
||||
SizeGrip* sizeGrip() const
|
||||
{ return m_sizeGrip; }
|
||||
//@}
|
||||
|
||||
InternalSettingsPtr m_internalSettings;
|
||||
KDecoration2::DecorationButtonGroup *m_leftButtons = nullptr;
|
||||
KDecoration2::DecorationButtonGroup *m_rightButtons = nullptr;
|
||||
|
||||
//* size grip widget
|
||||
SizeGrip *m_sizeGrip = nullptr;
|
||||
|
||||
//* active state change animation
|
||||
QVariantAnimation *m_animation;
|
||||
QVariantAnimation *m_shadowAnimation;
|
||||
|
||||
//* active state change opacity
|
||||
qreal m_opacity = 0;
|
||||
qreal m_shadowOpacity = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
bool Decoration::isMaximized() const
|
||||
{ return client().data()->isMaximized() && !m_internalSettings->drawBorderOnMaximizedWindows(); }
|
||||
|
||||
bool Decoration::isMaximizedHorizontally() const
|
||||
{ return client().data()->isMaximizedHorizontally() && !m_internalSettings->drawBorderOnMaximizedWindows(); }
|
||||
|
||||
bool Decoration::isMaximizedVertically() const
|
||||
{ return client().data()->isMaximizedVertically() && !m_internalSettings->drawBorderOnMaximizedWindows(); }
|
||||
|
||||
bool Decoration::isLeftEdge() const
|
||||
{ return (client().data()->isMaximizedHorizontally() || client().data()->adjacentScreenEdges().testFlag( Qt::LeftEdge ) ) && !m_internalSettings->drawBorderOnMaximizedWindows(); }
|
||||
|
||||
bool Decoration::isRightEdge() const
|
||||
{ return (client().data()->isMaximizedHorizontally() || client().data()->adjacentScreenEdges().testFlag( Qt::RightEdge ) ) && !m_internalSettings->drawBorderOnMaximizedWindows(); }
|
||||
|
||||
bool Decoration::isTopEdge() const
|
||||
{ return (client().data()->isMaximizedVertically() || client().data()->adjacentScreenEdges().testFlag( Qt::TopEdge ) ) && !m_internalSettings->drawBorderOnMaximizedWindows(); }
|
||||
|
||||
bool Decoration::isBottomEdge() const
|
||||
{ return (client().data()->isMaximizedVertically() || client().data()->adjacentScreenEdges().testFlag( Qt::BottomEdge ) ) && !m_internalSettings->drawBorderOnMaximizedWindows(); }
|
||||
|
||||
bool Decoration::hideTitleBar() const
|
||||
{ return m_internalSettings->hideTitleBar() && !client().data()->isShaded(); }
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,112 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeexceptionlist.cpp
|
||||
// window decoration exceptions
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezeexceptionlist.h"
|
||||
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//______________________________________________________________
|
||||
void ExceptionList::readConfig( KSharedConfig::Ptr config )
|
||||
{
|
||||
|
||||
_exceptions.clear();
|
||||
|
||||
QString groupName;
|
||||
for( int index = 0; config->hasGroup( groupName = exceptionGroupName( index ) ); ++index )
|
||||
{
|
||||
|
||||
// create exception
|
||||
InternalSettings exception;
|
||||
|
||||
// reset group
|
||||
readConfig( &exception, config.data(), groupName );
|
||||
|
||||
// create new configuration
|
||||
InternalSettingsPtr configuration( new InternalSettings() );
|
||||
configuration.data()->load();
|
||||
|
||||
// apply changes from exception
|
||||
configuration->setEnabled( exception.enabled() );
|
||||
configuration->setExceptionType( exception.exceptionType() );
|
||||
configuration->setExceptionPattern( exception.exceptionPattern() );
|
||||
configuration->setMask( exception.mask() );
|
||||
|
||||
// propagate all features found in mask to the output configuration
|
||||
if( exception.mask() & BorderSize ) configuration->setBorderSize( exception.borderSize() );
|
||||
configuration->setHideTitleBar( exception.hideTitleBar() );
|
||||
|
||||
// append to exceptions
|
||||
_exceptions.append( configuration );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//______________________________________________________________
|
||||
void ExceptionList::writeConfig( KSharedConfig::Ptr config )
|
||||
{
|
||||
|
||||
// remove all existing exceptions
|
||||
QString groupName;
|
||||
for( int index = 0; config->hasGroup( groupName = exceptionGroupName( index ) ); ++index )
|
||||
{ config->deleteGroup( groupName ); }
|
||||
|
||||
// rewrite current exceptions
|
||||
int index = 0;
|
||||
foreach( const InternalSettingsPtr& exception, _exceptions )
|
||||
{
|
||||
|
||||
writeConfig( exception.data(), config.data(), exceptionGroupName( index ) );
|
||||
++index;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________________________
|
||||
QString ExceptionList::exceptionGroupName( int index )
|
||||
{ return QString( "Windeco Exception %1" ).arg( index ); }
|
||||
|
||||
//______________________________________________________________
|
||||
void ExceptionList::writeConfig( KCoreConfigSkeleton* skeleton, KConfig* config, const QString& groupName )
|
||||
{
|
||||
|
||||
// list of items to be written
|
||||
QStringList keys = { "Enabled", "ExceptionPattern", "ExceptionType", "HideTitleBar", "Mask", "BorderSize"};
|
||||
|
||||
// write all items
|
||||
foreach( auto key, keys )
|
||||
{
|
||||
KConfigSkeletonItem* item( skeleton->findItem( key ) );
|
||||
if( !item ) continue;
|
||||
|
||||
if( !groupName.isEmpty() ) item->setGroup( groupName );
|
||||
KConfigGroup configGroup( config, item->group() );
|
||||
configGroup.writeEntry( item->key(), item->property() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//______________________________________________________________
|
||||
void ExceptionList::readConfig( KCoreConfigSkeleton* skeleton, KConfig* config, const QString& groupName )
|
||||
{
|
||||
|
||||
foreach( KConfigSkeletonItem* item, skeleton->items() )
|
||||
{
|
||||
if( !groupName.isEmpty() ) item->setGroup( groupName );
|
||||
item->readConfig( config );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
#ifndef breezeexceptionlist_h
|
||||
#define breezeexceptionlist_h
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeexceptionlist.h
|
||||
// window decoration exceptions
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezesettings.h"
|
||||
#include "breeze.h"
|
||||
|
||||
#include <KSharedConfig>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//! breeze exceptions list
|
||||
class ExceptionList
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! constructor from list
|
||||
explicit ExceptionList( const InternalSettingsList& exceptions = InternalSettingsList() ):
|
||||
_exceptions( exceptions )
|
||||
{}
|
||||
|
||||
//! exceptions
|
||||
const InternalSettingsList& get( void ) const
|
||||
{ return _exceptions; }
|
||||
|
||||
//! read from KConfig
|
||||
void readConfig( KSharedConfig::Ptr );
|
||||
|
||||
//! write to kconfig
|
||||
void writeConfig( KSharedConfig::Ptr );
|
||||
|
||||
protected:
|
||||
|
||||
//! generate exception group name for given exception index
|
||||
static QString exceptionGroupName( int index );
|
||||
|
||||
//! read configuration
|
||||
static void readConfig( KCoreConfigSkeleton*, KConfig*, const QString& );
|
||||
|
||||
//! write configuration
|
||||
static void writeConfig( KCoreConfigSkeleton*, KConfig*, const QString& );
|
||||
|
||||
private:
|
||||
|
||||
//! exceptions
|
||||
InternalSettingsList _exceptions;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,7 +0,0 @@
|
||||
File=breezesettingsdata.kcfg
|
||||
ClassName=InternalSettings
|
||||
NameSpace=Breeze
|
||||
Singleton=false
|
||||
Mutators=true
|
||||
GlobalEnums=true
|
||||
Notifiers=OutlineCloseButton
|
||||
@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="breezerc"/>
|
||||
|
||||
<!-- common options -->
|
||||
<group name="Common">
|
||||
|
||||
<entry name="ShadowStrength" type = "Int">
|
||||
<default>255</default>
|
||||
<min>25</min>
|
||||
<max>255</max>
|
||||
</entry>
|
||||
|
||||
<!-- shadow -->
|
||||
<entry name="ShadowSize" type = "Enum">
|
||||
<choices>
|
||||
<choice name="ShadowNone"/>
|
||||
<choice name="ShadowSmall"/>
|
||||
<choice name="ShadowMedium"/>
|
||||
<choice name="ShadowLarge"/>
|
||||
<choice name="ShadowVeryLarge"/>
|
||||
</choices>
|
||||
<default>ShadowLarge</default>
|
||||
</entry>
|
||||
|
||||
<entry name="ShadowColor" type = "Color">
|
||||
<default>0, 0, 0</default>
|
||||
</entry>
|
||||
|
||||
<!-- close button -->
|
||||
<entry name="OutlineCloseButton" type = "Bool">
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
</group>
|
||||
|
||||
<group name="Windeco">
|
||||
|
||||
<!-- border size -->
|
||||
<!--
|
||||
this one is used only for window specific settings, since the default is globally set by kwin
|
||||
the enumeration must be kept in sync with kwin's global settings
|
||||
-->
|
||||
<entry name="BorderSize" type = "Enum"></entry>
|
||||
|
||||
<!-- title alignment -->
|
||||
<entry name="TitleAlignment" type="Enum">
|
||||
<choices>
|
||||
<choice name="AlignLeft" />
|
||||
<choice name="AlignCenter" />
|
||||
<choice name="AlignCenterFullWidth" />
|
||||
<choice name="AlignRight" />
|
||||
</choices>
|
||||
<default>AlignCenterFullWidth</default>
|
||||
</entry>
|
||||
|
||||
<!-- button size -->
|
||||
<entry name="ButtonSize" type="Enum">
|
||||
<choices>
|
||||
<choice name="ButtonTiny" />
|
||||
<choice name="ButtonSmall" />
|
||||
<choice name="ButtonDefault" />
|
||||
<choice name="ButtonLarge" />
|
||||
<choice name="ButtonVeryLarge" />
|
||||
</choices>
|
||||
<default>ButtonDefault</default>
|
||||
</entry>
|
||||
|
||||
<!-- maximized windows -->
|
||||
<entry name="DrawBorderOnMaximizedWindows" type = "Bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="DrawTitleBarSeparator" type = "Bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<!-- size grip -->
|
||||
<entry name="DrawBackgroundGradient" type = "Bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<!-- size grip -->
|
||||
<entry name="DrawSizeGrip" type = "Bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<!-- hide title bar -->
|
||||
<entry name="HideTitleBar" type = "Bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<!-- window specific settings -->
|
||||
<entry name="ExceptionType" type="Enum">
|
||||
<choices>
|
||||
<choice name="ExceptionWindowClassName" />
|
||||
<choice name="ExceptionWindowTitle" />
|
||||
</choices>
|
||||
<default>ExceptionWindowClassName</default>
|
||||
</entry>
|
||||
|
||||
<entry name="ExceptionPattern" type = "String"/>
|
||||
|
||||
<entry name="Enabled" type = "Bool">
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="Mask" type = "Int">
|
||||
<default>0</default>
|
||||
</entry>
|
||||
|
||||
</group>
|
||||
|
||||
</kcfg>
|
||||
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include "breezesettingsprovider.h"
|
||||
|
||||
#include "breezeexceptionlist.h"
|
||||
|
||||
#include <KWindowInfo>
|
||||
|
||||
#include <QTextStream>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
SettingsProvider *SettingsProvider::s_self = nullptr;
|
||||
|
||||
//__________________________________________________________________
|
||||
SettingsProvider::SettingsProvider():
|
||||
m_config( KSharedConfig::openConfig( QStringLiteral("breezerc") ) )
|
||||
{ reconfigure(); }
|
||||
|
||||
//__________________________________________________________________
|
||||
SettingsProvider::~SettingsProvider()
|
||||
{ s_self = nullptr; }
|
||||
|
||||
//__________________________________________________________________
|
||||
SettingsProvider *SettingsProvider::self()
|
||||
{
|
||||
// TODO: this is not thread safe!
|
||||
if (!s_self)
|
||||
{ s_self = new SettingsProvider(); }
|
||||
|
||||
return s_self;
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
void SettingsProvider::reconfigure()
|
||||
{
|
||||
if( !m_defaultSettings )
|
||||
{
|
||||
m_defaultSettings = InternalSettingsPtr(new InternalSettings());
|
||||
m_defaultSettings->setCurrentGroup( QStringLiteral("Windeco") );
|
||||
}
|
||||
|
||||
m_defaultSettings->load();
|
||||
|
||||
ExceptionList exceptions;
|
||||
exceptions.readConfig( m_config );
|
||||
m_exceptions = exceptions.get();
|
||||
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
InternalSettingsPtr SettingsProvider::internalSettings( Decoration *decoration ) const
|
||||
{
|
||||
|
||||
QString windowTitle;
|
||||
QString className;
|
||||
|
||||
// get the client
|
||||
auto client = decoration->client().data();
|
||||
|
||||
foreach( auto internalSettings, m_exceptions )
|
||||
{
|
||||
|
||||
// discard disabled exceptions
|
||||
if( !internalSettings->enabled() ) continue;
|
||||
|
||||
// discard exceptions with empty exception pattern
|
||||
if( internalSettings->exceptionPattern().isEmpty() ) continue;
|
||||
|
||||
/*
|
||||
decide which value is to be compared
|
||||
to the regular expression, based on exception type
|
||||
*/
|
||||
QString value;
|
||||
switch( internalSettings->exceptionType() )
|
||||
{
|
||||
case InternalSettings::ExceptionWindowTitle:
|
||||
{
|
||||
value = windowTitle.isEmpty() ? (windowTitle = client->caption()):windowTitle;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
case InternalSettings::ExceptionWindowClassName:
|
||||
{
|
||||
if( className.isEmpty() )
|
||||
{
|
||||
// retrieve class name
|
||||
KWindowInfo info( client->windowId(), nullptr, NET::WM2WindowClass );
|
||||
QString window_className( QString::fromUtf8(info.windowClassName()) );
|
||||
QString window_class( QString::fromUtf8(info.windowClassClass()) );
|
||||
className = window_className + QStringLiteral(" ") + window_class;
|
||||
}
|
||||
|
||||
value = className;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check matching
|
||||
if( QRegExp( internalSettings->exceptionPattern() ).indexIn( value ) >= 0 )
|
||||
{ return internalSettings; }
|
||||
|
||||
}
|
||||
|
||||
return m_defaultSettings;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
#ifndef breezesettingsprovider_h
|
||||
#define breezesettingsprovider_h
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include "breezedecoration.h"
|
||||
#include "breezesettings.h"
|
||||
#include "breeze.h"
|
||||
|
||||
#include <KSharedConfig>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
class SettingsProvider: public QObject
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//* destructor
|
||||
~SettingsProvider();
|
||||
|
||||
//* singleton
|
||||
static SettingsProvider *self();
|
||||
|
||||
//* internal settings for given decoration
|
||||
InternalSettingsPtr internalSettings(Decoration *) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
//* reconfigure
|
||||
void reconfigure();
|
||||
|
||||
private:
|
||||
|
||||
//* constructor
|
||||
SettingsProvider();
|
||||
|
||||
//* default configuration
|
||||
InternalSettingsPtr m_defaultSettings;
|
||||
|
||||
//* exceptions
|
||||
InternalSettingsList m_exceptions;
|
||||
|
||||
//* config object
|
||||
KSharedConfigPtr m_config;
|
||||
|
||||
//* singleton
|
||||
static SettingsProvider *s_self;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,290 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
|
||||
#include "breezesizegrip.h"
|
||||
|
||||
#include <KDecoration2/DecoratedClient>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPolygon>
|
||||
#include <QTimer>
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//* scoped pointer convenience typedef
|
||||
template <typename T> using ScopedPointer = QScopedPointer<T, QScopedPointerPodDeleter>;
|
||||
|
||||
//_____________________________________________
|
||||
SizeGrip::SizeGrip( Decoration* decoration ):QWidget(nullptr)
|
||||
,m_decoration( decoration )
|
||||
{
|
||||
|
||||
setAttribute(Qt::WA_NoSystemBackground );
|
||||
setAutoFillBackground( false );
|
||||
|
||||
// cursor
|
||||
setCursor( Qt::SizeFDiagCursor );
|
||||
|
||||
// size
|
||||
setFixedSize( QSize( GripSize, GripSize ) );
|
||||
|
||||
// mask
|
||||
setMask( QRegion( QVector<QPoint>{
|
||||
QPoint( 0, GripSize ),
|
||||
QPoint( GripSize, 0 ),
|
||||
QPoint( GripSize, GripSize ),
|
||||
QPoint( 0, GripSize )} ) );
|
||||
|
||||
// embed
|
||||
embed();
|
||||
updatePosition();
|
||||
|
||||
// connections
|
||||
auto c = decoration->client().data();
|
||||
connect( c, &KDecoration2::DecoratedClient::widthChanged, this, &SizeGrip::updatePosition );
|
||||
connect( c, &KDecoration2::DecoratedClient::heightChanged, this, &SizeGrip::updatePosition );
|
||||
connect( c, &KDecoration2::DecoratedClient::activeChanged, this, &SizeGrip::updateActiveState );
|
||||
|
||||
// show
|
||||
show();
|
||||
|
||||
}
|
||||
|
||||
//_____________________________________________
|
||||
SizeGrip::~SizeGrip()
|
||||
{}
|
||||
|
||||
//_____________________________________________
|
||||
void SizeGrip::updateActiveState()
|
||||
{
|
||||
#if BREEZE_HAVE_X11
|
||||
if( QX11Info::isPlatformX11() )
|
||||
{
|
||||
const quint32 value = XCB_STACK_MODE_ABOVE;
|
||||
xcb_configure_window( QX11Info::connection(), winId(), XCB_CONFIG_WINDOW_STACK_MODE, &value );
|
||||
xcb_map_window( QX11Info::connection(), winId() );
|
||||
}
|
||||
#endif
|
||||
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
//_____________________________________________
|
||||
void SizeGrip::embed()
|
||||
{
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
|
||||
if( !QX11Info::isPlatformX11() ) return;
|
||||
auto c = m_decoration.data()->client().data();
|
||||
|
||||
xcb_window_t windowId = c->windowId();
|
||||
if( windowId )
|
||||
{
|
||||
|
||||
/*
|
||||
find client's parent
|
||||
we want the size grip to be at the same level as the client in the stack
|
||||
*/
|
||||
xcb_window_t current = windowId;
|
||||
auto connection = QX11Info::connection();
|
||||
xcb_query_tree_cookie_t cookie = xcb_query_tree_unchecked( connection, current );
|
||||
ScopedPointer<xcb_query_tree_reply_t> tree(xcb_query_tree_reply( connection, cookie, nullptr ) );
|
||||
if( !tree.isNull() && tree->parent ) current = tree->parent;
|
||||
|
||||
// reparent
|
||||
xcb_reparent_window( connection, winId(), current, 0, 0 );
|
||||
setWindowTitle( "Breeze::SizeGrip" );
|
||||
|
||||
} else {
|
||||
|
||||
hide();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//_____________________________________________
|
||||
void SizeGrip::paintEvent( QPaintEvent* )
|
||||
{
|
||||
|
||||
if( !m_decoration ) return;
|
||||
|
||||
// get relevant colors
|
||||
const QColor backgroundColor( m_decoration.data()->titleBarColor() );
|
||||
|
||||
// create and configure painter
|
||||
QPainter painter(this);
|
||||
painter.setRenderHints(QPainter::Antialiasing );
|
||||
|
||||
painter.setPen( Qt::NoPen );
|
||||
painter.setBrush( backgroundColor );
|
||||
|
||||
// polygon
|
||||
painter.drawPolygon( QVector<QPoint> {
|
||||
QPoint( 0, GripSize ),
|
||||
QPoint( GripSize, 0 ),
|
||||
QPoint( GripSize, GripSize ),
|
||||
QPoint( 0, GripSize )} );
|
||||
}
|
||||
|
||||
//_____________________________________________
|
||||
void SizeGrip::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
|
||||
switch (event->button())
|
||||
{
|
||||
|
||||
case Qt::RightButton:
|
||||
{
|
||||
hide();
|
||||
QTimer::singleShot(5000, this, &QWidget::show);
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::MiddleButton:
|
||||
{
|
||||
hide();
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::LeftButton:
|
||||
if( rect().contains( event->pos() ) )
|
||||
{ sendMoveResizeEvent( event->pos() ); }
|
||||
break;
|
||||
|
||||
default: break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________________________________
|
||||
void SizeGrip::updatePosition()
|
||||
{
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
if( !QX11Info::isPlatformX11() ) return;
|
||||
|
||||
auto c = m_decoration.data()->client().data();
|
||||
QPoint position(
|
||||
c->width() - GripSize - Offset,
|
||||
c->height() - GripSize - Offset );
|
||||
|
||||
quint32 values[2] = { quint32(position.x()), quint32(position.y()) };
|
||||
xcb_configure_window( QX11Info::connection(), winId(), XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//_____________________________________________
|
||||
void SizeGrip::sendMoveResizeEvent( QPoint position )
|
||||
{
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
if( !QX11Info::isPlatformX11() ) return;
|
||||
|
||||
// pointer to connection
|
||||
auto connection( QX11Info::connection() );
|
||||
|
||||
// client
|
||||
auto c = m_decoration.data()->client().data();
|
||||
|
||||
/*
|
||||
get root position matching position
|
||||
need to use xcb because the embedding of the widget
|
||||
breaks QT's mapToGlobal and other methods
|
||||
*/
|
||||
QPoint rootPosition( position );
|
||||
xcb_get_geometry_cookie_t cookie( xcb_get_geometry( connection, winId() ) );
|
||||
ScopedPointer<xcb_get_geometry_reply_t> reply( xcb_get_geometry_reply( connection, cookie, nullptr ) );
|
||||
if( reply )
|
||||
{
|
||||
|
||||
// translate coordinates
|
||||
xcb_translate_coordinates_cookie_t coordCookie( xcb_translate_coordinates(
|
||||
connection, winId(), reply.data()->root,
|
||||
-reply.data()->border_width,
|
||||
-reply.data()->border_width ) );
|
||||
|
||||
ScopedPointer< xcb_translate_coordinates_reply_t> coordReply( xcb_translate_coordinates_reply( connection, coordCookie, nullptr ) );
|
||||
|
||||
if( coordReply )
|
||||
{
|
||||
rootPosition.rx() += coordReply.data()->dst_x;
|
||||
rootPosition.ry() += coordReply.data()->dst_y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// move/resize atom
|
||||
if( !m_moveResizeAtom )
|
||||
{
|
||||
|
||||
// create atom if not found
|
||||
const QString atomName( "_NET_WM_MOVERESIZE" );
|
||||
xcb_intern_atom_cookie_t cookie( xcb_intern_atom( connection, false, atomName.size(), qPrintable( atomName ) ) );
|
||||
ScopedPointer<xcb_intern_atom_reply_t> reply( xcb_intern_atom_reply( connection, cookie, nullptr ) );
|
||||
m_moveResizeAtom = reply ? reply->atom:0;
|
||||
|
||||
}
|
||||
|
||||
if( !m_moveResizeAtom ) return;
|
||||
|
||||
// button release event
|
||||
xcb_button_release_event_t releaseEvent;
|
||||
memset(&releaseEvent, 0, sizeof(releaseEvent));
|
||||
|
||||
releaseEvent.response_type = XCB_BUTTON_RELEASE;
|
||||
releaseEvent.event = winId();
|
||||
releaseEvent.child = XCB_WINDOW_NONE;
|
||||
releaseEvent.root = QX11Info::appRootWindow();
|
||||
releaseEvent.event_x = position.x();
|
||||
releaseEvent.event_y = position.y();
|
||||
releaseEvent.root_x = rootPosition.x();
|
||||
releaseEvent.root_y = rootPosition.y();
|
||||
releaseEvent.detail = XCB_BUTTON_INDEX_1;
|
||||
releaseEvent.state = XCB_BUTTON_MASK_1;
|
||||
releaseEvent.time = XCB_CURRENT_TIME;
|
||||
releaseEvent.same_screen = true;
|
||||
xcb_send_event( connection, false, winId(), XCB_EVENT_MASK_BUTTON_RELEASE, reinterpret_cast<const char*>(&releaseEvent));
|
||||
|
||||
xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME );
|
||||
|
||||
// move resize event
|
||||
xcb_client_message_event_t clientMessageEvent;
|
||||
memset(&clientMessageEvent, 0, sizeof(clientMessageEvent));
|
||||
|
||||
clientMessageEvent.response_type = XCB_CLIENT_MESSAGE;
|
||||
clientMessageEvent.type = m_moveResizeAtom;
|
||||
clientMessageEvent.format = 32;
|
||||
clientMessageEvent.window = c->windowId();
|
||||
clientMessageEvent.data.data32[0] = rootPosition.x();
|
||||
clientMessageEvent.data.data32[1] = rootPosition.y();
|
||||
clientMessageEvent.data.data32[2] = 4; // bottom right
|
||||
clientMessageEvent.data.data32[3] = Qt::LeftButton;
|
||||
clientMessageEvent.data.data32[4] = 0;
|
||||
|
||||
xcb_send_event( connection, false, QX11Info::appRootWindow(),
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
|
||||
reinterpret_cast<const char*>(&clientMessageEvent) );
|
||||
|
||||
xcb_flush( connection );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef breezesizegrip_h
|
||||
#define breezesizegrip_h
|
||||
|
||||
#include "breezedecoration.h"
|
||||
#include "config-breeze.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QPaintEvent>
|
||||
#include <QWidget>
|
||||
#include <QPointer>
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
#include <xcb/xcb.h>
|
||||
#endif
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//* implements size grip for all widgets
|
||||
class SizeGrip: public QWidget
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit SizeGrip( Decoration* );
|
||||
|
||||
//* constructor
|
||||
virtual ~SizeGrip();
|
||||
|
||||
protected Q_SLOTS:
|
||||
|
||||
//* update background color
|
||||
void updateActiveState();
|
||||
|
||||
//* update position
|
||||
void updatePosition();
|
||||
|
||||
//* embed into parent widget
|
||||
void embed();
|
||||
|
||||
protected:
|
||||
|
||||
//*@name event handlers
|
||||
//@{
|
||||
|
||||
//* paint
|
||||
virtual void paintEvent( QPaintEvent* ) override;
|
||||
|
||||
//* mouse press
|
||||
virtual void mousePressEvent( QMouseEvent* ) override;
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
|
||||
//* send resize event
|
||||
void sendMoveResizeEvent( QPoint );
|
||||
|
||||
//* grip size
|
||||
enum {
|
||||
Offset = 0,
|
||||
GripSize = 14
|
||||
};
|
||||
|
||||
//* decoration
|
||||
QPointer<Decoration> m_decoration;
|
||||
|
||||
//* move/resize atom
|
||||
#if BREEZE_HAVE_X11
|
||||
xcb_atom_t m_moveResizeAtom = 0;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,15 +0,0 @@
|
||||
/* config-breeze.h. Generated by cmake from config-breeze.h.cmake */
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef config_breeze_h
|
||||
#define config_breeze_h
|
||||
|
||||
/* Define to 1 if XCB libraries are found */
|
||||
#cmakedefine01 BREEZE_HAVE_X11
|
||||
|
||||
#endif
|
||||
@ -1,187 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeconfigurationui.cpp
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezeconfigwidget.h"
|
||||
#include "breezeexceptionlist.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//_________________________________________________________
|
||||
ConfigWidget::ConfigWidget( QWidget* parent, const QVariantList &args ):
|
||||
KCModule(parent, args),
|
||||
m_configuration( KSharedConfig::openConfig( QStringLiteral( "breezerc" ) ) ),
|
||||
m_changed( false )
|
||||
{
|
||||
|
||||
// configuration
|
||||
m_ui.setupUi( this );
|
||||
|
||||
// track ui changes
|
||||
connect( m_ui.titleAlignment, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) );
|
||||
connect( m_ui.buttonSize, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) );
|
||||
connect( m_ui.outlineCloseButton, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged );
|
||||
connect( m_ui.drawBorderOnMaximizedWindows, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged );
|
||||
connect( m_ui.drawSizeGrip, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged );
|
||||
connect( m_ui.drawBackgroundGradient, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged );
|
||||
connect( m_ui.drawTitleBarSeparator, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged );
|
||||
|
||||
// track shadows changes
|
||||
connect( m_ui.shadowSize, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) );
|
||||
connect( m_ui.shadowStrength, SIGNAL(valueChanged(int)), SLOT(updateChanged()) );
|
||||
connect( m_ui.shadowColor, &KColorButton::changed, this, &ConfigWidget::updateChanged );
|
||||
|
||||
// track exception changes
|
||||
connect( m_ui.exceptions, &ExceptionListWidget::changed, this, &ConfigWidget::updateChanged );
|
||||
|
||||
}
|
||||
|
||||
//_________________________________________________________
|
||||
void ConfigWidget::load()
|
||||
{
|
||||
|
||||
// create internal settings and load from rc files
|
||||
m_internalSettings = InternalSettingsPtr( new InternalSettings() );
|
||||
m_internalSettings->load();
|
||||
|
||||
// assign to ui
|
||||
m_ui.titleAlignment->setCurrentIndex( m_internalSettings->titleAlignment() );
|
||||
m_ui.buttonSize->setCurrentIndex( m_internalSettings->buttonSize() );
|
||||
m_ui.drawBorderOnMaximizedWindows->setChecked( m_internalSettings->drawBorderOnMaximizedWindows() );
|
||||
m_ui.outlineCloseButton->setChecked( m_internalSettings->outlineCloseButton() );
|
||||
m_ui.drawSizeGrip->setChecked( m_internalSettings->drawSizeGrip() );
|
||||
m_ui.drawBackgroundGradient->setChecked( m_internalSettings->drawBackgroundGradient() );
|
||||
m_ui.drawTitleBarSeparator->setChecked( m_internalSettings->drawTitleBarSeparator() );
|
||||
|
||||
// load shadows
|
||||
if( m_internalSettings->shadowSize() <= InternalSettings::ShadowVeryLarge ) m_ui.shadowSize->setCurrentIndex( m_internalSettings->shadowSize() );
|
||||
else m_ui.shadowSize->setCurrentIndex( InternalSettings::ShadowLarge );
|
||||
|
||||
m_ui.shadowStrength->setValue( qRound(qreal(m_internalSettings->shadowStrength()*100)/255 ) );
|
||||
m_ui.shadowColor->setColor( m_internalSettings->shadowColor() );
|
||||
|
||||
// load exceptions
|
||||
ExceptionList exceptions;
|
||||
exceptions.readConfig( m_configuration );
|
||||
m_ui.exceptions->setExceptions( exceptions.get() );
|
||||
setChanged( false );
|
||||
|
||||
}
|
||||
|
||||
//_________________________________________________________
|
||||
void ConfigWidget::save()
|
||||
{
|
||||
|
||||
// create internal settings and load from rc files
|
||||
m_internalSettings = InternalSettingsPtr( new InternalSettings() );
|
||||
m_internalSettings->load();
|
||||
|
||||
// apply modifications from ui
|
||||
m_internalSettings->setTitleAlignment( m_ui.titleAlignment->currentIndex() );
|
||||
m_internalSettings->setButtonSize( m_ui.buttonSize->currentIndex() );
|
||||
m_internalSettings->setOutlineCloseButton( m_ui.outlineCloseButton->isChecked() );
|
||||
m_internalSettings->setDrawBorderOnMaximizedWindows( m_ui.drawBorderOnMaximizedWindows->isChecked() );
|
||||
m_internalSettings->setDrawSizeGrip( m_ui.drawSizeGrip->isChecked() );
|
||||
m_internalSettings->setDrawBackgroundGradient( m_ui.drawBackgroundGradient->isChecked() );
|
||||
m_internalSettings->setDrawTitleBarSeparator(m_ui.drawTitleBarSeparator->isChecked());
|
||||
|
||||
m_internalSettings->setShadowSize( m_ui.shadowSize->currentIndex() );
|
||||
m_internalSettings->setShadowStrength( qRound( qreal(m_ui.shadowStrength->value()*255)/100 ) );
|
||||
m_internalSettings->setShadowColor( m_ui.shadowColor->color() );
|
||||
|
||||
// save configuration
|
||||
m_internalSettings->save();
|
||||
|
||||
// get list of exceptions and write
|
||||
InternalSettingsList exceptions( m_ui.exceptions->exceptions() );
|
||||
ExceptionList( exceptions ).writeConfig( m_configuration );
|
||||
|
||||
// sync configuration
|
||||
m_configuration->sync();
|
||||
setChanged( false );
|
||||
|
||||
// needed to tell kwin to reload when running from external kcmshell
|
||||
{
|
||||
QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
|
||||
QDBusConnection::sessionBus().send(message);
|
||||
}
|
||||
|
||||
// needed for breeze style to reload shadows
|
||||
{
|
||||
QDBusMessage message( QDBusMessage::createSignal("/BreezeDecoration", "org.kde.Breeze.Style", "reparseConfiguration") );
|
||||
QDBusConnection::sessionBus().send(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//_________________________________________________________
|
||||
void ConfigWidget::defaults()
|
||||
{
|
||||
|
||||
// create internal settings and load from rc files
|
||||
m_internalSettings = InternalSettingsPtr( new InternalSettings() );
|
||||
m_internalSettings->setDefaults();
|
||||
|
||||
// assign to ui
|
||||
m_ui.titleAlignment->setCurrentIndex( m_internalSettings->titleAlignment() );
|
||||
m_ui.buttonSize->setCurrentIndex( m_internalSettings->buttonSize() );
|
||||
m_ui.outlineCloseButton->setChecked( m_internalSettings->outlineCloseButton() );
|
||||
m_ui.drawBorderOnMaximizedWindows->setChecked( m_internalSettings->drawBorderOnMaximizedWindows() );
|
||||
m_ui.drawSizeGrip->setChecked( m_internalSettings->drawSizeGrip() );
|
||||
m_ui.drawBackgroundGradient->setChecked( m_internalSettings->drawBackgroundGradient() );
|
||||
m_ui.drawTitleBarSeparator->setChecked( m_internalSettings->drawTitleBarSeparator() );
|
||||
|
||||
m_ui.shadowSize->setCurrentIndex( m_internalSettings->shadowSize() );
|
||||
m_ui.shadowStrength->setValue( qRound(qreal(m_internalSettings->shadowStrength()*100)/255 ) );
|
||||
m_ui.shadowColor->setColor( m_internalSettings->shadowColor() );
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________
|
||||
void ConfigWidget::updateChanged()
|
||||
{
|
||||
|
||||
// check configuration
|
||||
if( !m_internalSettings ) return;
|
||||
|
||||
// track modifications
|
||||
bool modified( false );
|
||||
|
||||
if (m_ui.drawTitleBarSeparator->isChecked() != m_internalSettings->drawTitleBarSeparator()) modified = true;
|
||||
if( m_ui.titleAlignment->currentIndex() != m_internalSettings->titleAlignment() ) modified = true;
|
||||
else if( m_ui.buttonSize->currentIndex() != m_internalSettings->buttonSize() ) modified = true;
|
||||
else if( m_ui.outlineCloseButton->isChecked() != m_internalSettings->outlineCloseButton() ) modified = true;
|
||||
else if( m_ui.drawBorderOnMaximizedWindows->isChecked() != m_internalSettings->drawBorderOnMaximizedWindows() ) modified = true;
|
||||
else if( m_ui.drawSizeGrip->isChecked() != m_internalSettings->drawSizeGrip() ) modified = true;
|
||||
else if( m_ui.drawBackgroundGradient->isChecked() != m_internalSettings->drawBackgroundGradient() ) modified = true;
|
||||
|
||||
// shadows
|
||||
else if( m_ui.shadowSize->currentIndex() != m_internalSettings->shadowSize() ) modified = true;
|
||||
else if( qRound( qreal(m_ui.shadowStrength->value()*255)/100 ) != m_internalSettings->shadowStrength() ) modified = true;
|
||||
else if( m_ui.shadowColor->color() != m_internalSettings->shadowColor() ) modified = true;
|
||||
|
||||
// exceptions
|
||||
else if( m_ui.exceptions->isChanged() ) modified = true;
|
||||
|
||||
setChanged( modified );
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________
|
||||
void ConfigWidget::setChanged( bool value )
|
||||
{
|
||||
emit changed( value );
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
#ifndef breezeconfigwidget_h
|
||||
#define breezeconfigwidget_h
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeconfigurationui.h
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ui_breezeconfigurationui.h"
|
||||
#include "breezeexceptionlistwidget.h"
|
||||
#include "breezesettings.h"
|
||||
#include "breeze.h"
|
||||
|
||||
#include <KCModule>
|
||||
#include <KSharedConfig>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//_____________________________________________
|
||||
class ConfigWidget: public KCModule
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit ConfigWidget( QWidget*, const QVariantList& );
|
||||
|
||||
//* destructor
|
||||
virtual ~ConfigWidget() = default;
|
||||
|
||||
//* default
|
||||
void defaults() override;
|
||||
|
||||
//* load configuration
|
||||
void load() override;
|
||||
|
||||
//* save configuration
|
||||
void save() override;
|
||||
|
||||
protected Q_SLOTS:
|
||||
|
||||
//* update changed state
|
||||
virtual void updateChanged();
|
||||
|
||||
protected:
|
||||
|
||||
//* set changed state
|
||||
void setChanged( bool );
|
||||
|
||||
private:
|
||||
|
||||
//* ui
|
||||
Ui_BreezeConfigurationUI m_ui;
|
||||
|
||||
//* kconfiguration object
|
||||
KSharedConfig::Ptr m_configuration;
|
||||
|
||||
//* internal exception
|
||||
InternalSettingsPtr m_internalSettings;
|
||||
|
||||
//* changed state
|
||||
bool m_changed;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,166 +0,0 @@
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezedetectwidget.cpp
|
||||
// Note: this class is a stripped down version of
|
||||
// /kdebase/workspace/kwin/kcmkwin/kwinrules/detectwidget.cpp
|
||||
// SPDX-FileCopyrightText: 2004 Lubos Lunak <l.lunak@kde.org>
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezedetectwidget.h"
|
||||
|
||||
#include "breeze.h"
|
||||
|
||||
#include <KWindowInfo>
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QMouseEvent>
|
||||
#include <config-breeze.h>
|
||||
#if BREEZE_HAVE_X11
|
||||
#include <QX11Info>
|
||||
#include <xcb/xcb.h>
|
||||
#endif
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//_________________________________________________________
|
||||
DetectDialog::DetectDialog( QWidget* parent ):
|
||||
QDialog( parent )
|
||||
{
|
||||
|
||||
// setup
|
||||
m_ui.setupUi( this );
|
||||
|
||||
connect( m_ui.buttonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked, this, &QWidget::close );
|
||||
m_ui.windowClassCheckBox->setChecked( true );
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
if (QX11Info::isPlatformX11()) {
|
||||
// create atom
|
||||
xcb_connection_t* connection( QX11Info::connection() );
|
||||
const QString atomName( QStringLiteral( "WM_STATE" ) );
|
||||
xcb_intern_atom_cookie_t cookie( xcb_intern_atom( connection, false, atomName.size(), qPrintable( atomName ) ) );
|
||||
QScopedPointer<xcb_intern_atom_reply_t, QScopedPointerPodDeleter> reply( xcb_intern_atom_reply( connection, cookie, nullptr) );
|
||||
m_wmStateAtom = reply ? reply->atom : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//_________________________________________________________
|
||||
void DetectDialog::detect( WId window )
|
||||
{
|
||||
if( window == 0 ) selectWindow();
|
||||
else readWindow( window );
|
||||
}
|
||||
|
||||
//_________________________________________________________
|
||||
void DetectDialog::readWindow( WId window )
|
||||
{
|
||||
|
||||
if( window == 0 )
|
||||
{
|
||||
emit detectionDone( false );
|
||||
return;
|
||||
}
|
||||
|
||||
m_info.reset(new KWindowInfo( window, NET::WMAllProperties, NET::WM2AllProperties ));
|
||||
if( !m_info->valid())
|
||||
{
|
||||
emit detectionDone( false );
|
||||
return;
|
||||
}
|
||||
|
||||
const QString wmClassClass( QString::fromUtf8( m_info->windowClassClass() ) );
|
||||
const QString wmClassName( QString::fromUtf8( m_info->windowClassName() ) );
|
||||
|
||||
m_ui.windowClass->setText( QStringLiteral( "%1 (%2 %3)" ).arg( wmClassClass ).arg( wmClassName ).arg( wmClassClass ) );
|
||||
m_ui.windowTitle->setText( m_info->name() );
|
||||
emit detectionDone( exec() == QDialog::Accepted );
|
||||
|
||||
}
|
||||
|
||||
//_________________________________________________________
|
||||
void DetectDialog::selectWindow()
|
||||
{
|
||||
|
||||
// use a dialog, so that all user input is blocked
|
||||
// use WX11BypassWM and moving away so that it's not actually visible
|
||||
// grab only mouse, so that keyboard can be used e.g. for switching windows
|
||||
m_grabber = new QDialog( nullptr, Qt::X11BypassWindowManagerHint );
|
||||
m_grabber->move( -1000, -1000 );
|
||||
m_grabber->setModal( true );
|
||||
m_grabber->show();
|
||||
|
||||
// need to explicitly override cursor for Qt5
|
||||
qApp->setOverrideCursor( Qt::CrossCursor );
|
||||
m_grabber->grabMouse( Qt::CrossCursor );
|
||||
m_grabber->installEventFilter( this );
|
||||
|
||||
}
|
||||
|
||||
//_________________________________________________________
|
||||
bool DetectDialog::eventFilter( QObject* o, QEvent* e )
|
||||
{
|
||||
// check object and event type
|
||||
if( o != m_grabber ) return false;
|
||||
if( e->type() != QEvent::MouseButtonRelease ) return false;
|
||||
|
||||
// need to explicitly release cursor for Qt5
|
||||
qApp->restoreOverrideCursor();
|
||||
|
||||
// delete old m_grabber
|
||||
delete m_grabber;
|
||||
m_grabber = nullptr;
|
||||
|
||||
// check button
|
||||
if( static_cast< QMouseEvent* >( e )->button() != Qt::LeftButton ) return true;
|
||||
|
||||
// read window information
|
||||
readWindow( findWindow() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//_________________________________________________________
|
||||
WId DetectDialog::findWindow()
|
||||
{
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
if (!QX11Info::isPlatformX11()) {
|
||||
return 0;
|
||||
}
|
||||
// check atom
|
||||
if( !m_wmStateAtom ) return 0;
|
||||
|
||||
xcb_connection_t* connection( QX11Info::connection() );
|
||||
xcb_window_t parent( QX11Info::appRootWindow() );
|
||||
|
||||
// why is there a loop of only 10 here
|
||||
for( int i = 0; i < 10; ++i )
|
||||
{
|
||||
|
||||
// query pointer
|
||||
xcb_query_pointer_cookie_t pointerCookie( xcb_query_pointer( connection, parent ) );
|
||||
QScopedPointer<xcb_query_pointer_reply_t, QScopedPointerPodDeleter> pointerReply( xcb_query_pointer_reply( connection, pointerCookie, nullptr ) );
|
||||
if( !( pointerReply && pointerReply->child ) ) return 0;
|
||||
|
||||
const xcb_window_t child( pointerReply->child );
|
||||
xcb_get_property_cookie_t cookie( xcb_get_property( connection, 0, child, m_wmStateAtom, XCB_GET_PROPERTY_TYPE_ANY, 0, 0 ) );
|
||||
QScopedPointer<xcb_get_property_reply_t, QScopedPointerPodDeleter> reply( xcb_get_property_reply( connection, cookie, nullptr ) );
|
||||
if( reply && reply->type ) return child;
|
||||
else parent = child;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
#ifndef breezedetectwidget_h
|
||||
#define breezedetectwidget_h
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezedetectwidget.h
|
||||
// Note: this class is a stripped down version of
|
||||
// /kdebase/workspace/kwin/kcmkwin/kwinrules/detectwidget.h
|
||||
// SPDX-FileCopyrightText: 2004 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezesettings.h"
|
||||
#include "ui_breezedetectwidget.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <QEvent>
|
||||
#include <QLabel>
|
||||
|
||||
#include <kwindowsystem.h>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
class DetectDialog : public QDialog
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit DetectDialog( QWidget* );
|
||||
|
||||
//* read window properties or select one from mouse grab
|
||||
void detect( WId window );
|
||||
|
||||
//* selected class
|
||||
QByteArray selectedClass() const;
|
||||
|
||||
//* window information
|
||||
const KWindowInfo& windowInfo() const
|
||||
{ return *(m_info.data()); }
|
||||
|
||||
//* exception type
|
||||
InternalSettings::EnumExceptionType exceptionType() const
|
||||
{
|
||||
if( m_ui.windowClassCheckBox->isChecked() ) return InternalSettings::ExceptionWindowClassName;
|
||||
else if( m_ui.windowTitleCheckBox->isChecked() ) return InternalSettings::ExceptionWindowTitle;
|
||||
else return InternalSettings::ExceptionWindowClassName;
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
void detectionDone( bool );
|
||||
|
||||
protected:
|
||||
|
||||
bool eventFilter( QObject* o, QEvent* e ) override;
|
||||
|
||||
private:
|
||||
|
||||
//* select window from grab
|
||||
void selectWindow();
|
||||
|
||||
//* read window properties
|
||||
void readWindow( WId window );
|
||||
|
||||
//* find window under cursor
|
||||
WId findWindow();
|
||||
|
||||
//* execute
|
||||
void executeDialog();
|
||||
|
||||
//* ui
|
||||
Ui::BreezeDetectWidget m_ui;
|
||||
|
||||
//* invisible dialog used to grab mouse
|
||||
QDialog* m_grabber = nullptr;
|
||||
|
||||
//* current window information
|
||||
QScopedPointer<KWindowInfo> m_info;
|
||||
|
||||
//* wm state atom
|
||||
quint32 m_wmStateAtom = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@ -1,168 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeexceptiondialog.cpp
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezeexceptiondialog.h"
|
||||
#include "breezedetectwidget.h"
|
||||
#include "config-breeze.h"
|
||||
|
||||
#if BREEZE_HAVE_X11
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//___________________________________________
|
||||
ExceptionDialog::ExceptionDialog( QWidget* parent ):
|
||||
QDialog( parent )
|
||||
{
|
||||
|
||||
m_ui.setupUi( this );
|
||||
|
||||
connect( m_ui.buttonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked, this, &QWidget::close );
|
||||
|
||||
// store checkboxes from ui into list
|
||||
m_checkboxes.insert( BorderSize, m_ui.borderSizeCheckBox );
|
||||
|
||||
// detect window properties
|
||||
connect( m_ui.detectDialogButton, &QAbstractButton::clicked, this, &ExceptionDialog::selectWindowProperties );
|
||||
|
||||
// connections
|
||||
connect( m_ui.exceptionType, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) );
|
||||
connect( m_ui.exceptionEditor, &QLineEdit::textChanged, this, &ExceptionDialog::updateChanged );
|
||||
connect( m_ui.borderSizeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateChanged()) );
|
||||
|
||||
for( CheckBoxMap::iterator iter = m_checkboxes.begin(); iter != m_checkboxes.end(); ++iter )
|
||||
{ connect( iter.value(), &QAbstractButton::clicked, this, &ExceptionDialog::updateChanged ); }
|
||||
|
||||
connect( m_ui.hideTitleBar, &QAbstractButton::clicked, this, &ExceptionDialog::updateChanged );
|
||||
|
||||
// hide detection dialog on non X11 platforms
|
||||
#if BREEZE_HAVE_X11
|
||||
if( !QX11Info::isPlatformX11() ) m_ui.detectDialogButton->hide();
|
||||
#else
|
||||
m_ui.detectDialogButton->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
//___________________________________________
|
||||
void ExceptionDialog::setException( InternalSettingsPtr exception )
|
||||
{
|
||||
|
||||
// store exception internally
|
||||
m_exception = exception;
|
||||
|
||||
// type
|
||||
m_ui.exceptionType->setCurrentIndex(m_exception->exceptionType() );
|
||||
m_ui.exceptionEditor->setText( m_exception->exceptionPattern() );
|
||||
m_ui.borderSizeComboBox->setCurrentIndex( m_exception->borderSize() );
|
||||
m_ui.hideTitleBar->setChecked( m_exception->hideTitleBar() );
|
||||
|
||||
// mask
|
||||
for( CheckBoxMap::iterator iter = m_checkboxes.begin(); iter != m_checkboxes.end(); ++iter )
|
||||
{ iter.value()->setChecked( m_exception->mask() & iter.key() ); }
|
||||
|
||||
setChanged( false );
|
||||
|
||||
}
|
||||
|
||||
//___________________________________________
|
||||
void ExceptionDialog::save()
|
||||
{
|
||||
m_exception->setExceptionType( m_ui.exceptionType->currentIndex() );
|
||||
m_exception->setExceptionPattern( m_ui.exceptionEditor->text() );
|
||||
m_exception->setBorderSize( m_ui.borderSizeComboBox->currentIndex() );
|
||||
m_exception->setHideTitleBar( m_ui.hideTitleBar->isChecked() );
|
||||
|
||||
// mask
|
||||
unsigned int mask = None;
|
||||
for( CheckBoxMap::iterator iter = m_checkboxes.begin(); iter != m_checkboxes.end(); ++iter )
|
||||
{ if( iter.value()->isChecked() ) mask |= iter.key(); }
|
||||
|
||||
m_exception->setMask( mask );
|
||||
|
||||
setChanged( false );
|
||||
|
||||
}
|
||||
|
||||
//___________________________________________
|
||||
void ExceptionDialog::updateChanged()
|
||||
{
|
||||
bool modified( false );
|
||||
if( m_exception->exceptionType() != m_ui.exceptionType->currentIndex() ) modified = true;
|
||||
else if( m_exception->exceptionPattern() != m_ui.exceptionEditor->text() ) modified = true;
|
||||
else if( m_exception->borderSize() != m_ui.borderSizeComboBox->currentIndex() ) modified = true;
|
||||
else if( m_exception->hideTitleBar() != m_ui.hideTitleBar->isChecked() ) modified = true;
|
||||
else
|
||||
{
|
||||
// check mask
|
||||
for( CheckBoxMap::iterator iter = m_checkboxes.begin(); iter != m_checkboxes.end(); ++iter )
|
||||
{
|
||||
if( iter.value()->isChecked() != (bool)( m_exception->mask() & iter.key() ) )
|
||||
{
|
||||
modified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setChanged( modified );
|
||||
|
||||
}
|
||||
|
||||
//___________________________________________
|
||||
void ExceptionDialog::selectWindowProperties()
|
||||
{
|
||||
|
||||
// create widget
|
||||
if( !m_detectDialog )
|
||||
{
|
||||
m_detectDialog = new DetectDialog( this );
|
||||
connect( m_detectDialog, &DetectDialog::detectionDone, this, &ExceptionDialog::readWindowProperties );
|
||||
}
|
||||
|
||||
m_detectDialog->detect(0);
|
||||
|
||||
}
|
||||
|
||||
//___________________________________________
|
||||
void ExceptionDialog::readWindowProperties( bool valid )
|
||||
{
|
||||
Q_CHECK_PTR( m_detectDialog );
|
||||
if( valid )
|
||||
{
|
||||
|
||||
// type
|
||||
m_ui.exceptionType->setCurrentIndex( m_detectDialog->exceptionType() );
|
||||
|
||||
// window info
|
||||
const KWindowInfo& info( m_detectDialog->windowInfo() );
|
||||
|
||||
switch( m_detectDialog->exceptionType() )
|
||||
{
|
||||
|
||||
default:
|
||||
case InternalSettings::ExceptionWindowClassName:
|
||||
m_ui.exceptionEditor->setText( QString::fromUtf8( info.windowClassClass() ) );
|
||||
break;
|
||||
|
||||
case InternalSettings::ExceptionWindowTitle:
|
||||
m_ui.exceptionEditor->setText( info.name() );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delete m_detectDialog;
|
||||
m_detectDialog = nullptr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,98 +0,0 @@
|
||||
#ifndef breezeexceptiondialog_h
|
||||
#define breezeexceptiondialog_h
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeexceptiondialog.h
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ui_breezeexceptiondialog.h"
|
||||
#include "breeze.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QMap>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
class DetectDialog;
|
||||
|
||||
//* breeze exceptions list
|
||||
class ExceptionDialog: public QDialog
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit ExceptionDialog( QWidget* parent );
|
||||
|
||||
//* destructor
|
||||
virtual ~ExceptionDialog()
|
||||
{}
|
||||
|
||||
//* set exception
|
||||
void setException( InternalSettingsPtr );
|
||||
|
||||
//* save exception
|
||||
void save();
|
||||
|
||||
//* true if changed
|
||||
virtual bool isChanged() const
|
||||
{ return m_changed; }
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
//* emitted when changed
|
||||
void changed( bool );
|
||||
|
||||
protected:
|
||||
|
||||
//* set changed state
|
||||
virtual void setChanged( bool value )
|
||||
{
|
||||
m_changed = value;
|
||||
emit changed( value );
|
||||
}
|
||||
|
||||
protected Q_SLOTS:
|
||||
|
||||
//* check whether configuration is changed and emit appropriate signal if yes
|
||||
virtual void updateChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
//* select window properties from grabbed pointers
|
||||
void selectWindowProperties();
|
||||
|
||||
//* read properties of selected window
|
||||
void readWindowProperties( bool );
|
||||
|
||||
private:
|
||||
|
||||
//* map mask and checkbox
|
||||
using CheckBoxMap=QMap< ExceptionMask, QCheckBox*>;
|
||||
|
||||
Ui::BreezeExceptionDialog m_ui;
|
||||
|
||||
//* map mask and checkbox
|
||||
CheckBoxMap m_checkboxes;
|
||||
|
||||
//* internal exception
|
||||
InternalSettingsPtr m_exception;
|
||||
|
||||
//* detection dialog
|
||||
DetectDialog* m_detectDialog = nullptr;
|
||||
|
||||
//* changed state
|
||||
bool m_changed = false;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,329 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeexceptionlistwidget.cpp
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezeexceptionlistwidget.h"
|
||||
#include "breezeexceptiondialog.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPointer>
|
||||
#include <QIcon>
|
||||
|
||||
//__________________________________________________________
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//__________________________________________________________
|
||||
ExceptionListWidget::ExceptionListWidget( QWidget* parent ):
|
||||
QWidget( parent )
|
||||
{
|
||||
|
||||
// ui
|
||||
m_ui.setupUi( this );
|
||||
|
||||
// list
|
||||
m_ui.exceptionListView->setAllColumnsShowFocus( true );
|
||||
m_ui.exceptionListView->setRootIsDecorated( false );
|
||||
m_ui.exceptionListView->setSortingEnabled( false );
|
||||
m_ui.exceptionListView->setModel( &model() );
|
||||
m_ui.exceptionListView->sortByColumn( ExceptionModel::ColumnType, Qt::AscendingOrder );
|
||||
m_ui.exceptionListView->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Ignored ) );
|
||||
|
||||
m_ui.moveUpButton->setIcon( QIcon::fromTheme( QStringLiteral( "arrow-up" ) ) );
|
||||
m_ui.moveDownButton->setIcon( QIcon::fromTheme( QStringLiteral( "arrow-down" ) ) );
|
||||
m_ui.addButton->setIcon( QIcon::fromTheme( QStringLiteral( "list-add" ) ) );
|
||||
m_ui.removeButton->setIcon( QIcon::fromTheme( QStringLiteral( "list-remove" ) ) );
|
||||
m_ui.editButton->setIcon( QIcon::fromTheme( QStringLiteral( "edit-rename" ) ) );
|
||||
|
||||
connect( m_ui.addButton, &QAbstractButton::clicked, this, &ExceptionListWidget::add );
|
||||
connect( m_ui.editButton, &QAbstractButton::clicked, this, &ExceptionListWidget::edit );
|
||||
connect( m_ui.removeButton, &QAbstractButton::clicked, this, &ExceptionListWidget::remove );
|
||||
connect( m_ui.moveUpButton, &QAbstractButton::clicked, this, &ExceptionListWidget::up );
|
||||
connect( m_ui.moveDownButton, &QAbstractButton::clicked, this, &ExceptionListWidget::down );
|
||||
|
||||
connect( m_ui.exceptionListView, &QAbstractItemView::activated, this, &ExceptionListWidget::edit );
|
||||
connect( m_ui.exceptionListView, &QAbstractItemView::clicked, this, &ExceptionListWidget::toggle );
|
||||
connect( m_ui.exceptionListView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ExceptionListWidget::updateButtons );
|
||||
|
||||
updateButtons();
|
||||
resizeColumns();
|
||||
|
||||
|
||||
}
|
||||
|
||||
//__________________________________________________________
|
||||
void ExceptionListWidget::setExceptions( const InternalSettingsList& exceptions )
|
||||
{
|
||||
model().set( exceptions );
|
||||
resizeColumns();
|
||||
setChanged( false );
|
||||
}
|
||||
|
||||
//__________________________________________________________
|
||||
InternalSettingsList ExceptionListWidget::exceptions()
|
||||
{
|
||||
return model().get();
|
||||
setChanged( false );
|
||||
}
|
||||
|
||||
//__________________________________________________________
|
||||
void ExceptionListWidget::updateButtons()
|
||||
{
|
||||
|
||||
bool hasSelection( !m_ui.exceptionListView->selectionModel()->selectedRows().empty() );
|
||||
m_ui.removeButton->setEnabled( hasSelection );
|
||||
m_ui.editButton->setEnabled( hasSelection );
|
||||
|
||||
m_ui.moveUpButton->setEnabled( hasSelection && !m_ui.exceptionListView->selectionModel()->isRowSelected( 0, QModelIndex() ) );
|
||||
m_ui.moveDownButton->setEnabled( hasSelection && !m_ui.exceptionListView->selectionModel()->isRowSelected( model().rowCount()-1, QModelIndex() ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
//_______________________________________________________
|
||||
void ExceptionListWidget::add()
|
||||
{
|
||||
|
||||
|
||||
QPointer<ExceptionDialog> dialog = new ExceptionDialog( this );
|
||||
dialog->setWindowTitle( i18n( "New Exception - Breeze Settings" ) );
|
||||
InternalSettingsPtr exception( new InternalSettings() );
|
||||
|
||||
exception->load();
|
||||
|
||||
dialog->setException( exception );
|
||||
|
||||
// run dialog and check existence
|
||||
if( !dialog->exec() )
|
||||
{
|
||||
delete dialog;
|
||||
return;
|
||||
}
|
||||
|
||||
dialog->save();
|
||||
delete dialog;
|
||||
|
||||
// check exceptions
|
||||
if( !checkException( exception ) ) return;
|
||||
|
||||
// create new item
|
||||
model().add( exception );
|
||||
setChanged( true );
|
||||
|
||||
// make sure item is selected
|
||||
QModelIndex index( model().index( exception ) );
|
||||
if( index != m_ui.exceptionListView->selectionModel()->currentIndex() )
|
||||
{
|
||||
m_ui.exceptionListView->selectionModel()->select( index, QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Rows );
|
||||
m_ui.exceptionListView->selectionModel()->setCurrentIndex( index, QItemSelectionModel::Current|QItemSelectionModel::Rows );
|
||||
}
|
||||
|
||||
resizeColumns();
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
void ExceptionListWidget::edit()
|
||||
{
|
||||
|
||||
// retrieve selection
|
||||
QModelIndex current( m_ui.exceptionListView->selectionModel()->currentIndex() );
|
||||
if( ! model().contains( current ) ) return;
|
||||
|
||||
InternalSettingsPtr exception( model().get( current ) );
|
||||
|
||||
// create dialog
|
||||
QPointer<ExceptionDialog> dialog( new ExceptionDialog( this ) );
|
||||
dialog->setWindowTitle( i18n( "Edit Exception - Breeze Settings" ) );
|
||||
dialog->setException( exception );
|
||||
|
||||
// map dialog
|
||||
if( !dialog->exec() )
|
||||
{
|
||||
delete dialog;
|
||||
return;
|
||||
}
|
||||
|
||||
// check modifications
|
||||
if( !dialog->isChanged() ) return;
|
||||
|
||||
// retrieve exception
|
||||
dialog->save();
|
||||
delete dialog;
|
||||
|
||||
// check new exception validity
|
||||
checkException( exception );
|
||||
resizeColumns();
|
||||
|
||||
setChanged( true );
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
void ExceptionListWidget::remove()
|
||||
{
|
||||
|
||||
// confirmation dialog
|
||||
{
|
||||
QMessageBox messageBox( QMessageBox::Question, i18n("Question - Breeze Settings" ), i18n("Remove selected exception?"), QMessageBox::Yes | QMessageBox::Cancel );
|
||||
messageBox.button( QMessageBox::Yes )->setText( i18n("Remove") );
|
||||
messageBox.setDefaultButton( QMessageBox::Cancel );
|
||||
if( messageBox.exec() == QMessageBox::Cancel ) return;
|
||||
}
|
||||
|
||||
// remove
|
||||
model().remove( model().get( m_ui.exceptionListView->selectionModel()->selectedRows() ) );
|
||||
resizeColumns();
|
||||
updateButtons();
|
||||
|
||||
setChanged( true );
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
void ExceptionListWidget::toggle( const QModelIndex& index )
|
||||
{
|
||||
|
||||
if( !model().contains( index ) ) return;
|
||||
if( index.column() != ExceptionModel::ColumnEnabled ) return;
|
||||
|
||||
// get matching exception
|
||||
InternalSettingsPtr exception( model().get( index ) );
|
||||
exception->setEnabled( !exception->enabled() );
|
||||
setChanged( true );
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
void ExceptionListWidget::up()
|
||||
{
|
||||
|
||||
InternalSettingsList selection( model().get( m_ui.exceptionListView->selectionModel()->selectedRows() ) );
|
||||
if( selection.empty() ) { return; }
|
||||
|
||||
// retrieve selected indexes in list and store in model
|
||||
QModelIndexList selectedIndices( m_ui.exceptionListView->selectionModel()->selectedRows() );
|
||||
InternalSettingsList selectedExceptions( model().get( selectedIndices ) );
|
||||
|
||||
InternalSettingsList currentException( model().get() );
|
||||
InternalSettingsList newExceptions;
|
||||
|
||||
for( InternalSettingsList::const_iterator iter = currentException.constBegin(); iter != currentException.constEnd(); ++iter )
|
||||
{
|
||||
|
||||
// check if new list is not empty, current index is selected and last index is not.
|
||||
// if yes, move.
|
||||
if(
|
||||
!( newExceptions.empty() ||
|
||||
selectedIndices.indexOf( model().index( *iter ) ) == -1 ||
|
||||
selectedIndices.indexOf( model().index( newExceptions.back() ) ) != -1
|
||||
) )
|
||||
{
|
||||
InternalSettingsPtr last( newExceptions.back() );
|
||||
newExceptions.removeLast();
|
||||
newExceptions.append( *iter );
|
||||
newExceptions.append( last );
|
||||
} else newExceptions.append( *iter );
|
||||
|
||||
}
|
||||
|
||||
model().set( newExceptions );
|
||||
|
||||
// restore selection
|
||||
m_ui.exceptionListView->selectionModel()->select( model().index( selectedExceptions.front() ), QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Rows );
|
||||
for( InternalSettingsList::const_iterator iter = selectedExceptions.constBegin(); iter != selectedExceptions.constEnd(); ++iter )
|
||||
{ m_ui.exceptionListView->selectionModel()->select( model().index( *iter ), QItemSelectionModel::Select|QItemSelectionModel::Rows ); }
|
||||
|
||||
setChanged( true );
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
void ExceptionListWidget::down()
|
||||
{
|
||||
|
||||
InternalSettingsList selection( model().get( m_ui.exceptionListView->selectionModel()->selectedRows() ) );
|
||||
if( selection.empty() )
|
||||
{ return; }
|
||||
|
||||
// retrieve selected indexes in list and store in model
|
||||
QModelIndexList selectedIndices( m_ui.exceptionListView->selectionModel()->selectedIndexes() );
|
||||
InternalSettingsList selectedExceptions( model().get( selectedIndices ) );
|
||||
|
||||
InternalSettingsList currentExceptions( model().get() );
|
||||
InternalSettingsList newExceptions;
|
||||
|
||||
InternalSettingsListIterator iter( currentExceptions );
|
||||
iter.toBack();
|
||||
while( iter.hasPrevious() )
|
||||
{
|
||||
|
||||
InternalSettingsPtr current( iter.previous() );
|
||||
|
||||
// check if new list is not empty, current index is selected and last index is not.
|
||||
// if yes, move.
|
||||
if(
|
||||
!( newExceptions.empty() ||
|
||||
selectedIndices.indexOf( model().index( current ) ) == -1 ||
|
||||
selectedIndices.indexOf( model().index( newExceptions.front() ) ) != -1
|
||||
) )
|
||||
{
|
||||
|
||||
InternalSettingsPtr first( newExceptions.front() );
|
||||
newExceptions.removeFirst();
|
||||
newExceptions.prepend( current );
|
||||
newExceptions.prepend( first );
|
||||
|
||||
} else newExceptions.prepend( current );
|
||||
}
|
||||
|
||||
model().set( newExceptions );
|
||||
|
||||
// restore selection
|
||||
m_ui.exceptionListView->selectionModel()->select( model().index( selectedExceptions.front() ), QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Rows );
|
||||
for( InternalSettingsList::const_iterator iter = selectedExceptions.constBegin(); iter != selectedExceptions.constEnd(); ++iter )
|
||||
{ m_ui.exceptionListView->selectionModel()->select( model().index( *iter ), QItemSelectionModel::Select|QItemSelectionModel::Rows ); }
|
||||
|
||||
setChanged( true );
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
void ExceptionListWidget::resizeColumns() const
|
||||
{
|
||||
m_ui.exceptionListView->resizeColumnToContents( ExceptionModel::ColumnEnabled );
|
||||
m_ui.exceptionListView->resizeColumnToContents( ExceptionModel::ColumnType );
|
||||
m_ui.exceptionListView->resizeColumnToContents( ExceptionModel::ColumnRegExp );
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
bool ExceptionListWidget::checkException( InternalSettingsPtr exception )
|
||||
{
|
||||
|
||||
while( exception->exceptionPattern().isEmpty() || !QRegExp( exception->exceptionPattern() ).isValid() )
|
||||
{
|
||||
|
||||
QMessageBox::warning( this, i18n( "Warning - Breeze Settings" ), i18n("Regular Expression syntax is incorrect") );
|
||||
QPointer<ExceptionDialog> dialog( new ExceptionDialog( this ) );
|
||||
dialog->setException( exception );
|
||||
if( dialog->exec() == QDialog::Rejected )
|
||||
{
|
||||
delete dialog;
|
||||
return false;
|
||||
}
|
||||
|
||||
dialog->save();
|
||||
delete dialog;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,108 +0,0 @@
|
||||
#ifndef breezeexceptionlistwidget_h
|
||||
#define breezeexceptionlistwidget_h
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeexceptionlistwidget.h
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ui_breezeexceptionlistwidget.h"
|
||||
#include "breezeexceptionmodel.h"
|
||||
|
||||
//* QDialog used to commit selected files
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
class ExceptionListWidget: public QWidget
|
||||
{
|
||||
|
||||
//* Qt meta object
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit ExceptionListWidget( QWidget* = nullptr );
|
||||
|
||||
//* set exceptions
|
||||
void setExceptions( const InternalSettingsList& );
|
||||
|
||||
//* get exceptions
|
||||
InternalSettingsList exceptions();
|
||||
|
||||
//* true if changed
|
||||
virtual bool isChanged() const
|
||||
{ return m_changed; }
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
//* emitted when changed
|
||||
void changed( bool );
|
||||
|
||||
protected:
|
||||
|
||||
//* model
|
||||
const ExceptionModel& model() const
|
||||
{ return m_model; }
|
||||
|
||||
//* model
|
||||
ExceptionModel& model()
|
||||
{ return m_model; }
|
||||
|
||||
protected Q_SLOTS:
|
||||
|
||||
//* update button states
|
||||
virtual void updateButtons();
|
||||
|
||||
//* add
|
||||
virtual void add();
|
||||
|
||||
//* edit
|
||||
virtual void edit();
|
||||
|
||||
//* remove
|
||||
virtual void remove();
|
||||
|
||||
//* toggle
|
||||
virtual void toggle( const QModelIndex& );
|
||||
|
||||
//* move up
|
||||
virtual void up();
|
||||
|
||||
//* move down
|
||||
virtual void down();
|
||||
|
||||
protected:
|
||||
|
||||
//* resize columns
|
||||
void resizeColumns() const;
|
||||
|
||||
//* check exception
|
||||
bool checkException( InternalSettingsPtr );
|
||||
|
||||
//* set changed state
|
||||
virtual void setChanged( bool value )
|
||||
{
|
||||
m_changed = value;
|
||||
emit changed( value );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//* model
|
||||
ExceptionModel m_model;
|
||||
|
||||
//* ui
|
||||
Ui_BreezeExceptionListWidget m_ui;
|
||||
|
||||
//* changed state
|
||||
bool m_changed = false;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,91 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeexceptionmodel.cpp
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezeexceptionmodel.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//_______________________________________________
|
||||
const QString ExceptionModel::m_columnTitles[ ExceptionModel::nColumns ] =
|
||||
{
|
||||
QStringLiteral( "" ),
|
||||
i18n("Exception Type"),
|
||||
i18n("Regular Expression")
|
||||
};
|
||||
|
||||
//__________________________________________________________________
|
||||
QVariant ExceptionModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
|
||||
// check index, role and column
|
||||
if( !index.isValid() ) return QVariant();
|
||||
|
||||
// retrieve associated file info
|
||||
const InternalSettingsPtr& configuration( get(index) );
|
||||
|
||||
// return text associated to file and column
|
||||
if( role == Qt::DisplayRole )
|
||||
{
|
||||
|
||||
switch( index.column() )
|
||||
{
|
||||
case ColumnType:
|
||||
{
|
||||
switch( configuration->exceptionType() )
|
||||
{
|
||||
|
||||
case InternalSettings::ExceptionWindowTitle:
|
||||
return i18n( "Window Title" );
|
||||
|
||||
default:
|
||||
case InternalSettings::ExceptionWindowClassName:
|
||||
return i18n( "Window Class Name" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case ColumnRegExp: return configuration->exceptionPattern();
|
||||
default: return QVariant();
|
||||
break;
|
||||
}
|
||||
|
||||
} else if( role == Qt::CheckStateRole && index.column() == ColumnEnabled ) {
|
||||
|
||||
return configuration->enabled() ? Qt::Checked : Qt::Unchecked;
|
||||
|
||||
} else if( role == Qt::ToolTipRole && index.column() == ColumnEnabled ) {
|
||||
|
||||
return i18n("Enable/disable this exception");
|
||||
|
||||
}
|
||||
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
//__________________________________________________________________
|
||||
QVariant ExceptionModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
|
||||
if(
|
||||
orientation == Qt::Horizontal &&
|
||||
role == Qt::DisplayRole &&
|
||||
section >= 0 &&
|
||||
section < nColumns )
|
||||
{ return m_columnTitles[section]; }
|
||||
|
||||
// return empty
|
||||
return QVariant();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
#ifndef breezeexceptionmodel_h
|
||||
#define breezeexceptionmodel_h
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// breezeexceptionmodel.h
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezelistmodel.h"
|
||||
#include "breezesettings.h"
|
||||
#include "breeze.h"
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//* qlistview for object counters
|
||||
class ExceptionModel: public ListModel<InternalSettingsPtr>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//* number of columns
|
||||
enum { nColumns = 3 };
|
||||
|
||||
//* column type enumeration
|
||||
enum ColumnType {
|
||||
ColumnEnabled,
|
||||
ColumnType,
|
||||
ColumnRegExp
|
||||
};
|
||||
|
||||
|
||||
//*@name methods reimplemented from base class
|
||||
//@{
|
||||
|
||||
//* return data for a given index
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
//* header data
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
//* number of columns for a given index
|
||||
int columnCount(const QModelIndex& ) const override
|
||||
{ return nColumns; }
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
//* sort
|
||||
void privateSort( int, Qt::SortOrder ) override
|
||||
{}
|
||||
|
||||
private:
|
||||
|
||||
//* column titles
|
||||
static const QString m_columnTitles[ nColumns ];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@ -1,52 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// itemmodel.cpp
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009-2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezeitemmodel.h"
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//_______________________________________________________________
|
||||
ItemModel::ItemModel( QObject* parent ):
|
||||
QAbstractItemModel( parent )
|
||||
{}
|
||||
|
||||
//____________________________________________________________
|
||||
void ItemModel::sort( int column, Qt::SortOrder order )
|
||||
{
|
||||
|
||||
// store column and order
|
||||
m_sortColumn = column;
|
||||
m_sortOrder = order;
|
||||
|
||||
// emit signals and call private methods
|
||||
emit layoutAboutToBeChanged();
|
||||
privateSort( column, order );
|
||||
emit layoutChanged();
|
||||
|
||||
}
|
||||
|
||||
//____________________________________________________________
|
||||
QModelIndexList ItemModel::indexes( int column, const QModelIndex& parent ) const
|
||||
{
|
||||
QModelIndexList out;
|
||||
int rows( rowCount( parent ) );
|
||||
for( int row = 0; row < rows; row++ )
|
||||
{
|
||||
QModelIndex index( this->index( row, column, parent ) );
|
||||
if( !index.isValid() ) continue;
|
||||
out.append( index );
|
||||
out += indexes( column, index );
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
#ifndef ItemModel_h
|
||||
#define ItemModel_h
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// itemmodel.h
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009-2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
//* Job model. Stores job information for display in lists
|
||||
class ItemModel : public QAbstractItemModel
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit ItemModel(QObject *parent = nullptr);
|
||||
|
||||
//* destructor
|
||||
virtual ~ItemModel()
|
||||
{}
|
||||
|
||||
//* return all indexes in model starting from parent [recursive]
|
||||
QModelIndexList indexes( int column = 0, const QModelIndex& parent = QModelIndex() ) const;
|
||||
|
||||
//*@name sorting
|
||||
//@{
|
||||
|
||||
//* sort
|
||||
virtual void sort()
|
||||
{ sort( sortColumn(), sortOrder() ); }
|
||||
|
||||
//* sort
|
||||
void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) override;
|
||||
|
||||
//* current sorting column
|
||||
const int& sortColumn() const
|
||||
{ return m_sortColumn; }
|
||||
|
||||
//* current sort order
|
||||
const Qt::SortOrder& sortOrder() const
|
||||
{ return m_sortOrder; }
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
//* this sort columns without calling the layout changed callbacks
|
||||
void privateSort()
|
||||
{ privateSort( m_sortColumn, m_sortOrder ); }
|
||||
|
||||
//* private sort, with no signals emitted
|
||||
virtual void privateSort( int column, Qt::SortOrder order ) = 0;
|
||||
|
||||
//* used to sort items in list
|
||||
class SortFTor
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//* constructor
|
||||
explicit SortFTor( const int& type, Qt::SortOrder order = Qt::AscendingOrder ):
|
||||
_type( type ),
|
||||
_order( order )
|
||||
{}
|
||||
|
||||
protected:
|
||||
|
||||
//* column
|
||||
int _type;
|
||||
|
||||
//* order
|
||||
Qt::SortOrder _order;
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
//* sorting column
|
||||
int m_sortColumn = 0;
|
||||
|
||||
//* sorting order
|
||||
Qt::SortOrder m_sortOrder = Qt::AscendingOrder;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,349 +0,0 @@
|
||||
#ifndef ListModel_h
|
||||
#define ListModel_h
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// listmodel.h
|
||||
// -------------------
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "breezeitemmodel.h"
|
||||
|
||||
#include <QSet>
|
||||
#include <QList>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
//! Job model. Stores job information for display in lists
|
||||
template<class T> class ListModel : public ItemModel
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! value type
|
||||
typedef T ValueType;
|
||||
|
||||
//! reference
|
||||
typedef T& Reference;
|
||||
|
||||
//! pointer
|
||||
typedef T* Pointer;
|
||||
|
||||
//! value list and iterators
|
||||
typedef QList<ValueType> List;
|
||||
typedef QListIterator<ValueType> ListIterator;
|
||||
typedef QMutableListIterator<ValueType> MutableListIterator;
|
||||
|
||||
//! list of vector
|
||||
// typedef QSet<ValueType> Set;
|
||||
|
||||
//! constructor
|
||||
ListModel(QObject *parent = nullptr):
|
||||
ItemModel( parent )
|
||||
{}
|
||||
|
||||
//! destructor
|
||||
virtual ~ListModel()
|
||||
{}
|
||||
|
||||
//!@name methods reimplemented from base class
|
||||
//@{
|
||||
|
||||
//! flags
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override
|
||||
{
|
||||
if (!index.isValid()) return Qt::NoItemFlags;
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
//! unique index for given row, column and parent index
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
|
||||
// check if index is valid
|
||||
if( !hasIndex( row, column, parent ) ) return QModelIndex();
|
||||
|
||||
// return invalid index if parent is valid
|
||||
if( parent.isValid() ) return QModelIndex();
|
||||
|
||||
// check against _values
|
||||
return ( row < (int) _values.size() ) ? createIndex( row, column ):QModelIndex();
|
||||
|
||||
}
|
||||
|
||||
//! index of parent
|
||||
QModelIndex parent(const QModelIndex &) const override
|
||||
{ return QModelIndex(); }
|
||||
|
||||
//! number of rows below given index
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{ return parent.isValid() ? 0:_values.size(); }
|
||||
|
||||
//@}
|
||||
|
||||
//!@name selection
|
||||
//@{
|
||||
|
||||
//! clear internal list selected items
|
||||
virtual void clearSelectedIndexes()
|
||||
{ _selection.clear(); }
|
||||
|
||||
//! store index internal selection state
|
||||
virtual void setIndexSelected( const QModelIndex& index, bool value )
|
||||
{
|
||||
if( value ) _selection.push_back( get(index) );
|
||||
else _selection.erase( std::remove( _selection.begin(), _selection.end(), get(index) ), _selection.end() );
|
||||
}
|
||||
|
||||
//! get list of internal selected items
|
||||
virtual QModelIndexList selectedIndexes() const
|
||||
{
|
||||
|
||||
QModelIndexList out;
|
||||
for( typename List::const_iterator iter = _selection.begin(); iter != _selection.end(); iter++ )
|
||||
{
|
||||
QModelIndex index( ListModel::index( *iter ) );
|
||||
if( index.isValid() ) out.push_back( index );
|
||||
}
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//!@name interface
|
||||
//@{
|
||||
|
||||
//! add value
|
||||
virtual void add( const ValueType& value )
|
||||
{
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
_add( value );
|
||||
privateSort();
|
||||
emit layoutChanged();
|
||||
|
||||
}
|
||||
|
||||
//! add values
|
||||
virtual void add( const List& values )
|
||||
{
|
||||
|
||||
// check if not empty
|
||||
// this avoids sending useless signals
|
||||
if( values.empty() ) return;
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
|
||||
for( typename List::const_iterator iter = values.begin(); iter != values.end(); iter++ )
|
||||
{ _add( *iter ); }
|
||||
|
||||
privateSort();
|
||||
emit layoutChanged();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! insert values
|
||||
virtual void insert( const QModelIndex& index, const ValueType& value )
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
_insert( index, value );
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
//! insert values
|
||||
virtual void insert( const QModelIndex& index, const List& values )
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
|
||||
// need to loop in reverse order so that the "values" ordering is preserved
|
||||
ListIterator iter( values );
|
||||
iter.toBack();
|
||||
while( iter.hasPrevious() )
|
||||
{ _insert( index, iter.previous() ); }
|
||||
|
||||
emit layoutChanged();
|
||||
|
||||
}
|
||||
|
||||
//! insert values
|
||||
virtual void replace( const QModelIndex& index, const ValueType& value )
|
||||
{
|
||||
if( !index.isValid() ) add( value );
|
||||
else {
|
||||
emit layoutAboutToBeChanged();
|
||||
setIndexSelected( index, false );
|
||||
_values[index.row()] = value;
|
||||
setIndexSelected( index, true );
|
||||
emit layoutChanged();
|
||||
}
|
||||
}
|
||||
|
||||
//! remove
|
||||
virtual void remove( const ValueType& value )
|
||||
{
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
_remove( value );
|
||||
emit layoutChanged();
|
||||
|
||||
}
|
||||
|
||||
//! remove
|
||||
virtual void remove( const List& values )
|
||||
{
|
||||
|
||||
// check if not empty
|
||||
// this avoids sending useless signals
|
||||
if( values.empty() ) return;
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
for( typename List::const_iterator iter = values.begin(); iter != values.end(); iter++ )
|
||||
{ _remove( *iter ); }
|
||||
emit layoutChanged();
|
||||
|
||||
}
|
||||
|
||||
//! clear
|
||||
virtual void clear()
|
||||
{ set( List() ); }
|
||||
|
||||
//! update values from list
|
||||
/*!
|
||||
values that are not found in current are removed
|
||||
new values are set to the end.
|
||||
This is slower than the "set" method, but the selection is not cleared in the process
|
||||
*/
|
||||
virtual void update( List values )
|
||||
{
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
|
||||
// store values to be removed
|
||||
List removed_values;
|
||||
|
||||
// update values that are common to both lists
|
||||
for( typename List::iterator iter = _values.begin(); iter != _values.end(); iter++ )
|
||||
{
|
||||
|
||||
// see if iterator is in list
|
||||
typename List::iterator found_iter( std::find( values.begin(), values.end(), *iter ) );
|
||||
if( found_iter == values.end() ) removed_values.push_back( *iter );
|
||||
else {
|
||||
*iter = *found_iter;
|
||||
values.erase( found_iter );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// remove values that have not been found in new list
|
||||
for( typename List::const_iterator iter = removed_values.constBegin(); iter != removed_values.constEnd(); iter++ )
|
||||
{ _remove( *iter ); }
|
||||
|
||||
// add remaining values
|
||||
for( typename List::const_iterator iter = values.constBegin(); iter != values.constEnd(); iter++ )
|
||||
{ _add( *iter ); }
|
||||
|
||||
privateSort();
|
||||
emit layoutChanged();
|
||||
|
||||
}
|
||||
|
||||
//! set all values
|
||||
virtual void set( const List& values )
|
||||
{
|
||||
|
||||
emit layoutAboutToBeChanged();
|
||||
_values = values;
|
||||
_selection.clear();
|
||||
privateSort();
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
//! return all values
|
||||
const List& get( void ) const
|
||||
{ return _values; }
|
||||
|
||||
//! return value for given index
|
||||
virtual ValueType get( const QModelIndex& index ) const
|
||||
{ return (index.isValid() && index.row() < int(_values.size()) ) ? _values[index.row()]:ValueType(); }
|
||||
|
||||
//! return value for given index
|
||||
virtual ValueType& get( const QModelIndex& index )
|
||||
{
|
||||
Q_ASSERT( index.isValid() && index.row() < int( _values.size() ) );
|
||||
return _values[index.row()];
|
||||
}
|
||||
|
||||
//! return all values
|
||||
List get( const QModelIndexList& indexes ) const
|
||||
{
|
||||
List out;
|
||||
for( QModelIndexList::const_iterator iter = indexes.begin(); iter != indexes.end(); iter++ )
|
||||
{ if( iter->isValid() && iter->row() < int(_values.size()) ) out.push_back( get( *iter ) ); }
|
||||
return out;
|
||||
}
|
||||
|
||||
//! return index associated to a given value
|
||||
virtual QModelIndex index( const ValueType& value, int column = 0 ) const
|
||||
{
|
||||
for( int row = 0; row < _values.size(); ++row )
|
||||
{ if( value == _values[row] ) return index( row, column ); }
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//! return true if model contains given index
|
||||
virtual bool contains( const QModelIndex& index ) const
|
||||
{ return index.isValid() && index.row() < _values.size(); }
|
||||
|
||||
protected:
|
||||
|
||||
//! return all values
|
||||
List& _get( void )
|
||||
{ return _values; }
|
||||
|
||||
//! add, without update
|
||||
virtual void _add( const ValueType& value )
|
||||
{
|
||||
typename List::iterator iter = std::find( _values.begin(), _values.end(), value );
|
||||
if( iter == _values.end() ) _values.push_back( value );
|
||||
else *iter = value;
|
||||
}
|
||||
|
||||
//! add, without update
|
||||
virtual void _insert( const QModelIndex& index, const ValueType& value )
|
||||
{
|
||||
if( !index.isValid() ) add( value );
|
||||
int row = 0;
|
||||
typename List::iterator iter( _values.begin() );
|
||||
for( ;iter != _values.end() && row != index.row(); iter++, row++ )
|
||||
{}
|
||||
|
||||
_values.insert( iter, value );
|
||||
}
|
||||
|
||||
//! remove, without update
|
||||
virtual void _remove( const ValueType& value )
|
||||
{
|
||||
_values.erase( std::remove( _values.begin(), _values.end(), value ), _values.end() );
|
||||
_selection.erase( std::remove( _selection.begin(), _selection.end(), value ), _selection.end() );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//! values
|
||||
List _values;
|
||||
|
||||
//! selection
|
||||
List _selection;
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@ -1,341 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BreezeConfigurationUI</class>
|
||||
<widget class="QWidget" name="BreezeConfigurationUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>428</width>
|
||||
<height>418</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Tit&le alignment:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>titleAlignment</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>B&utton size:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>buttonSize</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="buttonSize">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Tiny</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">Small</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">Medium</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">Large</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">Very Large</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="titleAlignment">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Center</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Center (Full Width)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="3">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="drawSizeGrip">
|
||||
<property name="text">
|
||||
<string>Add handle to resize windows with no border</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="drawTitleBarSeparator">
|
||||
<property name="text">
|
||||
<string>Draw separator under active window's titlebar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="drawBorderOnMaximizedWindows">
|
||||
<property name="text">
|
||||
<string>Allow resizing maximized windows from window edges</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="outlineCloseButton">
|
||||
<property name="text">
|
||||
<string>Draw a circle around close button</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="drawBackgroundGradient">
|
||||
<property name="text">
|
||||
<string>Draw titlebar background gradient</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="title">
|
||||
<string>Shadows</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Si&ze:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>shadowSize</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="shadowSize">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">Small</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">Medium</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">Large</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Button size:">Very Large</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string comment="strength of the shadow (from transparent to opaque)">S&trength:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>shadowStrength</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="shadowStrength">
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Color:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="KColorButton" name="shadowColor"/>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Window-Specific Overrides</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="Breeze::ExceptionListWidget" name="exceptions" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>kcolorbutton.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Breeze::ExceptionListWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>config/breezeexceptionlistwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>titleAlignment</tabstop>
|
||||
<tabstop>buttonSize</tabstop>
|
||||
<tabstop>outlineCloseButton</tabstop>
|
||||
<tabstop>drawBorderOnMaximizedWindows</tabstop>
|
||||
<tabstop>drawBackgroundGradient</tabstop>
|
||||
<tabstop>drawSizeGrip</tabstop>
|
||||
<tabstop>drawTitleBarSeparator</tabstop>
|
||||
<tabstop>shadowSize</tabstop>
|
||||
<tabstop>shadowStrength</tabstop>
|
||||
<tabstop>shadowColor</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,146 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BreezeDetectWidget</class>
|
||||
<widget class="QDialog" name="BreezeDetectWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>239</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Information about Selected Window</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Class: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="windowClass">
|
||||
<property name="text">
|
||||
<string notr="true">TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Title: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="windowTitle">
|
||||
<property name="text">
|
||||
<string notr="true">TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Window Property Selection</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="windowClassCheckBox">
|
||||
<property name="text">
|
||||
<string>Use window class (whole application)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="windowTitleCheckBox">
|
||||
<property name="locale">
|
||||
<locale language="French" country="France"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use window title</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>BreezeDetectWidget</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BreezeDetectWidget</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@ -1,231 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BreezeExceptionDialog</class>
|
||||
<widget class="QDialog" name="BreezeExceptionDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>362</width>
|
||||
<height>321</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Window Identification</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>&Matching window property: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>exceptionType</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Regular expression &to match: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>exceptionEditor</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="detectDialogButton">
|
||||
<property name="text">
|
||||
<string>Detect Window Properties</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="exceptionEditor">
|
||||
<property name="showClearButton" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="exceptionType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Window Class Name</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Window Title</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Decoration Options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="borderSizeCheckBox">
|
||||
<property name="text">
|
||||
<string>Border size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="hideTitleBar">
|
||||
<property name="text">
|
||||
<string>Hide window title bar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="borderSizeComboBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">No Border</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">No Side Borders</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Tiny</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Normal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Large</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Very Large</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Huge</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Very Huge</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Oversized</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>BreezeExceptionDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>252</x>
|
||||
<y>342</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BreezeExceptionDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>320</x>
|
||||
<y>342</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>borderSizeCheckBox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>borderSizeComboBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>125</x>
|
||||
<y>162</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>316</x>
|
||||
<y>163</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@ -1,114 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BreezeExceptionListWidget</class>
|
||||
<widget class="QWidget" name="BreezeExceptionListWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>473</width>
|
||||
<height>182</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" rowspan="6">
|
||||
<widget class="QTreeView" name="exceptionListView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="moveUpButton">
|
||||
<property name="text">
|
||||
<string>Move Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="moveDownButton">
|
||||
<property name="text">
|
||||
<string>Move Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="addButton">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="removeButton">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="editButton">
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>exceptionListView</tabstop>
|
||||
<tabstop>moveUpButton</tabstop>
|
||||
<tabstop>moveDownButton</tabstop>
|
||||
<tabstop>addButton</tabstop>
|
||||
<tabstop>removeButton</tabstop>
|
||||
<tabstop>editButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -1,19 +0,0 @@
|
||||
################# dependencies #################
|
||||
### Qt/KDE
|
||||
find_package(Qt5 REQUIRED CONFIG COMPONENTS Widgets)
|
||||
|
||||
################# breezestyle target #################
|
||||
set(breezecommon_LIB_SRCS
|
||||
breezeboxshadowrenderer.cpp
|
||||
)
|
||||
|
||||
add_library(kali-breezecommon5 ${breezecommon_LIB_SRCS})
|
||||
|
||||
generate_export_header(kali-breezecommon5
|
||||
BASE_NAME breezecommon
|
||||
EXPORT_FILE_NAME breezecommon_export.h)
|
||||
|
||||
target_link_libraries(kali-breezecommon5
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Gui)
|
||||
@ -1,350 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
*
|
||||
* The box blur implementation is based on AlphaBoxBlur from Firefox.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// own
|
||||
#include "breezeboxshadowrenderer.h"
|
||||
|
||||
// Qt
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
static inline int calculateBlurRadius(qreal stdDev)
|
||||
{
|
||||
// See https://www.w3.org/TR/SVG11/filters.html#feGaussianBlurElement
|
||||
const qreal gaussianScaleFactor = (3.0 * qSqrt(2.0 * M_PI) / 4.0) * 1.5;
|
||||
return qMax(2, qFloor(stdDev * gaussianScaleFactor + 0.5));
|
||||
}
|
||||
|
||||
static inline qreal calculateBlurStdDev(int radius)
|
||||
{
|
||||
// See https://www.w3.org/TR/css-backgrounds-3/#shadow-blur
|
||||
return radius * 0.5;
|
||||
}
|
||||
|
||||
static inline QSize calculateBlurExtent(int radius)
|
||||
{
|
||||
const int blurRadius = calculateBlurRadius(calculateBlurStdDev(radius));
|
||||
return QSize(blurRadius, blurRadius);
|
||||
}
|
||||
|
||||
struct BoxLobes
|
||||
{
|
||||
int left; ///< how many pixels sample to the left
|
||||
int right; ///< how many pixels sample to the right
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute box filter parameters.
|
||||
*
|
||||
* @param radius The blur radius.
|
||||
* @returns Parameters for three box filters.
|
||||
**/
|
||||
static QVector<BoxLobes> computeLobes(int radius)
|
||||
{
|
||||
const int blurRadius = calculateBlurRadius(calculateBlurStdDev(radius));
|
||||
const int z = blurRadius / 3;
|
||||
|
||||
int major;
|
||||
int minor;
|
||||
int final;
|
||||
|
||||
switch (blurRadius % 3) {
|
||||
case 0:
|
||||
major = z;
|
||||
minor = z;
|
||||
final = z;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
major = z + 1;
|
||||
minor = z;
|
||||
final = z;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
major = z + 1;
|
||||
minor = z;
|
||||
final = z + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
Q_ASSERT(major + minor + final == blurRadius);
|
||||
|
||||
return {
|
||||
{major, minor},
|
||||
{minor, major},
|
||||
{final, final}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a row with a box filter.
|
||||
*
|
||||
* @param src The start of the row.
|
||||
* @param dst The destination.
|
||||
* @param width The width of the row, in pixels.
|
||||
* @param horizontalStride The number of bytes from one alpha value to the
|
||||
* next alpha value.
|
||||
* @param verticalStride The number of bytes from one row to the next row.
|
||||
* @param lobes Params of the box filter.
|
||||
* @param transposeInput Whether the input is transposed.
|
||||
* @param transposeOutput Whether the output should be transposed.
|
||||
**/
|
||||
static inline void boxBlurRowAlpha(const uint8_t *src, uint8_t *dst, int width, int horizontalStride,
|
||||
int verticalStride, const BoxLobes &lobes, bool transposeInput,
|
||||
bool transposeOutput)
|
||||
{
|
||||
const int inputStep = transposeInput ? verticalStride : horizontalStride;
|
||||
const int outputStep = transposeOutput ? verticalStride : horizontalStride;
|
||||
|
||||
const int boxSize = lobes.left + 1 + lobes.right;
|
||||
const int reciprocal = (1 << 24) / boxSize;
|
||||
|
||||
uint32_t alphaSum = (boxSize + 1) / 2;
|
||||
|
||||
const uint8_t *left = src;
|
||||
const uint8_t *right = src;
|
||||
uint8_t *out = dst;
|
||||
|
||||
const uint8_t firstValue = src[0];
|
||||
const uint8_t lastValue = src[(width - 1) * inputStep];
|
||||
|
||||
alphaSum += firstValue * lobes.left;
|
||||
|
||||
const uint8_t *initEnd = src + (boxSize - lobes.left) * inputStep;
|
||||
while (right < initEnd) {
|
||||
alphaSum += *right;
|
||||
right += inputStep;
|
||||
}
|
||||
|
||||
const uint8_t *leftEnd = src + boxSize * inputStep;
|
||||
while (right < leftEnd) {
|
||||
*out = (alphaSum * reciprocal) >> 24;
|
||||
alphaSum += *right - firstValue;
|
||||
right += inputStep;
|
||||
out += outputStep;
|
||||
}
|
||||
|
||||
const uint8_t *centerEnd = src + width * inputStep;
|
||||
while (right < centerEnd) {
|
||||
*out = (alphaSum * reciprocal) >> 24;
|
||||
alphaSum += *right - *left;
|
||||
left += inputStep;
|
||||
right += inputStep;
|
||||
out += outputStep;
|
||||
}
|
||||
|
||||
const uint8_t *rightEnd = dst + width * outputStep;
|
||||
while (out < rightEnd) {
|
||||
*out = (alphaSum * reciprocal) >> 24;
|
||||
alphaSum += lastValue - *left;
|
||||
left += inputStep;
|
||||
out += outputStep;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Blur the alpha channel of a given image.
|
||||
*
|
||||
* @param image The input image.
|
||||
* @param radius The blur radius.
|
||||
* @param rect Specifies what part of the image to blur. If nothing is provided, then
|
||||
* the whole alpha channel of the input image will be blurred.
|
||||
**/
|
||||
static inline void boxBlurAlpha(QImage &image, int radius, const QRect &rect = {})
|
||||
{
|
||||
if (radius < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QVector<BoxLobes> lobes = computeLobes(radius);
|
||||
|
||||
const QRect blurRect = rect.isNull() ? image.rect() : rect;
|
||||
|
||||
const int alphaOffset = QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3;
|
||||
const int width = blurRect.width();
|
||||
const int height = blurRect.height();
|
||||
const int rowStride = image.bytesPerLine();
|
||||
const int pixelStride = image.depth() >> 3;
|
||||
|
||||
const int bufferStride = qMax(width, height) * pixelStride;
|
||||
QScopedPointer<uint8_t, QScopedPointerArrayDeleter<uint8_t> > buf(new uint8_t[2 * bufferStride]);
|
||||
uint8_t *buf1 = buf.data();
|
||||
uint8_t *buf2 = buf1 + bufferStride;
|
||||
|
||||
// Blur the image in horizontal direction.
|
||||
for (int i = 0; i < height; ++i) {
|
||||
uint8_t *row = image.scanLine(blurRect.y() + i) + blurRect.x() * pixelStride + alphaOffset;
|
||||
boxBlurRowAlpha(row, buf1, width, pixelStride, rowStride, lobes[0], false, false);
|
||||
boxBlurRowAlpha(buf1, buf2, width, pixelStride, rowStride, lobes[1], false, false);
|
||||
boxBlurRowAlpha(buf2, row, width, pixelStride, rowStride, lobes[2], false, false);
|
||||
}
|
||||
|
||||
// Blur the image in vertical direction.
|
||||
for (int i = 0; i < width; ++i) {
|
||||
uint8_t *column = image.scanLine(blurRect.y()) + (blurRect.x() + i) * pixelStride + alphaOffset;
|
||||
boxBlurRowAlpha(column, buf1, height, pixelStride, rowStride, lobes[0], true, false);
|
||||
boxBlurRowAlpha(buf1, buf2, height, pixelStride, rowStride, lobes[1], false, false);
|
||||
boxBlurRowAlpha(buf2, column, height, pixelStride, rowStride, lobes[2], false, true);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mirrorTopLeftQuadrant(QImage &image)
|
||||
{
|
||||
const int width = image.width();
|
||||
const int height = image.height();
|
||||
|
||||
const int centerX = qCeil(width * 0.5);
|
||||
const int centerY = qCeil(height * 0.5);
|
||||
|
||||
const int alphaOffset = QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3;
|
||||
const int stride = image.depth() >> 3;
|
||||
|
||||
for (int y = 0; y < centerY; ++y) {
|
||||
uint8_t *in = image.scanLine(y) + alphaOffset;
|
||||
uint8_t *out = in + (width - 1) * stride;
|
||||
|
||||
for (int x = 0; x < centerX; ++x, in += stride, out -= stride) {
|
||||
*out = *in;
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = 0; y < centerY; ++y) {
|
||||
const uint8_t *in = image.scanLine(y) + alphaOffset;
|
||||
uint8_t *out = image.scanLine(width - y - 1) + alphaOffset;
|
||||
|
||||
for (int x = 0; x < width; ++x, in += stride, out += stride) {
|
||||
*out = *in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void renderShadow(QPainter *painter, const QRect &rect, qreal borderRadius, const QPoint &offset, int radius, const QColor &color)
|
||||
{
|
||||
const QSize inflation = calculateBlurExtent(radius);
|
||||
const QSize size = rect.size() + 2 * inflation;
|
||||
|
||||
const qreal dpr = painter->device()->devicePixelRatioF();
|
||||
|
||||
QImage shadow(size * dpr, QImage::Format_ARGB32_Premultiplied);
|
||||
shadow.setDevicePixelRatio(dpr);
|
||||
shadow.fill(Qt::transparent);
|
||||
|
||||
QRect boxRect(QPoint(0, 0), rect.size());
|
||||
boxRect.moveCenter(QRect(QPoint(0, 0), size).center());
|
||||
|
||||
const qreal xRadius = 2.0 * borderRadius / boxRect.width();
|
||||
const qreal yRadius = 2.0 * borderRadius / boxRect.height();
|
||||
|
||||
QPainter shadowPainter;
|
||||
shadowPainter.begin(&shadow);
|
||||
shadowPainter.setRenderHint(QPainter::Antialiasing);
|
||||
shadowPainter.setPen(Qt::NoPen);
|
||||
shadowPainter.setBrush(Qt::black);
|
||||
shadowPainter.drawRoundedRect(boxRect, xRadius, yRadius);
|
||||
shadowPainter.end();
|
||||
|
||||
// Because the shadow texture is symmetrical, that's enough to blur
|
||||
// only the top-left quadrant and then mirror it.
|
||||
const QRect blurRect(0, 0, qCeil(shadow.width() * 0.5), qCeil(shadow.height() * 0.5));
|
||||
const int scaledRadius = qRound(radius * dpr);
|
||||
boxBlurAlpha(shadow, scaledRadius, blurRect);
|
||||
mirrorTopLeftQuadrant(shadow);
|
||||
|
||||
// Give the shadow a tint of the desired color.
|
||||
shadowPainter.begin(&shadow);
|
||||
shadowPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
shadowPainter.fillRect(shadow.rect(), color);
|
||||
shadowPainter.end();
|
||||
|
||||
// Actually, present the shadow.
|
||||
QRect shadowRect = shadow.rect();
|
||||
shadowRect.setSize(shadowRect.size() / dpr);
|
||||
shadowRect.moveCenter(rect.center() + offset);
|
||||
painter->drawImage(shadowRect, shadow);
|
||||
}
|
||||
|
||||
void BoxShadowRenderer::setBoxSize(const QSize &size)
|
||||
{
|
||||
m_boxSize = size;
|
||||
}
|
||||
|
||||
void BoxShadowRenderer::setBorderRadius(qreal radius)
|
||||
{
|
||||
m_borderRadius = radius;
|
||||
}
|
||||
|
||||
void BoxShadowRenderer::setDevicePixelRatio(qreal dpr)
|
||||
{
|
||||
m_dpr = dpr;
|
||||
}
|
||||
|
||||
void BoxShadowRenderer::addShadow(const QPoint &offset, int radius, const QColor &color)
|
||||
{
|
||||
Shadow shadow = {};
|
||||
shadow.offset = offset;
|
||||
shadow.radius = radius;
|
||||
shadow.color = color;
|
||||
m_shadows.append(shadow);
|
||||
}
|
||||
|
||||
QImage BoxShadowRenderer::render() const
|
||||
{
|
||||
if (m_shadows.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
QSize canvasSize;
|
||||
for (const Shadow &shadow : qAsConst(m_shadows)) {
|
||||
canvasSize = canvasSize.expandedTo(
|
||||
calculateMinimumShadowTextureSize(m_boxSize, shadow.radius, shadow.offset));
|
||||
}
|
||||
|
||||
QImage canvas(canvasSize * m_dpr, QImage::Format_ARGB32_Premultiplied);
|
||||
canvas.setDevicePixelRatio(m_dpr);
|
||||
canvas.fill(Qt::transparent);
|
||||
|
||||
QRect boxRect(QPoint(0, 0), m_boxSize);
|
||||
boxRect.moveCenter(QRect(QPoint(0, 0), canvasSize).center());
|
||||
|
||||
QPainter painter(&canvas);
|
||||
for (const Shadow &shadow : qAsConst(m_shadows)) {
|
||||
renderShadow(&painter, boxRect, m_borderRadius, shadow.offset, shadow.radius, shadow.color);
|
||||
}
|
||||
painter.end();
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
QSize BoxShadowRenderer::calculateMinimumBoxSize(int radius)
|
||||
{
|
||||
const QSize blurExtent = calculateBlurExtent(radius);
|
||||
return 2 * blurExtent + QSize(1, 1);
|
||||
}
|
||||
|
||||
QSize BoxShadowRenderer::calculateMinimumShadowTextureSize(const QSize &boxSize, int radius, const QPoint &offset)
|
||||
{
|
||||
return boxSize + 2 * calculateBlurExtent(radius) + QSize(qAbs(offset.x()), qAbs(offset.y()));
|
||||
}
|
||||
|
||||
} // namespace Breeze
|
||||
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// own
|
||||
#include "breezecommon_export.h"
|
||||
|
||||
// Qt
|
||||
#include <QColor>
|
||||
#include <QImage>
|
||||
#include <QPoint>
|
||||
#include <QSize>
|
||||
|
||||
namespace Breeze
|
||||
{
|
||||
|
||||
class BREEZECOMMON_EXPORT BoxShadowRenderer
|
||||
{
|
||||
public:
|
||||
// Compiler generated constructors & destructor are fine.
|
||||
|
||||
/**
|
||||
* Set the size of the box.
|
||||
* @param size The size of the box.
|
||||
**/
|
||||
void setBoxSize(const QSize &size);
|
||||
|
||||
/**
|
||||
* Set the radius of box' corners.
|
||||
* @param radius The border radius, in pixels.
|
||||
**/
|
||||
void setBorderRadius(qreal radius);
|
||||
|
||||
/**
|
||||
* Set the device pixel ratio of the resulting shadow texture.
|
||||
* @param dpr The device pixel ratio.
|
||||
**/
|
||||
void setDevicePixelRatio(qreal dpr);
|
||||
|
||||
/**
|
||||
* Add a shadow.
|
||||
* @param offset The offset of the shadow.
|
||||
* @param radius The blur radius.
|
||||
* @param color The color of the shadow.
|
||||
**/
|
||||
void addShadow(const QPoint &offset, int radius, const QColor &color);
|
||||
|
||||
/**
|
||||
* Render the shadow.
|
||||
**/
|
||||
QImage render() const;
|
||||
|
||||
/**
|
||||
* Calculate the minimum size of the box.
|
||||
*
|
||||
* This helper computes the minimum size of the box so the shadow behind it has
|
||||
* full its strength.
|
||||
*
|
||||
* @param radius The blur radius of the shadow.
|
||||
**/
|
||||
static QSize calculateMinimumBoxSize(int radius);
|
||||
|
||||
/**
|
||||
* Calculate the minimum size of the shadow texture.
|
||||
*
|
||||
* This helper computes the minimum size of the resulting texture so the shadow
|
||||
* is not clipped.
|
||||
*
|
||||
* @param boxSize The size of the box.
|
||||
* @param radius The blur radius.
|
||||
* @param offset The offset of the shadow.
|
||||
**/
|
||||
static QSize calculateMinimumShadowTextureSize(const QSize &boxSize, int radius, const QPoint &offset);
|
||||
|
||||
private:
|
||||
QSize m_boxSize;
|
||||
qreal m_borderRadius = 0.0;
|
||||
qreal m_dpr = 1.0;
|
||||
|
||||
struct Shadow {
|
||||
QPoint offset;
|
||||
int radius;
|
||||
QColor color;
|
||||
};
|
||||
|
||||
QVector<Shadow> m_shadows;
|
||||
};
|
||||
|
||||
} // namespace Breeze
|
||||
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
||||
SUBDIRS=emblems kali-logos KDE-themes
|
||||
SUBDIRS=emblems kali-logos
|
||||
DESKTOP_BACKGROUND=kali-nova
|
||||
LOGIN_BACKGROUND=kali-contours
|
||||
|
||||
|
||||
19
debian/control
vendored
19
debian/control
vendored
@ -3,17 +3,8 @@ Section: misc
|
||||
Priority: optional
|
||||
Maintainer: Kali Developers <devel@kali.org>
|
||||
Uploaders: Daniel Ruiz de Alegría <daniel@drasite.com>, Raphaël Hertzog <raphael@offensive-security.com>
|
||||
Build-Depends: cmake,
|
||||
Build-Depends:
|
||||
debhelper-compat (= 12),
|
||||
extra-cmake-modules,
|
||||
libkdecorations2-dev,
|
||||
libkf5configwidgets-dev,
|
||||
libkf5coreaddons-dev,
|
||||
libkf5guiaddons-dev,
|
||||
libkf5i18n-dev,
|
||||
libkf5iconthemes-dev,
|
||||
libkf5windowsystem-dev,
|
||||
libqt5x11extras5-dev,
|
||||
librsvg2-bin,
|
||||
optipng,
|
||||
Standards-Version: 4.5.1
|
||||
@ -87,14 +78,6 @@ Description: Configure all desktops to use the Kali theme
|
||||
provides configuration files and other settings for each desktop so that
|
||||
they use the Kali theme by default.
|
||||
|
||||
Package: kwin-style-kali
|
||||
Architecture: any
|
||||
Depends:
|
||||
${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Description: Kali theme for KWin
|
||||
Kali's window manager theme for KDE Plasma 5 desktop
|
||||
|
||||
Package: gnome-theme-kali
|
||||
Architecture: all
|
||||
Depends: kali-themes,
|
||||
|
||||
2
debian/kwin-style-kali.install
vendored
2
debian/kwin-style-kali.install
vendored
@ -1,2 +0,0 @@
|
||||
# Created by "make install"
|
||||
usr/lib/*/qt5/
|
||||
Loading…
x
Reference in New Issue
Block a user