File indexing completed on 2024-04-28 05:41:34
0001 /* 0002 This file is part of KCachegrind. 0003 0004 SPDX-FileCopyrightText: 2003-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-only 0007 */ 0008 0009 /* 0010 * Some helper functions for QListViewItem derivates 0011 */ 0012 0013 #include "listutils.h" 0014 0015 #include <QPainter> 0016 #include <QPixmap> 0017 0018 #include "globalguiconfig.h" 0019 0020 #define COSTPIX_WIDTH 25 0021 0022 QPixmap colorPixmap(int w, int h, QColor c) 0023 { 0024 static QPixmap* pixs[37]; 0025 static QColor cols[37]; 0026 static bool inited = false; 0027 0028 if (!inited) { 0029 for (int i=0;i<37;i++) pixs[i]=nullptr; 0030 inited = true; 0031 } 0032 int hash = (w+h+c.red()+c.green()+c.blue()) % 37; 0033 if (pixs[hash]) { 0034 if ((pixs[hash]->width() == w) && 0035 (pixs[hash]->height() == h) && 0036 (cols[hash] == c)) 0037 return *pixs[hash]; 0038 0039 delete pixs[hash]; 0040 } 0041 0042 0043 QPixmap* pix = new QPixmap(w, h); 0044 pix->fill(c); 0045 QPainter p(pix); 0046 p.setPen(c.lighter()); 0047 p.drawLine(0, 0, w-1, 0); 0048 p.drawLine(0, 0, 0, h-1); 0049 p.setPen(c.darker()); 0050 p.drawLine(w-1, 0, w-1, h-1); 0051 p.drawLine(0, h-1, w-1, h-1); 0052 0053 pixs[hash] = pix; 0054 cols[hash] = c; 0055 return *pix; 0056 } 0057 0058 /** 0059 * Create a percentage pixmap with a filling rate of p percent (0-100). 0060 * When withFrame==false, the pixmap is truncated to only the filled portion. 0061 */ 0062 QPixmap percentagePixmap(int w, int h, int percent, QColor c, bool framed) 0063 { 0064 int iw, ix1, ih, iy1, iy2; 0065 0066 // at max, draw 100% 0067 if (percent > 100) percent = 100; 0068 0069 // inner rectangle to fill with bar 0070 if (framed) { 0071 iw = w-2, ix1 = 1; 0072 ih = h-2, iy1 = 1, iy2 = h-2; 0073 } 0074 else { 0075 iw = w; ix1 = 0; 0076 ih = h; iy1 = 0; iy2 = h-1; 0077 } 0078 0079 int filled = iw*percent/100+1; 0080 if (!framed) w=filled; 0081 if (w<3) return QPixmap(); 0082 0083 QPixmap pix(w, h); 0084 pix.fill(Qt::white); 0085 QPainter p(&pix); 0086 p.setPen(Qt::black); 0087 if (framed) 0088 p.drawRect(0, 0, w-1, h-1); 0089 0090 // inside 0091 p.setPen(Qt::NoPen); 0092 p.setBrush(c); 0093 p.drawRect(ix1, iy1, filled-1,ih-1); 0094 0095 // last right pix column 0096 int lastY = ih-(filled*ih - iw*ih*percent/100); 0097 int lastX1 = ix1+filled-2 + ((lastY>1) ? 1: 0); 0098 int lastX2 = ix1+filled-2; 0099 0100 // frame 0101 p.setPen(c.lighter()); 0102 p.drawLine(ix1, iy1, lastX1, iy1); 0103 p.drawLine(ix1, iy1, ix1, iy2); 0104 p.setPen(c.darker()); 0105 p.drawLine(lastX1, iy1, lastX1, iy1+lastY); 0106 p.drawLine(lastX2, iy1+lastY, lastX2, iy2); 0107 p.drawLine(ix1+1, iy2, lastX2, iy2); 0108 0109 return pix; 0110 } 0111 0112 inline QColor partitionColor(int d, int max) 0113 { 0114 return QColor::fromHsv((720*d/max) % 360, 255-(128*d/max), 192); 0115 } 0116 0117 0118 QPixmap partitionPixmap(int w, int h, 0119 double* hist, EventTypeSet* set, int maxIndex, bool framed) 0120 { 0121 int lastPos = 0, nextPos; 0122 double val=0.0, sum=0.0; 0123 int d, dmin=maxIndex, dmax=0; 0124 for (d = 0;d<maxIndex;d++) 0125 if (hist[d]>0.0) { 0126 sum += hist[d]; 0127 if (dmin>d) dmin = d; 0128 if (dmax<d) dmax = d; 0129 } 0130 0131 // inner rectangle to fill with bar 0132 int iw, ix1, ih, iy1, iy2; 0133 if (framed) { 0134 iw = w-2, ix1 = 1; 0135 ih = h-2, iy1 = 1, iy2 = h-2; 0136 } 0137 else { 0138 iw = w; ix1 = 0; 0139 ih = h; iy1 = 0; iy2 = h-1; 0140 } 0141 0142 int filled = (int)(iw*sum+1); 0143 if (!framed) w=filled; 0144 if (w<3) return QPixmap(); 0145 0146 QPixmap pix(w, h); 0147 pix.fill(Qt::white); 0148 QPainter p(&pix); 0149 p.setPen(Qt::black); 0150 if (framed) 0151 p.drawRect(0, 0, w-1, h-1); 0152 0153 //qDebug("Sum %f, dw %d", sum,dw); 0154 0155 QColor c, cLast; 0156 bool leftDrawn = false; 0157 int x1, x2=0; 0158 int diff; 0159 d=dmin; 0160 while (d<dmax+1) { 0161 val += hist[d]; 0162 nextPos = (int)(filled * val/sum); 0163 0164 //qDebug(" hist[%d] %f, val %f, nextPos %d", d, hist[d], val, nextPos); 0165 0166 diff = nextPos-lastPos; 0167 if (diff==0) { d++; continue; } 0168 0169 if (set) 0170 c = GlobalGUIConfig::eventTypeColor(set->realType(d)); 0171 else 0172 c = partitionColor(d,maxIndex); 0173 0174 x1 = ix1+lastPos; 0175 x2 = ix1+nextPos; 0176 if (x2>=iw) x2=iw-1; 0177 0178 // inside 0179 p.setPen(Qt::NoPen); 0180 p.setBrush(c); 0181 p.drawRect(x1, iy1, x2-x1, ih-1); 0182 0183 // lighter top border 0184 p.setPen(c.lighter()); 0185 p.drawLine(x1, iy1, x2-1, iy1); 0186 0187 // when width for last and current distance >2, draw full 3D effect... 0188 if (!leftDrawn) { 0189 p.drawLine(x1, iy1+1, x1, iy2); 0190 leftDrawn = true; 0191 } 0192 0193 // darker bottom border 0194 p.setPen(c.darker()); 0195 p.drawLine(x1, iy2, x2-1, iy2); 0196 0197 lastPos = nextPos; 0198 cLast = c; 0199 d++; 0200 } 0201 0202 // right border (in last color) 0203 if (x2>0) 0204 p.drawLine(x2, iy1, x2, iy2); 0205 0206 return pix; 0207 } 0208 0209 0210 QPixmap costPixmap(EventType* ct, ProfileCostArray* cost, 0211 double total, bool framed) 0212 { 0213 if (!ct) return QPixmap(); 0214 0215 if (ct->isReal()) { 0216 QColor color = GlobalGUIConfig::eventTypeColor(ct); 0217 double p = 100.0 * cost->subCost(ct) / total; 0218 return percentagePixmap(COSTPIX_WIDTH, 10, (int)(p+.5), color, framed); 0219 } 0220 0221 int maxIndex; 0222 double h[MaxRealIndexValue]; 0223 maxIndex = ct->histCost(cost, total, h); 0224 0225 if (maxIndex ==0) return QPixmap(); 0226 return partitionPixmap(COSTPIX_WIDTH, 10, h, ct->set(), maxIndex, framed); 0227 } 0228 0229 0230 0231