File indexing completed on 2024-05-12 04:21:14
0001 /* 0002 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0003 All rights reserved. 0004 0005 Redistribution and use in source and binary forms, with or without 0006 modification, are permitted provided that the following conditions 0007 are met: 0008 0009 1. Redistributions of source code must retain the above copyright 0010 notice, this list of conditions and the following disclaimer. 0011 2. Redistributions in binary form must reproduce the above copyright 0012 notice, this list of conditions and the following disclaimer in the 0013 documentation and/or other materials provided with the distribution. 0014 0015 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0016 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0017 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0018 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0019 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0020 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0021 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0022 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0024 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0025 */ 0026 0027 0028 #define DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0 0029 0030 0031 #include "kpDocumentMetaInfoDialog.h" 0032 0033 #include "kpDefs.h" 0034 #include "imagelib/kpDocumentMetaInfo.h" 0035 0036 #include <KLocalizedString> 0037 #include <KMessageBox> 0038 #include "kpLogCategories.h" 0039 0040 #include <QAbstractItemView> 0041 #include <QDialogButtonBox> 0042 #include <QLabel> 0043 #include <QGroupBox> 0044 #include <QGridLayout> 0045 #include <QHBoxLayout> 0046 #include <QPushButton> 0047 #include <QTableWidget> 0048 #include <QSpinBox> 0049 #include <QDoubleSpinBox> 0050 0051 0052 struct kpDocumentMetaInfoDialogPrivate 0053 { 0054 const kpDocumentMetaInfo *originalMetaInfoPtr; 0055 0056 QDoubleSpinBox *horizDpiInput, *vertDpiInput; 0057 QSpinBox *horizOffsetInput, *vertOffsetInput; 0058 0059 QTableWidget *fieldsTableWidget; 0060 QPushButton *fieldsAddRowButton, *fieldsDeleteRowButton, *fieldsResetButton; 0061 }; 0062 0063 0064 // (shared by all dialogs, across all main windows, in a KolourPaint instance) 0065 static int LastWidth = -1, LastHeight = -1; 0066 0067 0068 // sync: You must keep DpiMinStep = 10 ^ (-DpiPrecision). 0069 // 0070 // You can increase the precision to reduce the chance of inadvertently changing 0071 // the resolution when converting from kpDocumentMetaInfo's "dots per meter" 0072 // to our "dots per inch" and back. It would be bad if simply going into this 0073 // dialog and pressing OK changed the resolution (it's unlikely but I still think 0074 // it might happen with the current precision). 0075 // TODO: On a related note, for many particular resolutions, if the user enters 0076 // one of them into the UI, presses OK and then comes back to the dialog, 0077 // s/he is presented with a different resolution to the one typed in. 0078 // Maybe make DotsPerMeter[XY] be of type "double" instead of "int" to 0079 // solve this problem? 0080 // 0081 // Of course, if you increase the precision too much, the minimum step will 0082 // become so small that it will start experiencing floating point inaccuracies 0083 // esp. since we use it for the "DpiUnspecified" hack. 0084 static const int DpiPrecision = 3; 0085 static const double DpiMinStep = 0.001; 0086 0087 static const double DpiLegalMin = 0088 kpDocumentMetaInfo::MinDotsPerMeter / KP_INCHES_PER_METER; 0089 0090 // Out of range represents unspecified DPI. 0091 static const double DpiUnspecified = ::DpiLegalMin - ::DpiMinStep; 0092 0093 static const double DpiInputMin = ::DpiUnspecified; 0094 static const double DpiInputMax = 0095 kpDocumentMetaInfo::MaxDotsPerMeter / KP_INCHES_PER_METER; 0096 0097 // The increment the DPI spinboxes jump by when they're clicked. 0098 // 0099 // We make this relatively big since people don't usually just increase their 0100 // DPIs by 1 or so -- they are usually changing from say, 72, to 96. 0101 // 0102 // Obviously, making it equal to DpiMinStep is too slow a UI. Therefore, with 0103 // our big setting, the user will still have to manually change the value in 0104 // the spinbox, using the keyboard, after all their clicking to ensure it is 0105 // exactly the value they want. 0106 static const double DpiInputStep = 10; 0107 0108 0109 // TODO: Halve groupbox layout margins in every other file since it doesn't 0110 // seem to be need in Qt4. 0111 kpDocumentMetaInfoDialog::kpDocumentMetaInfoDialog ( 0112 const kpDocumentMetaInfo *docMetaInfo, 0113 QWidget *parent) 0114 0115 : QDialog (parent), 0116 d (new kpDocumentMetaInfoDialogPrivate ()) 0117 { 0118 d->originalMetaInfoPtr = docMetaInfo; 0119 0120 0121 setWindowTitle (i18nc ("@title:window", "Document Properties")); 0122 auto * buttons = new QDialogButtonBox (QDialogButtonBox::Ok | 0123 QDialogButtonBox::Cancel, this); 0124 0125 connect (buttons, &QDialogButtonBox::accepted, this, &kpDocumentMetaInfoDialog::accept); 0126 connect (buttons, &QDialogButtonBox::rejected, this, &kpDocumentMetaInfoDialog::reject); 0127 0128 auto *baseWidget = new QWidget (this); 0129 0130 auto *dialogLayout = new QVBoxLayout (this); 0131 dialogLayout->addWidget (baseWidget); 0132 dialogLayout->addWidget (buttons); 0133 0134 0135 // 0136 // DPI Group Box 0137 // 0138 0139 Q_ASSERT (::DpiInputMin < ::DpiInputMax); 0140 0141 auto *dpiGroupBox = new QGroupBox(i18n("Dots &Per Inch (DPI)"), baseWidget); 0142 0143 d->horizDpiInput = new QDoubleSpinBox(dpiGroupBox); 0144 d->horizDpiInput->setRange(::DpiInputMin, ::DpiInputMax); 0145 d->horizDpiInput->setValue(0.0); 0146 d->horizDpiInput->setSingleStep(::DpiInputStep); 0147 d->horizDpiInput->setDecimals(::DpiPrecision); 0148 d->horizDpiInput->setSpecialValueText(i18n("Unspecified")); 0149 0150 auto *dpiXLabel = new QLabel ( 0151 i18nc ("Horizontal DPI 'x' Vertical DPI", " x "), dpiGroupBox); 0152 dpiXLabel->setAlignment (Qt::AlignCenter); 0153 0154 d->vertDpiInput = new QDoubleSpinBox(dpiGroupBox); 0155 d->vertDpiInput->setRange(::DpiInputMin, ::DpiInputMax); 0156 d->vertDpiInput->setValue(0.0); 0157 d->vertDpiInput->setSingleStep(::DpiInputStep); 0158 d->vertDpiInput->setDecimals(::DpiPrecision); 0159 d->vertDpiInput->setSpecialValueText(i18n("Unspecified")); 0160 0161 0162 auto *dpiLay = new QGridLayout(dpiGroupBox); 0163 0164 dpiLay->addWidget(new QLabel(i18n("Horizontal:")), 0, 0, Qt::AlignHCenter); 0165 dpiLay->addWidget(d->horizDpiInput, 1, 0); 0166 dpiLay->addWidget(dpiXLabel, 0, 1); 0167 dpiLay->addWidget(new QLabel(i18n("Vertical:")), 0, 2, Qt::AlignHCenter); 0168 dpiLay->addWidget(d->vertDpiInput, 1, 2); 0169 0170 dpiLay->setRowStretch(2, 1); 0171 0172 0173 dpiGroupBox->setWhatsThis ( 0174 i18n ( 0175 "<qt>" 0176 "<p><b>Dots Per Inch</b> (DPI) specifies the number of pixels" 0177 " of the image that should be printed inside one inch (2.54cm).</p>" 0178 0179 "<p>The higher the image's DPI, the smaller the printed image." 0180 " Note that your printer is unlikely to produce high" 0181 " quality prints if you increase this to more than 300 or 600 DPI," 0182 " depending on the printer.</p>" 0183 0184 "<p>If you would like to print the image so that it is the same" 0185 " size as it is displayed on the screen, set the image's DPI" 0186 " values to be the same as the screen's.</p>" 0187 0188 // TODO: This is currently not true! 0189 // See "96dpi" TODO in kpMainWindow::sendPixmapToPrinter(). 0190 // This also why we don't try to report the current screen DPI 0191 // for the above paragraph. 0192 "<p>If either DPI value is <b>Unspecified</b>, the image will also" 0193 " be printed to be the same size as on the screen.</p>" 0194 0195 "<p>Not all image formats support DPI values. If the format you" 0196 " save in does not support them, they will not be saved.</p>" 0197 "</qt>" 0198 )); 0199 0200 0201 // 0202 // Offset Group Box 0203 // 0204 0205 auto *offsetGroupBox = new QGroupBox(i18n ("O&ffset"), baseWidget); 0206 0207 d->horizOffsetInput = new QSpinBox; 0208 d->horizOffsetInput->setRange(kpDocumentMetaInfo::MinOffset, kpDocumentMetaInfo::MaxOffset); 0209 0210 d->vertOffsetInput = new QSpinBox; 0211 d->vertOffsetInput->setRange(kpDocumentMetaInfo::MinOffset, kpDocumentMetaInfo::MaxOffset); 0212 0213 auto *offsetLay = new QGridLayout(offsetGroupBox); 0214 0215 offsetLay->addWidget(new QLabel(i18n("Horizontal:")), 0, 0, Qt::AlignHCenter); 0216 offsetLay->addWidget(d->horizOffsetInput, 1, 0); 0217 offsetLay->addWidget(new QLabel(i18n("Vertical:")), 0, 1, Qt::AlignHCenter); 0218 offsetLay->addWidget(d->vertOffsetInput, 1, 1); 0219 0220 offsetLay->setRowStretch (2, 1); 0221 0222 0223 offsetGroupBox->setWhatsThis ( 0224 i18n ( 0225 "<qt>" 0226 "<p>The <b>Offset</b> is the relative position where this image" 0227 " should be placed, compared to other images.</p>" 0228 0229 "<p>Not all image formats support the <b>Offset</b> feature." 0230 " If the format you save in does not support it, the values" 0231 " specified here will not be saved.</p>" 0232 "</qt>" 0233 )); 0234 0235 0236 // 0237 // Fields Group Box 0238 // 0239 0240 0241 auto *fieldsGroupBox = new QGroupBox (i18n ("&Text Fields"), 0242 baseWidget); 0243 0244 d->fieldsTableWidget = new QTableWidget (fieldsGroupBox); 0245 d->fieldsTableWidget->setEditTriggers(QAbstractItemView::AllEditTriggers); 0246 0247 connect (d->fieldsTableWidget, &QTableWidget::currentCellChanged, 0248 this, &kpDocumentMetaInfoDialog::slotFieldsCurrentCellChanged); 0249 0250 connect (d->fieldsTableWidget, &QTableWidget::itemChanged, 0251 this, &kpDocumentMetaInfoDialog::slotFieldsItemChanged); 0252 0253 d->fieldsAddRowButton = new QPushButton (i18n ("&Add Row"), 0254 fieldsGroupBox); 0255 connect (d->fieldsAddRowButton, &QPushButton::clicked, 0256 this, &kpDocumentMetaInfoDialog::slotFieldsAddRowButtonClicked); 0257 0258 d->fieldsDeleteRowButton = new QPushButton (i18n ("&Delete Row"), 0259 fieldsGroupBox); 0260 connect (d->fieldsDeleteRowButton, &QPushButton::clicked, 0261 this, &kpDocumentMetaInfoDialog::slotFieldsDeleteRowButtonClicked); 0262 0263 d->fieldsResetButton = new QPushButton (i18n ("&Reset"), 0264 fieldsGroupBox); 0265 connect (d->fieldsResetButton, &QPushButton::clicked, 0266 this, &kpDocumentMetaInfoDialog::setUIToOriginalMetaInfo); 0267 0268 auto *fieldsButtonsLayout = new QHBoxLayout (); 0269 fieldsButtonsLayout->addWidget (d->fieldsAddRowButton); 0270 fieldsButtonsLayout->addWidget (d->fieldsDeleteRowButton); 0271 fieldsButtonsLayout->addStretch (); 0272 fieldsButtonsLayout->addWidget (d->fieldsResetButton); 0273 0274 auto *fieldsLayout = new QVBoxLayout (fieldsGroupBox); 0275 0276 fieldsLayout->addWidget (d->fieldsTableWidget); 0277 fieldsLayout->addLayout (fieldsButtonsLayout); 0278 0279 0280 fieldsGroupBox->setWhatsThis ( 0281 i18n ( 0282 "<qt>" 0283 "<p><b>Text Fields</b> provide extra information about the image." 0284 " This is probably a comment area that you can freely write any text in.</p>" 0285 0286 "<p>However, this is format-specific so the fields could theoretically be" 0287 " computer-interpreted data - that you should not modify -" 0288 " but this is unlikely.</p>" 0289 0290 "<p>Not all image formats support <b>Text Fields</b>. If the format" 0291 " you save in does not support them, they will not be saved.</p>" 0292 "</qt>" 0293 )); 0294 0295 0296 // 0297 // Global Layout 0298 // 0299 auto *baseLayout = new QGridLayout (baseWidget); 0300 baseLayout->setContentsMargins(0, 0, 0, 0); 0301 0302 // Col 0 0303 baseLayout->addWidget (dpiGroupBox, 0, 0); 0304 baseLayout->addWidget (offsetGroupBox, 1, 0); 0305 0306 // Col 1 0307 baseLayout->addWidget (fieldsGroupBox, 0, 1, 2/*row span*/, 1/*col span*/); 0308 baseLayout->setColumnStretch (1, 1/*stretch*/); 0309 0310 0311 // 0312 // Remaining UI Setup 0313 // 0314 0315 0316 setUIToOriginalMetaInfo (); 0317 0318 0319 if (::LastWidth > 0 && ::LastHeight > 0) { 0320 resize (::LastWidth, ::LastHeight); 0321 } 0322 } 0323 0324 //--------------------------------------------------------------------- 0325 0326 kpDocumentMetaInfoDialog::~kpDocumentMetaInfoDialog () 0327 { 0328 ::LastWidth = width (); 0329 ::LastHeight = height (); 0330 0331 delete d; 0332 } 0333 0334 //--------------------------------------------------------------------- 0335 // private 0336 0337 void kpDocumentMetaInfoDialog::editCell (int r, int c) 0338 { 0339 d->fieldsTableWidget->setCurrentCell (r, c); 0340 d->fieldsTableWidget->editItem (d->fieldsTableWidget->item (r, c)); 0341 } 0342 0343 //--------------------------------------------------------------------- 0344 // private slot 0345 0346 void kpDocumentMetaInfoDialog::setUIToOriginalMetaInfo () 0347 { 0348 // Set DPI spinboxes. 0349 d->horizDpiInput->setValue (d->originalMetaInfoPtr->dotsPerMeterX () / 0350 KP_INCHES_PER_METER); 0351 d->vertDpiInput->setValue (d->originalMetaInfoPtr->dotsPerMeterY () / 0352 KP_INCHES_PER_METER); 0353 0354 0355 // Set Offset spinboxes. 0356 d->horizOffsetInput->setValue (d->originalMetaInfoPtr->offset ().x ()); 0357 d->vertOffsetInput->setValue (d->originalMetaInfoPtr->offset ().y ()); 0358 0359 0360 // Set Text Fields. 0361 // 0362 // Block itemChanged() signal as slotFieldsItemChanged() should not get called 0363 // when rows are half-created. 0364 const bool b = d->fieldsTableWidget->blockSignals (true); 0365 { 0366 d->fieldsTableWidget->clear (); 0367 0368 d->fieldsTableWidget->setRowCount (d->originalMetaInfoPtr->textKeys ().size ()); 0369 d->fieldsTableWidget->setColumnCount (2); 0370 0371 QStringList fieldsHeader; 0372 fieldsHeader << i18n ("Key") << i18n ("Value"); 0373 d->fieldsTableWidget->setHorizontalHeaderLabels (fieldsHeader); 0374 0375 int row = 0; 0376 for (const auto &key : d->originalMetaInfoPtr->textKeys ()) 0377 { 0378 d->fieldsTableWidget->setItem (row, 0/*1st col*/, 0379 new QTableWidgetItem (key)); 0380 d->fieldsTableWidget->setItem (row, 1/*2nd col*/, 0381 new QTableWidgetItem (d->originalMetaInfoPtr->text (key))); 0382 0383 row++; 0384 } 0385 0386 fieldsAppendEmptyRow (); 0387 } 0388 d->fieldsTableWidget->blockSignals (b); 0389 0390 0391 editCell (0/*row*/, 0/*col*/); 0392 0393 0394 enableFieldsDeleteRowButtonIfShould (); 0395 } 0396 0397 //--------------------------------------------------------------------- 0398 // public 0399 0400 bool kpDocumentMetaInfoDialog::isNoOp () const 0401 { 0402 return (metaInfo () == *d->originalMetaInfoPtr); 0403 } 0404 0405 //--------------------------------------------------------------------- 0406 0407 // public 0408 kpDocumentMetaInfo kpDocumentMetaInfoDialog::originalMetaInfo () const 0409 { 0410 return *d->originalMetaInfoPtr; 0411 } 0412 0413 // public 0414 kpDocumentMetaInfo kpDocumentMetaInfoDialog::metaInfo ( 0415 QString *errorMessage) const 0416 { 0417 if (errorMessage) 0418 { 0419 // No errors to start with. 0420 *errorMessage = QString (); 0421 } 0422 0423 0424 kpDocumentMetaInfo ret; 0425 0426 0427 if (d->horizDpiInput->value () < ::DpiLegalMin) { 0428 ret.setDotsPerMeterX (0/*unspecified*/); 0429 } 0430 else { 0431 ret.setDotsPerMeterX (qRound (d->horizDpiInput->value () * KP_INCHES_PER_METER)); 0432 } 0433 0434 if (d->vertDpiInput->value () < ::DpiLegalMin) { 0435 ret.setDotsPerMeterY (0/*unspecified*/); 0436 } 0437 else { 0438 ret.setDotsPerMeterY (qRound (d->vertDpiInput->value () * KP_INCHES_PER_METER)); 0439 } 0440 0441 0442 ret.setOffset (QPoint (d->horizOffsetInput->value (), 0443 d->vertOffsetInput->value ())); 0444 0445 0446 for (int r = 0; r < d->fieldsTableWidget->rowCount (); r++) 0447 { 0448 const QString key = d->fieldsTableWidget->item (r, 0)->text (); 0449 const QString value = d->fieldsTableWidget->item (r, 1)->text (); 0450 0451 // Empty key? 0452 if (key.isEmpty ()) 0453 { 0454 // Empty value too? 0455 if (value.isEmpty ()) 0456 { 0457 // Ignore empty row. 0458 continue; 0459 } 0460 // Value without a key? 0461 0462 0463 if (errorMessage) 0464 { 0465 *errorMessage = 0466 ki18n ("The text value \"%1\" on line %2 requires a key.") 0467 .subs (value).subs (r + 1/*count from 1*/).toString (); 0468 0469 // Print only 1 error message per method invocation. 0470 errorMessage = nullptr; 0471 } 0472 0473 // Ignore. 0474 continue; 0475 0476 } 0477 0478 // Duplicate key? 0479 if (ret.textKeys ().contains (key)) 0480 { 0481 if (errorMessage) 0482 { 0483 int q; 0484 for (q = 0; q < r; q++) 0485 { 0486 if (d->fieldsTableWidget->item (q, 0)->text () == key) { 0487 break; 0488 } 0489 } 0490 Q_ASSERT (q != r); 0491 0492 *errorMessage = 0493 ki18n ("All text keys must be unique. The text key \"%1\"" 0494 " on lines %2 and %3 are identical.") 0495 .subs (key) 0496 .subs (q + 1/*count from 1*/) 0497 .subs (r + 1/*count from 1*/) 0498 .toString (); 0499 0500 // Print only 1 error message per method invocation. 0501 errorMessage = nullptr; 0502 } 0503 0504 // Ignore this duplicate - keep the first value of the key. 0505 continue; 0506 } 0507 0508 ret.setText (key, value); 0509 0510 } // for (r = 0; r < table widget rows; r++) { 0511 0512 0513 return ret; 0514 } 0515 0516 0517 // private 0518 void kpDocumentMetaInfoDialog::fieldsUpdateVerticalHeader () 0519 { 0520 QStringList vertLabels; 0521 for (int r = 1; r <= d->fieldsTableWidget->rowCount (); r++) { 0522 vertLabels << QString::number (r); 0523 } 0524 0525 d->fieldsTableWidget->setVerticalHeaderLabels (vertLabels); 0526 } 0527 0528 0529 // private 0530 void kpDocumentMetaInfoDialog::fieldsAddEmptyRow (int atRow) 0531 { 0532 // Block itemChanged() signal as slotFieldsItemChanged() should not get called 0533 // when rows are half-created. 0534 const bool b = d->fieldsTableWidget->blockSignals (true); 0535 { 0536 d->fieldsTableWidget->insertRow (atRow); 0537 0538 d->fieldsTableWidget->setItem (atRow, 0, new QTableWidgetItem (QString ())); 0539 d->fieldsTableWidget->setItem (atRow, 1, new QTableWidgetItem (QString ())); 0540 } 0541 d->fieldsTableWidget->blockSignals (b); 0542 0543 // Hack around Qt's failure to redraw these sometimes. 0544 fieldsUpdateVerticalHeader (); 0545 0546 enableFieldsDeleteRowButtonIfShould (); 0547 } 0548 0549 // private 0550 void kpDocumentMetaInfoDialog::fieldsAppendEmptyRow () 0551 { 0552 fieldsAddEmptyRow (d->fieldsTableWidget->rowCount ()); 0553 } 0554 0555 0556 // private 0557 bool kpDocumentMetaInfoDialog::isFieldsRowDeleteable (int row) const 0558 { 0559 // Can't delete no row and can't delete last (always blank) row, which 0560 // is used to make it easy for the user to add rows without pressing 0561 // the "Add" button explicitly. 0562 return (row >= 0 && row < d->fieldsTableWidget->rowCount () - 1); 0563 } 0564 0565 // private 0566 void kpDocumentMetaInfoDialog::fieldsDeleteRow (int r) 0567 { 0568 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0569 qCDebug(kpLogDialogs) << "kpDocumentMetaInfoDialog::fieldsDeleteRow(" 0570 << "row=" << r << ")" 0571 << " currentRow=" << d->fieldsTableWidget->currentRow (); 0572 #endif 0573 0574 Q_ASSERT (isFieldsRowDeleteable (r)); 0575 0576 if (r == d->fieldsTableWidget->currentRow ()) 0577 { 0578 // Assertion follows from previous assertion. 0579 const int newRow = r + 1; 0580 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0581 qCDebug(kpLogDialogs) << "\tnewRow=" << newRow; 0582 #endif 0583 Q_ASSERT (newRow < d->fieldsTableWidget->rowCount ()); 0584 0585 int newCol = d->fieldsTableWidget->currentColumn (); 0586 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0587 qCDebug(kpLogDialogs) << "\tnewCol=" << newCol; 0588 #endif 0589 if (newCol != 0 && newCol != 1) 0590 { 0591 newCol = 0; 0592 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0593 qCDebug(kpLogDialogs) << "\t\tcorrecting to " << newCol; 0594 #endif 0595 } 0596 0597 // WARNING: You must call this _before_ deleting the row. Else, you'll 0598 // trigger a Qt bug where if the editor is active on the row to 0599 // be deleted, it might crash. To reproduce, move this line to 0600 // after removeRow() (and subtract 1 from newRow) and 0601 // press the "Delete Row" button several times in succession 0602 // very quickly. 0603 // 0604 // TODO: This usually results in a redraw error if the scrollbar scrolls 0605 // after deleting the 2nd last row. Qt bug. 0606 editCell (newRow, newCol); 0607 } 0608 0609 0610 d->fieldsTableWidget->removeRow (r); 0611 0612 0613 fieldsUpdateVerticalHeader (); 0614 0615 enableFieldsDeleteRowButtonIfShould (); 0616 } 0617 0618 0619 // private 0620 void kpDocumentMetaInfoDialog::enableFieldsDeleteRowButtonIfShould () 0621 { 0622 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0623 qCDebug(kpLogDialogs) << "kpDocumentMetaInfoDialog::enableFieldsDeleteRowButtonIfShould()"; 0624 #endif 0625 0626 const int r = d->fieldsTableWidget->currentRow (); 0627 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0628 qCDebug(kpLogDialogs) << "\tr=" << r; 0629 #endif 0630 0631 d->fieldsDeleteRowButton->setEnabled (isFieldsRowDeleteable (r)); 0632 } 0633 0634 0635 // private slot 0636 void kpDocumentMetaInfoDialog::slotFieldsCurrentCellChanged (int row, int col, 0637 int oldRow, int oldCol) 0638 { 0639 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0640 qCDebug(kpLogDialogs) << "kpDocumentMetaInfoDialog::slotFieldsCurrentCellChanged(" 0641 << "row=" << row << ",col=" << col 0642 << ",oldRow=" << oldRow << ",oldCol=" << oldCol 0643 << ")" << endl; 0644 #endif 0645 0646 (void) row; 0647 (void) col; 0648 (void) oldRow; 0649 (void) oldCol; 0650 0651 enableFieldsDeleteRowButtonIfShould (); 0652 } 0653 0654 //--------------------------------------------------------------------- 0655 // private slot 0656 0657 void kpDocumentMetaInfoDialog::slotFieldsItemChanged (QTableWidgetItem *it) 0658 { 0659 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0660 qCDebug(kpLogDialogs) << "kpDocumentMetaInfoDialog::slotFieldsItemChanged(" 0661 << "item=" << it << ") rows=" << d->fieldsTableWidget->rowCount (); 0662 #endif 0663 0664 const int r = d->fieldsTableWidget->row (it); 0665 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0666 qCDebug(kpLogDialogs) << "\tr=" << r; 0667 #endif 0668 Q_ASSERT (r >= 0 && r < d->fieldsTableWidget->rowCount ()); 0669 0670 const QString key = d->fieldsTableWidget->item (r, 0)->text (); 0671 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0672 qCDebug(kpLogDialogs) << " key='" << key << "'"; 0673 #endif 0674 0675 const QString value = d->fieldsTableWidget->item (r, 1)->text (); 0676 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0677 qCDebug(kpLogDialogs) << " value='" << value << "'"; 0678 #endif 0679 0680 // At the last row? 0681 if (r == d->fieldsTableWidget->rowCount () - 1) 0682 { 0683 // Typed some text? 0684 if (!key.isEmpty () || !value.isEmpty ()) 0685 { 0686 // LOTODO: If we're called due to the cell's text being finalized 0687 // as a result of the user pressing the "Add Row" button, 0688 // should this really append a row since 0689 // slotFieldsAddRowButtonClicked() button is going to add 0690 // another one? That's two rows when the user only clicked 0691 // that button once! 0692 fieldsAppendEmptyRow (); 0693 } 0694 } 0695 } 0696 0697 //--------------------------------------------------------------------- 0698 // private slot 0699 0700 void kpDocumentMetaInfoDialog::slotFieldsAddRowButtonClicked () 0701 { 0702 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0703 qCDebug(kpLogDialogs) << "kpDocumentMetaInfoDialog::slotFieldsAddRowButtonClicked()"; 0704 #endif 0705 0706 const int r = d->fieldsTableWidget->currentRow (); 0707 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0708 qCDebug(kpLogDialogs) << "\tr=" << r; 0709 #endif 0710 0711 // (if no row is selected, r = -1) 0712 fieldsAddEmptyRow (r + 1); 0713 0714 // Edit the key of this new row (column 0). 0715 // No one edits the value first (column 1). 0716 editCell ((r + 1)/*row*/, 0/*col*/); 0717 } 0718 0719 //--------------------------------------------------------------------- 0720 0721 // private slot 0722 void kpDocumentMetaInfoDialog::slotFieldsDeleteRowButtonClicked () 0723 { 0724 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0725 qCDebug(kpLogDialogs) << "kpDocumentMetaInfoDialog::slotFieldsDeleteRowButtonClicked()"; 0726 #endif 0727 0728 const int r = d->fieldsTableWidget->currentRow (); 0729 #if DEBUG_KP_DOCUMENT_META_INFO_DIALOG 0730 qCDebug(kpLogDialogs) << "\tr=" << r; 0731 #endif 0732 0733 Q_ASSERT (isFieldsRowDeleteable (r)); 0734 fieldsDeleteRow (r); 0735 } 0736 0737 0738 // private slot virtual [base QDialog] 0739 void kpDocumentMetaInfoDialog::accept () 0740 { 0741 // Validate text fields. 0742 QString errorMessage; 0743 (void) metaInfo (&errorMessage); 0744 if (!errorMessage.isEmpty ()) 0745 { 0746 KMessageBox::error (this, errorMessage, i18nc ("@title:window", "Invalid Text Fields")); 0747 return; 0748 } 0749 0750 QDialog::accept (); 0751 } 0752 0753 #include "moc_kpDocumentMetaInfoDialog.cpp"