File indexing completed on 2024-05-12 16:35:16
0001 /* This file is part of the KDE project 0002 Copyright (C) 2002-2003 Norbert Andres <nandres@web.de> 0003 (C) 2002-2003 Philipp Mueller <philipp.mueller@gmx.de> 0004 (C) 2002 John Dailey <dailey@vt.edu> 0005 (C) 1999-2001 Laurent Montel <montel@kde.org> 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 0024 #include "ConditionalDialog.h" 0025 #include "Condition.h" 0026 0027 #include "Cell.h" 0028 #include "Map.h" 0029 #include "ui/Selection.h" 0030 #include "Sheet.h" 0031 #include "StyleManager.h" 0032 #include "ValueConverter.h" 0033 #include "ValueParser.h" 0034 #include "SheetsDebug.h" 0035 0036 // commands 0037 #include "commands/ConditionCommand.h" 0038 0039 #include <kcombobox.h> 0040 #include <klineedit.h> 0041 #include <KLocalizedString> 0042 #include <kmessagebox.h> 0043 0044 #include <QGroupBox> 0045 #include <QLabel> 0046 #include <QGridLayout> 0047 0048 using namespace Calligra::Sheets; 0049 0050 ConditionalWidget::ConditionalWidget(QWidget* parent, const char* /*name*/, Qt::WindowFlags fl) 0051 : QWidget(parent, fl) 0052 { 0053 QGridLayout * Form1Layout = new QGridLayout(this); 0054 0055 QGroupBox * groupBox1_3 = new QGroupBox(this); 0056 QGridLayout * groupBox1_3Layout = new QGridLayout(groupBox1_3); 0057 groupBox1_3Layout->setAlignment(Qt::AlignTop); 0058 0059 QLabel * textLabel1_3 = new QLabel(groupBox1_3); 0060 groupBox1_3Layout->addWidget(textLabel1_3, 0, 0); 0061 0062 m_condition_3 = new KComboBox(groupBox1_3); 0063 groupBox1_3Layout->addWidget(m_condition_3, 0, 1); 0064 0065 m_firstValue_3 = new KLineEdit(groupBox1_3); 0066 m_firstValue_3->setEnabled(false); 0067 groupBox1_3Layout->addWidget(m_firstValue_3, 0, 2); 0068 0069 m_secondValue_3 = new KLineEdit(groupBox1_3); 0070 m_secondValue_3->setEnabled(false); 0071 groupBox1_3Layout->addWidget(m_secondValue_3, 0, 3); 0072 0073 m_style_3 = new KComboBox(groupBox1_3); 0074 m_style_3->setEnabled(false); 0075 groupBox1_3Layout->addWidget(m_style_3, 1, 1); 0076 0077 QLabel * textLabel2_3 = new QLabel(groupBox1_3); 0078 groupBox1_3Layout->addWidget(textLabel2_3, 1, 0); 0079 0080 QSpacerItem * spacer = new QSpacerItem(41, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 0081 groupBox1_3Layout->addItem(spacer, 1, 2); 0082 QSpacerItem * spacer_2 = new QSpacerItem(61, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 0083 groupBox1_3Layout->addItem(spacer_2, 1, 3); 0084 0085 Form1Layout->addWidget(groupBox1_3, 2, 0); 0086 0087 QGroupBox * groupBox1_2 = new QGroupBox(this); 0088 0089 QGridLayout * groupBox1_2Layout = new QGridLayout(groupBox1_2); 0090 groupBox1_2Layout->setAlignment(Qt::AlignTop); 0091 0092 QLabel * textLabel1_2 = new QLabel(groupBox1_2); 0093 groupBox1_2Layout->addWidget(textLabel1_2, 0, 0); 0094 0095 QLabel * textLabel2_2 = new QLabel(groupBox1_2); 0096 groupBox1_2Layout->addWidget(textLabel2_2, 1, 0); 0097 0098 m_condition_2 = new KComboBox(groupBox1_2); 0099 groupBox1_2Layout->addWidget(m_condition_2, 0, 1); 0100 0101 m_style_2 = new KComboBox(groupBox1_2); 0102 m_style_2->setEnabled(false); 0103 groupBox1_2Layout->addWidget(m_style_2, 1, 1); 0104 0105 m_firstValue_2 = new KLineEdit(groupBox1_2); 0106 0107 m_firstValue_2->setEnabled(false); 0108 groupBox1_2Layout->addWidget(m_firstValue_2, 0, 2); 0109 0110 m_secondValue_2 = new KLineEdit(groupBox1_2); 0111 m_secondValue_2->setEnabled(false); 0112 0113 groupBox1_2Layout->addWidget(m_secondValue_2, 0, 3); 0114 0115 QSpacerItem * spacer_3 = new QSpacerItem(41, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 0116 groupBox1_2Layout->addItem(spacer_3, 1, 2); 0117 QSpacerItem * spacer_4 = new QSpacerItem(61, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 0118 groupBox1_2Layout->addItem(spacer_4, 1, 3); 0119 Form1Layout->addWidget(groupBox1_2, 1, 0); 0120 0121 QGroupBox * groupBox1_1 = new QGroupBox(this); 0122 0123 QGridLayout * groupBox1_1Layout = new QGridLayout(groupBox1_1); 0124 groupBox1_1Layout->setAlignment(Qt::AlignTop); 0125 0126 QLabel * textLabel1_1 = new QLabel(groupBox1_1); 0127 groupBox1_1Layout->addWidget(textLabel1_1, 0, 0); 0128 0129 QLabel * textLabel2_1 = new QLabel(groupBox1_1); 0130 groupBox1_1Layout->addWidget(textLabel2_1, 1, 0); 0131 0132 m_condition_1 = new KComboBox(groupBox1_1); 0133 groupBox1_1Layout->addWidget(m_condition_1, 0, 1); 0134 0135 m_style_1 = new KComboBox(groupBox1_1); 0136 m_style_1->setEnabled(false); 0137 groupBox1_1Layout->addWidget(m_style_1, 1, 1); 0138 0139 m_firstValue_1 = new KLineEdit(groupBox1_1); 0140 m_firstValue_1->setEnabled(false); 0141 groupBox1_1Layout->addWidget(m_firstValue_1, 0, 2); 0142 0143 m_secondValue_1 = new KLineEdit(groupBox1_1); 0144 m_secondValue_1->setEnabled(false); 0145 groupBox1_1Layout->addWidget(m_secondValue_1, 0, 3); 0146 0147 QSpacerItem * spacer_5 = new QSpacerItem(41, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 0148 groupBox1_1Layout->addItem(spacer_5, 1, 2); 0149 QSpacerItem * spacer_6 = new QSpacerItem(61, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 0150 groupBox1_1Layout->addItem(spacer_6, 1, 3); 0151 0152 Form1Layout->addWidget(groupBox1_1, 0, 0); 0153 resize(QSize(702, 380).expandedTo(minimumSizeHint())); 0154 0155 QStringList list; 0156 list += i18n("<none>"); // krazy:exclude=i18ncheckarg 0157 list += i18n("equal to"); 0158 list += i18n("greater than"); 0159 list += i18n("less than"); 0160 list += i18n("equal to or greater than"); 0161 list += i18n("equal to or less than"); 0162 list += i18n("between"); 0163 list += i18n("outside range"); 0164 list += i18n("different to"); 0165 0166 m_condition_1->clear(); 0167 m_condition_2->clear(); 0168 m_condition_3->clear(); 0169 m_condition_1->insertItems(0, list); 0170 m_condition_2->insertItems(0, list); 0171 m_condition_3->insertItems(0, list); 0172 0173 groupBox1_1->setTitle(i18n("First Condition")); 0174 groupBox1_2->setTitle(i18n("Second Condition")); 0175 groupBox1_3->setTitle(i18n("Third Condition")); 0176 textLabel1_1->setText(i18n("Cell is")); 0177 textLabel1_2->setText(i18n("Cell is")); 0178 textLabel1_3->setText(i18n("Cell is")); 0179 textLabel2_1->setText(i18n("Cell style")); 0180 textLabel2_2->setText(i18n("Cell style")); 0181 textLabel2_3->setText(i18n("Cell style")); 0182 0183 connect(m_condition_1, SIGNAL(highlighted(QString)), this, SLOT(slotTextChanged1(QString))); 0184 connect(m_condition_2, SIGNAL(highlighted(QString)), this, SLOT(slotTextChanged2(QString))); 0185 connect(m_condition_3, SIGNAL(highlighted(QString)), this, SLOT(slotTextChanged3(QString))); 0186 } 0187 0188 ConditionalWidget::~ConditionalWidget() 0189 { 0190 } 0191 0192 void ConditionalWidget::slotTextChanged1(const QString & text) 0193 { 0194 if (text == i18n("<none>")) { // krazy:exclude=i18ncheckarg 0195 m_firstValue_1->setEnabled(false); 0196 m_secondValue_1->setEnabled(false); 0197 m_style_1->setEnabled(false); 0198 } else { 0199 m_condition_2->setEnabled(true); 0200 m_style_1->setEnabled(true); 0201 if ((text == i18n("between")) || (text == i18n("different from"))) { 0202 m_firstValue_1->setEnabled(true); 0203 m_secondValue_1->setEnabled(true); 0204 } else { 0205 m_firstValue_1->setEnabled(true); 0206 m_secondValue_1->setEnabled(false); 0207 } 0208 } 0209 } 0210 0211 void ConditionalWidget::slotTextChanged2(const QString & text) 0212 { 0213 if (text == i18n("<none>")) { // krazy:exclude=i18ncheckarg 0214 m_firstValue_2->setEnabled(false); 0215 m_secondValue_2->setEnabled(false); 0216 m_style_2->setEnabled(false); 0217 } else { 0218 m_condition_3->setEnabled(true); 0219 m_style_2->setEnabled(true); 0220 if ((text == i18n("between")) || (text == i18n("different from"))) { 0221 m_firstValue_2->setEnabled(true); 0222 m_secondValue_2->setEnabled(true); 0223 } else { 0224 m_firstValue_2->setEnabled(true); 0225 m_secondValue_2->setEnabled(false); 0226 } 0227 } 0228 } 0229 0230 void ConditionalWidget::slotTextChanged3(const QString & text) 0231 { 0232 if (text == i18n("<none>")) { // krazy:exclude=i18ncheckarg 0233 m_firstValue_3->setEnabled(false); 0234 m_secondValue_3->setEnabled(false); 0235 m_style_3->setEnabled(false); 0236 } else { 0237 m_style_3->setEnabled(true); 0238 if ((text == i18n("between")) || (text == i18n("different from"))) { 0239 m_firstValue_3->setEnabled(true); 0240 m_secondValue_3->setEnabled(true); 0241 } else { 0242 m_firstValue_3->setEnabled(true); 0243 m_secondValue_3->setEnabled(false); 0244 } 0245 } 0246 } 0247 0248 /** 0249 * ConditionalDialog 0250 * Sets conditional cell formattings. 0251 */ 0252 ConditionalDialog::ConditionalDialog(QWidget* parent, Selection* selection) 0253 : KoDialog(parent), 0254 m_selection(selection), 0255 m_dlg(new ConditionalWidget(this)) 0256 { 0257 setButtons(KoDialog::Ok | KoDialog::Cancel); 0258 setCaption(i18n("Conditional Styles")); 0259 0260 QStringList list(m_selection->activeSheet()->map()->styleManager()->styleNames()); 0261 0262 m_dlg->m_style_1->insertItems(0, list); 0263 m_dlg->m_style_2->insertItems(0, list); 0264 m_dlg->m_style_3->insertItems(0, list); 0265 0266 setMainWidget(m_dlg); 0267 0268 connect(this, SIGNAL(okClicked()), this, SLOT(slotOk())); 0269 0270 init(); 0271 } 0272 0273 void ConditionalDialog::init() 0274 { 0275 QLinkedList<Conditional> conditionList; 0276 QLinkedList<Conditional> otherList; 0277 bool found; 0278 int numCondition; 0279 0280 QLinkedList<Conditional>::iterator it1; 0281 QLinkedList<Conditional>::iterator it2; 0282 0283 Sheet* sheet = m_selection->activeSheet(); 0284 0285 conditionList = Cell(sheet, m_selection->marker()).conditions().conditionList(); 0286 /* this is the list, but only display the conditions common to all selected 0287 cells*/ 0288 0289 for (int x = m_selection->lastRange().left(); x <= m_selection->lastRange().right(); x++) { 0290 for (int y = m_selection->lastRange().top(); y <= m_selection->lastRange().bottom(); y++) { 0291 otherList = Cell(sheet, x, y).conditions().conditionList(); 0292 0293 it1 = conditionList.begin(); 0294 while (it1 != conditionList.end()) { 0295 debugSheets << "Here"; 0296 found = false; 0297 for (it2 = otherList.begin(); !found && it2 != otherList.end(); ++it2) { 0298 debugSheets << "Found:" << found; 0299 found = ((*it1).value1 == (*it2).value1 && 0300 (*it1).value2 == (*it2).value2 && 0301 (*it1).cond == (*it2).cond); 0302 0303 if (!found) 0304 continue; 0305 0306 if ((*it1).styleName != (*it2).styleName) 0307 found = false; 0308 } 0309 0310 if (!found) { /* if it's not here, don't display this condition */ 0311 it1 = conditionList.erase(it1); 0312 } else { 0313 ++it1; 0314 } 0315 } 0316 } 0317 } 0318 0319 debugSheets << "Conditions:" << conditionList.size(); 0320 0321 m_dlg->m_condition_2->setEnabled(false); 0322 m_dlg->m_condition_3->setEnabled(false); 0323 0324 m_dlg->m_style_1->setEnabled(false); 0325 m_dlg->m_style_2->setEnabled(false); 0326 m_dlg->m_style_3->setEnabled(false); 0327 0328 numCondition = 0; 0329 for (it1 = conditionList.begin(); numCondition < 3 && it1 != conditionList.end(); ++it1) { 0330 init(*it1, numCondition); 0331 0332 ++numCondition; 0333 } 0334 } 0335 0336 void ConditionalDialog::init(Conditional const & tmp, int numCondition) 0337 { 0338 debugSheets << "Adding" << numCondition; 0339 KComboBox * cb = 0; 0340 KComboBox * sb = 0; 0341 KLineEdit * kl1 = 0; 0342 KLineEdit * kl2 = 0; 0343 QString value; 0344 Map *const map = m_selection->activeSheet()->map(); 0345 ValueConverter *const converter = map->converter(); 0346 0347 switch (numCondition) { 0348 case 0: 0349 cb = m_dlg->m_condition_1; 0350 sb = m_dlg->m_style_1; 0351 kl1 = m_dlg->m_firstValue_1; 0352 kl2 = m_dlg->m_secondValue_1; 0353 break; 0354 case 1: 0355 cb = m_dlg->m_condition_2; 0356 sb = m_dlg->m_style_2; 0357 kl1 = m_dlg->m_firstValue_2; 0358 kl2 = m_dlg->m_secondValue_2; 0359 break; 0360 case 2: 0361 cb = m_dlg->m_condition_3; 0362 sb = m_dlg->m_style_3; 0363 kl1 = m_dlg->m_firstValue_3; 0364 kl2 = m_dlg->m_secondValue_3; 0365 break; 0366 default: 0367 return; 0368 } 0369 0370 if (!tmp.styleName.isEmpty()) { 0371 sb->setCurrentIndex(sb->findText(tmp.styleName)); 0372 sb->setEnabled(true); 0373 } 0374 0375 switch (tmp.cond) { 0376 case Conditional::None : 0377 case Conditional::IsTrueFormula: // was unhandled 0378 break; 0379 0380 case Conditional::Equal : 0381 cb->setCurrentIndex(1); 0382 break; 0383 0384 case Conditional::Superior : 0385 cb->setCurrentIndex(2); 0386 break; 0387 0388 case Conditional::Inferior : 0389 cb->setCurrentIndex(3); 0390 break; 0391 0392 case Conditional::SuperiorEqual : 0393 cb->setCurrentIndex(4); 0394 break; 0395 0396 case Conditional::InferiorEqual : 0397 cb->setCurrentIndex(5); 0398 break; 0399 0400 case Conditional::Between : 0401 cb->setCurrentIndex(6); 0402 kl2->setText(converter->asString(tmp.value2).asString()); 0403 break; 0404 0405 case Conditional::Different : 0406 cb->setCurrentIndex(7); 0407 kl2->setText(converter->asString(tmp.value2).asString()); 0408 break; 0409 case Conditional::DifferentTo : 0410 cb->setCurrentIndex(8); 0411 break; 0412 } 0413 0414 if (tmp.cond != Conditional::None) { 0415 kl1->setEnabled(true); 0416 kl1->setText(converter->asString(tmp.value1).asString()); 0417 } 0418 } 0419 0420 Conditional::Type ConditionalDialog::typeOfCondition(KComboBox const * const cb) const 0421 { 0422 Conditional::Type result = Conditional::None; 0423 switch (cb->currentIndex()) { 0424 case 0 : 0425 result = Conditional::None; 0426 break; 0427 case 1 : 0428 result = Conditional::Equal; 0429 break; 0430 case 2 : 0431 result = Conditional::Superior; 0432 break; 0433 case 3 : 0434 result = Conditional::Inferior; 0435 break; 0436 case 4 : 0437 result = Conditional::SuperiorEqual; 0438 break; 0439 case 5 : 0440 result = Conditional::InferiorEqual; 0441 break; 0442 case 6 : 0443 result = Conditional::Between; 0444 break; 0445 case 7 : 0446 result = Conditional::Different; 0447 break; 0448 case 8 : 0449 result = Conditional::DifferentTo; 0450 break; 0451 default: 0452 debugSheets << "Error in list"; 0453 break; 0454 } 0455 0456 return result; 0457 } 0458 0459 bool ConditionalDialog::checkInputData(KLineEdit const * const edit1, 0460 KLineEdit const * const edit2) 0461 { 0462 bool b1 = false; 0463 bool b2 = false; 0464 0465 if (!edit2->isEnabled()) 0466 return true; 0467 0468 edit1->text().toDouble(&b1); 0469 edit2->text().toDouble(&b2); 0470 0471 if (b1 != b2) { 0472 if (b1) 0473 KMessageBox::sorry(0, i18n("If the first value is a number, the second value also has to be a number.")); 0474 else 0475 KMessageBox::sorry(0, i18n("If the first value is a string, the second value also has to be a string.")); 0476 return false; 0477 } 0478 0479 return true; 0480 } 0481 0482 bool ConditionalDialog::checkInputData() 0483 { 0484 if (m_dlg->m_firstValue_1->isEnabled() && !checkInputData(m_dlg->m_firstValue_1, m_dlg->m_secondValue_1)) 0485 return false; 0486 if (m_dlg->m_firstValue_2->isEnabled() && !checkInputData(m_dlg->m_firstValue_2, m_dlg->m_secondValue_2)) 0487 return false; 0488 if (m_dlg->m_firstValue_3->isEnabled() && !checkInputData(m_dlg->m_firstValue_3, m_dlg->m_secondValue_3)) 0489 return false; 0490 0491 return true; 0492 } 0493 0494 bool ConditionalDialog::getCondition(Conditional & newCondition, const KComboBox * cb, 0495 const KLineEdit * edit1, const KLineEdit * edit2, 0496 const KComboBox * sb) 0497 { 0498 if (!cb->isEnabled()) 0499 return false; 0500 0501 newCondition.cond = typeOfCondition(cb); 0502 if (newCondition.cond == Conditional::None) 0503 return false; 0504 0505 Map *const map = m_selection->activeSheet()->map(); 0506 ValueParser *const parser = map->parser(); 0507 0508 newCondition.value1 = parser->parse(edit1->text()); 0509 newCondition.value2 = parser->parse(edit2->text()); 0510 newCondition.styleName = sb->currentText(); 0511 0512 return true; 0513 } 0514 0515 void ConditionalDialog::slotOk() 0516 { 0517 debugSheets << "slotOk"; 0518 0519 if (!checkInputData()) 0520 return; 0521 0522 debugSheets << "Input data is valid"; 0523 0524 QLinkedList<Conditional> newList; 0525 0526 Conditional newCondition; 0527 0528 if (getCondition(newCondition, m_dlg->m_condition_1, m_dlg->m_firstValue_1, 0529 m_dlg->m_secondValue_1, m_dlg->m_style_1)) 0530 newList.append(newCondition); 0531 0532 if (getCondition(newCondition, m_dlg->m_condition_2, m_dlg->m_firstValue_2, 0533 m_dlg->m_secondValue_2, m_dlg->m_style_2)) 0534 newList.append(newCondition); 0535 0536 if (getCondition(newCondition, m_dlg->m_condition_3, m_dlg->m_firstValue_3, 0537 m_dlg->m_secondValue_3, m_dlg->m_style_3)) 0538 newList.append(newCondition); 0539 0540 debugSheets << "Setting conditional list"; 0541 ConditionCommand* manipulator = new ConditionCommand(); 0542 manipulator->setSheet(m_selection->activeSheet()); 0543 manipulator->setConditionList(newList); 0544 manipulator->add(*m_selection); 0545 manipulator->execute(m_selection->canvas()); 0546 0547 accept(); 0548 }