File indexing completed on 2024-04-14 05:44:26
0001 /* 0002 * SPDX-FileCopyrightText: 2002-2003 Jesper K. Pedersen <blackie@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-only 0005 **/ 0006 0007 #include "repeatwidget.h" 0008 0009 #include <QButtonGroup> 0010 #include <QGroupBox> 0011 #include <QLabel> 0012 #include <QPainter> 0013 #include <QRadioButton> 0014 #include <QSpinBox> 0015 #include <QVBoxLayout> 0016 0017 #include <KLocalizedString> 0018 #include <QDialog> 0019 #include <QDialogButtonBox> 0020 #include <QPushButton> 0021 0022 #include "concwidget.h" 0023 #include "kwidgetstreamer.h" 0024 #include "repeatregexp.h" 0025 0026 RepeatWidget::RepeatWidget(RegExpEditorWindow *editorWindow, QWidget *parent) 0027 : SingleContainerWidget(editorWindow, parent) 0028 { 0029 _child = new ConcWidget(editorWindow, this); 0030 init(); 0031 } 0032 0033 RepeatWidget::RepeatWidget(RepeatRegExp *regexp, RegExpEditorWindow *editorWindow, QWidget *parent) 0034 : SingleContainerWidget(editorWindow, parent) 0035 { 0036 init(); 0037 RegExpWidget *child = WidgetFactory::createWidget(regexp->child(), editorWindow, this); 0038 if (!(_child = dynamic_cast<ConcWidget *>(child))) { 0039 _child = new ConcWidget(editorWindow, child, this); 0040 } 0041 0042 if (regexp->max() == -1) { 0043 if (regexp->min() == 0) { 0044 _content->set(RepeatRangeWindow::ANY, regexp->min(), regexp->max()); 0045 } else { 0046 _content->set(RepeatRangeWindow::ATLEAST, regexp->min(), regexp->max()); // krazy:exclude=spelling 0047 } 0048 } else { 0049 if (regexp->min() == 0) { 0050 _content->set(RepeatRangeWindow::ATMOST, regexp->min(), regexp->max()); 0051 } else if (regexp->min() == regexp->max()) { 0052 _content->set(RepeatRangeWindow::EXACTLY, regexp->min(), regexp->max()); 0053 } else { 0054 _content->set(RepeatRangeWindow::MINMAX, regexp->min(), regexp->max()); 0055 } 0056 } 0057 } 0058 0059 void RepeatWidget::init() 0060 { 0061 _configWindow = new QDialog(this); 0062 _configWindow->setWindowTitle(i18n("Number of Times to Repeat Content")); 0063 QVBoxLayout *mainLayout = new QVBoxLayout; 0064 _configWindow->setLayout(mainLayout); 0065 0066 _content = new RepeatRangeWindow(_configWindow); 0067 connect(_configWindow, &QDialog::rejected, this, &RepeatWidget::slotConfigCanceled); 0068 connect(_configWindow, &QDialog::finished, this, &RepeatWidget::slotConfigWindowClosed); 0069 mainLayout->addWidget(_content); 0070 0071 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0072 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0073 okButton->setDefault(true); 0074 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0075 mainLayout->addWidget(buttonBox); 0076 _configWindow->connect(buttonBox, &QDialogButtonBox::accepted, _configWindow, &QDialog::accept); 0077 _configWindow->connect(buttonBox, &QDialogButtonBox::rejected, _configWindow, &QDialog::reject); 0078 } 0079 0080 QSize RepeatWidget::sizeHint() const 0081 { 0082 // TODO: Merge with LookAheadWidget::sizeHint 0083 QFontMetrics metrics = fontMetrics(); 0084 _textSize = metrics.size(0, _content->text()); 0085 0086 _childSize = _child->sizeHint(); 0087 0088 int height = _textSize.height() + bdSize + _childSize.height() + bdSize + 2 * pw; 0089 int width = 2 * pw + qMax(_childSize.width(), 4 * bdSize + _textSize.width()); 0090 return QSize(width, height); 0091 } 0092 0093 void RepeatWidget::paintEvent(QPaintEvent *e) 0094 { 0095 // TODO: Merge with LookAheadWidget::paintEvent 0096 QSize mySize = sizeHint(); 0097 QPainter painter(this); 0098 0099 drawPossibleSelection(painter, mySize); 0100 0101 // move the child to its position and resize it. 0102 _child->move(pw, _textSize.height() + bdSize); 0103 QSize curChildSize = _child->size(); 0104 QSize newChildSize = QSize(mySize.width() - 2 * pw, _childSize.height()); 0105 if (curChildSize != newChildSize) { 0106 _child->resize(newChildSize); 0107 // I resized the child, so give it a chance to relect thus. 0108 _child->update(); 0109 } 0110 0111 // Draw the border and the text. 0112 int startY = _textSize.height() / 2; 0113 0114 // Top lines and text 0115 painter.drawLine(pw, startY, bdSize, startY); 0116 painter.drawText(pw + 2 * bdSize, 0, _textSize.width(), _textSize.height(), 0, _content->text()); 0117 int offset = pw + 3 * bdSize + _textSize.width(); 0118 painter.drawLine(offset, startY, mySize.width() - pw, startY); 0119 0120 // horizontal lines 0121 painter.drawLine(0, startY, 0, mySize.height() - pw); 0122 painter.drawLine(mySize.width() - pw, startY, mySize.width() - pw, mySize.height() - pw); 0123 0124 // buttom line 0125 painter.drawLine(0, mySize.height() - pw, mySize.width() - pw, mySize.height() - pw); 0126 0127 SingleContainerWidget::paintEvent(e); 0128 } 0129 0130 RegExp *RepeatWidget::regExp() const 0131 { 0132 return new RepeatRegExp(isSelected(), _content->min(), _content->max(), _child->regExp()); 0133 } 0134 0135 void RepeatWidget::slotConfigWindowClosed() 0136 { 0137 _editorWindow->updateContent(nullptr); 0138 update(); 0139 } 0140 0141 void RepeatWidget::slotConfigCanceled() 0142 { 0143 QDataStream stream(&_backup, QIODevice::ReadOnly); 0144 0145 stream.setVersion(QDataStream::Qt_3_1); 0146 KWidgetStreamer streamer; 0147 streamer.fromStream(stream, _content); 0148 repaint(); 0149 } 0150 0151 int RepeatWidget::edit() 0152 { 0153 _configWindow->move(QCursor::pos() - QPoint(_configWindow->sizeHint().width() / 2, _configWindow->sizeHint().height() / 2)); 0154 QDataStream stream(&_backup, QIODevice::WriteOnly); 0155 0156 stream.setVersion(QDataStream::Qt_3_1); 0157 KWidgetStreamer streamer; 0158 streamer.toStream(_content, stream); 0159 0160 return _configWindow->exec(); 0161 } 0162 0163 //-------------------------------------------------------------------------------- 0164 RepeatRangeWindow::RepeatRangeWindow(QWidget *parent) 0165 : QWidget(parent) 0166 { 0167 QVBoxLayout *mainLayout = new QVBoxLayout(this); 0168 mainLayout->setContentsMargins(0, 0, 0, 0); 0169 0170 _groupWidget = new QGroupBox(i18n("Times to Match")); 0171 mainLayout->addWidget(_groupWidget); 0172 _group = new QButtonGroup(this); 0173 0174 QGridLayout *groupLayout = new QGridLayout(_groupWidget); 0175 0176 // Any number of times 0177 QRadioButton *radioBut = new QRadioButton(i18n("Any number of times (including zero times)")); 0178 radioBut->setObjectName(QStringLiteral("RepeatRangeWindow::choice any times")); 0179 0180 groupLayout->addWidget(radioBut, 0, 0, 1, 3); 0181 _group->addButton(radioBut, ANY); 0182 radioBut->click(); 0183 0184 createLine(groupLayout, i18n("At least"), &_leastTimes, ATLEAST); // krazy:exclude=spelling 0185 createLine(groupLayout, i18n("At most"), &_mostTimes, ATMOST); 0186 createLine(groupLayout, i18n("Exactly"), &_exactlyTimes, EXACTLY); 0187 0188 // from ___ to ___ times 0189 radioBut = new QRadioButton(i18n("From")); 0190 radioBut->setObjectName(QStringLiteral("RepeatRangeWindow::from")); 0191 groupLayout->addWidget(radioBut, 4, 0); 0192 _group->addButton(radioBut, MINMAX); 0193 0194 _rangeFrom = new QSpinBox(); 0195 _rangeFrom->setRange(1, 999); 0196 _rangeFrom->setSingleStep(1); 0197 groupLayout->addWidget(_rangeFrom, 4, 1); 0198 0199 QHBoxLayout *layout = new QHBoxLayout(); 0200 0201 QLabel *label = new QLabel(i18n("to")); 0202 layout->addWidget(label); 0203 0204 _rangeTo = new QSpinBox(); 0205 _rangeTo->setRange(1, 999); 0206 _rangeTo->setSingleStep(1); 0207 layout->addWidget(_rangeTo); 0208 0209 label = new QLabel(i18n("time(s)")); 0210 layout->addWidget(label); 0211 0212 groupLayout->addLayout(layout, 4, 2); 0213 0214 connect(_rangeFrom, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateMaxVal(int))); 0215 connect(_rangeTo, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateMinVal(int))); 0216 0217 connect(_group, &QButtonGroup::idClicked, this, &RepeatRangeWindow::slotItemChange); 0218 0219 _group->button(ANY)->click(); 0220 } 0221 0222 void RepeatRangeWindow::createLine(QGridLayout *layout, const QString &text, QSpinBox **spin, REPEATTYPE tp) 0223 { 0224 int row = layout->rowCount(); 0225 0226 QRadioButton *radioBut = new QRadioButton(text); 0227 layout->addWidget(radioBut, row, 0); 0228 0229 *spin = new QSpinBox(); 0230 (*spin)->setRange(1, 999); 0231 (*spin)->setSingleStep(1); 0232 (*spin)->setValue(1); 0233 layout->addWidget(*spin, row, 1); 0234 0235 QLabel *label = new QLabel(i18n("time(s)")); 0236 layout->addWidget(label, row, 2, 1, 2); 0237 _group->addButton(radioBut, tp); 0238 } 0239 0240 void RepeatRangeWindow::slotItemChange(int which) 0241 { 0242 _leastTimes->setEnabled(false); 0243 _mostTimes->setEnabled(false); 0244 _exactlyTimes->setEnabled(false); 0245 _rangeFrom->setEnabled(false); 0246 _rangeTo->setEnabled(false); 0247 0248 switch (which) { 0249 case ANY: 0250 break; 0251 case ATLEAST: 0252 _leastTimes->setEnabled(true); 0253 break; // krazy:exclude=spelling 0254 case ATMOST: 0255 _mostTimes->setEnabled(true); 0256 break; 0257 case EXACTLY: 0258 _exactlyTimes->setEnabled(true); 0259 break; 0260 case MINMAX: 0261 _rangeFrom->setEnabled(true); 0262 _rangeTo->setEnabled(true); 0263 break; 0264 } 0265 } 0266 0267 void RepeatRangeWindow::slotUpdateMinVal(int maxVal) 0268 { 0269 if (_rangeFrom->value() > maxVal) { 0270 _rangeFrom->setValue(maxVal); 0271 } 0272 } 0273 0274 void RepeatRangeWindow::slotUpdateMaxVal(int minVal) 0275 { 0276 if (_rangeTo->value() < minVal) { 0277 _rangeTo->setValue(minVal); 0278 } 0279 } 0280 0281 QString RepeatRangeWindow::text() 0282 { 0283 switch (_group->checkedId()) { 0284 case ANY: 0285 return i18n("Repeated Any Number of Times"); 0286 case ATLEAST: 0287 return i18np("Repeated at Least 1 Time", "Repeated at Least %1 Times", _leastTimes->value()); // krazy:exclude=spelling 0288 case ATMOST: 0289 return i18np("Repeated at Most 1 Time", "Repeated at Most %1 Times", _mostTimes->value()); 0290 case EXACTLY: 0291 return i18np("Repeated Exactly 1 Time", "Repeated Exactly %1 Times", _exactlyTimes->value()); 0292 case MINMAX: 0293 return i18n("Repeated From %1 to %2 Times", _rangeFrom->value(), _rangeTo->value()); 0294 } 0295 0296 qFatal("Fall through!"); 0297 return QString(); 0298 } 0299 0300 int RepeatRangeWindow::min() 0301 { 0302 switch (_group->checkedId()) { 0303 case ANY: 0304 return 0; 0305 case ATLEAST: 0306 return _leastTimes->value(); // krazy:exclude=spelling 0307 case ATMOST: 0308 return 0; 0309 case EXACTLY: 0310 return _exactlyTimes->value(); 0311 case MINMAX: 0312 return _rangeFrom->value(); 0313 } 0314 qFatal("Fall through!"); 0315 return -1; 0316 } 0317 0318 int RepeatRangeWindow::max() 0319 { 0320 switch (_group->checkedId()) { 0321 case ANY: 0322 return -1; 0323 case ATLEAST: 0324 return -1; // krazy:exclude=spelling 0325 case ATMOST: 0326 return _mostTimes->value(); 0327 case EXACTLY: 0328 return _exactlyTimes->value(); 0329 case MINMAX: 0330 return _rangeTo->value(); 0331 } 0332 qFatal("Fall through!"); 0333 return -1; 0334 } 0335 0336 void RepeatRangeWindow::set(REPEATTYPE tp, int min, int max) 0337 { 0338 _group->button(tp)->click(); 0339 switch (tp) { 0340 case ANY: 0341 break; 0342 case ATLEAST: // krazy:exclude=spelling 0343 _leastTimes->setValue(min); 0344 break; 0345 case ATMOST: 0346 _mostTimes->setValue(max); 0347 break; 0348 case EXACTLY: 0349 _exactlyTimes->setValue(min); 0350 break; 0351 case MINMAX: 0352 _rangeFrom->setValue(min); 0353 _rangeTo->setValue(max); 0354 break; 0355 } 0356 } 0357 0358 #include "moc_repeatwidget.cpp"