00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "image.h"
00014
00015 #include <QPainter>
00016 #include <QFile>
00017
00018 #include <KDirSelectDialog>
00019 #include <KDirWatch>
00020 #include <KFileDialog>
00021 #include <KGlobalSettings>
00022 #include <KImageFilePreview>
00023 #include <KNS/Engine>
00024 #include <KRandom>
00025 #include <KStandardDirs>
00026
00027 #include <Plasma/Theme>
00028 #include "backgroundlistmodel.h"
00029 #include "backgrounddelegate.h"
00030 #include "ksmserver_interface.h"
00031
00032
00033 Image::Image(QObject *parent, const QVariantList &args)
00034 : Plasma::Wallpaper(parent, args),
00035 m_currentSlide(-1),
00036 m_model(0),
00037 m_dialog(0),
00038 m_rendererToken(-1),
00039 m_randomize(true)
00040 {
00041 qRegisterMetaType<QImage>("QImage");
00042 connect(&m_renderer, SIGNAL(done(int, QImage)), this, SLOT(updateBackground(int, QImage)));
00043 connect(&m_timer, SIGNAL(timeout()), this, SLOT(nextSlide()));
00044 }
00045
00046 Image::~Image()
00047 {
00048 qDeleteAll(m_slideshowBackgrounds);
00049 }
00050
00051 void Image::init(const KConfigGroup &config)
00052 {
00053 m_timer.stop();
00054 m_mode = renderingMode().name();
00055 calculateGeometry();
00056
00057 m_delay = config.readEntry("slideTimer", 600);
00058 m_resizeMethod = (Background::ResizeMethod)config.readEntry("wallpaperposition",
00059 (int)Background::Scale);
00060 m_wallpaper = config.readEntry("wallpaper", QString());
00061 if (m_wallpaper.isEmpty()) {
00062 m_wallpaper = Plasma::Theme::defaultTheme()->wallpaperPath();
00063 int index = m_wallpaper.indexOf("/contents/images/");
00064 if (index > -1) {
00065 m_wallpaper = m_wallpaper.left(index);
00066 }
00067 }
00068
00069 m_color = config.readEntry("wallpapercolor", QColor(56, 111, 150));
00070 m_usersWallpapers = config.readEntry("userswallpapers", QStringList());
00071 m_dirs = config.readEntry("slidepaths", QStringList());
00072
00073 if (m_dirs.isEmpty()) {
00074 m_dirs << KStandardDirs::installPath("wallpaper");
00075 }
00076
00077 if (m_mode == "SingleImage") {
00078 setSingleImage();
00079 } else {
00080 startSlideshow();
00081 }
00082 }
00083
00084 void Image::save(KConfigGroup &config)
00085 {
00086 config.writeEntry("slideTimer", m_delay);
00087 config.writeEntry("wallpaperposition", (int)m_resizeMethod);
00088 config.writeEntry("slidepaths", m_dirs);
00089 config.writeEntry("wallpaper", m_wallpaper);
00090 config.writeEntry("wallpapercolor", m_color);
00091 config.writeEntry("userswallpapers", m_usersWallpapers);
00092 }
00093
00094 QWidget* Image::createConfigurationInterface(QWidget* parent)
00095 {
00096 m_widget = new QWidget(parent);
00097
00098 if (m_mode == "SingleImage") {
00099 m_uiImage.setupUi(m_widget);
00100
00101 m_model = new BackgroundListModel(m_ratio, this);
00102 m_uiImage.m_view->setModel(m_model);
00103 m_uiImage.m_view->setItemDelegate(new BackgroundDelegate(m_uiImage.m_view->view(),
00104 m_ratio, this));
00105 m_uiImage.m_view->view()->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
00106 m_model->reload(m_usersWallpapers);
00107 int index = m_model->indexOf(m_wallpaper);
00108 if (index != -1) {
00109 m_uiImage.m_view->setCurrentIndex(index);
00110 Background *b = m_model->package(index);
00111 if (b) {
00112 fillMetaInfo(b);
00113 }
00114 }
00115 connect(m_uiImage.m_view, SIGNAL(currentIndexChanged(int)), this, SLOT(pictureChanged(int)));
00116
00117 m_uiImage.m_pictureUrlButton->setIcon(KIcon("document-open"));
00118 connect(m_uiImage.m_pictureUrlButton, SIGNAL(clicked()), this, SLOT(showFileDialog()));
00119
00120 m_uiImage.m_emailLine->setTextInteractionFlags(Qt::TextSelectableByMouse);
00121
00122 m_uiImage.m_resizeMethod->addItem(i18n("Scaled & Cropped"), Background::ScaleCrop);
00123 m_uiImage.m_resizeMethod->addItem(i18n("Scaled"), Background::Scale);
00124 m_uiImage.m_resizeMethod->addItem(i18n("Scaled, keep proportions"), Background::Maxpect);
00125 m_uiImage.m_resizeMethod->addItem(i18n("Centered"), Background::Center);
00126 m_uiImage.m_resizeMethod->addItem(i18n("Tiled"), Background::Tiled);
00127 m_uiImage.m_resizeMethod->addItem(i18n("Center Tiled"), Background::CenterTiled);
00128 for (int i = 0; i < m_uiImage.m_resizeMethod->count(); ++i) {
00129 if (m_resizeMethod == m_uiImage.m_resizeMethod->itemData(i).value<int>()) {
00130 m_uiImage.m_resizeMethod->setCurrentIndex(i);
00131 break;
00132 }
00133 }
00134 connect(m_uiImage.m_resizeMethod, SIGNAL(currentIndexChanged(int)),
00135 this, SLOT(positioningChanged(int)));
00136
00137 m_uiImage.m_color->setColor(m_color);
00138 connect(m_uiImage.m_color, SIGNAL(changed(const QColor&)), this, SLOT(colorChanged(const QColor&)));
00139
00140 connect(m_uiImage.m_newStuff, SIGNAL(clicked()), this, SLOT(getNewWallpaper()));
00141 } else {
00142 m_uiSlideshow.setupUi(m_widget);
00143
00144 m_uiSlideshow.m_dirlist->clear();
00145 foreach (const QString &dir, m_dirs) {
00146 m_uiSlideshow.m_dirlist->addItem(dir);
00147 }
00148 m_uiSlideshow.m_dirlist->setCurrentRow(0);
00149 updateDirs();
00150 m_uiSlideshow.m_addDir->setIcon(KIcon("list-add"));
00151 connect(m_uiSlideshow.m_addDir, SIGNAL(clicked()), this, SLOT(slotAddDir()));
00152 m_uiSlideshow.m_removeDir->setIcon(KIcon("list-remove"));
00153 connect(m_uiSlideshow.m_removeDir, SIGNAL(clicked()), this, SLOT(slotRemoveDir()));
00154
00155 QTime time(0, 0, 0);
00156 time = time.addSecs(m_delay);
00157 m_uiSlideshow.m_slideshowDelay->setTime(time);
00158 m_uiSlideshow.m_slideshowDelay->setMinimumTime(QTime(0, 0, 30));
00159 connect(m_uiSlideshow.m_slideshowDelay, SIGNAL(timeChanged(const QTime&)),
00160 this, SLOT(timeChanged(const QTime&)));
00161
00162 m_uiSlideshow.m_resizeMethod->addItem(i18n("Scaled & Cropped"), Background::ScaleCrop);
00163 m_uiSlideshow.m_resizeMethod->addItem(i18n("Scaled"), Background::Scale);
00164 m_uiSlideshow.m_resizeMethod->addItem(i18n("Scaled, keep proportions"), Background::Maxpect);
00165 m_uiSlideshow.m_resizeMethod->addItem(i18n("Centered"), Background::Center);
00166 m_uiSlideshow.m_resizeMethod->addItem(i18n("Tiled"), Background::Tiled);
00167 m_uiSlideshow.m_resizeMethod->addItem(i18n("Center Tiled"), Background::CenterTiled);
00168 for (int i = 0; i < m_uiSlideshow.m_resizeMethod->count(); ++i) {
00169 if (m_resizeMethod == m_uiSlideshow.m_resizeMethod->itemData(i).value<int>()) {
00170 m_uiSlideshow.m_resizeMethod->setCurrentIndex(i);
00171 break;
00172 }
00173 }
00174 connect(m_uiSlideshow.m_resizeMethod, SIGNAL(currentIndexChanged(int)),
00175 this, SLOT(positioningChanged(int)));
00176
00177 m_uiSlideshow.m_color->setColor(m_color);
00178 connect(m_uiSlideshow.m_color, SIGNAL(changed(const QColor&)), this, SLOT(colorChanged(const QColor&)));
00179 }
00180
00181 return m_widget;
00182 }
00183
00184 void Image::calculateGeometry()
00185 {
00186 m_size = boundingRect().size().toSize();
00187 m_renderer.setSize(m_size);
00188 m_ratio = boundingRect().width() / boundingRect().height();
00189 m_renderer.setRatio(m_ratio);
00190 }
00191
00192 void Image::paint(QPainter *painter, const QRectF& exposedRect)
00193 {
00194
00195
00196 if (m_size != boundingRect().size().toSize()) {
00197 calculateGeometry();
00198 if (!m_img.isEmpty()) {
00199 render();
00200
00201 return;
00202 }
00203 }
00204
00205 if (m_pixmap.isNull()) {
00206 painter->fillRect(exposedRect, QBrush(m_color));
00207
00208 return;
00209 }
00210
00211 painter->save();
00212
00213 if (painter->worldMatrix() == QMatrix()) {
00214
00215 painter->resetTransform();
00216 }
00217
00218
00219 painter->setCompositionMode(QPainter::CompositionMode_Source);
00220
00221
00222
00223 painter->drawPixmap(exposedRect, m_pixmap, exposedRect);
00224
00225
00226 painter->restore();
00227 }
00228
00229 void Image::timeChanged(const QTime& time)
00230 {
00231 m_delay = QTime(0, 0, 0).secsTo(time);
00232 if (!m_slideshowBackgrounds.isEmpty()) {
00233 m_timer.start(m_delay * 1000);
00234 }
00235 }
00236
00237 void Image::slotAddDir()
00238 {
00239 KUrl empty;
00240 KDirSelectDialog dialog(empty, true, m_widget);
00241 if (dialog.exec()) {
00242 QString urlDir = dialog.url().path();
00243 if (!urlDir.isEmpty() && m_uiSlideshow.m_dirlist->findItems(urlDir, Qt::MatchExactly).isEmpty()) {
00244 m_uiSlideshow.m_dirlist->addItem(dialog.url().path());
00245 updateDirs();
00246 startSlideshow();
00247 }
00248 }
00249 }
00250
00251 void Image::slotRemoveDir()
00252 {
00253 int row = m_uiSlideshow.m_dirlist->currentRow();
00254 if (row != -1) {
00255 m_uiSlideshow.m_dirlist->takeItem(row);
00256 updateDirs();
00257 startSlideshow();
00258 }
00259 }
00260
00261 void Image::updateDirs()
00262 {
00263 m_dirs.clear();
00264 for (int i = 0; i < m_uiSlideshow.m_dirlist->count(); i++) {
00265 m_dirs.append(m_uiSlideshow.m_dirlist->item(i)->text());
00266 }
00267
00268 if (m_uiSlideshow.m_dirlist->count() == 0) {
00269 m_uiSlideshow.m_dirlist->hide();
00270 } else {
00271 const int itemHeight = m_uiSlideshow.m_dirlist->visualItemRect(m_uiSlideshow.m_dirlist->item(0)).height();
00272 const int vMargin = m_uiSlideshow.m_dirlist->height() - m_uiSlideshow.m_dirlist->viewport()->height();
00273
00274 if (m_uiSlideshow.m_dirlist->count() <= 6) {
00275 m_uiSlideshow.m_dirlist->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00276 m_uiSlideshow.m_dirlist->setFixedHeight(itemHeight * m_uiSlideshow.m_dirlist->count() + vMargin);
00277 } else {
00278 m_uiSlideshow.m_dirlist->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00279 }
00280
00281 if (!m_uiSlideshow.m_dirlist->isVisible()) {
00282 m_uiSlideshow.m_dirlist->setCurrentRow(0);
00283 }
00284
00285 m_uiSlideshow.m_dirlist->show();
00286 m_uiSlideshow.gridLayout->invalidate();
00287 }
00288
00289 m_uiSlideshow.m_removeDir->setEnabled(m_uiSlideshow.m_dirlist->currentRow() != -1);
00290 }
00291
00292 void Image::setSingleImage()
00293 {
00294 QString img;
00295 BackgroundPackage b(m_wallpaper, m_ratio);
00296
00297 img = b.findBackground(m_size, m_resizeMethod);
00298 kDebug() << img << m_wallpaper;
00299 if (img.isEmpty()) {
00300 img = m_wallpaper;
00301 }
00302
00303 render(img);
00304 }
00305
00306 void Image::startSlideshow()
00307 {
00308
00309 m_timer.stop();
00310 qDeleteAll(m_slideshowBackgrounds);
00311 m_slideshowBackgrounds.clear();
00312 foreach (const QString& dir, m_dirs) {
00313 m_slideshowBackgrounds += BackgroundListModel::findAllBackgrounds(0, dir, m_ratio);
00314 }
00315
00316
00317 if (m_slideshowBackgrounds.isEmpty()) {
00318 m_pixmap = QPixmap();
00319 emit update(boundingRect());
00320 } else {
00321 m_currentSlide = -1;
00322 nextSlide();
00323 m_timer.start(m_delay * 1000);
00324 }
00325 }
00326
00327 void Image::getNewWallpaper()
00328 {
00329 KNS::Engine engine(m_widget);
00330 if (engine.init("wallpaper.knsrc")) {
00331 KNS::Entry::List entries = engine.downloadDialogModal(m_widget);
00332
00333 if (entries.size() > 0 && m_model) {
00334 m_model->reload();
00335 }
00336 }
00337 }
00338
00339 void Image::colorChanged(const QColor& color)
00340 {
00341 m_color = color;
00342 setSingleImage();
00343 }
00344
00345 void Image::pictureChanged(int index)
00346 {
00347 if (index == -1 || !m_model) {
00348 return;
00349 }
00350
00351 Background *b = m_model->package(index);
00352 if (!b) {
00353 return;
00354 }
00355
00356 fillMetaInfo(b);
00357 m_wallpaper = b->path();
00358 setSingleImage();
00359 }
00360
00361 void Image::positioningChanged(int index)
00362 {
00363 if (m_mode == "SingleImage") {
00364 m_resizeMethod =
00365 (Background::ResizeMethod)m_uiImage.m_resizeMethod->itemData(index).value<int>();
00366 setSingleImage();
00367 } else {
00368 m_resizeMethod =
00369 (Background::ResizeMethod)m_uiSlideshow.m_resizeMethod->itemData(index).value<int>();
00370 startSlideshow();
00371 }
00372 }
00373
00374 void Image::fillMetaInfo(Background *b)
00375 {
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 if (!b->author().isEmpty()) {
00391 QString author = i18nc("Wallpaper info, author name", "%1", b->author());
00392 m_uiImage.m_authorLabel->setAlignment(Qt::AlignRight);
00393 setMetadata(m_uiImage.m_authorLine, author);
00394 } else {
00395 setMetadata(m_uiImage.m_authorLine, QString());
00396 m_uiImage.m_authorLabel->setAlignment(Qt::AlignLeft);
00397 }
00398 setMetadata(m_uiImage.m_licenseLine, QString());
00399 setMetadata(m_uiImage.m_emailLine, QString());
00400 m_uiImage.m_emailLabel->hide();
00401 m_uiImage.m_licenseLabel->hide();
00402 }
00403
00404 bool Image::setMetadata(QLabel *label, const QString &text)
00405 {
00406 if (text.isEmpty()) {
00407 label->hide();
00408 return false;
00409 }
00410 else {
00411 label->show();
00412 label->setText(text);
00413 return true;
00414 }
00415 }
00416
00417 void Image::showFileDialog()
00418 {
00419 if (!m_dialog) {
00420 m_dialog = new KFileDialog(KUrl(), "*.png *.jpeg *.jpg *.svg *.svgz", m_widget);
00421 m_dialog->setOperationMode(KFileDialog::Opening);
00422 m_dialog->setInlinePreviewShown(true);
00423 m_dialog->setCaption(i18n("Select Wallpaper Image File"));
00424 m_dialog->setModal(false);
00425 }
00426 m_dialog->show();
00427 m_dialog->raise();
00428 m_dialog->activateWindow();
00429
00430 connect(m_dialog, SIGNAL(okClicked()), this, SLOT(browse()));
00431 }
00432
00433 void Image::browse()
00434 {
00435 Q_ASSERT(m_model);
00436
00437 QString wallpaper = m_dialog->selectedFile();
00438 disconnect(m_dialog, SIGNAL(okClicked()), this, SLOT(browse()));
00439
00440 if (wallpaper.isEmpty()) {
00441 return;
00442 }
00443
00444 if (m_model->contains(wallpaper)) {
00445 m_uiImage.m_view->setCurrentIndex(m_model->indexOf(wallpaper));
00446 return;
00447 }
00448
00449
00450 m_model->addBackground(wallpaper);
00451
00452
00453 int index = m_model->indexOf(wallpaper);
00454 if (index != -1) {
00455 m_uiImage.m_view->setCurrentIndex(index);
00456 }
00457
00458 m_usersWallpapers << wallpaper;
00459 }
00460
00461 void Image::nextSlide()
00462 {
00463 if (m_slideshowBackgrounds.size() < 1) {
00464 return;
00465 }
00466
00467 QString previous;
00468 if (m_currentSlide >= 0 && m_currentSlide < m_slideshowBackgrounds.size()) {
00469 previous = m_slideshowBackgrounds[m_currentSlide]->findBackground(m_size, m_resizeMethod);
00470 }
00471
00472 if (m_randomize) {
00473 m_currentSlide = KRandom::random() % m_slideshowBackgrounds.size();
00474 } else if (++m_currentSlide >= m_slideshowBackgrounds.size()) {
00475 m_currentSlide = 0;
00476 }
00477
00478 QString current = m_slideshowBackgrounds[m_currentSlide]->findBackground(m_size, m_resizeMethod);
00479 if (current == previous) {
00480 QFileInfo info(previous);
00481 if (m_previousModified == info.lastModified()) {
00482
00483 if (m_slideshowBackgrounds.count() == 1) {
00484
00485 return;
00486 }
00487
00488 if (++m_currentSlide >= m_slideshowBackgrounds.size()) {
00489 m_currentSlide = 0;
00490 }
00491
00492 current = m_slideshowBackgrounds[m_currentSlide]->findBackground(m_size, m_resizeMethod);
00493 }
00494 }
00495
00496 QFileInfo info(current);
00497 m_previousModified = info.lastModified();
00498
00499 render(current);
00500 }
00501
00502 void Image::render(const QString& image)
00503 {
00504 if (!image.isEmpty()) {
00505 m_img = image;
00506 }
00507
00508 m_rendererToken = m_renderer.render(m_img, m_color, m_resizeMethod,
00509 Qt::SmoothTransformation);
00510 suspendStartup(true);
00511 }
00512
00513 void Image::updateBackground(int token, const QImage &img)
00514 {
00515 if (m_rendererToken == token) {
00516 m_pixmap = QPixmap::fromImage(img);
00517 emit update(boundingRect());
00518 suspendStartup(false);
00519 }
00520 }
00521
00522 void Image::suspendStartup(bool suspend)
00523 {
00524 org::kde::KSMServerInterface ksmserver("org.kde.ksmserver", "/KSMServer", QDBusConnection::sessionBus());
00525 const QString startupID("desktop wallaper");
00526 if (suspend) {
00527 ksmserver.suspendStartup(startupID);
00528 } else {
00529 ksmserver.resumeStartup(startupID);
00530 }
00531 }
00532
00533 void Image::updateScreenshot(QPersistentModelIndex index)
00534 {
00535 m_uiImage.m_view->view()->update(index);
00536 }
00537
00538 void Image::removeBackground(const QString &path)
00539 {
00540 if (m_model) {
00541 m_model->removeBackground(path);
00542 }
00543 }
00544
00545 #include "image.moc"