QVariant ChannelModel::data(const QModelIndex& index, int role) const { if (m_currentLayer.isValid() && index.isValid()) { QList<KoChannelInfo*> channels = m_currentLayer->colorSpace()->channels(); int channelIndex = KoChannelInfo::displayPositionToChannelIndex(index.row(), channels); switch (role) { case Qt::DisplayRole: { return channels.at(channelIndex)->name(); } case Qt::CheckStateRole: { Q_ASSERT(index.row() < rowCount()); Q_ASSERT(index.column() < columnCount()); if (index.column() == 0) { QBitArray flags = m_currentLayer->channelFlags(); return (flags.isEmpty() || flags.testBit(channelIndex)) ? Qt::Checked : Qt::Unchecked; } QBitArray flags = dynamic_cast<const KisPaintLayer*>(m_currentLayer.data())->channelLockFlags(); return (flags.isEmpty() || flags.testBit(channelIndex)) ? Qt::Unchecked : Qt::Checked; } } } return QVariant(); }
void VolumeMask::erodeBitmask(int mind, int maxd, int minw, int maxw, int minh, int maxh) { // QProgressDialog progress("Eroding Tag Mask", // "Cancel", // 0, 100, // 0); QBitArray bitcopy = m_bitmask; for(int d=mind; d<=maxd; d++) { emit progressChanged((int)(100.0*(float)d/(float)m_depth)); qApp->processEvents(); for(int w=minw; w<=maxw; w++) for(int h=minh; h<=maxh; h++) { qint64 bidx = (d*m_width*m_height + w*m_height + h); if (bitcopy.testBit(bidx)) { int d0 = qMax(d-1, mind); int d1 = qMin(d+1, maxd); int w0 = qMax(w-1, minw); int w1 = qMin(w+1, maxw); int h0 = qMax(h-1, minh); int h1 = qMin(h+1, maxh); bool ok = true; for(int d2=d0; d2<=d1; d2++) for(int w2=w0; w2<=w1; w2++) for(int h2=h0; h2<=h1; h2++) { qint64 idx = d2*m_width*m_height + w2*m_height + h2; ok &= bitcopy.testBit(idx); } if (!ok) // surface voxel m_bitmask.setBit(bidx, false); // set bit to 0 } } } emit progressReset(); }
void VolumeMask::tagDSlice(int d, QBitArray bitmask, uchar *usermask) { checkMaskFile(); int nbytes = m_width*m_height; uchar *mask = new uchar[nbytes]; int tag = Global::tag(); uchar *mslice = m_maskFileManager.getSlice(d); memcpy(mask, mslice, nbytes); qint64 idx = 0; for(int w=0; w<m_width; w++) for(int h=0; h<m_height; h++) { qint64 midx = d*m_width*m_height + w*m_height + h; if (bitmask.testBit(midx)) { if (usermask[4*idx] > 0) mask[idx] = tag; } idx ++; } m_maskFileManager.setSlice(d, mask); delete [] mask; }
void Recurrence::addMonthlyPos( short pos, const QBitArray &days ) { // Allow 53 for yearly! if ( d->mRecurReadOnly || pos > 53 || pos < -53 ) { return; } RecurrenceRule *rrule = defaultRRule( false ); if ( !rrule ) { return; } bool changed = false; QList<RecurrenceRule::WDayPos> positions = rrule->byDays(); for ( int i = 0; i < 7; ++i ) { if ( days.testBit( i ) ) { RecurrenceRule::WDayPos p( pos, i + 1 ); if ( !positions.contains( p ) ) { changed = true; positions.append( p ); } } } if ( changed ) { rrule->setByDays( positions ); updated(); } }
void TrisetObject::paint(QGLViewer *viewer, QBitArray doodleMask, float *depthMap, Vec tcolor, float tmix) { int swd = viewer->camera()->screenWidth(); int sht = viewer->camera()->screenHeight(); for(int i=0; i<m_tvertices.count(); i++) { Vec scr = viewer->camera()->projectedCoordinatesOf(m_tvertices[i]); int tx = scr.x; int ty = sht-scr.y; float td = scr.z; if (tx>0 && tx<swd && ty>0 && ty<sht) { int idx = ty*swd + tx; if (doodleMask.testBit(idx)) { float zd = depthMap[idx]; if (fabs(zd-td) < 0.0002) m_vcolor[i] = tmix*tcolor + (1.0-tmix)*m_vcolor[i]; } } } }
QList<QWidget *> FatherBlock::GetEnableBlocksWidget(int theStatusIndex) { QList<QWidget *>theBlockWidgets; if(theStatusIndex == -1) { theStatusIndex = m_current_status_index; } if(theStatusIndex < m_status_list.count()) { QBitArray theStatus = m_status_list[theStatusIndex]; int count = theStatus.count()-1; while(count >= 0) { if(theStatus.testBit(count) == true) { QWidget *ChildBlockWidget = GetSingleBlock(m_block_type); ChildBlockWidget->setStyleSheet(m_BlockStyleSheet); ChildBlockWidget->setGeometry(m_blocks_list[count]->geometry()); ChildBlockWidget->setGeometry(ChildBlockWidget->x()+this->x(),ChildBlockWidget->y()+this->y(),ChildBlockWidget->width(),ChildBlockWidget->height()); theBlockWidgets.append(ChildBlockWidget); } count--; } } return theBlockWidgets; }
/** * Spread contacts in the blockmap to any touched neighbors. * * @param box Map space region in which to perform spreading. */ void spread(AABoxd const &box) { BlockmapCellBlock const cellBlock = _blockmap.toCellBlock(box); BlockmapCell cell; for(cell.y = cellBlock.min.y; cell.y < cellBlock.max.y; ++cell.y) for(cell.x = cellBlock.min.x; cell.x < cellBlock.max.x; ++cell.x) { if(_spreadBlocks) { // Should we skip this cell? int cellIndex = _blockmap.toCellIndex(cell.x, cell.y); if(_spreadBlocks->testBit(cellIndex)) continue; // Mark the cell as processed. _spreadBlocks->setBit(cellIndex); } _blockmap.forAllInCell(cell, [this] (void *element) { spreadContact(*static_cast<Contact *>(element)); return LoopContinue; }); } }
// Sends the complete list of pieces that we have downloaded. void PeerWireClient::sendPieceList(const QBitArray &bitField) { // The bitfield message may only be sent immediately after the // handshaking sequence is completed, and before any other // messages are sent. if (!sentHandShake) sendHandShake(); // Don't send the bitfield if it's all zeros. if (bitField.count(true) == 0) return; int bitFieldSize = bitField.size(); int size = (bitFieldSize + 7) / 8; QByteArray bits(size, '\0'); for (int i = 0; i < bitFieldSize; ++i) { if (bitField.testBit(i)) { quint32 byte = quint32(i) / 8; quint32 bit = quint32(i) % 8; bits[byte] = uchar(bits.at(byte)) | (1 << (7 - bit)); } } char message[] = {0, 0, 0, 1, 5}; toNetworkData(bits.size() + 1, &message[0]); write(message, sizeof(message)); write(bits); }
void VolumeMask::tagHSlice(int h, QBitArray bitmask, uchar *usermask) { checkMaskFile(); int nbytes = m_width*m_height; uchar *mask = new uchar[nbytes]; int tag = Global::tag(); qint64 bidx = 0; for(int d=0; d<m_depth; d++) { uchar *mslice = m_maskFileManager.getSlice(d); memcpy(mask, mslice, nbytes); for(int w=0; w<m_width; w++) { qint64 midx = d*m_width*m_height + w*m_height + h; if (bitmask.testBit(midx)) { qint64 bidx = (d*m_width + w); qint64 idx = (w*m_height + h); if (usermask[4*bidx] > 0) mask[idx] = tag; } } m_maskFileManager.setSlice(d, mask); } delete [] mask; }
/****************************************************************************** * Replaces the particle selection. ******************************************************************************/ void ParticleSelectionSet::setParticleSelection(const PipelineFlowState& state, const QBitArray& selection, SelectionMode mode) { // Make a backup of the old snapshot so it may be restored. if(dataset()->undoStack().isRecording()) dataset()->undoStack().push(new ReplaceSelectionOperation(this)); ParticlePropertyObject* identifierProperty = ParticlePropertyObject::findInState(state, ParticleProperty::IdentifierProperty); if(identifierProperty && useIdentifiers()) { OVITO_ASSERT(selection.size() == identifierProperty->size()); _selection.clear(); int index = 0; if(mode == SelectionReplace) { _selectedIdentifiers.clear(); for(int id : identifierProperty->constIntRange()) { if(selection.testBit(index++)) _selectedIdentifiers.insert(id); } } else if(mode == SelectionAdd) { for(int id : identifierProperty->constIntRange()) { if(selection.testBit(index++)) _selectedIdentifiers.insert(id); } } else if(mode == SelectionSubtract) { for(int id : identifierProperty->constIntRange()) { if(selection.testBit(index++)) _selectedIdentifiers.remove(id); } } } else { _selectedIdentifiers.clear(); if(mode == SelectionReplace) _selection = selection; else if(mode == SelectionAdd) { _selection.resize(selection.size()); _selection |= selection; } else if(mode == SelectionSubtract) { _selection.resize(selection.size()); _selection &= ~selection; } } notifyDependents(ReferenceEvent::TargetChanged); }
void VolumeMask::erode(int mind, int maxd, int minw, int maxw, int minh, int maxh, QBitArray vbitmask) { createBitmask(); //int thickness = Global::spread(); int thickness = 1; while (thickness > 0) { erodeBitmask(mind, maxd, minw, maxw, minh, maxh); thickness --; } // m_bitmask now contains region eroded by thickness // QProgressDialog progress("Updating Mask", // "Cancel", // 0, 100, // 0); int nbytes = m_width*m_height; unsigned char *mask = new unsigned char[nbytes]; for(int d=mind; d<=maxd; d++) { emit progressChanged((int)(100.0*(float)d/(float)m_depth)); qApp->processEvents(); uchar *mslice = m_maskFileManager.getSlice(d); memcpy(mask, mslice, nbytes); for(int w=minw; w<=maxw; w++) for(int h=minh; h<=maxh; h++) { qint64 bidx = (d*m_width*m_height + w*m_height + h); if ( vbitmask.testBit(bidx) && !m_bitmask.testBit(bidx)) { // reset mask to 0 if the // mask value is same as supplied tag value qint64 idx = (w*m_height + h); if ( mask[idx] == Global::tag()) mask[idx] = 0; } } m_maskFileManager.setSlice(d, mask); } delete [] mask; emit progressReset(); }
QRect ImageOverlayRegionFinder::growRegion(int row, int column, QBitArray &mask) { QRect region; region.setCoords(column, row, column, row); QQueue<int> queue; queue.enqueue(getDataIndex(row, column)); while (!queue.isEmpty()) { int i = queue.dequeue(); if (m_overlay.getData()[i] > 0 && !mask.testBit(i)) { mask.setBit(i); row = getRowIndex(i); column = getColumnIndex(i); if (row < region.top()) { region.setTop(row); } if (row > region.bottom()) { region.setBottom(row); } if (column < region.left()) { region.setLeft(column); } if (column > region.right()) { region.setRight(column); } if (column - 1 >= 0) { queue.enqueue(getDataIndex(row, column - 1)); } if (column + 1 < static_cast<signed>(m_overlay.getColumns())) { queue.enqueue(getDataIndex(row, column + 1)); } if (row - 1 >= 0) { queue.enqueue(getDataIndex(row - 1, column)); } if (row + 1 < static_cast<signed>(m_overlay.getRows())) { queue.enqueue(getDataIndex(row + 1, column)); } } } return region; }
bool KoList::continueNumbering(int level) const { Q_ASSERT(level > 0 && level <= 10); level = qMax(qMin(level, 10), 1); QBitArray bitArray = d->properties.value(ContinueNumbering).toBitArray(); if (bitArray.isEmpty()) return false; return bitArray.testBit(level-1); }
void KisChannelFlagsWidget::setChannelFlags(const QBitArray & cf) { dbgUI << "KisChannelFlagsWidget::setChannelFlags " << cf.isEmpty(); if (cf.isEmpty()) return; QBitArray channelFlags = m_colorSpace->setChannelFlagsToColorSpaceOrder(cf); for (int i = 0; i < qMin(m_channelChecks.size(), channelFlags.size()); ++i) { m_channelChecks.at(i)->setChecked(channelFlags.testBit(i)); } }
T typeFromBitArray(QBitArray &array) { Q_ASSERT(sizeof(T) <= sizeof(quint64)); quint64 mask = 0x0000000000000001; T resultVector(0); for (uint i = 0; i < 8 * sizeof (T); ++i) { if (array.testBit(i)) resultVector |= mask; mask <<= 1; } return resultVector; }
void QLCDNumber::setNumDigits( int numDigits ) { if ( numDigits > 99 ) { #if defined(QT_CHECK_RANGE) qWarning( "QLCDNumber::setNumDigits: (%s) Max 99 digits allowed", name( "unnamed" ) ); #endif numDigits = 99; } if (numDigits < 0 ) { #if defined(QT_CHECK_RANGE) qWarning( "QLCDNumber::setNumDigits: (%s) Min 0 digits allowed", name( "unnamed" ) ); #endif numDigits = 0; } if ( digitStr.isNull() ) { // from constructor ndigits = numDigits; digitStr.fill( ' ', ndigits ); points.fill( 0, ndigits ); digitStr[ndigits - 1] = '0'; // "0" is the default number } else { bool doDisplay = ndigits == 0; if ( numDigits == ndigits ) // no change return; register int i; int dif; if ( numDigits > ndigits ) { // expand dif = numDigits - ndigits; QString buf; buf.fill( ' ', dif ); digitStr.insert( 0, buf ); points.resize( numDigits ); for ( i=numDigits-1; i>=dif; i-- ) points.setBit( i, points.testBit(i-dif) ); for ( i=0; i<dif; i++ ) points.clearBit( i ); } else { // shrink dif = ndigits - numDigits; digitStr = digitStr.right( numDigits ); QBitArray tmpPoints = points.copy(); points.resize( numDigits ); for ( i=0; i<(int)numDigits; i++ ) points.setBit( i, tmpPoints.testBit(i+dif) ); } ndigits = numDigits; if ( doDisplay ) display( value() ); update(); } }
void VolumeMask::dilate(QBitArray vbitmask) { createBitmask(); //int thickness = Global::spread(); int thickness = 1; while (thickness > 0) { dilateBitmask(); thickness --; } // m_bitmask now contains region dilated by thickness // QProgressDialog progress("Updating Mask", // "Cancel", // 0, 100, // 0); int nbytes = m_width*m_height; unsigned char *mask = new unsigned char[nbytes]; qint64 bidx = 0; for(int d=0; d<m_depth; d++) { emit progressChanged((int)(100.0*(float)d/(float)m_depth)); qApp->processEvents(); uchar *mslice = m_maskFileManager.getSlice(d); memcpy(mask, mslice, nbytes); for(int w=0; w<m_width; w++) for(int h=0; h<m_height; h++) { if ( vbitmask.testBit(bidx) && m_bitmask.testBit(bidx)) { qint64 idx = (w*m_height + h); mask[idx] = Global::tag(); } bidx++; } m_maskFileManager.setSlice(d, mask); } delete [] mask; emit progressReset(); }
/*! Sets the current number of digits to \a numDigits. Must be in the range 0..99. */ void QLCDNumber::setDigitCount(int numDigits) { Q_D(QLCDNumber); if (numDigits > 99) { qWarning("QLCDNumber::setNumDigits: (%s) Max 99 digits allowed", objectName().toLocal8Bit().constData()); numDigits = 99; } if (numDigits < 0) { qWarning("QLCDNumber::setNumDigits: (%s) Min 0 digits allowed", objectName().toLocal8Bit().constData()); numDigits = 0; } if (d->digitStr.isNull()) { // from constructor d->ndigits = numDigits; d->digitStr.fill(QLatin1Char(' '), d->ndigits); d->points.fill(0, d->ndigits); d->digitStr[d->ndigits - 1] = QLatin1Char('0'); // "0" is the default number } else { bool doDisplay = d->ndigits == 0; if (numDigits == d->ndigits) // no change return; int i; int dif; if (numDigits > d->ndigits) { // expand dif = numDigits - d->ndigits; QString buf; buf.fill(QLatin1Char(' '), dif); d->digitStr.insert(0, buf); d->points.resize(numDigits); for (i=numDigits-1; i>=dif; i--) d->points.setBit(i, d->points.testBit(i-dif)); for (i=0; i<dif; i++) d->points.clearBit(i); } else { // shrink dif = d->ndigits - numDigits; d->digitStr = d->digitStr.right(numDigits); QBitArray tmpPoints = d->points; d->points.resize(numDigits); for (i=0; i<(int)numDigits; i++) d->points.setBit(i, tmpPoints.testBit(i+dif)); } d->ndigits = numDigits; if (doDisplay) display(value()); update(); } }
err_info *Pagemodel::commit (void) { Desktopmodel *contents = (Desktopmodel *)_contents; QModelIndex index = _stackindex; // may be invalid int del_count = 0; QVector<Pageinfo> *pages = &_pages; bool lost = _lost_scan; if (lost) { pages = &_scan_pages; _lost_scan = false; contents = (Desktopmodel *)_lost_contents; _lost_contents = 0; } if (!contents) return NULL; // delete any pages marked for deletion QBitArray ba (pages->size ()); for (int i = 0; i < pages->size (); i++) if ((*pages) [i].toRemove ()) { ba.setBit (i); del_count++; } // process on our local model (reverse order) if (!lost) for (int i = pages->size () - 1; i >= 0; i--) if (ba.testBit (i)) removeRow (i, QModelIndex ()); // update any annotation data if (!lost && index.isValid ()) contents->updateAnnot (index, _annot_updates); //FIXME: need to write ocr text somewhere also, but needs to be page-based //FIXME: should only update annotations if they have changed //FIXME: what happens if they delete all pages? Should delete the stack /* now delete the pages we don't want, or trash the whole stack if we want none of them. This function also handles the case where contents points to another directory */ // this may invalidate _stackIndex // also this function copes with an invalid index return contents->scanCommitPages (index, del_count, ba, !lost); }
void VolumeMask::tagUsingBitmask(QList<int> pos, QBitArray bitmask) { checkMaskFile(); if (pos.count()) findConnectedRegion(pos); // QProgressDialog progress("Updating Mask", // "Cancel", // 0, 100, // 0); int nbytes = m_width*m_height; uchar *mask = new uchar[nbytes]; int tag = Global::tag(); qint64 bidx = 0; for(int d=0; d<m_depth; d++) { emit progressChanged((int)(100.0*(float)d/(float)m_depth)); qApp->processEvents(); uchar *mslice = m_maskFileManager.getSlice(d); memcpy(mask, mslice, nbytes); for(int w=0; w<m_width; w++) for(int h=0; h<m_height; h++) { if (bitmask.testBit(bidx)) { qint64 idx = (w*m_height + h); //if (tag == 0 || mask[idx] == 0) mask[idx] = tag; } bidx++; } m_maskFileManager.setSlice(d, mask); } delete [] mask; emit progressReset(); }
void EventWinRecurrence::setCheckedDays(QBitArray &rDays) { if (rDays.testBit(0)) mondayBox->setChecked(TRUE); if (rDays.testBit(1)) tuesdayBox->setChecked(TRUE); if (rDays.testBit(2)) wednesdayBox->setChecked(TRUE); if (rDays.testBit(3)) thursdayBox->setChecked(TRUE); if (rDays.testBit(4)) fridayBox->setChecked(TRUE); if (rDays.testBit(5)) saturdayBox->setChecked(TRUE); if (rDays.testBit(6)) sundayBox->setChecked(TRUE); }
void TreeWidget::restoreState(const QByteArray& data) { QVariantMap state; QDataStream in(data); in >> state; if (state.contains("expanded")) { QBitArray expanded = state.value("expanded").toBitArray(); if (expanded.count() == topLevelItemCount()) { for (int i = 0; i < expanded.count(); ++i) topLevelItem(i)->setExpanded(expanded.testBit(i)); } } if (state.contains("sorting")) { d.sorting = state.value("sorting").toMap(); restoreSortOrder(); } }
void VolumeMask::dilateBitmask() { // QProgressDialog progress("Dilating Tag Mask", // "Cancel", // 0, 100, // 0); QBitArray bitcopy = m_bitmask; m_bitmask.fill(false); qint64 bidx = 0; for(int d=0; d<m_depth; d++) { emit progressChanged((int)(100.0*(float)d/(float)m_depth)); qApp->processEvents(); for(int w=0; w<m_width; w++) for(int h=0; h<m_height; h++) { if (bitcopy.testBit(bidx)) { int d0 = qMax(d-1, 0); int d1 = qMin(d+1, m_depth-1); int w0 = qMax(w-1, 0); int w1 = qMin(w+1, m_width-1); int h0 = qMax(h-1, 0); int h1 = qMin(h+1, m_height-1); for(int d2=d0; d2<=d1; d2++) for(int w2=w0; w2<=w1; w2++) for(int h2=h0; h2<=h1; h2++) { qint64 idx = d2*m_width*m_height + w2*m_height + h2; m_bitmask.setBit(idx); } } bidx ++; } } emit progressReset(); }
QList<QRect> FatherBlock::GetEnableBlockRects(int theStatusIndex,bool theRealBlocksFlag) { QList<QRect>theBlockRects; if(theStatusIndex == -1) { theStatusIndex = m_current_status_index; } if(theStatusIndex < m_status_list.count()) { QBitArray theStatus = m_status_list[theStatusIndex]; int count = theStatus.count()-1; while(count >= 0) { if(theStatus.testBit(count) == true) { QRect ChildBlockRect = QRect(m_blocks_list[count]->geometry()); ChildBlockRect.setX(ChildBlockRect.x() + this->x()); ChildBlockRect.setY(ChildBlockRect.y() + this->y()); ChildBlockRect.setWidth(m_blocks_list[count]->width()); ChildBlockRect.setHeight(m_blocks_list[count]->height()); if(!hasBottomBlock(count) && !theRealBlocksFlag) { QRect tempBlock(ChildBlockRect); tempBlock.setY(ChildBlockRect.y()+m_blocks_list[count]->height()); theBlockRects.append(tempBlock); } if(!hasRightBlock(count) && !theRealBlocksFlag) { QRect tempBlock(ChildBlockRect); tempBlock.setX(ChildBlockRect.x() + m_blocks_list[count]->width()); theBlockRects.append(tempBlock); } theBlockRects.append(ChildBlockRect); } count--; } } return theBlockRects; }
bool FatherBlock::RotateShape(int theStatusIndex) { if(theStatusIndex < m_status_list.count()) { QBitArray theStatus = m_status_list[theStatusIndex]; int count = theStatus.count()-1; while(count >= 0) { if(theStatus.testBit(count) == true) { SetStatusEnable(m_blocks_list[count]); }else { SetStatusDisable(m_blocks_list[count]); } count--; } return true; }else { return false; } }
QBitArray KisChannelFlagsWidget::channelFlags() const { bool allTrue = true; QBitArray ba(m_channelChecks.size()); for (int i = 0; i < m_channelChecks.size(); ++i) { bool flag = m_channelChecks.at(i)->isChecked(); if (!flag) allTrue = false; ba.setBit(i, flag); dbgUI << " channel " << i << " is " << flag << ", allTrue = " << allTrue << ", so ba.testBit("<<i<<")" << " is " << ba.testBit(i); } if (allTrue) return QBitArray(); else { QBitArray result = m_colorSpace->setChannelFlagsToPixelOrder(ba); for (int i = 0; i < result.size(); ++i) { dbgUI << "On conversion to the pixel order, flag " << i << " is " << result.testBit(i); } return result; } }
void KeyWidget::paintEvent(QPaintEvent*){ const QColor bgColor(68, 64, 64); const QColor keyColor(112, 110, 110); const QColor highlightColor(136, 176, 240); const QColor highlightAnimColor(136, 200, 240); const QColor animColor(112, 200, 110); uint count = keyMap.count(); // Determine which keys to highlight QBitArray highlight; switch(mouseDownMode){ case SET: highlight = newSelection; break; case ADD: highlight = selection | newSelection; break; case SUBTRACT: highlight = selection & ~newSelection; break; case TOGGLE: highlight = selection ^ newSelection; break; default: highlight = selection; } QPainter painter(this); #if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) int ratio = painter.device()->devicePixelRatio(); #else int ratio = 1; #endif float xScale = (float)width() / (keyMap.width() + KEY_SIZE) * ratio; float yScale = (float)height() / (keyMap.height() + KEY_SIZE) * ratio; // Draw background painter.setPen(Qt::NoPen); painter.setRenderHint(QPainter::Antialiasing, true); painter.setBrush(QBrush(bgColor)); painter.drawRect(0, 0, width(), height()); // Draw mouse highlight (if any) if(mouseDownMode != NONE && (mouseDownX != mouseCurrentX || mouseDownY != mouseCurrentY)){ int x1 = (mouseDownX > mouseCurrentX) ? mouseCurrentX : mouseDownX; int x2 = (mouseDownX > mouseCurrentX) ? mouseDownX : mouseCurrentX; int y1 = (mouseDownY > mouseCurrentY) ? mouseCurrentY : mouseDownY; int y2 = (mouseDownY > mouseCurrentY) ? mouseDownY : mouseCurrentY; painter.setPen(QPen(highlightColor, 0.5)); QColor bColor = highlightColor; bColor.setAlpha(128); painter.setBrush(QBrush(bColor)); painter.drawRect(x1, y1, x2 - x1, y2 - y1); } // Draw key backgrounds on a separate pixmap so that a drop shadow can be applied to them. int wWidth = width(), wHeight = height(); KeyMap::Model model = keyMap.model(); QPixmap keyBG(wWidth * ratio, wHeight * ratio); keyBG.fill(QColor(0, 0, 0, 0)); QPainter bgPainter(&keyBG); bgPainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); bgPainter.setPen(Qt::NoPen); for(uint i = 0; i < count; i++){ const KeyPos& key = *keyMap.key(i); float x = key.x + 6.f - key.width / 2.f + 1.f; float y = key.y + 6.f - key.height / 2.f + 1.f; float w = key.width - 2.f; float h = key.height - 2.f; // In RGB mode, ignore volume wheel on K70/K95 if(model != KeyMap::K65 && _rgbMode && (!strcmp(key.name, "volup") || !strcmp(key.name, "voldn"))) continue; // Set color based on key highlight if(highlight.testBit(i)){ if(animation.testBit(i)) bgPainter.setBrush(QBrush(highlightAnimColor)); else bgPainter.setBrush(QBrush(highlightColor)); } else if(animation.testBit(i)) bgPainter.setBrush(QBrush(animColor)); else bgPainter.setBrush(QBrush(keyColor)); if(!strcmp(key.name, "mr") || !strcmp(key.name, "m1") || !strcmp(key.name, "m2") || !strcmp(key.name, "m3") || !strcmp(key.name, "light") || !strcmp(key.name, "lock") || (model == KeyMap::K65 && !strcmp(key.name, "mute"))){ // Switch keys are circular x += w / 8.f; y += h / 8.f; w *= 0.75f; h *= 0.75f; bgPainter.drawEllipse(QRectF(x * xScale, y * yScale, w * xScale, h * yScale)); } else { if(!strcmp(key.name, "enter")){ if(key.height == 24){ // ISO enter key isn't rectangular y = key.y + 1.f; h = 10.f; bgPainter.drawRect(QRectF((x + w - 13.f) * xScale, y * yScale, 13.f * xScale, 22.f * yScale)); } else { // US enter key isn't perfectly centered, needs an extra pixel on the left to appear correctly x -= 1.f; w += 1.f; } } else if(!strcmp(key.name, "rshift") || !strcmp(key.name, "stop")){ // A few other keys also need extra pixels x -= 1.f; w += 1.f; } else if(!strcmp(key.name, "caps") || !strcmp(key.name, "lshift") || !strcmp(key.name, "next")){ w += 1.f; } bgPainter.drawRect(QRectF(x * xScale, y * yScale, w * xScale, h * yScale)); } } // Render the key decorations (RGB -> light circles, binding -> key names) on yet another layer QPixmap decoration(wWidth * ratio, wHeight * ratio); decoration.fill(QColor(0, 0, 0, 0)); QPainter decPainter(&decoration); decPainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); if(_rgbMode){ // Draw key colors (RGB mode) decPainter.setPen(QPen(QColor(255, 255, 255), 1.5)); for(uint i = 0; i < count; i++){ const KeyPos& key = *keyMap.key(i); if(model != KeyMap::K65 && _rgbMode && (!strcmp(key.name, "volup") || !strcmp(key.name, "voldn"))) continue; float x = key.x + 6.f - 1.8f; float y = key.y + 6.f - 1.8f; float w = 3.6f; float h = 3.6f; decPainter.setBrush(QBrush(_colorMap[key.name])); decPainter.drawEllipse(QRectF(x * xScale, y * yScale, w * xScale, h * yScale)); } } else { // Draw key names decPainter.setBrush(Qt::NoBrush); QFont font = painter.font(); font.setBold(true); font.setPixelSize(5.25f * yScale); QFont font0 = font; for(uint i = 0; i < count; i++){ const KeyPos& key = *keyMap.key(i); float x = key.x + 6.f - key.width / 2.f + 1.f; float y = key.y + 6.f - key.height / 2.f; float w = key.width - 2.f; float h = key.height; // Print the key's friendly name (with some exceptions) QString keyName = KbBind::globalRemap(key.name); QString name = key.friendlyName(false); name = name.split(" ").last(); struct _names { const char* keyName, *displayName; }; _names names[] = { {"light", "☼"}, {"lock", "☒"}, {"mute", "◖⊘"}, {"volup", keyMap.model() == KeyMap::K65 ? "◖))" : "▲"}, {"voldn", keyMap.model() == KeyMap::K65 ? "◖)" : "▼"}, {"prtscn", "PrtScn\nSysRq"}, {"scroll", "Scroll\nLock"}, {"pause", "Pause\nBreak"}, {"stop", "▪"}, {"prev", "|◂◂"}, {"play", "▸||"}, {"next", "▸▸|"}, {"pgup", "Page\nUp"}, {"pgdn", "Page\nDown"}, {"numlock", "Num\nLock"}, {"caps", "Caps"}, {"lshift", "Shift"}, {"rshift", "Shift"}, #ifdef Q_OS_MACX {"lctrl", "⌃"}, {"rctrl", "⌃"}, {"lwin", "⌘"}, {"rwin", "⌘"}, {"lalt", "⌥"}, {"ralt", "⌥"}, #else {"lctrl", "Ctrl"}, {"rctrl", "Ctrl"}, {"lwin", "❖"}, {"rwin", "❖"}, {"lalt", "Alt"}, {"ralt", "Alt"}, #endif {"rmenu", "▤"}, {"up", "▲"}, {"left", "◀"}, {"down", "▼"}, {"right", "▶"} }; for(uint k = 0; k < sizeof(names) / sizeof(_names); k++){ if(keyName == names[k].keyName){ name = names[k].displayName; break; } } if(keyName == "mr" || keyName == "m1" || keyName == "m2" || keyName == "m3" || keyName == "up" || keyName == "down" || keyName == "left" || keyName == "right") // Use a smaller size for MR, M1 - M3, and arrow keys font.setPixelSize(font.pixelSize() * 0.75); else if(keyName == "end") // Use a smaller size for "End" to match everything else in that area font.setPixelSize(font.pixelSize() * 0.65); else if(keyName == "light" #ifndef Q_OS_MACX || keyName == "lwin" || keyName == "rwin" #endif ) // Use a larger font size for Win and Brightness to compensate for the unicode symbols looking smaller (Linux only) font.setPixelSize(font.pixelSize() * 1.3); // Determine the appropriate size to draw the text at decPainter.setFont(font); QRectF rect(x * xScale, y * yScale - 1, w * xScale, h * yScale); int flags = Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextWordWrap; QRectF bounds = decPainter.boundingRect(rect, flags, name); while((bounds.height() >= rect.height() - 8. || bounds.width() >= rect.width() - 2.) && font.pixelSize() >= 5){ // Scale font size down until it fits inside the key font.setPixelSize(font.pixelSize() - 2); decPainter.setFont(font); bounds = decPainter.boundingRect(rect, flags, name); } // Pick color based on key function QString bind = _bindMap.value(key.name); QString def = KbBind::defaultAction(key.name); if(bind.isEmpty()) // Unbound - red decPainter.setPen(QColor(255, 136, 136)); else if(KbBind::isProgram(bind)) // Custom program - orange decPainter.setPen(QColor(255, 224, 192)); else if(KbBind::isSpecial(bind) && (bind == def || !KbBind::isSpecial(def))) // Special function - blue (only if not mapped to a different function - if a special function is remapped, color it yellow) decPainter.setPen(QColor(128, 224, 255)); else if(KbBind::isMedia(bind) && (bind == def || !KbBind::isMedia(def))) // Media key - green decPainter.setPen(QColor(160, 255, 168)); else if(bind == def) // Standard key - white decPainter.setPen(QColor(255, 255, 255)); else // Remapped key - yellow decPainter.setPen(QColor(255, 248, 128)); decPainter.drawText(rect, flags, name); font = font0; } } // Create drop shadow effects QGraphicsDropShadowEffect* bgEffect = new QGraphicsDropShadowEffect; // Have to use "new", creating these on the stack causes a crash... bgEffect->setBlurRadius(2.); bgEffect->setColor(QColor(0, 0, 0, 32)); bgEffect->setOffset(0, 1); QGraphicsDropShadowEffect* decEffect = new QGraphicsDropShadowEffect; decEffect->setBlurRadius(4.); decEffect->setColor(QColor(0, 0, 0, 104)); decEffect->setOffset(0, 1); // Apply them to the pixmaps QGraphicsPixmapItem* bgItem = new QGraphicsPixmapItem(keyBG); bgItem->setGraphicsEffect(bgEffect); QGraphicsPixmapItem* decItem = new QGraphicsPixmapItem(decoration); decItem->setGraphicsEffect(decEffect); // Render everything QGraphicsScene* scene = new QGraphicsScene; scene->addItem(bgItem); scene->addItem(decItem); // It has to be rendered onto yet another pixmap or else DPI scaling will look terrible... QPixmap final(wWidth * ratio, wHeight * ratio); final.fill(QColor(0, 0, 0, 0));
void HoleFinderPrivate::mergeHoles() { // Make copy, clear original, add merged holes back into original QVector<Hole> holeCopy (this->holes); const int numHoles = this->holes.size(); this->holes.clear(); this->holes.reserve(numHoles); // If the bit is on, it has not been merged. If off, it has been. QBitArray mask (holeCopy.size(), true); // Check each pair of unmerged holes. If one contains the other, merge them. QVector<Hole*> toMerge; toMerge.reserve(256); // Way bigger than we need, but certainly sufficient // Temp vars Eigen::Vector3d diffVec; // "i" indexes the "base" hole for (int i = 0; i < numHoles; ++i) { if (!mask.testBit(i)) continue; mask.clearBit(i); Hole &hole_i = holeCopy[i]; toMerge.clear(); toMerge.reserve(256); toMerge.push_back(&hole_i); // "j" indexes the compared holes for (int j = i+1; j < numHoles; ++j) { if (!mask.testBit(j)) continue; Hole &hole_j = holeCopy[j]; diffVec = hole_j.center - hole_i.center; // Use the greater of the two radii const double rad = (hole_i.radius > hole_j.radius) ? hole_i.radius : hole_j.radius; const double radSq = rad * rad; // Check periodic conditions // Convert diffVec to fractional units this->cartToFrac(&diffVec); // Adjust each component to range [-0.5, 0.5] (shortest representation) while (diffVec.x() < -0.5) ++diffVec.x(); while (diffVec.y() < -0.5) ++diffVec.y(); while (diffVec.z() < -0.5) ++diffVec.z(); while (diffVec.x() > 0.5) --diffVec.x(); while (diffVec.y() > 0.5) --diffVec.y(); while (diffVec.z() > 0.5) --diffVec.z(); // Back to cartesian this->fracToCart(&diffVec); // if j is within i's radius, add "j" to the merge list // and mark "j" as merged if (fabs(diffVec.x()) > rad || fabs(diffVec.y()) > rad || fabs(diffVec.z()) > rad || fabs(diffVec.squaredNorm()) > radSq) continue; // no match // match: // Reset j's position to account for periodic wrap-around hole_j.center = hole_i.center + diffVec; mask.clearBit(j); toMerge.push_back(&hole_j); } if (toMerge.size() == 1) this->holes.push_back(hole_i); else this->holes.push_back(reduceHoles(toMerge)); } }
void VolumeMask::findConnectedRegion(QList<int> pos) { QBitArray bitcopy = m_bitmask; m_bitmask.fill(false); QStack<int> stack; // put the seeds in for(int pi=0; pi<pos.size()/3; pi++) { int d = pos[3*pi]; int w = pos[3*pi+1]; int h = pos[3*pi+2]; qint64 idx = d*m_width*m_height + w*m_height + h; if (bitcopy.testBit(idx)) { uchar mask; uchar *mslice = m_maskFileManager.rawValue(d, w, h); if (mslice) mask = mslice[0]; if (mask != Global::tag()) { m_bitmask.setBit(idx); stack.push(d); stack.push(w); stack.push(h); } } } uchar tag = Global::tag(); while(!stack.isEmpty()) { int h = stack.pop(); int w = stack.pop(); int d = stack.pop(); qint64 idx = d*m_width*m_height + w*m_height + h; if (bitcopy.testBit(idx)) { int d0 = qMax(d-1, 0); int d1 = qMin(d+1, m_depth-1); int w0 = qMax(w-1, 0); int w1 = qMin(w+1, m_width-1); int h0 = qMax(h-1, 0); int h1 = qMin(h+1, m_height-1); for(int d2=d0; d2<=d1; d2++) for(int w2=w0; w2<=w1; w2++) for(int h2=h0; h2<=h1; h2++) { uchar mask; qint64 idx = d2*m_width*m_height + w2*m_height + h2; uchar *mslice = m_maskFileManager.rawValue(d2, w2, h2); if (mslice) mask = mslice[0]; if (tag == mask || (tag && !mask) || (!tag && mask) ) { if ( bitcopy.testBit(idx) && !m_bitmask.testBit(idx) ) { m_bitmask.setBit(idx); stack.push(d2); stack.push(w2); stack.push(h2); } } } } } // end find connected //------------------------------------------------------ }
void KeyWidget::paintEvent(QPaintEvent*){ const QColor bgColor(68, 64, 64); const QColor keyColor(112, 110, 110); const QColor sniperColor(130, 90, 90); const QColor highlightColor(136, 176, 240); const QColor highlightAnimColor(136, 200, 240); const QColor animColor(112, 200, 110); // Determine which keys to highlight QBitArray highlight; switch(mouseDownMode){ case SET: highlight = newSelection; break; case ADD: highlight = selection | newSelection; break; case SUBTRACT: highlight = selection & ~newSelection; break; case TOGGLE: highlight = selection ^ newSelection; break; default: highlight = selection; } QPainter painter(this); #if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) int ratio = painter.device()->devicePixelRatio(); #else int ratio = 1; #endif int wWidth = width(), wHeight = height(); KeyMap::Model model = keyMap.model(); float scale, offX, offY; drawInfo(scale, offX, offY); // Draw background painter.setPen(Qt::NoPen); painter.setRenderHint(QPainter::Antialiasing, true); if(model == KeyMap::M65){ // M65: Draw overlay if(!m65Overlay) m65Overlay = new QImage(":/img/overlay_m65.png"); const QImage& overlay = *m65Overlay; painter.setBrush(palette().brush(QPalette::Window)); painter.drawRect(0, 0, width(), height()); float oXScale = scale / 9.f, oYScale = scale / 9.f; // The overlay has a resolution of 9px per keymap unit float x = (2.f + offX) * scale, y = (-2.f + offY) * scale; // It is positioned at (2, -2) int w = overlay.width() * oXScale, h = overlay.height() * oYScale; // We need to transform the image with QImage::scaled() because painter.drawImage() will butcher it, even with smoothing enabled // However, the width/height need to be rounded to integers int iW = round(w), iH = round(h); painter.drawImage(QRectF(x - (iW - w) / 2.f, y - (iH - h) / 2.f, iW, iH), overlay.scaled(iW, iH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } else { // Otherwise, draw a solid background painter.setBrush(QBrush(bgColor)); painter.drawRect(0, 0, width(), height()); } // Draw mouse highlight (if any) if(mouseDownMode != NONE && (mouseDownX != mouseCurrentX || mouseDownY != mouseCurrentY)){ int x1 = (mouseDownX > mouseCurrentX) ? mouseCurrentX : mouseDownX; int x2 = (mouseDownX > mouseCurrentX) ? mouseDownX : mouseCurrentX; int y1 = (mouseDownY > mouseCurrentY) ? mouseCurrentY : mouseDownY; int y2 = (mouseDownY > mouseCurrentY) ? mouseDownY : mouseCurrentY; painter.setPen(QPen(highlightColor, 0.5)); QColor bColor = highlightColor; bColor.setAlpha(128); painter.setBrush(QBrush(bColor)); painter.drawRect(x1, y1, x2 - x1, y2 - y1); } // Draw key backgrounds on a separate pixmap so that a drop shadow can be applied to them. QPixmap keyBG(wWidth * ratio, wHeight * ratio); keyBG.fill(QColor(0, 0, 0, 0)); QPainter bgPainter(&keyBG); bgPainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); bgPainter.setPen(Qt::NoPen); QHashIterator<QString, Key> k(keyMap); uint i = -1; while(k.hasNext()){ k.next(); i++; const Key& key = k.value(); float x = key.x + offX - key.width / 2.f + 1.f; float y = key.y + offY - key.height / 2.f + 1.f; float w = key.width - 2.f; float h = key.height - 2.f; // In RGB mode, ignore keys without LEDs if((_rgbMode && !key.hasLed) || (!_rgbMode && !key.hasScan)) continue; // Set color based on key highlight bgPainter.setOpacity(1.); if(highlight.testBit(i)){ if(animation.testBit(i)) bgPainter.setBrush(QBrush(highlightAnimColor)); else bgPainter.setBrush(QBrush(highlightColor)); } else if(animation.testBit(i)){ bgPainter.setBrush(QBrush(animColor)); } else { if(!strcmp(key.name, "sniper")) // Sniper key uses a reddish base color instead of the usual grey bgPainter.setBrush(QBrush(sniperColor)); else { bgPainter.setBrush(QBrush(keyColor)); if(KeyMap::isMouse(model)) bgPainter.setOpacity(0.7); } } if(!strcmp(key.name, "mr") || !strcmp(key.name, "m1") || !strcmp(key.name, "m2") || !strcmp(key.name, "m3") || !strcmp(key.name, "light") || !strcmp(key.name, "lock") || (model == KeyMap::K65 && !strcmp(key.name, "mute"))){ // Switch keys are circular x += w / 8.f; y += h / 8.f; w *= 0.75f; h *= 0.75f; bgPainter.drawEllipse(QRectF(x * scale, y * scale, w * scale, h * scale)); } else { if(!strcmp(key.name, "enter")){ if(key.height == 24){ // ISO enter key isn't rectangular y = key.y + 1.f; h = 10.f; bgPainter.drawRect(QRectF((x + w - 13.f) * scale, y * scale, 13.f * scale, 22.f * scale)); } else { // US enter key isn't perfectly centered, needs an extra pixel on the left to appear correctly x -= 1.f; w += 1.f; } } else if(!strcmp(key.name, "rshift") || !strcmp(key.name, "stop")){ // A few other keys also need extra pixels x -= 1.f; w += 1.f; } else if(!strcmp(key.name, "caps") || !strcmp(key.name, "lshift") || !strcmp(key.name, "next")){ w += 1.f; } bgPainter.drawRect(QRectF(x * scale, y * scale, w * scale, h * scale)); } } // Render the key decorations (RGB -> light circles, binding -> key names) on yet another layer QPixmap decoration(wWidth * ratio, wHeight * ratio); decoration.fill(QColor(0, 0, 0, 0)); QPainter decPainter(&decoration); decPainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); if(_rgbMode){ // Draw key colors (RGB mode) decPainter.setPen(QPen(QColor(255, 255, 255), 1.5)); QHashIterator<QString, Key> k(keyMap); uint i = -1; while(k.hasNext()){ k.next(); i++; const Key& key = k.value(); if(!key.hasLed) continue; float x = key.x + offX - 1.8f; float y = key.y + offY - 1.8f; float w = 3.6f; float h = 3.6f; if(_displayColorMap.contains(key.name)) decPainter.setBrush(QBrush(_displayColorMap.value(key.name))); else decPainter.setBrush(QBrush(_colorMap.value(key.name))); decPainter.drawEllipse(QRectF(x * scale, y * scale, w * scale, h * scale)); } } else { // Draw key names decPainter.setBrush(Qt::NoBrush); QFont font = painter.font(); font.setBold(true); font.setPixelSize(5.25f * scale); QFont font0 = font; QHashIterator<QString, Key> k(keyMap); uint i = -1; while(k.hasNext()){ k.next(); i++; const Key& key = k.value(); if(!key.hasScan) continue; float x = key.x + offX - key.width / 2.f + 1.f; float y = key.y + offY - key.height / 2.f; float w = key.width - 2.f; float h = key.height; // Print the key's friendly name (with some exceptions) QString keyName = KbBind::globalRemap(key.name); QString name = key.friendlyName(false); name = name.split(" ").last(); struct { const char* keyName, *displayName; } names[] = { {"light", "☼"}, {"lock", "☒"}, {"mute", "◖⊘"}, {"volup", keyMap.model() == KeyMap::K65 ? "◖))" : "▲"}, {"voldn", keyMap.model() == KeyMap::K65 ? "◖)" : "▼"}, {"prtscn", "PrtScn\nSysRq"}, {"scroll", "Scroll\nLock"}, {"pause", "Pause\nBreak"}, {"stop", "▪"}, {"prev", "|◂◂"}, {"play", "▸||"}, {"next", "▸▸|"}, {"pgup", "Page\nUp"}, {"pgdn", "Page\nDown"}, {"numlock", "Num\nLock"}, {"caps", "Caps"}, {"lshift", "Shift"}, {"rshift", "Shift"}, #ifdef Q_OS_MACX {"lctrl", "⌃"}, {"rctrl", "⌃"}, {"lwin", "⌘"}, {"rwin", "⌘"}, {"lalt", "⌥"}, {"ralt", "⌥"}, #else {"lctrl", "Ctrl"}, {"rctrl", "Ctrl"}, {"lwin", "❖"}, {"rwin", "❖"}, {"lalt", "Alt"}, {"ralt", "Alt"}, #endif {"rmenu", "▤"}, {"up", "▲"}, {"left", "◀"}, {"down", "▼"}, {"right", "▶"}, {"mouse1", ""}, {"mouse2", ""}, {"mouse3", "∙"}, {"dpiup", "▲"}, {"dpidn", "▼"}, {"wheelup", "▲"}, {"wheeldn", "▼"}, {"dpi", "◉"}, {"mouse5", "▲"}, {"mouse4", "▼"}, {"sniper", "⊕"} }; for(uint k = 0; k < sizeof(names) / sizeof(names[0]); k++){ if(keyName == names[k].keyName){ name = names[k].displayName; break; } } if(keyName == "mr" || keyName == "m1" || keyName == "m2" || keyName == "m3" || keyName == "up" || keyName == "down" || keyName == "left" || keyName == "right") // Use a smaller size for MR, M1 - M3, and arrow keys font.setPixelSize(font.pixelSize() * 0.75); else if(keyName == "end") // Use a smaller size for "End" to match everything else in that area font.setPixelSize(font.pixelSize() * 0.65); else if(keyName == "light" #ifndef Q_OS_MACX || keyName == "lwin" || keyName == "rwin" #endif ) // Use a larger font size for Super (Linux only) and Brightness to compensate for the unicode symbols looking smaller font.setPixelSize(font.pixelSize() * 1.3); // Determine the appropriate size to draw the text at decPainter.setFont(font); QRectF rect(x * scale, y * scale - 1, w * scale, h * scale); int flags = Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextWordWrap; QRectF bounds = decPainter.boundingRect(rect, flags, name); while((bounds.height() >= rect.height() - 8. || bounds.width() >= rect.width() - 2.) && font.pixelSize() >= 5){ // Scale font size down until it fits inside the key font.setPixelSize(font.pixelSize() - 2); decPainter.setFont(font); bounds = decPainter.boundingRect(rect, flags, name); } // Pick color based on key function QString bind = _bindMap.value(key.name); QString def = KbBind::defaultAction(key.name); if(bind.isEmpty()) // Unbound - red decPainter.setPen(QColor(255, 136, 136)); else if(KeyAction(bind).isProgram()) // Custom program - orange decPainter.setPen(QColor(255, 224, 192)); else if(KeyAction(bind).isSpecial() && (bind == def || !KeyAction(def).isSpecial())) // Special function - blue (only if not mapped to a different function - if a special function is remapped, color it yellow) decPainter.setPen(QColor(128, 224, 255)); else if(KeyAction(bind).isMedia() && (bind == def || !KeyAction(def).isMedia())) // Media key - green decPainter.setPen(QColor(160, 255, 168)); else if(bind == def) // Standard key - white decPainter.setPen(QColor(255, 255, 255)); else // Remapped key - yellow decPainter.setPen(QColor(255, 248, 128)); decPainter.drawText(rect, flags, name); font = font0; } } // Create drop shadow effects QGraphicsDropShadowEffect* bgEffect = new QGraphicsDropShadowEffect; // Have to use "new", creating these on the stack causes a crash... bgEffect->setBlurRadius(2.); bgEffect->setColor(QColor(0, 0, 0, 32)); bgEffect->setOffset(0, 1); QGraphicsDropShadowEffect* decEffect = new QGraphicsDropShadowEffect; decEffect->setBlurRadius(4.); decEffect->setColor(QColor(0, 0, 0, 104)); decEffect->setOffset(0, 1); // Apply them to the pixmaps QGraphicsPixmapItem* bgItem = new QGraphicsPixmapItem(keyBG); bgItem->setGraphicsEffect(bgEffect); QGraphicsPixmapItem* decItem = new QGraphicsPixmapItem(decoration); decItem->setGraphicsEffect(decEffect); // Render everything QGraphicsScene* scene = new QGraphicsScene; scene->addItem(bgItem); scene->addItem(decItem); // It has to be rendered onto yet another pixmap or else DPI scaling will look terrible... QPixmap final(wWidth * ratio, wHeight * ratio); final.fill(QColor(0, 0, 0, 0));