void Layout::draw(QPainter* painter, float width, float height) { if (hasBackgroundColor()) painter->fillRect(0, 0, width, height, getBackgroundColor()); if (background_image) { if (width == background_image->width() && height == background_image->height()) painter->drawPixmap(QRectF(0, 0, width, height), *background_image, QRectF(0, 0, background_image->width(), background_image->height())); else { if (!background_image_cache || background_image_cache->width() != width || background_image_cache->height() != height) { delete background_image_cache; background_image_cache = new QPixmap(width, height); QPainter cache_painter(background_image_cache); cache_painter.setRenderHint(QPainter::SmoothPixmapTransform, true); cache_painter.drawPixmap(QRectF(0, 0, width, height), *background_image, QRectF(0, 0, background_image->width(), background_image->height())); cache_painter.setRenderHint(QPainter::SmoothPixmapTransform, false); } painter->drawPixmap(QRectF(0, 0, width, height), *background_image_cache, QRectF(0, 0, background_image_cache->width(), background_image_cache->height())); } } for (std::map<QString, Point*>::iterator it = points.begin(); it != points.end(); ++it) { Point* point = it->second; Font* font_data = point->strong_font ? point->font_strong : point->font_normal; QFont font = qFontFromFont(font_data, height); QFontMetricsF font_metrics(font); // NOTE: Could optimize this by caching the size float text_width = font_metrics.width(point->text); float text_height = font_metrics.height(); // TODO: Count lines QRectF rect = QRectF(point->pos.x()*width - 0.5f*text_width, point->pos.y()*height - 0.5f*text_height, text_width, text_height); Qt::Alignment alignment = point->alignment; if (point->alignment & Qt::AlignLeft) rect.translate(0.5f*text_width, 0); else if (point->alignment & Qt::AlignRight) rect.translate(-0.5f*text_width, 0); if (point->alignment & Qt::AlignTop) rect.translate(0, 0.5f*text_height); else if (point->alignment & Qt::AlignBottom) rect.translate(0, -0.5f*text_height); else if (point->alignment & Qt::AlignAbsolute) { rect.translate(0, 0.5f*text_height - font_metrics.ascent()); alignment = (alignment & ~Qt::AlignAbsolute) | Qt::AlignVCenter; } painter->setFont(font); painter->setPen(font_data->color); if (point->max_width > 0) painter->drawText(rect, alignment, font_metrics.elidedText(point->text, Qt::ElideMiddle, point->max_width*width)); else painter->drawText(rect, alignment, point->text); } }
void PlaylistView::paintEvent(QPaintEvent* event) { // Reimplemented to draw the background image. // Reimplemented also to draw the drop indicator // When the user is dragging some stuff over the playlist paintEvent gets // called for the entire viewport every time the user moves the mouse. // The drawTree is kinda expensive, so we cache the result and draw from the // cache while the user is dragging. The cached pixmap gets invalidated in // dragLeaveEvent, dropEvent and scrollContentsBy. // Draw background if (background_image_type_ == Custom || background_image_type_ == AlbumCover) { if (!background_image_.isNull() || !previous_background_image_.isNull()) { QPainter background_painter(viewport()); // Check if we should recompute the background image if (height() != last_height_ || width() != last_width_ || force_background_redraw_) { if (background_image_.isNull()) { cached_scaled_background_image_ = QPixmap(); } else { cached_scaled_background_image_ = QPixmap::fromImage(background_image_.scaled( width(), height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); } last_height_ = height(); last_width_ = width(); force_background_redraw_ = false; } // Actually draw the background image if (!cached_scaled_background_image_.isNull()) { // Set opactiy only if needed, as this deactivate hardware acceleration if (!qFuzzyCompare(previous_background_image_opacity_, qreal(0.0))) { background_painter.setOpacity(1.0 - previous_background_image_opacity_); } background_painter.drawPixmap( (width() - cached_scaled_background_image_.width()) / 2, (height() - cached_scaled_background_image_.height()) / 2, cached_scaled_background_image_); } // Draw the previous background image if we're fading if (!previous_background_image_.isNull()) { background_painter.setOpacity(previous_background_image_opacity_); background_painter.drawPixmap( (width() - previous_background_image_.width()) / 2, (height() - previous_background_image_.height()) / 2, previous_background_image_); } } } QPainter p(viewport()); if (drop_indicator_row_ != -1) { if (cached_tree_.isNull()) { cached_tree_ = QPixmap(size()); cached_tree_.fill(Qt::transparent); QPainter cache_painter(&cached_tree_); drawTree(&cache_painter, event->region()); } p.drawPixmap(0, 0, cached_tree_); } else { drawTree(&p, event->region()); return; } const int first_column = header_->logicalIndex(0); // Find the y position of the drop indicator QModelIndex drop_index = model()->index(drop_indicator_row_, first_column); int drop_pos = -1; switch (dropIndicatorPosition()) { case QAbstractItemView::OnItem: return; // Don't draw anything case QAbstractItemView::AboveItem: drop_pos = visualRect(drop_index).top(); break; case QAbstractItemView::BelowItem: drop_pos = visualRect(drop_index).bottom() + 1; break; case QAbstractItemView::OnViewport: if (model()->rowCount() == 0) drop_pos = 1; else drop_pos = 1 + visualRect(model()->index(model()->rowCount() - 1, first_column)).bottom(); break; } // Draw a nice gradient first QColor line_color(QApplication::palette().color(QPalette::Highlight)); QColor shadow_color(line_color.lighter(140)); QColor shadow_fadeout_color(shadow_color); shadow_color.setAlpha(255); shadow_fadeout_color.setAlpha(0); QLinearGradient gradient(QPoint(0, drop_pos - kDropIndicatorGradientWidth), QPoint(0, drop_pos + kDropIndicatorGradientWidth)); gradient.setColorAt(0.0, shadow_fadeout_color); gradient.setColorAt(0.5, shadow_color); gradient.setColorAt(1.0, shadow_fadeout_color); QPen gradient_pen(QBrush(gradient), kDropIndicatorGradientWidth * 2); p.setPen(gradient_pen); p.drawLine(QPoint(0, drop_pos), QPoint(width(), drop_pos)); // Now draw the line on top QPen line_pen(line_color, kDropIndicatorWidth); p.setPen(line_pen); p.drawLine(QPoint(0, drop_pos), QPoint(width(), drop_pos)); }