File indexing completed on 2024-04-28 09:47:01
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 "altnwidget.h" 0008 0009 #include <QPaintEvent> 0010 #include <QPainter> 0011 0012 #include <KLocalizedString> 0013 #include <KMessageBox> 0014 0015 #include "altnregexp.h" 0016 #include "concwidget.h" 0017 #include "dragaccepter.h" 0018 0019 AltnWidget::AltnWidget(RegExpEditorWindow *editorWindow, QWidget *parent) 0020 : MultiContainerWidget(editorWindow, parent) 0021 { 0022 DragAccepter *accepter = new DragAccepter(editorWindow, this); 0023 accepter->resize(0, 0); // See note (1) in Comments 0024 _children.append(accepter); 0025 _text = i18n("Alternatives"); 0026 } 0027 0028 AltnWidget::AltnWidget(AltnRegExp *regexp, RegExpEditorWindow *editorWindow, QWidget *parent) 0029 : MultiContainerWidget(editorWindow, parent) 0030 { 0031 DragAccepter *accepter = new DragAccepter(editorWindow, this); 0032 accepter->resize(0, 0); // See note (1) in Comments 0033 _children.append(accepter); 0034 _text = i18n("Alternatives"); 0035 0036 const RegExpList list = regexp->children(); 0037 for (RegExp *r : list) { 0038 RegExpWidget *child = WidgetFactory::createWidget(r, editorWindow, this); 0039 ConcWidget *conc; 0040 if (!(conc = dynamic_cast<ConcWidget *>(child))) { 0041 conc = new ConcWidget(editorWindow, child, parent); 0042 } 0043 append(conc); 0044 } 0045 updateDrawLineInfo(); 0046 } 0047 0048 void AltnWidget::addNewChild(DragAccepter *accepter, RegExpWidget *child) 0049 { 0050 ConcWidget *conc = new ConcWidget(_editorWindow, child, this); 0051 MultiContainerWidget::addNewChild(accepter, conc); 0052 updateDrawLineInfo(); 0053 repaint(); 0054 } 0055 0056 void AltnWidget::setConcChild(ConcWidget *child) 0057 { 0058 addNewConcChild(dynamic_cast<DragAccepter *>(_children.at(0)), child); 0059 } 0060 0061 void AltnWidget::addNewConcChild(DragAccepter *accepter, ConcWidget *child) 0062 { 0063 child->setParent(this); 0064 MultiContainerWidget::addNewChild(accepter, child); 0065 updateDrawLineInfo(); 0066 } 0067 0068 QSize AltnWidget::sizeHint() const 0069 { 0070 QList<RegExpWidget *>::const_iterator it = _children.constBegin(); 0071 // Skip the first child, as we only need half of the size of the first and the 0072 // last drag accepter. Does, however, not apply when there only is onw child. 0073 if (_children.count() != 1) { 0074 ++it; 0075 } 0076 0077 _childrenWidth = 0; 0078 _childrenHeight = 0; 0079 0080 for (; it != _children.constEnd(); ++it) { 0081 QSize thisChildSize = (*it)->sizeHint(); 0082 _childrenWidth = qMax(_childrenWidth, thisChildSize.width()); 0083 _childrenHeight += thisChildSize.height(); 0084 } 0085 0086 // Now add the size of the header 0087 QFontMetrics metrics = fontMetrics(); 0088 _textSize = metrics.size(0, _text); 0089 0090 int headerWidth = _textSize.width() + 2 * bdSize + 2; 0091 0092 _childrenWidth = qMax(_childrenWidth, headerWidth); 0093 0094 return QSize(_childrenWidth + 2 * pw, _childrenHeight + _textSize.height() + 1 * pw); 0095 } 0096 0097 void AltnWidget::paintEvent(QPaintEvent *e) 0098 { 0099 Q_ASSERT(dynamic_cast<DragAccepter *>(_children.at(0))); 0100 // if this fails, then I should check the location of the show() 0101 Q_ASSERT(_children.count() == 1 || (_children.count() >= 3 && dynamic_cast<DragAccepter *>(_children.at(_children.count() - 1)))); 0102 0103 int offset = 0; 0104 QSize mySize = sizeHint(); 0105 0106 QPainter painter(this); 0107 drawPossibleSelection(painter, mySize); 0108 0109 //-------------------------------------- First draw the border and text 0110 int startY = _textSize.height() / 2; 0111 0112 painter.drawLine(0, startY, bdSize, startY); 0113 int xOffset = bdSize + 1; 0114 0115 painter.drawText(xOffset, 0, _textSize.width(), _textSize.height(), 0, _text); 0116 xOffset += _textSize.width() + 1; 0117 painter.drawLine(xOffset, startY, mySize.width(), startY); 0118 painter.drawLine(0, startY, 0, mySize.height()); 0119 painter.drawLine(mySize.width() - pw, startY, mySize.width() - pw, mySize.height()); 0120 painter.drawLine(0, mySize.height() - pw, mySize.width() - pw, mySize.height() - pw); 0121 0122 //---- Run through all the children and place them at the correct location. 0123 offset = _textSize.height(); 0124 xOffset = pw; 0125 0126 for (int i = 0; i < _children.count(); i++) { 0127 RegExpWidget *child = _children.at(i); 0128 0129 QSize childSize = child->sizeHint(); 0130 QSize curChildSize = child->size(); 0131 0132 //-------------------------------------- place the child 0133 int x = xOffset; 0134 int y = offset; 0135 int h = childSize.height(); 0136 if ((_children.count() != 1) && (i == 0 || i == _children.count() - 1)) { 0137 // first and last DragAccepter should only be half size. 0138 h /= 2; 0139 } 0140 0141 int w = _childrenWidth; 0142 child->setGeometry(x, y, w, h); 0143 if (w != curChildSize.width() || h != curChildSize.height()) { 0144 // I resized the child, so give it a chance to relect thus. 0145 child->update(); 0146 } 0147 0148 offset += h; 0149 } 0150 MultiContainerWidget::paintEvent(e); 0151 } 0152 0153 RegExp *AltnWidget::regExp() const 0154 { 0155 AltnRegExp *regexp = new AltnRegExp(isSelected()); 0156 0157 QList<RegExpWidget *>::const_iterator it = _children.constBegin(); 0158 ++it; // start with the second element 0159 for (; it != _children.constEnd(); it += 2) { 0160 regexp->addRegExp((*it)->regExp()); 0161 } 0162 0163 return regexp; 0164 } 0165 0166 void AltnWidget::applyRegExpToSelection(RegExpType type) 0167 { 0168 for (int i = 1; i < _children.count(); i += 2) { 0169 RegExpWidget *child = _children.at(i); 0170 if (child->hasSelection()) { 0171 child->applyRegExpToSelection(type); 0172 } 0173 } 0174 } 0175 0176 RegExp *AltnWidget::selection() const 0177 { 0178 if (isSelected()) { 0179 return regExp(); 0180 } else { 0181 QList<RegExpWidget *>::const_iterator it = _children.constBegin(); 0182 ++it; // Skip past DragAccepter 0183 for (; *it; it += 2) { 0184 if ((*it)->hasSelection()) { 0185 return (*it)->selection(); 0186 } 0187 } 0188 } 0189 qFatal("Selection not found"); 0190 return nullptr; // compiler shut up. 0191 } 0192 0193 bool AltnWidget::validateSelection() const 0194 { 0195 if (_isSelected) { 0196 return true; 0197 } 0198 0199 bool foundASelection = false; 0200 QList<RegExpWidget *>::const_iterator it = _children.constBegin(); 0201 ++it; // Skip past DragAccepter 0202 for (; it != _children.constEnd(); it += 2) { 0203 if ((*it)->hasSelection()) { 0204 if (foundASelection) { 0205 KMessageBox::information(const_cast<AltnWidget *>(this), 0206 i18n("Selecting several alternatives is " 0207 "currently not supported."), 0208 i18n("Selection Invalid")); 0209 _editorWindow->clearSelection(true); 0210 return false; 0211 } else { 0212 foundASelection = true; 0213 } 0214 } 0215 } 0216 return true; 0217 } 0218 0219 void AltnWidget::updateDrawLineInfo() 0220 { 0221 for (int i = 0; i < _children.count(); i += 2) { 0222 bool line = (i != 0 && i != _children.count() - 1); 0223 DragAccepter *accepter = dynamic_cast<DragAccepter *>(_children.at(i)); 0224 if (accepter) { 0225 accepter->setDrawLine(line); 0226 } 0227 } 0228 } 0229 0230 void AltnWidget::deleteSelection() 0231 { 0232 MultiContainerWidget::deleteSelection(); 0233 updateDrawLineInfo(); 0234 }