1 /***************************************************************************
2 								  BoardTheme - graphics theme for BoardView
3 									  -------------------
4 	 begin                : nie sie 21 2005
5 	 copyright            : (C) 2005 Michal Rudolf <mrudolf@kdewebdev.org>
6  ***************************************************************************/
7 
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  ***************************************************************************/
16 
17 #include "boardtheme.h"
18 #include "settings.h"
19 #include "messagedialog.h"
20 
21 #include <QPixmap>
22 
23 #if defined(_MSC_VER) && defined(_DEBUG)
24 #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
25 #define new DEBUG_NEW
26 #endif // _MSC_VER
27 
BoardTheme()28 BoardTheme::BoardTheme()
29 {}
30 
~BoardTheme()31 BoardTheme::~BoardTheme()
32 {}
33 
piece(Piece p) const34 const QPixmap& BoardTheme::piece(Piece p) const
35 {
36     return m_piece[p];
37 }
38 
square(bool dark) const39 const QPixmap& BoardTheme::square(bool dark) const
40 {
41     return m_square[dark ? 1 : 0];
42 }
43 
originalPiece(Piece p) const44 const QPixmap& BoardTheme::originalPiece(Piece p) const
45 {
46     return m_originalPiece[p];
47 }
48 
originalSquare(bool dark) const49 const QPixmap& BoardTheme::originalSquare(bool dark) const
50 {
51     return m_originalSquare[dark ? 1 : 0];
52 }
53 
pieceThemeName() const54 QString BoardTheme::pieceThemeName() const
55 {
56     int start = m_pieceFilename.lastIndexOf('/') + 1;
57     return m_pieceFilename.mid(start + 1, m_pieceFilename.length() - start - 4);
58 }
59 
boardThemeName() const60 QString BoardTheme::boardThemeName() const
61 {
62     int start = m_boardFilename.lastIndexOf('/') + 1;
63     return m_boardFilename.mid(start + 1, m_pieceFilename.length() - start - 4);
64 }
65 
isValid() const66 bool BoardTheme::isValid() const
67 {
68     return !m_pieceFilename.isNull();
69 }
70 
loadPieces(const QString & pieces,int effect)71 bool BoardTheme::loadPieces(const QString& pieces, int effect)
72 {
73     QString effectPath;
74     if(effect == Outline)
75     {
76         effectPath = "outline";
77     }
78     else if(effect == Shadow)
79     {
80         effectPath = "shadow";
81     }
82 
83     QString themePath = AppSettings->getThemePath(effectPath, pieces);
84 
85     QPixmap big;
86     if(!big.load(themePath) || big.width() < 160)
87     {
88         return false;
89     }
90 
91     big.setDevicePixelRatio(2.0);
92 
93     int realsize = big.height() / 2;
94     if(realsize == big.width() / 6)
95     {
96         /* Cut big theme bitmap into separate pieces */
97         m_originalPiece[WhiteRook] = big.copy(0 * realsize, 0, realsize, realsize);
98         m_originalPiece[WhiteKnight] = big.copy(1 * realsize, 0, realsize, realsize);
99         m_originalPiece[WhiteBishop] = big.copy(2 * realsize, 0, realsize, realsize);
100         m_originalPiece[WhiteQueen] = big.copy(3 * realsize, 0, realsize, realsize);
101         m_originalPiece[WhiteKing] = big.copy(4 * realsize, 0, realsize, realsize);
102         m_originalPiece[WhitePawn] = big.copy(5 * realsize, 0, realsize, realsize);
103         m_originalPiece[BlackRook] = big.copy(0 * realsize, realsize, realsize, realsize);
104         m_originalPiece[BlackKnight] = big.copy(1 * realsize, realsize, realsize, realsize);
105         m_originalPiece[BlackBishop] = big.copy(2 * realsize, realsize, realsize, realsize);
106         m_originalPiece[BlackQueen] = big.copy(3 * realsize, realsize, realsize, realsize);
107         m_originalPiece[BlackKing] = big.copy(4 * realsize, realsize, realsize, realsize);
108         m_originalPiece[BlackPawn] = big.copy(5 * realsize, realsize, realsize, realsize);
109     }
110     else
111     {
112         // Test SCID format
113         realsize = big.height();
114         if(realsize != big.width() / 12)
115         {
116             return false;
117         }
118         /* Cut big theme bitmap into separate pieces */
119         m_originalPiece[WhitePawn] = big.copy(0 * realsize, 0, realsize, realsize);
120         m_originalPiece[WhiteKnight] = big.copy(1 * realsize, 0, realsize, realsize);
121         m_originalPiece[WhiteBishop] = big.copy(2 * realsize, 0, realsize, realsize);
122         m_originalPiece[WhiteRook] = big.copy(3 * realsize, 0, realsize, realsize);
123         m_originalPiece[WhiteQueen] = big.copy(4 * realsize, 0, realsize, realsize);
124         m_originalPiece[WhiteKing] = big.copy(5 * realsize, 0, realsize, realsize);
125         m_originalPiece[BlackPawn] = big.copy(6 * realsize, 0, realsize, realsize);
126         m_originalPiece[BlackKnight] = big.copy(7 * realsize, 0, realsize, realsize);
127         m_originalPiece[BlackBishop] = big.copy(8 * realsize, 0, realsize, realsize);
128         m_originalPiece[BlackRook] = big.copy(9 * realsize, 0, realsize, realsize);
129         m_originalPiece[BlackQueen] = big.copy(10 * realsize, 0, realsize, realsize);
130         m_originalPiece[BlackKing] = big.copy(11 * realsize, 0, realsize, realsize);
131     }
132 
133     m_pieceFilename = themePath;
134 
135     if(size().isEmpty())
136     {
137         setSize(QSize(realsize, realsize));
138     }
139     else
140     {
141         setSize(size());
142     }
143     return true;
144 }
145 
loadBoard(const QString & board)146 bool BoardTheme::loadBoard(const QString& board)
147 {
148     if(board.isEmpty())
149     {
150         m_boardFilename = board;
151         updateSquares();
152         return true;
153     }
154     QString themePath = AppSettings->getBoardPath(board);
155 
156     QPixmap big;
157     if(!big.load(themePath))
158     {
159         return false;
160     }
161     int realsize = big.height() / 2;
162     if(realsize != big.width())
163     {
164         return false;
165     }
166 
167     m_originalSquare[0] = big.copy(0, 0, realsize, realsize);
168     m_originalSquare[1] = big.copy(0, realsize, realsize, realsize);
169     m_boardFilename = themePath;
170 
171     updateSquares();
172     return true;
173 }
174 
configure()175 void BoardTheme::configure()
176 {
177     AppSettings->beginGroup("/Board/");
178     setColor(BoardTheme::LightSquare, AppSettings->getValue("lightColor").value<QColor>());
179     setColor(BoardTheme::DarkSquare, AppSettings->getValue("darkColor").value<QColor>());
180     setColor(BoardTheme::Highlight, AppSettings->getValue("highlightColor").value<QColor>());
181     setColor(BoardTheme::Frame, AppSettings->getValue("frameColor").value<QColor>());
182     setColor(BoardTheme::CurrentMove, AppSettings->getValue("currentMoveColor").value<QColor>());
183     setColor(BoardTheme::StoredMove, AppSettings->getValue("storedMoveColor").value<QColor>());
184     setColor(BoardTheme::VariationMove, AppSettings->getValue("variationMoveColor").value<QColor>());
185     setColor(BoardTheme::Threat, AppSettings->getValue("threatColor").value<QColor>());
186     setColor(BoardTheme::Target, AppSettings->getValue("targetColor").value<QColor>());
187     setColor(BoardTheme::Check, AppSettings->getValue("checkColor").value<QColor>());
188     setColor(BoardTheme::Wall, AppSettings->getValue("wallColor").value<QColor>());
189     setColor(BoardTheme::UnderProtected, AppSettings->getValue("underprotectedColor").value<QColor>());
190     setColor(BoardTheme::Engine, AppSettings->getValue("engineColor").value<QColor>());
191 
192     QString pieceTheme = AppSettings->getValue("pieceTheme").toString();
193     int pieceEffect = AppSettings->getValue("pieceEffect").toInt();
194     QString boardTheme = AppSettings->getValue("boardTheme").toString();
195     AppSettings->endGroup();
196 
197     if(!loadPieces(pieceTheme, pieceEffect))
198     {
199         static bool errorShown = false;
200         if (!errorShown)
201         {
202             errorShown = true;
203             MessageDialog::error(tr("Cannot find piece data.\nPlease check your installation."));
204         }
205     }
206     if (!loadBoard(boardTheme))
207     {
208         static bool errorShown = false;
209         if (!errorShown)
210         {
211             errorShown = true;
212             MessageDialog::error(tr("Cannot find board data.\nPlease check your installation."));
213         }
214     }
215 }
216 
size() const217 QSize BoardTheme::size() const
218 {
219     return m_size;
220 }
221 
pieceCenter() const222 QPoint BoardTheme::pieceCenter() const
223 {
224     return QPoint(m_size.width() / 2, m_size.height() / 2);
225 }
226 
rect() const227 QRect BoardTheme::rect() const
228 {
229     return QRect(QPoint(0, 0), m_size);
230 }
231 
setSize(const QSize & value)232 void BoardTheme::setSize(const QSize& value)
233 {
234     if(!isValid())
235     {
236         return;
237     }
238     m_size = value;
239     for(int i = 1; i < ConstPieceTypes; i++)
240     {
241         float r = m_originalPiece[i].devicePixelRatio();
242         m_piece[i] = m_originalPiece[i].scaled(m_size * r, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
243         m_piece[i].setDevicePixelRatio(r);
244     }
245     updateSquares();
246 }
247 
updateSquares()248 void BoardTheme::updateSquares()
249 {
250     if(!isValid())
251     {
252         return;
253     }
254     bool scale = m_size.width() > m_originalPiece[WhiteRook].width()
255                  || m_size.height() > m_originalPiece[WhiteRook].height()
256                  || m_size.width() < 30 || m_size.height() < 30;
257     if (AppSettings->getValue("/Board/AlwaysScale").toBool())
258     {
259         scale = true;
260     }
261     if(isBoardPlain())
262     {
263         m_square[0] = QPixmap(m_size);
264         m_square[0].fill(color(LightSquare).rgb());
265         m_square[1] = QPixmap(m_size);
266         m_square[1].fill(color(DarkSquare).rgb());
267     }
268     else if(scale)
269     {
270         QSize sz = size();
271         m_square[0] =  m_originalSquare[0].scaled(sz, Qt::IgnoreAspectRatio,
272                        Qt::SmoothTransformation);
273         m_square[1] =  m_originalSquare[1].scaled(sz, Qt::IgnoreAspectRatio,
274                        Qt::SmoothTransformation);
275     }
276     else
277     {
278         m_square[0] =  m_originalSquare[0].copy(rect());
279         m_square[1] =  m_originalSquare[1].copy(rect());
280     }
281 }
282 
isBoardPlain() const283 bool BoardTheme::isBoardPlain() const
284 {
285     return m_boardFilename.isEmpty();
286 }
287 
setColor(ColorRole role,const QColor & value)288 void BoardTheme::setColor(ColorRole role, const QColor& value)
289 {
290     m_colors[role] = value;
291     if(role == LightSquare || role == DarkSquare)
292     {
293         updateSquares();
294     }
295 }
296 
color(ColorRole role) const297 QColor BoardTheme::color(ColorRole role) const
298 {
299     return m_colors[role];
300 }
301 
setEnabled(bool enabled)302 void BoardTheme::setEnabled(bool enabled)
303 {
304     if(enabled)
305     {
306         AppSettings->beginGroup("/Board/");
307         setColor(BoardTheme::LightSquare, AppSettings->getValue("lightColor").value<QColor>());
308         setColor(BoardTheme::DarkSquare, AppSettings->getValue("darkColor").value<QColor>());
309         QString boardTheme = AppSettings->getValue("boardTheme").toString();
310         AppSettings->endGroup();
311         loadBoard(boardTheme);
312     }
313     else
314     {
315         setColor(BoardTheme::LightSquare, QColor(Qt::lightGray));
316         setColor(BoardTheme::DarkSquare, QColor(Qt::darkGray));
317         loadBoard(QString());
318     }
319 }
320