#include "splashscreen.h" #include "settings.h" #include #include #include #include #include #include SplashScreen::SplashScreen(QWidget *parent) : QSplashScreen() { Q_UNUSED(parent); // Load theme colors loadThemeColors(); // Create transparent pixmap QPixmap pixmap(WIDTH, HEIGHT); pixmap.fill(Qt::transparent); setPixmap(pixmap); setWindowFlags(Qt::SplashScreen | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); setAttribute(Qt::WA_TranslucentBackground); // Center on screen if (QScreen *screen = QApplication::primaryScreen()) { QRect screenGeometry = screen->geometry(); int x = (screenGeometry.width() - WIDTH) / 2; int y = (screenGeometry.height() - HEIGHT) / 2; move(x, y); } } void SplashScreen::loadThemeColors() { Theme theme = Settings::instance().theme(); mPrimaryColor = QColor(theme.accentColor); mBgColor = QColor(theme.backgroundColor); mPanelColor = QColor(theme.panelColor); mTextColor = QColor(theme.textColor); mTextColorMuted = QColor(theme.textColorMuted); mBorderColor = QColor(theme.borderColor); } void SplashScreen::setStatus(const QString &message) { mStatus = message; repaint(); QApplication::processEvents(); } void SplashScreen::setProgress(int value, int max) { mProgress = value; mProgressMax = max; repaint(); QApplication::processEvents(); } void SplashScreen::setWaitForInteraction(bool wait) { mWaitForInteraction = wait; } void SplashScreen::finish(QWidget *mainWindow) { // Always show the main window if (mainWindow) { mainWindow->show(); } if (mWaitForInteraction && !mInteractionReceived) { // Keep splash visible on top until user interacts mPendingMainWindow = mainWindow; raise(); activateWindow(); mStatus = "Click or press any key to continue..."; repaint(); return; } // Normal behavior - close splash close(); } void SplashScreen::mousePressEvent(QMouseEvent *event) { Q_UNUSED(event); mInteractionReceived = true; if (mWaitForInteraction && mPendingMainWindow) { close(); // Just close the splash } } void SplashScreen::keyPressEvent(QKeyEvent *event) { Q_UNUSED(event); mInteractionReceived = true; if (mWaitForInteraction && mPendingMainWindow) { close(); // Just close the splash } } void SplashScreen::drawContents(QPainter *painter) { painter->setRenderHint(QPainter::Antialiasing, true); painter->setRenderHint(QPainter::TextAntialiasing, true); // Create clipping path for rounded corners QPainterPath clipPath; clipPath.addRoundedRect(0, 0, WIDTH, HEIGHT, 12, 12); painter->setClipPath(clipPath); // Draw background painter->setPen(Qt::NoPen); painter->setBrush(mBgColor); painter->drawRect(0, 0, WIDTH, HEIGHT); // Draw accent stripe at top (clipped to rounded corners) painter->setBrush(mPrimaryColor); painter->drawRect(0, 0, WIDTH, 8); // Draw logo/title area QFont titleFont("Segoe UI", 36, QFont::Bold); painter->setFont(titleFont); painter->setPen(mTextColor); // App name with primary color accent QString appName = "XPlor"; QFontMetrics titleMetrics(titleFont); int titleWidth = titleMetrics.horizontalAdvance(appName); int titleX = (WIDTH - titleWidth) / 2; int titleY = 80; // Draw "X" in primary color painter->setPen(mPrimaryColor); painter->drawText(titleX, titleY, "X"); // Draw "Plor" in text color painter->setPen(mTextColor); int xWidth = titleMetrics.horizontalAdvance("X"); painter->drawText(titleX + xWidth, titleY, "Plor"); // Tagline QFont taglineFont("Segoe UI", 11); painter->setFont(taglineFont); painter->setPen(mTextColorMuted); QString tagline = "Binary File Format Explorer"; QFontMetrics taglineMetrics(taglineFont); int taglineWidth = taglineMetrics.horizontalAdvance(tagline); painter->drawText((WIDTH - taglineWidth) / 2, titleY + 25, tagline); // Version info QFont versionFont("Segoe UI", 10); painter->setFont(versionFont); painter->setPen(mTextColorMuted); QString version = QString("Version %1").arg(QCoreApplication::applicationVersion()); QFontMetrics versionMetrics(versionFont); int versionWidth = versionMetrics.horizontalAdvance(version); painter->drawText((WIDTH - versionWidth) / 2, titleY + 50, version); // Company/copyright - use QCoreApplication values QFont copyrightFont("Segoe UI", 9); painter->setFont(copyrightFont); painter->setPen(mTextColorMuted); QString orgName = QCoreApplication::organizationName(); QFontMetrics copyrightMetrics(copyrightFont); int copyrightWidth = copyrightMetrics.horizontalAdvance(orgName); painter->drawText((WIDTH - copyrightWidth) / 2, HEIGHT - 45, orgName); QString year = QString::number(QDate::currentDate().year()); int yearWidth = copyrightMetrics.horizontalAdvance(year); painter->drawText((WIDTH - yearWidth) / 2, HEIGHT - 30, year); // Progress bar background int progressX = 40; int progressY = HEIGHT - 80; int progressWidth = WIDTH - 80; int progressHeight = 6; painter->setPen(Qt::NoPen); painter->setBrush(mPanelColor); painter->drawRoundedRect(progressX, progressY, progressWidth, progressHeight, 3, 3); // Progress bar fill if (mProgressMax > 0 && mProgress > 0) { int fillWidth = (progressWidth * mProgress) / mProgressMax; if (fillWidth > 0) { // Gradient from primary to lighter QLinearGradient gradient(progressX, 0, progressX + fillWidth, 0); gradient.setColorAt(0, mPrimaryColor); gradient.setColorAt(1, mPrimaryColor.lighter(120)); painter->setBrush(gradient); painter->drawRoundedRect(progressX, progressY, fillWidth, progressHeight, 3, 3); } } // Status text if (!mStatus.isEmpty()) { QFont statusFont("Segoe UI", 9); painter->setFont(statusFont); painter->setPen(mTextColorMuted); QFontMetrics statusMetrics(statusFont); QString elidedStatus = statusMetrics.elidedText(mStatus, Qt::ElideMiddle, progressWidth); painter->drawText(progressX, progressY - 8, elidedStatus); } // Draw subtle border (disable clipping first) painter->setClipping(false); painter->setPen(QPen(mBorderColor, 1)); painter->setBrush(Qt::NoBrush); painter->drawRoundedRect(0, 0, WIDTH - 1, HEIGHT - 1, 12, 12); }