1 /* This file is part of the KDE project
2  * Copyright (C) 2007, 2009 Thomas Zander <zander@kde.org>
3  * Copyright (c) 2003 David Faure <faure@kde.org>
4  * Copyright (C)  2011 Mojtaba Shahi Senobari <mojtaba.shahi3000@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "ParagraphIndentSpacing.h"
23 
24 #include <KoParagraphStyle.h>
25 #include <QDebug>
26 
ParagraphIndentSpacing(QWidget * parent)27 ParagraphIndentSpacing::ParagraphIndentSpacing(QWidget *parent)
28         : QWidget(parent),
29         m_fontMetricsChecked(false)
30 {
31     widget.setupUi(this);
32 
33     connect(widget.first, SIGNAL(valueChangedPt(qreal)), this, SLOT(firstLineMarginChanged(qreal)));
34     connect(widget.left, SIGNAL(valueChangedPt(qreal)), this, SLOT(leftMarginChanged(qreal)));
35     connect(widget.right, SIGNAL(valueChangedPt(qreal)), this, SLOT(rightMarginChanged(qreal)));
36 
37     // Keep order in sync with lineSpacingType() and display()
38     widget.lineSpacing->addItem(i18nc("Line spacing value", "Single"));
39     widget.lineSpacing->addItem(i18nc("Line spacing value", "1.5 Lines"));
40     widget.lineSpacing->addItem(i18nc("Line spacing value", "Double"));
41     widget.lineSpacing->addItem(i18nc("Line spacing type", "Proportional"));    // called Proportional like in OO
42     widget.lineSpacing->addItem(i18nc("Line spacing type", "Additional"));    // normal distance + absolute value
43     widget.lineSpacing->addItem(i18nc("Line spacing type", "Fixed"));
44     widget.lineSpacing->addItem(i18nc("Line spacing type", "At least"));
45 
46     connect(widget.first, SIGNAL(valueChangedPt(qreal)), this, SLOT(firstIndentValueChanged()));
47     connect(widget.left, SIGNAL(valueChangedPt(qreal)), this, SLOT(leftMarginValueChanged()));
48     connect(widget.right, SIGNAL(valueChangedPt(qreal)), this, SLOT(rightMarginValueChanged()));
49     connect(widget.after, SIGNAL(valueChangedPt(qreal)), this, SLOT(bottomMarginValueChanged()));
50     connect(widget.before, SIGNAL(valueChangedPt(qreal)), this, SLOT(topMarginValueChanged()));
51     connect(widget.lineSpacing, SIGNAL(currentIndexChanged(int)), this, SLOT(lineSpacingChanged(int)));
52     connect(widget.useFont, SIGNAL(toggled(bool)), this, SLOT(useFontMetrices(bool)));
53     connect(widget.autoTextIndent, SIGNAL(stateChanged(int)), this, SLOT(autoTextIndentChanged(int)));
54     connect(widget.proportional, SIGNAL(valueChanged(int)), this, SLOT(spacingPercentChanged()));
55     connect(widget.custom, SIGNAL(valueChangedPt(qreal)), this, SLOT(spacingValueChanged()));
56     lineSpacingChanged(0);
57 }
58 
autoTextIndentChanged(int state)59 void ParagraphIndentSpacing::autoTextIndentChanged(int state)
60 {
61     widget.first->setEnabled(state == Qt::Unchecked);
62     m_autoTextIndentInherited = false;
63     emit parStyleChanged();
64 }
firstIndentValueChanged()65 void ParagraphIndentSpacing::firstIndentValueChanged()
66 {
67     m_textIndentInherited = false;
68     emit parStyleChanged();
69 }
70 
rightMarginValueChanged()71 void ParagraphIndentSpacing::rightMarginValueChanged()
72 {
73     m_rightMarginIngerited = false;
74     emit parStyleChanged();
75 }
76 
leftMarginValueChanged()77 void ParagraphIndentSpacing::leftMarginValueChanged()
78 {
79     m_leftMarginInherited = false;
80     emit parStyleChanged();
81 }
82 
topMarginValueChanged()83 void ParagraphIndentSpacing::topMarginValueChanged()
84 {
85     m_topMarginInherited = false;
86     emit parStyleChanged();
87 }
88 
bottomMarginValueChanged()89 void ParagraphIndentSpacing::bottomMarginValueChanged()
90 {
91     m_bottomMarginInherited = false;
92     emit parStyleChanged();
93 }
94 
setDisplay(KoParagraphStyle * style,bool directFormattingMode)95 void ParagraphIndentSpacing::setDisplay(KoParagraphStyle *style, bool directFormattingMode)
96 {
97     m_style = style;
98     // TODO : handle relatives
99     widget.first->changeValue(style->textIndent());
100     widget.left->changeValue(style->leftMargin());
101     widget.right->changeValue(style->rightMargin());
102     widget.before->changeValue(style->topMargin());
103     widget.after->changeValue(style->bottomMargin());
104 
105     m_rightMarginIngerited = directFormattingMode || !style->hasProperty(QTextFormat::BlockRightMargin);
106     m_leftMarginInherited = directFormattingMode || !style->hasProperty(QTextFormat::BlockLeftMargin);
107     m_topMarginInherited = directFormattingMode || !style->hasProperty(QTextFormat::BlockTopMargin);
108     m_bottomMarginInherited = directFormattingMode || !style->hasProperty(QTextFormat::BlockBottomMargin);
109     m_autoTextIndentInherited = directFormattingMode  || !style->hasProperty(KoParagraphStyle::AutoTextIndent);
110     m_textIndentInherited = directFormattingMode || !style->hasProperty(QTextFormat::TextIndent);
111 
112     widget.autoTextIndent->setChecked(style->autoTextIndent());
113 
114     m_spacingInherited = !(style->hasProperty(KoParagraphStyle::FixedLineHeight) || style->hasProperty(KoParagraphStyle::LineSpacing) || style->hasProperty(KoParagraphStyle::PercentLineHeight) ||style->hasProperty(KoParagraphStyle::MinimumLineHeight));
115 
116     int index;
117     if (style->hasProperty(KoParagraphStyle::FixedLineHeight) && style->lineHeightAbsolute() != 0) {
118         // this is the strongest; if this is set we don't care what other properties there are.
119         index = 5;
120     } else if (style->hasProperty(KoParagraphStyle::LineSpacing) && style->lineSpacing() != 0) {
121         // if LineSpacing is set then percent is ignored.
122         index = 4;
123     } else if (style->hasProperty(KoParagraphStyle::PercentLineHeight) && style->lineHeightPercent() != 0) {
124         int percent = style->lineHeightPercent();
125         if (percent == 100)
126             index = 0; // single
127         else if (percent == 150)
128             index = 1; // 1.5
129         else if (percent == 200)
130             index = 2; // double
131         else
132             index = 3; // proportional
133     } else if (style->hasProperty(KoParagraphStyle::MinimumLineHeight) && style->minimumLineHeight() != 0) {
134         index = 6;
135     } else {
136         index = 0; // nothing set, default is 'single' just like for geeks.
137     }
138     widget.lineSpacing->setCurrentIndex(index);
139     //widget.minimumLineSpacing->changeValue(style->minimumLineHeight());
140     widget.useFont->setChecked(style->lineSpacingFromFont());
141     m_fontMetricsChecked = style->lineSpacingFromFont();
142 }
143 
lineSpacingChanged(int row)144 void ParagraphIndentSpacing::lineSpacingChanged(int row)
145 {
146     bool percent = false, custom = false;
147     qreal customValue = 0.0;
148     switch (row) {
149         case 0:
150         case 1:
151         case 2:
152             break;
153         case 3: // proportional
154             percent = true;
155             widget.proportional->setValue(m_style->lineHeightPercent());
156             break;
157         case 4: // additional
158             custom = true;
159             customValue = qMax(qreal(0.1), m_style->lineSpacing());
160             break;
161         case 5: // fixed
162             custom = true;
163             if (m_style->lineHeightAbsolute() == 0) // unset
164                 customValue = 12.0; // nice default value...
165             else
166                 customValue = m_style->lineHeightAbsolute();
167             break;
168         case 6: // minimum
169             custom = true;
170             customValue = m_style->minimumLineHeight();
171             break;
172         default:; // other cases don't need the spinboxes
173     }
174 
175     m_spacingInherited = false;
176 
177     if (custom) {
178         widget.custom->setEnabled(true);
179         widget.spacingStack->setCurrentWidget(widget.unitsPage);
180         widget.custom->changeValue(customValue);
181     } else {
182         widget.spacingStack->setCurrentWidget(widget.percentPage);
183         widget.proportional->setEnabled(percent);
184         if (! percent)
185             widget.proportional->setValue(100);
186     }
187 
188     widget.useFont->setEnabled(row != 5);
189     widget.useFont->setChecked(row == 5 ? false : m_fontMetricsChecked);
190     emit parStyleChanged();
191 }
192 
spacingPercentChanged()193 void ParagraphIndentSpacing::spacingPercentChanged()
194 {
195     m_spacingInherited = false;
196     emit parStyleChanged();
197 }
198 
spacingValueChanged()199 void ParagraphIndentSpacing::spacingValueChanged()
200 {
201     m_spacingInherited = false;
202     emit parStyleChanged();
203 }
204 
save(KoParagraphStyle * style)205 void ParagraphIndentSpacing::save(KoParagraphStyle *style)
206 {
207     // general note; we have to unset values by setting it to zero instead of removing the item
208     // since this dialog may be used on a copy style, which will be applied later. And removing
209     // items doesn't work for that.
210     if (!m_textIndentInherited){
211         style->setTextIndent(QTextLength(QTextLength::FixedLength, widget.first->value()));
212     }
213     if (!m_leftMarginInherited){
214         style->setLeftMargin(QTextLength(QTextLength::FixedLength, widget.left->value()));
215     }
216     if (!m_rightMarginIngerited){
217         style->setRightMargin(QTextLength(QTextLength::FixedLength, widget.right->value()));
218     }
219     if (!m_topMarginInherited){
220         style->setTopMargin(QTextLength(QTextLength::FixedLength, widget.before->value()));
221     }
222     if (!m_bottomMarginInherited){
223         style->setBottomMargin(QTextLength(QTextLength::FixedLength, widget.after->value()));
224     }
225     if (!m_autoTextIndentInherited){
226         style->setAutoTextIndent(widget.autoTextIndent->isChecked());
227     }
228     if (!m_spacingInherited) {
229         style->setLineHeightAbsolute(0); // since it trumps percentage based line heights, unset it.
230         style->setMinimumLineHeight(QTextLength(QTextLength::FixedLength, 0));
231         style->setLineSpacing(0);
232         switch (widget.lineSpacing->currentIndex()) {
233         case 0: style->setLineHeightPercent(100); break;
234         case 1: style->setLineHeightPercent(150); break;
235         case 2: style->setLineHeightPercent(200); break;
236         case 3: style->setLineHeightPercent(widget.proportional->value()); break;
237         case 4:
238             if (widget.custom->value() == 0.0) { // then we need to save it differently.
239                 style->setLineHeightPercent(100);
240             } else {
241                 style->setLineSpacing(widget.custom->value());
242             }
243             break;
244         case 5:
245             style->setLineHeightAbsolute(widget.custom->value());
246             break;
247         case 6:
248             style->setMinimumLineHeight(QTextLength(QTextLength::FixedLength, widget.custom->value()));
249             break;
250         }
251         style->setLineSpacingFromFont(widget.lineSpacing->currentIndex() != 5 && widget.useFont->isChecked());
252     }
253 }
254 
setUnit(const KoUnit & unit)255 void ParagraphIndentSpacing::setUnit(const KoUnit &unit)
256 {
257     widget.first->setUnit(unit);
258     widget.left->setUnit(unit);
259     widget.right->setUnit(unit);
260     widget.before->setUnit(unit);
261     widget.after->setUnit(unit);
262     widget.custom->setUnit(unit);
263 }
264 
useFontMetrices(bool on)265 void ParagraphIndentSpacing::useFontMetrices(bool on)
266 {
267     if (widget.lineSpacing->currentIndex() != 5)
268         m_fontMetricsChecked = on;
269     emit parStyleChanged();
270 }
271 
firstLineMarginChanged(qreal margin)272 void ParagraphIndentSpacing::firstLineMarginChanged(qreal margin)
273 {
274     Q_UNUSED(margin);
275     emit parStyleChanged();
276 }
277 
leftMarginChanged(qreal margin)278 void ParagraphIndentSpacing::leftMarginChanged(qreal margin)
279 {
280     Q_UNUSED(margin);
281     emit parStyleChanged();
282 }
283 
rightMarginChanged(qreal margin)284 void ParagraphIndentSpacing::rightMarginChanged(qreal margin)
285 {
286     Q_UNUSED(margin);
287     emit parStyleChanged();
288 }
289