1 /* This file is part of the KDE project
2    Copyright 2005-2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18 */
19 
20 // Local
21 #include "StyleCommand.h"
22 
23 #include <QBrush>
24 
25 #include <KLocalizedString>
26 
27 #include "Cell.h"
28 #include "CellStorage.h"
29 #include "Damages.h"
30 #include "Map.h"
31 #include "Sheet.h"
32 #include "Style.h"
33 #include "StyleStorage.h"
34 
35 using namespace Calligra::Sheets;
36 
StyleCommand(KUndo2Command * parent)37 StyleCommand::StyleCommand(KUndo2Command* parent)
38         : AbstractRegionCommand(parent)
39         , m_horizontalPen(QPen(QColor(), 0, Qt::NoPen))
40         , m_verticalPen(QPen(QColor(), 0, Qt::NoPen))
41         , m_horizontalPenChanged(false)
42         , m_verticalPenChanged(false)
43         , m_style(new Style())
44 {
45 }
46 
~StyleCommand()47 StyleCommand::~StyleCommand()
48 {
49     delete m_style;
50 }
51 
process(Element * element)52 bool StyleCommand::process(Element* element)
53 {
54     const QRect range = element->rect();
55     if (!m_reverse) { // (re)do
56         if (m_firstrun) {
57             const QRect rect = range.adjusted(m_style->hasAttribute(Style::LeftPen) ? -1 : 0,
58                                               m_style->hasAttribute(Style::TopPen) ? -1 : 0,
59                                               m_style->hasAttribute(Style::RightPen) ? 1 : 0,
60                                               m_style->hasAttribute(Style::BottomPen) ? 1 : 0);
61             const QList< QPair<QRectF, SharedSubStyle> > rawUndoData
62             = m_sheet->styleStorage()->undoData(Region(rect));
63             for (int i = 0; i < rawUndoData.count(); ++i) {
64 //                 if ( m_style->hasAttribute( rawUndoData[i].second->type() ) ||
65 //                      rawUndoData[i].second->type() == Style::DefaultStyleKey ||
66 //                      rawUndoData[i].second->type() == Style::NamedStyleKey )
67                 m_undoData << rawUndoData[i];
68             }
69         }
70         // special handling for the border
71         bool hasLeftPen = m_style->hasAttribute(Style::LeftPen);
72         bool hasRightPen = m_style->hasAttribute(Style::RightPen);
73         bool hasTopPen = m_style->hasAttribute(Style::TopPen);
74         bool hasBottomPen = m_style->hasAttribute(Style::BottomPen);
75         const QPen leftPen = m_style->leftBorderPen();
76         const QPen rightPen = m_style->rightBorderPen();
77         const QPen topPen = m_style->topBorderPen();
78         const QPen bottomPen = m_style->bottomBorderPen();
79         m_style->clearAttribute(Style::LeftPen);
80         m_style->clearAttribute(Style::RightPen);
81         m_style->clearAttribute(Style::TopPen);
82         m_style->clearAttribute(Style::BottomPen);
83 
84         // use the horizontal/vertical pens
85         if (m_horizontalPenChanged) {
86             m_style->setTopBorderPen(m_horizontalPen);
87             m_style->setBottomBorderPen(m_horizontalPen);
88             hasTopPen = hasBottomPen = true;
89         }
90         if (m_verticalPenChanged) {
91             m_style->setLeftBorderPen(m_verticalPen);
92             m_style->setRightBorderPen(m_verticalPen);
93             hasLeftPen = hasRightPen = true;
94         }
95 
96         // special handling for indentation: reset the indentation first
97         if (m_style->hasAttribute(Style::Indentation)) {
98             Style style;
99             style.setIndentation(0);
100             m_sheet->cellStorage()->setStyle(Region(range), style);
101         }
102 
103         // special handling for precision: reset the precision first
104         if (m_style->hasAttribute(Style::Precision)) {
105             Style style;
106             style.setPrecision(0);   // insert storage default
107             m_sheet->cellStorage()->setStyle(Region(range), style);
108         }
109 
110         // set the actual style
111         m_sheet->cellStorage()->setStyle(Region(range), *m_style);
112 
113         // prepare to restore pens
114         m_style->clearAttribute(Style::LeftPen);
115         m_style->clearAttribute(Style::RightPen);
116         m_style->clearAttribute(Style::TopPen);
117         m_style->clearAttribute(Style::BottomPen);
118 
119         // set the outer border styles
120         Style style;
121         if (hasLeftPen) {
122             style.setLeftBorderPen(leftPen);
123             m_sheet->cellStorage()->setStyle(Region(QRect(range.left(), range.top(), 1, range.height())), style);
124             m_style->setLeftBorderPen(leftPen); // restore pen
125             // reset the border of the adjacent cell
126             if (range.left() > 1) {
127                 Style tmpStyle;
128                 tmpStyle.setRightBorderPen(QPen(Qt::NoPen));
129                 const Region region(QRect(range.left() - 1, range.top(), 1, range.height()));
130                 m_sheet->cellStorage()->setStyle(region, tmpStyle);
131                 m_sheet->map()->addDamage(new CellDamage(m_sheet, region, CellDamage::Appearance));
132             }
133         }
134         if (hasRightPen) {
135             style.clear();
136             style.setRightBorderPen(rightPen);
137             m_sheet->cellStorage()->setStyle(Region(QRect(range.right(), range.top(), 1, range.height())), style);
138             m_style->setRightBorderPen(rightPen); // restore pen
139             // reset the border of the adjacent cell
140             if (range.right() < KS_colMax) {
141                 Style tmpStyle;
142                 tmpStyle.setLeftBorderPen(QPen(Qt::NoPen));
143                 const Region region(QRect(range.right() + 1, range.top(), 1, range.height()));
144                 m_sheet->cellStorage()->setStyle(region, tmpStyle);
145                 m_sheet->map()->addDamage(new CellDamage(m_sheet, region, CellDamage::Appearance));
146             }
147         }
148         if (hasTopPen) {
149             style.clear();
150             style.setTopBorderPen(topPen);
151             m_sheet->cellStorage()->setStyle(Region(QRect(range.left(), range.top(), range.width(), 1)), style);
152             m_style->setTopBorderPen(topPen); // restore pen
153             // reset the border of the adjacent cell
154             if (range.top() > 1) {
155                 Style tmpStyle;
156                 tmpStyle.setBottomBorderPen(QPen(Qt::NoPen));
157                 const Region region(QRect(range.left(), range.top() - 1, range.width(), 1));
158                 m_sheet->cellStorage()->setStyle(region, tmpStyle);
159                 m_sheet->map()->addDamage(new CellDamage(m_sheet, region, CellDamage::Appearance));
160             }
161         }
162         if (hasBottomPen) {
163             style.clear();
164             style.setBottomBorderPen(bottomPen);
165             m_sheet->cellStorage()->setStyle(Region(QRect(range.left(), range.bottom(), range.width(), 1)), style);
166             m_style->setBottomBorderPen(bottomPen); // restore pen
167             // reset the border of the adjacent cell
168             if (range.bottom() < KS_rowMax) {
169                 Style tmpStyle;
170                 tmpStyle.setTopBorderPen(QPen(Qt::NoPen));
171                 const Region region(QRect(range.left(), range.bottom() + 1, range.width(), 1));
172                 m_sheet->cellStorage()->setStyle(region, tmpStyle);
173                 m_sheet->map()->addDamage(new CellDamage(m_sheet, region, CellDamage::Appearance));
174             }
175         }
176     }
177     return true;
178 }
179 
preProcessing()180 bool StyleCommand::preProcessing()
181 {
182     if (m_firstrun) {
183         if (m_style->isDefault())
184             setText(kundo2_i18n("Reset Style"));
185         else
186             setText(kundo2_i18n("Change Style"));
187 
188         // special handling for precision
189         if (m_style->hasAttribute(Style::Precision)) {
190             if (m_style->precision() == -1)   // Style default
191                 m_style->setPrecision(0);   // storage default
192             else if (m_style->precision() == 0)
193                 m_style->setPrecision(-1);   // anything resulting in zero, but not storage default
194         }
195     }
196     return AbstractRegionCommand::preProcessing();
197 }
198 
mainProcessing()199 bool StyleCommand::mainProcessing()
200 {
201     if (!m_reverse) {
202     } else { // m_reverse
203         Style style;
204         style.setDefault();
205         // special handling for indentation
206         style.setIndentation(0);   // reset to zero
207         // special handling for precision
208         style.setPrecision(0);   // reset to storage default
209         m_sheet->cellStorage()->setStyle(*this, style);
210         for (int i = 0; i < m_undoData.count(); ++i) {
211             m_sheet->cellStorage()->insertSubStyle(m_undoData[i].first.toRect(), m_undoData[i].second);
212         }
213     }
214     return AbstractRegionCommand::mainProcessing();
215 }
216 
postProcessing()217 bool StyleCommand::postProcessing()
218 {
219     return true;
220 }
221