Logo Search packages:      
Sourcecode: qmpdclient version File versions  Download package

trayicon.cpp

/*
 * QMPDClient - An MPD client written in Qt 4.
 * Copyright (C) 2005-2008 HÃ¥vard Tautra Knutsen <havtknut@tihlde.org>
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "trayicon.h"
#include "config.h"
#include "iconmanager.h"
#include "mpd.h"
#include "mpdconnection.h"
#include "mpdsong.h"
#include "richtext.h"
#include "traysonginfo.h"
#include <QApplication>
#include <QBoxLayout>
#include <QMenu>
#include <QPainter>
#include <QSlider>
#include <QWheelEvent>
#include <QDesktopWidget>
#ifndef Q_WS_X11
#include "macroexpander.h"
#endif

00039 struct VolumeMenu : QMenu {
      VolumeMenu(QWidget *parent) : QMenu(parent) {
            QFrame *w = new QFrame(this);
            QLabel *min = new QLabel("-", w);
            QLabel *max = new QLabel("+", w);
            QSlider *s = new QSlider(w);

            min->setAlignment(Qt::AlignHCenter);
            max->setAlignment(Qt::AlignHCenter);

            QVBoxLayout *l = new QVBoxLayout(w);
            l->setMargin(3);
            l->addWidget(max);
            l->addWidget(s);
            l->addWidget(min);

            layout = new QHBoxLayout(this);
            layout->setMargin(0);
            layout->addWidget(w);

            connect(MPD::instance(), SIGNAL(volumeUpdated(int)), s, SLOT(setValue(int)));
            connect(s, SIGNAL(valueChanged(int)), MPD::instance(), SLOT(setVolume(int)));
      }

      QSize sizeHint() const {
            return layout->sizeHint();
      }

private:
      QHBoxLayout *layout;
};


TrayIcon::TrayIcon(QWidget *parent) : QSystemTrayIcon(parent),
#ifndef Q_WS_X11
            m_connected(":/icons/16x16/qmpdclient.png"),
            m_disconnected(":/icons/16x16/qmpdclientd.png")
#else
            m_connected(":/icons/22x22/qmpdclient.png"),
            m_disconnected(":/icons/22x22/qmpdclientd.png")
#endif
{
      setObjectName("trayicon");
      setIcon(m_disconnected);

      m_songInfoWidget = new TraySongInfo();

      QMenu *menu = new QMenu(parent);
      m_showHideAction = menu->addAction("", parent, SLOT(showHide()));
      menu->addSeparator();
      m_prevAction = menu->addAction("", MPD::instance(), SLOT(prev()));
      m_playAction = menu->addAction("", MPD::instance(), SLOT(play()));
      m_pauseAction = menu->addAction("", MPD::instance(), SLOT(pause()));
      m_stopAction = menu->addAction("", MPD::instance(), SLOT(stop()));
      m_nextAction = menu->addAction("", MPD::instance(), SLOT(next()));
      menu->addSeparator();
      menu->addMenu(m_volumeMenu = new VolumeMenu(menu));
      menu->addSeparator();
      m_quitAction = menu->addAction("", qApp, SLOT(quit()));
      setContextMenu(menu);

      // For icon changes
      m_showHideAction->setObjectName("showHideAction");
      m_prevAction->setObjectName("prevAction");
      m_playAction->setObjectName("playAction");
      m_pauseAction->setObjectName("pauseAction");
      m_stopAction->setObjectName("stopAction");
      m_nextAction->setObjectName("nextAction");
      m_quitAction->setObjectName("quitAction");
      m_volumeMenu->setObjectName("volumeMenu");

      connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(action(QSystemTrayIcon::ActivationReason)));
      connect(menu, SIGNAL(aboutToShow()), this, SLOT(menuAboutToShow()));
      connect(MPD::instance(), SIGNAL(playingSongUpdated(const MPDSong &)), this, SLOT(setSong(const MPDSong &)));
      connect(MPDConnection::instance(), SIGNAL(connected(const ServerInfo &)), this, SLOT(connected()));
      connect(MPDConnection::instance(), SIGNAL(disconnected(const QString &)), this, SLOT(disconnected()));

      MPDConnection::instance()->isConnected() ? connected() : disconnected();

      setToolTip(NAMEVER);
}

void TrayIcon::menuAboutToShow() {
      Q_ASSERT(m_showHideAction);
      if (qobject_cast<QWidget*>(parent())->isVisible())
            m_showHideAction->setText(tr("Hide"));
      else
            m_showHideAction->setText(tr("Show"));
}

void TrayIcon::updateTranslation() {
      Q_ASSERT(m_prevAction);
      Q_ASSERT(m_playAction);
      Q_ASSERT(m_pauseAction);
      Q_ASSERT(m_stopAction);
      Q_ASSERT(m_nextAction);
      Q_ASSERT(m_quitAction);
      Q_ASSERT(m_volumeMenu);
      m_prevAction->setText(tr("Previuos"));
      m_playAction->setText(tr("Play"));
      m_pauseAction->setText(tr("Pause"));
      m_stopAction->setText(tr("Stop"));
      m_nextAction->setText(tr("Next"));
      m_quitAction->setText(tr("Quit"));
      m_volumeMenu->setTitle(tr("Volume"));
}

void TrayIcon::action(QSystemTrayIcon::ActivationReason reason) {
      if (reason == QSystemTrayIcon::MiddleClick)
            MPD::instance()->togglePlay();
      else if (reason != QSystemTrayIcon::Context)
            emit clicked();
}

void TrayIcon::setSong(const MPDSong &s) {
      if (Config::instance()->extendedSongInfoEnabled())
            m_songInfoWidget->setSong(s);

      if (s.isNull()) {
            QString msg = tr("Not playing", "This is for the trayicon tooltip, indicating that no song is playing");
#ifndef Q_WS_X11
            // Win32 and OSX does not seem to support richtext in tooltips
            setToolTip(msg);
#else
            QString tooltip = "<html><body>";
            tooltip += "<table><tr><td><img src=':/icons/48x48/qmpdclient.png'></td><td valign='middle'>";
            tooltip += QString("&nbsp;%1</td></tr></table>").arg(NAMEVER);
            tooltip += QString("<b>%1</b>").arg(msg);
            tooltip += "</body></html>";
            setToolTip(tooltip);
#endif
            return;
      }

#ifndef Q_WS_X11
      // Win32 and OSX does not seem to support richtext in tooltips
      setToolTip(expandMacros(s, Config::instance()->playlistPattern()));
#else
      QString tooltip = "<html><body><table>";
      tooltip += "<tr><td rowspan='%1' valign='middle'><img src=':/icons/48x48/qmpdclient.png' /></td>";
      tooltip += "<td valign='middle' align='center'>%2</td></tr>";

      // Make nice tooltip
      QString album = elideRichText("", s.album(), "", 175);
      QString artist = elideRichText("", s.artist(), "", 175);
      QString title;
      if (s.title().isEmpty())
            title = s.filename();
      else
            title = s.title();
      title = elideRichText("<b>", title, "</b>", 175);

      int rows = 2;
      tooltip += QString("<tr><td>%1</td></tr>").arg(title.isEmpty() ? QObject::tr("Not tagged") : title);

      if (!artist.isEmpty()) {
            tooltip += QString("<tr><td>%1</td></tr>").arg(artist);
            rows++;
      }
      if (!album.isEmpty()) {
            tooltip += QString("<tr><td>%1</td></tr>").arg(album);
            rows++;
      }
      tooltip += "</table></body></html>";

      setToolTip(tooltip.arg(rows).arg(NAMEVER));
#endif
}

void TrayIcon::connected() {
      setIcon(m_connected);
      toggleEnabled(true);
}

void TrayIcon::disconnected() {
      setIcon(m_disconnected);
      toggleEnabled(false);
}

void TrayIcon::toggleEnabled(bool enabled) {
      foreach(QAction *w, contextMenu()->findChildren<QAction*>(QRegExp("Action$"))) {
            w->setEnabled(enabled);
      }
      m_volumeMenu->setEnabled(enabled);
      m_showHideAction->setEnabled(true);
      m_quitAction->setEnabled(true);
}

bool TrayIcon::event(QEvent *event) {
      static int songInfoWidgetTimerId = -1;

      if (event->type() == QEvent::Wheel) {
            QWheelEvent *e = static_cast<QWheelEvent*>(event);
            const int numDegrees = e->delta() / 8;
            const int numSteps = numDegrees / 15;

            if (e->orientation() == Qt::Horizontal) {
                  if (numSteps > 0)
                        MPD::instance()->seekForward();
                  else if (numSteps < 0)
                        MPD::instance()->seekBackward();
            } else {
                  if (numSteps > 0)
                        MPD::instance()->volumeUp(5*numSteps);
                  else if (numSteps < 0)
                        MPD::instance()->volumeDown(5*numSteps);
            }
            return true;
      }
      else if (event->type() == QEvent::ToolTip) {
            if (Config::instance()->extendedSongInfoEnabled()) {
                  m_songInfoWidget->show();

                  int x = geometry().right() + m_songInfoWidget->width() < QApplication::desktop()->width() ?
                                    geometry().right() :
                                    geometry().left() - m_songInfoWidget->width();
                  int y = geometry().top() - m_songInfoWidget->height() > 0 ?
                                    geometry().top() - m_songInfoWidget->height() :
                                    geometry().bottom();

                  m_songInfoWidget->move(x, y);

                  songInfoWidgetTimerId = startTimer(100);
                  return true;
            }
      }
      else if (event->type() == QEvent::Timer) {
            if (static_cast<QTimerEvent*>(event)->timerId() == songInfoWidgetTimerId) {
                  if (!geometry().contains(QCursor::pos())) {
                        killTimer(songInfoWidgetTimerId);
                        songInfoWidgetTimerId = -1;

                        m_songInfoWidget->close();
                  }
            }
      }

      return QSystemTrayIcon::event(event);
}

Generated by  Doxygen 1.6.0   Back to index