1 /* This file is part of the KDE project
2 * Copyright (C) 2007, 2010 Thomas Zander <zander@kde.org>
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 // clazy:excludeall=qstring-arg
21 #include "KoPageLayoutWidget.h"
22
23 #include <ui_KoPageLayoutWidget.h>
24
25 #include <KoUnit.h>
26
27 #include <QButtonGroup>
28
29 class Q_DECL_HIDDEN KoPageLayoutWidget::Private
30 {
31 public:
32 Ui::KoPageLayoutWidget widget;
33 KoPageLayout pageLayout;
34 KoUnit unit;
35
36 QButtonGroup *orientationGroup;
37 bool marginsEnabled;
38 bool allowSignals;
39 };
40
41
KoPageLayoutWidget(QWidget * parent,const KoPageLayout & layout)42 KoPageLayoutWidget::KoPageLayoutWidget(QWidget *parent, const KoPageLayout &layout)
43 : QWidget(parent)
44 , d(new Private)
45 {
46 d->widget.setupUi(this);
47
48 d->pageLayout = layout;
49 d->marginsEnabled = true;
50 d->allowSignals = true;
51 d->orientationGroup = new QButtonGroup(this);
52 d->orientationGroup->addButton(d->widget.portrait, KoPageFormat::Portrait);
53 d->orientationGroup->addButton(d->widget.landscape, KoPageFormat::Landscape);
54
55 QButtonGroup *group2 = new QButtonGroup(this);
56 group2->addButton(d->widget.singleSided);
57 group2->addButton(d->widget.facingPages);
58 // the two sets of labels we use might have different lengths; make sure this does not create a 'jumping' ui
59 d->widget.facingPages->setChecked(true);
60 facingPagesChanged();
61 int width = qMax(d->widget.leftLabel->width(), d->widget.rightLabel->width());
62 d->widget.singleSided->setChecked(true);
63 facingPagesChanged();
64 width = qMax(width, qMax(d->widget.leftLabel->width(), d->widget.rightLabel->width()));
65 d->widget.leftLabel->setMinimumSize(QSize(width, 5));
66
67 d->widget.units->addItems(KoUnit::listOfUnitNameForUi(KoUnit::HidePixel));
68 d->widget.sizes->addItems(KoPageFormat::localizedPageFormatNames());
69 setPageSpread(false);
70
71 connect(d->widget.sizes, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &KoPageLayoutWidget::sizeChanged);
72 connect(d->widget.units, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &KoPageLayoutWidget::slotUnitChanged);
73 connect(group2, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &KoPageLayoutWidget::facingPagesChanged);
74 connect(d->orientationGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &KoPageLayoutWidget::orientationChanged);
75 connect(d->widget.width, &KoUnitDoubleSpinBox::valueChangedPt, this, &KoPageLayoutWidget::optionsChanged);
76 connect(d->widget.height, &KoUnitDoubleSpinBox::valueChangedPt, this, &KoPageLayoutWidget::optionsChanged);
77 connect(d->widget.topMargin, &KoUnitDoubleSpinBox::valueChangedPt, this, &KoPageLayoutWidget::marginsChanged);
78 connect(d->widget.bottomMargin, &KoUnitDoubleSpinBox::valueChangedPt, this, &KoPageLayoutWidget::marginsChanged);
79 connect(d->widget.bindingEdgeMargin, &KoUnitDoubleSpinBox::valueChangedPt, this, &KoPageLayoutWidget::marginsChanged);
80 connect(d->widget.pageEdgeMargin, &KoUnitDoubleSpinBox::valueChangedPt, this, &KoPageLayoutWidget::marginsChanged);
81 connect(d->widget.width, &KoUnitDoubleSpinBox::valueChangedPt, this, &KoPageLayoutWidget::optionsChanged);
82 connect(d->widget.height, &KoUnitDoubleSpinBox::valueChangedPt, this, &KoPageLayoutWidget::optionsChanged);
83
84 setUnit(KoUnit(KoUnit::Millimeter));
85 setPageLayout(layout);
86 if (layout.format == 0) // make sure we always call this during startup, even if the A3 (index=0) was chosen
87 sizeChanged(layout.format);
88
89 showTextDirection(false);
90 /* disable advanced page layout features by default */
91 d->widget.facingPageLabel->setVisible(false);
92 d->widget.facingPages->setVisible(false);
93 d->widget.singleSided->setVisible(false);
94 d->widget.stylesLabel->setVisible(false);
95 d->widget.pageStyle->setVisible(false);
96 }
97
~KoPageLayoutWidget()98 KoPageLayoutWidget::~KoPageLayoutWidget()
99 {
100 delete d;
101 }
102
pageLayout() const103 KoPageLayout KoPageLayoutWidget::pageLayout() const
104 {
105 return d->pageLayout;
106 }
107
sizeChanged(int row)108 void KoPageLayoutWidget::sizeChanged(int row)
109 {
110 if (row < 0) return;
111 if (! d->allowSignals) return;
112 d->allowSignals = false;
113 d->pageLayout.format = static_cast<KoPageFormat::Format> (row);
114 bool custom = d->pageLayout.format == KoPageFormat::CustomSize;
115 d->widget.width->setEnabled(custom);
116 d->widget.height->setEnabled(custom);
117
118 if (!custom) {
119 d->pageLayout.width = MM_TO_POINT(KoPageFormat::width(d->pageLayout.format, d->pageLayout.orientation));
120 d->pageLayout.height = MM_TO_POINT(KoPageFormat::height(d->pageLayout.format, d->pageLayout.orientation));
121 if (d->widget.facingPages->isChecked()) // is pagespread
122 d->pageLayout.width *= 2;
123 }
124
125 d->widget.width->changeValue(d->pageLayout.width);
126 d->widget.height->changeValue(d->pageLayout.height);
127
128 emit layoutChanged(d->pageLayout);
129 d->allowSignals = true;
130 }
131
slotUnitChanged(int row)132 void KoPageLayoutWidget::slotUnitChanged(int row)
133 {
134 setUnit(KoUnit::fromListForUi(row, KoUnit::HidePixel));
135 }
136
setUnit(const KoUnit & unit)137 void KoPageLayoutWidget::setUnit(const KoUnit &unit)
138 {
139 if (d->unit == unit)
140 return;
141 d->unit = unit;
142
143 d->widget.width->setUnit(unit);
144 d->widget.height->setUnit(unit);
145 d->widget.topMargin->setUnit(unit);
146 d->widget.bottomMargin->setUnit(unit);
147 d->widget.bindingEdgeMargin->setUnit(unit);
148 d->widget.pageEdgeMargin->setUnit(unit);
149 d->widget.units->setCurrentIndex(unit.indexInListForUi(KoUnit::HidePixel));
150
151 emit unitChanged(d->unit);
152 }
153
setPageLayout(const KoPageLayout & layout)154 void KoPageLayoutWidget::setPageLayout(const KoPageLayout &layout)
155 {
156 if (! d->allowSignals) return;
157 d->allowSignals = false;
158 d->pageLayout = layout;
159
160 Q_ASSERT(d->orientationGroup->button(layout.orientation));
161 d->orientationGroup->button(layout.orientation)->setChecked(true);
162 if (layout.bindingSide >= 0 && layout.pageEdge >= 0) {
163 d->widget.facingPages->setChecked(true);
164 d->widget.bindingEdgeMargin->changeValue(layout.bindingSide);
165 d->widget.pageEdgeMargin->changeValue(layout.pageEdge);
166 d->pageLayout.leftMargin = -1;
167 d->pageLayout.rightMargin = -1;
168 }
169 else {
170 d->widget.singleSided->setChecked(true);
171 d->widget.bindingEdgeMargin->changeValue(layout.leftMargin);
172 d->widget.pageEdgeMargin->changeValue(layout.rightMargin);
173 d->pageLayout.pageEdge = -1;
174 d->pageLayout.bindingSide = -1;
175 }
176 facingPagesChanged();
177
178 d->widget.topMargin->changeValue(layout.topMargin);
179 d->widget.bottomMargin->changeValue(layout.bottomMargin);
180 d->allowSignals = true;
181 d->widget.sizes->setCurrentIndex(layout.format); // calls sizeChanged()
182 }
183
facingPagesChanged()184 void KoPageLayoutWidget::facingPagesChanged()
185 {
186 if (! d->allowSignals) return;
187 d->allowSignals = false;
188 if (d->widget.singleSided->isChecked()) {
189 d->widget.leftLabel->setText(i18n("Left Edge:"));
190 d->widget.rightLabel->setText(i18n("Right Edge:"));
191 }
192 else {
193 d->widget.leftLabel->setText(i18n("Binding Edge:"));
194 d->widget.rightLabel->setText(i18n("Page Edge:"));
195 }
196 d->allowSignals = true;
197 marginsChanged();
198 sizeChanged(d->widget.sizes->currentIndex());
199 }
200
marginsChanged()201 void KoPageLayoutWidget::marginsChanged()
202 {
203 if (! d->allowSignals) return;
204 d->allowSignals = false;
205 d->pageLayout.leftMargin = -1;
206 d->pageLayout.rightMargin = -1;
207 d->pageLayout.bindingSide = -1;
208 d->pageLayout.pageEdge = -1;
209 d->pageLayout.topMargin = d->marginsEnabled?d->widget.topMargin->value():0;
210 d->pageLayout.bottomMargin = d->marginsEnabled?d->widget.bottomMargin->value():0;
211 qreal left = d->marginsEnabled?d->widget.bindingEdgeMargin->value():0;
212 qreal right = d->marginsEnabled?d->widget.pageEdgeMargin->value():0;
213 if (left + right > d->pageLayout.width - 10) {
214 // make sure the actual text area is never smaller than 10 points.
215 qreal diff = d->pageLayout.width - 10 - left - right;
216 left = qMin(d->pageLayout.width - 10, qMax(qreal(0.0), left - diff / qreal(2.0)));
217 right = qMax(qreal(0.0), right - d->pageLayout.width - 10 - left);
218 }
219
220 if (d->widget.singleSided->isChecked()) {
221 d->pageLayout.leftMargin = left;
222 d->pageLayout.rightMargin = right;
223 }
224 else {
225 d->pageLayout.bindingSide = left;
226 d->pageLayout.pageEdge = right;
227 }
228 // debugWidgets << " " << d->pageLayout.left <<"|"<< d->pageLayout.bindingSide << "," <<
229 // d->pageLayout.right << "|"<< d->pageLayout.pageEdge;
230 emit layoutChanged(d->pageLayout);
231 d->allowSignals = true;
232 }
233
setTextAreaAvailable(bool available)234 void KoPageLayoutWidget::setTextAreaAvailable(bool available)
235 {
236 d->marginsEnabled = available;
237 d->widget.margins->setEnabled(available);
238 marginsChanged();
239 }
240
optionsChanged()241 void KoPageLayoutWidget::optionsChanged()
242 {
243 if (! d->allowSignals) return;
244 if (d->widget.sizes->currentIndex() == KoPageFormat::CustomSize) {
245 d->pageLayout.width = d->widget.width->value();
246 d->pageLayout.height = d->widget.height->value();
247 } else
248 sizeChanged(d->widget.sizes->currentIndex());
249
250 marginsChanged();
251 }
252
orientationChanged()253 void KoPageLayoutWidget::orientationChanged()
254 {
255 if (! d->allowSignals) return;
256 d->allowSignals = false;
257 d->pageLayout.orientation = d->widget.landscape->isChecked() ? KoPageFormat::Landscape : KoPageFormat::Portrait;
258
259 qreal x = d->widget.height->value();
260 d->widget.height->changeValue(d->widget.width->value());
261 d->widget.width->changeValue(x);
262
263 d->allowSignals = true;
264 optionsChanged();
265 }
266
showUnitchooser(bool on)267 void KoPageLayoutWidget::showUnitchooser(bool on) {
268 d->widget.units->setVisible(on);
269 d->widget.unitsLabel->setVisible(on);
270 }
271
showPageSpread(bool on)272 void KoPageLayoutWidget::showPageSpread(bool on)
273 {
274 d->widget.facingPageLabel->setVisible(on);
275 d->widget.singleSided->setVisible(on);
276 d->widget.facingPages->setVisible(on);
277 }
278
setPageSpread(bool pageSpread)279 void KoPageLayoutWidget::setPageSpread(bool pageSpread)
280 {
281 if (pageSpread)
282 d->widget.facingPages->setChecked(true);
283 else
284 d->widget.singleSided->setChecked(true);
285 }
286
setApplyToDocument(bool apply)287 void KoPageLayoutWidget::setApplyToDocument(bool apply)
288 {
289 if (apply) {
290 d->widget.facingPageLabel->setText(i18n("Facing Pages:"));
291 d->widget.facingPages->setText(i18n("Facing pages"));
292 }
293 else {
294 d->widget.facingPageLabel->setText(i18n("Page Layout:"));
295 d->widget.facingPages->setText(i18n("Page spread"));
296 }
297 }
298
showTextDirection(bool on)299 void KoPageLayoutWidget::showTextDirection(bool on)
300 {
301 d->widget.directionLabel->setVisible(on);
302 d->widget.textDirection->setVisible(on);
303 }
304 /*
305 void KoPageLayoutWidget::setTextDirection(KoText::Direction direction)
306 {
307 int index = 0;
308 switch(direction) {
309 case KoText::LeftRightTopBottom:
310 index = 1;
311 break;
312 case KoText::RightLeftTopBottom:
313 index = 2;
314 break;
315 case KoText::TopBottomRightLeft: // unused for now.
316 case KoText::InheritDirection:
317 case KoText::AutoDirection:
318 index = 0;
319 case KoText::TopBottomLeftRight:
320 ; // unhandled, because it actually doesn't exist in real-world writing systems.
321 // Boustrophedon would be interesting to implement, though
322 }
323 d->widget.textDirection->setCurrentIndex(index);
324 }
325
326 KoText::Direction KoPageLayoutWidget::textDirection() const
327 {
328 switch(d->widget.textDirection->currentIndex()) {
329 case 1: return KoText::LeftRightTopBottom;
330 case 2: return KoText::RightLeftTopBottom;
331 default:
332 case 0: return KoText::AutoDirection;
333 }
334 }
335 */
showPageStyles(bool on)336 void KoPageLayoutWidget::showPageStyles(bool on)
337 {
338 d->widget.stylesLabel->setVisible(on);
339 d->widget.pageStyle->setVisible(on);
340 }
341
setPageStyles(const QStringList & styles)342 void KoPageLayoutWidget::setPageStyles(const QStringList &styles)
343 {
344 d->widget.pageStyle->clear();
345 d->widget.pageStyle->addItems(styles);
346 }
347
currentPageStyle() const348 QString KoPageLayoutWidget::currentPageStyle() const
349 {
350 return d->widget.pageStyle->currentText();
351 }
352