Logo Search packages:      
Sourcecode: kdemultimedia version File versions

systray.cpp

// systray.h
//
// Copyright (C) 2000 Neil Stevens <multivac@fcmail.com>
// Copyright (C) 1999 Charles Samuels <charles@kde.org>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name(s) of the author(s) shall not be
// used in advertising or otherwise to promote the sale, use or other dealings
// in this Software without prior written authorization from the author(s).

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <noatun/effects.h>
#include <noatun/app.h>
#include <noatun/pref.h>
#include <noatun/player.h>
#include "systray.h"
#include "kitsystemtray.h"
#include <noatun/stdaction.h>
#include "cmodule.h"

#include <kaction.h>
#include <kconfig.h>
#include <kfiledialog.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kpassivepopup.h>
#include <kpixmapeffect.h>
#include <kstdaction.h>
#include <qbitmap.h>
#include <qhbox.h>
#include <qpainter.h>
#include <qpushbutton.h>
#include <qtimer.h>
#include <qtooltip.h>
#include <qvbox.h>

#include <qimage.h>
#include <kurl.h>
#include <kio/netaccess.h>
#include <kdebug.h>
#include <kstandarddirs.h>

// TODO: Maybe make this value configurable?
const int COVER_MAXW = 128;
const int COVER_MAXH = 128;
#define BASEICON "noatun"

NoatunSystray *NoatunSystray::self = 0;

NoatunSystray::NoatunSystray()
      : KMainWindow(0, "NoatunSystray")
      , Plugin()
      , trayStatus(0), trayBase(0), mTray(0)
      , mPassivePopup(0L)
{
      self = this;
      hide();

      tmpCoverPath = locateLocal("tmp", "youngHickoryCover.png");
      removeCover(); // make sure any old temp cover is gone

      KStdAction::quit(napp, SLOT(quit()), actionCollection());
      KStdAction::open(napp, SLOT(fileOpen()), actionCollection());
      KStdAction::preferences(napp, SLOT(preferences()), actionCollection());
      NoatunStdAction::back(actionCollection(), "back");
      NoatunStdAction::stop(actionCollection(), "stop");
      NoatunStdAction::playpause(actionCollection(), "play");
      NoatunStdAction::forward(actionCollection(), "forward");
      NoatunStdAction::playlist(actionCollection(), "show_playlist");
      NoatunStdAction::loop(actionCollection(), "loop_style");
      NoatunStdAction::effects(actionCollection(), "effects");
      NoatunStdAction::equalizer(actionCollection(), "equalizer");

      createGUI("systrayui.rc");

      mTray = new KitSystemTray("tray", this);
      mTray->show();

      trayBase = renderIcon(BASEICON, QString::null);
      trayStatus = renderIcon(BASEICON, "player_stop");

      mTray->changeTitle(*trayBase, i18n("Noatun"));
      showingTrayStatus = false;

      mBlink = Neither;
      mBlinkTimer = new QTimer(this, "mBlinkTimer");
      connect(mBlinkTimer, SIGNAL(timeout()), this, SLOT(slotBlinkTimer()));

      connect(napp->player(), SIGNAL(playing()), this, SLOT(slotPlaying()));
      connect(napp->player(), SIGNAL(stopped()), this, SLOT(slotStopped()));
      connect(napp->player(), SIGNAL(paused()), this, SLOT(slotPaused()));
      napp->player()->handleButtons();
}


NoatunSystray::~NoatunSystray()
{
      //kdDebug(66666) << k_funcinfo << "Called." << endl;
      removeCover();
      delete trayBase;
      delete trayStatus;
      napp->showInterfaces();
}


void NoatunSystray::init()
{
      new YHModule(this);
      slotBlinkTimer();
}


void NoatunSystray::setBlink(Blink b)
{
//    kdDebug(66666) << k_funcinfo << "Called, b=" << (int)b << endl;

      if(mBlink == b)
            return;

      mBlink = b;

      if(mBlink == BlinkIcon)
            mBlinkTimer->start(1000);
      else
            mBlinkTimer->stop();

      slotBlinkTimer();
}


void NoatunSystray::setTip(bool b)
{
      mTip = b;
      if(mTip)
            QToolTip::add(mTray, tipText);
      else
            QToolTip::remove(mTray);
}


void NoatunSystray::closeEvent(QCloseEvent*)
{
      //kdDebug(66666) << k_funcinfo << "Called." << endl;
      disconnect(napp->player(), 0, 0, 0);
      unload();
}


