diff options
Diffstat (limited to 'tderadio3/plugins/gui-docking-menu/docking.cpp')
-rw-r--r-- | tderadio3/plugins/gui-docking-menu/docking.cpp | 674 |
1 files changed, 674 insertions, 0 deletions
diff --git a/tderadio3/plugins/gui-docking-menu/docking.cpp b/tderadio3/plugins/gui-docking-menu/docking.cpp new file mode 100644 index 0000000..7c5d817 --- /dev/null +++ b/tderadio3/plugins/gui-docking-menu/docking.cpp @@ -0,0 +1,674 @@ +/*************************************************************************** + docking.cpp - description + ------------------- + begin : Don M�r 8 21:57:17 CET 2001 + copyright : (C) 2002 by Ernst Martin Witte + email : [email protected] +***************************************************************************/ + +/*************************************************************************** + * * + * 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 <kiconloader.h> +#include <tqtooltip.h> +#include <kpopupmenu.h> +#include <kapplication.h> +#include <kaction.h> +#include <kdialogbase.h> +#include <kaboutdata.h> +#include <tdeconfig.h> +#include <twin.h> + +#include "../../src/include/radiodevice_interfaces.h" +#include "../../src/include/stationlist.h" +#include "../../src/include/pluginmanager.h" +#include "../../src/include/widgetplugins.h" +#include "../../src/include/radiostation.h" +#include "../../src/include/aboutwidget.h" +#include "../../src/include/station-drag-object.h" + +#include "docking.h" +#include "docking-configuration.h" + +#define POPUP_ID_START_RECORDING_DEFAULT 0 +#define POPUP_ID_STOP_RECORDING_BASE 100 + +/////////////////////////////////////////////////////////////////////// + +PLUGIN_LIBRARY_FUNCTIONS(RadioDocking, "kradio-gui-docking-menu", i18n("Tray Menu for TDERadio")); + +///////////////////////////////////////////////////////////////////////////// + +RadioDocking::RadioDocking(const TQString &name) + : KSystemTray (NULL, name.ascii()), + PluginBase(name, i18n("Docking Plugin")), + m_pluginMenu(NULL), + m_recordingMenu(NULL), + m_NextRecordingMenuID(POPUP_ID_STOP_RECORDING_BASE), + m_leftClickAction(lcaShowHide) +{ + setPixmap(BarIcon("kradio")); + + m_menu = contextMenu(); + TQObject::connect(m_menu, TQT_SIGNAL(activated(int)), + this, TQT_SLOT(slotMenuItemActivated(int))); + + buildContextMenu (); + show(); + setAcceptDrops(true); +} + +RadioDocking::~RadioDocking() +{ +} + + +bool RadioDocking::connectI (Interface *i) +{ + bool a = IRadioClient::connectI(i); + bool b = ITimeControlClient::connectI(i); + bool c = IRadioDevicePoolClient::connectI(i); + bool d = IStationSelection::connectI(i); + bool e = ISoundStreamClient::connectI(i); + bool f = PluginBase::connectI(i); + return a || b || c || d || e || f; +} + + +bool RadioDocking::disconnectI (Interface *i) +{ + bool a = IRadioClient::disconnectI(i); + bool b = ITimeControlClient::disconnectI(i); + bool c = IRadioDevicePoolClient::disconnectI(i); + bool d = IStationSelection::disconnectI(i); + bool e = ISoundStreamClient::disconnectI(i); + bool f = PluginBase::disconnectI(i); + return a || b || c || d || e || f; +} + + +void RadioDocking::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid) +{ + ISoundStreamClient::noticeConnectedI(s, pointer_valid); + if (s && pointer_valid) { + s->register4_sendStartRecordingWithFormat(this); + s->register4_sendStopRecording (this); + s->register4_notifySoundStreamChanged (this); + } +} + + + +bool RadioDocking::setStationSelection(const TQStringList &sl) +{ + if (m_stationIDs != sl) { + m_stationIDs = sl; + buildContextMenu(); + notifyStationSelectionChanged(m_stationIDs); + } + return true; +} + + +// PluginBase + +void RadioDocking::restoreState (TDEConfig *config) +{ + config->setGroup(TQString("radiodocking-") + name()); + + m_stationIDs.clear(); + int nStations = config->readNumEntry("nStations", 0); + for (int i = 1; i <= nStations; ++i) { + TQString s = config->readEntry(TQString("stationID-") + TQString().setNum(i), TQString()); + if (s.length()) + m_stationIDs += s; + } + + m_leftClickAction = (LeftClickAction)config->readNumEntry("left_click_action", lcaShowHide); + + buildContextMenu(); + notifyStationSelectionChanged(m_stationIDs); + + int n = config->readNumEntry("show_hide_cache_entries", 0); + for (int i = 1; i <= n; ++i) { + TQString s = config->readEntry(TQString("show_hide_cache_id_%1").arg(i), TQString()); + bool b = config->readBoolEntry(TQString("show_hide_cache_value_%1").arg(i), false); + if (!s.isNull()) { + m_widgetsShownCache.insert(s,b); + } + } +} + + +void RadioDocking::saveState (TDEConfig *config) const +{ + config->setGroup(TQString("radiodocking-") + name()); + + config->writeEntry("nStations", m_stationIDs.size()); + int i = 1; + TQStringList::const_iterator end = m_stationIDs.end(); + for (TQStringList::const_iterator it = m_stationIDs.begin(); it != end; ++it, ++i) { + config->writeEntry(TQString("stationID-") + TQString().setNum(i), *it); + } + config->writeEntry("left_click_action", (int)m_leftClickAction); + + config->writeEntry("show_hide_cache_entries", m_widgetsShownCache.count()); + i = 1; + for (TQMapConstIterator<TQString, bool> it = m_widgetsShownCache.begin(); it != m_widgetsShownCache.end(); ++it, ++i) { + config->writeEntry(TQString("show_hide_cache_id_%1").arg(i), it.key()); + config->writeEntry(TQString("show_hide_cache_value_%1").arg(i), *it); + } +} + + +ConfigPageInfo RadioDocking::createConfigurationPage() +{ + DockingConfiguration *conf = new DockingConfiguration(this, NULL); + connectI (conf); + + TQObject::connect(this, TQT_SIGNAL(sigLeftClickActionChanged(LeftClickAction)), + conf, TQT_SLOT(slotLeftClickActionChanged(LeftClickAction))); + + return ConfigPageInfo( + conf, + i18n("Docking Menu"), + i18n("Docking Menu Configuration"), + "kmenuedit" + ); +} + +AboutPageInfo RadioDocking::createAboutPage() +{ +/* TDEAboutData aboutData("kradio", + NULL, + NULL, + I18N_NOOP("Docking Menu for TDERadio"), + TDEAboutData::License_GPL, + "(c) 2002-2005 Martin Witte, Klas Kalass", + 0, + "http://sourceforge.net/projects/kradio", + 0); + aboutData.addAuthor("Martin Witte", "", "[email protected]"); + aboutData.addAuthor("Klas Kalass", "", "[email protected]"); + + return AboutPageInfo( + new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed), + i18n("Docking Menu"), + i18n("Docking Menu Plugin"), + "kmenuedit" + );*/ + return AboutPageInfo(); +} + + + +void RadioDocking::buildContextMenu() +{ + m_menu->clear(); + m_pluginMenu = NULL; + m_recordingMenu = NULL; + + m_titleID = m_menu->insertTitle ("title-dummy"); + + buildStationList(); + + m_alarmID = m_menu->insertTitle ("alarm-dummy"); + noticeNextAlarmChanged(queryNextAlarm()); + + m_sleepID = m_menu->insertItem(SmallIcon("kradio_zzz"), "sleep-dummy", + this, TQT_SLOT(slotSleepCountdown())); + noticeCountdownStarted(queryCountdownEnd()); + + m_seekfwID = m_menu->insertItem(SmallIcon("forward"), i18n("Search Next Station"), + this, TQT_SLOT(slotSeekFwd())); + m_seekbwID = m_menu->insertItem(SmallIcon("back"), i18n("Search Previous Station"), + this, TQT_SLOT(slotSeekBkwd())); + + // recording menu + buildRecordingMenu(); + m_menu->insertItem(i18n("Recording"), m_recordingMenu); + + + m_powerID = m_menu->insertItem(SmallIcon("kradio_muteoff"), "power-dummy", + this, TQT_SLOT(slotPower())); + m_pauseID = m_menu->insertItem(SmallIcon("kradio_pause"), i18n("Pause Radio"), + this, TQT_SLOT(slotPause())); + noticePowerChanged(queryIsPowerOn()); + + m_menu->insertSeparator(); + + m_menu->insertItem(SmallIcon("kradio"), i18n("&About"), this, TQT_SLOT(slotShowAbout())); + + // build list of widgets for hide/show items + m_pluginMenu = new TDEPopupMenu(m_menu); + if (m_manager) { + m_manager->addWidgetPluginMenuItems(m_pluginMenu, m_widgetPluginIDs); + m_menu->insertItem(SmallIcon("kradio_plugins"), i18n("Show/Hide Plugins"), m_pluginMenu); + } + + m_menu->insertSeparator(); + m_menu->insertItem( SmallIcon("exit"), i18n("&Quit" ), kapp, TQT_SLOT(quit()) ); + + + noticeStationChanged(queryCurrentStation(), -1); + +} + + +void RadioDocking::buildStationList() +{ + m_stationMenuIDs.clear(); + + const RawStationList &sl = queryStations().all(); + const RadioStation &crs = queryCurrentStation(); + + int k = 0; + TQStringList::iterator end = m_stationIDs.end(); + for (TQStringList::iterator it = m_stationIDs.begin(); it != end; ++it) { + const RadioStation &rs = sl.stationWithID(*it); + + if (rs.isValid()) { + + ++k; + TQString shortcut = k < 10 ? "&"+TQString().setNum(k) : k == 10 ? "1&0" : TQString().setNum(k); + TQString name = rs.longName().replace("&", "&&"); + TQString item = shortcut + " " + name; + int id = m_menu->insertItem(item); + + m_stationMenuIDs.push_back(id); + m_menu->setItemChecked (id, rs.compare(crs) == 0); + + } else { + m_stationMenuIDs.push_back(-1); + } + } +} + + +void RadioDocking::slotSeekFwd() +{ + ISeekRadio *seeker = dynamic_cast<ISeekRadio*>(queryActiveDevice()); + if (seeker) + seeker->startSeekUp(); +} + + +void RadioDocking::slotSeekBkwd() +{ + ISeekRadio *seeker = dynamic_cast<ISeekRadio*>(queryActiveDevice()); + if (seeker) + seeker->startSeekUp(); +} + + + +void RadioDocking::slotShowAbout() +{ + if (m_manager) { + KDialogBase *d = m_manager->getAboutDialog(); + if (d) d->show(); + } +} + + +void RadioDocking::slotPower() +{ + if (queryIsPowerOn()) { + sendPowerOff(); + } else { + sendPowerOn(); + } +} + + +void RadioDocking::slotPause() +{ + if (queryIsPowerOn()) { + sendPausePlayback(queryCurrentSoundStreamID()); + } +} + + +void RadioDocking::slotSleepCountdown() +{ + if (queryCountdownEnd().isValid()) { + sendStopCountdown(); + } else { + sendStartCountdown(); + } +} + + +bool RadioDocking::noticeNextAlarmChanged(const Alarm *a) +{ + TQDateTime d; + if (a) d = a->nextAlarm(); + + if (d.isValid()) + m_menu->changeTitle (m_alarmID, i18n("next alarm: %1").arg(d.toString())); + else + m_menu->changeTitle (m_alarmID, i18n("<no alarm pending>")); + return true; +} + + +bool RadioDocking::noticeCountdownStarted(const TQDateTime &end) +{ + if (end.isValid()) + m_menu->changeItem (m_sleepID, SmallIcon("kradio_zzz"), i18n("Stop Sleep Countdown (running until %1)").arg(end.toString())); + else + m_menu->changeItem (m_sleepID, SmallIcon("kradio_zzz"), i18n("Start Sleep Countdown")); + return true; +} + + +bool RadioDocking::noticeCountdownStopped() +{ + m_menu->changeItem (m_sleepID, SmallIcon("kradio_zzz"), i18n("Start Sleep Countdown")); + return true; +} + + +bool RadioDocking::noticeCountdownZero() +{ + m_menu->changeItem (m_sleepID, SmallIcon("kradio_zzz"), i18n("Start Sleep Countdown")); + return true; +} + + +bool RadioDocking::noticePowerChanged(bool on) +{ + m_menu->changeItem(m_powerID, SmallIcon(on ? "kradio_muteon" : "kradio_muteoff"), + on ? i18n("Power Off") : i18n("Power On")); + m_menu->setItemEnabled(m_pauseID, on); + return true; +} + +bool RadioDocking::noticeCountdownSecondsChanged(int /*n*/) +{ + return false; +} + + + +bool RadioDocking::noticeStationChanged (const RadioStation &rs, int /*idx*/) +{ + TQString s = i18n("invalid station"); + if (rs.isValid()) + s = rs.longName(); + + TQToolTip::add(this, s); + m_menu->changeTitle (m_titleID, i18n("TDERadio: %1").arg(s)); + // FIXME: title does not change in opened popupmenu + + TQValueList<int>::iterator iit = m_stationMenuIDs.begin(); + TQValueList<int>::iterator end = m_stationMenuIDs.end(); + TQStringList::iterator sit = m_stationIDs.begin(); + for (; iit != end; ++iit, ++sit) { + if (*iit != -1) { + bool on = rs.stationID() == *sit; + m_menu->setItemChecked (*iit, on); + } + } + + bool r = false; + SoundFormat sf; + queryIsRecordingRunning(queryCurrentSoundStreamID(), r, sf); + m_recordingMenu->setItemEnabled(m_recordingID, !r); + return true; +} + + +bool RadioDocking::noticeStationsChanged(const StationList &/*sl*/) +{ + buildContextMenu(); + return true; +} + + +void RadioDocking::mousePressEvent( TQMouseEvent *e ) +{ + KSystemTray::mousePressEvent(e); + + switch ( e->button() ) { + case Qt::LeftButton: + switch (m_leftClickAction) { + case lcaShowHide : + ShowHideWidgetPlugins(); + // FIXME: [mcamen] According the KDE usability guidelines a left + // click on the systray icon should show/hide the + // application window + // TODO: [mcamen] Use KSystemtray::toggleActive and friends once we + // depend on KDE 3.3 + break; + case lcaPowerOnOff : + if (queryIsPowerOn()) + sendPowerOff(); + else + sendPowerOn(); + break; + default: + break; + } + break; + default: + // nothing + break; + } +} + +void RadioDocking::ShowHideWidgetPlugins() +{ + // nothing in cache => hide everything + if (!m_widgetsShownCache.count()) { + for (TQMapIterator<WidgetPluginBase*, int> it = m_widgetPluginIDs.begin(); it != m_widgetPluginIDs.end(); ++it) { + WidgetPluginBase *p = it.key(); + if (p) { + bool visible = p->isAnywhereVisible(); + TQString name = p->name(); + logDebug(TQString("visibility of %1: %2").arg(name).arg(visible)); + m_widgetsShownCache.insert(name, visible); + p->getWidget()->hide(); + } + } + } + else { + TQMap<TQString, bool> tmpCache = m_widgetsShownCache; + int d = KWin::currentDesktop(); + for (TQMapIterator<WidgetPluginBase*, int> it = m_widgetPluginIDs.begin(); it != m_widgetPluginIDs.end(); ++it) { + WidgetPluginBase *p = it.key(); + TQString name = p ? p->name() : TQString(); + if (p && tmpCache.contains(name) && tmpCache[name]) { + p->showOnOrgDesktop(); + } + } + m_widgetsShownCache.clear(); + KWin::setCurrentDesktop(d); + } +} + +void RadioDocking::slotMenuItemActivated(int id) +{ + const StationList &sl = queryStations(); + TQValueList<int>::iterator iit = m_stationMenuIDs.begin(); + TQValueList<int>::iterator end = m_stationMenuIDs.end(); + TQStringList::iterator sit = m_stationIDs.begin(); + for (; iit != end; ++iit, ++sit) { + if (*iit == id) { + const RadioStation &rs = sl.stationWithID(*sit); + if (rs.isValid()) + sendActivateStation(rs); + } + } +} + + +void RadioDocking::noticeWidgetPluginShown(WidgetPluginBase *b, bool shown) +{ + if (!m_manager || !b || !m_widgetPluginIDs.contains(b)) + return; + m_manager->updateWidgetPluginMenuItem(b, m_pluginMenu, m_widgetPluginIDs, shown); + + if (shown) + m_widgetsShownCache.clear(); +} + + +void RadioDocking::noticePluginsChanged(const PluginList &/*l*/) +{ + buildContextMenu(); +} + + +// ISoundStreamClient + +bool RadioDocking::startRecordingWithFormat( + SoundStreamID id, + const SoundFormat &/*proposed_format*/, + SoundFormat &/*real_format*/) +{ + if (!id.isValid() || id != queryCurrentSoundStreamID() || m_StreamID2MenuID.contains(id)) + return false; + + TQString descr; + querySoundStreamDescription(id, descr); + int menu_id = m_NextRecordingMenuID++; + m_recordingMenu->insertItem(SmallIcon("kradio_record"), + i18n("Stop Recording of %1").arg(descr), + menu_id); + m_MenuID2StreamID.insert(menu_id, id); + m_StreamID2MenuID.insert(id, menu_id); + + if (id == queryCurrentSoundStreamID()) + m_recordingMenu->setItemEnabled(m_recordingID, false); + + setPixmap(BarIcon("kradio_plus_rec")); + return false; // this is only a "hook" that does not initiate the recording so don't say that we handled the event +} + + +bool RadioDocking::stopRecording (SoundStreamID id) +{ + if (!id.isValid() || !m_StreamID2MenuID.contains(id)) + return false; + + int menu_id = m_StreamID2MenuID[id]; + m_recordingMenu->removeItem(menu_id); + m_MenuID2StreamID.remove(menu_id); + m_StreamID2MenuID.remove(id); + + if (id == queryCurrentSoundStreamID()) + m_recordingMenu->setItemEnabled(m_recordingID, true); + + setPixmap(BarIcon("kradio")); + + return false; +} + + +void RadioDocking::slotRecordingMenu(int i) +{ + if (i == POPUP_ID_START_RECORDING_DEFAULT) { + SoundStreamID id = queryCurrentSoundStreamID(); + bool r = false; + SoundFormat sf; + queryIsRecordingRunning(id, r, sf); + if (!r) { + if (!queryIsPowerOn()) + sendPowerOn(); + sendStartRecording(id); + } + } else if (m_MenuID2StreamID.contains(i)) { + sendStopRecording(m_MenuID2StreamID[i]); + } +} + +void RadioDocking::buildRecordingMenu() +{ + TQMap<TQString, SoundStreamID> streams; + queryEnumerateSoundStreams(streams); + + TDEPopupMenu *m = new TDEPopupMenu(m_menu); + + m_recordingID = m->insertItem(SmallIcon("kradio_record"), i18n("Start Recording"), + POPUP_ID_START_RECORDING_DEFAULT); + TQObject::connect(m, TQT_SIGNAL(activated(int)), + this, TQT_SLOT(slotRecordingMenu(int))); + SoundStreamID currentID = queryCurrentSoundStreamID(); + + TQMapIterator<TQString, SoundStreamID> end = streams.end(); + for (TQMapIterator<TQString, SoundStreamID> it = streams.begin(); it != end; ++it) { + + SoundStreamID id = *it; + TQString descr = it.key(); + bool r = false; + SoundFormat sf; + queryIsRecordingRunning(id, r, sf); + if (r) { + int menu_id = m_NextRecordingMenuID++; + m->insertItem(SmallIcon("kradio_record"), + i18n("Stop Recording of %1").arg(descr), + menu_id); + m_MenuID2StreamID.insert(menu_id, id); + m_StreamID2MenuID.insert(id, menu_id); + + if (id == currentID) + m_recordingMenu->setItemEnabled(m_recordingID, false); + } + } + m_recordingMenu = m; +} + + +bool RadioDocking::noticeSoundStreamChanged(SoundStreamID id) +{ + if (m_StreamID2MenuID.contains(id)) { + TQString descr; + querySoundStreamDescription(id, descr); + m_recordingMenu->changeItem(m_StreamID2MenuID[id], + SmallIcon("kradio_record"), + i18n("Stop Recording of %1").arg(descr)); + return true; + } + return false; +} + + +void RadioDocking::setLeftClickAction(LeftClickAction action) +{ + if (m_leftClickAction != action) { + m_leftClickAction = action; + emit sigLeftClickActionChanged(m_leftClickAction); + } +} + +void RadioDocking::dragEnterEvent(TQDragEnterEvent* event) +{ + bool a = StationDragObject::canDecode(event); + if (a) + IErrorLogClient::staticLogDebug("contentsDragEnterEvent accepted"); + else + IErrorLogClient::staticLogDebug("contentsDragEnterEvent rejected"); + event->accept(a); +} + +void RadioDocking::dropEvent(TQDropEvent* event) +{ + TQStringList list; + + if ( StationDragObject::decode(event, list) ) { + TQStringList l = getStationSelection(); + for (TQValueListConstIterator<TQString> it = list.begin(); it != list.end(); ++it) + if (!l.contains(*it)) + l.append(*it); + setStationSelection(l); + } +} + +#include "docking.moc" |