// src/CommonWidgets.cpp #include "CommonWidgets.h" #include #include #include #include #include #include #include // --- PlaylistDelegate Implementation --- void PlaylistDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { painter->save(); painter->setRenderHint(QPainter::Antialiasing); // Background if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, QColor(50, 50, 50)); } else { painter->fillRect(option.rect, QColor(17, 17, 17)); // Match list background } QRect r = option.rect.adjusted(5, 5, -5, -5); // Icon / Art QPixmap art = index.data(Qt::DecorationRole).value(); QRect iconRect(r.left(), r.top(), 50, 50); if (!art.isNull()) { // Draw scaled art painter->drawPixmap(iconRect, art.scaled(iconRect.size(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); } else { // Placeholder painter->fillRect(iconRect, QColor(40, 40, 40)); } // Text QRect textRect = r.adjusted(60, 0, 0, 0); QString title = index.data(Qt::DisplayRole).toString(); QString artist = index.data(Qt::UserRole + 1).toString(); // Title painter->setPen(Qt::white); QFont f = option.font; f.setBold(true); f.setPointSize(14); painter->setFont(f); // Calculate height for title QFontMetrics fmTitle(f); int titleHeight = fmTitle.height(); QRect titleRect = textRect; titleRect.setHeight(titleHeight); QString elidedTitle = fmTitle.elidedText(title, Qt::ElideRight, titleRect.width()); painter->drawText(titleRect, Qt::AlignLeft | Qt::AlignTop, elidedTitle); // Artist painter->setPen(QColor(170, 170, 170)); f.setBold(false); f.setPointSize(12); painter->setFont(f); QFontMetrics fmArtist(f); QRect artistRect = textRect; artistRect.setTop(titleRect.bottom() + 2); artistRect.setHeight(fmArtist.height()); QString elidedArtist = fmArtist.elidedText(artist, Qt::ElideRight, artistRect.width()); painter->drawText(artistRect, Qt::AlignLeft | Qt::AlignTop, elidedArtist); // Separator painter->setPen(QColor(34, 34, 34)); painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight()); painter->restore(); } QSize PlaylistDelegate::sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const { return QSize(0, 60); } // --- XYPad --- XYPad::XYPad(const QString& title, QWidget* parent) : QWidget(parent), m_title(title) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setMinimumHeight(150); setCursor(Qt::CrossCursor); } void XYPad::setFormatter(std::function formatter) { m_formatter = formatter; } void XYPad::setValues(float x, float y) { m_x = std::clamp(x, 0.0f, 1.0f); m_y = std::clamp(y, 0.0f, 1.0f); update(); } void XYPad::paintEvent(QPaintEvent*) { QPainter p(this); p.setRenderHint(QPainter::Antialiasing); p.fillRect(rect(), QColor(40, 40, 40, 200)); p.setPen(QPen(QColor(80, 80, 80), 1)); p.drawRect(rect().adjusted(0, 0, -1, -1)); p.setPen(QPen(QColor(60, 60, 60), 1, Qt::DotLine)); p.drawLine(width()/2, 0, width()/2, height()); p.drawLine(0, height()/2, width(), height()/2); int px = m_x * width(); int py = (1.0f - m_y) * height(); p.setPen(Qt::NoPen); p.setBrush(QColor(0, 212, 255, 180)); p.drawEllipse(QPoint(px, py), 12, 12); p.setBrush(Qt::white); p.drawEllipse(QPoint(px, py), 4, 4); p.setPen(QPen(QColor(0, 212, 255, 100), 1)); p.drawLine(px, 0, px, height()); p.drawLine(0, py, width(), py); p.setPen(Qt::white); QFont f = font(); f.setBold(true); f.setPointSize(10); p.setFont(f); QString text = m_title; if (m_formatter) { text += "\n" + m_formatter(m_x, m_y); } p.drawText(rect().adjusted(10, 10, -10, -10), Qt::AlignLeft | Qt::AlignTop, text); } void XYPad::mousePressEvent(QMouseEvent* event) { updateFromPos(event->pos()); } void XYPad::mouseMoveEvent(QMouseEvent* event) { updateFromPos(event->pos()); } void XYPad::updateFromPos(const QPoint& pos) { m_x = std::clamp((float)pos.x() / width(), 0.0f, 1.0f); m_y = std::clamp(1.0f - (float)pos.y() / height(), 0.0f, 1.0f); update(); emit valuesChanged(m_x, m_y); } OverlayWidget::OverlayWidget(QWidget* content, QWidget* parent) : QWidget(parent), m_content(content) { QPalette pal = palette(); pal.setColor(QPalette::Window, QColor(0, 0, 0, 100)); setAutoFillBackground(true); setPalette(pal); QVBoxLayout* layout = new QVBoxLayout(this); layout->setAlignment(Qt::AlignCenter); layout->setContentsMargins(20, 20, 20, 20); content->setParent(this); content->setMaximumWidth(500); content->setMaximumHeight(600); layout->addWidget(content); hide(); } void OverlayWidget::mousePressEvent(QMouseEvent* event) { if (!m_content->geometry().contains(event->pos())) { hide(); } } void OverlayWidget::paintEvent(QPaintEvent* event) { QPainter p(this); p.fillRect(rect(), QColor(0, 0, 0, 100)); } WelcomeWidget::WelcomeWidget(QWidget* parent) : QWidget(parent) { QVBoxLayout* layout = new QVBoxLayout(this); layout->setAlignment(Qt::AlignCenter); layout->setSpacing(20); QLabel* title = new QLabel("Yr Crystals", this); title->setStyleSheet("color: white; font-size: 32px; font-weight: bold;"); title->setAlignment(Qt::AlignCenter); layout->addWidget(title); QString btnStyle = "QPushButton { background-color: #333; color: white; border: 1px solid #555; border-radius: 8px; padding: 15px; font-size: 18px; } QPushButton:pressed { background-color: #555; }"; QPushButton* btnFile = new QPushButton("Open File", this); btnFile->setStyleSheet(btnStyle); btnFile->setFixedWidth(250); connect(btnFile, &QPushButton::clicked, this, &WelcomeWidget::openFileClicked); layout->addWidget(btnFile); QPushButton* btnFolder = new QPushButton("Open Folder", this); btnFolder->setStyleSheet(btnStyle); btnFolder->setFixedWidth(250); connect(btnFolder, &QPushButton::clicked, this, &WelcomeWidget::openFolderClicked); layout->addWidget(btnFolder); }