kde-extraapps/kdeplasma-addons/wallpapers/virus/virus.cpp
Ivailo Monev 246f75dd09 kdeplasma-addons: do not suspend startup from virus wallpaper
done by plasma-desktop itself, see:
kde-workspace/plasma/shells/plasma-desktop/plasmaapp.cpp

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2023-08-31 19:51:02 +03:00

424 lines
12 KiB
C++

/*
Copyright (c) 2009 by Beat Wolf <asraniel@fryx.ch>
Copyright (c) 2007 by Paolo Capriotti <p.capriotti@gmail.com>
Copyright (c) 2007 by Aaron Seigo <aseigo@kde.org>
Copyright (c) 2008 by Alexis Ménard <darktears31@gmail.com>
Copyright (c) 2008 by Petri Damsten <damu@iki.fi>
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 "virus.h"
#include <QPainter>
#include <KDebug>
#include <KDirWatch>
#include <KFileDialog>
#include <KStandardDirs>
#include <KImageIO>
#include <Plasma/Theme>
#include <Plasma/Animator>
#include "backgroundlistmodel.h"
#include "backgrounddelegate.h"
K_EXPORT_PLASMA_WALLPAPER(virus, Virus)
Virus::Virus(QObject *parent, const QVariantList &args)
: Plasma::Wallpaper(parent, args),
m_configWidget(0),
m_model(0),
m_dialog(0)
{
connect(this, SIGNAL(renderCompleted(QImage)), this, SLOT(updateBackground(QImage)));
connect(&alife, SIGNAL(finished()), this, SLOT(virusUpdated()));
//m_timer = QTimer(this);
m_timer.setSingleShot(true);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(requestUpdate()));
}
Virus::~Virus()
{
alife.exit(0);
alife.wait();
}
void Virus::init(const KConfigGroup &config)
{
m_timer.stop();
m_mode = QLatin1String( "SingleImage" );//renderingMode().name();
calculateGeometry();
m_resizeMethod = (ResizeMethod)config.readEntry("wallpaperposition", (int)ScaledResize);
m_wallpaper = config.readEntry("wallpaper", QString());
if (m_wallpaper.isEmpty()) {
m_wallpaper = Plasma::Theme::defaultTheme()->wallpaperPath();
int index = m_wallpaper.indexOf(QLatin1String( "/contents/images/" ));
if (index > -1) { // We have file from package -> get path to package
m_wallpaper = m_wallpaper.left(index);
}
}
m_color = config.readEntry("wallpapercolor", QColor(56, 111, 150));
m_usersWallpapers = config.readEntry("userswallpapers", QStringList());
alife.setUpdateInterval(config.readEntry("updateinterval", 200));
alife.setMaxViruses(config.readEntry("maxcells", 2000));
alife.setShowCells(config.readEntry("showcells", true));
if (m_dirs.isEmpty()) {
m_dirs << KStandardDirs::installPath("wallpaper");
}
setUsingRenderingCache(false);
setSingleImage();
}
void Virus::requestUpdate()
{
alife.start();
}
void Virus::virusUpdated()
{
m_pixmap = QPixmap::fromImage(alife.currentImage());
emit update(alife.updatedArea());
m_timer.start(alife.getUpdateInterval());
}
void Virus::save(KConfigGroup &config)
{
config.writeEntry("wallpaperposition", (int)m_resizeMethod);
config.writeEntry("wallpaper", m_wallpaper);
config.writeEntry("wallpapercolor", m_color);
config.writeEntry("userswallpapers", m_usersWallpapers);
config.writeEntry("updateinterval", alife.getUpdateInterval());
config.writeEntry("maxcells",alife.getMaxViruses());
config.writeEntry("showcells",alife.showCells());
}
void Virus::configWidgetDestroyed()
{
m_configWidget = 0;
m_model = 0;
}
QWidget* Virus::createConfigurationInterface(QWidget* parent)
{
m_configWidget = new QWidget(parent);
connect(m_configWidget, SIGNAL(destroyed(QObject*)), this, SLOT(configWidgetDestroyed()));
m_uiVirus.setupUi(m_configWidget);
m_model = new BackgroundListModel(this, m_configWidget);
m_model->setResizeMethod(m_resizeMethod);
m_model->setWallpaperSize(m_size);
m_model->reload(m_usersWallpapers);
m_uiVirus.m_view->setModel(m_model);
m_uiVirus.m_view->setItemDelegate(new BackgroundDelegate(m_uiVirus.m_view));
m_uiVirus.m_view->setMinimumWidth((BackgroundDelegate::SCREENSHOT_SIZE + BackgroundDelegate::MARGIN * 2 +
BackgroundDelegate::BLUR_INCREMENT) * 3 +
m_uiVirus.m_view->spacing() * 4 +
QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent) +
QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2 + 7);
m_uiVirus.m_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QModelIndex index = m_model->indexOf(m_wallpaper);
if (index.isValid()) {
m_uiVirus.m_view->setCurrentIndex(index);
Plasma::Package *b = m_model->package(index.row());
if (b) {
fillMetaInfo(b);
}
}
connect(m_uiVirus.m_view, SIGNAL(activated(QModelIndex)), this, SLOT(pictureChanged(QModelIndex)));
m_uiVirus.m_pictureUrlButton->setIcon(KIcon(QLatin1String( "document-open" )));
connect(m_uiVirus.m_pictureUrlButton, SIGNAL(clicked()), this, SLOT(showFileDialog()));
m_uiVirus.m_resizeMethod->addItem(i18n("Scaled & Cropped"), ScaledAndCroppedResize);
m_uiVirus.m_resizeMethod->addItem(i18n("Scaled"), ScaledResize);
m_uiVirus.m_resizeMethod->addItem(i18n("Scaled, keep proportions"), MaxpectResize);
m_uiVirus.m_resizeMethod->addItem(i18n("Centered"), CenteredResize);
m_uiVirus.m_resizeMethod->addItem(i18n("Tiled"), TiledResize);
m_uiVirus.m_resizeMethod->addItem(i18n("Center Tiled"), CenterTiledResize);
for (int i = 0; i < m_uiVirus.m_resizeMethod->count(); ++i) {
if (m_resizeMethod == m_uiVirus.m_resizeMethod->itemData(i).value<int>()) {
m_uiVirus.m_resizeMethod->setCurrentIndex(i);
break;
}
}
connect(m_uiVirus.m_resizeMethod, SIGNAL(currentIndexChanged(int)),
this, SLOT(positioningChanged(int)));
m_uiVirus.m_color->setColor(m_color);
connect(m_uiVirus.m_color, SIGNAL(changed(QColor)), this, SLOT(colorChanged(QColor)));
m_uiVirus.m_maxCells->setValue(alife.getMaxViruses());
connect(m_uiVirus.m_maxCells, SIGNAL(valueChanged(int)), this, SLOT(maxCellsChanged(int)));
m_uiVirus.m_updateInterval->setValue(alife.getUpdateInterval());
connect(m_uiVirus.m_updateInterval, SIGNAL(valueChanged(int)), this, SLOT(intervalChanged(int)));
m_uiVirus.m_showCells->setChecked(alife.showCells());
connect(m_uiVirus.m_showCells, SIGNAL(stateChanged(int)), this, SLOT(showCellsChanged(int)));
connect(this, SIGNAL(settingsChanged(bool)), parent, SLOT(settingsChanged(bool)));
connect(m_uiVirus.m_view, SIGNAL(clicked(QModelIndex)), this, SLOT(modified()));
return m_configWidget;
}
void Virus::modified()
{
emit settingsChanged(true);
}
void Virus::calculateGeometry()
{
m_size = boundingRect().size().toSize();
if (m_model) {
m_model->setWallpaperSize(m_size);
}
}
void Virus::paint(QPainter *painter, const QRectF& exposedRect)
{
// Check if geometry changed
//kDebug() << m_size << boundingRect().size().toSize();
if (m_size != boundingRect().size().toSize()) {
calculateGeometry();
if (!m_size.isEmpty() && !m_img.isEmpty()) { // We have previous image
renderWallpaper();
//kDebug() << "re-rendering";
return;
}
}
if (m_pixmap.isNull()) {
painter->fillRect(exposedRect, QBrush(m_color));
//kDebug() << "pixmap null";
return;
}
if (painter->worldMatrix() == QMatrix()) {
// draw the background untransformed when possible;(saves lots of per-pixel-math)
painter->resetTransform();
}
// blit the background (saves all the per-pixel-products that blending does)
painter->setCompositionMode(QPainter::CompositionMode_Source);
// for pixmaps we draw only the exposed part (untransformed since the
// bitmapBackground already has the size of the viewport)
painter->drawPixmap(exposedRect, m_pixmap, exposedRect.translated(-boundingRect().topLeft()));
}
void Virus::setSingleImage()
{
if (m_wallpaper.isEmpty()) {
return;
}
QString img;
if (QDir::isAbsolutePath(m_wallpaper)) {
Plasma::Package b(m_wallpaper, packageStructure(this));
img = b.filePath("preferred");
kDebug() << img << m_wallpaper;
if (img.isEmpty()) {
img = m_wallpaper;
}
//if it's not an absolute path, check if it's just a wallpaper name
} else {
const QString path = KStandardDirs::locate("wallpaper", m_wallpaper + QLatin1String( "/metadata.desktop" ));
if (!path.isEmpty()) {
QDir dir(path);
dir.cdUp();
Plasma::Package b(dir.path(), packageStructure(this));
img = b.filePath("preferred");
}
}
if (!m_size.isEmpty()) {
renderWallpaper(img);
}
}
void Virus::colorChanged(const QColor& color)
{
m_color = color;
setSingleImage();
emit settingsChanged(true);
}
void Virus::pictureChanged(QModelIndex index)
{
if (index.row() == -1 || !m_model) {
return;
}
Plasma::Package *b = m_model->package(index.row());
if (!b) {
return;
}
fillMetaInfo(b);
if (b->structure()->contentsPrefixPaths().isEmpty()) {
// it's not a full package, but a single paper
m_wallpaper = b->filePath("preferred");
} else {
m_wallpaper = b->path();
}
setSingleImage();
}
void Virus::maxCellsChanged(int maxCells)
{
alife.setMaxViruses(maxCells);
emit settingsChanged(true);
}
void Virus::intervalChanged(int interval)
{
alife.setUpdateInterval(interval);
emit settingsChanged(true);
}
void Virus::showCellsChanged(int state)
{
alife.setShowCells(state == Qt::Checked);
emit settingsChanged(true);
}
void Virus::positioningChanged(int index)
{
m_resizeMethod = (ResizeMethod)m_uiVirus.m_resizeMethod->itemData(index).value<int>();
setSingleImage();
setResizeMethodHint(m_resizeMethod);
if (m_model) {
m_model->setResizeMethod(m_resizeMethod);
}
emit settingsChanged(true);
}
void Virus::fillMetaInfo(Plasma::Package *b)
{
QString author = b->metadata().author();
/*setMetadata(m_uiVirus.m_licenseLine, QString());
setMetadata(m_uiVirus.m_emailLine, QString());
m_uiVirus.m_emailLabel->hide();
m_uiVirus.m_licenseLabel->hide(); */
}
bool Virus::setMetadata(QLabel *label, const QString &text)
{
if (text.isEmpty()) {
label->hide();
return false;
}
else {
label->show();
label->setText(text);
return true;
}
}
void Virus::showFileDialog()
{
if (!m_dialog) {
m_dialog = new KFileDialog(KUrl(), KImageIO::pattern(KImageIO::Reading), m_configWidget);
m_dialog->setOperationMode(KFileDialog::Opening);
m_dialog->setInlinePreviewShown(true);
m_dialog->setCaption(i18n("Select Wallpaper Image File"));
m_dialog->setModal(false);
connect(m_dialog, SIGNAL(okClicked()), this, SLOT(wallpaperBrowseCompleted()));
connect(m_dialog, SIGNAL(destroyed(QObject*)), this, SLOT(fileDialogFinished()));
}
m_dialog->show();
m_dialog->raise();
m_dialog->activateWindow();
connect(m_dialog, SIGNAL(okClicked()), this, SLOT(browse()));
}
void Virus::browse()
{
Q_ASSERT(m_model);
const QString wallpaper = m_dialog->selectedFile();
if (wallpaper.isEmpty()) {
return;
}
if (m_model->contains(wallpaper)) {
m_uiVirus.m_view->setCurrentIndex(m_model->indexOf(wallpaper));
return;
}
// add background to the model
m_model->addBackground(wallpaper);
// select it
QModelIndex index = m_model->indexOf(wallpaper);
if (index.isValid()) {
m_uiVirus.m_view->setCurrentIndex(index);
}
// save it
m_usersWallpapers << wallpaper;
}
void Virus::renderWallpaper(const QString& image)
{
if (!image.isEmpty()) {
m_img = image;
}
if (m_img.isEmpty()) {
return;
}
render(m_img, m_size, m_resizeMethod, m_color);
}
QString Virus::cacheId() const
{
QSize s = boundingRect().size().toSize();
return QString(QLatin1String( "%5_%3_%4_%1x%2" )).arg(s.width()).arg(s.height()).arg(m_color.name()).arg(m_resizeMethod).arg(m_img);
}
void Virus::updateBackground(const QImage &img)
{
m_pixmap = QPixmap::fromImage(img);
alife.setImage(m_pixmap.toImage());
m_timer.start(alife.getUpdateInterval());
emit update(boundingRect());
}
void Virus::updateScreenshot(QPersistentModelIndex index)
{
m_uiVirus.m_view->update(index);
}
#include "moc_virus.cpp"