File indexing completed on 2024-04-21 05:51:36
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 "compoundwidget.h" 0008 0009 #include <QCheckBox> 0010 #include <QDialog> 0011 #include <QDialogButtonBox> 0012 #include <QLabel> 0013 #include <QLineEdit> 0014 #include <QMouseEvent> 0015 #include <QPainter> 0016 #include <QPushButton> 0017 #include <QVBoxLayout> 0018 0019 #include <KIconLoader> 0020 #include <KLocalizedString> 0021 #include <KTextEdit> 0022 0023 #include "compoundregexp.h" 0024 #include "concwidget.h" 0025 #include "kwidgetstreamer.h" 0026 0027 //================================================================================ 0028 0029 CompoundDetailWindow::CompoundDetailWindow(QWidget *parent) 0030 : QWidget(parent) 0031 { 0032 QVBoxLayout *layout = new QVBoxLayout(this); 0033 layout->setContentsMargins(0, 0, 0, 0); 0034 0035 QLabel *label = new QLabel(i18n("&Title:"), this); 0036 layout->addWidget(label); 0037 _title = new QLineEdit(this); 0038 layout->addWidget(_title); 0039 label->setBuddy(_title); 0040 0041 label = new QLabel(i18n("&Description:"), this); 0042 layout->addWidget(label); 0043 _description = new KTextEdit(this); 0044 layout->addWidget(_description); 0045 label->setBuddy(_description); 0046 0047 _allowReplace = new QCheckBox(i18n("&Automatically replace using this item"), this); 0048 layout->addWidget(_allowReplace); 0049 _allowReplace->setToolTip( 0050 i18n("When the content of this box is typed in to the ASCII line,<br />" 0051 "this box will automatically be added around it,<br />" 0052 "if this check box is selected.")); 0053 _allowReplace->setChecked(true); 0054 0055 _title->setFocus(); 0056 } 0057 0058 QString CompoundDetailWindow::title() const 0059 { 0060 return _title->text(); 0061 } 0062 0063 QString CompoundDetailWindow::description() const 0064 { 0065 return _description->toPlainText(); 0066 } 0067 0068 bool CompoundDetailWindow::allowReplace() const 0069 { 0070 return _allowReplace->isChecked(); 0071 } 0072 0073 void CompoundDetailWindow::setTitle(const QString &txt) 0074 { 0075 _title->setText(txt); 0076 } 0077 0078 void CompoundDetailWindow::setDescription(const QString &txt) 0079 { 0080 _description->setText(txt); 0081 } 0082 0083 void CompoundDetailWindow::setAllowReplace(bool b) 0084 { 0085 _allowReplace->setChecked(b); 0086 } 0087 0088 //================================================================================ 0089 0090 CompoundWidget::CompoundWidget(RegExpEditorWindow *editorWindow, QWidget *parent) 0091 : SingleContainerWidget(editorWindow, parent) 0092 { 0093 _child = new ConcWidget(editorWindow, this); 0094 init(); 0095 } 0096 0097 CompoundWidget::CompoundWidget(CompoundRegExp *regexp, RegExpEditorWindow *editorWindow, QWidget *parent) 0098 : SingleContainerWidget(editorWindow, parent) 0099 { 0100 init(); 0101 _content->setTitle(regexp->title()); 0102 _content->setDescription(regexp->description()); 0103 _content->setAllowReplace(regexp->allowReplace()); 0104 RegExpWidget *child = WidgetFactory::createWidget(regexp->child(), _editorWindow, this); 0105 if (!(_child = dynamic_cast<ConcWidget *>(child))) { 0106 _child = new ConcWidget(_editorWindow, child, this); 0107 } 0108 0109 _hidden = regexp->hidden(); 0110 } 0111 0112 void CompoundWidget::init() 0113 { 0114 _configWindow = new QDialog(this); 0115 _configWindow->setWindowTitle(i18n("Configure Compound")); 0116 0117 QVBoxLayout *mainLayout = new QVBoxLayout; 0118 _configWindow->setLayout(mainLayout); 0119 0120 _content = new CompoundDetailWindow(_configWindow); 0121 mainLayout->addWidget(_content); 0122 0123 connect(_configWindow, &QDialog::rejected, this, &CompoundWidget::slotConfigCanceled); 0124 connect(_configWindow, &QDialog::finished, this, &CompoundWidget::slotConfigWindowClosed); 0125 0126 _down = getIcon(QStringLiteral("arrow-down")); 0127 _up = getIcon(QStringLiteral("arrow-up")); 0128 0129 _hidden = false; 0130 _backRefId = -1; 0131 0132 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0133 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0134 okButton->setDefault(true); 0135 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0136 _configWindow->connect(buttonBox, &QDialogButtonBox::accepted, _configWindow, &QDialog::accept); 0137 _configWindow->connect(buttonBox, &QDialogButtonBox::rejected, _configWindow, &QDialog::reject); 0138 mainLayout->addWidget(buttonBox); 0139 } 0140 0141 QSize CompoundWidget::sizeHint() const 0142 { 0143 QFontMetrics metrics = fontMetrics(); 0144 _childSize = _child->sizeHint(); 0145 _textSize = metrics.size(0, _content->title()); 0146 0147 int width, height; 0148 0149 if (_hidden) { 0150 _pixmapSize = _up.size(); 0151 width = 2 * pw + qMax(2 * bdSize + _textSize.width(), 2 * bdSize + _pixmapSize.width()); 0152 height = _pixmapSize.height() + 2 * bdSize + _textSize.height() + pw; 0153 } else { 0154 _pixmapSize = _down.size(); 0155 int headerLineWidth = 2 * pw + 2 * bdSize + _pixmapSize.width(); 0156 if (_textSize.width() != 0) { 0157 headerLineWidth += 3 * bdSize + _textSize.width(); 0158 } 0159 0160 width = qMax(2 * pw + _childSize.width(), headerLineWidth); 0161 height = qMax(_textSize.height(), _pixmapSize.height()) + 2 * bdSize + _childSize.height() + pw; 0162 } 0163 return QSize(width, height); 0164 } 0165 0166 void CompoundWidget::paintEvent(QPaintEvent *e) 0167 { 0168 QSize mySize = sizeHint(); 0169 0170 QPainter painter(this); 0171 drawPossibleSelection(painter, mySize); 0172 0173 int horLineY, childY; 0174 0175 // draw top line 0176 if (_hidden) { 0177 horLineY = _pixmapSize.height() / 2; 0178 childY = _pixmapSize.height() + bdSize; 0179 _pixmapPos = QPoint(mySize.width() - pw - bdSize - _pixmapSize.width(), 0); 0180 painter.drawLine(pw, horLineY, _pixmapPos.x(), horLineY); 0181 painter.drawLine(mySize.width() - bdSize - pw, horLineY, mySize.width(), horLineY); 0182 painter.drawPixmap(_pixmapPos, _up); 0183 } else { 0184 int maxH = qMax(_textSize.height(), _pixmapSize.height()); 0185 int offset = 0; 0186 horLineY = maxH / 2; 0187 childY = maxH + bdSize; 0188 0189 painter.drawLine(pw, horLineY, bdSize, horLineY); 0190 if (_textSize.width() != 0) { 0191 offset += pw + 2 * bdSize; 0192 0193 painter.drawText(offset, horLineY - _textSize.height() / 2, bdSize + _textSize.width(), horLineY + _textSize.height() / 2, 0, _content->title()); 0194 offset += _textSize.width() + bdSize; 0195 } 0196 0197 _pixmapPos = QPoint(mySize.width() - pw - bdSize - _pixmapSize.width(), horLineY - _pixmapSize.height() / 2); 0198 0199 painter.drawLine(offset, horLineY, _pixmapPos.x(), horLineY); 0200 painter.drawPixmap(_pixmapPos, _down); 0201 0202 painter.drawLine(mySize.width() - bdSize - pw, horLineY, mySize.width(), horLineY); 0203 } 0204 0205 // draw rest frame 0206 painter.drawLine(0, horLineY, 0, mySize.height()); 0207 painter.drawLine(mySize.width() - pw, horLineY, mySize.width() - pw, mySize.height()); 0208 painter.drawLine(0, mySize.height() - pw, mySize.width(), mySize.height() - pw); 0209 0210 // place/size child 0211 if (_hidden) { 0212 _child->hide(); 0213 painter.drawText(pw + bdSize, childY, pw + bdSize + _textSize.width(), childY + _textSize.height(), 0, _content->title()); 0214 } else { 0215 QSize curSize = _child->size(); 0216 QSize newSize = QSize(qMax(_child->sizeHint().width(), mySize.width() - 2 * pw), _child->sizeHint().height()); 0217 0218 _child->move(pw, childY); 0219 if (curSize != newSize) { 0220 _child->resize(newSize); 0221 // I resized the child, so give it a chance to relect thus. 0222 _child->update(); 0223 } 0224 0225 _child->show(); 0226 } 0227 0228 RegExpWidget::paintEvent(e); 0229 } 0230 0231 void CompoundWidget::slotConfigWindowClosed() 0232 { 0233 _editorWindow->updateContent(nullptr); 0234 update(); 0235 } 0236 0237 void CompoundWidget::slotConfigCanceled() 0238 { 0239 QDataStream stream(&_backup, QIODevice::ReadOnly); 0240 0241 stream.setVersion(QDataStream::Qt_3_1); 0242 KWidgetStreamer streamer; 0243 streamer.fromStream(stream, _content); 0244 repaint(); 0245 } 0246 0247 RegExp *CompoundWidget::regExp() const 0248 { 0249 return new CompoundRegExp(isSelected(), _content->title(), _content->description(), _hidden, _content->allowReplace(), _child->regExp()); 0250 } 0251 0252 void CompoundWidget::mousePressEvent(QMouseEvent *event) 0253 { 0254 if (event->button() == Qt::LeftButton && QRect(_pixmapPos, _pixmapSize).contains(event->pos())) { 0255 // Skip otherwise we will never see the mouse release 0256 // since it is eaten by Editor window. 0257 } else { 0258 SingleContainerWidget::mousePressEvent(event); 0259 } 0260 } 0261 0262 void CompoundWidget::mouseReleaseEvent(QMouseEvent *event) 0263 { 0264 if (event->button() == Qt::LeftButton && QRect(_pixmapPos, _pixmapSize).contains(event->pos())) { 0265 _hidden = !_hidden; 0266 _editorWindow->updateContent(nullptr); 0267 repaint(); // is this necesary? 0268 _editorWindow->emitChange(); 0269 } else { 0270 SingleContainerWidget::mouseReleaseEvent(event); 0271 } 0272 } 0273 0274 bool CompoundWidget::updateSelection(bool parentSelected) 0275 { 0276 if (_hidden) { 0277 bool changed = RegExpWidget::updateSelection(parentSelected); 0278 _child->selectWidget(_isSelected); 0279 if (changed) { 0280 repaint(); 0281 } 0282 return changed; 0283 } else { 0284 return SingleContainerWidget::updateSelection(parentSelected); 0285 } 0286 } 0287 0288 int CompoundWidget::edit() 0289 { 0290 _configWindow->move(QCursor::pos() - QPoint(_configWindow->sizeHint().width() / 2, _configWindow->sizeHint().height() / 2)); 0291 QDataStream stream(&_backup, QIODevice::WriteOnly); 0292 0293 stream.setVersion(QDataStream::Qt_3_1); 0294 KWidgetStreamer streamer; 0295 streamer.toStream(_content, stream); 0296 return _configWindow->exec(); 0297 } 0298 0299 int nextId() 0300 { 0301 static int counter = 0; 0302 return ++counter; 0303 } 0304 0305 QPixmap CompoundWidget::getIcon(const QString &name) 0306 { 0307 return QIcon::fromTheme(name).pixmap(KIconLoader::SizeSmall); 0308 } 0309 0310 #include "moc_compoundwidget.cpp"