• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KStyles

helper.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2008 Long Huynh Huu <long.upcase@googlemail.com>
00003  * Copyright 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
00004  * Copyright 2007 Casper Boemann <cbr@boemann.dk>
00005  * Copyright 2007 Fredrik Höglund <fredrik@kde.org>
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Library General Public
00009  * License version 2 as published by the Free Software Foundation.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public License
00017  * along with this library; see the file COPYING.LIB.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  */
00021 
00022 #include "helper.h"
00023 
00024 #include <KGlobalSettings>
00025 #include <KColorUtils>
00026 #include <KColorScheme>
00027 
00028 #include <QtGui/QWidget>
00029 #include <QtGui/QPainter>
00030 
00031 #include <math.h>
00032 
00033 const double OxygenHelper::_shadowGain = 1.5;
00034 
00035 // NOTE: OxygenStyleHelper needs to use a KConfig from its own KComponentData
00036 // Since the ctor order causes a SEGV if we try to pass in a KConfig here from
00037 // a KComponentData constructed in the OxygenStyleHelper ctor, we'll just keep
00038 // one here, even though the window decoration doesn't really need it.
00039 OxygenHelper::OxygenHelper(const QByteArray &componentName)
00040     : _componentData(componentName, 0, KComponentData::SkipMainComponentRegistration)
00041 {
00042     _config = _componentData.config();
00043     _contrast = KGlobalSettings::contrastF(_config);
00044     _bgcontrast = 0.3;// // shouldn't use contrast for this _contrast; // TODO get style setting
00045 
00046     m_backgroundCache.setMaxCost(64);
00047     m_windecoButtonCache.setMaxCost(64);
00048     m_windecoButtonGlowCache.setMaxCost(64);
00049 }
00050 
00051 KSharedConfigPtr OxygenHelper::config() const
00052 {
00053     return _config;
00054 }
00055 
00056 void OxygenHelper::reloadConfig()
00057 {
00058     double old_contrast = _contrast;
00059 
00060     _config->reparseConfiguration();
00061     _contrast = KGlobalSettings::contrastF(_config);
00062 
00063     if (_contrast != old_contrast)
00064         invalidateCaches(); // contrast changed, invalidate our caches
00065 }
00066 
00067 void OxygenHelper::renderWindowBackground(QPainter *p, const QRect &clipRect, const QWidget *widget, const QPalette & pal, int y_shift)
00068 {
00069     const QWidget* window = widget->window();
00070     // get coordinates relative to the client area
00071     const QWidget* w = widget;
00072     int x = 0, y = -y_shift;
00073     while (!w->isWindow()) {
00074         x += w->geometry().x();
00075         y += w->geometry().y();
00076         w = w->parentWidget();
00077     } 
00078     
00079     if (clipRect.isValid()) {
00080         p->save();
00081         p->setClipRegion(clipRect,Qt::IntersectClip);
00082     }
00083     QRect r = window->rect();
00084     QColor color = pal.color(window->backgroundRole());
00085     int splitY = qMin(300, 3*r.height()/4);
00086 
00087     QRect upperRect = QRect(-x, -y, r.width(), splitY);
00088     QPixmap tile = verticalGradient(color, splitY);
00089     p->drawTiledPixmap(upperRect, tile);
00090 
00091     QRect lowerRect = QRect(-x, splitY-y, r.width(), r.height() - splitY-y_shift);
00092     p->fillRect(lowerRect, backgroundBottomColor(color));
00093 
00094     int radialW = qMin(600, r.width());
00095     int frameH = 10; // on first paint the frame may not have been done yet, so just fixate it
00096     QRect radialRect = QRect((r.width() - radialW) / 2-x, -y, radialW, 64-frameH);
00097     if (clipRect.intersects(radialRect))
00098     {
00099         tile = radialGradient(color, radialW);
00100         p->drawPixmap(radialRect, tile);
00101      }
00102 
00103     if (clipRect.isValid())
00104         p->restore();
00105 }
00106 
00107 void OxygenHelper::invalidateCaches()
00108 {
00109     m_backgroundCache.clear();
00110     m_windecoButtonCache.clear();
00111     m_windecoButtonGlowCache.clear();
00112 }
00113 
00114 bool OxygenHelper::lowThreshold(const QColor &color)
00115 {
00116     QColor darker = KColorScheme::shade(color, KColorScheme::MidShade, 0.5);
00117     return KColorUtils::luma(darker) > KColorUtils::luma(color);
00118 }
00119 
00120 QColor OxygenHelper::alphaColor(QColor color, double alpha)
00121 {
00122     if (alpha >= 1.0)
00123         return color;
00124     color.setAlphaF(qMax(0.0, alpha) * color.alphaF());
00125     return color;
00126 }
00127 
00128 QColor OxygenHelper::backgroundRadialColor(const QColor &color) const
00129 {
00130     if (lowThreshold(color))
00131         return KColorScheme::shade(color, KColorScheme::LightShade, 0.0);
00132     else
00133         return KColorScheme::shade(color, KColorScheme::LightShade, _bgcontrast);
00134 }
00135 
00136 QColor OxygenHelper::backgroundTopColor(const QColor &color) const
00137 {
00138     if (lowThreshold(color))
00139         return KColorScheme::shade(color, KColorScheme::MidlightShade, 0.0);
00140     else
00141         return KColorScheme::shade(color, KColorScheme::MidlightShade, _bgcontrast);
00142 }
00143 
00144 QColor OxygenHelper::backgroundBottomColor(const QColor &color) const
00145 {
00146     QColor midColor = KColorScheme::shade(color, KColorScheme::MidShade, 0.0);
00147     if (lowThreshold(color))
00148         return midColor;
00149 
00150     double by = KColorUtils::luma(color), my = KColorUtils::luma(midColor);
00151     return KColorUtils::shade(color, (my - by) * _bgcontrast);
00152 }
00153 
00154 QColor OxygenHelper::calcLightColor(const QColor &color) const
00155 {
00156     return KColorScheme::shade(color, KColorScheme::LightShade, _contrast);
00157 }
00158 
00159 QColor OxygenHelper::calcDarkColor(const QColor &color) const
00160 {
00161     if (lowThreshold(color))
00162         return KColorUtils::mix(calcLightColor(color), color, 0.2 + 0.8 * _contrast);
00163     else
00164         return KColorScheme::shade(color, KColorScheme::MidShade, _contrast);
00165 }
00166 
00167 QColor OxygenHelper::calcShadowColor(const QColor &color) const
00168 {
00169     return KColorScheme::shade(KColorUtils::mix(QColor(255,255,255),color, color.alpha()*(1/255.0)),
00170                     KColorScheme::ShadowShade, _contrast);
00171 
00172 }
00173 
00174 QColor OxygenHelper::backgroundColor(const QColor &color, int height, int y)
00175 {
00176     double h = height * 0.5;
00177     if (y > height>>1) {
00178         double a = double(y) / h;
00179         return KColorUtils::mix(backgroundTopColor(color), color, a);
00180     }
00181     else {
00182         double a = (double(y) - h) / h;
00183         return KColorUtils::mix(color, backgroundBottomColor(color), a);
00184     }
00185 }
00186 
00187 QPixmap OxygenHelper::verticalGradient(const QColor &color, int height)
00188 {
00189     quint64 key = (quint64(color.rgba()) << 32) | height | 0x8000;
00190     QPixmap *pixmap = m_backgroundCache.object(key);
00191 
00192     if (!pixmap)
00193     {
00194         pixmap = new QPixmap(32, height);
00195 
00196         QLinearGradient gradient(0, 0, 0, height);
00197         gradient.setColorAt(0.0, backgroundTopColor(color));
00198         gradient.setColorAt(0.5, color);
00199         gradient.setColorAt(1.0, backgroundBottomColor(color));
00200 
00201         QPainter p(pixmap);
00202         p.setCompositionMode(QPainter::CompositionMode_Source);
00203         p.fillRect(pixmap->rect(), gradient);
00204 
00205         m_backgroundCache.insert(key, pixmap);
00206     }
00207 
00208     return *pixmap;
00209 }
00210 
00211 QPixmap OxygenHelper::radialGradient(const QColor &color, int width)
00212 {
00213     quint64 key = (quint64(color.rgba()) << 32) | width | 0xb000;
00214     QPixmap *pixmap = m_backgroundCache.object(key);
00215 
00216     if (!pixmap)
00217     {
00218 //        width /= 2;
00219         pixmap = new QPixmap(width, 64);
00220         pixmap->fill(QColor(0,0,0,0));
00221         QColor radialColor = backgroundRadialColor(color);
00222         radialColor.setAlpha(255);
00223         QRadialGradient gradient(64, 0, 64);
00224         gradient.setColorAt(0, radialColor);
00225         radialColor.setAlpha(101);
00226         gradient.setColorAt(0.5, radialColor);
00227         radialColor.setAlpha(37);
00228         gradient.setColorAt(0.75, radialColor);
00229         radialColor.setAlpha(0);
00230         gradient.setColorAt(1, radialColor);
00231 
00232         QPainter p(pixmap);
00233         p.scale(width/128.0,1);
00234         p.fillRect(QRect(0,0,128,64), gradient);
00235 
00236         m_backgroundCache.insert(key, pixmap);
00237     }
00238 
00239     return *pixmap;
00240 }
00241 
00242 void OxygenHelper::drawShadow(QPainter &p, const QColor &color, int size) const
00243 {
00244     double m = double(size-2)*0.5;
00245 
00246     const double offset = 0.8;
00247     double k0 = (m-4.0) / m;
00248     QRadialGradient shadowGradient(m+1.0, m+offset+1.0, m);
00249     for (int i = 0; i < 8; i++) { // sinusoidal gradient
00250         double k1 = (k0 * double(8 - i) + double(i)) * 0.125;
00251         double a = (cos(3.14159 * i * 0.125) + 1.0) * 0.25;
00252         shadowGradient.setColorAt(k1, alphaColor(color, a * _shadowGain));
00253     }
00254     shadowGradient.setColorAt(1.0, alphaColor(color, 0.0));
00255     p.setBrush(shadowGradient);
00256     p.drawEllipse(QRectF(0, 0, size, size));
00257 }
00258 
00259 QLinearGradient OxygenHelper::decoGradient(const QRect &r, const QColor &color)
00260 {
00261     QColor light = KColorScheme::shade(color, KColorScheme::LightShade, _contrast * 0.7);
00262     QColor dark = KColorScheme::shade(color, KColorScheme::DarkShade, _contrast * 0.7);
00263     double y = KColorUtils::luma(color);
00264     double yd = KColorUtils::luma(dark);
00265     double yl = KColorUtils::luma(light);
00266 
00267     QLinearGradient gradient(r.topLeft(), r.bottomLeft());
00268     if (yd > y)
00269     {
00270         gradient.setColorAt(0.2, color);
00271         gradient.setColorAt(0.8, dark);
00272     }
00273     else if (yl < y)
00274     {
00275         gradient.setColorAt(0.2, light);
00276         gradient.setColorAt(0.8, color);
00277     }
00278     else
00279     {
00280         gradient.setColorAt(0.2, dark);
00281         gradient.setColorAt(0.5, color);
00282         gradient.setColorAt(0.8, light);
00283     }
00284 
00285     return gradient;
00286 }
00287 
00288 QPixmap OxygenHelper::windecoButton(const QColor &color, bool pressed, int size)
00289 {
00290     quint64 key = (quint64(color.rgba()) << 32) | (size << 1) | pressed;
00291     QPixmap *pixmap = m_windecoButtonCache.object(key);
00292 
00293     if (!pixmap)
00294     {
00295         pixmap = new QPixmap(size, size);
00296         pixmap->fill(Qt::transparent);
00297 
00298         QPainter p(pixmap);
00299         p.setRenderHints(QPainter::Antialiasing);
00300         p.setPen(Qt::NoPen);
00301 
00302         double u = size/21.0;
00303 
00304         QColor light  = calcLightColor(color);
00305         QColor dark   = calcDarkColor(color);
00306         QColor shadow = calcShadowColor(color);
00307 
00308         QRectF rect(0.0, 0.0, size, size);
00309         QRectF buttonRect = rect.adjusted(2*u,2*u,-2*u,-2*u);
00310 
00311         QLinearGradient fill(QPointF(0.0, 0.0*u),
00312                 QPointF(0.0, 21.0*u));
00313         fill.setColorAt(0.0, alphaColor(light, 0.7));
00314         fill.setColorAt(1.0, alphaColor(dark, 0.7));
00315 
00316         p.setBrush(fill);
00317         p.drawEllipse(buttonRect);
00318         p.setBrush(Qt::NoBrush);
00319 
00320         // shadow
00321         if (pressed)
00322         {
00323             p.setPen(alphaColor(dark, 0.4));
00324             p.drawEllipse(buttonRect.adjusted(0.9, 0.6, -0.7, -0.7).adjusted(1.7,1.7,-1.7,-1.7));
00325             p.setPen(alphaColor(dark, 0.8));
00326             p.drawEllipse(buttonRect.adjusted(0.9, 0.6, -0.7, -0.7).adjusted(1.2,1.2,-1.2,-1.2));
00327         }
00328         p.setPen(QPen(KColorUtils::mix(dark, shadow, 0.12), 2.0));
00329         p.drawEllipse(buttonRect.adjusted(0.9, 0.6, -0.7, -0.7).adjusted(0,0.1,0,-0.1));
00330         p.setPen(QPen(KColorUtils::mix(dark, shadow, 0.6), 1.2));
00331         p.drawEllipse(buttonRect.adjusted(1.0, 1.4, -0.8, -0.8));
00332 
00333         // reflection
00334         QLinearGradient lightgr(QPointF(0.0, 0.0*u),
00335                 QPointF(0.0, 21.0*u));
00336         lightgr.setColorAt(0.0, Qt::transparent);
00337         lightgr.setColorAt(1.0, light);
00338         p.setPen(QPen(lightgr, 1.7));
00339         p.drawEllipse(buttonRect.adjusted(0.0, -0.5, -0.1, 0.0));
00340 
00341         m_windecoButtonCache.insert(key, pixmap);
00342     }
00343 
00344     return *pixmap;
00345 }
00346 
00347 QPixmap OxygenHelper::windecoButtonGlow(const QColor &color, int size)
00348 {
00349     quint64 key = (quint64(color.rgba()) << 32) | size;
00350     QPixmap *pixmap = m_windecoButtonGlowCache.object(key);
00351 
00352     if (!pixmap)
00353     {
00354         pixmap = new QPixmap(size, size);
00355         pixmap->fill(Qt::transparent);
00356 
00357         QPainter p(pixmap);
00358         p.setRenderHints(QPainter::Antialiasing);
00359         p.setPen(Qt::NoPen);
00360 
00361         double u = size/21.0;
00362         QRectF rect(0.0, 0.0, size, size);
00363         QRectF buttonRect = rect.adjusted(2*u,2*u,-2*u,-2*u);
00364 
00365         //mask
00366         p.setBrush(QColor(0,0,0,125));
00367         p.drawEllipse(rect.adjusted(u, 0, -u, -2*u));
00368 
00369         //glow
00370         QColor dark  = calcDarkColor(color);
00371         QColor light = calcLightColor(color);
00372 
00373         QRadialGradient glow(QPointF(size/2.0, size/2.0 + 0.25), size/2.0);
00374         glow.setColorAt(12.0 / 21.0, Qt::transparent);
00375         glow.setColorAt(16.0 / 21.0, dark);
00376         glow.setColorAt(18.0 / 21.0, alphaColor(light, 0.25));
00377         glow.setColorAt(20.0 / 21.0, Qt::transparent);
00378 
00379         p.setCompositionMode(QPainter::CompositionMode_SourceIn);
00380         p.setBrush(glow);
00381         p.drawEllipse(rect);
00382 
00383         m_windecoButtonGlowCache.insert(key, pixmap);
00384     }
00385 
00386     return *pixmap;
00387 }
00388 
00389 QPixmap OxygenHelper::glow(const QColor &color, int size, int rsize)
00390 {
00391     QPixmap pixmap(rsize, rsize);
00392     pixmap.fill(QColor(0,0,0,0));
00393 
00394     QPainter p(&pixmap);
00395     p.setRenderHints(QPainter::Antialiasing);
00396     p.setPen(Qt::NoPen);
00397     p.setWindow(0,0,size,size);
00398 
00399     QRectF r(0, 0, size, size);
00400     double m = double(size)*0.5;
00401 
00402     const double width = 3.0;
00403     const double bias = _glowBias * double(size) / double(rsize);
00404     double k0 = (m-width+bias) / m;
00405     QRadialGradient glowGradient(m, m, m);
00406     for (int i = 0; i < 8; i++) { // inverse parabolic gradient
00407         double k1 = (k0 * double(8 - i) + double(i)) * 0.125;
00408         double a = 1.0 - sqrt(i * 0.125);
00409         glowGradient.setColorAt(k1, alphaColor(color, a));
00410     }
00411     glowGradient.setColorAt(1.0, alphaColor(color, 0.0));
00412 
00413     // glow
00414     p.setBrush(glowGradient);
00415     p.drawEllipse(r);
00416 
00417     // mask
00418     p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00419     p.setBrush(QBrush(Qt::black));
00420     p.drawEllipse(r.adjusted(width, width, -width, -width));
00421 
00422     p.end();
00423 
00424     return pixmap;
00425 }
00426 
00427 void OxygenHelper::drawFloatFrame(QPainter *p, const QRect r, const QColor &color, bool drawUglyShadow, bool isActive, const QColor &frameColor) const
00428 {
00429     p->setRenderHint(QPainter::Antialiasing);
00430     QRect frame = r;
00431     frame.adjust(1,1,-1,-1);
00432     int x,y,w,h;
00433     frame.getRect(&x, &y, &w, &h);
00434 
00435     QColor light = calcLightColor(backgroundTopColor(color));
00436     QColor dark = calcLightColor(backgroundBottomColor(color));
00437     QColor glow = KColorUtils::mix(QColor(128,128,128),frameColor,0.7);
00438 
00439     p->setBrush(Qt::NoBrush);
00440 
00441     if (drawUglyShadow) {
00442         if(isActive) { //window active - it's a glow - not a shadow
00443             p->setPen(glow);
00444             p->drawLine(QPointF(x+4, y-0.5), QPointF(x+w-4, y-0.5));
00445             p->drawArc(QRectF(x-0.5, y-0.5, 11, 11),90*16, 90*16);
00446             p->drawArc(QRectF(x+w-11+0.5, y-0.5, 11, 11), 0, 90*16);
00447             p->drawLine(QPointF(x-0.5, y+4), QPointF(x-0.5, y+h-4));
00448             p->drawLine(QPointF(x+w+0.5, y+4), QPointF(x+w+0.5, y+h-4));
00449             p->drawArc(QRectF(0.5, y+h-11+0.5, 11, 11),180*16, 90*16);
00450             p->drawArc(QRectF(x+w-11+0.5, y+h-11+0.5, 11, 11),270*16, 90*16);
00451             p->drawLine(QPointF(x+4, y+h+0.5), QPointF(x+w-4, y+h+0.5));
00452             light = KColorUtils::mix(light, frameColor);
00453             dark = KColorUtils::mix(dark, frameColor);
00454         }
00455         else { //window inactive - draw something resembling shadow
00456             QColor shadow = KColorUtils::darken(color, 0.0, 0.0); // fully desaturate
00457             p->setPen(KColorUtils::darken(shadow, 0.2));
00458             p->drawLine(QPointF(x+4, y-0.5), QPointF(x+w-4, y-0.5));
00459             p->drawArc(QRectF(x-0.5, y-0.5, 11, 11),90*16, 90*16);
00460             p->drawArc(QRectF(x+w-11+0.5, y-0.5, 11, 11), 0, 90*16);
00461             p->setPen(KColorUtils::darken(shadow, 0.35));
00462             p->drawLine(QPointF(x-0.5, y+4), QPointF(x-0.5, y+h-4));
00463             p->drawLine(QPointF(x+w+0.5, y+4), QPointF(x+w+0.5, y+h-4));
00464             p->setPen(KColorUtils::darken(shadow, 0.45));
00465             p->drawArc(QRectF(0.5, y+h-11+0.5, 11, 11),180*16, 90*16);
00466             p->drawArc(QRectF(x+w-11+0.5, y+h-11+0.5, 11, 11),270*16, 90*16);
00467             p->setPen(KColorUtils::darken(shadow, 0.6));
00468             p->drawLine(QPointF(x+4, y+h+0.5), QPointF(x+w-4, y+h+0.5));
00469         }
00470     }
00471 
00472     p->setPen(QPen(light, 0.8));
00473     p->drawLine(QPointF(x+4, y+0.6), QPointF(x+w-4, y+0.6));
00474     QLinearGradient lg = QLinearGradient(0.0, 1.5, 0.0, 4.5);
00475     lg.setColorAt(0, light);
00476     lg.setColorAt(1, dark);
00477     p->setPen(QPen(lg, 0.8));
00478     p->drawArc(QRectF(x+0.6, y+0.6, 9, 9),90*16, 90*16);
00479     p->drawArc(QRectF(x+w-9-0.6, y+0.6, 9, 9), 0, 90*16);
00480     p->drawLine(QPointF(x+0.6, y+4), QPointF(x+0.6, y+h-4));
00481     p->drawLine(QPointF(x+w-0.6, y+4), QPointF(x+w-0.6, y+h-4));
00482 
00483     return;
00484 }
00485 
00486 void OxygenHelper::drawSeparator(QPainter *p, const QRect &rect, const QColor &color, Qt::Orientation orientation) const
00487 {
00488     QColor light = calcLightColor(color);
00489     QColor dark = calcDarkColor(color);
00490 
00491     bool antialias = p->testRenderHint(QPainter::Antialiasing);
00492     p->setRenderHint(QPainter::Antialiasing,false);
00493 
00494     QPoint start,end,offset;
00495 
00496     if (orientation == Qt::Horizontal) {
00497         start = QPoint(rect.x(),rect.y()+rect.height()/2-1);
00498         end = QPoint(rect.right(),rect.y()+rect.height()/2-1);
00499         offset = QPoint(0,1);
00500     } else {
00501         start = QPoint(rect.x()+rect.width()/2-1,rect.y());
00502         end = QPoint(rect.x()+rect.width()/2-1,rect.bottom());
00503         offset = QPoint(1,0);
00504         light.setAlpha(150);
00505     }
00506 
00507     QLinearGradient lg(start,end);
00508     lg.setColorAt(0.3, dark);
00509     lg.setColorAt(0.7, dark);
00510     dark.setAlpha(0);
00511     lg.setColorAt(0.0, dark);
00512     lg.setColorAt(1.0, dark);
00513     p->setPen(QPen(lg,1));
00514 
00515     if (orientation == Qt::Horizontal)
00516         p->drawLine(start,end);
00517     else
00518         p->drawLine(start+offset,end+offset);
00519 
00520     lg = QLinearGradient(start,end);
00521     lg.setColorAt(0.3, light);
00522     lg.setColorAt(0.7, light);
00523     light.setAlpha(0);
00524     lg.setColorAt(0.0, light);
00525     lg.setColorAt(1.0, light);
00526     p->setPen(QPen(lg,1));
00527 
00528 
00529     if (orientation == Qt::Horizontal)
00530         p->drawLine(start+offset,end+offset);
00531     else
00532     {
00533         p->drawLine(start,end);
00534         p->drawLine(start+offset*2,end+offset*2);
00535     }
00536 
00537     p->setRenderHint(QPainter::Antialiasing, antialias);
00538 }
00539 

KStyles

Skip menu "KStyles"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KCMShell
  • KNotify
  • KStyles
  • Nepomuk Daemons
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal