1 /*
2 Copyright (C) 2011 Elvis Stansvik <elvstone@gmail.com>
3
4 For general Scribus (>=1.3.2) copyright and licensing information please refer
5 to the COPYING file provided with the program. Following this notice may exist
6 a copyright and/or license notice that predates the release of Scribus 1.3.2
7 for which a new license (GPL+exception) is in place.
8 */
9 #include <QColor>
10 #include <QListWidget>
11 #include <QListWidgetItem>
12 #include <QWidget>
13
14 #include "appmodehelper.h"
15 #include "appmodes.h"
16 #include "colorcombo.h"
17 #include "commonstrings.h"
18 #include "iconmanager.h"
19 #include "pageitem_table.h"
20 #include "propertiespalette_table.h"
21 #include "sccolorengine.h"
22 #include "scribus.h"
23 #include "scribusapp.h"
24 #include "selection.h"
25 #include "tableborder.h"
26 #include "tablesideselector.h"
27 #include "util.h"
28 #include "util_color.h"
29
30
31
PropertiesPalette_Table(QWidget * parent)32 PropertiesPalette_Table::PropertiesPalette_Table(QWidget* parent) : QWidget(parent)
33 {
34 setupUi(this);
35 setSizePolicy( QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
36
37 iconSetChange();
38 labelTable->setBuddy(tableStyleCombo);
39 labelCells->setBuddy(cellStyleCombo);
40
41 connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
42
43 connect(tableStyleCombo, SIGNAL(newStyle(const QString&)), this, SLOT(setTableStyle(const QString&)));
44 connect(cellStyleCombo, SIGNAL(newStyle(const QString&)), this, SLOT(setCellStyle(const QString&)));
45 }
46
iconSetChange()47 void PropertiesPalette_Table::iconSetChange()
48 {
49 IconManager& iconManager = IconManager::instance();
50
51 addBorderLineButton->setIcon(iconManager.loadIcon("penciladd.png"));
52 removeBorderLineButton->setIcon(iconManager.loadIcon("pencilsub.png"));
53 buttonClearTableStyle->setIcon(iconManager.loadIcon("16/edit-clear.png"));
54 buttonClearCellStyle->setIcon(iconManager.loadIcon("16/edit-clear.png"));
55 }
56
handleUpdateRequest(int updateFlags)57 void PropertiesPalette_Table::handleUpdateRequest(int updateFlags)
58 {
59 if (updateFlags & reqColorsUpdate)
60 updateColorList();
61 tableStyleCombo->updateStyleList();
62 cellStyleCombo->updateStyleList();
63 }
64
updateColorList()65 void PropertiesPalette_Table::updateColorList()
66 {
67 if (!m_doc)
68 return;
69
70 borderLineColor->setColors(m_doc->PageColors, true);
71 fillColor->setColors(m_doc->PageColors, true);
72 }
73
setMainWindow(ScribusMainWindow * mainWindow)74 void PropertiesPalette_Table::setMainWindow(ScribusMainWindow* mainWindow)
75 {
76 m_mainWindow = mainWindow;
77
78 connect(m_mainWindow, SIGNAL(UpdateRequest(int)), SLOT(handleUpdateRequest(int)));
79 connect(m_mainWindow->appModeHelper, SIGNAL(AppModeChanged(int,int)), this, SLOT(updateFillControls()));
80 connect(m_mainWindow->appModeHelper, SIGNAL(AppModeChanged(int,int)), this, SLOT(updateStyleControls()));
81 }
82
setDocument(ScribusDoc * doc)83 void PropertiesPalette_Table::setDocument(ScribusDoc *doc)
84 {
85 if (m_doc)
86 {
87 disconnect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(handleSelectionChanged()));
88 disconnect(m_doc , SIGNAL(docChanged()) , this, SLOT(handleSelectionChanged()));
89 }
90
91 m_doc = doc;
92
93 tableStyleCombo->setDoc(m_doc);
94 cellStyleCombo->setDoc(m_doc);
95
96 connect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(handleSelectionChanged()));
97 connect(m_doc , SIGNAL(docChanged()) , this, SLOT(handleSelectionChanged()));
98 }
99
unsetDocument()100 void PropertiesPalette_Table::unsetDocument()
101 {
102 if (m_doc)
103 {
104 disconnect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(handleSelectionChanged()));
105 disconnect(m_doc , SIGNAL(docChanged()) , this, SLOT(handleSelectionChanged()));
106 }
107
108 m_doc = nullptr;
109
110 tableStyleCombo->setDoc(m_doc);
111 cellStyleCombo->setDoc(m_doc);
112 }
113
setItem(PageItem * item)114 void PropertiesPalette_Table::setItem(PageItem* item)
115 {
116 m_item = item;
117 if (item->isTable())
118 connect(m_item->asTable(), SIGNAL(selectionChanged()), this, SLOT(handleCellSelectionChanged()), Qt::UniqueConnection);
119 }
120
unsetItem()121 void PropertiesPalette_Table::unsetItem()
122 {
123 disconnect(this, SLOT(handleCellSelectionChanged()));
124
125 // if ((m_item) && (m_item->isTable()))
126 // disconnect(m_item->asTable(), SIGNAL(selectionChanged()), this, SLOT(handleCellSelectionChanged()));
127 m_item = nullptr;
128 }
129
handleSelectionChanged()130 void PropertiesPalette_Table::handleSelectionChanged()
131 {
132 if (!m_doc)
133 return;
134
135 // We only handle a single item for now.
136 if (m_doc->m_Selection->count() >= 1 && m_doc->m_Selection->itemAt(0)->isTable())
137 m_item = m_doc->m_Selection->itemAt(0);
138 else
139 m_item = nullptr;
140
141 // HACK: Guard against "false" re-selections resulting from m_item->update().
142 if (m_item == m_previousItem)
143 return;
144 m_previousItem = m_item;
145
146 sideSelector->setSelection(TableSideSelector::All);
147
148 updateFillControls();
149 updateStyleControls();
150 }
151
handleCellSelectionChanged()152 void PropertiesPalette_Table::handleCellSelectionChanged()
153 {
154 if (!m_doc)
155 return;
156 if (!m_item)
157 return;
158 updateFillControls();
159 updateStyleControls();
160 on_sideSelector_selectionChanged();
161 }
162
showTableStyle(const QString & name)163 void PropertiesPalette_Table::showTableStyle(const QString& name)
164 {
165 bool blocked = tableStyleCombo->blockSignals(true);
166 tableStyleCombo->setStyle(name);
167 tableStyleCombo->blockSignals(blocked);
168 }
169
showCellStyle(const QString & name)170 void PropertiesPalette_Table::showCellStyle(const QString& name)
171 {
172 bool blocked = cellStyleCombo->blockSignals(true);
173 cellStyleCombo->setStyle(name);
174 cellStyleCombo->blockSignals(blocked);
175 }
176
updateStyleControls()177 void PropertiesPalette_Table::updateStyleControls()
178 {
179 if (m_item && m_item->isTable())
180 {
181 PageItem_Table* table = m_item->asTable();
182 tableStyleCombo->setEnabled(true);
183 cellStyleCombo->setEnabled(true);
184 buttonClearTableStyle->setEnabled(true);
185 buttonClearCellStyle->setEnabled(true);
186 // Fill in values.
187 if (m_doc->appMode != modeEditTable)
188 {
189 showTableStyle(table->styleName());
190 cellStyleCombo->setEnabled(false);
191 buttonClearCellStyle->setEnabled(false);
192 }
193 else
194 {
195 // showTableStyle(table->style());
196 showCellStyle(table->activeCell().styleName());
197 }
198 }
199 else
200 {
201 tableStyleCombo->setEnabled(false);
202 cellStyleCombo->setEnabled(false);
203 buttonClearTableStyle->setEnabled(false);
204 buttonClearCellStyle->setEnabled(false);
205 }
206 }
207
setTableStyle(const QString & name)208 void PropertiesPalette_Table::setTableStyle(const QString &name)
209 {
210 if (!m_item || !m_item->isTable())
211 return;
212 m_item->asTable()->setStyle(name);
213 m_item->asTable()->update();
214 showTableStyle(name);
215 }
216
setCellStyle(const QString & name)217 void PropertiesPalette_Table::setCellStyle(const QString &name)
218 {
219 if (!m_item || !m_item->isTable())
220 return;
221 m_doc->dontResize = true;
222 m_item->asTable()->activeCell().setStyle(name);
223 m_doc->dontResize = true;
224 m_item->asTable()->update();
225 showCellStyle(name);
226 }
227
on_sideSelector_selectionChanged()228 void PropertiesPalette_Table::on_sideSelector_selectionChanged()
229 {
230 if (!m_item || !m_item->isTable())
231 return;
232
233 /*
234 * Figure out the selection state. Either
235 *
236 * 1) Some sides are selected and they all have the same border, or
237 * 2) Some sides are selected but they have different borders, or
238 * 3) No sides are selected.
239 */
240 State borderState = Unset;
241 m_currentBorder = TableBorder();
242 TableSideSelector::Sides selectedSides = sideSelector->selection();
243 PageItem_Table* table = m_item->asTable();
244 bool tableEditMode = (m_doc->appMode == modeEditTable);
245
246 if (selectedSides & TableSideSelector::Left)
247 {
248 TableBorder leftBorder = tableEditMode ? table->activeCell().leftBorder() : table->leftBorder();
249 if (borderState == Unset && !leftBorder.isNull())
250 {
251 m_currentBorder = leftBorder;
252 borderState = Set;
253 }
254 else if (m_currentBorder != leftBorder)
255 borderState = TriState;
256 }
257
258 if (selectedSides & TableSideSelector::Right)
259 {
260 TableBorder rightBorder = tableEditMode ? table->activeCell().rightBorder() : table->rightBorder();
261 if (borderState == Unset && !rightBorder.isNull())
262 {
263 m_currentBorder = rightBorder;
264 borderState = Set;
265 }
266 else if (m_currentBorder != rightBorder)
267 borderState = TriState;
268 }
269
270 if (selectedSides & TableSideSelector::Top)
271 {
272 TableBorder topBorder = tableEditMode ? table->activeCell().topBorder() : table->topBorder();
273 if (borderState == Unset && !table->topBorder().isNull())
274 {
275 m_currentBorder = topBorder;
276 borderState = Set;
277 }
278 else if (m_currentBorder != topBorder)
279 borderState = TriState;
280 }
281
282 if (selectedSides & TableSideSelector::Bottom)
283 {
284 TableBorder bottomBorder = tableEditMode ? table->activeCell().bottomBorder() : table->bottomBorder();
285 if (borderState == Unset && !bottomBorder.isNull())
286 {
287 m_currentBorder = bottomBorder;
288 borderState = Set;
289 }
290 else if (m_currentBorder != bottomBorder)
291 borderState = TriState;
292 }
293
294 if (borderState == Set)
295 {
296 /// Some sides selected and they have same border.
297 addBorderLineButton->setEnabled(true);
298 removeBorderLineButton->setEnabled(true);
299 borderLineList->setEnabled(true);
300 }
301 else if (borderState == TriState)
302 {
303 /// Some sides selected but they have different border.
304 m_currentBorder = TableBorder();
305 addBorderLineButton->setEnabled(true);
306 removeBorderLineButton->setEnabled(true);
307 borderLineList->setEnabled(true);
308 }
309 else
310 {
311 /// No sides selected.
312 m_currentBorder = TableBorder();
313 addBorderLineButton->setEnabled(false);
314 removeBorderLineButton->setEnabled(false);
315 borderLineList->setEnabled(false);
316 }
317
318 updateBorderLineList();
319 }
320
updateBorderLineList()321 void PropertiesPalette_Table::updateBorderLineList()
322 {
323 borderLineList->clear();
324 for (const TableBorderLine& borderLine : m_currentBorder.borderLines())
325 {
326 QString text = QString(" %1%2 %3").arg(borderLine.width()).arg(borderLineWidth->suffix(), CommonStrings::translatePenStyleName(borderLine.style()));
327 if (borderLine.color() != CommonStrings::None)
328 {
329 QPixmap *icon = getWidePixmap(getColor(borderLine.color(), borderLine.shade()));
330 borderLineList->addItem(new QListWidgetItem(*icon, text, borderLineList));
331 }
332 else
333 borderLineList->addItem(new QListWidgetItem(text, borderLineList));
334 }
335 removeBorderLineButton->setEnabled(borderLineList->count() > 1);
336 }
337
updateBorderLineList(const TableBorderLine & current)338 void PropertiesPalette_Table::updateBorderLineList(const TableBorderLine& current)
339 {
340 updateBorderLineList();
341
342 const QList<TableBorderLine>& borderLines = m_currentBorder.borderLines();
343 for (int i = 0; i < borderLines.count(); ++i)
344 {
345 const TableBorderLine& borderLine = borderLines.at(i);
346 if (borderLine == current)
347 {
348 borderLineList->setCurrentRow(i);
349 break;
350 }
351 }
352 }
353
updateBorderLineListItem()354 void PropertiesPalette_Table::updateBorderLineListItem()
355 {
356 QListWidgetItem* item = borderLineList->currentItem();
357 QString text = QString(" %1%2 %3").arg(borderLineWidth->getValue()).arg(borderLineWidth->suffix(), CommonStrings::translatePenStyleName(static_cast<Qt::PenStyle>(borderLineStyle->currentIndex() + 1)));
358 if (borderLineColor->currentColor() != CommonStrings::None)
359 {
360 QPixmap *icon = getWidePixmap(getColor(borderLineColor->currentColor(), borderLineShade->value()));
361 item->setIcon(*icon);
362 }
363 item->setText(text);
364 }
365
updateFillControls()366 void PropertiesPalette_Table::updateFillControls()
367 {
368 if (m_item && m_item->isTable())
369 {
370 PageItem_Table* table = m_item->asTable();
371 // Enable fill editing controls.
372 fillColor->setEnabled(true);
373 fillColorLabel->setEnabled(true);
374 fillShade->setEnabled(true);
375 fillShadeLabel->setEnabled(true);
376 // Fill in values.
377 if (m_doc->appMode != modeEditTable)
378 {
379 QString color = table->fillColor();
380 if (color == CommonStrings::None)
381 color = CommonStrings::tr_NoneColor;
382 setCurrentComboItem(fillColor, color);
383 bool sigBlocked = fillShade->blockSignals(true);
384 fillShade->setValue(table->fillShade());
385 fillShade->blockSignals(sigBlocked);
386 }
387 else
388 {
389 TableCell cell = table->activeCell();
390 QString color = cell.fillColor();
391 if (color == CommonStrings::None)
392 color = CommonStrings::tr_NoneColor;
393 setCurrentComboItem(fillColor, color);
394 bool sigBlocked = fillShade->blockSignals(true);
395 fillShade->setValue(cell.fillShade());
396 fillShade->blockSignals(sigBlocked);
397 }
398 }
399 else
400 {
401 // Disable fill editing controls.
402 fillColor->setEnabled(false);
403 fillColorLabel->setEnabled(false);
404 fillShade->setEnabled(false);
405 fillShadeLabel->setEnabled(false);
406 }
407 }
408
getColor(const QString & colorName,int shade) const409 QColor PropertiesPalette_Table::getColor(const QString& colorName, int shade) const
410 {
411 if (!m_doc)
412 return QColor();
413
414 return ScColorEngine::getDisplayColor(m_doc->PageColors[colorName], m_doc, shade);
415 }
416
on_borderLineList_currentRowChanged(int row)417 void PropertiesPalette_Table::on_borderLineList_currentRowChanged(int row)
418 {
419 if (row == -1)
420 {
421 // No list item selected, so disable editing widgets.
422 borderLineWidth->setEnabled(false);
423 borderLineWidthLabel->setEnabled(false);
424 borderLineColor->setEnabled(false);
425 borderLineColorLabel->setEnabled(false);
426 borderLineStyle->setEnabled(false);
427 borderLineStyleLabel->setEnabled(false);
428 borderLineShade->setEnabled(false);
429 borderLineShadeLabel->setEnabled(false);
430 }
431 else
432 {
433 QList<TableBorderLine> borderLines = m_currentBorder.borderLines();
434 Q_ASSERT(borderLineList->count() == borderLines.size());
435 const TableBorderLine& line = borderLines.at(row);
436
437 // Enable editing widgets.
438 borderLineWidth->setEnabled(true);
439 borderLineWidthLabel->setEnabled(true);
440 borderLineColor->setEnabled(true);
441 borderLineColorLabel->setEnabled(true);
442 borderLineStyle->setEnabled(true);
443 borderLineStyleLabel->setEnabled(true);
444 borderLineShade->setEnabled(true);
445 borderLineShadeLabel->setEnabled(true);
446
447 // Fill in values.
448 borderLineWidth->showValue(line.width());
449 setCurrentComboItem(borderLineColor, line.color());
450 borderLineStyle->setCurrentIndex(static_cast<int>(line.style()) - 1);
451 borderLineShade->setValue(line.shade());
452 }
453 }
454
455 /// Handles adding of a new border line.
on_addBorderLineButton_clicked()456 void PropertiesPalette_Table::on_addBorderLineButton_clicked()
457 {
458 if (!m_item || !m_item->isTable())
459 return;
460
461 m_currentBorder.addBorderLine(TableBorderLine());
462 updateBorderLineList();
463 }
464
465 /// Handles removing of a border line.
on_removeBorderLineButton_clicked()466 void PropertiesPalette_Table::on_removeBorderLineButton_clicked()
467 {
468 int index = borderLineList->currentRow();
469 borderLineList->removeItemWidget(borderLineList->currentItem());
470 m_currentBorder.removeBorderLine(index);
471
472 updateBorders();
473 updateBorderLineList();
474 }
475
on_borderLineWidth_valueChanged(double width)476 void PropertiesPalette_Table::on_borderLineWidth_valueChanged(double width)
477 {
478 int index = borderLineList->currentRow();
479 TableBorderLine borderLine = m_currentBorder.borderLines().at(index);
480 borderLine.setWidth(width);
481 m_currentBorder.replaceBorderLine(index, borderLine);
482
483 updateBorders();
484 updateBorderLineList(borderLine);
485 }
486
on_borderLineShade_valueChanged(double shade)487 void PropertiesPalette_Table::on_borderLineShade_valueChanged(double shade)
488 {
489 int index = borderLineList->currentRow();
490 TableBorderLine borderLine = m_currentBorder.borderLines().at(index);
491 borderLine.setShade(shade);
492 m_currentBorder.replaceBorderLine(index, borderLine);
493
494 updateBorders();
495 updateBorderLineListItem();
496 }
497
on_borderLineColor_activated(const QString & colorName)498 void PropertiesPalette_Table::on_borderLineColor_activated(const QString& colorName)
499 {
500 int index = borderLineList->currentRow();
501 TableBorderLine borderLine = m_currentBorder.borderLines().at(index);
502 QString color = colorName;
503 if (colorName == CommonStrings::tr_NoneColor)
504 color = CommonStrings::None;
505 borderLine.setColor(color);
506 m_currentBorder.replaceBorderLine(index, borderLine);
507
508 updateBorders();
509 updateBorderLineListItem();
510 }
511
on_borderLineStyle_activated(int style)512 void PropertiesPalette_Table::on_borderLineStyle_activated(int style)
513 {
514 int index = borderLineList->currentRow();
515 TableBorderLine borderLine = m_currentBorder.borderLines().at(index);
516 borderLine.setStyle(static_cast<Qt::PenStyle>(style + 1));
517 m_currentBorder.replaceBorderLine(index, borderLine);
518
519 updateBorders();
520 updateBorderLineListItem();
521 }
522
on_fillColor_activated(const QString & colorName)523 void PropertiesPalette_Table::on_fillColor_activated(const QString& colorName)
524 {
525 if (!m_item || !m_item->isTable())
526 return;
527 QString color = colorName;
528 if (colorName == CommonStrings::tr_NoneColor)
529 color = CommonStrings::None;
530 PageItem_Table* table = m_item->asTable();
531 if (m_doc->appMode != modeEditTable)
532 {
533 table->setFillColor(color);
534 table->setFillShade(fillShade->value());
535 }
536 else
537 {
538 QSet<TableCell> cells = table->selectedCells();
539 if (cells.isEmpty())
540 cells.insert(table->activeCell());
541 QSet<TableCell>::Iterator cellIter;
542 for (cellIter = cells.begin(); cellIter != cells.end(); cellIter++)
543 {
544 TableCell currentCell(*cellIter);
545 currentCell.setFillColor(color);
546 currentCell.setFillShade(fillShade->value());
547 }
548 }
549
550 table->update();
551 }
552
on_fillShade_valueChanged(double shade)553 void PropertiesPalette_Table::on_fillShade_valueChanged(double shade)
554 {
555 if (!m_item || !m_item->isTable())
556 return;
557
558 QString color = fillColor->currentColor();
559 if (color == CommonStrings::tr_NoneColor)
560 color = CommonStrings::None;
561 PageItem_Table* table = m_item->asTable();
562 if (m_doc->appMode != modeEditTable)
563 {
564 table->setFillColor(color);
565 table->setFillShade(shade);
566 }
567 else
568 {
569 QSet<TableCell> cells = table->selectedCells();
570 if (cells.isEmpty())
571 cells.insert(table->activeCell());
572 QSet<TableCell>::Iterator cellIter;
573 for (cellIter = cells.begin(); cellIter != cells.end(); cellIter++)
574 {
575 TableCell currentCell(*cellIter);
576 currentCell.setFillColor(color);
577 currentCell.setFillShade(shade);
578 }
579 }
580 table->update();
581 }
582
on_buttonClearTableStyle_clicked()583 void PropertiesPalette_Table::on_buttonClearTableStyle_clicked()
584 {
585 if (!m_item || !m_item->isTable())
586 return;
587 PageItem_Table* table = m_item->asTable();
588 table->unsetDirectFormatting();
589 table->update();
590 }
591
on_buttonClearCellStyle_clicked()592 void PropertiesPalette_Table::on_buttonClearCellStyle_clicked()
593 {
594 if (!m_item || !m_item->isTable())
595 return;
596 m_doc->dontResize = true;
597 PageItem_Table* table = m_item->asTable();
598 table->activeCell().unsetDirectFormatting();
599 table->adjustTable();
600 table->update();
601 }
602
updateBorders()603 void PropertiesPalette_Table::updateBorders()
604 {
605 if (!m_doc || !m_item || !m_item->isTable())
606 return;
607
608 PageItem_Table* table = m_item->asTable();
609 TableSideSelector::Sides selectedSides = sideSelector->selection();
610
611 m_doc->dontResize = true;
612 if (m_doc->appMode != modeEditTable)
613 {
614 if (selectedSides & TableSideSelector::Left)
615 table->setLeftBorder(m_currentBorder);
616 if (selectedSides & TableSideSelector::Right)
617 table->setRightBorder(m_currentBorder);
618 if (selectedSides & TableSideSelector::Top)
619 table->setTopBorder(m_currentBorder);
620 if (selectedSides & TableSideSelector::Bottom)
621 table->setBottomBorder(m_currentBorder);
622 }
623 else
624 {
625 QSet<TableCell> cells = table->selectedCells();
626 if (cells.isEmpty())
627 cells.insert(table->activeCell());
628 QSet<TableCell>::Iterator cellIter;
629 for (cellIter = cells.begin(); cellIter != cells.end(); cellIter++)
630 {
631 TableCell currentCell(*cellIter);
632 if (selectedSides & TableSideSelector::Left)
633 currentCell.setLeftBorder(m_currentBorder);
634 if (selectedSides & TableSideSelector::Right)
635 currentCell.setRightBorder(m_currentBorder);
636 if (selectedSides & TableSideSelector::Top)
637 currentCell.setTopBorder(m_currentBorder);
638 if (selectedSides & TableSideSelector::Bottom)
639 currentCell.setBottomBorder(m_currentBorder);
640 }
641 }
642
643 table->adjustTable();
644 table->update();
645 }
646
languageChange()647 void PropertiesPalette_Table::languageChange()
648 {
649 retranslateUi(this);
650 }
651
unitChange()652 void PropertiesPalette_Table::unitChange()
653 {
654 // Not implemented.
655 }
656