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"