1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7
8 #include "propertywidget_distance.h"
9
10 #include <QSignalBlocker>
11
12 #include "appmodehelper.h"
13 #include "appmodes.h"
14 #include "localemgr.h"
15 #include "pageitem_table.h"
16 #include "pageitem_textframe.h"
17 #include "scribus.h"
18 #include "scribusapp.h"
19 #include "scribusdoc.h"
20 #include "selection.h"
21 #include "tabmanager.h"
22
PropertyWidget_Distance(QWidget * parent)23 PropertyWidget_Distance::PropertyWidget_Distance(QWidget* parent) : QFrame(parent)
24 {
25 setupUi(this);
26
27 layout()->setAlignment(Qt::AlignTop);
28
29 columnsLabel->setBuddy(columns);
30 columnGap->setValues(0, 300, 2, 0);
31
32 topDistance->setValues(0, 300, 2, 0);
33 topLabel->setBuddy(topDistance);
34
35 bottomDistance->setValues(0, 300, 2, 0);
36 bottomLabel->setBuddy(bottomDistance);
37
38 leftDistance->setValues(0, 300, 2, 0);
39 leftLabel->setBuddy(leftDistance);
40
41 rightDistance->setValues(0, 300, 2, 0);
42 rightLabel->setBuddy(rightDistance);
43
44 columns->setDecimals(0);
45 columns->setSuffix("");
46
47 languageChange();
48
49 columnGapLabel->setCurrentIndex(0);
50
51 connect(ScQApp, SIGNAL(localeChanged()), this, SLOT(localeChange()));
52 }
53
setMainWindow(ScribusMainWindow * mw)54 void PropertyWidget_Distance::setMainWindow(ScribusMainWindow* mw)
55 {
56 m_ScMW = mw;
57
58 connect(m_ScMW->appModeHelper, SIGNAL(AppModeChanged(int, int)), this, SLOT(handleAppModeChanged(int, int)));
59 connect(m_ScMW, SIGNAL(UpdateRequest(int)) , this, SLOT(handleUpdateRequest(int)));
60 }
61
setDoc(ScribusDoc * d)62 void PropertyWidget_Distance::setDoc(ScribusDoc *d)
63 {
64 if(d == (ScribusDoc*) m_doc)
65 return;
66
67 if (m_doc)
68 {
69 disconnect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(handleSelectionChanged()));
70 disconnect(m_doc , SIGNAL(docChanged()) , this, SLOT(handleSelectionChanged()));
71 }
72
73 m_doc = d;
74 m_item = nullptr;
75
76 if (m_doc.isNull())
77 {
78 disconnectSignals();
79 return;
80 }
81
82 m_unitRatio = m_doc->unitRatio();
83 m_unitIndex = m_doc->unitIndex();
84
85 columns->setDecimals(0);
86 columnGap->setDecimals(2);
87 topDistance->setDecimals(2);
88 leftDistance->setDecimals(2);
89 bottomDistance->setDecimals(2);
90 rightDistance->setDecimals(2);
91
92 connect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(handleSelectionChanged()));
93 connect(m_doc , SIGNAL(docChanged()) , this, SLOT(handleSelectionChanged()));
94 }
95
setCurrentItem(PageItem * item)96 void PropertyWidget_Distance::setCurrentItem(PageItem *item)
97 {
98 if (!m_ScMW || m_ScMW->scriptIsRunning())
99 return;
100 //CB We shouldn't really need to process this if our item is the same one
101 //maybe we do if the item has been changed by scripter.. but that should probably
102 //set some status if so.
103 //FIXME: This won't work until when a canvas deselect happens, m_item must be nullptr.
104 //if (m_item == i)
105 // return;
106
107 if (item && m_doc.isNull())
108 setDoc(item->doc());
109
110 m_item = item;
111
112 disconnectSignals();
113 configureWidgets();
114
115 if (!m_item) return;
116
117 PageItem_TextFrame *textItem = m_item->asTextFrame();
118 if (m_doc->appMode == modeEditTable)
119 textItem = m_item->asTable()->activeCell().textFrame();
120 if (!textItem) return;
121
122 //#14427: columns->setMaximum(qMax(qRound(textItem->width() / qMax(textItem->ColGap, 10.0)), 1));
123 columns->setMinimum(1);
124 columns->setValue(textItem->m_columns);
125 columnGap->setMinimum(0);
126 if (columnGapLabel->currentIndex() == 0)
127 {
128 columnGap->setMaximum(qMax((textItem->width() / textItem->m_columns - textItem->textToFrameDistLeft() - textItem->textToFrameDistRight()) * m_unitRatio, 0.0));
129 columnGap->setValue(textItem->m_columnGap * m_unitRatio);
130 }
131 else
132 {
133 columnGap->setMaximum(qMax((textItem->width() / textItem->m_columns) * m_unitRatio, 0.0));
134 columnGap->setValue(textItem->columnWidth() * m_unitRatio);
135 }
136 leftDistance->setValue(textItem->textToFrameDistLeft()*m_unitRatio);
137 topDistance->setValue(textItem->textToFrameDistTop()*m_unitRatio);
138 bottomDistance->setValue(textItem->textToFrameDistBottom()*m_unitRatio);
139 rightDistance->setValue(textItem->textToFrameDistRight()*m_unitRatio);
140 if (columns->value() == 1)
141 {
142 columnGap->setEnabled(false);
143 columnGapLabel->setEnabled(false);
144 }
145 else
146 {
147 columnGap->setEnabled(true);
148 columnGapLabel->setEnabled(true);
149 }
150
151 showTextDistances(textItem->textToFrameDistLeft(), textItem->textToFrameDistTop(), textItem->textToFrameDistBottom(), textItem->textToFrameDistRight());
152 verticalAlign->setCurrentIndex(textItem->verticalAlignment());
153 connectSignals();
154 }
155
connectSignals()156 void PropertyWidget_Distance::connectSignals()
157 {
158 connect(columns , SIGNAL(valueChanged(double)) , this, SLOT(handleColumns()), Qt::UniqueConnection);
159 connect(columnGap , SIGNAL(valueChanged(double)), this, SLOT(handleColumnGap()), Qt::UniqueConnection);
160 connect(columnGapLabel, SIGNAL(activated(int)) , this, SLOT(handleGapSwitch()), Qt::UniqueConnection);
161 connect(topDistance , SIGNAL(valueChanged(double)), this, SLOT(handleTextDistances()), Qt::UniqueConnection);
162 connect(leftDistance , SIGNAL(valueChanged(double)), this, SLOT(handleTextDistances()), Qt::UniqueConnection);
163 connect(rightDistance , SIGNAL(valueChanged(double)), this, SLOT(handleTextDistances()), Qt::UniqueConnection);
164 connect(bottomDistance, SIGNAL(valueChanged(double)), this, SLOT(handleTextDistances()), Qt::UniqueConnection);
165 connect(tabsButton , SIGNAL(clicked()) , this, SLOT(handleTabs()), Qt::UniqueConnection);
166 connect(verticalAlign , SIGNAL(activated(int)) , this, SLOT(handleVAlign()), Qt::UniqueConnection);
167 }
168
disconnectSignals()169 void PropertyWidget_Distance::disconnectSignals()
170 {
171 disconnect(columns , SIGNAL(valueChanged(double)) , this, SLOT(handleColumns()));
172 disconnect(columnGap , SIGNAL(valueChanged(double)), this, SLOT(handleColumnGap()));
173 disconnect(columnGapLabel, SIGNAL(activated(int)) , this, SLOT(handleGapSwitch()));
174 disconnect(topDistance , SIGNAL(valueChanged(double)), this, SLOT(handleTextDistances()));
175 disconnect(leftDistance , SIGNAL(valueChanged(double)), this, SLOT(handleTextDistances()));
176 disconnect(rightDistance , SIGNAL(valueChanged(double)), this, SLOT(handleTextDistances()));
177 disconnect(bottomDistance, SIGNAL(valueChanged(double)), this, SLOT(handleTextDistances()));
178 disconnect(tabsButton , SIGNAL(clicked()) , this, SLOT(handleTabs()));
179 disconnect(verticalAlign , SIGNAL(activated(int)) , this, SLOT(handleVAlign()));
180 }
181
configureWidgets()182 void PropertyWidget_Distance::configureWidgets()
183 {
184 bool enabled = false;
185 if (m_item && m_doc)
186 {
187 PageItem_TextFrame *textItem = m_item->asTextFrame();
188 if (m_doc->appMode == modeEditTable)
189 textItem = m_item->asTable()->activeCell().textFrame();
190
191 enabled = (textItem != nullptr);
192 enabled &= (m_doc->m_Selection->count() == 1);
193
194 if (textItem)
195 {
196 int numCols = textItem->m_columns;
197
198 columnGap->setEnabled(numCols != 1);
199 columnGapLabel->setEnabled(numCols != 1);
200 }
201 }
202 setEnabled(enabled);
203 }
204
handleAppModeChanged(int oldMode,int mode)205 void PropertyWidget_Distance::handleAppModeChanged(int oldMode, int mode)
206 {
207 if (oldMode == modeEditTable || mode == modeEditTable)
208 {
209 setCurrentItem(m_item);
210 }
211 }
212
handleSelectionChanged()213 void PropertyWidget_Distance::handleSelectionChanged()
214 {
215 if (!m_doc || !m_ScMW || m_ScMW->scriptIsRunning())
216 return;
217
218 PageItem* currItem = currentItemFromSelection();
219 setCurrentItem(currItem);
220 updateGeometry();
221 }
222
handleUpdateRequest(int)223 void PropertyWidget_Distance::handleUpdateRequest(int /*updateFlags*/)
224 {
225 // Nothing to do in this widget
226 }
227
showColumns(int r,double g)228 void PropertyWidget_Distance::showColumns(int r, double g)
229 {
230 if (!m_ScMW || m_ScMW->scriptIsRunning())
231 return;
232
233 bool cSigWasBlocked = columns->blockSignals(true);
234 bool cGapSigWasBlocked = columnGap->blockSignals(true);
235
236 columns->setValue(r);
237 columnGap->setValue(g * m_unitRatio);
238 if (m_item)
239 {
240 PageItem_TextFrame *textItem = m_item->asTextFrame();
241 if (m_doc->appMode == modeEditTable)
242 textItem = m_item->asTable()->activeCell().textFrame();
243
244 if (textItem != nullptr)
245 {
246 //#14427: columns->setMaximum(qMax(qRound(textItem->width() / qMax(textItem->ColGap, 10.0)), 1));
247 if (columnGapLabel->currentIndex() == 0)
248 {
249 columnGap->setMaximum(qMax((textItem->width() / textItem->m_columns - textItem->textToFrameDistLeft() - textItem->textToFrameDistRight()) * m_unitRatio, 0.0));
250 columnGap->setValue(textItem->m_columnGap * m_unitRatio);
251 }
252 else
253 {
254 columnGap->setMaximum(qMax((textItem->width() / textItem->m_columns) * m_unitRatio, 0.0));
255 columnGap->setValue(textItem->columnWidth() * m_unitRatio);
256 }
257 }
258 }
259 columns->setMinimum(1);
260 columnGap->setMinimum(0);
261 columnGap->setEnabled(columns->value() != 1);
262 columnGapLabel->setEnabled(columns->value() != 1);
263
264 columns->blockSignals(cSigWasBlocked);
265 columnGap->blockSignals(cGapSigWasBlocked);
266 }
267
showTextDistances(double left,double top,double bottom,double right)268 void PropertyWidget_Distance::showTextDistances(double left, double top, double bottom, double right)
269 {
270 leftDistance->showValue(left * m_unitRatio);
271 topDistance->showValue(top * m_unitRatio);
272 bottomDistance->showValue(bottom * m_unitRatio);
273 rightDistance->showValue(right * m_unitRatio);
274 }
275
handleColumns()276 void PropertyWidget_Distance::handleColumns()
277 {
278 if (!m_doc || !m_item || !m_ScMW || m_ScMW->scriptIsRunning())
279 return;
280
281 PageItem *textItem = m_item;
282 if (m_doc->appMode == modeEditTable)
283 textItem = m_item->asTable()->activeCell().textFrame();
284
285 if (textItem)
286 {
287 textItem->setColumns(static_cast<int>(columns->value()));
288 showColumns(textItem->m_columns, textItem->m_columnGap);
289 //this is already done in showColumns()
290 /*if (static_cast<int>(columns->value()) == 1)
291 {
292 columnGap->setEnabled(false);
293 columnGapLabel->setEnabled(false);
294 }
295 else
296 {
297 columnGap->setEnabled(true);
298 columnGapLabel->setEnabled(true);
299 }*/
300 textItem->update();
301 if (m_doc->appMode == modeEditTable)
302 m_item->asTable()->update();
303 m_doc->regionsChanged()->update(QRect());
304 }
305 }
306
handleColumnGap()307 void PropertyWidget_Distance::handleColumnGap()
308 {
309 if (!m_doc || !m_item || !m_ScMW || m_ScMW->scriptIsRunning())
310 return;
311
312 PageItem *textItem = m_item;
313 if (m_doc->appMode == modeEditTable)
314 textItem = m_item->asTable()->activeCell().textFrame();
315 if (!textItem)
316 return;
317
318 if (columnGapLabel->currentIndex() == 0)
319 textItem->setColumnGap(columnGap->value() / m_unitRatio);
320 else
321 {
322 double lineCorr=0.0;
323 if ((textItem->lineColor() != CommonStrings::None) || (!textItem->strokePattern().isEmpty()))
324 lineCorr = textItem->lineWidth();
325 double newWidth = columnGap->value() / m_unitRatio;
326 double newGap = qMax(((textItem->width() - textItem->textToFrameDistLeft() - textItem->textToFrameDistRight() - lineCorr) - (newWidth * textItem->m_columns)) / (textItem->m_columns - 1), 0.0);
327 textItem->setColumnGap(newGap);
328 }
329 textItem->update();
330 if (m_doc->appMode == modeEditTable)
331 m_item->asTable()->update();
332 m_doc->regionsChanged()->update(QRect());
333 }
334
handleGapSwitch()335 void PropertyWidget_Distance::handleGapSwitch()
336 {
337 if (!m_doc || !m_item || !m_ScMW || m_ScMW->scriptIsRunning())
338 return;
339 PageItem *textItem = m_item;
340 if (m_doc->appMode == modeEditTable)
341 textItem = m_item->asTable()->activeCell().textFrame();
342 if (textItem != nullptr)
343 showColumns(textItem->m_columns, textItem->m_columnGap);
344
345 int index = columnGapLabel->currentIndex();
346 columnGap->setToolTip((index == 0) ? tr( "Distance between columns" ) : tr( "Column width" ));
347 }
348
handleVAlign()349 void PropertyWidget_Distance::handleVAlign()
350 {
351 if (!m_doc || !m_item || !m_ScMW || m_ScMW->scriptIsRunning())
352 return;
353 PageItem *textItem = m_item;
354 if (m_doc->appMode == modeEditTable)
355 textItem = m_item->asTable()->activeCell().textFrame();
356 if (textItem != nullptr)
357 {
358 textItem->setVerticalAlignment(verticalAlign->currentIndex());
359 textItem->update();
360 if (m_doc->appMode == modeEditTable)
361 m_item->asTable()->update();
362 m_doc->regionsChanged()->update(QRect());
363 }
364 }
365
handleTabs()366 void PropertyWidget_Distance::handleTabs()
367 {
368 if (!m_doc || !m_item)
369 return;
370
371 PageItem_TextFrame *tItem = m_item->asTextFrame();
372 if (tItem == nullptr)
373 return;
374 const ParagraphStyle& style(m_doc->appMode == modeEdit ? tItem->currentStyle() : tItem->itemText.defaultStyle());
375 TabManager *dia = new TabManager(this, m_doc->unitIndex(), style.tabValues(), tItem->columnWidth());
376 if (dia->exec())
377 {
378 if (m_doc->appMode != modeEdit)
379 {
380 ParagraphStyle newStyle(m_item->itemText.defaultStyle());
381 newStyle.setTabValues(dia->tabList());
382 Selection tempSelection(this, false);
383 tempSelection.addItem(m_item, true);
384 m_doc->itemSelection_ApplyParagraphStyle(newStyle, &tempSelection);
385 }
386 else
387 {
388 ParagraphStyle newStyle;
389 newStyle.setTabValues(dia->tabList());
390 m_doc->itemSelection_ApplyParagraphStyle(newStyle);
391 }
392 m_item->update();
393 }
394 delete dia;
395 }
396
handleTextDistances()397 void PropertyWidget_Distance::handleTextDistances()
398 {
399 if (!m_doc || !m_item || !m_ScMW || m_ScMW->scriptIsRunning())
400 return;
401
402 PageItem *textItem = m_item;
403 if (m_doc->appMode == modeEditTable)
404 textItem = m_item->asTable()->activeCell().textFrame();
405 if (!textItem) return;
406
407 double left = leftDistance->value() / m_unitRatio;
408 double right = rightDistance->value() / m_unitRatio;
409 double top = topDistance->value() / m_unitRatio;
410 double bottom = bottomDistance->value() / m_unitRatio;
411 textItem->setTextToFrameDist(left, right, top, bottom);
412 showColumns(textItem->m_columns, textItem->m_columnGap);
413
414 textItem->update();
415 if (m_doc->appMode == modeEditTable)
416 m_item->asTable()->update();
417 m_doc->regionsChanged()->update(QRect());
418 }
419
changeEvent(QEvent * e)420 void PropertyWidget_Distance::changeEvent(QEvent *e)
421 {
422 if (e->type() == QEvent::LanguageChange)
423 {
424 languageChange();
425 return;
426 }
427 QWidget::changeEvent(e);
428 }
429
languageChange()430 void PropertyWidget_Distance::languageChange()
431 {
432 retranslateUi(this);
433
434 QSignalBlocker verticalAlignBlocker(verticalAlign);
435 int oldAlignIndex = verticalAlign->currentIndex();
436 verticalAlign->clear();
437 verticalAlign->addItem( tr("Top"));
438 verticalAlign->addItem( tr("Middle"));
439 verticalAlign->addItem( tr("Bottom"));
440 verticalAlign->setCurrentIndex(oldAlignIndex);
441
442 QSignalBlocker columnGapLabelBlocker(columnGapLabel);
443 int oldColGapLabel = columnGapLabel->currentIndex();
444 columnGapLabel->clear();
445 columnGapLabel->addItem( tr("Gap:"));
446 columnGapLabel->addItem( tr("Width:"));
447 columnGapLabel->setCurrentIndex(oldColGapLabel);
448
449 QString ptSuffix = tr(" pt");
450
451 QString suffix = (m_doc) ? unitGetSuffixFromIndex(m_doc->unitIndex()) : ptSuffix;
452
453 columnGap->setSuffix(suffix);
454 leftDistance->setSuffix(suffix);
455 topDistance->setSuffix(suffix);
456 bottomDistance->setSuffix(suffix);
457 rightDistance->setSuffix(suffix);
458 }
459
unitChange()460 void PropertyWidget_Distance::unitChange()
461 {
462 if (!m_doc)
463 return;
464
465 QSignalBlocker columnGapBlocker(columnGap);
466 QSignalBlocker leftDistanceBlocker(leftDistance);
467 QSignalBlocker topDistanceBlocker(topDistance);
468 QSignalBlocker bottomDistanceBlocker(bottomDistance);
469 QSignalBlocker rightDistanceBlocker(rightDistance);
470
471 m_unitRatio = m_doc->unitRatio();
472 m_unitIndex = m_doc->unitIndex();
473
474 columnGap->setNewUnit(m_unitIndex);
475 leftDistance->setNewUnit(m_unitIndex);
476 topDistance->setNewUnit(m_unitIndex);
477 bottomDistance->setNewUnit(m_unitIndex);
478 rightDistance->setNewUnit(m_unitIndex);
479 }
480
localeChange()481 void PropertyWidget_Distance::localeChange()
482 {
483 const QLocale& l(LocaleManager::instance().userPreferredLocale());
484 columnGap->setLocale(l);
485 topDistance->setLocale(l);
486 bottomDistance->setLocale(l);
487 leftDistance->setLocale(l);
488 rightDistance->setLocale(l);
489 }
490