File indexing completed on 2024-05-12 16:43:55
0001 /* 0002 SPDX-FileCopyrightText: 2015-2018 Thomas Baumgart <tbaumgart@kde.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "widgethintframe.h" 0007 0008 // ---------------------------------------------------------------------------- 0009 // QT Includes 0010 0011 #include <QEvent> 0012 #include <QMoveEvent> 0013 0014 // ---------------------------------------------------------------------------- 0015 // KDE Includes 0016 0017 // ---------------------------------------------------------------------------- 0018 // Project Includes 0019 0020 class WidgetHintFrameCollection::Private 0021 { 0022 public: 0023 QList<QWidget*> widgetList; 0024 QList<WidgetHintFrame*> frameList; 0025 }; 0026 0027 WidgetHintFrameCollection::WidgetHintFrameCollection(QObject* parent) 0028 : QObject(parent) 0029 , d(new Private) 0030 { 0031 } 0032 0033 WidgetHintFrameCollection::~WidgetHintFrameCollection() 0034 { 0035 delete d; 0036 } 0037 0038 void WidgetHintFrameCollection::addFrame(WidgetHintFrame* frame) 0039 { 0040 if(!d->frameList.contains(frame)) { 0041 connect(frame, &QObject::destroyed, this, &WidgetHintFrameCollection::frameDestroyed); 0042 connect(frame, &WidgetHintFrame::changed, this, [=] { QMetaObject::invokeMethod(this, "updateWidgets", Qt::QueuedConnection); }); 0043 d->frameList.append(frame); 0044 } 0045 } 0046 0047 void WidgetHintFrameCollection::addWidget(QWidget* w) 0048 { 0049 if(!d->widgetList.contains(w)) { 0050 d->widgetList.append(w); 0051 updateWidgets(); 0052 } 0053 } 0054 0055 void WidgetHintFrameCollection::removeWidget(QWidget* w) 0056 { 0057 d->widgetList.removeAll(w); 0058 w->setEnabled(true); 0059 } 0060 0061 void WidgetHintFrameCollection::frameDestroyed(QObject* o) 0062 { 0063 WidgetHintFrame* frame = qobject_cast< WidgetHintFrame* >(o); 0064 if(frame) { 0065 d->frameList.removeAll(frame); 0066 } 0067 } 0068 0069 void WidgetHintFrameCollection::updateWidgets() 0070 { 0071 bool enabled = true; 0072 Q_FOREACH(WidgetHintFrame* frame, d->frameList) { 0073 enabled &= !frame->isErroneous(); 0074 if(!enabled) { 0075 break; 0076 } 0077 } 0078 0079 Q_FOREACH(QWidget* w, d->widgetList) { 0080 w->setEnabled(enabled); 0081 } 0082 } 0083 0084 0085 0086 0087 0088 0089 0090 class WidgetHintFrame::Private 0091 { 0092 public: 0093 QWidget* editWidget; 0094 bool status; 0095 FrameStyle style; 0096 }; 0097 0098 WidgetHintFrame::WidgetHintFrame(QWidget* editWidget, FrameStyle style, Qt::WindowFlags f) 0099 : QFrame(editWidget->parentWidget(), f) 0100 , d(new Private) 0101 { 0102 d->editWidget = 0; 0103 d->status = false; 0104 d->style = style; 0105 switch(style) { 0106 case Error: 0107 setStyleSheet("QFrame { background-color: none; padding: 1px; border: 2px solid red; border-radius: 4px; }"); 0108 break; 0109 case Warning: 0110 case Info: 0111 setStyleSheet("QFrame { background-color: none; padding: 1px; border: 2px dashed red; border-radius: 4px; }"); 0112 break; 0113 } 0114 attachToWidget(editWidget); 0115 } 0116 0117 WidgetHintFrame::~WidgetHintFrame() 0118 { 0119 delete d; 0120 } 0121 0122 bool WidgetHintFrame::isErroneous() const 0123 { 0124 return (d->style == Error) && (d->status == true); 0125 } 0126 0127 static WidgetHintFrame* frame(QWidget* editWidget) 0128 { 0129 QList<WidgetHintFrame*> allErrorFrames = editWidget->parentWidget()->findChildren<WidgetHintFrame*>(); 0130 QList<WidgetHintFrame*>::const_iterator it; 0131 foreach(WidgetHintFrame* f, allErrorFrames) { 0132 if(f->editWidget() == editWidget) { 0133 return f; 0134 } 0135 } 0136 return 0; 0137 } 0138 0139 0140 void WidgetHintFrame::show(QWidget* editWidget, const QString& tooltip) 0141 { 0142 WidgetHintFrame* f = frame(editWidget); 0143 if(f) { 0144 f->QWidget::show(); 0145 f->d->status = true; 0146 emit f->changed(); 0147 } 0148 if(!tooltip.isNull()) 0149 editWidget->setToolTip(tooltip); 0150 } 0151 0152 void WidgetHintFrame::hide(QWidget* editWidget, const QString& tooltip) 0153 { 0154 WidgetHintFrame* f = frame(editWidget); 0155 if(f) { 0156 f->QWidget::hide(); 0157 f->d->status = false; 0158 emit f->changed(); 0159 } 0160 if(!tooltip.isNull()) 0161 editWidget->setToolTip(tooltip); 0162 } 0163 0164 QWidget* WidgetHintFrame::editWidget() const 0165 { 0166 return d->editWidget; 0167 } 0168 0169 void WidgetHintFrame::detachFromWidget() 0170 { 0171 if(d->editWidget) { 0172 d->editWidget->removeEventFilter(this); 0173 d->editWidget = 0; 0174 } 0175 } 0176 0177 void WidgetHintFrame::attachToWidget(QWidget* w) 0178 { 0179 // detach first 0180 detachFromWidget(); 0181 if(w) { 0182 d->editWidget = w; 0183 // make sure we receive changes in position and size 0184 w->installEventFilter(this); 0185 // place frame around widget 0186 move(w->pos() - QPoint(2, 2)); 0187 resize(w->width()+4, w->height()+4); 0188 // make sure widget is on top of frame 0189 w->raise(); 0190 // and hide frame for now 0191 QWidget::hide(); 0192 } 0193 } 0194 0195 bool WidgetHintFrame::eventFilter(QObject* o, QEvent* e) 0196 { 0197 if(o == d->editWidget) { 0198 QMoveEvent* mev = 0; 0199 QResizeEvent* sev = 0; 0200 switch(e->type()) { 0201 case QEvent::EnabledChange: 0202 case QEvent::Hide: 0203 case QEvent::Show: 0204 /** 0205 * @todo think about what to do when widget is enabled/disabled 0206 * hidden or shown 0207 */ 0208 break; 0209 0210 case QEvent::Move: 0211 mev = static_cast<QMoveEvent*>(e); 0212 move(mev->pos() - QPoint(2, 2)); 0213 break; 0214 0215 case QEvent::Resize: 0216 sev = static_cast<QResizeEvent*>(e); 0217 resize(sev->size().width()+4, sev->size().height()+4); 0218 break; 0219 default: 0220 break; 0221 } 0222 } 0223 return QObject::eventFilter(o, e); 0224 }