void NoatunSystray::slotPlaying()
{
      //mStop->setEnabled(true);
      changeTray("player_play");
      const PlaylistItem item = napp->player()->current();

      if(item.length()>0)
      {
            if(mShowCovers && QFile::exists(tmpCoverPath))
            {
                  setTipText(i18n("<table cellspacing=0 cellpadding=0>" \
                        "<tr><td colspan=2 align=center><nobr><b>Noatun - Playing</b></nobr></td></tr>" \
                        "<tr><td align=center>%1</td><td rowspan=2><img src='%3'></td></tr>" \
                        "<tr><td align=center>%2</td></tr>" \
                        "</table>").arg(item.title(), item.lengthString(), tmpCoverPath));
            }
            else
            {
                  setTipText(i18n("<table cellspacing=0 cellpadding=0>" \
                        "<tr><td align=center><nobr><b>Noatun - Playing</b></nobr></td></tr>" \
                        "<tr><td align=center>%1</td</tr>" \
                        "<tr><td align=center>%2</td></tr>" \
                        "</table>").arg(item.title(), item.lengthString()));
            }
      }
      else
      {
            if(mShowCovers && QFile::exists(tmpCoverPath))
            {
                  setTipText(i18n("<table cellspacing=0 cellpadding=0>" \
                        "<tr><td colspan=2 align=center><nobr><b>Noatun - Playing</b></nobr></td></tr>" \
                        "<tr><td>%1</td><td><img src='%2'></td></tr>" \
                        "</table>").arg(item.title(), tmpCoverPath));
            }
            else
            {
                  setTipText(i18n("<table cellspacing=0 cellpadding=0>" \
                        "<tr><td align=center><nobr><b>Noatun - Playing</b></nobr></td></tr>" \
                        "<tr><td>%1</td</tr>" \
                        "</table>").arg(item.title()));
            }
      }
}


void NoatunSystray::slotStopped()
{
      if(!napp->player()->current())
            return;
      changeTray("player_stop");
      setTipText(i18n("<table cellspacing=0 cellpadding=0>" \
            "<tr><td align=center><nobr><b>Noatun - Stopped</b></nobr></td></tr></table>"));
}


void NoatunSystray::slotPaused()
{
      changeTray("player_pause");

      const PlaylistItem item = napp->player()->current();

      if(item.length()>0)
      {
            setTipText(i18n("<table cellspacing=0 cellpadding=0>" \
                  "<tr><td align=center><nobr><b>Noatun - Paused</b></nobr></td></tr>" \
                  "<tr><td>%1</td></tr>" \
                  "<tr><td>%2</td></tr></table>")
                  .arg(item.title(), item.lengthString()));
      }
      else
      {
            setTipText(i18n("<table cellspacing=0 cellpadding=0>" \
                  "<tr><td align=center><nobr><b>Noatun - Paused</b></nobr></td></tr>" \
                  "<tr><td>%1</td></tr></table>")
                  .arg(item.title()));
      }
}


void NoatunSystray::changeTray(const QString &pm)
{
      delete trayStatus;
      trayStatus = renderIcon(BASEICON, pm);
      if(showingTrayStatus)
            slotBlinkTimer();
}


void NoatunSystray::slotBlinkTimer()
{
      switch((int)mBlink)
      {
            case BlinkIcon:
                  showingTrayStatus ^= true;
                  break;
            case ShowIcon:
                  showingTrayStatus = true;
                  break;
            case Neither:
                  showingTrayStatus = false;
                  break;
      }

      if(showingTrayStatus)
            mTray->setPixmap(*trayStatus);
      else
            mTray->setPixmap(*trayBase);
}


// taken from patched karamba xmmssensor
// modified heavily to work in this place
void NoatunSystray::updateCover()
{
      //kdDebug(66666) << k_funcinfo << endl;
      QString dir = napp->player()->current().url().directory();
      QString cover;

      // TODO: Maybe make these filenames configurable?
      if(QFile::exists(dir + "/folder.png"))
            cover = dir + "/folder.png";
      else if(QFile::exists(dir + "/.folder.png"))
            cover = dir + "/.folder.png";
      else if(QFile::exists(dir + "/cover.png"))
            cover = dir + "/cover.png";
      else if(QFile::exists(dir + "/cover.jpg"))
            cover = dir + "/cover.jpg";
      else if(QFile::exists(dir + "/cover.jpeg"))
            cover = dir + "/cover.jpeg";
      else // no cover
      {
            //kdDebug(66666) << k_funcinfo << "NO COVER" <<  endl;
            removeCover();
            return;
      }

      QString title = napp->player()->current().title();

      QImage previmg;
      previmg.load(tmpCoverPath);

      if(previmg.text("Title") != title)
      { //Verify song change to limit CPU usage
            /*kdDebug(66666) << k_funcinfo << "Creating new temp cover for '" <<
                  cover << "'" << endl;*/

            QImage src;
            QImage tmpimg;
            src.load(cover);

            if(src.width() >= COVER_MAXW || src.height() >= COVER_MAXH)
                  tmpimg = src.scale(COVER_MAXW, COVER_MAXH, QImage::ScaleMin);
            else
                  tmpimg = src;

            tmpimg.setText("Title", 0, title); //add Title in the image text for cache usage
            tmpimg.save(tmpCoverPath, "PNG", 0);
      }
}


