1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3 
4     SPDX-FileCopyrightText: 2002 Dario Abatianni <eisfuchs@tigress.com>
5     SPDX-FileCopyrightText: 2005-2006 Eike Hein <hein@kde.org>
6 */
7 
8 #include "images.h"
9 #include "common.h"
10 #include "application.h"
11 #include "nickiconset.h"
12 
13 #include <QIconEngine>
14 #include <QPainter>
15 
16 #include <QStandardPaths>
17 
18 
19 using namespace Konversation;
20 
21 
22 class LedIconEngine : public QIconEngine
23 {
24     public:
LedIconEngine(const QColor & color,bool state)25         LedIconEngine(const QColor &color, bool state)
26             : QIconEngine(), m_color(color), m_state(state)
27         {
28         }
29         ~LedIconEngine() override = default;
30 
31         // QIconEngine
32         void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
33         QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
34         QIconEngine* clone() const override;
35 
36     private:
37         const QColor m_color;
38         const bool m_state;
39 
40         Q_DISABLE_COPY(LedIconEngine)
41 };
42 
paint(QPainter * painter,const QRect & rect,QIcon::Mode mode,QIcon::State state)43 void LedIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
44 {
45     Q_UNUSED(mode)
46     Q_UNUSED(state)
47 
48     QColor color;
49     QBrush brush;
50     QPen pen;
51 
52     if (!m_state)
53         color = m_color.darker(180);
54     else
55         color = m_color;
56 
57     int scale = rect.width() / 12;
58     int width = rect.width();
59 
60     // Set the brush to Qt::SolidPattern, this fills the entire area
61     // of the ellipse which is drawn first
62     brush.setStyle( Qt::SolidPattern );
63     brush.setColor( color );
64     painter->setBrush( brush );
65 
66     // Draw a "flat" LED with the given color
67     painter->drawEllipse( scale, scale, width - scale*2, width - scale*2 );
68 
69     // Setting the new width of the pen is essential to avoid "pixelized"
70     // shadow like it can be observed with the old LED code
71     pen.setWidth( rect.width() / 12 );
72 
73     // shrink the light on the LED to a size about 2/3 of the complete LED
74     int pos = width/5 + 1;
75     int light_width = width;
76     light_width *= 2;
77     light_width /= 3;
78 
79     // Calculate the LEDs "light factor"
80     int light_quote = (130*2/(light_width?light_width:1))+100;
81 
82     // Draw the bright spot on the LED
83     while (light_width)
84     {
85         color = color.lighter( light_quote ); // make color lighter
86         pen.setColor( color );              // set color as pen color
87         painter->setPen( pen );                // select the pen for drawing
88         painter->drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle)
89         light_width--;
90         if (!light_width)
91             break;
92         painter->drawEllipse( pos, pos, light_width, light_width );
93         light_width--;
94         if (!light_width)
95             break;
96         painter->drawEllipse( pos, pos, light_width, light_width );
97         pos++; light_width--;
98     }
99 
100     // Draw border
101     pen.setWidth( rect.width() / 12 + 1 );
102     color = QColor("#7D7D7D");
103     pen.setColor( color );             // Set the pen accordingly
104     painter->setPen( pen );               // Select pen for drawing
105     brush.setStyle( Qt::NoBrush ); // Switch off the brush
106     painter->setBrush( brush );           // This avoids filling of the ellipse
107     painter->drawEllipse( 2, 2, rect.width() - 4, rect.width() - 4 );
108 }
109 
pixmap(const QSize & size,QIcon::Mode mode,QIcon::State state)110 QPixmap LedIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
111 {
112     QPixmap pix(size);
113     {
114         pix.fill(Qt::transparent);
115         QPainter p(&pix);
116         p.setRenderHint(QPainter::Antialiasing);
117         paint(&p, QRect(QPoint(0, 0), size), mode, state);
118     }
119     return pix;
120 }
121 
clone() const122 QIconEngine* LedIconEngine::clone() const
123 {
124     auto* newEngine = new LedIconEngine(m_color, m_state);
125 
126     return newEngine;
127 }
128 
129 
Images()130 Images::Images()
131     : nickIconSet(new NickIconSet)
132 {
133     initializeLeds();
134     initializeNickIcons();
135 }
136 
~Images()137 Images::~Images()
138 {
139 }
140 
getNickIconSize() const141 int Images::getNickIconSize() const
142 {
143     return nickIconSet->defaultIconSize();
144 }
145 
getNickIcon(NickPrivilege privilege,bool isAway) const146 QIcon Images::getNickIcon(NickPrivilege privilege,bool isAway) const
147 {
148     return nickIconSet->nickIcon(privilege, isAway ? NickIconSet::UserAway : NickIconSet::UserPresent);
149 }
150 
getNickIconAwayOverlay() const151 QIcon Images::getNickIconAwayOverlay() const
152 {
153     return nickIconSet->nickIconAwayOverlay();
154 }
155 
initializeLeds()156 void Images::initializeLeds()
157 {
158     m_serverColor = "steelblue";
159     m_systemColor = Preferences::self()->tabNotificationsSystemColor();
160     m_msgsColor = Preferences::self()->tabNotificationsMsgsColor();
161     m_privateColor = Preferences::self()->tabNotificationsPrivateColor();
162     m_eventsColor = Preferences::self()->tabNotificationsEventsColor();
163     m_nickColor = Preferences::self()->tabNotificationsNickColor();
164     m_highlightsColor = Preferences::self()->tabNotificationsHighlightsColor();
165 
166     // m_serverLedOn = getLed(m_serverColor,true);
167     m_serverLedOff = getLed(m_serverColor,false);
168     m_systemLedOn = getLed(m_systemColor,true);
169     m_systemLedOff = getLed(m_systemColor,false);
170     m_msgsLedOn = getLed(m_msgsColor,true);
171     m_msgsLedOff = getLed(m_msgsColor,false);
172     m_privateLedOn = getLed(m_privateColor,true);
173     m_privateLedOff = getLed(m_privateColor,false);
174     m_eventsLedOn = getLed(m_eventsColor,true);
175     m_nickLedOn = getLed(m_nickColor,true);
176     m_highlightsLedOn = getLed(m_highlightsColor,true);
177 }
178 
179 // NickIcons
180 
initializeNickIcons()181 void Images::initializeNickIcons()
182 {
183     QString iconTheme = Preferences::self()->iconTheme();
184     QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("konversation/themes/") + iconTheme, QStandardPaths::LocateDirectory);
185     const bool isDefaultTheme = (iconTheme == QLatin1String("default"));
186 
187     for (const QString& dir : qAsConst(dirs)) {
188         if (nickIconSet->load(dir)) {
189             break;
190         }
191     }
192 
193     // fallback to default if theme could not be loaded
194     if (nickIconSet->isNull() && !isDefaultTheme) {
195         dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("konversation/themes/default"), QStandardPaths::LocateDirectory);
196 
197         for (const QString& dir : qAsConst(dirs)) {
198             if (nickIconSet->load(dir)) {
199                 break;
200             }
201         }
202     }
203 }
204 
getLed(const QColor & col,bool state) const205 QIcon Images::getLed(const QColor& col,bool state) const
206 {
207     Q_UNUSED(col)
208     Q_UNUSED(state)
209 
210     return QIcon(new LedIconEngine(col, state));
211 }
212 
getServerLed(bool state) const213 QIcon Images::getServerLed(bool state) const
214 {
215     if (state)
216         return m_serverLedOn;
217     else
218         return m_serverLedOff;
219 }
220 
getSystemLed(bool state) const221 QIcon Images::getSystemLed(bool state) const
222 {
223     if (Preferences::self()->tabNotificationsSystemColor()!=m_systemColor)
224     {
225         if (state)
226             return getLed(Preferences::self()->tabNotificationsSystemColor(),true);
227         else
228             return getLed(Preferences::self()->tabNotificationsSystemColor(),false);
229     }
230     else
231     {
232         if (state)
233             return m_systemLedOn;
234         else
235             return m_systemLedOff;
236     }
237 }
238 
getMsgsLed(bool state) const239 QIcon Images::getMsgsLed(bool state) const
240 {
241     if (Preferences::self()->tabNotificationsMsgsColor()!=m_msgsColor)
242     {
243         if (state)
244             return getLed(Preferences::self()->tabNotificationsMsgsColor(),true);
245         else
246             return getLed(Preferences::self()->tabNotificationsMsgsColor(),false);
247     }
248     else
249     {
250         if (state)
251             return m_msgsLedOn;
252         else
253             return m_msgsLedOff;
254     }
255 }
256 
getPrivateLed(bool state) const257 QIcon Images::getPrivateLed(bool state) const
258 {
259     if (Preferences::self()->tabNotificationsPrivateColor()!=m_privateColor)
260     {
261         if (state)
262             return getLed(Preferences::self()->tabNotificationsPrivateColor(),true);
263         else
264             return getLed(Preferences::self()->tabNotificationsPrivateColor(),false);
265     }
266     else
267     {
268         if (state)
269             return m_privateLedOn;
270         else
271             return m_privateLedOff;
272     }
273 }
274 
getEventsLed() const275 QIcon Images::getEventsLed() const
276 {
277     if (Preferences::self()->tabNotificationsEventsColor()!=m_eventsColor)
278         return getLed(Preferences::self()->tabNotificationsEventsColor(),true);
279     else
280         return m_eventsLedOn;
281 }
282 
getNickLed() const283 QIcon Images::getNickLed() const
284 {
285     if (Preferences::self()->tabNotificationsNickColor()!=m_nickColor)
286         return getLed(Preferences::self()->tabNotificationsNickColor(),true);
287     else
288         return m_nickLedOn;
289 }
290 
getHighlightsLed() const291 QIcon Images::getHighlightsLed() const
292 {
293     if (Preferences::self()->tabNotificationsHighlightsColor()!=m_highlightsColor)
294         return getLed(Preferences::self()->tabNotificationsHighlightsColor(),true);
295     else
296         return m_highlightsLedOn;
297 }
298 
299 
300