File indexing completed on 2024-04-28 05:47:26
0001 /***************************************************************************** 0002 * Copyright 2007 - 2010 Craig Drummond <craig.p.drummond@gmail.com> * 0003 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU Lesser General Public License as * 0007 * published by the Free Software Foundation; either version 2.1 of the * 0008 * License, or (at your option) version 3, or any later version accepted * 0009 * by the membership of KDE e.V. (or its successor approved by the * 0010 * membership of KDE e.V.), which shall act as a proxy defined in * 0011 * Section 6 of version 3 of the license. * 0012 * * 0013 * This program is distributed in the hope that it will be useful, * 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0016 * Lesser General Public License for more details. * 0017 * * 0018 * You should have received a copy of the GNU Lesser General Public * 0019 * License along with this library. If not, * 0020 * see <http://www.gnu.org/licenses/>. * 0021 *****************************************************************************/ 0022 0023 #include "qtcurve_p.h" 0024 #include "utils.h" 0025 0026 #include <QToolBar> 0027 #include <QToolButton> 0028 #include <QAbstractItemView> 0029 #include <QDialog> 0030 #include <QSplitter> 0031 #include <QMdiSubWindow> 0032 #include <QMainWindow> 0033 #include <QComboBox> 0034 #include <QTreeView> 0035 #include <QGroupBox> 0036 #include <QListView> 0037 #include <QCheckBox> 0038 #include <QRadioButton> 0039 #include <QTextEdit> 0040 #include <QDial> 0041 #include <QLabel> 0042 #include <QStackedLayout> 0043 #include <QMenuBar> 0044 #include <QMouseEvent> 0045 #include <QScrollBar> 0046 #include <QWizard> 0047 #include <QDialogButtonBox> 0048 #include <QPushButton> 0049 #include <QHeaderView> 0050 #include <QLineEdit> 0051 #include <QSpinBox> 0052 #include <QDir> 0053 #include <QSettings> 0054 #include <QPixmapCache> 0055 #include <QTextStream> 0056 0057 #include "shadowhelper.h" 0058 #include <qtcurve-utils/x11qtc.h> 0059 #include <qtcurve-utils/qtutils.h> 0060 #include <sys/time.h> 0061 0062 namespace QtCurve { 0063 0064 bool 0065 blendOOMenuHighlight(const QPalette &pal, const QColor &highlight) 0066 { 0067 QColor text(pal.text().color()); 0068 QColor hl(pal.highlightedText().color()); 0069 0070 return ((text.red() < 50) && (text.green() < 50) && (text.blue() < 50) && 0071 (hl.red() > 127) && (hl.green() > 127) && (hl.blue() > 127) && 0072 TOO_DARK(highlight)); 0073 } 0074 0075 bool isNoEtchWidget(const QWidget *widget) 0076 { 0077 if (theThemedApp == APP_KRUNNER) { 0078 return true; 0079 } 0080 if (theThemedApp == APP_PLASMA) { 0081 const QWidget *top = widget->window(); 0082 0083 return !top || (!qobject_cast<const QDialog*>(top) && 0084 !qobject_cast<const QMainWindow*>(top)); 0085 } 0086 0087 if (widget && widget->inherits("QWebView")) { 0088 return true; 0089 } 0090 // KHTML: widget -> QWidget -> QWidget -> KHTMLView 0091 const QObject *w = (widget && widget->parent() && 0092 widget->parent()->parent() ? 0093 widget->parent()->parent()->parent() : nullptr); 0094 0095 return ((w && isA(w, "KHTMLView")) || 0096 (widget && isInQAbstractItemView(widget->parentWidget()))); 0097 } 0098 0099 void 0100 setOpacityProp(QWidget *w, unsigned short opacity) 0101 { 0102 // DO NOT condition compile on QTC_ENABLE_X11. 0103 // There's no direct linkage on X11 and the following code will just do 0104 // nothing if X11 is not enabled (either at compile time or at run time). 0105 QTC_RET_IF_FAIL(qtcX11Enabled()); 0106 if (WId wid = qtcGetWid(w->window())) { 0107 qtcX11SetOpacity(wid, opacity); 0108 } 0109 } 0110 0111 void 0112 setBgndProp(QWidget *w, EAppearance app, bool haveBgndImage) 0113 { 0114 // DO NOT condition compile on QTC_ENABLE_X11. 0115 // There's no direct linkage on X11 and the following code will just do 0116 // nothing if X11 is not enabled (either at compile time or at run time). 0117 QTC_RET_IF_FAIL(qtcX11Enabled()); 0118 if (WId wid = qtcGetWid(w->window())) { 0119 uint32_t prop = (((qtcIsFlatBgnd(app) ? 0120 (haveBgndImage ? APPEARANCE_RAISED : 0121 APPEARANCE_FLAT) : app) & 0xFF) | 0122 (w->palette().window().color().rgb() & 0123 0x00FFFFFF) << 8); 0124 qtcX11SetBgnd(wid, prop); 0125 } 0126 } 0127 0128 void setSbProp(QWidget *w) 0129 { 0130 // DO NOT condition compile on QTC_ENABLE_X11. 0131 // There's no direct linkage on X11 and the following code will just do 0132 // nothing if X11 is not enabled (either at compile time or at run time). 0133 QTC_RET_IF_FAIL(qtcX11Enabled()); 0134 if (WId wid = qtcGetWid(w->window())) { 0135 static const char *constStatusBarProperty = "qtcStatusBar"; 0136 QVariant prop(w->property(constStatusBarProperty)); 0137 0138 if (!prop.isValid() || !prop.toBool()) { 0139 w->setProperty(constStatusBarProperty, true); 0140 qtcX11SetStatusBar(wid); 0141 } 0142 } 0143 } 0144 0145 QWidget* 0146 scrollViewFrame(QWidget *widget) 0147 { 0148 QWidget *w = widget; 0149 0150 for (int i = 0; i < 10 && w;i++, w = w->parentWidget()) { 0151 if ((qobject_cast<QFrame*>(w) && 0152 ((QFrame*)w)->frameWidth() > 0) || 0153 qobject_cast<QTabWidget*>(w)) { 0154 return w; 0155 } 0156 } 0157 return nullptr; 0158 } 0159 0160 QToolBar* 0161 getToolBarChild(QWidget *w) 0162 { 0163 for (QObject *child: w->children()) { 0164 if (child->isWidgetType()) { 0165 if (qobject_cast<QToolBar*>(child)) 0166 return static_cast<QToolBar*>(child); 0167 QToolBar *tb = getToolBarChild((QWidget*)child); 0168 if (tb) { 0169 return tb; 0170 } 0171 } 0172 } 0173 0174 return nullptr; 0175 } 0176 0177 void 0178 setStyleRecursive(QWidget *w, QStyle *s, int minSize) 0179 { 0180 w->setStyle(s); 0181 if (qobject_cast<QToolButton*>(w)) 0182 w->setMinimumSize(1, minSize); 0183 0184 for (QObject *child: w->children()) { 0185 if (child->isWidgetType()) { 0186 setStyleRecursive((QWidget*)child, s, minSize); 0187 } 0188 } 0189 } 0190 0191 // 0192 // QtCurve's menu's have a 2 pixel border all around - but want the top, 0193 // and left edges to active the nearest menu item. Therefore, when we get a 0194 // mouse event in that region then adjsut its position... 0195 bool 0196 updateMenuBarEvent(QMouseEvent *event, QMenuBar *menu) 0197 { 0198 struct HackEvent: public QMouseEvent { 0199 bool 0200 adjust() 0201 { 0202 if (l.x() < 2 || l.y() < 2) { 0203 l = QPointF(l.x() < 2 ? l.x() + 2 : l.x(), 0204 l.y() < 2 ? l.y() + 2 : l.y()); 0205 s = QPointF(l.x() < 2 ? s.x() + 2 : s.x(), 0206 l.y() < 2 ? s.y() + 2 : s.y()); 0207 return true; 0208 } 0209 return false; 0210 } 0211 }; 0212 0213 if (((HackEvent*)event)->adjust()) { 0214 static_cast<QObject*>(menu)->event(event); 0215 return true; 0216 } 0217 return false; 0218 } 0219 0220 QRegion 0221 windowMask(const QRect &r, bool full) 0222 { 0223 int x, y, w, h; 0224 r.getRect(&x, &y, &w, &h); 0225 0226 if (full) { 0227 QRegion region(x + 4, y + 0, w-4*2, h-0*2); 0228 region += QRegion(x + 0, y + 4, w-0*2, h-4*2); 0229 region += QRegion(x + 2, y + 1, w-2*2, h-1*2); 0230 region += QRegion(x + 1, y + 2, w-1*2, h-2*2); 0231 return region; 0232 } else { 0233 QRegion region(x+1, y+1, w-2, h-2); 0234 region += QRegion(x, y+2, w, h-4); 0235 region += QRegion(x+2, y, w-4, h); 0236 return region; 0237 } 0238 } 0239 0240 const QWidget* 0241 getWidget(const QPainter *p) 0242 { 0243 if (p) { 0244 if (p->device()->devType() == QInternal::Widget) { 0245 return static_cast<const QWidget*>(p->device()); 0246 } 0247 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) 0248 // No-op on 5.13+. 0249 else { 0250 QPaintDevice *dev = QPainter::redirected(p->device()); 0251 if (dev && dev->devType() == QInternal::Widget) { 0252 return static_cast<const QWidget*>(dev); 0253 } 0254 } 0255 #endif 0256 } 0257 return nullptr; 0258 } 0259 0260 const QImage* 0261 getImage(const QPainter *p) 0262 { 0263 return (p && p->device() && QInternal::Image==p->device()->devType() ? 0264 static_cast<const QImage*>(p->device()) : nullptr); 0265 } 0266 0267 const QAbstractButton* 0268 getButton(const QWidget *w, const QPainter *p) 0269 { 0270 const QWidget *widget = w ? w : getWidget(p); 0271 return widget ? qobject_cast<const QAbstractButton*>(widget) : nullptr; 0272 } 0273 0274 void 0275 drawDots(QPainter *p, const QRect &r, bool horiz, int nLines, int offset, 0276 const QColor *cols, int startOffset, int dark) 0277 { 0278 int space((nLines*2)+(nLines-1)), 0279 x(horiz ? r.x() : r.x()+((r.width()-space)>>1)), 0280 y(horiz ? r.y()+((r.height()-space)>>1) : r.y()), 0281 i, j, 0282 numDots((horiz ? (r.width()-(2*offset))/3 : (r.height()-(2*offset))/3)+1); 0283 0284 p->setRenderHint(QPainter::Antialiasing, true); 0285 if (horiz) { 0286 if(startOffset && y+startOffset>0) 0287 y+=startOffset; 0288 0289 p->setPen(cols[dark]); 0290 for(i=0; i<space; i+=3) 0291 for(j=0; j<numDots; j++) 0292 drawAaPoint(p, x+offset+(3*j), y+i); 0293 0294 p->setPen(cols[0]); 0295 for(i=1; i<space; i+=3) 0296 for(j=0; j<numDots; j++) 0297 drawAaPoint(p, x+offset+1+(3*j), y+i); 0298 } else { 0299 if(startOffset && x+startOffset>0) 0300 x+=startOffset; 0301 0302 p->setPen(cols[dark]); 0303 for(i=0; i<space; i+=3) 0304 for(j=0; j<numDots; j++) 0305 drawAaPoint(p, x+i, y+offset+(3*j)); 0306 0307 p->setPen(cols[0]); 0308 for(i=1; i<space; i+=3) 0309 for(j=0; j<numDots; j++) 0310 drawAaPoint(p, x+i, y+offset+1+(3*j)); 0311 } 0312 QPAINTER_RENDERHINT_AA_MAYBE_OFF(p); 0313 } 0314 0315 bool 0316 isInQAbstractItemView(const QObject *w) 0317 { 0318 int level = 8; 0319 while (w && --level > 0) { 0320 if (qobject_cast<const QAbstractItemView*>(w)) 0321 return true; 0322 if (qobject_cast<const QDialog*>(w) 0323 /* || qobject_cast<const QMainWindow *>(w)*/) 0324 return false; 0325 w = w->parent(); 0326 } 0327 return false; 0328 } 0329 0330 const QToolBar* 0331 getToolBar(const QWidget *w) 0332 { 0333 return (w ? qobject_cast<const QToolBar*>(w) ? 0334 static_cast<const QToolBar*>(w) : 0335 getToolBar(w->parentWidget()) : nullptr); 0336 } 0337 0338 void 0339 drawTbArrow(const QStyle *style, const QStyleOptionToolButton *toolbutton, 0340 const QRect &rect, QPainter *painter, const QWidget *widget) 0341 { 0342 QStyle::PrimitiveElement pe; 0343 switch (toolbutton->arrowType) { 0344 case Qt::LeftArrow: 0345 pe = QStyle::PE_IndicatorArrowLeft; 0346 break; 0347 case Qt::RightArrow: 0348 pe = QStyle::PE_IndicatorArrowRight; 0349 break; 0350 case Qt::UpArrow: 0351 pe = QStyle::PE_IndicatorArrowUp; 0352 break; 0353 case Qt::DownArrow: 0354 pe = QStyle::PE_IndicatorArrowDown; 0355 break; 0356 default: 0357 return; 0358 } 0359 0360 QStyleOption arrowOpt; 0361 arrowOpt.rect = rect; 0362 arrowOpt.palette = toolbutton->palette; 0363 arrowOpt.state = toolbutton->state; 0364 style->drawPrimitive(pe, &arrowOpt, painter, widget); 0365 } 0366 0367 void 0368 adjustToolbarButtons(const QWidget *widget, const QToolBar *toolbar, 0369 int &leftAdjust, int &topAdjust, int &rightAdjust, 0370 int &bottomAdjust, int &round) 0371 { 0372 const int constAdjust=6; 0373 const int d = 1; 0374 QRect geo(widget->geometry()); 0375 if (toolbar->orientation() == Qt::Horizontal) { 0376 bool haveLeft = 0377 qobject_cast<QToolButton*>(toolbar->childAt(geo.x() - 0378 d, geo.y())); 0379 bool haveRight = 0380 qobject_cast<QToolButton*>(toolbar->childAt(geo.right() + 0381 d, geo.y())); 0382 0383 if (haveLeft && haveRight) { 0384 leftAdjust = -constAdjust; 0385 rightAdjust = constAdjust; 0386 round = ROUNDED_NONE; 0387 } else if (haveLeft) { 0388 leftAdjust = -constAdjust; 0389 round = ROUNDED_RIGHT; 0390 } else if (haveRight) { 0391 rightAdjust = constAdjust; 0392 round = ROUNDED_LEFT; 0393 } 0394 } else { 0395 bool haveTop = 0396 qobject_cast<QToolButton*>(toolbar->childAt(geo.x(), geo.y() - d)); 0397 bool haveBot = 0398 qobject_cast<QToolButton*>(toolbar->childAt(geo.x(), 0399 geo.bottom() + d)); 0400 if (haveTop && haveBot) { 0401 topAdjust = -constAdjust; 0402 bottomAdjust = constAdjust; 0403 round = ROUNDED_NONE; 0404 } else if (haveTop) { 0405 topAdjust = -constAdjust; 0406 round = ROUNDED_BOTTOM; 0407 } else if (haveBot) { 0408 bottomAdjust = constAdjust; 0409 round = ROUNDED_TOP; 0410 } 0411 } 0412 } 0413 0414 bool 0415 isA(const QObject *w, const char *type) 0416 { 0417 return (w && (0 == strcmp(w->metaObject()->className(), type) || 0418 (w->parent() && 0419 0 == strcmp(w->parent()->metaObject()->className(), type)))); 0420 } 0421 0422 }