void NoatunSystray::removeCover()
{
      if(QFile::exists(tmpCoverPath))
      {
//          kdDebug(66666) << k_funcinfo << "Deleting temp cover file" << endl;
            KIO::NetAccess::del(KURL(tmpCoverPath), this);
      }
}


void NoatunSystray::setShowCovers(bool show)
{
      mShowCovers = show;
      if (!show)
            removeCover();
}


void NoatunSystray::setPopupTimeout(int timeout)
{
      mPassivePopupTimeout = timeout * 1000;
      if (mPassivePopup)
            mPassivePopup->setTimeout(mPassivePopupTimeout);
}


void NoatunSystray::setShowButtons(bool show)
{
      mShowButtons = show;
}


void NoatunSystray::setTipText(const QString& text)
{
      if(text == tipText) // save the planet, save cpu cycles ;)
            return;

      tipText = text;

      // prepare cover image for display
      if (mShowCovers)
            updateCover();

      if(mPassivePopup)
            QTimer::singleShot(0, this, SLOT(showPassivePopup()));

      if(mTip)
            QToolTip::add(mTray, tipText);
}


void NoatunSystray::showPassivePopup()
{
      mPassivePopup->reparent(0L, QPoint(0,0));

      if (mShowButtons && !napp->player()->isStopped())
      {
            QVBox *widget = mPassivePopup->standardView(QString::null, tipText,
                  QPixmap());
            QHBox *box = new QHBox(mPassivePopup, "popup box");
            //box->setSpacing(15);

            QPushButton *backButton
                  = new QPushButton(action("back")->iconSet(), 0, box, "popup_back");
            backButton->setFlat(true);
            connect(backButton, SIGNAL(clicked()), action("back"),
                  SLOT(activate()));

            widget->reparent(box, QPoint(0, 0));

            QPushButton *forwardButton = new QPushButton(action("forward")->iconSet(),
                  0, box, "popup_forward");
            forwardButton->setFlat(true);
            connect(forwardButton, SIGNAL(clicked()), action("forward"),
                        SLOT(activate()));

            mPassivePopup->setView(box);
      }
      else
      {
            mPassivePopup->setView(QString::null, tipText);
      }

      mPassivePopup->show();
}


void NoatunSystray::setPassivePopup(bool pop)
{
      if(pop==(mPassivePopup!=0L))
            return;

      if(pop)
      {
            mPassivePopup = new KPassivePopup(mTray, "NoatunPassivePopup");
            mPassivePopup->setTimeout(mPassivePopupTimeout);
      }
      else
      {
            delete mPassivePopup;
            mPassivePopup = 0L;
      }
}


QPixmap *NoatunSystray::renderIcon(const QString& baseIcon, const QString &overlayIcon) const
{
      QPixmap *base = new QPixmap(KSystemTray::loadIcon(baseIcon));

      if(!(overlayIcon.isNull())) // otherwise leave the base as-is
      {
            QPixmap overlay = KSystemTray::loadIcon(overlayIcon);
            if(!overlay.isNull())
            {
                  // first combine the masks of both pixmaps (in case both actually have one)
                  if((overlay.mask()!=0) && (base->mask()!=0))
                  {
                        QBitmap mask = *(base->mask());
                        bitBlt(&mask, 0, 0, const_cast<QBitmap *>(overlay.mask()),
                              0, 0, overlay.width(), overlay.height(), Qt::OrROP);
                        base->setMask(mask);
                  }
                  // draw the overlay on top of it
                  QPainter p(base);
                  p.drawPixmap(0, 0, overlay);
            }
      }
      return base;
}

#include "systray.moc"

Generated by  Doxygen 1.6.0   Back to index