/*************************************************************************** * Copyright (C) by * * - 2005: Christian Leh * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "magiclabel.h" #include "thememoodin.h" K_EXPORT_COMPONENT_FACTORY(ksplashmoodin, KGenericFactory("ksplash")) ThemeMoodin::ThemeMoodin(TQWidget* parent, const char* name, const TQStringList& args) :ThemeEngine(parent, name, args) { readSettings(); init(); } void ThemeMoodin::readSettings() { const TQRect screen = kapp->desktop()->screenGeometry(mTheme->xineramaScreen()); if (!mTheme) return; TDEConfig* cfg = mTheme->themeConfig(); if (!cfg) return; cfg->setGroup(TQString("KSplash Theme: %1").arg(mTheme->theme())); TQFont defaultFont("Trebuchet MS", 10); TQFont defaultStatusFont("Trebuchet MS", 12, TQFont::Bold); TQColor defaultColor(0xFF, 0xFF, 0xFF); TQColor defaultShadowColor(0x6D, 0x6D, 0x6D); TQPoint defaultPoint(-1, -1), defaultOffset(0, 0); TQString defaultIcon; mCurrentStatusIndex = 0; mSplashRect = cfg->readRectEntry("SplashRect", &screen); mBackgroundImage = cfg->readEntry("Background", TQString()); mStatusColor = cfg->readColorEntry("StatusColor", &defaultColor); mStatusFont = cfg->readFontEntry("StatusFont", &defaultStatusFont); mStatusCoords = cfg->readPointEntry("StatusCoords", &defaultPoint); mLabelShadow = cfg->readBoolEntry("LabelShadow", true); mLabelShadowColor = cfg->readColorEntry("LabelShadowColor", &defaultShadowColor); mShowStatusText = cfg->readBoolEntry("ShowStatusText", true); mAnimationLength = cfg->readNumEntry("AnimationLength", 30); mAnimationDelay = cfg->readNumEntry("AnimationDelay", 30); mBeginOpacity = cfg->readDoubleNumEntry("BeginOpacity", 0.20); mUseIconSet = cfg->readBoolEntry("UseIconSet", true); mIconSetSize = cfg->readNumEntry("IconSetSize", 48); mAppendX = cfg->readBoolEntry("AppendX", true); mImageSpacer = cfg->readNumEntry("ImageSpacer", mUseIconSet ? mIconSetSize : 0); mUsersBackground = cfg->readBoolEntry("UsersBackground", false); mLabelCount = cfg->readNumEntry("Labels", 0); mLabelShadowOffset = cfg->readPointEntry("LabelShadowOffset", new TQPoint(2, 2)); mBaseResolution = cfg->readSizeEntry("BaseResolution", new TQSize(1280, 1024)); mTranslate = cfg->readBoolEntry("Translate", true); mLineUpImages = cfg->readBoolEntry("LineUpImages", false); mKubuntuStyle = cfg->readBoolEntry("KubuntuStyle", false); // so we can centre icons, JRiddell int iconX = mBaseResolution.width(); int iconY = mBaseResolution.height(); TQRect defaultScreen = kapp->desktop()->screenGeometry(0); float scaleRatioWidth = ((float)mBaseResolution.width()) / ((float)defaultScreen.width()); // unused. float scaleRatioHeight = ((float)mBaseResolution.height()) / ((float)desktopWidget.height()); iconX = iconX / 2; // first icon position calculated based on size and spacing // Edgy Dialog.png is off centre so take off random 8 pixels iconX = iconX - (int)((((mIconSetSize+mImageSpacer)*4) - 8) * scaleRatioWidth); // Edgy Dialog.png is off centre so add random 20 pixels iconY = (iconY / 2) + 20; for (int i = 0; i < int(statusPixmaps().count()); i++) { if (mUseIconSet) defaultIcon = statusPixmaps()[i]; else defaultIcon = TQString("%1.png").arg(i + 1); mStatusIcons.append(cfg->readEntry(TQString("Image%1").arg(i + 1), defaultIcon)); if (mKubuntuStyle) { TQPoint *mypoint; mypoint = new TQPoint((int)(iconX + (i * (mIconSetSize+mImageSpacer) * scaleRatioWidth)), iconY); mStatusIconCoords.append( *mypoint ); } else { mStatusIconCoords.append(cfg->readPointEntry(TQString("ImageCoords%1").arg(i + 1), &defaultPoint)); } mStatusImageOffsets.append(cfg->readPointEntry(TQString("ImageOffset%1").arg(i + 1), &defaultOffset)); mStatusMessages.append(cfg->readEntry(TQString("StatusMessage%1").arg(i + 1), TQString())); } for (int i = 0; i < mLabelCount; i++) { mLabels.append(cfg->readEntry(TQString("Label%1").arg(i + 1), TQString())); mLabelCoords.append(cfg->readPointEntry(TQString("LabelCoords%1").arg(i + 1), &defaultPoint)); mLabelFonts.append(cfg->readFontEntry(TQString("LabelFont%1").arg(i + 1), &defaultFont)); mLabelColors.append(cfg->readColorEntry(TQString("LabelColor%1").arg(i + 1), &defaultColor)); } } void ThemeMoodin::init() { setBackgroundMode(NoBackground); setFixedSize(mSplashRect.size()); mContainer = new TQWidget(this); mContainer->setFixedSize(size()); mScaler = new Scaler(mBaseResolution, size()); mCache = new Cache(mScaler, mTheme->themeEngine(), mTheme->theme()); mBG = new KPixmap(); mBG->resize(size()); TQPainter p; p.begin(mBG); initBackground(&p); initLabels(&p); initEffectWidgets(); p.end(); move(mSplashRect.topLeft()); } void ThemeMoodin::initBackground(TQPainter* p) { if (!p) return; TQString bgImage; bool scaleBgImage; if (mUsersBackground) { TDEConfig kdesktoprc("kdesktoprc", true, false); kdesktoprc.setGroup("Background Common"); int num = kdesktoprc.readNumEntry("DeskNum", 0); kdesktoprc.setGroup(TQString("Desktop%1").arg(num)); bgImage = kdesktoprc.readPathEntry("Wallpaper", TQString()); if (kdesktoprc.readPathEntry("WallpaperMode", TQString()) == "Scaled") { scaleBgImage = true; } else { scaleBgImage = false; } } else { if (!mBackgroundImage.isEmpty()) bgImage = mTheme->locateThemeData(mBackgroundImage); scaleBgImage = false; } if (bgImage.isEmpty()) { bgImage = mTheme->locateThemeData(TQString("Background-%1x%2.jpg").arg(width()).arg(height())); scaleBgImage = false; } if (bgImage.isEmpty()) { bgImage = mTheme->locateThemeData("Background.jpg"); scaleBgImage = true; } if (bgImage.isEmpty()) { KMessageBox::error(this, i18n("No background. Try to put a Background.jpg in theme folder")); return; } TQImage* bg = mCache->cacheFile(bgImage); if (scaleBgImage) { p->drawImage(0, 0, (*bg).scale(width(), height())); } else { p->drawImage(0, 0, *bg); } delete bg; if (mKubuntuStyle) { //central Dialogue, JRiddell TQImage* central = new TQImage( mTheme->locateThemeData("Dialog.png") ); p->drawImage((mBG->width() / 2) - (462 / 2), (mBG->height() / 2) - (324 / 2), *central); delete central; } } void ThemeMoodin::initLabels(TQPainter* p) { if ((mLabelCount == 0) || (!p)) return; for (int i = 0; i < mLabelCount; i++) { TQString s = mLabels[i]; TQPoint pt = mLabelCoords[i]; TQColor c = mLabelColors[i]; TQFont f = mLabelFonts[i]; if (s.isNull() || s.isEmpty()) continue; MagicLabel ml(s, mTranslate); s = ml.value(); mScaler->scaleSize(&f); mScaler->autoCoords(&pt, f, s); p->setFont(f); if (mLabelShadow) { p->setPen(mLabelShadowColor); p->drawText(pt + mLabelShadowOffset, s); } p->setPen(c); p->drawText(pt, s); } } void ThemeMoodin::initEffectWidgets() { EffectWidget::setBackgroundImage(new TQImage(mBG->convertToImage())); EffectWidget *fadeWidget = 0; TQImage *image = 0; int index = -1; for (TQStringList::ConstIterator it = mStatusIcons.constBegin(); it != mStatusIcons.constEnd(); ++it) { index++; if (mUseIconSet) { if ((*it).isEmpty()) continue; // TODO: use cache in iconset mode TQPixmap* px = new TQPixmap(DesktopIcon(*it, mIconSetSize)); image = new TQImage(px->convertToImage()); // JRiddell don't scale icons if (!mKubuntuStyle) { mScaler->scaleSize(image); } } else { TQString name = mTheme->locateThemeData(*it); if (name.isEmpty()) continue; image = mCache->cacheFile(name); if (image->isNull()) { delete image; continue; } } fadeWidget = createEffectWidget(mContainer, image); mEffectWidgets.append(fadeWidget); mImages.append(image); arrangeWidget(fadeWidget, index); } for (EffectWidget *fw = mEffectWidgets.first(); fw; fw = mEffectWidgets.next()) fw->updateCache(); } void ThemeMoodin::arrangeWidget(TQWidget* w, const int index) { TQPoint current(mStatusIconCoords[index]); if (mLineUpImages) { static bool first = true; if (first) { int hw = mAppendX ? width() : height(); int hwi = mAppendX ? height() : width(); int icons = mStatusIcons.count() * mIconSetSize; int spaces = (mStatusIcons.count() - 1) * mIconSetSize;// + int(float(mIconSetSize) * 0.5); int q = int((hwi - mIconSetSize) / 2); int r = int((hw - icons - spaces) / 2); int x = mAppendX ? r : q; int y = mAppendX ? q : r; current.setX(x); current.setY(y); first = false; } else { int x = mAppendX ? mIconSetSize * 2 : 0; int y = mAppendX ? 0 : mIconSetSize * 2; current = mStatusIconCoords[index - 1] + TQPoint(x, y); } } else { mScaler->autoCoords(¤t, TQSize(mIconSetSize, mIconSetSize)); current += mStatusImageOffsets[index]; } mStatusIconCoords[index] = current; w->move(current); } EffectWidget* ThemeMoodin::createEffectWidget(TQWidget* parent, TQImage* image) { EffectWidget *fw = new EffectWidget(parent); fw->hide(); fw->setBackgroundOrigin(TQWidget::WindowOrigin); fw->setDelay(mAnimationDelay); fw->setSteps(mAnimationLength); fw->setFixedSize(image->size()); fw->setImage(image); fw->setStart(mBeginOpacity); fw->show(); return fw; } void ThemeMoodin::slotSetText(const TQString& s) { if (mShowStatusText) { if (!mStatusMessages[mCurrentStatusIndex].isNull()) mCurrentAction = mStatusMessages[mCurrentStatusIndex]; else mCurrentAction = s; } } void ThemeMoodin::slotSetPixmap(const TQString& s) { if (!mEffectWidgets.count() > 0) return; int n = statusPixmaps().findIndex(s); if (n == -1) return; mCurrentStatusIndex = n + 1; EffectWidget *fw = mEffectWidgets.at(n); if (fw) fw->start(); repaint(false); } void ThemeMoodin::updateStatus() { TQPainter p; p.begin(mContainer); // use a copy, otherwise status messages move around TQPoint pt = mStatusCoords; TQFontMetrics fm(mStatusFont); TQSize fmSize(fm.size(0L, mCurrentAction)); mScaler->autoCoords(&pt, fmSize); p.setFont(mStatusFont); if (mLabelShadow) { p.setPen(mLabelShadowColor); p.drawText(pt + mLabelShadowOffset, mCurrentAction); } p.setPen(mStatusColor); p.drawText(pt, mCurrentAction); p.end(); } void ThemeMoodin::paintEvent(TQPaintEvent* pe) { TQRect r = pe->rect(); bitBlt(mContainer, r.x(), r.y(), mBG, r.x(), r.y(), r.width(), r.height()); if (mShowStatusText) updateStatus(); } #include "thememoodin.moc"