diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 84da08d7b7fcda12c85caeb5a10b4903770a6f69 (patch) | |
tree | 2a6aea76f2dfffb4cc04bb907c4725af94f70e72 /kicker-applets | |
download | tdeaddons-84da08d7b7fcda12c85caeb5a10b4903770a6f69.tar.gz tdeaddons-84da08d7b7fcda12c85caeb5a10b4903770a6f69.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeaddons@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kicker-applets')
91 files changed, 10349 insertions, 0 deletions
diff --git a/kicker-applets/Makefile.am b/kicker-applets/Makefile.am new file mode 100644 index 0000000..462f19f --- /dev/null +++ b/kicker-applets/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = $(AUTODIRS) + diff --git a/kicker-applets/kbinaryclock/Makefile.am b/kicker-applets/kbinaryclock/Makefile.am new file mode 100644 index 0000000..5039925 --- /dev/null +++ b/kicker-applets/kbinaryclock/Makefile.am @@ -0,0 +1,22 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = kbinaryclock_panelapplet.la + +kbinaryclock_panelapplet_la_SOURCES = kbinaryclock.cpp settings.ui datepicker.cpp prefs.kcfgc + +METASOURCES = AUTO + +noinst_HEADERS = kbinaryclock.h datepicker.h + +lnkdir = $(kde_datadir)/kicker/applets +lnk_DATA = kbinaryclock.desktop +kde_kcfg_DATA = kbinaryclock.kcfg + +EXTRA_DIST = $(lnk_DATA) + +kbinaryclock_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kbinaryclock_panelapplet_la_LIBADD = $(LIB_KDEUI) + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/kbinaryclock.pot + diff --git a/kicker-applets/kbinaryclock/datepicker.cpp b/kicker-applets/kbinaryclock/datepicker.cpp new file mode 100644 index 0000000..19efc1d --- /dev/null +++ b/kicker-applets/kbinaryclock/datepicker.cpp @@ -0,0 +1,51 @@ +/************************************************************ + +Copyright (c) 1996-2002 the kicker authors. See file AUTHORS. + +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 +AUTHORS 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. + +******************************************************************/ + +#include "datepicker.h" + + +#include <kdatepicker.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kwin.h> + +DatePicker::DatePicker(QWidget *parent, const QDate& date) + : QVBox( parent, 0, WType_TopLevel | WDestructiveClose | + WStyle_Customize | WStyle_StaysOnTop | WStyle_NoBorder ) +{ + setFrameStyle( QFrame::PopupPanel | QFrame::Raised ); + KWin::setOnAllDesktops( handle(), true ); + picker = new KDatePicker(this, date); + picker->setCloseButton(true); + + /* name and icon for kicker's taskbar */ + setCaption(i18n("Calendar")); + setIcon(SmallIcon("date")); +} + +void DatePicker::keyReleaseEvent(QKeyEvent *e) +{ + DATEPICKER_INHERITED::keyReleaseEvent(e); + if (e->key() == Qt::Key_Escape) + close(); +} diff --git a/kicker-applets/kbinaryclock/datepicker.h b/kicker-applets/kbinaryclock/datepicker.h new file mode 100644 index 0000000..2cf524a --- /dev/null +++ b/kicker-applets/kbinaryclock/datepicker.h @@ -0,0 +1,42 @@ +/***************************************************************** + +Copyright (c) 1996-2000 the kicker authors. See file AUTHORS. + +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 +AUTHORS 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. + +******************************************************************/ + +#ifndef __DATEPICKER_H +#define __DATEPICKER_H + +#include <qvbox.h> + +class QDate; +class KDatePicker; + +#define DATEPICKER_INHERITED QVBox +class DatePicker : public QVBox +{ +public: + DatePicker(QWidget*, const QDate&); +private: + KDatePicker *picker; + void keyReleaseEvent(QKeyEvent *e); +}; + +#endif diff --git a/kicker-applets/kbinaryclock/kbinaryclock.cpp b/kicker-applets/kbinaryclock/kbinaryclock.cpp new file mode 100644 index 0000000..33e8ced --- /dev/null +++ b/kicker-applets/kbinaryclock/kbinaryclock.cpp @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2003 Benjamin C Meyer ([email protected]) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#include "kbinaryclock.h" +#include "datepicker.h" + +#include <kapplication.h> +#include <kconfigdialog.h> +#include <kconfig.h> +#include <kiconloader.h> +#include <kglobalsettings.h> + +#include <qradiobutton.h> +#include <kcolorbutton.h> +#include <kpopupmenu.h> +#include <qslider.h> +#include <qcursor.h> +#include <qtimer.h> +#include <qtooltip.h> +#include <qlabel.h> + +#include <kprocess.h> +#include <kstandarddirs.h> +#include <qclipboard.h> +#include <kled.h> + +extern "C" +{ + KDE_EXPORT KPanelApplet* init( QWidget *parent, const QString& configFile ) { + KGlobal::locale()->insertCatalogue( "kbinaryclock"); + return new KBinaryClock( configFile, KPanelApplet::Normal, + KPanelApplet::Preferences, parent, "kbinaryclock"); + } +} + +KConfigDialogImp::KConfigDialogImp( QWidget *parent, const char *name, KConfigSkeleton *prefs, KDialogBase::DialogType dialogType, KDialogBase::ButtonCode defaultButton, bool modal) : + KConfigDialog(parent, name, prefs, dialogType,(KDialogBase::ButtonCode) (KDialogBase::Default | KDialogBase::Ok | KDialogBase::Apply | KDialogBase::Cancel ), defaultButton, modal) +{ + // As a temporary mesure until the kicker applet's app name is set to the + // applets name so KDialogBase gets the right info. + setPlainCaption(i18n("Configure - KBinaryClock")); + setIcon(SmallIcon("date")); + + settings = new SettingsImp(0, "General"); + addPage(settings, i18n("General"), "package_settings"); + connect(this, SIGNAL(widgetModified()), settings, SLOT(updatePreview())); +} + +SettingsImp::SettingsImp(QWidget* parent, const char* name, WFlags fl): Settings(parent, name, fl){ +} + +/** + * Update the preview + */ +void SettingsImp::updatePreview(){ + int shape = Shape_Circular->isChecked() ? Prefs::EnumShape::Circular : Prefs::EnumShape::Rectangular; + int look = KLed::Raised; + look = Look_Flat->isChecked() ? Prefs::EnumLook::Flat : look; + look = Look_Sunken->isChecked() ? Prefs::EnumLook::Sunken : look; + QColor color = kcfg_Color->color(); + int darkFactor = kcfg_DarkFactor->value(); + QColor backgroundColor = kcfg_Background->color(); + frame1->setBackgroundColor(backgroundColor); + + kLed1->setBackgroundColor(backgroundColor); + kLed2->setBackgroundColor(backgroundColor); + kLed3->setBackgroundColor(backgroundColor); + kLed4->setBackgroundColor(backgroundColor); + kLed5->setBackgroundColor(backgroundColor); + kLed6->setBackgroundColor(backgroundColor); + + kLed1->setShape((KLed::Shape)shape); + kLed2->setShape((KLed::Shape)shape); + kLed3->setShape((KLed::Shape)shape); + kLed4->setShape((KLed::Shape)shape); + kLed5->setShape((KLed::Shape)shape); + kLed6->setShape((KLed::Shape)shape); + + kLed1->setColor(color); + kLed2->setColor(color); + kLed3->setColor(color); + kLed4->setColor(color); + kLed5->setColor(color); + kLed6->setColor(color); + + kLed1->setLook((KLed::Look)look); + kLed2->setLook((KLed::Look)look); + kLed3->setLook((KLed::Look)look); + kLed4->setLook((KLed::Look)look); + kLed5->setLook((KLed::Look)look); + kLed6->setLook((KLed::Look)look); + + kLed1->setDarkFactor(darkFactor); + kLed2->setDarkFactor(darkFactor); + kLed3->setDarkFactor(darkFactor); + kLed4->setDarkFactor(darkFactor); + kLed5->setDarkFactor(darkFactor); + kLed6->setDarkFactor(darkFactor); +} + +/** + * Constructor, create LED's + */ +KBinaryClock::KBinaryClock(const QString& configFile, Type type, int actions, QWidget *parent, const char *name) + : KPanelApplet(configFile, type, actions, parent, name), ledWidth(6), + _calendar(NULL), _disableCalendar(false), + prefs( new Prefs(sharedConfig())), m_tooltip(this) +{ + prefs->readConfig(); + setBackgroundOrigin(AncestorOrigin); + for(int i=0; i < 4; i++){ + for(int j=0; j < ledWidth;j++){ + KLed *led = new KLed( this ); + led->setBackgroundOrigin(AncestorOrigin); + ledMatrix[j][i] = led; + } + } + + // Why does kicker start out with a size of 800x409? + // Kicker bug? + resize(60,42); + + updateClock(); + loadSettings(); + QTimer *timer=new QTimer(this); + connect (timer, SIGNAL (timeout()), this, SLOT (updateClock())); + timer->start(500,false); +} + +KBinaryClock::~KBinaryClock() +{ + delete prefs; + KGlobal::locale()->removeCatalogue( "kbinaryclock"); +} + +/** + * Return the computed height of the widget. + */ +int KBinaryClock::widthForHeight( int height ) const { + return (height-2)/4*ledWidth; +} + +/** + * Return the computed width of the widget. + */ +int KBinaryClock::heightForWidth( int width ) const { + return (width/ledWidth)*4; +} + +void KBinaryClock::resizeEvent( QResizeEvent *e ) { + int width = e->size().width(); + for (int i=0; i < ledWidth; i++) + for (int j=0; j < 4; j++) + ledMatrix[i][j]->setGeometry( QRect( (width/ledWidth)*i, (width/ledWidth)*j, width/ledWidth, width/ledWidth) ); +} + +/** + * Load the settings for the clock. + */ +void KBinaryClock::loadSettings(){ + int shape = prefs->shape(); + int look = prefs->look(); + QColor color = prefs->color(); + + int darkFactor = prefs->darkFactor(); + QColor backgroundColor = prefs->background(); + bool modifyBackground = false; + if(backgroundColor != KApplication::palette().active().background()){ + setPaletteBackgroundColor(backgroundColor); + modifyBackground = true; + } + + bool showSeconds = prefs->show_Seconds(); + ledWidth = (showSeconds == true) ? 6 : 4; + for(int i=0; i < 4; i++){ + for(int j=4; j < 6;j++){ + if(showSeconds) + ledMatrix[j][i]->show(); + else + ledMatrix[j][i]->hide(); + } + } + for(int i=0; i < 4; i++){ + for(int j=0; j < ledWidth;j++){ + ledMatrix[j][i]->setShape((KLed::Shape)shape); + ledMatrix[j][i]->setColor(color); + ledMatrix[j][i]->setLook((KLed::Look)look); + ledMatrix[j][i]->setDarkFactor(darkFactor); + // Dammed if you do, dammed if you don't + if(modifyBackground || ledMatrix[j][i]->backgroundColor() != backgroundColor) + ledMatrix[j][i]->setPaletteBackgroundColor(backgroundColor); + } + } + updateLayout(); +} + +/** + * Show Settings dialog. + */ +void KBinaryClock::preferences(){ + if(KConfigDialog::showDialog("settings")) + return; + + KConfigDialogImp *dialog = new KConfigDialogImp(this, "settings", prefs, KDialogBase::Swallow); + connect(dialog, SIGNAL(settingsChanged()), this, SLOT(loadSettings())); + dialog->show(); + dialog->settings->updatePreview(); +} + +/** + * Get the time and update the LED's + */ +void KBinaryClock::updateClock(){ + QString time = "hhmmss"; + if(KGlobal::locale()->use12Clock()) + time += "ap"; + + QString currentTime = (QTime::currentTime()).toString(time); + int splice[6]; + splice[0] = currentTime.mid( 0, 1 ).toInt(); + splice[1] = currentTime.mid( 1, 1 ).toInt(); + splice[2] = currentTime.mid( 2, 1 ).toInt(); + splice[3] = currentTime.mid( 3, 1 ).toInt(); + splice[4] = currentTime.mid( 4, 1 ).toInt(); + splice[5] = currentTime.mid( 5, 1 ).toInt(); + + for (int i=0; i<ledWidth; i++) { + (splice[i] & 8) != 0 ? ledMatrix[i][0]->setState(KLed::On) : ledMatrix[i][0]->setState(KLed::Off); + (splice[i] & 4) != 0 ? ledMatrix[i][1]->setState(KLed::On) : ledMatrix[i][1]->setState(KLed::Off); + (splice[i] & 2) != 0 ? ledMatrix[i][2]->setState(KLed::On) : ledMatrix[i][2]->setState(KLed::Off); + (splice[i] & 1) != 0 ? ledMatrix[i][3]->setState(KLed::On) : ledMatrix[i][3]->setState(KLed::Off); + } + + // TODO add hide_Off_Leds checkbox to ui file post 3.3 + // sense we can't add strings. + if(prefs->hide_Off_Leds()) + for (int i=0; i<ledWidth; i++) { + for( int j=0; j < 4;j++){ + if(ledMatrix[i][j]->state() == KLed::Off) + ledMatrix[i][j]->hide(); + else + ledMatrix[i][j]->show(); + } + } +} + +/** + * Catch the right click press + */ + void KBinaryClock::mousePressEvent(QMouseEvent *event) { + switch (event->button()) { + case QMouseEvent::RightButton: + QToolTip::remove(this); + openContextMenu(); + break; + case QMouseEvent::LeftButton: + toggleCalendar(); + QToolTip::remove(this); + break; + case QMouseEvent::MidButton: + QToolTip::remove(this); + break; + default: + break; + } +} + +/** + * Deal with right click's + */ +void KBinaryClock::openContextMenu() { + bool bImmutable = config()->isImmutable(); + + KPopupMenu *menu = new KPopupMenu(); + menu->insertTitle( SmallIcon( "clock" ), i18n( "KBinaryClock" ) ); + + KLocale *loc = KGlobal::locale(); + QDateTime dt = QDateTime::currentDateTime(); + + KPopupMenu *copyMenu = new KPopupMenu( menu ); + copyMenu->insertItem(loc->formatDateTime(dt), 201); + copyMenu->insertItem(loc->formatDate(dt.date()), 202); + copyMenu->insertItem(loc->formatDate(dt.date(), true), 203); + copyMenu->insertItem(loc->formatTime(dt.time()), 204); + copyMenu->insertItem(loc->formatTime(dt.time(), true), 205); + copyMenu->insertItem(dt.date().toString(), 206); + copyMenu->insertItem(dt.time().toString(), 207); + copyMenu->insertItem(dt.toString(), 208); + connect( copyMenu, SIGNAL( activated(int) ), this, SLOT( slotCopyMenuActivated(int) ) ); + + if (!bImmutable) + { + if (kapp->authorize("user/root")) + { + menu->insertItem(SmallIcon("date"), i18n("&Adjust Date && Time..."), 103, 4); + } + menu->insertItem(SmallIcon("kcontrol"), i18n("Date && Time &Format..."), 104, 5); + } + + menu->insertItem(SmallIcon("editcopy"), i18n("C&opy to Clipboard"), copyMenu, 105, 6); + if (!bImmutable) + { + menu->insertSeparator(7); + menu->insertItem(SmallIcon("configure"), i18n("&Configure KBinaryClock..."), 102, 8); + } + int result = menu->exec( QCursor::pos() ); + + KProcess proc; + switch (result) { + case 102: + preferences(); + break; + case 103: + proc << locate("exe", "kdesu"); + proc << "--nonewdcop"; + proc << QString("%1 clock --lang %2") + .arg(locate("exe", "kcmshell")) + .arg(KGlobal::locale()->language()); + proc.start(KProcess::DontCare); + break; + case 104: + proc << locate("exe", "kcmshell"); + proc << "language"; + proc.start(KProcess::DontCare); + break; + case 110: + preferences(); + break; + } /* switch() */ + delete menu; +} + +void KBinaryClock::slotCopyMenuActivated( int id ) { + QPopupMenu *m = (QPopupMenu *) sender(); + QString s = m->text(id); + QApplication::clipboard()->setText(s); +} + +void KBinaryClock::toggleCalendar() +{ + if (_calendar && !_disableCalendar) { + // calls slotCalendarDeleted which does the cleanup for us + _calendar->close(); + return; + } + if (_calendar || _disableCalendar){ + return; + } + _calendar = new DatePicker(this, QDateTime::currentDateTime().date()); + connect( _calendar, SIGNAL( destroyed() ), SLOT( slotCalendarDeleted() )); + + // some extra spacing is included if aligned on a desktop edge + QPoint c = mapToGlobal(QPoint(0,0)); + + int w = _calendar->sizeHint().width() + 28; + // Added 28 px. to size poperly as said in API + int h = _calendar->sizeHint().height(); + + switch (position()) { + case KPanelApplet::pLeft: c.setX(c.x()+width()+2); break; + case KPanelApplet::pRight: c.setX(c.x()-w-2); break; + case KPanelApplet::pTop: c.setY(c.y()+height()+2); break; + case KPanelApplet::pBottom: c.setY(c.y()-h-2); break; + } + + // make calendar fully visible + QRect deskR = KGlobalSettings::desktopGeometry(QPoint(0,0)); + + if (c.y()+h > deskR.bottom()) c.setY(deskR.bottom()-h-1); + if (c.x()+w > deskR.right()) c.setX(deskR.right()-w-1); + + _calendar->move(c); + _calendar->show(); +} + +void KBinaryClock::slotCalendarDeleted() +{ + _calendar = 0L; + // don't reopen the calendar immediately ... + _disableCalendar = true; + QTimer::singleShot(100, this, SLOT(slotEnableCalendar())); +} + +void KBinaryClock::slotEnableCalendar() +{ + _disableCalendar = false; +} + +ClockAppletToolTip::ClockAppletToolTip( KBinaryClock *clock ) : QToolTip( clock ), m_clock( clock ) {} + +void ClockAppletToolTip::maybeTip( const QPoint & /*point*/ ) +{ + tip(m_clock->geometry(), KGlobal::locale()->formatDate(QDateTime::currentDateTime().date(), false)); +} + +#include "kbinaryclock.moc" diff --git a/kicker-applets/kbinaryclock/kbinaryclock.desktop b/kicker-applets/kbinaryclock/kbinaryclock.desktop new file mode 100644 index 0000000..962d48e --- /dev/null +++ b/kicker-applets/kbinaryclock/kbinaryclock.desktop @@ -0,0 +1,108 @@ +[Desktop Entry] +Type=Plugin +Name=Binary Clock +Name[bg]=Двоичен часовник +Name[br]=Eurier binarel +Name[ca]=Rellotge binari +Name[cs]=Binární hodiny +Name[cy]=Cloc Deuaidd +Name[da]=Binært ur +Name[de]=Binäruhr +Name[el]=Δυαδικό ρολόι +Name[eo]=Duuma horloĝo +Name[es]=Reloj binario +Name[et]=Binaarkell +Name[eu]=Erloju bitarra +Name[fa]=ساعت دودویی +Name[fi]=Binäärikello +Name[fr]=Horloge binaire +Name[fy]=Binêre klok +Name[ga]=Clog Dénártha +Name[gl]=Relóxio Binário +Name[he]=שעון בינרי +Name[hi]=बाइनरी क्लॉक +Name[hr]=Binarni sat +Name[hu]=KBinaryClock +Name[is]=Tvíundarklukka +Name[it]=Orologio binario +Name[ja]=バイナリ時計 +Name[ka]=ორობითი საათი +Name[kk]=Бинарлы сағат +Name[km]=នាឡិកាគោលពីរ +Name[lt]=Skaitmeninis laikrodis +Name[mk]=Бинарен часовник +Name[ms]=Jam Binari +Name[nb]=Binærklokke +Name[nds]=Bineerklock +Name[ne]=बाइनरि घडी +Name[nl]=Binaire klok +Name[nn]=Binærklokke +Name[pa]=ਬਾਈਨਰੀ ਘੜੀ +Name[pl]=Zegar binarny +Name[pt]=Relógio Binário +Name[pt_BR]=Relógio Binário +Name[ru]=Двоичные часы +Name[sk]=Binárne hodiny +Name[sl]=Dvojiška ura +Name[sr]=Бинарни часовник +Name[sr@Latn]=Binarni časovnik +Name[sv]=Binärklocka +Name[ta]=இருநிலை கடிகாரம் +Name[tr]=İkili Saat +Name[uk]=KBinaryClock +Name[uz]=Binar soat +Name[uz@cyrillic]=Бинар соат +Name[vi]=Đồng hồ nhị phân +Name[zh_CN]=二进制时钟 +Name[zh_TW]=二位元鐘 +Comment=Shows the time in binary format +Comment[bg]=Показване на времето в двоичен формат +Comment[ca]=Mostra l'hora en format binari +Comment[cs]=Zobrazuje čas v binárním tvaru +Comment[da]=Viser tiden i binært format +Comment[de]=Zeigt die Zeit in binärem Format +Comment[el]=Εμφάνιση του χρόνου σε δυαδική μορφή +Comment[eo]=Montras la tempon per duuma formato +Comment[es]=Muestra la hora en formato binario +Comment[et]=Näitab aega binaarkujul +Comment[eu]=Erakutsi ordua formatu bitarrean +Comment[fa]=فقرهها را در قالب دودویی نمایش میدهد +Comment[fi]=Näyttää ajan binäärimuodossa +Comment[fr]=Affiche l'heure en binaire +Comment[fy]=Toant de tiid yn in binêr formaat +Comment[ga]=Taispeáin an t-am i bhformáid dhénártha +Comment[gl]=Mostra a hora en formato binário +Comment[hr]=Prikaz vremena u binarnom obliku +Comment[hu]=Bináris formátumban jeleníti meg az időt +Comment[is]=Sýnir tímann í tvíunarsniði +Comment[it]=Mostra il tempo in formato binario +Comment[ja]=時刻をバイナリ形式で表示します +Comment[ka]=დროს ორობით ფორმატში აჩვენებს +Comment[kk]=Уақытты бинарлы пішімінде көрсету +Comment[km]=បង្ហាញម៉ោងជាទ្រង់ទ្រាយគោលពីរ +Comment[lt]=Rodo laiką skaitmeniniu formatu +Comment[mk]=Го прикажува времето во бинарен формат +Comment[nb]=Viser klokkeslett i binært format +Comment[nds]=Wiest de Tiet in bineer Formaat +Comment[ne]=बाइनरि ढाँचामा समय देखाउछ +Comment[nl]=Toont de tijd in een binair formaat +Comment[nn]=Viser tida i binærformat +Comment[pl]=Pokazuje czas w postaci binarnej +Comment[pt]=Mostra a hora em formato binário +Comment[pt_BR]=Mostra a hora em formato binário +Comment[ru]=Показ времени в двоичном формате +Comment[sk]=Zobrazí čas v binárnom formáte +Comment[sl]=Prikazuje čas v dvojiški obliki +Comment[sr]=Приказује време у бинарном формату +Comment[sr@Latn]=Prikazuje vreme u binarnom formatu +Comment[sv]=Visar tiden med binärformat +Comment[tr]=Zamanı ikili biçemde gösterir +Comment[uk]=Показує час в двійковому форматі +Comment[uz]=Vaqtni ikkili sanoq tizimida koʻrsatish +Comment[uz@cyrillic]=Вақтни иккили саноқ тизимида кўрсатиш +Comment[vi]=Hiển thị giờ định dạng nhị phân +Comment[zh_CN]=以二进制格式显示时间 +Comment[zh_TW]=以二進位格式顯示時間 +Icon=kbinaryclock +X-KDE-Library=kbinaryclock_panelapplet +X-KDE-UniqueApplet = false diff --git a/kicker-applets/kbinaryclock/kbinaryclock.h b/kicker-applets/kbinaryclock/kbinaryclock.h new file mode 100644 index 0000000..9edf51d --- /dev/null +++ b/kicker-applets/kbinaryclock/kbinaryclock.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2003 Benjamin C Meyer ([email protected]) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef KBINARYCLOCK_H +#define KBINARYCLOCK_H + +#include <kpanelapplet.h> +#include <qevent.h> +#include <kglobal.h> +#include <kaboutdata.h> +#include <qdatetime.h> +#include <qtooltip.h> +#include <kconfigdialog.h> + +#include "settings.h" +#include "prefs.h" + +class KLed; +class QGridLayout; +class DatePicker; +class QGridLayout; +class KBinaryClock; + +class SettingsImp : public Settings { + Q_OBJECT +public: + SettingsImp(QWidget* parent=0, + const char* name=0, + WFlags fl=0); +public slots: + void updatePreview(); + +}; + +class KConfigDialogImp : public KConfigDialog { +public: + KConfigDialogImp(QWidget *parent, const char *name, + KConfigSkeleton *prefs, + KDialogBase::DialogType dialogType = KDialogBase::IconList, + KDialogBase::ButtonCode defaultButton = Ok, + bool modal=false); + SettingsImp *settings; +}; + +class ClockAppletToolTip : public QToolTip +{ + public: + ClockAppletToolTip( KBinaryClock* clock ); + + protected: + virtual void maybeTip( const QPoint & ); + + private: + KBinaryClock *m_clock; +}; + +class KBinaryClock : public KPanelApplet { + Q_OBJECT +public: + KBinaryClock(const QString& configFile, Type t = Normal, int actions = 0, QWidget *parent = 0, const char *name = 0); + ~KBinaryClock(); + + virtual int widthForHeight (int height) const; + virtual int heightForWidth (int width) const; + +protected: + virtual void resizeEvent(QResizeEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + +protected slots: + void preferences(); + void updateClock(); + void loadSettings(); + void slotCopyMenuActivated(int); + void slotCalendarDeleted(); + void slotEnableCalendar(); + +private: + void openContextMenu(); + void toggleCalendar(); + KLed *ledMatrix[6][4]; + int ledWidth; + DatePicker *_calendar; + bool _disableCalendar; + Prefs *prefs; + ClockAppletToolTip m_tooltip; +}; + +#endif // KBINARYCLOCK_H + diff --git a/kicker-applets/kbinaryclock/kbinaryclock.kcfg b/kicker-applets/kbinaryclock/kbinaryclock.kcfg new file mode 100644 index 0000000..b5a5fb3 --- /dev/null +++ b/kicker-applets/kbinaryclock/kbinaryclock.kcfg @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <include>kapplication.h</include> + <kcfgfile arg="true"/> + <group name="General"> + <entry name="Shape" type="Enum"> + <label>Shape of the LEDs</label> + <choices> + <choice name="Rectangular"/> + <choice name="Circular"/> + </choices> + <default>Circular</default> + </entry> + <entry name="Look" type="Enum"> + <label>Look</label> + <choices> + <choice name="Flat"/> + <choice name="Raised"/> + <choice name="Sunken"/> + </choices> + <default>Raised</default> + </entry> + <entry name="Color" type="Color"> + <label>Color of the LEDs</label> + <default>55,49,238</default> + </entry> + <entry name="DarkFactor" type="Int"> + <label>Darkness of disabled LEDs</label> + <default>300</default> + <min>0</min> + <max>1000</max> + </entry> + <entry name="Background" type="Color"> + <label>Background color</label> + <default code="true">KApplication::palette().active().background()</default> + </entry> + <entry name="Show_Seconds" type="Bool"> + <label>Whether to show seconds</label> + <default>true</default> + </entry> + <entry name="Hide_Off_Leds" type="Bool"> + <label>Whether to show LEDs that are off</label> + <default>false</default> + </entry> + </group> +</kcfg> diff --git a/kicker-applets/kbinaryclock/prefs.kcfgc b/kicker-applets/kbinaryclock/prefs.kcfgc new file mode 100644 index 0000000..7e91072 --- /dev/null +++ b/kicker-applets/kbinaryclock/prefs.kcfgc @@ -0,0 +1,7 @@ +# Code generation options for kconfig_compiler +File=kbinaryclock.kcfg +#IncludeFiles=defines.h +ClassName=Prefs +Singleton=false +#CustomAdditions=true +#Mutators=Zoom diff --git a/kicker-applets/kbinaryclock/settings.ui b/kicker-applets/kbinaryclock/settings.ui new file mode 100644 index 0000000..43462af --- /dev/null +++ b/kicker-applets/kbinaryclock/settings.ui @@ -0,0 +1,483 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>Settings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Settings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>452</width> + <height>247</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>groupBox6</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>GroupBoxPanel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="title"> + <string>Disabled LED</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Light</string> + </property> + </widget> + <widget class="QSlider" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_DarkFactor</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="maxValue"> + <number>1000</number> + </property> + <property name="lineStep"> + <number>5</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="value"> + <number>300</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>NoMarks</enum> + </property> + <property name="tickInterval"> + <number>50</number> + </property> + </widget> + <spacer row="1" column="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>Dark</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Color</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Background:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>LED:</string> + </property> + </widget> + <widget class="KColorButton" row="0" column="1"> + <property name="name"> + <cstring>kcfg_Color</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="1" column="1"> + <property name="name"> + <cstring>kcfg_Background</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer row="0" column="2" rowspan="2" colspan="1"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QButtonGroup" row="2" column="2"> + <property name="name"> + <cstring>kcfg_Shape</cstring> + </property> + <property name="title"> + <string>LED Shape</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>Shape_Rectangular</cstring> + </property> + <property name="text"> + <string>&Rectangular</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>Shape_Circular</cstring> + </property> + <property name="text"> + <string>&Circular</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </vbox> + </widget> + <widget class="QButtonGroup" row="1" column="2"> + <property name="name"> + <cstring>kcfg_Look</cstring> + </property> + <property name="title"> + <string>LED Look</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>Look_Flat</cstring> + </property> + <property name="text"> + <string>&Flat</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>Look_Raised</cstring> + </property> + <property name="text"> + <string>R&aised</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>Look_Sunken</cstring> + </property> + <property name="text"> + <string>&Sunken</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="0" column="4" rowspan="3" colspan="1"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>preview</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Preview</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QFrame"> + <property name="name"> + <cstring>frame1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="lineWidth"> + <number>1</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>2</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="KLed" row="0" column="0"> + <property name="name"> + <cstring>kLed1</cstring> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="state"> + <enum>Off</enum> + </property> + </widget> + <widget class="KLed" row="0" column="1"> + <property name="name"> + <cstring>kLed2</cstring> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="KLed" row="1" column="1"> + <property name="name"> + <cstring>kLed4</cstring> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="KLed" row="1" column="0"> + <property name="name"> + <cstring>kLed3</cstring> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="state"> + <enum>Off</enum> + </property> + </widget> + <widget class="KLed" row="2" column="1"> + <property name="name"> + <cstring>kLed6</cstring> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="state"> + <enum>Off</enum> + </property> + </widget> + <widget class="KLed" row="2" column="0"> + <property name="name"> + <cstring>kLed5</cstring> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>84</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>kcfg_Show_Seconds</cstring> + </property> + <property name="text"> + <string>Show seconds</string> + </property> + </widget> + <widget class="QCheckBox" row="0" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kcfg_Hide_Off_Leds</cstring> + </property> + <property name="text"> + <string>Hide unlit LEDs</string> + </property> + </widget> + <widget class="Line" row="0" column="3" rowspan="3" colspan="1"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>VLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcolorbutton.h</includehint> + <includehint>kled.h</includehint> +</includehints> +</UI> diff --git a/kicker-applets/kolourpicker/Makefile.am b/kicker-applets/kolourpicker/Makefile.am new file mode 100644 index 0000000..8c86635 --- /dev/null +++ b/kicker-applets/kolourpicker/Makefile.am @@ -0,0 +1,23 @@ + +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = kolourpicker_panelapplet.la + +kolourpicker_panelapplet_la_SOURCES = kolourpicker.cpp simplebutton.cpp + +noinst_HEADERS = kolourpicker.h + +kolourpicker_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +kolourpicker_panelapplet_la_LIBADD = $(LIB_KDEUI) + +METASOURCES = AUTO + +lnkdir = $(kde_datadir)/kicker/applets + +lnk_DATA = kolourpicker.desktop + +EXTRA_DIST = $(lnk_DATA) + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/kolourpicker.pot + diff --git a/kicker-applets/kolourpicker/TODO b/kicker-applets/kolourpicker/TODO new file mode 100644 index 0000000..44d9566 --- /dev/null +++ b/kicker-applets/kolourpicker/TODO @@ -0,0 +1 @@ +Add a menu item to edit the colour via KColorDialog (wish by Neil Stevens <[email protected]>) diff --git a/kicker-applets/kolourpicker/kolourpicker.cpp b/kicker-applets/kolourpicker/kolourpicker.cpp new file mode 100644 index 0000000..98f5302 --- /dev/null +++ b/kicker-applets/kolourpicker/kolourpicker.cpp @@ -0,0 +1,382 @@ +/* This file is part of KolourPicker + Copyright (c) 2001 Malte Starostik <[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. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +$Id$ +*/ + +#include <qfile.h> +#include <qtextstream.h> +#include <qlayout.h> +#include <qimage.h> +#include <qclipboard.h> +#include <qregexp.h> +#include <qbitmap.h> +#include <qpainter.h> +#include <qtooltip.h> +#include <qcursor.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <kconfig.h> +#include <kaboutdata.h> +#include <kaboutapplication.h> +#include <kmessagebox.h> +#include <kpopupmenu.h> + +#include "kolourpicker.h" +#include "kolourpicker.moc" + +#include <X11/Xlib.h> + +// Applet initialization function +extern "C" +{ + KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile) + { + KGlobal::locale()->insertCatalogue("kolourpicker"); + return new KolourPicker(configFile, KPanelApplet::Normal, + KPanelApplet::About, + parent, "kolourpicker"); + } +} + +KolourPicker::KolourPicker(const QString& configFile, Type type, + int actions, QWidget *parent, const char *name) + : KPanelApplet(configFile, type, actions, parent, name), + m_picking(0) +{ + KAboutData *about = new KAboutData("kolourpicker", + I18N_NOOP("Color Picker"), + "v0.1", + I18N_NOOP("An applet to pick color values from anywhere on the screen"), + KAboutData::License_GPL_V2, + "(c) 2001 Malte Starostik"); + about->addAuthor("Malte Starostik", I18N_NOOP("Original Author"), "[email protected]"); + m_instance = new KInstance(about); + + KConfig *conf = config(); + conf->setGroup("General"); + QStringList history = conf->readListEntry("History"); + for (QStringList::ConstIterator it = history.begin(); it != history.end(); ++it) + m_history.append(QColor(*it)); + + setBackgroundOrigin(AncestorOrigin); + + m_colourButton = new SimpleButton(this); + m_colourButton->setPixmap(SmallIcon("colorpicker")); + m_colourButton->setFixedSize(20, 20); + QToolTip::add(m_colourButton, i18n("Pick a color")); + connect(m_colourButton, SIGNAL(clicked()), SLOT(slotPick())); + + m_historyButton = new SimpleButton(this); + m_historyButton->setFixedSize(20, 20); + if (m_history.count()) + m_historyButton->setPixmap(colorPixmap(m_history.last())); + else + { + m_historyButton->setPixmap(colorPixmap(QColor())); + m_historyButton->setEnabled(false); + } + QToolTip::add(m_historyButton, i18n("History")); + connect(m_historyButton, SIGNAL(clicked()), SLOT(slotHistory())); +} + +KolourPicker::~KolourPicker() +{ + KGlobal::locale()->removeCatalogue("kolourpicker"); +} + + +int KolourPicker::heightForWidth(int width) const +{ + return (width > 40) ? 22 : 44; +} + +int KolourPicker::widthForHeight(int height) const +{ + return (height > 40) ? 22 : 44; +} + +void KolourPicker::about() +{ + KAboutApplication dlg(m_instance->aboutData()); + dlg.exec(); +} + +void KolourPicker::slotPick() +{ + m_picking = true; + grabMouse(crossCursor); + grabKeyboard(); +} + +void KolourPicker::slotHistory() +{ + KPopupMenu popup; + popup.insertTitle(SmallIcon("colorize"), i18n("History")); + QPtrList<QPopupMenu> subMenus; + subMenus.setAutoDelete(true); + for (QValueList<QColor>::ConstIterator it = m_history.fromLast(); + it != m_history.end(); + --it) + { + QPopupMenu *sub = copyPopup(*it, false); + subMenus.append(sub); + popup.insertItem(colorPixmap(*it), + QString("%1, %2, %3").arg((*it).red()).arg((*it).green()).arg((*it).blue()), + sub); + } + popup.insertSeparator(); + int clear = popup.insertItem(SmallIcon("history_clear"), i18n("&Clear History")); + int id = popup.exec(QCursor::pos()); + if (id == clear) + { + m_history.clear(); + m_historyButton->setEnabled(false); + arrangeButtons(); + KConfig *conf = config(); + conf->setGroup("General"); + conf->writeEntry("History", QStringList()); + conf->sync(); + } + else if (id != -1) + setClipboard(popup.findItem(id)->text()); +} + +void KolourPicker::mouseReleaseEvent(QMouseEvent *e) +{ + if (m_picking) + { + m_picking = false; + releaseMouse(); + releaseKeyboard(); + QWidget *desktop = QApplication::desktop(); + QPixmap pm = QPixmap::grabWindow(desktop->winId(), + e->globalPos().x(), e->globalPos().y(), 1, 1); + QImage img = pm.convertToImage(); + QColor color(img.pixel(0, 0)); + + // eventually remove a dupe + QValueListIterator<QColor> dupe = m_history.find(color); + if (dupe != m_history.end()) + m_history.remove(dupe); + + m_history.append(color); + while (m_history.count() >= 10) + m_history.remove(m_history.begin()); + m_historyButton->setEnabled(true); + arrangeButtons(); + QStringList history; + for (QValueList<QColor>::ConstIterator it = m_history.begin(); + it != m_history.end(); + ++it) + { + history.append((*it).name()); + } + KConfig *conf = config(); + conf->setGroup("General"); + conf->writeEntry("History", history); + conf->sync(); + m_historyButton->setPixmap(colorPixmap(color)); + QPopupMenu *popup = copyPopup(color, true); + int id = popup->exec(e->globalPos()); + if (id != -1) + setClipboard( popup->findItem(id)->text() ); + delete popup; + } + else + KPanelApplet::mouseReleaseEvent(e); +} + +// set both clipboard and selection +void KolourPicker::setClipboard(const QString& text) +{ + QClipboard *clip = QApplication::clipboard(); + bool oldMode = clip->selectionModeEnabled(); + clip->setSelectionMode(true); + clip->setText(text); + clip->setSelectionMode(false); + clip->setText(text); + clip->setSelectionMode( oldMode ); +} + +void KolourPicker::keyPressEvent(QKeyEvent *e) +{ + if (m_picking) + { + if (e->key() == Key_Escape) + { + m_picking = false; + releaseMouse(); + releaseKeyboard(); + } + e->accept(); + return; + } + KPanelApplet::keyPressEvent(e); +} + +void KolourPicker::resizeEvent(QResizeEvent *) +{ + arrangeButtons(); +} + +void KolourPicker::arrangeButtons() +{ + int h, w, p; + + if (orientation() == Horizontal) + { + h = height(); + if (h > 40) + { + // vertical layout + p = (h - 40)/3; + m_colourButton->setGeometry(2, p, 20, 20); + m_historyButton->setGeometry(2, 2*p+20, 20, 20); + } + else + { + // horizontal layout + p = (h - 20)/2; + m_colourButton->setGeometry(2, p, 20, 20); + m_historyButton->setGeometry(24, p, 20, 20); + } + } + else + { + w = width(); + if (w > 40) + { + // horizontal layout + p = (w - 40)/3; + m_colourButton->setGeometry(p, 2, 20, 20); + m_historyButton->setGeometry(2*p+20, 2, 20, 20); + } + else + { + // vertical layout + p = (w - 20)/2; + m_colourButton->setGeometry(p, 2, 20, 20); + m_historyButton->setGeometry(p, 24, 20, 20); + } + } + + updateGeometry(); +} + +QPopupMenu *KolourPicker::copyPopup(const QColor &c, bool title) const +{ + KPopupMenu *popup = new KPopupMenu; + if (title) + popup->insertTitle(colorPixmap(c), i18n("Copy Color Value")); + QString value; + // r, g, b + value.sprintf("%u, %u, %u", c.red(), c.green(), c.blue()); + popup->insertItem(SmallIcon("text"), value); + // HTML, lower case hex chars + value.sprintf("#%.2x%.2x%.2x", c.red(), c.green(), c.blue()); + popup->insertItem(SmallIcon("html"), value); + if (value.find(QRegExp("[a-f]")) >= 0) + { + // HTML, upper case hex chars + value.sprintf("#%.2X%.2X%.2X", c.red(), c.green(), c.blue()); + popup->insertItem(SmallIcon("html"), value); + } + // lower case hex chars + value.sprintf( "%.2x%.2x%.2x", c.red(), c.green(), c.blue() ); + popup->insertItem( SmallIcon( "html" ), value ); + if ( value.find( QRegExp( "[a-f]" ) ) >= 0 ) + { + // upper case hex chars + value.sprintf( "%.2X%.2X%.2X", c.red(), c.green(), c.blue() ); + popup->insertItem( SmallIcon( "html" ), value ); + } + // Color name + QStringList names = colorNames(c.red(), c.green(), c.blue()); + for (QStringList::ConstIterator it = names.begin(); it != names.end(); ++it) + popup->insertItem(SmallIcon("text"), *it); + return popup; +} + +#define AAFACTOR 4 + +QPixmap KolourPicker::colorPixmap(const QColor &c) const +{ + int x, y, dx, dy, d; + + QImage img(16 * AAFACTOR, 16 * AAFACTOR, 32); + img.setAlphaBuffer(true); + img.fill(0); + + for (x = 0; x < img.width(); x++) + for (y = 0; y < img.height(); y++) + { + dx = 1 + x - 15 * AAFACTOR / 2; + dy = 1 + y - 15 * AAFACTOR / 2; + d = dx * dx + dy * dy; + + if (d < (36 * AAFACTOR * AAFACTOR)) + img.setPixel(x, y, c.pixel()); + else if (d < (56.25 * AAFACTOR * AAFACTOR)) + img.setPixel(x, y, qRgba(128, 128, 128, 255)); + } + + QBitmap mask(16, 16); + mask.fill(Qt::color0); + QPainter p(&mask); + p.setPen(Qt::NoPen); + p.setBrush(Qt::color1); + p.drawEllipse(0, 0, 15, 15); + p.end(); + + QPixmap pm = QPixmap(img.smoothScale(16, 16)); + pm.setMask(mask); + + return pm; +} + +const QStringList &KolourPicker::colorNames(int r, int g, int b) const +{ + static QStringList NullList; + if (m_colorNames.isEmpty()) + { + QFile f("/usr/lib/X11/rgb.txt"); + if (!f.open(IO_ReadOnly)) + return NullList; + QTextStream str(&f); + QString red, green, blue; + while (!str.atEnd()) + { + str >> red; + if (red.simplifyWhiteSpace()[0].latin1() == '!') + { + str.readLine(); + continue; + } + str >> green >> blue; + const_cast<KolourPicker *>(this)->m_colorNames[(red.toInt() << 16) + (green.toInt() << 8) + blue.toInt()] + .append(str.readLine().simplifyWhiteSpace()); + } + } + return m_colorNames[(r << 16) + (g << 8) + b]; +} + +// vim: ts=4 sw=4 noet diff --git a/kicker-applets/kolourpicker/kolourpicker.desktop b/kicker-applets/kolourpicker/kolourpicker.desktop new file mode 100644 index 0000000..34f13d0 --- /dev/null +++ b/kicker-applets/kolourpicker/kolourpicker.desktop @@ -0,0 +1,145 @@ +[Desktop Entry] +Type=Plugin +Name=Color Picker +Name[af]=Kleur Kieser +Name[ar]=أداة اختيار الألوان +Name[az]=Rəng Alıcısı +Name[bg]=Избор на цвят +Name[br]=Dibaber al liv +Name[bs]=Izbornik boja +Name[ca]=Selector de colors +Name[cs]=Výběr barev +Name[cy]=Dewisydd Lliw +Name[da]=Farveplukker +Name[de]=Farbauswahl +Name[el]=Επιλογή χρωμάτων +Name[en_GB]=Colour Picker +Name[eo]=Kolorelektilo +Name[es]=Selector de color +Name[et]=Värvide valimine +Name[eu]=Kolore hautagailua +Name[fa]=برگزینندۀ رنگ +Name[fi]=Värivalitsin +Name[fo]=Litveljari +Name[fr]=Pipette +Name[fy]=Kleurekiezer +Name[gl]=Escolla de Cores +Name[he]=בוחר צבעים +Name[hi]=रंग चयनक +Name[hr]=Birač boja +Name[hu]=Színválasztó +Name[is]=Litaval +Name[it]=Scelta colore +Name[ja]=色の抽出 +Name[ka]=ფერთა ამღები +Name[kk]=Түсті шұқып алу +Name[km]=កម្មវិធីរើសពណ៌ +Name[ko]=색 고르기 +Name[lt]=Spalvų rinkėjas +Name[lv]=Krāsu Lasītājs +Name[mk]=Бирач на бои +Name[ms]=Pengutip Warna +Name[mt]=Agħżel kulur +Name[nb]=Fargevelger +Name[nds]=Klöörutwahl +Name[ne]=रङ पिकर +Name[nl]=Kleurenkiezer +Name[nn]=Fargeveljar +Name[pa]=ਰੰਗ ਚੋਣਕਾਰ +Name[pl]=Wybór koloru +Name[pt]=Escolha de Cores +Name[pt_BR]=Seletor de cores +Name[ro]=Selector de culori +Name[ru]=Выбор цвета +Name[sk]=Výber farieb +Name[sl]=Izbirnik barv +Name[sr]=Бирач боја +Name[sr@Latn]=Birač boja +Name[sv]=Färgväljare +Name[ta]=வண்ண எடுப்பான் +Name[tg]=Интихоби рангҳо +Name[th]=เครื่องมือเลือกสี +Name[tr]=Renk Seçici +Name[uk]=Селектор кольорів +Name[uz]=Rang tanlagich +Name[uz@cyrillic]=Ранг танлагич +Name[ven]=Tshidobamuvhala +Name[vi]=Bộ kén màu +Name[xh]=Umkhethi Wombala +Name[zh_CN]=颜色提取程序 +Name[zh_TW]=色彩選擇器 +Name[zu]=Umcoshi Wombala +Icon=colorpicker +Comment=Pick colors from anywhere and get their values +Comment[af]=Kies kleure van orals en kry hulle waardes +Comment[ar]=اختر الألوان من أي مكان و احصل على قيمتها الرقمية +Comment[az]=İstədiyiniz yerdən rəng alaraq qiymətlərini öyrənin +Comment[bg]=Избор на цвят от екрана и получаване на неговата стойност +Comment[bs]=Izbor boje sa bilo kojeg mjesta i ispis njenih vrijednosti +Comment[ca]=Selecciona colors des de qualsevol lloc i obté els seus valors +Comment[cs]=Výběr barev z libovolného místa a získání jejich hodnot +Comment[cy]=Dewis lliwiau oddiwrth unrhyw man a cael eu gwerthoedd +Comment[da]=Pluk farver fra et vilkårligt sted og få deres værdier +Comment[de]=Farben aufnehmen und ihre RGB-Werte ermitteln +Comment[el]=Επιλέξτε χρώματα από οπουδήποτε και πάρτε τις τιμές τους +Comment[en_GB]=Pick colours from anywhere and get their values +Comment[eo]=Elprenas koloron de ie sur la ekrano kaj montras ĝiajn valorojn +Comment[es]=Selecciona colores desde cualquier sitio y devuelve sus valores +Comment[et]=Värvide valimine ekraanilt ja nende väärtuste vaatamine +Comment[eu]=Hautatu koloreak edonondik eta euren balioak eskuratu +Comment[fa]=رنگها را از هر جایی برگزیده و مقادیر آنها را به دست میآورد. +Comment[fi]=Valitse värejä kaikkialta ja tutki värien arvoja +Comment[fo]=Vel litir frá skriviborði. +Comment[fr]=Capture une couleur n'importe où et obtient sa composition +Comment[fy]=Kies kleuren fan elk willekeurich plak en krij harren wearden +Comment[ga]=Roghnaigh dath ó áit ar bith agus faigh a luach +Comment[gl]=Extrai as cores de calquer sítio e obtén os seus valores +Comment[he]=בחירת צבעים מכל מקום שהוא וקבלת ערכיהם +Comment[hi]=कहीं से भी रंग चुने तथा उसका मान प्रदर्शित करता है +Comment[hr]=Odabir boja s bilo kojeg mjesta i iščitavanje njihovih vrijednosti +Comment[hu]=Színleolvasás a képernyő bármely képpontjáról +Comment[is]=Velja liti hvaðan sem er af skjánum og fá tölugildi þeirra +Comment[it]=Scegli un colore da un posto qualsiasi e scopri il suo valore +Comment[ja]=色を抽出してそれの値を読み込みます +Comment[ka]=ნებისმიერი ადგილიდან იღებს ფერს, მათი მნიშვნელობის მისაღებად +Comment[kk]=Кез келген жерден түсті шұқып, параметрлерін алу +Comment[km]=រើសពណ៌ពីកន្លែងណាមួយ និងយកតម្លៃរបស់ពួកវា +Comment[ko]=어디에 있는 색이든 고를 수 있는 도구 +Comment[lt]=Paima iš bet kur spalvas ir parodo jų reikšmes +Comment[lv]= Lasa krāsas no jebkurienes un iegūst to vērtības +Comment[mk]=Избира бои од каде било и ги зема нивните вредности +Comment[ms]=Memungut warna dari mana-mana dan dapatkan nilainya +Comment[mt]=Agħżel kulur minn fejn trid u ħu l-valur tiegħu +Comment[nb]=Plukk opp farger fra hvor som helst og se verdiene deres +Comment[nds]=Klören jichtenswo utsöken un ehr Weerten faststellen +Comment[ne]=सबै ठाउको रङ लिनुहोस् र तिनका मान प्राप्त गर्नुहोस् +Comment[nl]=Kies kleuren van elke willekeurige plek en verkrijg hun waarden +Comment[nn]=Plukk fargar frå kvar som helst og finn verdien deira +Comment[pa]=ਕਿਤੋਂ ਵੀ ਰੰਗ ਵੀ ਚੁੱਕੋ ਅਤੇ ਉਹਨਾਂ ਦੇ ਮੁੱਲ ਲਵੋ +Comment[pl]=Wybierz kolory z dowolnego miejsca i pobierz ich wartości +Comment[pt]=Extrai as cores de qualquer sítio e obtém os seus valores +Comment[pt_BR]=Selecione as cores de qualquer lugar e obtenha seus valores +Comment[ro]=Preia culori de oriunde şi afişează valorile lor +Comment[ru]=Подбирает цвет из любого места экрана и показывает его значение +Comment[sk]=Výber farieb z ktoréhokoľvek miesta a získanie ich hodnôt +Comment[sl]=Pobira barve od vsepovsod in dobiva njihove vrednosti +Comment[sr]=Узмите узорак боје одакле било и сазнајте њену вредност +Comment[sr@Latn]=Uzmite uzorak boje odakle bilo i saznajte njenu vrednost +Comment[sv]=Välj färger var som helst och få deras värden +Comment[ta]=எங்கிருந்தும் வண்ணங்களைத் எடுத்து அதன் மதிப்புகளை பெறு +Comment[tg]=Интихоб кардани ранг аз ҳар ҷойи экран ва нишон додани қимати ӯ +Comment[th]=เลือกสีจากที่ใด ๆ และรับค่าของมัน +Comment[tr]=Herhangi bir yerden renk seçer ve değerlerini alır +Comment[uk]=Вибирає кольори будь-звідки та отримує їхні значення +Comment[uz]=Ekranning istalgan joyidan rang va uning qiymatini olish +Comment[uz@cyrillic]=Экраннинг исталган жойидан ранг ва унинг қийматини олиш +Comment[ven]=Zwi doba mivhala hothe na hothe zwa wana kuitele kwazwo +Comment[vi]=Kén màu từ bất cứ nơi nào và lấy giá trị của nó +Comment[xh]=Khetha imibala esuka naphi na ze ufumane amaxabiso awo +Comment[zh_CN]=从任何地方获取颜色值 +Comment[zh_TW]=從點選的地方取得顏色值 +Comment[zu]=Cosha imibala kunoma ikephi kanye namabizo azo ufumane amaxabiso ayo +X-KDE-Library=kolourpicker_panelapplet +X-KDE-UniqueApplet=true +DocPath=kicker-applets/kolourpicker.html +X-KDE-ParentApp=applets diff --git a/kicker-applets/kolourpicker/kolourpicker.h b/kicker-applets/kolourpicker/kolourpicker.h new file mode 100644 index 0000000..0b576e9 --- /dev/null +++ b/kicker-applets/kolourpicker/kolourpicker.h @@ -0,0 +1,70 @@ +/* This file is part of Kolourpicker + Copyright (c) 2001 Malte Starostik <[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. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef _KOLOURPICKER_H_ +#define _KOLOURPICKER_H_ + +#include <qmap.h> +#include <qvaluelist.h> + +#include <kpanelapplet.h> + +#include "simplebutton.h" + +class KInstance; +class QPopupMenu; + +class KolourPicker : public KPanelApplet +{ + Q_OBJECT +public: + KolourPicker(const QString& configFile, Type t = Normal, int actions = 0, + QWidget *parent = 0, const char *name = 0); + ~KolourPicker(); + virtual int heightForWidth(int) const; + virtual int widthForHeight(int) const; + virtual void about(); + +protected: + virtual void mouseReleaseEvent(QMouseEvent *); + virtual void keyPressEvent(QKeyEvent *); + virtual void resizeEvent(QResizeEvent*); + +private slots: + void slotPick(); + void slotHistory(); + +private: + QPopupMenu *copyPopup(const QColor &, bool title) const; + QPixmap colorPixmap(const QColor &) const; + const QStringList &colorNames(int r, int g, int b) const; + void arrangeButtons(); + void setClipboard(const QString& text); + + KInstance *m_instance; + bool m_picking; + SimpleButton *m_historyButton, *m_colourButton; + QValueList<QColor> m_history; + QMap<int, QStringList> m_colorNames; +}; + +#endif + +// vim: ts=4 sw=4 noet diff --git a/kicker-applets/kolourpicker/simplebutton.cpp b/kicker-applets/kolourpicker/simplebutton.cpp new file mode 100644 index 0000000..9daa926 --- /dev/null +++ b/kicker-applets/kolourpicker/simplebutton.cpp @@ -0,0 +1,256 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan <[email protected]> + Copyright (C) 2004-2005 Aaron J. Seigo <[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. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "simplebutton.h" + +#include <qpainter.h> +#include <qstyle.h> + +#include <kapplication.h> +#include <kcursor.h> +#include <kdialog.h> +#include <kglobalsettings.h> +#include <kiconeffect.h> +#include <kicontheme.h> +#include <kipc.h> +#include <kstandarddirs.h> + +SimpleButton::SimpleButton(QWidget *parent, const char *name) + : QButton(parent, name), + m_highlight(false), + m_orientation(Qt::Horizontal) +{ + setBackgroundOrigin( AncestorOrigin ); + + connect( kapp, SIGNAL( settingsChanged( int ) ), + SLOT( slotSettingsChanged( int ) ) ); + connect( kapp, SIGNAL( iconChanged( int ) ), + SLOT( slotIconChanged( int ) ) ); + + kapp->addKipcEventMask( KIPC::SettingsChanged ); + kapp->addKipcEventMask( KIPC::IconChanged ); + + slotSettingsChanged( KApplication::SETTINGS_MOUSE ); +} + +void SimpleButton::setPixmap(const QPixmap &pix) +{ + QButton::setPixmap(pix); + generateIcons(); + update(); +} + +void SimpleButton::setOrientation(Qt::Orientation orientation) +{ + m_orientation = orientation; + update(); +} + +QSize SimpleButton::sizeHint() const +{ + const QPixmap* pm = pixmap(); + + if (!pm) + return QButton::sizeHint(); + else + return QSize(pm->width() + KDialog::spacingHint(), pm->height() + KDialog::spacingHint()); +} + +QSize SimpleButton::minimumSizeHint() const +{ + const QPixmap* pm = pixmap(); + + if (!pm) + return QButton::minimumSizeHint(); + else + return QSize(pm->width(), pm->height()); +} + +void SimpleButton::drawButton( QPainter *p ) +{ + drawButtonLabel(p); +} + +void SimpleButton::drawButtonLabel( QPainter *p ) +{ + if (!pixmap()) + { + return; + } + + QPixmap pix = isEnabled() ? (m_highlight? m_activeIcon : m_normalIcon) : m_disabledIcon; + + if (isOn() || isDown()) + { + pix = pix.convertToImage().smoothScale(pix.width() - 2, + pix.height() - 2); + } + + int h = height(); + int w = width(); + int ph = pix.height(); + int pw = pix.width(); + int margin = KDialog::spacingHint(); + QPoint origin(margin / 2, margin / 2); + + if (ph < (h - margin)) + { + origin.setY((h - ph) / 2); + } + + if (pw < (w - margin)) + { + origin.setX((w - pw) / 2); + } + + p->drawPixmap(origin, pix); +} + +void SimpleButton::generateIcons() +{ + if (!pixmap()) + { + return; + } + + QImage image = pixmap()->convertToImage(); + KIconEffect effect; + + m_normalIcon = effect.apply(image, KIcon::Panel, KIcon::DefaultState); + m_activeIcon = effect.apply(image, KIcon::Panel, KIcon::ActiveState); + m_disabledIcon = effect.apply(image, KIcon::Panel, KIcon::DisabledState); + + updateGeometry(); +} + +void SimpleButton::slotSettingsChanged(int category) +{ + if (category != KApplication::SETTINGS_MOUSE) + { + return; + } + + bool changeCursor = KGlobalSettings::changeCursorOverIcon(); + + if (changeCursor) + { + setCursor(KCursor::handCursor()); + } + else + { + unsetCursor(); + } +} + +void SimpleButton::slotIconChanged( int group ) +{ + if (group != KIcon::Panel) + { + return; + } + + generateIcons(); + update(); +} + +void SimpleButton::enterEvent( QEvent *e ) +{ + m_highlight = true; + + repaint( false ); + QButton::enterEvent( e ); +} + +void SimpleButton::leaveEvent( QEvent *e ) +{ + m_highlight = false; + + repaint( false ); + QButton::enterEvent( e ); +} + +void SimpleButton::resizeEvent( QResizeEvent * ) +{ + generateIcons(); +} + + +SimpleArrowButton::SimpleArrowButton(QWidget *parent, Qt::ArrowType arrow, const char *name) + : SimpleButton(parent, name) +{ + setBackgroundOrigin(AncestorOrigin); + _arrow = arrow; + _inside = false; +} + +QSize SimpleArrowButton::sizeHint() const +{ + return QSize( 12, 12 ); +} + +void SimpleArrowButton::setArrowType(Qt::ArrowType a) +{ + if (_arrow != a) + { + _arrow = a; + update(); + } +} + +Qt::ArrowType SimpleArrowButton::arrowType() const +{ + return _arrow; +} + +void SimpleArrowButton::drawButton( QPainter *p ) +{ + QRect r(1, 1, width() - 2, height() - 2); + + QStyle::PrimitiveElement pe = QStyle::PE_ArrowLeft; + switch (_arrow) + { + case Qt::LeftArrow: pe = QStyle::PE_ArrowLeft; break; + case Qt::RightArrow: pe = QStyle::PE_ArrowRight; break; + case Qt::UpArrow: pe = QStyle::PE_ArrowUp; break; + case Qt::DownArrow: pe = QStyle::PE_ArrowDown; break; + } + + int flags = QStyle::Style_Default | QStyle::Style_Enabled; + if (isDown() || isOn()) flags |= QStyle::Style_Down; + style().drawPrimitive(pe, p, r, colorGroup(), flags); +} + +void SimpleArrowButton::enterEvent( QEvent *e ) +{ + _inside = true; + SimpleButton::enterEvent( e ); + update(); +} + +void SimpleArrowButton::leaveEvent( QEvent *e ) +{ + _inside = false; + SimpleButton::enterEvent( e ); + update(); +} + +#include "simplebutton.moc" + +// vim:ts=4:sw=4:et diff --git a/kicker-applets/kolourpicker/simplebutton.h b/kicker-applets/kolourpicker/simplebutton.h new file mode 100644 index 0000000..5423dff --- /dev/null +++ b/kicker-applets/kolourpicker/simplebutton.h @@ -0,0 +1,89 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan <[email protected]> + Copyright (C) 2004-2005 Aaron J. Seigo <[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. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SIMPLEBUTTON_H +#define SIMPLEBUTTON_H + +#include <qbutton.h> +#include <qpixmap.h> + +#include <kdemacros.h> + +class KDE_EXPORT SimpleButton : public QButton +{ + Q_OBJECT + + public: + SimpleButton(QWidget *parent, const char *name = 0); + void setPixmap(const QPixmap &pix); + void setOrientation(Qt::Orientation orientaton); + QSize sizeHint() const; + QSize minimumSizeHint() const; + + protected: + void drawButton( QPainter *p ); + void drawButtonLabel( QPainter *p ); + void generateIcons(); + + void enterEvent( QEvent *e ); + void leaveEvent( QEvent *e ); + void resizeEvent( QResizeEvent *e ); + + protected slots: + virtual void slotSettingsChanged( int category ); + virtual void slotIconChanged( int group ); + + private: + bool m_highlight; + QPixmap m_normalIcon; + QPixmap m_activeIcon; + QPixmap m_disabledIcon; + Qt::Orientation m_orientation; + class SimpleButtonPrivate; + SimpleButtonPrivate* d; +}; + +class KDE_EXPORT SimpleArrowButton: public SimpleButton +{ + Q_OBJECT + + public: + SimpleArrowButton(QWidget *parent = 0, Qt::ArrowType arrow = Qt::UpArrow, const char *name = 0); + virtual ~SimpleArrowButton() {}; + QSize sizeHint() const; + + protected: + virtual void enterEvent( QEvent *e ); + virtual void leaveEvent( QEvent *e ); + virtual void drawButton(QPainter *p); + Qt::ArrowType arrowType() const; + + public slots: + void setArrowType(Qt::ArrowType a); + + private: + Qt::ArrowType _arrow; + bool _inside; +}; + + +#endif // HIDEBUTTON_H + +// vim:ts=4:sw=4:et diff --git a/kicker-applets/ktimemon/Makefile.am b/kicker-applets/ktimemon/Makefile.am new file mode 100644 index 0000000..fee10c7 --- /dev/null +++ b/kicker-applets/ktimemon/Makefile.am @@ -0,0 +1,22 @@ +kde_module_LTLIBRARIES = ktimemon_panelapplet.la + +ktimemon_panelapplet_la_SOURCES = confdlg.cc sample.cc timemon.cc +METASOURCES = AUTO + +noinst_HEADERS = confdlg.h sample.h timemon.h + +INCLUDES= $(all_includes) + +ktimemon_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +ktimemon_panelapplet_la_LIBADD = $(LIB_KDEUI) $(LIBKSTAT) $(LIB_KIO) + +KDE_ICON = ktimemon + +lnk_DATA = ktimemon.desktop +lnkdir = $(kde_datadir)/kicker/applets + +EXTRA_DIST = $(lnk_DATA) + +messages: + $(XGETTEXT) *.cc -o $(podir)/ktimemon.pot + diff --git a/kicker-applets/ktimemon/README b/kicker-applets/ktimemon/README new file mode 100644 index 0000000..ec8fb3a --- /dev/null +++ b/kicker-applets/ktimemon/README @@ -0,0 +1,65 @@ + +This is the CVS version of KTimemon. Check out the original authors +homepage at + +http://www.fortunecity.com/victorian/university/394/sw/ktimemon.html + +for more information. This version is based (despite the original readme +below says) on KTimemon 0.3b and modified to compile under KDE 2.0 & +Qt 2.0 by Dirk A. Mueller <[email protected]>. + +2006-04-08: version 0.3c, modified to add iowait display +by Michael Blakeley <[email protected]> + +Credits go to the original author(s) Helmut & Martin Maierhofer for +writing such a useful tool and allowing me to include it into CVS :-). + +Please don't bother them with bugs, problems, etc. you may experience +with this version. It's likely that they're my fault, so report them +to [email protected]. Thanks! + +original README attached below.... + +========================================================================== + + +KTimemon 0.3a +------------- + +KTimemon is a small but nifty system monitor, which can display information +about CPU and memory/swap usage as well as ongoing paging/swapping and +context switch activity. It is well integrated in KDE and can be +configured graphically. For more information, see the associated +documentation (before installation it can be found in ktimemon/doc/*.html) + +KTimemon works on Linux using the /proc filesystem, on Solaris using the +kstat interface, and on Digital Unix (formerly known as DEC/OSF1) using +the table() system call interface. If you can help me to port it to other +platforms, please drop me a note! + +While I was able to test the system interface on Solaris and DEC/OSF1 in +isolation, I could not test the whole application for lack of KDE on the +machines I have access to. Hence I have no idea whether this thing +actually compiles, let alone works on these platforms. The machines I tested +were running DEC/OSF V4.0 and Solaris 2.5.1 respectively. If you get it to +work (or not) on such a system, please let me know! + + +Noteworthy changes from version 0.2: +- Port to DEC/OSF1 and Solaris +- Configurable mouse bindings +- Slight rearrangement of memory information +- Bars can be displayed vertically +- Improved (actually working) configuration interface +- Fixed a few bugs and doubtlessly introduced some more + +Version 0.3a has only minor improvements over 0.3: +- New tooltips with numeric information about system load +- Translation fixes + +Note that some of the configuration entry names have changed from version +0.2 to 0.3, so you may want to delete your current configuration in +$(HOME)/.kde/share/config/ktimemonrc and start with a fresh installation +if you are upgrading from 0.2 + +Martin <[email protected]> diff --git a/kicker-applets/ktimemon/TODO b/kicker-applets/ktimemon/TODO new file mode 100644 index 0000000..eec7578 --- /dev/null +++ b/kicker-applets/ktimemon/TODO @@ -0,0 +1,13 @@ +* port it to more platforms (what about remote monitoring?) + +* include some sort of support for SMP status (smaller bars?); also for + multiple swap partitions/files? + +* make it more flexible (plug-in concept?) + +* improve documentation (add images?), better internationalisation + +* add help button in configuration dialog + +* have some way of attaching watchdogs (e.g. if %idle > 90 for more than + 10 seconds, do this or that (or pop up a dialog)) diff --git a/kicker-applets/ktimemon/confdlg.cc b/kicker-applets/ktimemon/confdlg.cc new file mode 100644 index 0000000..ff5ab9d --- /dev/null +++ b/kicker-applets/ktimemon/confdlg.cc @@ -0,0 +1,295 @@ +/**********************************************************************/ +/* TimeMon (c) 1994 Helmut Maierhofer */ +/* KDE-ified M. Maierhofer 1998 */ +/**********************************************************************/ + +/* + * confdlg.h + * + * Definitions for the timemon configuration dialog. + */ + +#include <config.h> +#include <stdio.h> +#include <qgroupbox.h> +#include <qlineedit.h> +#include <qslider.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qvgroupbox.h> +#include <qcheckbox.h> +#include <qcombobox.h> + +#include <kcolorbutton.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kurlrequester.h> + +#include "confdlg.h" +#include "timemon.h" + +// -- KConfDialog definition --------------------------------------------- + +KConfDialog::KConfDialog(KTimeMon *t) + : KDialogBase( Tabbed, i18n("Configuration" ), + Ok|Cancel|Apply, Ok, t, 0, false ), + timemon(t) +{ + QFrame *page; + QBoxLayout *bl; + QGridLayout *gl; + QLabel *l; + QGroupBox *b; + KColorButton *cb; + unsigned i, j; + + setIcon( SmallIcon( "ktimemon" ) ); + + // first tab: general + page = addPage( i18n( "&General" ) ); + + bl = new QVBoxLayout(page, 0, spacingHint()); + + b = new QVGroupBox(i18n("Sample &Rate"), page); + bl->addWidget(b); + + intervalEdit = new KIntNumInput(250, b); + intervalEdit->setRange(20, 1000, 10); + intervalEdit->setSuffix(i18n(" msec")); + + // scaling group box + b = new QVGroupBox(i18n("Scaling"), page); + bl->addWidget(b); + + bl->addStretch(); + + autoScaleBox = new QCheckBox(i18n("&Automatic"), b); + connect(autoScaleBox, SIGNAL(toggled(bool)), this, SLOT(toggle(bool))); + + pageScaleEdit = new KIntNumInput(intervalEdit, 1000, b); + pageScaleEdit->setRange(10, 10000, 10); + pageScaleEdit->setLabel(i18n("&Paging:"), AlignVCenter | AlignLeft); + + swapScaleEdit = new KIntNumInput(pageScaleEdit, 1000, b); + swapScaleEdit->setRange(1, 10000, 5); + swapScaleEdit->setLabel(i18n("&Swapping:"), AlignVCenter | AlignLeft); + + ctxScaleEdit = new KIntNumInput(swapScaleEdit, 10000, b); + ctxScaleEdit->setLabel(i18n("&Context switch:"), AlignVCenter | AlignLeft); + ctxScaleEdit->setRange(1, 10000, 30); + + bl->addStretch(1); + + // second tab: colours + page = addPage( i18n( "C&olors" ) ); + + gl = new QGridLayout(page, 12, 10, 0, spacingHint()); + + gl->setColStretch(3, 1); gl->setColStretch(6, 1); // eat up horizontal space + gl->setRowStretch(11, 1); // eat up vertical space + + gl->addRowSpacing(0, 20); gl->addRowSpacing(4, 20); gl->addRowSpacing(8, 20); + gl->addRowSpacing(2, 8); gl->addRowSpacing(6, 8); gl->addRowSpacing(10, 8); + + gl->addColSpacing(0, 10); gl->addColSpacing(9, 25); + + QString cpuColourLabels[4]; + cpuColourLabels[0] = i18n("Kernel:"); + cpuColourLabels[1] = i18n("User:"); + cpuColourLabels[2] = i18n("Nice:"); + cpuColourLabels[3] = i18n("IOWait:"); + + QString memColourLabels[4]; + memColourLabels[0] = i18n("Kernel:"); + memColourLabels[1] = i18n("Used:"); + memColourLabels[2] = i18n("Buffers:"); + memColourLabels[3] = i18n("Cached:"); + + KColorButton **cpuColourButtons[4] = { &kernelCB, &userCB, &niceCB, &iowaitCB }; + b = new QGroupBox(i18n("CPU"), page); + gl->addMultiCellWidget(b, 0, 2, 0, 13); + + for (j = 0; j < 4; j++) { + l = new QLabel(cpuColourLabels[j], page); + gl->addWidget(l, 1, 3*j+1, AlignVCenter | AlignRight); + + cb = *cpuColourButtons[j] = new KColorButton(white, page); + gl->addWidget(cb, 1, 3*j+2, AlignCenter); + + connect(cb, SIGNAL(changed(const QColor &)), + this, SLOT(updateSampleWidget(const QColor &))); + } + + KColorButton **memColourButtons[4] = { &mkernelCB, &usedCB, &buffersCB, &cachedCB }; + b = new QGroupBox(i18n("Memory"), page); + gl->addMultiCellWidget(b, 4, 6, 0, 13); + + for (j = 0; j < 4; j++) { + l = new QLabel(memColourLabels[j], page); + gl->addWidget(l, 5, 3*j+1, AlignVCenter | AlignRight); + + cb = *memColourButtons[j] = new KColorButton(white, page); + gl->addWidget(cb, 5, 3*j+2, AlignCenter); + + connect(cb, SIGNAL(changed(const QColor &)), + this, SLOT(updateSampleWidget(const QColor &))); + } + + b = new QGroupBox(i18n("Swap"), page); + gl->addMultiCellWidget(b, 8, 10, 0, 6); + + l = new QLabel(i18n("Swap:"), page); + gl->addWidget(l, 9, 1, AlignVCenter | AlignRight); + + cb = swapCB = new KColorButton(red, page); + gl->addWidget(cb, 9, 2); + + connect(cb, SIGNAL(changed(const QColor &)), + this, SLOT(updateSampleWidget(const QColor &))); + + l = new QLabel(i18n("Backgd:"), page); + gl->addWidget(l, 9, 4, AlignVCenter | AlignRight); + + cb = bgCB = new KColorButton(blue, page); + gl->addWidget(cb, 9, 5); + + connect(cb, SIGNAL(changed(const QColor &)), + this, SLOT(updateSampleWidget(const QColor &))); + + //b = new QGroupBox(i18n("Sample"), page); + //gl->addMultiCellWidget(b, 8, 10, 7, 9); + + // third tab: interaction + page = addPage( i18n( "&Interaction" ) ); + + bl = new QVBoxLayout(page, 0, spacingHint()); + + b = new QGroupBox(i18n("Mouse Events"), page); + b->setColumnLayout( 0, Qt::Vertical ); + bl->addWidget(b); + bl->addStretch(); + + QVBoxLayout *vbox = new QVBoxLayout( b->layout() ); + + gl = new QGridLayout(b, MAX_MOUSE_ACTIONS + 1, 3, 0, 6 ); + + vbox->addLayout( gl ); + + for (i = 1; i < MAX_MOUSE_ACTIONS + 1; i++) + gl->setRowStretch(i, 1); + gl->setColStretch(2, 1); + + QString buttonText[MAX_MOUSE_ACTIONS] = { i18n("Left button:"), + i18n("Middle button:"), + i18n("Right button:") }; + + for (i = 0; i < (int) MAX_MOUSE_ACTIONS; i++) { + + l = new QLabel(buttonText[i], b); + gl->addWidget(l, i+1, 0); + + mouseC[i] = new KComboBox(false, b); + mouseC[i]->insertItem(i18n("Is Ignored"), KTimeMon::NOTHING); +// SWITCH doesn't DO anything. remove it from config dialog for now +// mouseC[i]->insertItem(i18n("Switches Mode"), KTimeMon::SWITCH); + mouseC[i]->insertItem(i18n("Pops Up Menu"), KTimeMon::MENU - 1); + mouseC[i]->insertItem(i18n("Starts"), KTimeMon::COMMAND - 1); + gl->addWidget(mouseC[i], i+1, 1); + + connect( mouseC[ i ], SIGNAL( activated( int ) ), this, + SLOT( mouseCommandEnable() ) ); + + mouseLE[i] = new KURLRequester(b); + mouseLE[i]->lineEdit()->setText(t->mouseActionCommand[i]); + gl->addWidget(mouseLE[i], i+1, 2); + } + + gl->activate(); + + resize(380, 300); + + connect(this, SIGNAL(applyClicked()), timemon, SLOT(apply())); + connect(this, SIGNAL(okClicked()), timemon, SLOT(apply())); +} + +// Adjust the colours of the sample widget in the configuration dialog. +void KConfDialog::updateSampleWidget(const QColor &) +{ +#if 0 + sample->kernelColour = kernelCB->color(); + sample->userColour = userCB->color(); + sample->niceColour = niceCB->color(); + sample->iowaitColour = iowaitCB->color(); + sample->kernelColour = kernelCB->color(); + sample->cachedColour = cachedCB->color(); + sample->usedColour = usedCB->color(); + sample->buffersColour = buffersCB->color(); + sample->swapColour = swapCB->color(); + sample->bgColour = bgCB->color(); + sample->update(); +#endif +} + +// ----------------------------------------------------------------------------- + +// enable/disable the scale widgets +void KConfDialog::toggle(bool state) +{ + swapScaleEdit->setEnabled(!state); + pageScaleEdit->setEnabled(!state); + ctxScaleEdit->setEnabled(!state); +} + +void KConfDialog::mouseCommandEnable() +{ + for ( int i = 0; i < MAX_MOUSE_ACTIONS; i++ ) { + unsigned action = mouseC[ i ]->currentItem(); + + // the - 1 is for compat with the no longer shown Switch option + mouseLE[ i ]->setEnabled( action == KTimeMon::COMMAND - 1); + } +} + +// update the dialog fields +void KConfDialog::update() +{ + intervalEdit->setValue(timemon->interval); + kernelCB->setColor(timemon->kernelColour); + userCB->setColor(timemon->userColour); + niceCB->setColor(timemon->niceColour); + iowaitCB->setColor(timemon->iowaitColour); + buffersCB->setColor(timemon->buffersColour); + mkernelCB->setColor(timemon->mkernelColour); + usedCB->setColor(timemon->usedColour); + cachedCB->setColor(timemon->cachedColour); + swapCB->setColor(timemon->swapColour); + bgCB->setColor(timemon->bgColour); + pageScaleEdit->setValue(timemon->pageScale); + swapScaleEdit->setValue(timemon->swapScale); + ctxScaleEdit->setValue(timemon->ctxScale); + autoScaleBox->setChecked(timemon->autoScale); + + for ( int i = 0; i < MAX_MOUSE_ACTIONS; i++ ) + { + int action = timemon->mouseAction[i]; + if (action > 0) + --action; // compat for the no longer shown Switch action + mouseC[i]->setCurrentItem(action); + } + mouseCommandEnable(); + + updateSampleWidget(white); // fake colour +} + +unsigned int KConfDialog::getMouseAction(int i) const +{ + int action = mouseC[i]->currentItem(); + + if (action > 0) + ++action; // compat for the no longer shown Switch action + + return action; +} + +#include "confdlg.moc" diff --git a/kicker-applets/ktimemon/confdlg.h b/kicker-applets/ktimemon/confdlg.h new file mode 100644 index 0000000..d458bf2 --- /dev/null +++ b/kicker-applets/ktimemon/confdlg.h @@ -0,0 +1,99 @@ +/* -*- C++ -*- */ + +/**********************************************************************/ +/* TimeMon (c) 1994 Helmut Maierhofer */ +/* KDE-ified M. Maierhofer 1998 */ +/* */ +/* Ported to KDE 2.0 and other stuff: */ +/* Copyright (c) Dirk A. Mueller <[email protected]> */ +/* */ +/**********************************************************************/ + +/* + * confdlg.h + * + * Definitions for the timemon configuration dialog. + */ + +#ifndef CONFDLG_H +#define CONFDLG_H + +#include <qcolor.h> +#include <qcheckbox.h> +#include <qtabdialog.h> + +#include <kcolorbutton.h> +#include <kcombobox.h> +#include <klineedit.h> +#include <knuminput.h> +#include <kdialogbase.h> +#include <kurlrequester.h> + +#include "timemon.h" + +// -- forward declaration ------------------------------------------------ + +class KTimeMon; +class QLineEdit; +class QSlider; +class KColorButton; + +// -- KConfDialog declaration -------------------------------------------- + +/* + * KConfDialog + */ + +class KConfDialog : public KDialogBase +{ + + Q_OBJECT + +public: + KConfDialog(KTimeMon *timemon); + ~KConfDialog() {} + + void update(); // get values from timemon + + unsigned getInterval() const { return intervalEdit->value(); } + QColor getKernelColour() const { return kernelCB->color(); } + QColor getUserColour() const { return userCB->color(); } + QColor getNiceColour() const { return niceCB->color(); } + QColor getIOWaitColour() const { return iowaitCB->color(); } + QColor getCachedColour() const { return cachedCB->color(); } + QColor getUsedColour() const { return usedCB->color(); } + QColor getBuffersColour() const { return buffersCB->color(); } + QColor getMKernelColour() const { return mkernelCB->color(); } + QColor getSwapColour() const { return swapCB->color(); } + QColor getBgColour() const { return bgCB->color(); } + + bool getAutoScale() const { return autoScaleBox->isChecked(); } + unsigned getPageScale() const { return pageScaleEdit->value(); } + unsigned getSwapScale() const { return swapScaleEdit->value(); } + unsigned getCtxScale() const { return ctxScaleEdit->value(); } + + unsigned getMouseAction(int i) const; + QString getMouseActionCommand(int i) const { return mouseLE[i]->lineEdit()->text(); } + +private slots: + void updateSampleWidget(const QColor &); // update colours in configuration + void toggle(bool state); // enable/disable scales + void mouseCommandEnable(); + +private: + + KTimeMon *timemon; + KIntNumInput *intervalEdit, *swapScaleEdit, *pageScaleEdit, *ctxScaleEdit; + QLineEdit *procFileEdit; + QCheckBox *autoScaleBox; + KColorButton *kernelCB, *userCB, *niceCB, *iowaitCB; + KColorButton *buffersCB, *usedCB, *cachedCB, *mkernelCB; + KColorButton *swapCB, *bgCB; + KURLRequester *mouseLE[MAX_MOUSE_ACTIONS]; + KComboBox *mouseC[MAX_MOUSE_ACTIONS]; + bool haveWarned; + + friend class KTimeMon; +}; + +#endif // CONFDLG_H diff --git a/kicker-applets/ktimemon/configure.in.in b/kicker-applets/ktimemon/configure.in.in new file mode 100644 index 0000000..7b9657e --- /dev/null +++ b/kicker-applets/ktimemon/configure.in.in @@ -0,0 +1,3 @@ +AC_CHECK_HEADERS(fcntl.h) +AC_CHECK_LIB(kstat, kstat_open, LIBKSTAT="-lkstat") +AC_SUBST(LIBKSTAT) diff --git a/kicker-applets/ktimemon/cr16-app-ktimemon.png b/kicker-applets/ktimemon/cr16-app-ktimemon.png Binary files differnew file mode 100644 index 0000000..d9295e6 --- /dev/null +++ b/kicker-applets/ktimemon/cr16-app-ktimemon.png diff --git a/kicker-applets/ktimemon/cr32-app-ktimemon.png b/kicker-applets/ktimemon/cr32-app-ktimemon.png Binary files differnew file mode 100644 index 0000000..71ff476 --- /dev/null +++ b/kicker-applets/ktimemon/cr32-app-ktimemon.png diff --git a/kicker-applets/ktimemon/ktimemon.desktop b/kicker-applets/ktimemon/ktimemon.desktop new file mode 100644 index 0000000..9f9013e --- /dev/null +++ b/kicker-applets/ktimemon/ktimemon.desktop @@ -0,0 +1,129 @@ +[Desktop Entry] +Type=Plugin +Icon=ktimemon +X-KDE-Library=ktimemon_panelapplet +X-KDE-UniqueApplet=true +Comment=A simple system monitor +Comment[ar]=مراقب النظام بسيط +Comment[bg]=Системен монитор за KDE +Comment[br]=Un diskweler reizhiad eeun +Comment[ca]=Un monitor del sistema senzill +Comment[cs]=Jednoduchý monitor systému +Comment[da]=En simpel systemovervåger til KDE +Comment[de]=Ein einfacher Systemmonitor +Comment[el]=Ένας απλός επόπτης συστήματος +Comment[eo]=Simpla sistemobservilo +Comment[es]=Un monitor de sistema sencillo +Comment[et]=Lihtne süsteemi monitor +Comment[eu]=Sistemaren monitore sinplea +Comment[fa]=نمایشگر سیستم ساده +Comment[fi]=Yksinkertainen järjestelmänvalvontaohjelma +Comment[fr]=Un moniteur système simple +Comment[fy]=In ienfâldige systeemmonitor +Comment[ga]=Monatóir simplí an chórais +Comment[gl]=Un monitor do sistema simples +Comment[he]=צג מערכת פשוט עבור KDE +Comment[hr]=Jednostavan nadzor sustava +Comment[hu]=Egyszerű rendszermonitor +Comment[is]=Einfalt kerfiseftirlit +Comment[it]=Un semplice monitor di sistema +Comment[ja]=シンプルなシステムモニタ +Comment[ka]=მარტივი სისტემური მონიტორი +Comment[kk]=Қарапайым жүйе қадағалауышы +Comment[km]=កម្មវិធីត្រួតពិនិត្យប្រព័ន្ធធម្មតាមួយ +Comment[lt]=Sistemos stebėjimo priemonė +Comment[mk]=Едноставен набљудувач на системот +Comment[nb]=En enkel systemovervåker +Comment[nds]=En eenfach Systeemkieker +Comment[ne]=एउट सामान्य प्रणाली मनिटर +Comment[nl]=Een eenvoudige systeemmonitor +Comment[nn]=Ein enkel systemovervakar +Comment[pa]=ਇੱਕ ਸਧਾਰਨ ਸਿਸਟਮ ਨਿਗਰਾਨ +Comment[pl]=Prosty monitor systemu +Comment[pt]=Um monitor do sistema simples +Comment[pt_BR]=Um monitor de sistema simples +Comment[ru]=Простой системный монитор +Comment[sk]=Jednoduchý monitor systému +Comment[sl]=Preprost nadzornik sistema +Comment[sr]=Једноставно надгледање система +Comment[sr@Latn]=Jednostavno nadgledanje sistema +Comment[sv]=En enkel systemövervakare +Comment[tr]=Basit bir sistem izleyici +Comment[uk]=Простий системний монітор +Comment[uz]=Tizimni nazorat qilish uchun oddiy vosita +Comment[uz@cyrillic]=Тизимни назорат қилиш учун оддий восита +Comment[vi]=Bộ theo dõi hệ thống đơn giản +Comment[zh_CN]=简单的系统监视器 +Comment[zh_TW]=簡單的系統監視器 +Name=System Monitor +Name[af]=Stelsel Monitor +Name[ar]=مراقب النظام +Name[az]=Sistem İzləyici +Name[bg]=Системен монитор +Name[br]=Diskwel saviad ar reizhiad +Name[bs]=Stanje sistema +Name[ca]=Monitor del sistema +Name[cs]=Monitor systému +Name[cy]=Gwarchodydd Cysawd +Name[da]=Systemovervåger +Name[de]=Systemmonitor +Name[el]=Εποπτεία συστήματος +Name[eo]=Sistemobservilo +Name[es]=Monitor de sistema +Name[et]=Süsteemi monitor +Name[eu]=Sistemaren monitorea +Name[fa]=نمایشگر سیستم +Name[fi]=Järjestelmänvalvonta +Name[fo]=Skipanaryvirvakari +Name[fr]=Surveillance du système +Name[fy]=Systeemmonitor +Name[ga]=Monatóir Córais +Name[gl]=Monitor do Sistema +Name[he]=צג מערכת +Name[hi]=तंत्र मॉनीटर +Name[hr]=Nadzor sustava +Name[hu]=Rendszermonitor +Name[is]=Kerfiseftirlit +Name[it]=Monitor di sistema +Name[ja]=システムモニタ +Name[ka]=სისტემური მონიტორი +Name[kk]=Жүйе қадағалауышы +Name[km]=កម្មវិធីត្រួតពិនិត្យប្រព័ន្ធ +Name[ko]=시스템 지켜보기 +Name[lt]=Sistemos stebėtojas +Name[lv]=Sistēmas Monitors +Name[mk]=Набљудувач на системот +Name[ms]=Monitor Sistem +Name[mt]=Monitur tas-sistema +Name[nb]=Systemovervåker +Name[nds]=Systeemkieker +Name[ne]=प्रणाली मनिटर +Name[nl]=Systeemmonitor +Name[nn]=Systemovervakar +Name[pa]=ਸਿਸਟਮ ਨਿਗਰਾਨ +Name[pl]=Monitor systemu +Name[pt]=Monitor do Sistema +Name[pt_BR]=Monitor do sistema +Name[ro]=Monitor de sistem +Name[ru]=Системный монитор +Name[sk]=Monitor systému +Name[sl]=Sistemski nadzornik +Name[sr]=Надгледање система +Name[sr@Latn]=Nadgledanje sistema +Name[sv]=Systemövervakare +Name[ta]=அமைப்பு திரை +Name[tg]=Монитори системавӣ +Name[th]=สอดส่องระบบ +Name[tr]=Sistem İzleyici +Name[uk]=Системний монітор +Name[uz]=Oddiy tizim nazoratchisi +Name[uz@cyrillic]=Оддий тизим назоратчиси +Name[ven]=Monitha wa Sistemu +Name[vi]=Bộ theo dõi hệ thống +Name[xh]=Indlela yokwenza yeCebo lokubonisa +Name[zh_CN]=系统监视器 +Name[zh_TW]=系統監視器 +Name[zu]=Umphendli Wendlela esetshenziswayo +DocPath=kicker-applets/ktimemon.html +X-KDE-StartupNotify=true +X-KDE-ParentApp=applets diff --git a/kicker-applets/ktimemon/lo16-app-ktimemon.png b/kicker-applets/ktimemon/lo16-app-ktimemon.png Binary files differnew file mode 100644 index 0000000..d9295e6 --- /dev/null +++ b/kicker-applets/ktimemon/lo16-app-ktimemon.png diff --git a/kicker-applets/ktimemon/lo32-app-ktimemon.png b/kicker-applets/ktimemon/lo32-app-ktimemon.png Binary files differnew file mode 100644 index 0000000..71ff476 --- /dev/null +++ b/kicker-applets/ktimemon/lo32-app-ktimemon.png diff --git a/kicker-applets/ktimemon/sample.cc b/kicker-applets/ktimemon/sample.cc new file mode 100644 index 0000000..25f25a3 --- /dev/null +++ b/kicker-applets/ktimemon/sample.cc @@ -0,0 +1,508 @@ +/**********************************************************************/ +/* TimeMon (c) 1994 Helmut Maierhofer */ +/* KDE-ified M. Maierhofer 1998 */ +/**********************************************************************/ + +/* + * sample.cc + * + * Definitions for the system dependent sampling class. + */ + +#include <config.h> + +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include <fstream> +#include <stdio.h> + +#ifdef __osf__ +#include <sys/table.h> +#elif defined(USE_SOLARIS) +#include <kstat.h> +#include <sys/sysinfo.h> +#include <sys/stat.h> +#include <sys/swap.h> +#endif + +#include <qwidget.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "timemon.h" +#include "sample.h" + +// -- global definitions ------------------------------------------------- + +#if defined(__osf__) || defined(USE_SOLARIS) +extern "C" int getpagesize(); // argh, have to define prototype! +#endif + +#ifdef __linux__ +// -- global constants --------------------------------------------------- +#define STAT_NAME "/proc/stat" +#define MEMINFO_NAME "/proc/meminfo" +#endif + +// -- KSample::Sample definition ----------------------------------------- + +// Fill sample with some default values (e.g. used in preview widget +// in configuration) +void KSample::Sample::fill(unsigned scale) +{ + user = scale * 40; user /= 100; + nice = scale * 25; user /= 100; + kernel = scale * 10; kernel /= 100; + iowait = scale * 5; iowait /= 100; + cpus = 1; + buffers = scale * 20; buffers /= 100; + used = scale * 30; used /= 100; + cached = scale * 20; cached /= 100; + sused = scale * 25; sused /= 100; +} + +// -- KSample definition ------------------------------------------------- + +// Initialise the member variables and try to open the standard files in +// the proc filesystem; for other platforms perform equivalent initialisation +KSample::KSample(KTimeMon *t, bool a, unsigned p, unsigned s, unsigned c) : + timemon(t), +#ifdef __linux__ + memFD(-1), statFD(-1), +#elif defined (USE_SOLARIS) + kc(0), warned(false), +#endif + pageScale(p), swapScale(s), cxScale(c), autoscale(a) +{ +#ifdef __linux__ + memstats[0].name = "SwapTotal:"; + memstats[0].stat = &sample.stotal; + memstats[1].name = "MemTotal:"; + memstats[1].stat = &sample.mtotal; + memstats[2].name = "MemFree:"; + memstats[2].stat = &sample.free; + memstats[3].name = "Buffers:"; + memstats[3].stat = &sample.buffers; + memstats[4].name = "Cached:"; + memstats[4].stat = &sample.cached; + memstats[5].name = "SwapFree:"; + memstats[5].stat = &sample.sfree; + memstats[6].name = 0; + memstats[6].stat = 0; + + if ((memFD = open(MEMINFO_NAME, O_RDONLY)) == -1) { + KMessageBox::error(timemon, + i18n("Unable to open the file '%1'. The diagnostics are:\n%2.\n" + "This file is required to determine current memory usage.\n" + "Maybe your proc filesystem is non-Linux standard?").arg(MEMINFO_NAME).arg(strerror(errno))); + exit(1); + } + + fcntl( memFD,F_SETFD, FD_CLOEXEC ); + + if ((statFD = open(STAT_NAME, O_RDONLY)) == -1) { + KMessageBox::error(timemon, + i18n("Unable to open the file '%1'. The diagnostics are:\n%2.\n" + "This file is required to determine current system info. " + "Maybe your proc filesystem is non-Linux standard?").arg(MEMINFO_NAME).arg(strerror(errno))); + exit(1); + } + + fcntl( statFD,F_SETFD, FD_CLOEXEC ); + +#elif defined (USE_SOLARIS) + if ((kc = kstat_open()) == 0) { + KMessageBox::error(timemon, i18n("Unable to initialize the 'kstat' library. " + "This library is used for accessing kernel information. " + "The diagnostics are:\n%1.\n" + "Are you really running Solaris? " + "Please contact the maintainer at [email protected] " + "who will try to figure out what went wrong.").arg(strerror(errno))); + exit(1); + } +#endif + +#if defined(USE_SOLARIS) || defined(__osf__) + pagesPerMB = (1024*1024) / getpagesize(); + if (pagesPerMB == 0) pagesPerMB = 1; // paranoia sanity check +#endif + + readSample(); + updateSample(); +} + +// Get rid of the resources we acquired in the constructor. +KSample::~KSample() +{ +#ifdef __linux__ + close(memFD); + close(statFD); +#elif defined (USE_SOLARIS) + if (kc != 0) kstat_close(kc); +#endif +} + +// Set the appropriate scaling parameters +void KSample::setScaling(bool a, unsigned p, unsigned s, unsigned c) +{ + autoscale = a; + pageScale = p; + swapScale = s; + cxScale = c; +} + +// ----------------------------------------------------------------------------- +// Show a message box with the given message and terminate the application. + +void KSample::fatal(const QString& msg) +{ + timemon->stop(); + + KMessageBox::error(timemon, msg); +// exit(1); +} + + +// ----------------------------------------------------------------------------- +// Show a message box with the given message and don't terminate the app ;-) + +void KSample::nonfatal(const QString& msg) +{ + timemon->stop(); + + KMessageBox::sorry(timemon, msg); + timemon->cont(); +} + + +// ----------------------------------------------------------------------------- +// Read a new sample from the files or whatever resource the OS implements + +/* For 2.5 kernels */ +static inline void +scan_one(const char* buff, const char *key, unsigned long int* val) +{ + const char *b = strstr(buff, key); + if (b) { + b = strstr(b, " "); + if (b) + sscanf(b, " %lu", val); + } +} + +void KSample::readSample() +{ + sample.cpus = 0; // just to make sure... + +#ifdef __linux__ // linux makes it simple: use the /proc if + int l; + char buffer[4096]; + + lseek(memFD, 0, 0); + if ((l = read(memFD, buffer, sizeof(buffer) - 1)) < 0) + { + fatal(i18n("Unable to read the memory usage file '%1'.\n" + "The diagnostics are: %2").arg(MEMINFO_NAME).arg(strerror(errno))); + } + buffer[l] = '\0'; + l = 0; + char *p; + while (memstats[l].name != 0) { + p = strstr(buffer, memstats[l].name); + if (p == 0 || + sscanf(p + strlen(memstats[l].name), "%lu kB", memstats[l].stat) < 1) + fatal(i18n("The memory usage file '%1' seems to use a " + "different file format than expected.\n" + "Maybe your version of the proc filesystem is " + "incompatible with supported versions. " + "Please contact the developer at http://bugs.kde.org/ who will try to sort this out.").arg(MEMINFO_NAME)); + l++; + } + + if ( ( p = strstr(buffer, "Slab:") ) ) { + unsigned long slabs; + sscanf(p + 5, "%lu kB", &slabs); + sample.mkernel = slabs; + } + + /* read the data for the cpu stats */ + lseek(statFD, 0, 0); + if ((l = read(statFD, buffer, sizeof(buffer)-1)) < 0) + fatal(i18n("Unable to read the system usage file '%1'.\n" + "The diagnostics are: %2").arg(STAT_NAME).arg(strerror(errno))); + + buffer[l] = '\0'; + + bool ok = (sscanf(buffer, "cpu %lu %lu %lu %lu %lu", &sample.user, + &sample.nice, &sample.kernel, &sample.idle, &sample.iowait) == 5); + + if (ok) { + for (l = 0; l < MAX_CPU; l++) { // get individual stat for SMP machines + char cpuname[10]; + sprintf(cpuname, "cpu%d", l); + + if ((p = strstr(buffer, cpuname)) == NULL) break; + + unsigned long u, n, k, i; + ok = sscanf(p, "cpu%*d %lu %lu %lu %lu", &u, &n, &k, &i); + if (!ok) break; + + sample.smptotal[l] = u+n+k+i; + sample.smpbusy[l] = sample.smptotal[l] - i; + } + } + sample.cpus = l; + +#elif defined(__osf__) // in OSF/2, we can use table() + + QString msg = i18n("Unable to obtain system information.\n" + "The table(2) system call returned an error " + "for table %1.\n" + "Please contact the maintainer at [email protected] " + "who will try to figure out what went wrong."); + + struct tbl_sysinfo sysinfo; + if (table(TBL_SYSINFO, 0, &sysinfo, 1, sizeof(sysinfo)) != 1) + fatal(msg.arg("TBL_SYSINFO")); + + sample.user = sysinfo.si_user; + sample.nice = sysinfo.si_nice; + sample.kernel = sysinfo.si_sys; + sample.iowait = sysinfo.wait; + sample.idle = sysinfo.si_idle; + + struct tbl_vmstats vmstats; + if (table(TBL_VMSTATS, 0, &vmstats, 1, sizeof(vmstats)) != 1) + fatal(msg.arg("TBL_VMSTATS")); + + sample.mtotal = vmstats.free_count + vmstats.active_count + + vmstats.inactive_count + vmstats.wire_count; + sample.free = vmstats.free_count; + sample.buffers = vmstats.inactive_count; // pages not used for some time + sample.cached = vmstats.wire_count; // kernel/driver memory + + struct tbl_swapinfo swapinfo; + if (table(TBL_SWAPINFO, -1, &swapinfo, 1, sizeof(swapinfo)) != 1) + fatal(msg.arg("TBL_SWAPINFO")); + + sample.stotal = swapinfo.size; + sample.sfree = swapinfo.free; + +#elif defined(USE_SOLARIS) + kstat_t *ksp; + + sample.cpus = 0; + for (ksp = kc->kc_chain; ksp != 0; ksp = ksp->ks_next) { + if (strncmp(ksp->ks_name, "cpu_stat", 8) != 0) continue; + sample.cpus++; + } + + if (sample.cpus == 0) + fatal(i18n("Unable to find any entries for CPU statistics " + "in the 'kstat' library. Are you running a non-standard " + "version of Solaris?\n" + "Please contact the maintainer via http://bugs.kde.org/ who will try to sort this out.")); + + sample.user = sample.nice = sample.kernel = sample.iowait = sample.idle = 0; + sample.stotal = sample.sfree = 0; + + int cpus = 0; + for (ksp = kc->kc_chain; ksp != 0; ksp = ksp->ks_next) { + if (strncmp(ksp->ks_name, "cpu_stat", 8) != 0) continue; + cpus++; + + cpu_stat_t cstat; + if (kstat_read(kc, ksp, 0) == -1 || // update from kernel + kstat_read(kc, ksp, &cstat) == -1) // and read into buffer + fatal(i18n("Unable to read the CPU statistics entry " + "from the 'kstat' library. The diagnostics are '%1'.\n" + "Please contact the maintainer via http://bugs.kde.org/ who will try to sort this out.").arg(strerror(errno))); + + // fields are: idle user kernel iowait (no nice info?) + sample.user += cstat.cpu_sysinfo.cpu[1] / sample.cpus; + sample.nice += 0; + sample.kernel += cstat.cpu_sysinfo.cpu[2] / sample.cpus; + sample.iowait += cstat.cpu_sysinfo.cpu[3] / sample.cpus; + sample.idle += cstat.cpu_sysinfo.cpu[0] / sample.cpus; + } + + if (cpus != sample.cpus) + fatal(i18n("The number of CPUs appears to have changed at " + "very short notice, or the 'kstat' library returns " + "inconsistent results (%1 vs. %2 CPUs).\n" + "Please contact the maintainer via http://bugs.kde.org/ who will try to sort this out.").arg(sample.cpus).arg(cpus)); + + // availrmem = pages of core for user-proc ( == physmem - kernelmem) + // freemem = no of free pages + // physmem == total mem in 4KB blocks + + errno = 0; + if ((ksp = kstat_lookup(kc, "unix", -1, "system_pages")) == 0 || + kstat_read(kc, ksp, 0) == -1) + fatal(i18n("Unable to read the memory statistics entry " + "from the 'kstat' library. The diagnostics are '%1'\n" + "You might want to contact the maintainer at " + "http://bugs.kde.org/ who will try to sort this out.").arg(strerror(errno))); + + int i; + unsigned long physmem = 0, freemem = 0, availrmem = 0; + + kstat_named_t *kn = (kstat_named_t *)ksp->ks_data; + for (i = 0; i < (int) ksp->ks_ndata; i++) { + if (strcmp(kn->name, "physmem") == 0) physmem = kn->value.ul; + else if (strcmp(kn->name, "freemem") == 0) freemem = kn->value.ul; + else if (strcmp(kn->name, "availrmem") == 0) availrmem = kn->value.ul; + kn++; + } + + if (physmem == 0) // sanity check, this should always be > 0 + fatal(i18n("There seems to be a problem with KTimeMon's handling " + "of the 'kstat' library: 0 bytes of physical memory determined!\n" + "Free memory is %1, available memory is %2.\n" + "Please contact the maintainer at [email protected] who will try to sort this out.").arg(freemem).arg(availrmem)); + + sample.mtotal = physmem; + sample.free = freemem; + sample.buffers = 0; + sample.cached = physmem - availrmem; // memory used by the kernel + + int swapentries; + if ((swapentries = swapctl(SC_GETNSWP, 0)) == -1) + fatal(i18n("Unable to determine the number of " + "swap spaces. The diagnostics are '%1'.\n" + "Please contact the maintainer at http://bugs.kde.org/ who will try to sort this out.").arg(strerror(errno))); + + if (swapentries != 0) { + // 2* to get some space for padding?? + swaptbl_t *stbl = (swaptbl_t *) malloc(2*sizeof(int) + swapentries * + sizeof(struct swapent)); + if (stbl == 0) + fatal(i18n("KTimeMon ran out of memory while " + "trying to determine the swap usage.\n" + "Attempted to allocate %1 bytes of memory (2 * %2 + %3 * %4).\n" + "Please contact the maintainer at http://bugs.kde.org/ who will try to sort this out.") + .arg(2 * sizeof(int) + swapentries * sizeof(struct swapent)) + .arg(sizeof(int)).arg(swapentries).arg(sizeof(struct swapent))); + + char path[1024]; + stbl->swt_n = swapentries; + for (i = 0; i < swapentries; i++) stbl->swt_ent[i].ste_path = path; + + if ((swapentries = swapctl(SC_LIST, stbl)) == -1) + fatal(i18n("Unable to determine the swap usage.\n" + "The diagnostics are '%1'.\n" + "Please contact the maintainer at http://bugs.kde.org/ who will try to sort this out.").arg(strerror(errno))); + + + if (!warned && swapentries != stbl->swt_n) { + warned = true; + nonfatal(i18n("Information was requested for " + "%1 swap spaces, but only %2 swap entries were returned.\n" + "KTimeMon will attempt to continue.\n" + "Please contact the maintainer at http://bugs.kde.org/ who will try to sort this out.").arg(stbl->swt_n).arg(swapentries)); + } + + for (i = 0; i < swapentries; i++) { + sample.stotal += stbl->swt_ent[i].ste_pages; + sample.sfree += stbl->swt_ent[i].ste_free; + } + + free(stbl); + } + +#else +#warning This type of system is not supported + sample.stotal = sample.sfree = 0; +#endif + + sample.cputotal = + sample.user + sample.nice + sample.kernel + sample.iowait + sample.idle; + sample.used = sample.mtotal - sample.mkernel - sample.free - sample.buffers - sample.cached; + sample.sused = sample.stotal - sample.sfree; +} + +// Read a new sample after copying the old one. +void KSample::updateSample() +{ + oldSample = sample; + readSample(); +} + +// Convert v to a value representing megabytes. +inline void KSample::makeMBytes(unsigned long &v) +{ +#ifdef __linux__ + v /= 1024; // can it be simpler ;-) +#elif defined (__osf__) || defined(USE_SOLARIS) + v /= pagesPerMB; +#endif +} + +// Return unscaled sample +KSample::Sample KSample::getRawSample() +{ + Sample diff = sample; + + diff.cputotal -= oldSample.cputotal; + + diff.user -= oldSample.user; + diff.nice -= oldSample.nice; + diff.kernel -= oldSample.kernel; + diff.iowait -= oldSample.iowait; + + for (int i = 0; i < diff.cpus; i++) { + diff.smptotal[i] -= oldSample.smptotal[i]; + diff.smpbusy[i] -= oldSample.smpbusy[i]; + } + + return diff; +} + +// Better scaling, round according to first decimal +inline unsigned long KSample::doScale(unsigned long value, unsigned scale1, + unsigned long scale2) +{ + if (scale2 == 0) scale2 = (unsigned long)~0; // avoid SEGVs + + unsigned long v = value * scale1 * 10; + v /= scale2; + unsigned r = v % 10; + v /= 10; + if (r > 4) v++; + return v; +} + +// Provide the difference from the last to the current sample, scale it +// and return it. +KSample::Sample KSample::getSample(unsigned scale) +{ + Sample s = getRawSample(); + + s.user = doScale(s.user, scale, s.cputotal); + s.nice = doScale(s.nice, scale, s.cputotal); + s.kernel = doScale(s.kernel, scale, s.cputotal); + s.iowait = doScale(s.iowait, scale, s.cputotal); + + for (int i = 0; i < s.cpus; i++) + s.smpbusy[i] = doScale(s.smpbusy[i], scale, s.smptotal[i]); + + s.cached = doScale(s.cached, scale, s.mtotal); + s.buffers = doScale(s.buffers, scale, s.mtotal); + s.used = doScale(s.used, scale, s.mtotal); + s.mkernel = doScale(s.mkernel, scale, s.mtotal); + makeMBytes(s.mtotal); + + s.sused = doScale(s.sused, scale, s.stotal); + makeMBytes(s.stotal); + + return s; +} + diff --git a/kicker-applets/ktimemon/sample.h b/kicker-applets/ktimemon/sample.h new file mode 100644 index 0000000..b4a0723 --- /dev/null +++ b/kicker-applets/ktimemon/sample.h @@ -0,0 +1,94 @@ +/* -*- C++ -*- */ + +/**********************************************************************/ +/* TimeMon (c) 1994 Helmut Maierhofer */ +/* KDE-ified M. Maierhofer 1998 */ +/**********************************************************************/ + +/* + * sample.h + * + * Definitions for the system dependent sampling class (currently relies + * on the linux /proc filesystem). + */ + +#ifndef SAMPLE_H +#define SAMPLE_H + +// -- global constants --------------------------------------------------- + +#define MAX_CPU 16 // max number of CPUS in an SMP machine + // we get the status for + +// -- forward declaration ------------------------------------------------ +class KTimeMon; + +#ifdef USE_SOLARIS +struct kstat_ctl; +#endif + +// -- class declaration -------------------------------------------------- + +/* + * KSample + * + * This class is responsible for reading the /proc file system and parsing + * the system information. + */ +class KSample { +public: + // -- Sample declaration ----------------------------------------------- + struct Sample { + unsigned long cputotal; + unsigned long user, nice, kernel, iowait, idle; + int cpus; + unsigned long smptotal[MAX_CPU], smpbusy[MAX_CPU]; + unsigned long mtotal, free, buffers, cached, mkernel, used; + unsigned long stotal, sused, sfree; + + void fill(unsigned scale); // fill sample with some fake values + }; + + struct MemStats { + const char *name; + unsigned long *stat; + }; + + KSample(KTimeMon *timemon, bool autoScale, unsigned pageScale, + unsigned swapScale, unsigned ctxScale); + virtual ~KSample(); + + void setScaling(bool autoScale, unsigned pageScale, + unsigned swapScale, unsigned ctxScale); + + Sample getSample(unsigned scale); // returns the current sample + Sample getRawSample(); // returns unscaled sample + void updateSample(); // updates the internally stored sample + +private: + void readSample(); // reads a new sample from /proc + unsigned long doScale(unsigned long value, unsigned scale1, + unsigned long scale2); + // converts pages to MB + void makeMBytes(unsigned long &pages); + + void fatal(const QString& msg); + void nonfatal(const QString& msg); + + KTimeMon *timemon; +#ifdef __linux__ + int memFD, statFD; +#elif defined(USE_SOLARIS) + struct kstat_ctl *kc; + bool warned; +#endif +#if defined(USE_SOLARIS) || defined(__osf__) + unsigned long pagesPerMB; +#endif + Sample sample, oldSample; + unsigned pageScale, swapScale, cxScale; + bool autoscale; + struct MemStats memstats[7]; +}; + +#endif // SAMPLE_H diff --git a/kicker-applets/ktimemon/timemon.cc b/kicker-applets/ktimemon/timemon.cc new file mode 100644 index 0000000..84b0e79 --- /dev/null +++ b/kicker-applets/ktimemon/timemon.cc @@ -0,0 +1,435 @@ + +/**********************************************************************/ +/* TimeMon (c) 1994 Helmut Maierhofer */ +/* KDE-ified M. Maierhofer 1998 */ +/* maintained by Dirk A. Mueller <[email protected]> */ +/**********************************************************************/ + +/* + * timemon.h + * + * Definitions for the timemon widget. + */ + +#include <config.h> + +#include <qpainter.h> +#include <qtimer.h> +#include <qtooltip.h> + +#include <kconfig.h> +#include <kglobal.h> +#include <klocale.h> +#include <khelpmenu.h> +#include <kpopupmenu.h> +#include <kprocess.h> +#include <kmessagebox.h> +#include <kdebug.h> + +#include "timemon.h" +#include "confdlg.h" +#include "sample.h" + +#include "timemon.moc" +#include <stdio.h> + +extern "C" +{ + KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile) + { + KGlobal::locale()->insertCatalogue("ktimemon"); + KTimeMon *mon = new KTimeMon(configFile, KPanelApplet::Normal, + KPanelApplet::Preferences, parent, "ktimemon"); + return mon; + } +} + +// Update colour settings with the new ones from the config dialog. +void KTimeMon::updateConfig(KConfDialog *d) +{ + kernelColour = d->getKernelColour(); + userColour = d->getUserColour(); + iowaitColour = d->getIOWaitColour(); + niceColour = d->getNiceColour(); + cachedColour = d->getCachedColour(); + usedColour = d->getUsedColour(); + buffersColour = d->getBuffersColour(); + mkernelColour = d->getMKernelColour(); + swapColour = d->getSwapColour(); + bgColour = d->getBgColour(); +} + +// ----------------------------------------------------------------------------- +// some KPanelApplet API functions + +int KTimeMon::widthForHeight(int height) const +{ + int s = (int) (vertical ? 2/3.*height : height); + return s>=18? s : 18; +} + + +int KTimeMon::heightForWidth(int width) const +{ + int s = (int) (vertical ? width : 2/3.*width); + return s>=18? s : 18; +} + +void KTimeMon::preferences() +{ + configure(); +} + + +// ----------------------------------------------------------------------------- +// Repaint the object; get the current sample and paint the bar graphs +// correspondingly. Use a pixmap to minimise flicker. + +void KTimeMon::paintEvent(QPaintEvent *) +{ + int w, h, x, y, b, r; + + w = vertical ? width() : height(); + h = vertical ? height() : width(); + + r = w; // remaining height + + x = 0; + + KSample::Sample s; + + if (sample != 0) + s = sample->getSample(h); + else + s.fill(h); + + QPixmap pixmap(width(), height()); + pixmap.fill(this, 0, 0); + + QPainter painter(&pixmap); + + b = r / 3; // bar width + r -= b; + + if (bgColour != colorGroup().background()) + { + paintRect(x, 0, b, h, bgColour, &painter); + } + + y = h - s.kernel; paintRect(x, y, b, s.kernel, kernelColour, &painter); + y -= s.iowait; paintRect(x, y, b, s.iowait, iowaitColour, &painter); + y -= s.user; paintRect(x, y, b, s.user, userColour, &painter); + y -= s.nice; paintRect(x, y, b, s.nice, niceColour, &painter); + + x += b; + b = r / 2; + r -= b; + + if (bgColour != colorGroup().background()) + { + paintRect(x, 0, b, h, bgColour, &painter); + } + + y = h - s.mkernel; paintRect(x, y, b, s.mkernel, mkernelColour, &painter); + y -= s.used; paintRect(x, y, b, s.used, usedColour, &painter); + y -= s.buffers; paintRect(x, y, b, s.buffers, buffersColour, &painter); + y -= s.cached; paintRect(x, y, b, s.cached, cachedColour, &painter); + + x += b; + b = r; + + if (bgColour != colorGroup().background()) + { + paintRect(x, 0, b, h, bgColour, &painter); + } + + y = h - s.sused; paintRect(x, y, b, s.sused, swapColour, &painter); + painter.end(); + + bitBlt(this, 0, 0, &pixmap); +} + +// ----------------------------------------------------------------------------- +// Draw part of a bar, depending on the bar orientation. + +void KTimeMon::paintRect(int x, int y, int w, int h, QColor c, QPainter *p) +{ + if (vertical) + p->fillRect(x, y, w, h, c); + else + p->fillRect(width() - y - h, x, h, w, c); +} + +// Show a tool-tip with some status information. +void KTimeMon::maybeTip(const QPoint& p) +{ + if (sample == 0) return; // no associated sample... + if(!rect().contains(p)) return; + + KSample::Sample s = sample->getSample(100); // scale to 100(%) + int idle = 100 - s.kernel - s.user - s.nice; + if ( idle < 0 ) + idle = 0; + QString str = i18n("cpu: %1% idle\nmem: %2 MB %3% free\nswap: %4 MB %5% free") + .arg(idle) + .arg(KGlobal::locale()->formatNumber(s.used/100.*s.mtotal, 0)) + .arg(100-s.used) + .arg(KGlobal::locale()->formatNumber(s.stotal, 0)) + .arg(100-s.sused); + + tip(rect(), str); +} + +// -- KTimeMon definition ------------------------------------------------ + +// Initialise the member variables, read the configuration data base, +// set up the widget, and start the timer. +KTimeMon::KTimeMon(const QString& configFile, Type type, int actions, + QWidget *parent, const char *name) + : KPanelApplet(configFile, type, actions, parent, name, WRepaintNoErase), QToolTip(this), + configDialog(0), bgProcess(0), + kernelColour("red1"), userColour("blue"), + niceColour("yellow"), iowaitColour("darkgreen"), + usedColour("blue1"), buffersColour("yellow"), + cachedColour("darkgreen"), mkernelColour("red1"), + swapColour("cyan3"), bgColour(colorGroup().background()) +{ + mouseAction[0] = NOTHING; + mouseAction[1] = NOTHING; + mouseAction[2] = MENU; + + KConfig* conf = config(); + conf->setGroup("Parameters"); + interval = conf->readUnsignedNumEntry("Interval", 500); + autoScale = conf->readBoolEntry("AutoScale", true); + + pageScale = conf->readUnsignedNumEntry("PageScale", 10); + swapScale = conf->readUnsignedNumEntry("SwapScale", 5); + ctxScale = conf->readUnsignedNumEntry("ContextScale", 300); + for (int i = 0; i < MAX_MOUSE_ACTIONS; i++) { + QString n; + n.setNum(i); + + mouseAction[i] = (MouseAction) + conf->readUnsignedNumEntry(QString("MouseAction")+n, mouseAction[i]); + mouseActionCommand[i] = conf->readPathEntry(QString("MouseActionCommand")+n); + } + + conf->setGroup("Interface"); + kernelColour = conf->readColorEntry("KernelColour", &kernelColour); + userColour = conf->readColorEntry("UserColour", &userColour); + niceColour = conf->readColorEntry("NiceColour", &niceColour); + iowaitColour = conf->readColorEntry("IOWaitColour", &iowaitColour); + cachedColour = conf->readColorEntry("CachedColour", &cachedColour); + usedColour = conf->readColorEntry("UsedColour", &usedColour); + buffersColour = conf->readColorEntry("BuffersColour", &buffersColour); + swapColour = conf->readColorEntry("SwapColour", &swapColour); + mkernelColour = conf->readColorEntry("MKernelColour", &mkernelColour); + bgColour = conf->readColorEntry("BgColour", &bgColour); + + vertical = conf->readBoolEntry("Vertical", true); + + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(timeout())); + timer->start(interval); + + sample = new KSample(this, autoScale, pageScale, swapScale, ctxScale); + + QString aboutmsg = i18n("KTimeMon for KDE\n" + "Maintained by Dirk A. Mueller <[email protected]>\n" + "Written by M. Maierhofer ([email protected])\n" + "Based on timemon by H. Maierhofer"); + + hmenu = new KHelpMenu(this, aboutmsg); + menu = new KPopupMenu(this); + + menu->insertTitle( SmallIcon( "ktimemon" ), i18n( "System Monitor" ) ) ; + menu->insertItem(i18n("Horizontal Bars"), 4); + menu->insertItem(SmallIcon( "configure" ), i18n( "Preferences..." ), 2); + menu->insertSeparator(); + menu->insertItem(SmallIcon( "help" ), i18n("Help"), hmenu->menu(), 1); + + menu->connectItem(2, this, SLOT(configure())); + menu->connectItem(4, this, SLOT(orientation())); + + menu->setCheckable(true); + + vertical = !vertical; // and similar for orientation + orientation(); +} + +// ----------------------------------------------------------------------------- + +// delete the member variables +KTimeMon::~KTimeMon() +{ + delete sample; + delete bgProcess; + KGlobal::locale()->removeCatalogue("ktimemon"); +} + + +// Apply the settings from the configuration dialog and save them. +void KTimeMon::apply() +{ + stop(); + interval = configDialog->getInterval(); + cont(); + + updateConfig(configDialog); + + sample->setScaling(configDialog->getAutoScale(), + configDialog->getPageScale(), + configDialog->getSwapScale(), + configDialog->getCtxScale()); + + for (int i = 0; i < MAX_MOUSE_ACTIONS; i++) { + mouseAction[i] = (MouseAction) configDialog->getMouseAction(i); + mouseActionCommand[i] = configDialog->getMouseActionCommand(i); + } + + update(); + writeConfiguration(); +} + +void KTimeMon::stop() +{ + timer->stop(); +} + +void KTimeMon::cont() +{ + timer->start(interval); +} + +// Dump the current configuration entries to the data base. +void KTimeMon::writeConfiguration() +{ + KConfig* conf = config(); + conf->setGroup("Interface"); + conf->writeEntry("KernelColour", kernelColour); + conf->writeEntry("UserColour", userColour); + conf->writeEntry("NiceColour", niceColour); + conf->writeEntry("IOWaitColour", iowaitColour); + conf->writeEntry("CachedColour", cachedColour); + conf->writeEntry("UsedColour", usedColour); + conf->writeEntry("BuffersColour", buffersColour); + conf->writeEntry("MKernelColour", mkernelColour); + conf->writeEntry("SwapColour", swapColour); + conf->writeEntry("BgColour", bgColour); + conf->writeEntry("Mode", true); + conf->writeEntry("Vertical", vertical); + + conf->setGroup("Parameters"); + conf->writeEntry("Interval", interval); + conf->writeEntry("AutoScale", autoScale); + conf->writeEntry("PageScale", pageScale); + conf->writeEntry("SwapScale", swapScale); + conf->writeEntry("ContextScale", ctxScale); + conf->writeEntry("WidgetSize", size()); + for (int i = 0; i < MAX_MOUSE_ACTIONS; i++) { + QString n; + n.setNum(i); + + conf->writeEntry(QString("MouseAction")+n, (unsigned)mouseAction[i]); + conf->writePathEntry(QString("MouseActionCommand")+n, mouseActionCommand[i]); + } + conf->sync(); +} + +// Make the KSample object update its internal sample and repaint the +// object. +void KTimeMon::timeout() +{ + sample->updateSample(); + update(); +} + +// This is called when the session management strikes, and also when the +// main program exits with a code of 0 (i.e. there was no error). +void KTimeMon::save() +{ + writeConfiguration(); +} + +// ----------------------------------------------------------------------------- +// Update the configuration dialog with the current values and show it. + +void KTimeMon::configure() +{ + if (configDialog == 0) configDialog = new KConfDialog(this); + configDialog->update(); + configDialog->show(); +} + +// ----------------------------------------------------------------------------- +// Change the orientation of the status bars + +void KTimeMon::orientation() +{ + vertical = !vertical; + + KConfig* conf = config(); + conf->setGroup("Interface"); + conf->writeEntry("Vertical", vertical); + + menu->setItemChecked(4, !vertical); + + update(); + emit updateLayout(); +} + +// Pop up the menu when the appropriate button has been pressed. +void KTimeMon::mousePressEvent(QMouseEvent *event) +{ + if (event == 0) return; + + int index = -1; + if (event->button() == LeftButton) index = 0; + else if (event->button() == MidButton) index = 1; + else if (event->button() == RightButton) index = 2; + + if (index == -1) return; + + switch (mouseAction[index]) { + case NOTHING: + break; + case SWITCH: + break; + case MENU: + menu->popup(mapToGlobal(event->pos())); + break; + case COMMAND: + runCommand(index); + break; + } +} + +// Start the given command +void KTimeMon::runCommand(int index) +{ + // just in case it still hangs around + delete bgProcess; + + bgProcess = new KShellProcess; + *bgProcess << mouseActionCommand[index]; + connect(bgProcess, SIGNAL(receivedStderr(KProcess *, char *, int)), + this, SLOT(commandStderr(KProcess *, char *, int))); + bgProcess->start(KProcess::DontCare, KProcess::Stderr); +} + +// ----------------------------------------------------------------------------- +// Check if there is any diagnostic output (command not found or such) + +void KTimeMon::commandStderr(KProcess * /*proc*/, char *buffer, int /*length*/) +{ + QString msgbuf; + + msgbuf = i18n("Got diagnostic output from child command:\n\n"); + msgbuf += QString::fromLocal8Bit(buffer); + + KMessageBox::information(this, msgbuf); +} + + +// ----------------------------------------------------------------------------- diff --git a/kicker-applets/ktimemon/timemon.h b/kicker-applets/ktimemon/timemon.h new file mode 100644 index 0000000..8f5664c --- /dev/null +++ b/kicker-applets/ktimemon/timemon.h @@ -0,0 +1,107 @@ +/* -*- C++ -*- */ + +/**********************************************************************/ +/* TimeMon (c) 1994 Helmut Maierhofer */ +/* KDE-ified M. Maierhofer 1998 */ +/* maintained by Dirk A. Mueller <[email protected] */ +/**********************************************************************/ + +/* + * timemon.h + * + * Definitions for the timemon widget. + */ + +#ifndef TIMEMON_H +#define TIMEMON_H + +#include <qtooltip.h> +#include <kiconloader.h> +#include <kpanelapplet.h> + +// -- global constants --------------------------------------------------- + +const int MAX_MOUSE_ACTIONS = 3; // event handlers for the three buttons only + +// -- forward declaration ------------------------------------------------ +class KSample; +class KConfDialog; +class QPaintEvent; +class QMouseEvent; +class QPainter; +class KProcess; +class KShellProcess; +class KHelpMenu; +class KPopupMenu; + +// -- KTimeMon declaration ----------------------------------------------- + +/* + * KTimeMon + * + * This is the main widget of the application. It handles the configuration + * dialog and may have an associated KTimeMonWidget in the panel (in which + * case it hides itself). + */ + +class KTimeMon : public KPanelApplet, QToolTip { + Q_OBJECT +public: + enum MouseAction { NOTHING, SWITCH, MENU, COMMAND }; + + KTimeMon(const QString& configFile, Type t = Normal, int actions = 0, + QWidget *parent = 0, const char *name = 0); + virtual ~KTimeMon(); + + void writeConfiguration(); // write back the configuration data + + // reimplemented from KPanelApplet + virtual int widthForHeight(int height) const; + virtual int heightForWidth(int width) const; + + virtual void preferences(); + + void stop(); + void cont(); + +public slots: + void timeout(); // timer expired + void save(); // session management callback + void apply(); // apply configuration information + +protected: + virtual void maybeTip(const QPoint&); + virtual void mousePressEvent(QMouseEvent *event); + virtual void updateConfig(KConfDialog *d); + virtual void paintEvent(QPaintEvent *event); + +private slots: // called from the menu + void configure(); // show the configuration dialog + void orientation(); // switch vertical/horizontal orientation + void commandStderr(KProcess *proc, char *buffer, int length); + +private: + void runCommand(int index); + void paintRect(int x, int y, int w, int h, QColor c, QPainter *p); + + unsigned interval; + bool autoScale; + unsigned pageScale, swapScale, ctxScale; + KPopupMenu* menu; + KHelpMenu* hmenu; + QTimer* timer; + KConfDialog *configDialog; + MouseAction mouseAction[MAX_MOUSE_ACTIONS]; + QString mouseActionCommand[MAX_MOUSE_ACTIONS]; + KShellProcess *bgProcess; + + KSample *sample; + QColor kernelColour, userColour, niceColour, iowaitColour; + QColor usedColour, buffersColour, cachedColour, mkernelColour; + QColor swapColour, bgColour; + bool vertical, tooltip; + + friend class KConfDialog; +}; + +#endif // TIMEMON_H diff --git a/kicker-applets/math/Makefile.am b/kicker-applets/math/Makefile.am new file mode 100644 index 0000000..da94ffb --- /dev/null +++ b/kicker-applets/math/Makefile.am @@ -0,0 +1,19 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = math_panelapplet.la + +math_panelapplet_la_SOURCES = mathapplet.cpp parser.cpp + +METASOURCES = mathapplet.moc +noinst_HEADERS = mathapplet.h parser.h + +lnkdir = $(kde_datadir)/kicker/applets +lnk_DATA = mathapplet.desktop + +EXTRA_DIST = $(lnk_DATA) + +math_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +math_panelapplet_la_LIBADD = $(LIB_KSYCOCA) $(LIB_KDEUI) + +messages: + $(XGETTEXT) *.cpp *.h -o $(podir)/kmathapplet.pot diff --git a/kicker-applets/math/mathapplet.cpp b/kicker-applets/math/mathapplet.cpp new file mode 100644 index 0000000..b4966b2 --- /dev/null +++ b/kicker-applets/math/mathapplet.cpp @@ -0,0 +1,285 @@ +/***************************************************************** + +Based on code 'Run' applet code, copyright (c) 2000 Matthias Elter <[email protected]> + +Modifications made by Andrew Coles, 2004 <[email protected]> + +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 +AUTHORS 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. + +******************************************************************/ + +#include <qlabel.h> +#include <qfont.h> +#include <qstringlist.h> +#include <qpushbutton.h> +#include <qhbox.h> + +#include <kapplication.h> +#include <kglobal.h> +#include <klocale.h> +#include <kconfig.h> +#include <kcombobox.h> +#include <kurifilter.h> +#include <kdialog.h> +#include <krun.h> +#include <kmessagebox.h> +#include <kpopupmenu.h> + +#include "parser.h" + + + +#include "mathapplet.h" +#include "mathapplet.moc" + +extern "C" +{ + KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile) + { + KGlobal::locale()->insertCatalogue("kmathapplet"); + return new MathApplet(configFile, KPanelApplet::Stretch, 0, parent, "kmathapplet"); + } +} + +MathApplet::MathApplet(const QString& configFile, Type type, int actions, + QWidget *parent, const char *name) + : KPanelApplet(configFile, type, actions, parent, name), + m_hasFocus(false) +{ + // setBackgroundMode(X11ParentRelative); + setBackgroundOrigin( AncestorOrigin ); + // setup label + _label = new QLabel(i18n("Evaluate:"), this); + QFont f(_label->font()); + f.setPixelSize(12); +// _label->setBackgroundMode(X11ParentRelative); + _label->setBackgroundOrigin( AncestorOrigin ); + _label->setFixedHeight(14); + _label->setFont(f); + + // setup popup button + _btn = new QPushButton(this); + f = _btn->font(); + f.setPixelSize(12); + _btn->setFont(f); + connect(_btn, SIGNAL(clicked()), SLOT(popup_combo())); + + // setup history combo + _input = new KHistoryCombo(this); + _input->setFocus(); + _input->clearEdit(); + watchForFocus(_input->lineEdit()); + connect(_input, SIGNAL(activated(const QString&)), + SLOT(evaluate(const QString&))); + + initContextMenu(); + useDegrees(); + + KConfig *c = config(); + c->setGroup("General"); + + + // restore history and completion list + QStringList list = c->readListEntry("Completion list"); + _input->completionObject()->setItems(list); + list = c->readListEntry("History list"); + _input->setHistoryItems(list); + int mode = c->readNumEntry( "CompletionMode", KGlobalSettings::completionMode() ); + _input->setCompletionMode( (KGlobalSettings::Completion) mode ); + + _hbox = new QHBox( 0, 0, WStyle_Customize | WType_Popup ); + _hbox->setFixedSize(120, 22); + + +} + +void MathApplet::initContextMenu() +{ + mContextMenu = new KPopupMenu(this); + mContextMenu->setCheckable(true); + mContextMenu->insertItem(i18n("Use &Degrees"), this, SLOT(useDegrees()), 0, 0, 0); + mContextMenu->insertItem(i18n("Use &Radians"), this, SLOT(useRadians()), 0, 1, 1); + setCustomMenu(mContextMenu); +} + + +MathApplet::~MathApplet() +{ + KConfig *c = config(); + c->setGroup("General"); + + // save history and completion list + QStringList list = _input->completionObject()->items(); + c->writeEntry("Completion list", list); + list = _input->historyItems(); + c->writeEntry("History list", list); + c->writeEntry( "CompletionMode", (int) _input->completionMode() ); + c->sync(); + + KGlobal::locale()->removeCatalogue("kmathapplet"); +} + +void MathApplet::useDegrees() { + + mContextMenu->setItemChecked(0, true); + mContextMenu->setItemChecked(1, false); + Parser dummy; + dummy.setAngleMode(1); +} + +void MathApplet::useRadians() { + mContextMenu->setItemChecked(0, false); + mContextMenu->setItemChecked(1, true); + Parser dummy; + dummy.setAngleMode(0); +} + +void MathApplet::resizeEvent(QResizeEvent*) +{ + if(orientation() == Horizontal) + { + _btn->hide(); + _input->reparent(this, QPoint(0,0), true); + _label->setGeometry(0,0, width(), _label->height()); + + if(height() >= _input->sizeHint().height() + _label->height()) + { + int inputVOffset = height() - _input->sizeHint().height() - 2; + int labelHeight = _label->sizeHint().height(); + _label->setGeometry(0, inputVOffset - labelHeight, + width(), labelHeight); + _input->setGeometry(0, inputVOffset, + width(), _input->sizeHint().height()); + _label->show(); + } + else + { + _label->hide(); + + // make it as high as the combobox naturally wants to be + // but no taller than the panel is! + // don't forget to center it vertically either. + int newHeight = _input->sizeHint().height(); + if (newHeight > height()) + newHeight = height(); + _input->setGeometry(0, (height() - newHeight) / 2, + width(), newHeight); + } + } + else + { + _btn->show(); + _btn->setFixedSize(width(), 22); + _input->reparent( _hbox, QPoint(0, 0), false); + _label->hide(); + } + setButtonText(); +} + +void MathApplet::positionChange(KPanelApplet::Position) +{ + setButtonText(); +} + +void MathApplet::setButtonText() +{ + QString t; + + if (position() == pLeft) + { + if (width() >= 42) + t = i18n("< Eval"); + else + t = "<"; + } + else + { + if(width() >= 42) + t = i18n("Eval >"); + else + t = ">"; + } + + _btn->setText(t); +} + +int MathApplet::widthForHeight(int ) const +{ + return 110; +} + +int MathApplet::heightForWidth(int ) const +{ + return 22; +} + +void MathApplet::popup_combo() +{ + QPoint p; + if (position() == pLeft) + p = mapToGlobal(QPoint(-_input->width()-1, 0)); + else + p = mapToGlobal(QPoint(width()+1, 0)); + _hbox->move(p); + _hbox->show(); + _input->setFocus(); +} + +void MathApplet::evaluate(const QString& command) +{ + QString exec; + + Parser evaluator; + + kapp->propagateSessionManager(); + + _input->addToHistory(command); + + + QString cmd = command; + + // Nothing interesting. Quit! + if ( cmd.isEmpty() ){ + KMessageBox::sorry(0L, i18n("You have to enter an expression to be evaluated first.")); + needsFocus(true); + } else { + double answer = evaluator.eval(command); + if (evaluator.errmsg() == 0) { + QString ansAsString = QString::number(answer); + _input->clearEdit(); + _input->setEditText(ansAsString); + } else { + _input->removeFromHistory(_input->currentText()); + needsFocus(true); + } + } + + if (orientation() == Vertical) + _hbox->hide(); +} + +void MathApplet::mousePressEvent(QMouseEvent *e) +{ + if ( e->button() != RightButton ) + { + KPanelApplet::mousePressEvent( e ); + return; + } + + mContextMenu->exec(e->globalPos()); +} diff --git a/kicker-applets/math/mathapplet.desktop b/kicker-applets/math/mathapplet.desktop new file mode 100644 index 0000000..9aba622 --- /dev/null +++ b/kicker-applets/math/mathapplet.desktop @@ -0,0 +1,114 @@ +[Desktop Entry] +Type=Plugin +Name=Math Expression Evaluator +Name[bg]=Математически изрази +Name[bs]=Procjena matematičkih izraza +Name[ca]=Avaluador d'expressions matemàtiques +Name[cs]=Vyhodnocení matematického výrazu +Name[da]=Evaluering af matematiske udtryk +Name[de]=Auswertung mathematischer Ausdrücke +Name[el]=Ελεγκτής εγκυρότητας μαθηματικής έκφρασης +Name[en_GB]=Maths Expression Evaluator +Name[eo]=Matematikesprima interpretilo +Name[es]=Evaluador de expresiones matemáticas +Name[et]=Matemaatikaavaldiste kontrollija +Name[eu]=Espresio matematikoen balidatzailea +Name[fa]=ارزیاب عبارت ریاضی +Name[fi]=Matemaattisen lausekkeen laskija +Name[fr]=Interpréteur d'expressions mathématique +Name[fy]=Lytse rekkenmachine +Name[ga]=Luachálaí Slonn Matamaiticiúil +Name[gl]=Avaliación de Expresións Matemáticas +Name[he]=מפענח נוסחאות מתמטיות +Name[hi]=मैथ एक्सप्रेशन इवेल्यूएटर्स +Name[hr]=Ocjena matematičkih izraza +Name[hu]=Kifejezéskiértékelő +Name[is]=Algebrureiknivél +Name[it]=Disegnatore di funzioni matematiche +Name[ja]=数学的表現の評価者 +Name[ka]=მათემატიკური გამოსახულებების გამომთვლელი +Name[kk]=Математикалық өрнегін есептеу +Name[km]=កម្មវិធីវាយតម្លៃកន្សោមពិជគណិត +Name[lt]=Matematinių išraiškų vertinimo priemonė +Name[mk]=Пресметувач на математички изрази +Name[ms]=Penilaian Ungkapan Matematik +Name[nb]=Matematikkberegner +Name[nds]=Mathemaatsche Utdrück utreken +Name[ne]=गणित अभिव्यक्ति मुल्याङ्कनकर्ता +Name[nl]=Kleine rekenmachine +Name[nn]=Matteuttrykkevaluerar +Name[pl]=Program wyliczający wyrażenia matematyczne +Name[pt]=Avaliação de Expressões Matemáticas +Name[pt_BR]=Validador de Expressões Matemáticas +Name[ru]=Вычисление математических выражений +Name[sk]=Vyhodnotenie matematického výrazu +Name[sl]=Vrednotenje matematičnih izrazov +Name[sr]=Рачунар математичких израза +Name[sr@Latn]=Računar matematičkih izraza +Name[sv]=Utvärdering av matematiska uttryck +Name[ta]=கணிதத் தொடர் மதிப்பிடு +Name[tg]=Тафтиши ифодаҳои математикӣ +Name[tr]=Matematiksel İşlem Değerlendiricisi +Name[uk]=Перевірка математичних виразів +Name[uz]=Matematik ifodalarni hisoblagich +Name[uz@cyrillic]=Математик ифодаларни ҳисоблагич +Name[vi]=Bộ định giá biểu thức toán học +Name[zh_CN]=数学表达式计算器 +Name[zh_TW]=數學運算模擬器 +Comment=A mathematical expression evaluator +Comment[bg]=Изчисление на математически изрази +Comment[bs]=Procjena matematičkih izraza +Comment[ca]=Un avaluador d'expressions matemàtiques +Comment[cs]=Program pro vyhodnocování matematických výrazů +Comment[da]=Til evaluering af matematiske udtryk +Comment[de]=Auswerten von mathematischen Ausdrücken +Comment[el]=Ένας ελεγκτής εγκυρότητας μαθηματικών εκφράσεων +Comment[eo]=Matematikesprima interpretilo +Comment[es]=Un evaluador de expresiones matemáticas +Comment[et]=Matemaatikaavaldiste kontrollija +Comment[eu]=Espresio matematikoen ebaluatzailea +Comment[fa]=ارزیاب عبارتهای ریاضی +Comment[fi]=Matemaattisen lausekkeen laskija +Comment[fr]=Un interpréteur d'expressions mathématiques +Comment[fy]=In applet om wiskundige útdrukkingen te evaluearjen +Comment[ga]=Luachálaí slonn matamaiticiúil +Comment[gl]=Un avaliador de expresións matemáticas +Comment[he]=מפענח נוסחאות מתמטיות +Comment[hi]=एक मैथमेटिकल एक्सप्रेशन इवेल्यूएटर +Comment[hr]=Ocjenjivanje matematičkih izraza +Comment[hu]=Matematikai kifejezések kiszámítására alkalmas program +Comment[is]=Algebrureiknivél +Comment[it]=Uno strumento per disegnare funzioni matematiche +Comment[ja]=数学的表現の評価者 +Comment[ka]=მათემატიკური გამოსახულებების გამომთვლელი +Comment[kk]=Математикалық өрнекті есептеп шығару +Comment[km]=កម្មវិធីវាយតម្លៃកន្សោមពិជគណិត +Comment[lt]=Matematinių išraiškų vertinimo priemonė +Comment[mk]=Пресметување математички изрази +Comment[ms]=Penilai ungkapan matematik +Comment[nb]=En beregner for matematiske uttrykk +Comment[nds]=Utreken vun mathemaatsche Utdrück +Comment[ne]=एउटा गणितिय अभिव्यक्ति मुल्याङ्कनकर्ता +Comment[nl]=Een applet waarmee u wiskundige uitdrukkingen kunt evalueren +Comment[nn]=Ein utreknar for matematiske uttrykk +Comment[pl]=Program wyliczający wyrażenia matematyczne +Comment[pt]=Um avaliador de expressões matemáticas +Comment[pt_BR]=Um validador de expressões +Comment[ru]=Вычисление математических выражений +Comment[sk]=Program pre vyhodnotenie matematických výrazov +Comment[sl]=Vrednotenje matematičnih izrazov +Comment[sr]=Израчунава задате математичке изразе +Comment[sr@Latn]=Izračunava zadate matematičke izraze +Comment[sv]=Ett verktyg för utvärdering av matematiska uttryck +Comment[ta]=கணிதத் தொடர் மதிப்பிடு +Comment[tg]=Тафтиши ифодаҳои математикӣ +Comment[tr]=Matematiksel işlem değerlendirici +Comment[uk]=Перевірка математичних виразів +Comment[uz]=Matematik ifodalarni hisoblagich +Comment[uz@cyrillic]=Математик ифодаларни ҳисоблагич +Comment[vi]=Bộ định giá biểu thức toán học +Comment[zh_CN]=数学表达式计算器 +Comment[zh_TW]=數學運算模擬器 +Icon=math_int +X-KDE-Library=math_panelapplet +X-KDE-UniqueApplet=true diff --git a/kicker-applets/math/mathapplet.h b/kicker-applets/math/mathapplet.h new file mode 100644 index 0000000..1a918c3 --- /dev/null +++ b/kicker-applets/math/mathapplet.h @@ -0,0 +1,74 @@ +/***************************************************************** + +Based on code 'Run' applet code, copyright (c) 2000 Matthias Elter <[email protected]> + +Modifications made by Andrew Coles, 2004 <[email protected]> + +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 +AUTHORS 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. + +******************************************************************/ + +#ifndef __mathapplet_h__ +#define __mathapplet_h__ + +#include <qstring.h> +#include <kpanelapplet.h> + +class QLabel; +class QHBox; +class QPushButton; +class KHistoryCombo; +class KPopupMenu; + +class MathApplet : public KPanelApplet +{ + Q_OBJECT + +public: + MathApplet(const QString& configFile, Type t = Stretch, int actions = 0, + QWidget *parent = 0, const char *name = 0); + virtual ~MathApplet(); + + int widthForHeight(int height) const; + int heightForWidth(int width) const; + +protected: + void resizeEvent(QResizeEvent*); + void positionChange(KPanelApplet::Position); + +protected slots: + void evaluate(const QString&); + void popup_combo(); + void setButtonText(); + void useDegrees(); + void useRadians(); + +private: + + void initContextMenu(); + void mousePressEvent(QMouseEvent *e); + + KHistoryCombo *_input; + QLabel *_label; + QPushButton *_btn; + QHBox *_hbox; + KPopupMenu *mContextMenu; + bool m_hasFocus; +}; + +#endif diff --git a/kicker-applets/math/parser.cpp b/kicker-applets/math/parser.cpp new file mode 100644 index 0000000..7d99c87 --- /dev/null +++ b/kicker-applets/math/parser.cpp @@ -0,0 +1,813 @@ +/* +* Code based on parser from KmPlot - a math. function plotter for the KDE-Desktop +* +* Original code +* Copyright (C) 1998, 1999 Klaus-Dieter M�ller +* 2000, 2002 [email protected] +* +* Modifications: 2004 Andrew Coles ([email protected]) +* +* This file is part of the KDE Project. +* KmPlot is part of the KDE-EDU Project. +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*/ + +// standard c(++) includes +#include <stdlib.h> +#include <stdio.h> +#include <math.h> + +//KDE includes +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> + +// local includes +#include "parser.h" +//#include "settings.h" +//#include "xparser.h" + +double Parser::m_anglemode = 0; + +/// List of predefined functions. +Parser::Mfkt Parser::mfkttab[ FANZ ]= +{ + {"tanh", ltanh}, // Tangens hyperbolicus + {"tan", ltan}, // Tangens + {"sqrt", sqrt}, // Square root + {"sqr", sqr}, // Square + {"sinh", lsinh}, // Sinus hyperbolicus + {"sin", lsin}, // Sinus + {"sign", sign}, // Signum + {"sech", sech}, // Secans hyperbolicus + {"sec", sec}, // Secans + {"log", log10}, // Logarithm base 10 + {"ln", log}, // Logarithm base e + {"exp", exp}, // Exponential function base e + {"coth", coth}, // Co-Tangens hyperbolicus + {"cot", cot}, // Co-Tangens = 1/tan + {"cosh", lcosh}, // Cosinus hyperbolicus + {"cosech", cosech}, // Co-Secans hyperbolicus + {"cosec", cosec}, // Co-Secans + {"cos", lcos}, // Cosinus + {"artanh", artanh}, // Area-tangens hyperbolicus = inverse of tanh + {"arsinh", arsinh}, // Area-sinus hyperbolicus = inverse of sinh + {"arsech", arsech}, // Area-secans hyperbolicus = invers of sech + {"arctan", arctan}, // Arcus tangens = inverse of tan + {"arcsin", arcsin}, // Arcus sinus = inverse of sin + {"arcsec", arcsec}, // Arcus secans = inverse of sec + {"arcoth", arcoth}, // Area-co-tangens hyperbolicus = inverse of coth + {"arcosh", arcosh}, // Area-cosinus hyperbolicus = inverse of cosh + {"arcosech", arcosech}, // Area-co-secans hyperbolicus = inverse of cosech + {"arccot", arccot}, // Arcus co-tangens = inverse of cotan + {"arccosec", arccosec}, // Arcus co-secans = inverse of cosec + {"arccos", arccos}, // Arcus cosinus = inverse of cos + {"abs", fabs} // Absolute value +}; + + +Parser::Parser() +{ ps_init( UFANZ, MEMSIZE, STACKSIZE ); +} + + +Parser::Parser( int anz, int m_size, int s_size ) +{ ps_init( anz, m_size, s_size ); +} + + +void Parser::ps_init(int anz, int m_size, int s_size) +{ int ix; + + ufanz=anz; + memsize=m_size; + stacksize=s_size; + ufkt=new Ufkt[ufanz]; + evalflg=ixa=0; + for(ix=0; ix<ufanz; ++ix) + { ufkt[ix].memsize=memsize; + ufkt[ix].stacksize=stacksize; + ufkt[ix].fname=""; //.resize(1); + ufkt[ix].fvar=""; //.resize(1); + ufkt[ix].fpar=""; //.resize(1); + ufkt[ix].fstr=""; //.resize(1); + ufkt[ix].mem=new unsigned char [memsize]; + } +} + + +Parser::~Parser() +{ delete [] ufkt; +} + + +Parser::Ufkt::Ufkt() +{ +} + + +Parser::Ufkt::~Ufkt() +{ delete [] mem; +} + + +void Parser::setAngleMode(int angle) +{ if(angle==0) + m_anglemode = 1; + else + m_anglemode = M_PI/180; +} + +double Parser::anglemode() +{ return m_anglemode; +} + +double Parser::eval(QString str) +{ double erg; + + stack=new double [stacksize]; + stkptr=stack; + evalflg=1; + lptr=str.latin1(); + err=0; + heir1(); + if(*lptr!=0 && err==0) err=1; + evalflg=0; + erg=*stkptr; + delete [] stack; + if(err==0) + { errpos=0; + return erg; + } + else + { errpos=lptr-(str.latin1())+1; + return 0.; + } +} + + +double Parser::Ufkt::fkt(double x) +{ unsigned char token; + double *pd, (**pf)(double); + double erg, *stack, *stkptr; + Ufkt **puf; + + mptr=mem; + stack=stkptr= new double [stacksize]; + while(1) + { switch(token=*mptr++) + { case KONST: pd=(double*)mptr; + *stkptr=*pd++; + mptr=(unsigned char*)pd; + break; + case XWERT: *stkptr=x; + break; + case YWERT: *stkptr=oldy; + break; + case KWERT: *stkptr=k; + break; + + case PUSH: ++stkptr; + break; + + case PLUS: stkptr[-1]+=*stkptr; + --stkptr; + break; + + case MINUS: stkptr[-1]-=*stkptr; + --stkptr; + break; + + case MULT: stkptr[-1]*=*stkptr; + --stkptr; + break; + + case DIV: if(*stkptr==0.)*(--stkptr)=HUGE_VAL; + else + { stkptr[-1]/=*stkptr; + --stkptr; + } + break; + + case POW: stkptr[-1]=pow(*(stkptr-1), *stkptr); + --stkptr; + break; + + case NEG: *stkptr=-*stkptr; + break; + + case FKT: pf=(double(**)(double))mptr; + *stkptr=(*pf++)(*stkptr); + mptr=(unsigned char*)pf; + break; + + case UFKT: puf=(Ufkt**)mptr; + *stkptr=(*puf++)->fkt(*stkptr); + mptr=(unsigned char*)puf; + break; + + case ENDE: erg=*stkptr; + delete [] stack; + return erg; + } + } +} + +int Parser::getNextIndex() +{ + int ix = 0; + while( ( ix < ufanz ) && !ufkt[ ix ].fname.isEmpty() ) ix++; + if( ix == ufanz ) ix = -1; + return ix; +} + +int Parser::addfkt(QString str) +{ + int ix; + + stkptr=stack=0; + err=0; + errpos=1; + str.remove(" " ); + const int p1=str.find('('); + int p2=str.find(','); + const int p3=str.find(")="); + + //insert '*' when it is needed + for(int i=p1+3; i < (int) str.length();i++) + { + if( (str.at(i).isNumber() || str.at(i).category()==QChar::Letter_Uppercase )&& ( str.at(i-1).isLetter() || str.at(i-1) == ')' ) ) + { + str.insert(i,'*'); + } + else if( (str.at(i).isNumber() || str.at(i) == ')' || str.at(i).category()==QChar::Letter_Uppercase) && ( str.at(i+1).isLetter() || str.at(i+1) == '(' ) ) + { + str.insert(i+1,'*'); + i++; + } + } + + if(p1==-1 || p3==-1 || p1>p3) + { err=4; + return -1; + } + if ( p3+2 == (int) str.length()) //empty function + { err=11; + return -1; + } + if(p2==-1 || p2>p3) p2=p3; + if(getfix(str.left(p1))!=-1) + { err=8; + return -1; + } + else err=0; + + if (str.mid(p1+1, p2-p1-1) == "e") + { err=4; + return -1; + } + + for(ix=0; ix<ufanz; ++ix) + { if(ufkt[ix].fname.isEmpty()) + { ufkt[ix].fname=str.left(p1); + ufkt[ix].fvar=str.mid(p1+1, p2-p1-1); + ufkt[ix].fstr=str; + if(p2<p3) ufkt[ix].fpar=str.mid(p2+1, p3-p2-1); + else ufkt[ix].fpar=""; //.resize(1); + break; + } + } + + if(ix==ufanz) + { err=5; + return -1; + } // zu viele Funktionen + + ixa=ix; + mem=mptr=ufkt[ix].mem; + lptr=(str.latin1())+p3+2; + heir1(); + if(*lptr!=0 && err==0) err=1; // Syntaxfehler + addtoken(ENDE); + + if(err!=0) + { ufkt[ix].fname=""; //.resize(1); + errpos=lptr-(str.latin1())+1; + return -1; + } + + + errpos=0; + return ix; +} + + +int Parser::delfkt(QString name) +{ int ix; + + ix=getfix(name); + if(ix!=-1) ufkt[ix].fname=""; //.resize(1); // Name l�chen + return ix; +} + + +int Parser::delfkt(int ix) +{ if(ix<0 || ix>=ufanz) return -1; // ungltiger Index + + ufkt[ix].fname=""; //.resize(1); // Name l�chen + return ix; +} + + +double Parser::fkt(QString name, double x) +{ int ix; + + ix=getfix(name); + if(ix==-1) return 0.; + + return ufkt[ix].fkt(x); +} + + +void Parser::heir1() +{ char c; + + heir2(); + if(err!=0) return ; + + while(1) + { switch(c=*lptr) + { default: return ; + + case ' ': ++lptr; + continue; + + case '+': + case '-': ++lptr; + addtoken(PUSH); + heir2(); + if(err!=0) return ; + } + + switch(c) + { case '+': addtoken(PLUS); + break; + + case '-': addtoken(MINUS); + } + } +} + + +void Parser::heir2() +{ if(match("-")) + { heir2(); + if(err!=0) return; + + addtoken(NEG); + } + + else heir3(); +} + + +void Parser::heir3() +{ char c; + + heir4(); + if(err!=0) return; + + while(1) + { switch(c=*lptr) + { default: return ; + + case ' ': ++lptr; + continue; + + case '*': + case '/': ++lptr; + addtoken(PUSH); + heir4(); + if(err!=0) return ; + } + + switch(c) + { case '*': addtoken(MULT); + break; + + case '/': addtoken(DIV); + } + } +} + + +void Parser::heir4() +{ primary(); + if(err!=0) return; + + while(match("^")) + { addtoken(PUSH); + primary(); + if(err!=0) return; + addtoken(POW); + } +} + + +void Parser::primary() +{ char *p; + int i; + double w; + + if(match("(")) + { heir1(); + if(match(")")==0) err=2; // fehlende Klammer + return; + } + + for(i=0; i<FANZ; ++i) + { if(match(mfkttab[i].mfstr)) + { primary(); + addtoken(FKT); + addfptr(mfkttab[i].mfadr); + return; + } + } + + for(i=0; i<ufanz; ++i) + { if(ufkt[i].fname[0]==0) continue; + if(match(ufkt[i].fname.latin1())) + { if(i==ixa) {err=9; return;} + + primary(); + addtoken(UFKT); + addfptr(&ufkt[i]); + return; + } + } + // A constant + if(lptr[0] >='A' && lptr[0]<='Z' ) + { char tmp[2]; + tmp[1] = '\0'; + for( int i = 0; i< (int)constant.size();i++) + { + tmp[0] = constant[i].constant; + if ( match( tmp) ) + { + addtoken(KONST); + addwert(constant[i].value); + return; + } + + } + err = 10; + return; + } + + + if(match("pi")) + { addtoken(KONST); + addwert(M_PI); + return; + } + + if(match("e")) + { addtoken(KONST); + addwert(M_E); + return; + } + + if(match(ufkt[ixa].fvar.latin1())) + { addtoken(XWERT); + return; + } + + if(match("y")) + { addtoken(YWERT); + return; + } + + if(match(ufkt[ixa].fpar.latin1())) + { addtoken(KWERT); + return; + } + + w=strtod(lptr, &p); + if(lptr!=p) + { lptr=p; + addtoken(KONST); + addwert(w); + } + else err=1; // Syntax-Fehler +} + + +int Parser::match(const char *lit) +{ const char *p; + + if(*lit==0) return 0; + + while(*lptr==' ') ++lptr; + p=lptr; + while(*lit) + { if(*lit++!=*p++) return 0; + } + lptr=p; + return 1; +} + + +void Parser::addtoken(unsigned char token) +{ if(stkptr>=stack+stacksize-1) + { err=7; + return; + } + + if(evalflg==0) + { if(mptr>=&mem[memsize-10]) err=6; + else *mptr++=token; + + switch(token) + { case PUSH: ++stkptr; + break; + + case PLUS: + case MINUS: + case MULT: + case DIV: + case POW: --stkptr; + } + } + else switch(token) + { case PUSH: ++stkptr; + break; + + case PLUS: stkptr[-1]+=*stkptr; + --stkptr; + break; + + case MINUS: stkptr[-1]-=*stkptr; + --stkptr; + break; + + case MULT: stkptr[-1]*=*stkptr; + --stkptr; + break; + + case DIV: if(*stkptr==0.) *(--stkptr)=HUGE_VAL; + else + { stkptr[-1]/=*stkptr; + --stkptr; + } + break; + + case POW: stkptr[-1]=pow(*(stkptr-1), *stkptr); + --stkptr; + break; + case NEG: *stkptr=-*stkptr; + } +} + + +void Parser::addwert(double x) +{ double *pd=(double*)mptr; + + if(evalflg==0) + { if(mptr>=&mem[memsize-10]) err=6; + else + { *pd++=x; + mptr=(unsigned char*)pd; + } + } + else *stkptr=x; +} + + +void Parser::addfptr(double(*fadr)(double)) +{ double (**pf)(double)=(double(**)(double))mptr; + + if(evalflg==0) + { if(mptr>=&mem[memsize-10]) err=6; + else + { *pf++=fadr; + mptr=(unsigned char*)pf; + } + } + else *stkptr=(*fadr)(*stkptr); +} + + +void Parser::addfptr(Ufkt *adr) +{ Ufkt **p=(Ufkt**)mptr; + + if(evalflg==0) + { if(mptr>=&mem[memsize-10]) err=6; + else + { *p++=adr; + mptr=(unsigned char*)p; + } + } + else *stkptr=adr->fkt(*stkptr); +} + + +int Parser::chkfix(int ix) +{ if(ix<0 || ix>=ufanz) return -1; // ungltiger Index + if(ufkt[ix].fname.isEmpty()) return -1; // keine Funktion + return ix; +} + + +int Parser::getfkt(int ix, QString& name, QString& str) +{ if(ix<0 || ix>=ufanz) return -1; // ungltiger Index + if(ufkt[ix].fname.isEmpty()) return -1; // keine Funktion + name=ufkt[ix].fname.copy(); + str=ufkt[ix].fstr.copy(); + return ix; +} + + +int Parser::getfix(QString name) +{ int ix; + + err=0; + for(ix=0; ix<ufanz; ++ix) + { if(name==ufkt[ix].fname) return ix; + } + err=3; // Name nicht bekannt + return -1; +} + + +int Parser::errmsg() +{ switch(err) + { case 1: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Syntax error").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + + case 2: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Missing parenthesis").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + + case 3: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Function name unknown").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + + case 4: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Void function variable").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + + case 5: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Too many functions").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + + case 6: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Token-memory overflow").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + + case 7: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Stack overflow").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + + case 8: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "Name of function not free").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + + case 9: KMessageBox::error(0, i18n("Parser error at position %1:\n" + "recursive function not allowed").arg(QString::number(errpos)), i18n("Math Expression Evaluator")); + break; + case 10: KMessageBox::error(0, i18n("Could not find a defined constant at position %1" ).arg(QString::number(errpos)), + i18n("Math Expression Evaluator")); + break; + case 11: KMessageBox::error(0, i18n("Empty function"), i18n("Math Expression Evaluator")); + break; + } + + return err; +} + + +double sign(double x) +{ if(x<0.) return -1.; + else if(x>0.) return 1.; + return 0.; +} + +double sqr(double x) +{ return x*x; +} + +double arsinh(double x) +{ return log(x+sqrt(x*x+1)); +} + + +double arcosh(double x) +{ return log(x+sqrt(x*x-1)); +} + + +double artanh(double x) +{ return log((1+x)/(1-x))/2; +} + +// sec, cosec, cot and their inverses + +double sec(double x) +{ return (1 / cos(x*Parser::anglemode())); +} + +double cosec(double x) +{ return (1 / sin(x*Parser::anglemode())); +} + +double cot(double x) +{ return (1 / tan(x*Parser::anglemode())); +} + +double arcsec(double x) +{ if ( !Parser::anglemode() ) return ( 1/acos(x)* 180/M_PI ); + else return acos(1/x); +} + +double arccosec(double x) +{ return asin(1/x)* 1/Parser::anglemode(); +} + +double arccot(double x) +{ return atan(1/x)* 1/Parser::anglemode(); +} + +// sech, cosech, coth and their inverses + + +double sech(double x) +{ return (1 / cosh(x*Parser::anglemode())); +} + +double cosech(double x) +{ return (1 / sinh(x*Parser::anglemode())); +} + +double coth(double x) +{ return (1 / tanh(x*Parser::anglemode())); +} + +double arsech(double x) +{ return arcosh(1/x)* 1/Parser::anglemode(); +} + +double arcosech(double x) +{ return arsinh(1/x)* 1/Parser::anglemode(); +} + +double arcoth(double x) +{ return artanh(1/x)* 1/Parser::anglemode(); +} + +//basic trigonometry functions + +double lcos(double x) +{ return cos(x*Parser::anglemode()); +} +double lsin(double x) +{ return sin(x*Parser::anglemode()); +} +double ltan(double x) +{ return tan(x*Parser::anglemode()); +} + +double lcosh(double x) +{ return cosh(x*Parser::anglemode()); +} +double lsinh(double x) +{ return sinh(x*Parser::anglemode()); +} +double ltanh(double x) +{ return tanh(x*Parser::anglemode()); +} + +double arccos(double x) +{ return acos(x) * 1/Parser::anglemode(); +} +double arcsin(double x) +{ return asin(x)* 1/Parser::anglemode(); +} + +double arctan(double x) +{ return atan(x)* 1/Parser::anglemode(); +} diff --git a/kicker-applets/math/parser.h b/kicker-applets/math/parser.h new file mode 100644 index 0000000..44e82ba --- /dev/null +++ b/kicker-applets/math/parser.h @@ -0,0 +1,241 @@ +/* +* Code based on parser from KmPlot - a math. function plotter for the KDE-Desktop +* +* Original code +* Copyright (C) 1998, 1999 Klaus-Dieter M�ller +* 2000, 2002 [email protected] +* +* Modifications: 2004 Andrew Coles ([email protected]) +* +* This file is part of the KDE Project. +* KmPlot is part of the KDE-EDU Project. +* +* 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*/ + +/** @file parser.h + * \brief Contains the parser core class Parser. */ + +// Qt includes +#include <qstring.h> +#include <qvaluevector.h> + +#ifndef parser_included +#define parser_included + +// Voreinstellungen bei Verwendung des Standardkonstruktors : + + +#define UFANZ 10 ///< max. count of user defined functions +#define MEMSIZE 200 ///< memory size for tokens +#define STACKSIZE 50 ///< stack depth + +//@{ +/** Token type. */ +#define KONST 0 // double value follows +#define XWERT 1 // get x value +#define KWERT 2 // get function parameter +#define PUSH 3 // push value to stack +#define PLUS 4 // add +#define MINUS 5 // subtract +#define MULT 6 // multiply +#define DIV 7 // divide +#define POW 8 // exponentiate +#define NEG 9 // negate +#define FKT 10 // address to function followes +#define UFKT 11 // address to user defined function follows +#define ENDE 12 // end of function +#define YWERT 13 // get y value +#define FANZ 31 // number of mathematical functions in mfkttab[] +//@} + +//@{ +/** Predefined mathematical function. */ +double sign(double x); +double sqr(double x); +double arsinh(double x); +double arcosh(double x); +double artanh(double x); + +double sec(double x); +double cosec(double x); +double cot(double x); +double arcsec(double x); +double arccosec(double x); +double arccot(double x); + +double sech(double x); +double cosech(double x); +double coth(double x); +double arsech(double x); +double arcosech(double x); +double arcoth(double x); + +double lcos(double x); +double lsin(double x); +double ltan(double x); + +double lcosh(double x); +double lsinh(double x); +double ltanh(double x); + +double arccos(double x); +double arcsin(double x); +double arctan(double x); + +//@} + +class Constant +{ +public: + Constant( char c='A', double v=0) + { + constant = c; + value = v; + } + + char constant; + double value; +}; + +/** @short Parser. + * + * Tokenizes a function equation to be evaluated. + */ +class Parser +{ +public: + + Parser(); + Parser(int, int, int); + + ~Parser(); + + /// Evaluates the given expression. + double eval(QString); + /// Evaluates the function with the given name at the position. + double fkt(QString, double); + /// Evaluates the function with the given index at the position. + double fkt(int ix, double x) {return ufkt[ix].fkt(x);} + /// Adds a user defined function with the given equation. + int addfkt(QString); + /// Removes the function with the given name. + int delfkt(QString); + /// Removes the function with the given index. + int delfkt(int); + /// Returns name and expression of the function with the given index. + int getfkt(int, QString&, QString&); + /// Checks, if at the given index a function is stored. + int chkfix(int); + /// Returns the index of the function with the given name. + int getfix(QString); + /// Returns the lowest index in the array of user defined functions which is empty, + /// or -1, if the array is full. + int getNextIndex(); + /// Shows an error message box. + int errmsg(); + /// ? + void setparameter(int ix, double k) {ufkt[ix].k=k;} + /// return the angletype + static double anglemode(); + /// sets the angletype. TRUE is radians and FALSE degrees + void setAngleMode(int); + + QValueVector<Constant> constant; + + /// Error codes. + /** + * The values have following meanings: + * \li 0 => parse success + * \li 1 => syntax error + * \li 2 => missing bracket + * \li 3 => function unknown + * \li 4 => function variable not valid + * \li 5 => too much functions + * \li 6 => memory overflow + * \li 7 => stack overflow + * \li 8 => function name allready used + * \li 9 => recursive function call + * \li 10 => didn't found the wanted constant + * \li 11 => emtpy function + */ + int err, + errpos, ///< Position where the error occured. + ufanz; ///< Max. count of user defined functions. + + + /** User function. */ + class Ufkt + { + public: + Ufkt(); + ~Ufkt(); + double fkt(double); ///< User defined function. + + unsigned char *mem; ///< Pointer to the allocated memory for the tokens. + unsigned char *mptr; ///< Pointer to the token. + QString fname; ///< Name of the function. + QString fvar; ///< Dummy variable. + QString fpar; ///< Parameter. + QString fstr; ///< Function expression. + int memsize; ///< Size of token memory + int stacksize; ///< Size of the stack. + double k, ///< Function parameter. + oldy; ///< The last y-value needed for Euler's method + } + *ufkt; ///< Points to the array of user defined functions. + +protected: + /** Mathematical function. */ + struct Mfkt + { + const char *mfstr; + double (*mfadr)(double); + }; + static Mfkt mfkttab[FANZ]; + +//private: +public: + + void ps_init(int, int, int), + heir1(), + heir2(), + heir3(), + heir4(), + primary(), + addtoken(unsigned char), + addwert(double), + addfptr(double(*)(double)), + addfptr(Ufkt*); + int match(const char*); + + unsigned + char evalflg, // 0 => String wird tokenisiert + // 1 => String wird direkt ausgewertet + *mem, // Zeiger auf Speicher fr Token + *mptr; // Zeiger fr Token + const + char *lptr; // Zeiger fr Funktions-String + int memsize, // Gr�e des Tokenspeichers + stacksize, // Gr�e des Stack + ixa; // Index der aktuellen Funktion + double *stack, // Zeiger auf Stackanfang + *stkptr; // Stackpointer + static double m_anglemode; + +}; + +#endif // parser_included diff --git a/kicker-applets/mediacontrol/AUTHORS b/kicker-applets/mediacontrol/AUTHORS new file mode 100644 index 0000000..b7d6d85 --- /dev/null +++ b/kicker-applets/mediacontrol/AUTHORS @@ -0,0 +1,5 @@ +Michael Startek <[email protected]> +Stefan Gehn <metz {AT} gehn {DOT} net> +Teemu Rytilahti <[email protected]> +Thomas Capricelli <[email protected]> +William Robinson <[email protected]> diff --git a/kicker-applets/mediacontrol/Makefile.am b/kicker-applets/mediacontrol/Makefile.am new file mode 100644 index 0000000..0afe266 --- /dev/null +++ b/kicker-applets/mediacontrol/Makefile.am @@ -0,0 +1,28 @@ +SUBDIRS = . pics +INCLUDES = $(XMMS_INCLUDES) $(all_includes) +METASOURCES = AUTO + +kde_module_LTLIBRARIES = mediacontrol_panelapplet.la + +mediacontrol_panelapplet_la_COMPILE_FIRST = mediacontrolconfigwidget.h +mediacontrol_panelapplet_la_SOURCES = mcslider.cpp \ + mediacontrol.cpp playerInterface.cpp \ + configfrontend.cpp mediacontrolconfigwidget.ui \ + mediacontrolconfig.cpp mediacontroliface.skel \ + noatunInterface.cpp \ + xmmsInterface.cpp \ + mpdInterface.cpp \ + jukInterface.cpp \ + amarokInterface.cpp \ + kscdInterface.cpp \ + simplebutton.cpp + +mediacontrol_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) $(XMMS_LIBS) +mediacontrol_panelapplet_la_LIBADD = $(LIB_KDEUI) + +lnkdir = $(kde_datadir)/kicker/applets +lnk_DATA = mediacontrol.desktop +EXTRA_DIST = $(lnk_DATA) + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/mediacontrol.pot diff --git a/kicker-applets/mediacontrol/README b/kicker-applets/mediacontrol/README new file mode 100644 index 0000000..0c3acc7 --- /dev/null +++ b/kicker-applets/mediacontrol/README @@ -0,0 +1,28 @@ +MediaControl v0.4 +Stefan Gehn <metz AT gehn.net> +---------------------------------------------------------------------- + +This is a small applet for the kde-panel (kicker) to control various +mediaplayers with. + +Supported players at the moment are: +- Noatun +- XMMS +- JuK +- Amarok +- KsCD +- more to come :) + +If you ask "Why another applet for xmms?" then there are a few answers for you: + +1. most of those applets are for XMMS _only_ and I wanted to support various + mediaplayers +2. there was no applet for noatun (... and I was never able to find that noatun + -window on my huge desktop) +3. many xmms-applets use skins to look like xmms itself, I really dislike that + on a panel + +The applet is still very small and can't make coffee yet but this will surely +come one day ;) + +Have fun with this small and (hopefully) handy tool. diff --git a/kicker-applets/mediacontrol/TODO b/kicker-applets/mediacontrol/TODO new file mode 100644 index 0000000..0066900 --- /dev/null +++ b/kicker-applets/mediacontrol/TODO @@ -0,0 +1,7 @@ +Tooltip -> DONE (want to make it configurable) +Themes -> DONE (need some more contributions) +i18n -> need to find out where to put it in kde-cvs +Drag n Drop -> DONE +Playlist-Popup -> maybe never, what about 9000 files playlists in a popup, eh? :) +Squelch-Support -> when squelch got its dcopiface +more players -> hey gimme a nice interface for it and I'll add support ;) diff --git a/kicker-applets/mediacontrol/amarokInterface.cpp b/kicker-applets/mediacontrol/amarokInterface.cpp new file mode 100644 index 0000000..2045c12 --- /dev/null +++ b/kicker-applets/mediacontrol/amarokInterface.cpp @@ -0,0 +1,310 @@ +/*************************************************************************** + Interface to access Amarok + ------------------- + begin : Tue Dec 2 23:54:53 CET 2003 + copyright : (c) 2003 by Thomas Capricelli + adapted from juk* (C) 2001-2002 by Stefan Gehn (metz {AT} gehn {DOT} net) + 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 "amarokInterface.h" +#include "amarokInterface.moc" + +#include <kdebug.h> +#include <qstringlist.h> +#include <qstrlist.h> +#include <kurldrag.h> + +#define TIMER_FAST 250 + +AmarokInterface::AmarokInterface() : PlayerInterface() +{ + mTimerValue = TIMER_FAST; + mAmarokTimer = new QTimer ( this, "mAmaroKTimer" ); + + connect(mAmarokTimer, SIGNAL(timeout()), SLOT(updateSlider()) ); + kapp->dcopClient()->setNotifications ( true ); + + connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)), + SLOT(appRegistered(const QCString&)) ); + + connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT(appRemoved(const QCString&))); + + QTimer::singleShot(0, this, SLOT(myInit())); +} + +AmarokInterface::~AmarokInterface() +{ + kapp->dcopClient()->setNotifications(false); + delete mAmarokTimer; +} + +void AmarokInterface::myInit() +{ + // Start the timer if amarok is already running + // Needed if user adds applet while running amarok + if ( findRunningAmarok() ) + { + emit playerStarted(); + mAmarokTimer->start(mTimerValue); + } + else + { + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void AmarokInterface::appRegistered ( const QCString &appId ) +{ + if(appId.contains("amarok",false) ) + { + mAppId = appId; + emit playerStarted(); + mAmarokTimer->start(mTimerValue); + } +} + +void AmarokInterface::appRemoved ( const QCString &appId ) +{ + if ( appId.contains("amarok",false) ) + { + // is there still another amarok alive? + if ( findRunningAmarok() ) + return; + mAmarokTimer->stop(); + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void AmarokInterface::updateSlider ( ) +{ + // length/time in msecs, -1 means "no playobject in amarok" + int len, time; + QByteArray data, replyData; + QCString replyType; + + if (!kapp->dcopClient()->call(mAppId, "player", "trackTotalTime()",data, replyType, replyData)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication Error" << endl; + // -2 is an internal errornumber, might be used later + len = -2; + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> len; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + // -3 is an internal errornumber, might be used later + len = -3; + } + } + + data = 0; + replyData = 0; + replyType = 0; + + if (!kapp->dcopClient()->call(mAppId, "player", "trackCurrentTime()",data, replyType, replyData)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication error" << endl; + time = -2; + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> time; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + time = -3; + } + } + + if ( (time < 0) || (len < 0)) // Amarok isn't playing and thus returns -1 + { + len = 0; + time = 0; + } + emit newSliderPosition(len,time); + emit playingStatusChanged(playingStatus()); +} + +// Drag-n-Drop stuff ================================================================= + +void AmarokInterface::dragEnterEvent(QDragEnterEvent* event) +{ +// kdDebug(90200) << "AmarokInterface::dragEnterEvent()" << endl; + event->accept( KURLDrag::canDecode(event) ); +} + +void AmarokInterface::dropEvent(QDropEvent* event) +{ + kdDebug(90200) << "AmarokInterface::dropEvent()" << endl; + KURL::List list; + if (KURLDrag::decode(event, list)) + { + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << list; + if (!kapp->dcopClient()->send(mAppId, "player", "addMediaList(KURL::List)",data)) + kdDebug(90200) << "Couldn't send drop to amarok" << endl; + } +} + +// ==================================================================================== + +void AmarokInterface::sliderStartDrag() +{ + mAmarokTimer->stop(); +} + +void AmarokInterface::sliderStopDrag() +{ + mAmarokTimer->start(mTimerValue); +} + +void AmarokInterface::jumpToTime( int sec ) +{ + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << sec; + kapp->dcopClient()->send(mAppId, "player", "seek(int)", data); +} + +void AmarokInterface::playpause() +{ + if (!findRunningAmarok()) + startPlayer("amarok"); + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "playPause()", data); +} + +void AmarokInterface::stop() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "stop()", data); +} + +void AmarokInterface::next() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "next()", data); +} + +void AmarokInterface::prev() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "prev()", data); +} + +void AmarokInterface::volumeUp() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "volumeUp()", data); +} + +void AmarokInterface::volumeDown() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "player", "volumeDown()", data); +} + +const QString AmarokInterface::getTrackTitle() const +{ + QString title; + QByteArray data, replyData; + QCString replyType; + if (!kapp->dcopClient()->call(mAppId, "player", "nowPlaying()",data, replyType, replyData)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication Error" << endl; + return QString(""); + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> title; + return title; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + return QString(""); + } + } +} + +bool AmarokInterface::findRunningAmarok() +{ + QCStringList allApps = kapp->dcopClient()->registeredApplications(); + QValueList<QCString>::const_iterator iterator; + QByteArray data, replyData; + QCString replyType; + + for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator) + { + if ((*iterator).contains("amarok",false)) + { + if (kapp->dcopClient()->call((*iterator), "player", "interfaces()", data, replyType, replyData) ) + { + if ( replyType == "QCStringList" ) + { + QDataStream reply(replyData, IO_ReadOnly); + QCStringList list; + reply >> list; + + if ( list.contains("AmarokPlayerInterface") ) + { + kdDebug(90200) << "mediacontrol: amarok found" << endl; + mAppId = *iterator; + return true; + } + } + } + } + } + kdDebug(90200) << "mediacontrol: amarok not found" << endl; + return false; +} + + +int AmarokInterface::playingStatus() +{ + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "player", "status()", data, replyType, + replyData)) + { + int status = 0; + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> status; + if (status == 2) + return Playing; + else if (status == 1) + return Paused; + } + return Stopped; +} diff --git a/kicker-applets/mediacontrol/amarokInterface.h b/kicker-applets/mediacontrol/amarokInterface.h new file mode 100644 index 0000000..3a71031 --- /dev/null +++ b/kicker-applets/mediacontrol/amarokInterface.h @@ -0,0 +1,69 @@ +/*************************************************************************** + Interface to access Amarok + ------------------- + begin : Tue Dec 2 23:54:53 CET 2003 + copyright : (c) 2003 by Thomas Capricelli + adapted from juk* (C) 2001-2002 by Stefan Gehn (metz {AT} gehn {DOT} net) + 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. * + * * + ***************************************************************************/ + +#ifndef AMAROKINTERFACE_H +#define AMAROKINTERFACE_H + +#include "playerInterface.h" + +#include <kapplication.h> +#include <dcopclient.h> + +#include <qtimer.h> + +class AmarokInterface : public PlayerInterface +{ + Q_OBJECT + public: + AmarokInterface(); + ~AmarokInterface(); + + public slots: + virtual void updateSlider(); // gets called on timer-timeout + virtual void sliderStartDrag(); + virtual void sliderStopDrag(); + virtual void jumpToTime( int msec ); + virtual void playpause(); + virtual void stop(); + virtual void next(); + virtual void prev(); + virtual void volumeUp(); + virtual void volumeDown(); + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual const QString getTrackTitle() const; + virtual int playingStatus(); + + private slots: + void myInit(); + void appRegistered ( const QCString &appId ); + void appRemoved ( const QCString &appId ); + + private: + QTimer *mAmarokTimer; + int mTimerValue; + QCString mAppId; + + /** + * Tries to find a DCOP registered instance of AmaroK + * Stores the name of the first found instance in appId + * @returns true is instance is found, false otherwise + */ + bool findRunningAmarok(); +}; +#endif diff --git a/kicker-applets/mediacontrol/configfrontend.cpp b/kicker-applets/mediacontrol/configfrontend.cpp new file mode 100644 index 0000000..ba206c8 --- /dev/null +++ b/kicker-applets/mediacontrol/configfrontend.cpp @@ -0,0 +1,99 @@ +/*************************************************************************** + provides access to mediacontrol configuration file + ------------------- + begin : forgot :/ + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + + code-skeleton taken from knewsticker which is + Copyright (c) Frerich Raabe <[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 "configfrontend.h" +// #include <kdebug.h> + +ConfigFrontend::ConfigFrontend() : QObject(0, 0) +{ + _config = new KConfig(QString::null, true, false); + _ownConfig = true; +} + +ConfigFrontend::~ConfigFrontend() +{ + if (_ownConfig) + { + delete _config; + } +} + +ConfigFrontend::ConfigFrontend(KConfig *config) : QObject(0, 0) +{ + _config = config; + _config->setGroup("MediaControl"); + _ownConfig = false; +} + +// ==================================================================================== + +uint ConfigFrontend::mouseWheelSpeed() const +{ + return _config->readNumEntry("Mouse wheel speed", 5); +} + +void ConfigFrontend::setMouseWheelSpeed(const uint mouseWheelSpeed) +{ + _config->writeEntry("Mouse wheel speed", mouseWheelSpeed); + _config->sync(); +} + +// ==================================================================================== + +QString ConfigFrontend::player() const +{ + return _config->readPathEntry("Player", "Noatun"); +} + +void ConfigFrontend::setPlayer(const QString &player) +{ + _config->writePathEntry("Player", player); + _config->sync(); +} + +// ==================================================================================== + +QString ConfigFrontend::theme() const +{ + return _config->readEntry("Theme", "default"); +} + +void ConfigFrontend::setTheme(const QString &theme) +{ + _config->writeEntry("Theme", theme); + _config->sync(); +} + +// ==================================================================================== + +bool ConfigFrontend::useCustomTheme() const +{ + return _config->readBoolEntry("UseCustomTheme", false); +} + +void ConfigFrontend::setUseCustomTheme(const bool use) +{ + _config->writeEntry("UseCustomTheme", use); + _config->sync(); +} + +// ==================================================================================== + +#include "configfrontend.moc" diff --git a/kicker-applets/mediacontrol/configfrontend.h b/kicker-applets/mediacontrol/configfrontend.h new file mode 100644 index 0000000..87a0bf4 --- /dev/null +++ b/kicker-applets/mediacontrol/configfrontend.h @@ -0,0 +1,52 @@ +/*************************************************************************** + provides access to mediacontrol configuration file + ------------------- + begin : forgot :/ + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + + code-skeleton taken from knewsticker which is + Copyright (c) Frerich Raabe <[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. * + * * + ***************************************************************************/ + +#ifndef CONFIGFRONTEND_H +#define CONFIGFRONTEND_H + +#include <kconfig.h> +#include <klocale.h> + +class ConfigFrontend : public QObject +{ + Q_OBJECT + public: + ConfigFrontend(); + ConfigFrontend(KConfig *); + virtual ~ConfigFrontend(); + + uint mouseWheelSpeed() const; + QString player() const; + QString theme() const; + bool useCustomTheme() const; + + public slots: + void setMouseWheelSpeed(const uint); + void setPlayer(const QString &player); + void setTheme(const QString &theme); + void setUseCustomTheme(const bool use); + void reparseConfiguration() { _config->reparseConfiguration(); } + + private: + KConfig *_config; + bool _ownConfig:1; +}; + +#endif // CONFIGFRONTEND_H diff --git a/kicker-applets/mediacontrol/configure.in.in b/kicker-applets/mediacontrol/configure.in.in new file mode 100644 index 0000000..8a48beb --- /dev/null +++ b/kicker-applets/mediacontrol/configure.in.in @@ -0,0 +1,48 @@ +dnl AM_PATH_XMMS([1.0.0]) +dnl AM_INIT_AUTOMAKE(mediacontrol, 0.1) +dnl AC_PATH_PROG(XMMS_CONFIG, xmms-config, no) +dnl AM_PATH_XMMS(1.0.0,,AC_MSG_ERROR([*** XMMS >= 1.0.0 not installed - please install first ***])) + +AC_DEFUN([AC_CHECK_XMMS], +[ + AC_MSG_CHECKING([for libxmms]) + AC_CACHE_VAL(ac_cv_have_xmms, + [ + ac_save_libs="$LIBS" + LIBS="`xmms-config --libs`" + ac_CPPFLAGS_save="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $all_includes `xmms-config --cflags 2> /dev/null`" + ac_LDFLAGS_save="$LDFLAGS" + LDFLAGS="$LDFLAGS $all_libraries" + AC_TRY_LINK( + [#include <xmms/xmmsctrl.h>], + [xmms_remote_play_pause(0);], + [ac_cv_have_xmms="yes"], + [ac_cv_have_xmms="no"] + ) + LIBS="$ac_save_libs" + LDFLAGS="$ac_LDFLAGS_save" + CPPFLAGS="$ac_CPPFLAGS_save" + ]) + AC_MSG_RESULT($ac_cv_have_xmms) + if test "$ac_cv_have_xmms" = "yes"; then + XMMS_LIBS="`xmms-config --libs`" + XMMS_INCLUDES="`xmms-config --cflags`" + AC_DEFINE(HAVE_XMMS, 1, [Define if you have xmms libraries and header files.]) + fi +]) + +AC_ARG_WITH(xmms, + [AC_HELP_STRING([--with-xmms],[enable XMMS control applet @<:@default=check@:>@])], + [], with_xmms=check) + +if test "x$with_xmms" != xno; then + AC_CHECK_XMMS + + if test "x$with_xmms" != xcheck && test "x$ac_cv_have_xmms" != xyes; then + AC_MSG_ERROR([--with-xmms was given, but test for XMMS failed]) + fi +fi + +AC_SUBST(XMMS_LIBS) +AC_SUBST(XMMS_INCLUDES) diff --git a/kicker-applets/mediacontrol/jukInterface.cpp b/kicker-applets/mediacontrol/jukInterface.cpp new file mode 100644 index 0000000..302e7f2 --- /dev/null +++ b/kicker-applets/mediacontrol/jukInterface.cpp @@ -0,0 +1,314 @@ +/*************************************************************************** + Interface to access JuK + ------------------- + begin : Mon Jan 15 21:09:00 CEST 2001 + copyright : (C) 2001-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "jukInterface.h" +#include "jukInterface.moc" + +#include <kapplication.h> +#include <kdebug.h> +#include <qstringlist.h> +#include <qstrlist.h> +#include <qprocess.h> +#include <kurldrag.h> + +#define TIMER_FAST 250 + +JuKInterface::JuKInterface() : PlayerInterface(), mProc(0) +{ + mTimerValue = TIMER_FAST; + mJuKTimer = new QTimer ( this, "mJukTimer" ); + + connect(mJuKTimer, SIGNAL(timeout()), SLOT(updateSlider()) ); + kapp->dcopClient()->setNotifications ( true ); + + connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)), + SLOT(appRegistered(const QCString&)) ); + + connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT(appRemoved(const QCString&))); + + QTimer::singleShot(0, this, SLOT(myInit())); +} + +JuKInterface::~JuKInterface() +{ + kapp->dcopClient()->setNotifications(false); + delete mJuKTimer; +} + +void JuKInterface::myInit() +{ + // Start the timer if juk is already running + // Needed if user adds applet while running juk + if ( findRunningJuK() ) + { + emit playerStarted(); + mJuKTimer->start(mTimerValue); + } + else + { + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void JuKInterface::appRegistered ( const QCString &appId ) +{ + if(appId.contains("juk",false) ) + { + mAppId = appId; + + // BWAHAHAHA EVIL HACK + // JuK blocks DCOP signals on its startup, so if we try to + // ping it now, it'll simply cause us to block, which will + // cause kicker to block, which is bad, m'kay? + // + // So what we do is launch the dcop command instead, and let + // *it* block for us. As soon as the command exits, we know + // that JuK is ready to go (and so are we). + mProc = new QProcess(this, "jukdcopCheckProc"); + mProc->addArgument("dcop"); + mProc->addArgument("juk"); + mProc->addArgument("Player"); + mProc->addArgument("status()"); + + connect(mProc, SIGNAL(processExited()), SLOT(jukIsReady())); + mProc->start(); + } +} + +void JuKInterface::appRemoved ( const QCString &appId ) +{ + if ( appId.contains("juk",false) ) + { + // is there still another juk alive? + if ( findRunningJuK() ) + return; + mJuKTimer->stop(); + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +/* Called when the dcop process we launch terminates */ +void JuKInterface::jukIsReady() +{ + emit playerStarted(); + mJuKTimer->start(mTimerValue); + + mProc->deleteLater(); + mProc = 0; +} + +void JuKInterface::updateSlider () +{ + // length/time in msecs, -1 means "no playobject in juk" + int len = -1; + int time = -1; + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "Player", "totalTime()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> len; + } + + data = 0; + replyData = 0; + replyType = 0; + + if (kapp->dcopClient()->call(mAppId, "Player", "currentTime()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> time; + } + + if ( (time < 0) || (len < 0)) // JuK isn't playing and thus returns -1 + { + len = 0; + time = 0; + } + emit ( newSliderPosition(len,time) ); + emit playingStatusChanged(playingStatus()); +} + +// Drag-n-Drop stuff ================================================================= + +void JuKInterface::dragEnterEvent(QDragEnterEvent* event) +{ +// kdDebug(90200) << "JuKInterface::dragEnterEvent()" << endl; + event->accept( KURLDrag::canDecode(event) ); +} + +void JuKInterface::dropEvent(QDropEvent* event) +{ +// kdDebug(90200) << "JuKInterface::dropEvent()" << endl; + KURL::List list; + if (KURLDrag::decode(event, list)) + { + QByteArray data, replyData; + QStringList fileList; + QCString replyType; + QDataStream arg(data, IO_WriteOnly); + + // Juk doesn't handle KURL's yet, so we need to form a list + // that contains the local paths. + for (KURL::List::ConstIterator it = list.begin(); it != list.end(); ++it) + fileList += (*it).path(); + + arg << fileList << false; + + // Use call instead of send to make sure the files are added + // before we try to play. + if (!kapp->dcopClient()->call(mAppId, "Collection", "openFile(QStringList)", data, + replyType, replyData, true)) + { + kdDebug(90200) << "Couldn't send drop to juk" << endl; + } + + // Apparently we should auto-play? + QByteArray strData; + QDataStream strArg(strData, IO_WriteOnly); + strArg << *fileList.begin(); + + if (!kapp->dcopClient()->send(mAppId, "Player", "play(QString)", strData)) + kdDebug(90200) << "Couldn't send play command to juk" << endl; + } +} + +// ==================================================================================== + +void JuKInterface::sliderStartDrag() +{ + mJuKTimer->stop(); +} + +void JuKInterface::sliderStopDrag() +{ + mJuKTimer->start(mTimerValue); +} + +void JuKInterface::jumpToTime( int sec ) +{ + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << sec; + // Used in JuK shipping with KDE < 3.3 + //kapp->dcopClient()->send(mAppId, "Player", "setTime(int)", data); + kapp->dcopClient()->send(mAppId, "Player", "seek(int)", data); +} + +void JuKInterface::playpause() +{ + if (!findRunningJuK()) + startPlayer("juk"); + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "playPause()", data); +} + +void JuKInterface::stop() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "stop()", data); +} + +void JuKInterface::next() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "forward()", data); +} + +void JuKInterface::prev() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "back()", data); +} + +void JuKInterface::volumeUp() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "volumeUp()", data); +} + +void JuKInterface::volumeDown() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "Player", "volumeDown()", data); +} + +const QString JuKInterface::getTrackTitle() const +{ + QString title; + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "Player", "playingString()",data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> title; + return title; + } + } + return QString(""); +} + +// FIXME: what if we have a dcop app named, let's say, 'jukfrontend'? +bool JuKInterface::findRunningJuK() +{ + QCStringList allApps = kapp->dcopClient()->registeredApplications(); + QValueList<QCString>::const_iterator iterator; + + for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator) + { + if ((*iterator).contains("juk",false)) + { + mAppId = *iterator; + return true; + } + } + return false; +} + +int JuKInterface::playingStatus() +{ + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "Player", "status()", data, replyType, + replyData)) + { + int status = 0; + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> status; + + if (status == 2) + return Playing; + else if (status == 1) + return Paused; + } + + return Stopped; +} diff --git a/kicker-applets/mediacontrol/jukInterface.h b/kicker-applets/mediacontrol/jukInterface.h new file mode 100644 index 0000000..fb7f9bb --- /dev/null +++ b/kicker-applets/mediacontrol/jukInterface.h @@ -0,0 +1,72 @@ +/*************************************************************************** + Interface to access JuK + ------------------- + begin : Mon Jan 15 21:09:00 CEST 2001 + copyright : (C) 2001-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef JUKINTERFACE_H +#define JUKINTERFACE_H + +#include "playerInterface.h" + +#include <kapplication.h> +#include <dcopclient.h> + +#include <qtimer.h> + +class QProcess; + +class JuKInterface : public PlayerInterface +{ + Q_OBJECT + public: + JuKInterface(); + ~JuKInterface(); + + public slots: + void updateSlider(); + void sliderStartDrag(); + void sliderStopDrag(); + void jumpToTime( int sec ); + void playpause(); + void stop(); + void next(); + void prev(); + void volumeUp(); + void volumeDown(); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + const QString getTrackTitle() const; + int playingStatus(); + + private slots: + void myInit(); + void appRegistered ( const QCString &appId ); + void appRemoved ( const QCString &appId ); + void jukIsReady(); + + private: + QTimer *mJuKTimer; + QProcess *mProc; + int mTimerValue; + QCString mAppId; + + /** + * Tries to find a DCOP registered instance of juk + * Stores the name of the first found instance in appId + * @returns true is instance is found, false otherwise + */ + bool findRunningJuK(); +}; +#endif diff --git a/kicker-applets/mediacontrol/kscdInterface.cpp b/kicker-applets/mediacontrol/kscdInterface.cpp new file mode 100644 index 0000000..f7f7e90 --- /dev/null +++ b/kicker-applets/mediacontrol/kscdInterface.cpp @@ -0,0 +1,332 @@ +/*************************************************************************** + Interface to access KsCD + ------------------- + begin : Sat Dec 04 13:36:00 CET 2004 + copyright : (C) 2004 by Michal Startek + adapted from JuK interface which is (C) 2001-2002 by Stefan Gehn + 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 "kscdInterface.h" +#include "kscdInterface.moc" + +#include <kapplication.h> +#include <kdebug.h> +#include <qstringlist.h> +#include <qstrlist.h> +#include <kurldrag.h> +#include <klocale.h> + +#define TIMER_FAST 250 + +KsCDInterface::KsCDInterface() : PlayerInterface() +{ + mKsCDTimer = new QTimer(this, "mKsCDTimer"); + + connect(mKsCDTimer, SIGNAL(timeout()), SLOT(updateSlider()) ); + kapp->dcopClient()->setNotifications ( true ); + + connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)), + SLOT(appRegistered(const QCString&)) ); + + connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT(appRemoved(const QCString&))); + + QTimer::singleShot(0, this, SLOT(myInit())); +} + +KsCDInterface::~KsCDInterface() +{ + kapp->dcopClient()->setNotifications(false); + delete mKsCDTimer; +} + +void KsCDInterface::myInit() +{ + // Start the timer if KsCD is already running + // Needed if user adds applet while running KsCD + if (findRunningKsCD()) + { + emit playerStarted(); + mKsCDTimer->start(TIMER_FAST); + } + else + { + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void KsCDInterface::appRegistered(const QCString &appId) +{ + if((appId) == "kscd") + { + mAppId = appId; + emit playerStarted(); + mKsCDTimer->start(TIMER_FAST); + } +} + +void KsCDInterface::appRemoved(const QCString &appId) +{ + if ((appId) == "kscd") + { + // is there still another KsCD alive? + // Okay, KsCD does not allow multiple instances + // of it to run at the same time, but + // this can change. + if (findRunningKsCD()) + return; + mKsCDTimer->stop(); + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void KsCDInterface::updateSlider() +{ + // length/time in secs, -1 means "no playobject in kscd" + int len = -1; + int time = -1; + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentTrackLength()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> len; + } + + data = 0; + replyData = 0; + replyType = 0; + + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentPosition()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> time; + } + + if ( (time < 0) || (len < 0)) // KsCD isn't playing and thus returns -1 + { + len = 0; + time = 0; + } + emit newSliderPosition(len,time); + emit playingStatusChanged(playingStatus()); +} + +// Drag-n-Drop stuff ================================================================= +// As far as I know there is currently no way to drag an AudioCD track to KsCD, +// or even no application to drag AudioCD track from (not the KIO-wrapped track +// path (audiocd:/...) like from Konqueror) + +void KsCDInterface::dragEnterEvent(QDragEnterEvent* event) +{ + event->ignore(); +} + +void KsCDInterface::dropEvent(QDropEvent* event) +{ + event->ignore(); +} + +// ==================================================================================== + +void KsCDInterface::sliderStartDrag() +{ + mKsCDTimer->stop(); +} + +void KsCDInterface::sliderStopDrag() +{ + mKsCDTimer->start(TIMER_FAST); +} + +void KsCDInterface::jumpToTime(int sec) +{ + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << sec; + kapp->dcopClient()->send(mAppId, "CDPlayer", "jumpTo(int)", data); +} + +void KsCDInterface::playpause() +{ + if (!findRunningKsCD()) + startPlayer("kscd"); + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "play()", data); +} + +void KsCDInterface::stop() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "stop()", data); +} + +void KsCDInterface::next() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "next()", data); +} + +void KsCDInterface::prev() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "previous()", data); +} + +void KsCDInterface::volumeUp() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "volumeUp()", data); +} + +void KsCDInterface::volumeDown() +{ + QByteArray data; + kapp->dcopClient()->send(mAppId, "CDPlayer", "volumeDown()", data); +} + +const QString KsCDInterface::getTrackTitle() const +{ + QString title, artist, album, result; + QByteArray data, replyData; + QCString replyType; + + // Get track title from KsCD... + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentTrackTitle()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> title; + } + } + + // Album... + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentAlbum()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> album; + } + } + + // Artist... + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "currentArtist()", data, + replyType, replyData)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + { + reply >> artist; + } + } + + // And compose them into one string that will be displayed... + if(album.isEmpty()) + { + if(artist.isEmpty()) + { + result = title; + } + else // artist is non-empty + { + if(title.isEmpty()) + { + result = artist; + } + else + { + result = i18n("artist - trackname", "%1 - %2").arg(artist, title); + } + } + } + else // album is non-empty + { + if(artist.isEmpty()) + { + if(title.isEmpty()) + { + result = album; + } + else + { + result = i18n("(album) - trackname", "(%1) - %2").arg(artist, title); + } + } + else // artist is non-empty + { + if(title.isEmpty()) + { + result = i18n("artistname (albumname)", "%1 (%2)").arg(artist, album); + } + else + { + result = i18n("artistname (albumname) - trackname", "%1 (%2) - %3").arg(artist, album, title); + } + } + } + + return result; +} + +bool KsCDInterface::findRunningKsCD() +{ + QCStringList allApps = kapp->dcopClient()->registeredApplications(); + QValueList<QCString>::const_iterator iterator; + + for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator) + { + if ((*iterator) == "kscd") + { + mAppId = *iterator; + return true; + } + } + return false; +} + +int KsCDInterface::playingStatus() +{ + QByteArray data, replyData; + QCString replyType; + + if (kapp->dcopClient()->call(mAppId, "CDPlayer", "getStatus()", data, replyType, + replyData)) + { + int status = 0; + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> status; + + switch (status) + { + case 2: + return Playing; + case 4: + return Paused; + default: + return Stopped; + } + } + return Stopped; +} diff --git a/kicker-applets/mediacontrol/kscdInterface.h b/kicker-applets/mediacontrol/kscdInterface.h new file mode 100644 index 0000000..0817b1e --- /dev/null +++ b/kicker-applets/mediacontrol/kscdInterface.h @@ -0,0 +1,68 @@ +/*************************************************************************** + Interface to access KsCD + ------------------- + begin : Sat Dec 04 12:48:00 CET 2004 + copyright : (C) 2004 by Michal Startek + adapted from JuK interface which is (C) 2001-2002 by Stefan Gehn + 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. * + * * + ***************************************************************************/ + +#ifndef KSCDINTERFACE_H +#define KSCDINTERFACE_H + +#include "playerInterface.h" + +#include <kapplication.h> +#include <dcopclient.h> + +#include <qtimer.h> + +class KsCDInterface : public PlayerInterface +{ + Q_OBJECT + public: + KsCDInterface(); + ~KsCDInterface(); + + public slots: + void updateSlider(); + void sliderStartDrag(); + void sliderStopDrag(); + void jumpToTime( int sec ); + void playpause(); + void stop(); + void next(); + void prev(); + void volumeUp(); + void volumeDown(); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + const QString getTrackTitle() const; + int playingStatus(); + + private slots: + void myInit(); + void appRegistered ( const QCString &appId ); + void appRemoved ( const QCString &appId ); + + private: + QTimer *mKsCDTimer; + QCString mAppId; + + /** + * Tries to find a DCOP registered instance of KsCD + * Stores the name of the first found instance in appId + * @returns true is instance is found, false otherwise + */ + bool findRunningKsCD(); +}; +#endif diff --git a/kicker-applets/mediacontrol/mcslider.cpp b/kicker-applets/mediacontrol/mcslider.cpp new file mode 100644 index 0000000..642d2e2 --- /dev/null +++ b/kicker-applets/mediacontrol/mcslider.cpp @@ -0,0 +1,66 @@ +/*************************************************************************** + mcslider.cpp - description + ------------------- + begin : 20040410 + copyright : (C) 2004 by Teemu Rytilahti + 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 <qpixmap.h> + +#include "mcslider.h" + +MCSlider::MCSlider( Orientation orientation, QWidget *parent, const char *name ) + : QSlider( orientation, parent, name ) +{ + setBackgroundOrigin(WidgetOrigin); + setBackground(); +} + +MCSlider::~MCSlider() +{ +} + +// This is needed because KStyle draws slider background incorrectly. + +void MCSlider::setBackground() +{ + unsetPalette(); + + if (parentWidget()->paletteBackgroundPixmap()) + { + QPixmap pm(width(), height()); + pm.fill(parentWidget(), pos()); + setPaletteBackgroundPixmap(pm); + } +} + +void MCSlider::wheelEvent(QWheelEvent *e) +{ + if (e->orientation() == Horizontal) + return; + + if (e->state() == ShiftButton) + { + if (e->delta() > 0) + emit volumeUp(); + else + emit volumeDown(); + e->accept(); + } + else + { + QSlider::wheelEvent(e); + } +} + +#include "mcslider.moc" diff --git a/kicker-applets/mediacontrol/mcslider.h b/kicker-applets/mediacontrol/mcslider.h new file mode 100644 index 0000000..9b11893 --- /dev/null +++ b/kicker-applets/mediacontrol/mcslider.h @@ -0,0 +1,37 @@ +/*************************************************************************** + mcslider.h - description + ------------------- + begin : 20040410 + copyright : (C) 2004 by Teemu Rytilahti + 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. * + * * + ***************************************************************************/ + +#ifndef MCSLIDER_H +#define MCSLIDER_H + +#include <qslider.h> + +class MCSlider : public QSlider +{ + Q_OBJECT + + public: + MCSlider( Orientation orientation, QWidget *parent, const char *name = 0 ); + ~MCSlider(); + void setBackground(); + private: + virtual void wheelEvent(QWheelEvent *e); + signals: + void volumeUp(); + void volumeDown(); +}; +#endif diff --git a/kicker-applets/mediacontrol/mediacontrol.cpp b/kicker-applets/mediacontrol/mediacontrol.cpp new file mode 100644 index 0000000..e69e0e0 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrol.cpp @@ -0,0 +1,614 @@ +/*************************************************************************** + main file of mediacontrol applet + ------------------- + begin : Tue Apr 25 11:53:11 CEST 2000 + copyright : (C) 2000-2005 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "mediacontrol.h" +#include "mediacontrol.moc" + +#include "mediacontrolconfig.h" +#include "configfrontend.h" + + +#include "noatunInterface.h" +#include "xmmsInterface.h" +#include "jukInterface.h" +#include "amarokInterface.h" +#include "mpdInterface.h" +#include "kscdInterface.h" + +#include "mcslider.h" + +#include <qfile.h> +#include <qdragobject.h> +#include <qtooltip.h> +#include <qstyle.h> +#include <qslider.h> +#include <qpainter.h> +#include <qiconset.h> +#include <kpopupmenu.h> + +#include <kapplication.h> +#include <kipc.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <knotifyclient.h> +#include <kbugreport.h> +#include <dcopclient.h> + +const int MC_BUTTONSIZE = 20; // TODO: Might become dynamical for bigger panels +const int NO_BUTTONS = 4; + +extern "C" +{ + KDE_EXPORT KPanelApplet *init( QWidget *parent, const QString &configFile) + { + KGlobal::locale()->insertCatalogue("mediacontrol"); + return new MediaControl(configFile, KPanelApplet::Normal, + KPanelApplet::About | KPanelApplet::Preferences | + KPanelApplet::ReportBug, parent, "mediacontrol"); + } +} + +// ============================================================================= + +class MediaControlToolTip : public QToolTip +{ + public: + MediaControlToolTip(QWidget *widget, PlayerInterface *pl_obj) : + QToolTip(widget), mWidget(widget), mPlayer(pl_obj) {} + + protected: + virtual void maybeTip(const QPoint &pt) + { + QRect rc( mWidget->rect()); + if (rc.contains(pt)) + { + tip ( rc, mPlayer->getTrackTitle() ); + } + } + private: + QWidget *mWidget; + PlayerInterface *mPlayer; +}; + +// ============================================================================= + +MediaControl::MediaControl(const QString &configFile, Type t, int actions, + QWidget *parent, const char *name) + : DCOPObject("MediaControl"), + KPanelApplet(configFile, t, actions, parent, name), + mInstance(new KInstance("mediacontrol")), + mAboutData(new KAboutData("mediacontrol", + I18N_NOOP("MediaControl"), + MEDIACONTROL_VERSION, + I18N_NOOP("A small control-applet for various media players"), + KAboutData::License_GPL_V2, + "(c) 2001-2004 Stefan Gehn", + 0, + "http://metz.gehn.net")) +{ + setBackgroundOrigin(AncestorOrigin); + _player = 0L; + _prefsDialog = 0L; + + _configFrontend = new ConfigFrontend(config()); + // My own dcopclient + _dcopClient = new DCOPClient(); + _dcopClient->registerAs("mediacontrol", false); + + mAboutData->addAuthor("Stefan Gehn", I18N_NOOP("Main Developer"), + "[email protected]", "http://metz.gehn.net"); + mAboutData->addAuthor("Robbie Ward", I18N_NOOP("Initial About-Dialog"), + "[email protected]", "http://www.robbieward.co.uk"); + + mAboutData->addCredit("Sascha Hoffman", I18N_NOOP("Button-Pixmaps"), + "[email protected]", 0); + mAboutData->addCredit("Christian Hoffman", I18N_NOOP("Button-Pixmaps"), + "[email protected]", "http://www.crixensgfxcorner.de.vu/"); + mAboutData->addCredit("Ulrik Mikaelsson", I18N_NOOP("Fix for Noatun-Support"), + "[email protected]", 0); + mAboutData->addCredit("Anthony J Moulen", I18N_NOOP("Fix for Vertical Slider"), + "[email protected]", 0); + mAboutData->addCredit("Teemu Rytilahti", I18N_NOOP("Volume Control Implementation"), + "[email protected]", 0); + mAboutData->addCredit("Jan Spitalnik", I18N_NOOP("Fix for JuK-Support"), + "[email protected]", 0); + mAboutData->addCredit("William Robinson", I18N_NOOP("mpd-Support"), + "[email protected]", 0); + + setAcceptDrops(true); + + prev_button = new TrayButton (this, "PREVIOUS"); + playpause_button = new TrayButton (this, "PLAYPAUSE"); + stop_button = new TrayButton (this, "STOP"); + next_button = new TrayButton (this, "NEXT"); + time_slider = new MCSlider (QSlider::Horizontal, this, "time_slider" ); + time_slider->setRange(0,0); + time_slider->setValue(0); + time_slider->setTracking( false ); + time_slider->installEventFilter(this); + + // request notification of changes in icon style + kapp->addKipcEventMask(KIPC::IconChanged); + connect(kapp, SIGNAL(iconChanged(int)), this, SLOT(slotIconChanged())); + + reparseConfig(); + + rmbMenu = new KPopupMenu(this, "RMBMenu"); + rmbMenu->insertTitle(i18n("MediaControl"), 0, 0); + rmbMenu->insertItem(SmallIcon("configure"), i18n("Configure MediaControl..."), + this, SLOT(preferences())); + rmbMenu->insertItem(i18n("About MediaControl"), this, SLOT(about())); +} + +MediaControl::~MediaControl() +{ + delete _player; + delete _configFrontend; + delete _dcopClient; + KGlobal::locale()->removeCatalogue("mediacontrol"); +} + +// Drag-n-Drop stuff =========================================================== + +void MediaControl::dragEnterEvent(QDragEnterEvent* event) +{ + _player->dragEnterEvent(event); // Just pass dnd to the playerInterface +} + +void MediaControl::dropEvent(QDropEvent* event) +{ + _player->dropEvent(event); // Just pass dnd to the playerInterface +} + +// ============================================================================= + + +void MediaControl::setSliderPosition(int len ,int time) +{ + time_slider->blockSignals(true); + if(orientation() == Vertical) + time = len - time; + + if (mLastLen != len) + time_slider->setRange(0,len); + mLastLen = len; + + if (mLastTime != time) + time_slider->setValue(time); + mLastTime = time; + + time_slider->blockSignals(false); +} + +void MediaControl::enableAll() +{ + prev_button->setDisabled(false); + playpause_button->setDisabled(false); + QToolTip::remove(playpause_button); + stop_button->setDisabled(false); + next_button->setDisabled(false); + time_slider->setDisabled(false); +} + +void MediaControl::disableAll() +{ + prev_button->setDisabled(true); + playpause_button->setDisabled(false); + QToolTip::add(playpause_button, i18n("Start the player")); + stop_button->setDisabled(true); + next_button->setDisabled(true); + time_slider->setDisabled(true); + if(_configFrontend->useCustomTheme()) { + QString skindir = locate("data", "mediacontrol/"+_configFrontend->theme()+"/"); + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"play.png"))); + } + else + playpause_button->setIconSet(SmallIconSet("player_play")); +} + +void MediaControl::slotPlayingStatusChanged(int status) +{ + if (mLastStatus == status) + return; + + mLastStatus = status; + QString skindir = locate("data", "mediacontrol/"+_configFrontend->theme()+"/"); + + switch (status) + { + case (PlayerInterface::Stopped): + case (PlayerInterface::Paused): + if(_configFrontend->useCustomTheme()) + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"play.png"))); + else + playpause_button->setIconSet(SmallIconSet("player_play")); + break; + case (PlayerInterface::Playing): + if(_configFrontend->useCustomTheme()) + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"pause.png"))); + else + playpause_button->setIconSet(SmallIconSet("player_pause")); + break; + } +} + +void MediaControl::slotIconChanged() +{ + if(!_configFrontend->useCustomTheme()) + { + prev_button->setIconSet(SmallIconSet("player_start")); + if (_player->playingStatus() == PlayerInterface::Playing) + playpause_button->setIconSet(SmallIconSet("player_pause")); + else + playpause_button->setIconSet(SmallIconSet("player_play")); + stop_button->setIconSet(SmallIconSet("player_stop")); + next_button->setIconSet(SmallIconSet("player_end")); + } +} + +// Dialogs ===================================================================== + +void MediaControl::preferences() +{ + if ( _prefsDialog ) + { + _prefsDialog->raise(); + } + else + { + _prefsDialog = new MediaControlConfig ( _configFrontend ); + connect ( _prefsDialog, SIGNAL(closing()), + this, SLOT(slotClosePrefsDialog()) ); + connect ( _prefsDialog, SIGNAL(destroyed()), + this, SLOT(slotPrefsDialogClosing()) ); + connect ( _prefsDialog, SIGNAL(configChanged()), + this, SLOT(slotConfigChanged()) ); + } +} + +void MediaControl::slotConfigChanged() +{ + reparseConfig(); +} + +void MediaControl::slotClosePrefsDialog() +{ + delete _prefsDialog; +} + +void MediaControl::slotPrefsDialogClosing() +{ + if ( _prefsDialog ) + _prefsDialog = 0L; +} + + +void MediaControl::about() +{ + KAboutApplication aboutDlg(mAboutData); + aboutDlg.exec(); +} + + +void MediaControl::reportBug() +{ + KBugReport bugReport(this, true, mAboutData); + bugReport.exec(); +} + + +// Fixing the orientation problem in qslider. +void MediaControl::adjustTime(int time) +{ + if(orientation() == Vertical) + emit(newJumpToTime(mLastLen - time)); + else + emit(newJumpToTime(time)); +} + +// Config Stuff ================================================================ + +void MediaControl::reparseConfig() +{ +// kdDebug(90200) << "reparseConfig();" << endl; + _configFrontend->reparseConfiguration(); + + if (_player != 0L) // make sure there is no player-object + { + _player->disconnect(); // disconnect from all things + + time_slider->disconnect(); + prev_button->disconnect(); + playpause_button->disconnect(); + stop_button->disconnect(); + next_button->disconnect(); + + delete slider_tooltip; // tooltip depends on _player : delete it before _player gets deleted + slider_tooltip = 0L; + + delete _player; + _player = 0L; + } + + mLastLen = -1; + mLastTime = -1; + mLastStatus = -1; + + QString playerString = _configFrontend->player(); + + +#ifdef HAVE_XMMS + if (playerString == "XMMS") + { + _player = new XmmsInterface (); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()*1000), + (_configFrontend->mouseWheelSpeed()*1000)); + } + else +#endif + if (playerString == "JuK") + { + _player = new JuKInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + else if (playerString == "Amarok") + { + _player = new AmarokInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + else if (playerString == "KsCD") + { + _player = new KsCDInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + else if (playerString == "mpd") + { + _player = new MpdInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + else // Fallback is Noatun + { + _player = new NoatunInterface(); + time_slider->setSteps((_configFrontend->mouseWheelSpeed()), + (_configFrontend->mouseWheelSpeed())); + } + + // this signal gets emitted by a playerInterface when the player's playtime changed + connect(_player, SIGNAL(newSliderPosition(int,int)), + this, SLOT(setSliderPosition(int,int))); + + connect(_player, SIGNAL(playerStarted()), SLOT(enableAll())); + connect(_player, SIGNAL(playerStopped()), SLOT(disableAll())); + connect(_player, SIGNAL(playingStatusChanged(int)), SLOT(slotPlayingStatusChanged(int))); + + // do we use our icons or the default ones from KDE? + if(_configFrontend->useCustomTheme()) + { + // load theme + QString skindir = locate("data", "mediacontrol/"+_configFrontend->theme()+"/"); + + // the user has to take care if all pixmaps are there, we only check for one of them + if (QFile(skindir+"play.png").exists()) + { + prev_button->setIconSet(SmallIconSet(locate("data",skindir+"prev.png"))); + if (_player->playingStatus() == PlayerInterface::Playing) + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"play.png"))); + else + playpause_button->setIconSet(SmallIconSet(locate("data",skindir+"pause.png"))); + stop_button->setIconSet(SmallIconSet(locate("data",skindir+"stop.png"))); + next_button->setIconSet(SmallIconSet(locate("data",skindir+"next.png"))); + } + else // icon-theme is invalid or not there + { + KNotifyClient::event(winId(), KNotifyClient::warning, + i18n("There was trouble loading theme %1. Please choose" \ + " a different theme.").arg(skindir)); + + // default to kde-icons, they have to be installed :) + slotIconChanged(); + + // and open prefs-dialog + preferences(); + } + } + else // KDE default-icons, assuming that these icons exist! + { + // sets icons from kde + slotIconChanged(); + } + + slider_tooltip = new MediaControlToolTip(time_slider, _player); + + connect(prev_button, SIGNAL(clicked()), _player, SLOT(prev())); + connect(playpause_button, SIGNAL(clicked()), _player, SLOT(playpause())); + connect(stop_button, SIGNAL(clicked()), _player, SLOT(stop())); + connect(next_button, SIGNAL(clicked()), _player, SLOT(next())); + + connect(time_slider, SIGNAL(sliderPressed()), _player, SLOT(sliderStartDrag())); + connect(time_slider, SIGNAL(sliderReleased()), _player, SLOT(sliderStopDrag())); + connect(time_slider, SIGNAL(valueChanged(int)), this, SLOT(adjustTime(int))); + connect(time_slider, SIGNAL(volumeUp()), _player, SLOT(volumeUp())); + connect(time_slider, SIGNAL(volumeDown()), _player, SLOT(volumeDown())); + connect(this, SIGNAL(newJumpToTime(int)), _player, SLOT(jumpToTime(int))); +} + +// Widget Placement =================================================================== + +// kicker wants to know what width we need for a given height +// (this is called when being a HORIZONTAL panel) +int MediaControl::widthForHeight(int height) const +{ +// kdDebug(90200) << "kicker height: " << height << endl; +// kdDebug(90200) << "slider needs: " << time_slider->minimumSizeHint().height() << endl; + + // slider height + button height + if ( height >= (time_slider->minimumSizeHint().height()+MC_BUTTONSIZE) ) + { // slider UNDER buttons + // (5 * button width + spaces between them); + return (4*MC_BUTTONSIZE+10); + } + else + { // slider ASIDE buttons + // (5 * button width + spaces between them) * 2 [size of slider = size of all buttons] + return ((4*MC_BUTTONSIZE+10)*2); + } +} + +// kicker wants to know what height we need for a given width +// (this is called when being a VERTICAL panel) +int MediaControl::heightForWidth(int width) const +{ +// kdDebug(90200) << "kicker width: " << width << endl; + + // slider height + button height + if ( width >= (time_slider->minimumSizeHint().width()+MC_BUTTONSIZE) ) + { // slider ASIDE icons + // (5 * button width + spaces between them); + return (4*MC_BUTTONSIZE+10); + } + else + { // slider UNDER buttons + // (5 * button width + spaces between them) * 2 + // because the size of the slider = the size of all buttons + return ((4*MC_BUTTONSIZE+10)*2); + } +} + +void MediaControl::mousePressEvent(QMouseEvent* e) +{ + if (e->button() == QMouseEvent::RightButton) + rmbMenu->popup(e->globalPos()); +} + +bool MediaControl::eventFilter(QObject *, QEvent *e) +{ + if (e->type() == QEvent::MouseButtonPress) + { + QMouseEvent *me = static_cast<QMouseEvent *>(e); + if (me->button() == QMouseEvent::RightButton) + { + rmbMenu->popup(me->globalPos()); + return true; + } + } + return false; +} + +void MediaControl::paletteChange( const QPalette& ) +{ + time_slider->setBackground(); +} + +void MediaControl::moveEvent( QMoveEvent* ) +{ + time_slider->setBackground(); +} + +// Danger: Weird Code ahead! ;)) +void MediaControl::resizeEvent( QResizeEvent* ) +{ +// kdDebug(90200) << "resizeEvent()" << endl; + int w = width(); + int h = height(); + if ( orientation() == Vertical ) + { // ====== VERTICAL ================================================= + time_slider->setOrientation(QSlider::Vertical); + int slider_width = time_slider->minimumSizeHint().width(); + // some styles need more space for sliders than avilable in very small panels :( + if ( slider_width > w ) slider_width = w; + + // that width would be needed to put the slider aside the buttons + if ( w >= (slider_width+MC_BUTTONSIZE) ) + { // Slider ASIDE icons + int applet_space = (w - (slider_width+MC_BUTTONSIZE) ) / 2; + if ( applet_space < 0 ) + applet_space = 0; + + prev_button->setGeometry ( applet_space, 1, MC_BUTTONSIZE, MC_BUTTONSIZE ); + playpause_button->setGeometry ( applet_space, 3+1*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + stop_button->setGeometry ( applet_space, 5+2*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + next_button->setGeometry ( applet_space, 7+3*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + time_slider->setGeometry ( applet_space+MC_BUTTONSIZE, 1, slider_width, NO_BUTTONS*MC_BUTTONSIZE+8 ); + } + else + { // Slider UNDER Icons + int slider_space = (w - slider_width)/2; + int button_space = (w - MC_BUTTONSIZE)/2; + + prev_button->setGeometry ( button_space, 1 , MC_BUTTONSIZE, MC_BUTTONSIZE ); + playpause_button->setGeometry ( button_space, 3+1*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + stop_button->setGeometry ( button_space, 5+2*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + next_button->setGeometry ( button_space, 7+3*MC_BUTTONSIZE, MC_BUTTONSIZE, MC_BUTTONSIZE ); + time_slider->setGeometry ( slider_space, 9+4*MC_BUTTONSIZE, slider_width, NO_BUTTONS*MC_BUTTONSIZE+8 ); + } + } + else // ====== HORIZONTAL =============================================== + { + time_slider->setOrientation(QSlider::Horizontal); + int slider_height = time_slider->minimumSizeHint().height(); + // some styles need more space for sliders than avilable in very small panels :( + if ( slider_height > h ) slider_height = h; + + // that h would be needed to put the slider under the buttons + if ( h >= (slider_height+MC_BUTTONSIZE) ) + { // Slider UNDER icons + int applet_space = (h-(slider_height+MC_BUTTONSIZE))/2; + if ( applet_space < 0 ) + applet_space = 0; + + prev_button->setGeometry ( 1 , applet_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + playpause_button->setGeometry ( 3+MC_BUTTONSIZE, applet_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + stop_button->setGeometry ( 5+2*MC_BUTTONSIZE, applet_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + next_button->setGeometry ( 7+3*MC_BUTTONSIZE, applet_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + time_slider->setGeometry ( 1, applet_space + MC_BUTTONSIZE, NO_BUTTONS*MC_BUTTONSIZE+8, slider_height ); + } + else + { // Slider ASIDE Icons + int slider_space = (h - slider_height)/2; + int button_space = (h - MC_BUTTONSIZE)/2; + + prev_button->setGeometry ( 1 , button_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + playpause_button->setGeometry ( 3+1*MC_BUTTONSIZE, button_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + stop_button->setGeometry ( 5+2*MC_BUTTONSIZE, button_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + next_button->setGeometry ( 7+3*MC_BUTTONSIZE, button_space, MC_BUTTONSIZE, MC_BUTTONSIZE ); + time_slider->setGeometry ( 9+4*MC_BUTTONSIZE, slider_space, NO_BUTTONS*MC_BUTTONSIZE+8, slider_height ); + } + } +} + +// Our Button ======================================================================== + +TrayButton::TrayButton(QWidget* parent, const char* name) + : SimpleButton (parent, name) +{ + setBackgroundMode(PaletteBackground); + setBackgroundOrigin(AncestorOrigin); +} + +void TrayButton::setIconSet(const QIconSet &iconSet) +{ + setPixmap(iconSet.pixmap(QIconSet::Automatic, QIconSet::Normal, QIconSet::On)); +} + diff --git a/kicker-applets/mediacontrol/mediacontrol.desktop b/kicker-applets/mediacontrol/mediacontrol.desktop new file mode 100644 index 0000000..b7ed81d --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrol.desktop @@ -0,0 +1,121 @@ +[Desktop Entry] +Type=Plugin +Name=Media Control +Name[ar]=التحكم بلوسائط +Name[bg]=Медия контрол +Name[ca]=Control multimèdia +Name[cs]=Ovládání médií +Name[da]=Mediekontrol +Name[de]=Medienkontrolle +Name[el]=Έλεγχος μέσων +Name[eo]=Mediostirilo +Name[es]=Control de medios +Name[et]=Meediakontroll +Name[eu]=Multimedia kontrola +Name[fa]=کنترل رسانه +Name[fi]=Medianhallinta +Name[fr]=Télécommande multimédia +Name[gl]=Controlo Multimédia +Name[he]=בקרת מדיה +Name[hr]=Upravljanje medijima +Name[hu]=Médiavezérlő +Name[is]=Margmiðlunarstjórn +Name[it]=Controllo multimediale +Name[ja]=メディアコントロール +Name[ka]=მედიის მმართველი +Name[kk]=Ойнатқышты басқару +Name[km]=វត្ថុបញ្ជាមេឌៀ +Name[lt]=Media valdymas +Name[mk]=Контрола на мултимедија +Name[nb]=Mediastyring +Name[nds]=Medienkuntrull +Name[ne]=मिडिया नियन्त्रण +Name[nn]=Mediekontroll +Name[pa]=ਮੀਡਿਆ ਕੰਟਰੋਲ +Name[pl]=Zarządzanie mediami +Name[pt]=Controlo Multimédia +Name[pt_BR]=Controle de Mídia +Name[ru]=Управление мультимедиа +Name[sk]=Ovládanie médií +Name[sl]=Nadzor predvajalnikov +Name[sr]=Контрола медија +Name[sr@Latn]=Kontrola medija +Name[sv]=Mediakontroll +Name[tr]=Medya Kontrolü +Name[uk]=Керування медіа +Name[uz]=Media-pleyer boshqaruvi +Name[uz@cyrillic]=Медиа-плейер бошқаруви +Name[vi]=Điều khiển nhạc/ảnh +Name[zh_CN]=媒体控制 +Name[zh_TW]=媒體控制 +Comment=Applet to control mediaplayers +Comment[af]=Miniprogram na kontrole media spelers +Comment[ar]=بريمج للتحكم بمشغلات الوسائط +Comment[az]=Konsol medya çalğıcıları appleti +Comment[bg]=Лесно и универсално управление на плеъри за мултимедийни файлове +Comment[bs]=Applet za kontrolu mediaplayera +Comment[ca]=Applet controlador dels reproductors multimèdia +Comment[cs]=Applet pro ovládání přehrávačů médií +Comment[cy]=Rhaglennig i reoli chwaraewyr cyfryngau +Comment[da]=Program til at kontrollere medieafspillere +Comment[de]=Programm zur Steuerung von Medienabspielern +Comment[el]=Μικροεφαρμογή για τον έλεγχο αναπαραγωγέων μέσων +Comment[eo]=Aplikaĵo por stiri medioludilojn +Comment[es]=Aplicación integrada para controlar el reproductor de medios +Comment[et]=Meediafailide mängijate juhtimise aplett +Comment[eu]=Multimedia erreproduzigailuak kontrolatzeko appleta +Comment[fa]=برنامکی برای کنترل پخشکنندههای رسانه +Comment[fi]=Mediasoittimien hallintasovelma +Comment[fo]=Smáforrit at stýra mediuspælarum við +Comment[fr]=Applet pour commander les lecteurs multimédia +Comment[fy]=Applet om mediaspilers te bestjoeren +Comment[ga]=Feidhmchláirín chun seinnteoirí meán a rialú +Comment[gl]=Unha applet para controlar os reprodutores multimédia +Comment[he]=יישומן לשליטה בנגני מדיה +Comment[hi]=मीडिया प्लेयर्स को नियंत्रित करने का ऐपलेट +Comment[hr]=Aplet za upravljanje multimedijskim programima +Comment[hu]=Médialejátszók vezérlésére szolgáló kisalkalmazás +Comment[is]=Íforrit til að stjórna margmiðlunarspilurum +Comment[it]=Applet per controllare i lettori multimediali +Comment[ja]=メディアプレーヤを操作するアプレット +Comment[ka]=მედია დამკვრელის მართვის აპლეტი +Comment[kk]=Мультимедиа ойнатқыштарды басқару апплеті +Comment[km]=អាប់ភ្លេតដើម្បីត្រួតពិនិត្យកម្មវិធីចាក់មេឌៀ +Comment[lt]=Media grotuvų valdymo įskiepis +Comment[lv]=Aplets mēdijuatskaņotāju vadībai +Comment[mk]=Аплет за контрола на медијаплеери +Comment[ms]=Aplet untuk kawal pemain media +Comment[mt]=Applet biex tikkontrolla players ta' media +Comment[nb]=Miniprogram for å styre multimediaspillere +Comment[nds]=Lüttprogramm för't Stüern vun Medienafspelers +Comment[ne]=मिडिया प्लेएर नियन्त्रण गर्ने एप्लेट +Comment[nl]=Applet om mediaspelers te besturen +Comment[nn]=Applet for kontroll av mediespelarar +Comment[pa]=ਮੀਡਿਆ ਪਲੇਅਰ ਕੰਟਰੋਲ ਲਈ ਐਪਲਿਟ +Comment[pl]=Programik do zarządzania mediami +Comment[pt]=Uma 'applet' para controlar os reprodutores multimédia +Comment[pt_BR]=Mini-aplicativo para controlar tocadores de mídia +Comment[ro]=Miniaplicaţie pentru controlul redării multimedia +Comment[ru]=Аплет для управления медиаплеерами +Comment[sk]=Applet pre ovládanie prehrávačov médií +Comment[sl]=Vstavek za nadzor večpredstavnih predvajalnikov +Comment[sr]=Аплет за контролисање медија плејера +Comment[sr@Latn]=Aplet za kontrolisanje medija plejera +Comment[sv]=Miniprogram för att kontrollera mediaspelare +Comment[ta]=ஊடக வாசிப்பான்களை கட்டுப்படுத்துவதற்கு சிறுநிரல் +Comment[tg]=Аплет барои идоракунии медиаплеерҳо +Comment[th]=แอพเพล็ตควบคุมโปรแกรมเล่นสื่อ +Comment[tr]=Ortam yürütücülerini kontrol etmek için bir programcık +Comment[uk]=Аплет для керування програвачами мультимедіа +Comment[uz]=Media-pleyerlarni boshqarish uchun applet +Comment[uz@cyrillic]=Медиа-плейерларни бошқариш учун апплет +Comment[ven]=Apulete yau langula tshitambi tsha media +Comment[vi]=Tiểu dụng điều khiển bộ phát nhạc/ảnh +Comment[xh]=Applet ukulawula usasazo lwabadlali +Comment[zh_CN]=控制媒体播放器的小程序 +Comment[zh_TW]=控制媒體播放器的小程式 +Comment[zu]=i Applet ukulawula abadlali bolawulo laphakathi +X-KDE-Library=mediacontrol_panelapplet +X-KDE-UniqueApplet=true +Icon=multimedia +X-KDE-ParentApp=kicker diff --git a/kicker-applets/mediacontrol/mediacontrol.h b/kicker-applets/mediacontrol/mediacontrol.h new file mode 100644 index 0000000..f5a6e5e --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrol.h @@ -0,0 +1,122 @@ +/*************************************************************************** + main file of mediacontrol applet + ------------------- + begin : Tue Apr 25 11:53:11 CEST 2000 + copyright : (C) 2000-2005 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef MEDIACONTROL_H +#define MEDIACONTROL_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <klocale.h> +#include <kpanelapplet.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kaboutdata.h> +#include <kaboutapplication.h> + +#include <qpalette.h> + +// used everywhere :) +#include <qstring.h> + +#include "playerInterface.h" +#include "configfrontend.h" +#include "mediacontroliface.h" +#include "simplebutton.h" + +#define MEDIACONTROL_VERSION "0.4" + +class MCSlider; +class KPopupMenu; +class KInstance; +class MediaControlConfig; +class KAboutData; +class MediaControlToolTip; + +// ============================================================================= + +class TrayButton : public SimpleButton +{ + Q_OBJECT + + public: + TrayButton(QWidget* parent, const char* name); + virtual ~TrayButton() {} + void setIconSet(const QIconSet &iconSet); +}; + +// ============================================================================= + +class MediaControl : public KPanelApplet, virtual public MediaControlIface +{ + Q_OBJECT + + public: + MediaControl(const QString&, Type, int ,QWidget * = 0, const char * = 0); + virtual ~MediaControl(); + + int widthForHeight(int height) const; + int heightForWidth(int width) const; + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + virtual void reparseConfig(); + + public slots: + void about(); + void preferences(); + void reportBug(); + + private: + KInstance *mInstance; + KAboutData *mAboutData; + DCOPClient *_dcopClient; + PlayerInterface *_player; + ConfigFrontend *_configFrontend; + MediaControlConfig *_prefsDialog; + TrayButton *prev_button; // GoTo Previous Playlist-Item + TrayButton *playpause_button; // Start/Pause playing + TrayButton *stop_button; // Stop the music + TrayButton *next_button; // GoTo Next Playlist-Item + MCSlider *time_slider; + int mLastLen, mLastTime, mLastStatus; + KPopupMenu *rmbMenu; + + virtual void mousePressEvent(QMouseEvent* e); + virtual void moveEvent(QMoveEvent*); + virtual void paletteChange(const QPalette&); + virtual void resizeEvent(QResizeEvent*); + virtual bool eventFilter(QObject *watched, QEvent *e); + + friend class MediaControlToolTip; + MediaControlToolTip *slider_tooltip; + + private slots: + void setSliderPosition(int len, int time); + void slotIconChanged(); + void disableAll(); + void enableAll(); + void slotClosePrefsDialog(); + void slotPrefsDialogClosing(); + void slotConfigChanged(); + void adjustTime(int); + void slotPlayingStatusChanged(int status); + + signals: + void newJumpToTime(int); +}; +#endif diff --git a/kicker-applets/mediacontrol/mediacontrolconfig.cpp b/kicker-applets/mediacontrol/mediacontrolconfig.cpp new file mode 100644 index 0000000..b146ff1 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrolconfig.cpp @@ -0,0 +1,197 @@ +/*************************************************************************** + mediacontrol configuration dialog + ------------------- + begin : forgot :/ + copyright : (C) 2000-2005 by Stefan Gehn + email : metz {AT} gehn {DOT} net + + code-skeleton taken from knewsticker which is + Copyright (c) Frerich Raabe <[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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "mediacontrolconfig.h" +#include "mediacontrolconfigwidget.h" + +#include <qdir.h> +#include <qcheckbox.h> +#include <qlistbox.h> +#include <qtoolbutton.h> +#include <qlayout.h> +#include <qgroupbox.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kconfig.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klistbox.h> +#include <klocale.h> +#include <knuminput.h> +#include <kstandarddirs.h> + +MediaControlConfig::MediaControlConfig( ConfigFrontend *cfg, QWidget *parent, const char* name) +: KDialogBase( parent, name, false, i18n("MediaControl"), Ok | Apply | Cancel, Ok, false ) +{ + _configFrontend = cfg; + if (!_configFrontend) // emergency!!! + return; + + _child = new MediaControlConfigWidget(this); + setMainWidget ( _child ); + +#ifdef HAVE_XMMS + _child->playerListBox->insertItem("XMMS"); +#endif + _child->playerListBox->insertItem("Noatun"); + _child->playerListBox->insertItem("Amarok"); + _child->playerListBox->insertItem("JuK"); + _child->playerListBox->insertItem("mpd"); + _child->playerListBox->insertItem("KsCD"); + + _child->themeListBox->clear(); + // fill with available skins + KGlobal::dirs()->addResourceType("themes", KStandardDirs::kde_default("data") + "mediacontrol"); + QStringList list = KGlobal::dirs()->resourceDirs("themes"); + for (QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) + readSkinDir(*it); + + connect(_child->mWheelScrollAmount, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); + connect(_child->playerListBox, SIGNAL(selectionChanged()), SLOT(slotConfigChanged())); + connect(_child->themeListBox, SIGNAL(selectionChanged()), SLOT(slotConfigChanged())); + connect(_child->themeListBox, SIGNAL(selectionChanged(QListBoxItem *)), SLOT(slotChangePreview(QListBoxItem *))); + connect(_child->mUseThemes, SIGNAL(toggled(bool)), SLOT(slotConfigChanged()) ); + connect(_child->mUseThemes, SIGNAL(toggled(bool)), SLOT(slotUseThemesToggled(bool)) ); + + load(); + show(); + + enableButtonApply ( false ); // apply id disabled until something changed +} + +void MediaControlConfig::readSkinDir( const QString &dir ) +{ + QDir directory( dir ); + if (!directory.exists()) + return; + + const QFileInfoList *list = directory.entryInfoList(); + QFileInfoListIterator it(*list); + + while ( it.current() ) + { + // append directory-name to our theme-listbox + if ( QFile(it.current()->absFilePath()+"/play.png").exists() ) + _child->themeListBox->insertItem ( it.current()->baseName(), -1 ); + ++it; + } +} + +// ============================================================================ + +void MediaControlConfig::load() +{ + // find the playerstring from config in the playerlist and select it if found + QListBoxItem *item = 0; + + item = _child->playerListBox->findItem( _configFrontend->player() ); + if ( item ) + _child->playerListBox->setCurrentItem ( item ); + else + _child->playerListBox->setCurrentItem( 0 ); + + // reset item to a proper state + item=0; + + _child->mWheelScrollAmount->setValue( _configFrontend->mouseWheelSpeed() ); + + // Select the used Theme + item = _child->themeListBox->findItem( _configFrontend->theme() ); + if ( item ) + _child->themeListBox->setCurrentItem( item ); + else + _child->themeListBox->setCurrentItem( 0 ); + + + bool ison = _configFrontend->useCustomTheme(); + _child->mUseThemes->setChecked( ison ); + slotUseThemesToggled( ison ); +} + +void MediaControlConfig::save() +{ +// kdDebug(90200) << "MediaControlConfig::save()" << endl; + for ( int it=0 ; it <= _child->playerListBox->numRows(); ++it ) + { + if ( _child->playerListBox->isSelected(it) ) + { + _configFrontend->setPlayer ( _child->playerListBox->text(it) ); + } + } + + _configFrontend->setMouseWheelSpeed ( _child->mWheelScrollAmount->value() ); + + for ( int it=0 ; it <= _child->themeListBox->numRows(); ++it ) + { + if ( _child->themeListBox->isSelected(it) ) + { + _configFrontend->setTheme ( _child->themeListBox->text(it) ); + } + } + + _configFrontend->setUseCustomTheme( _child->mUseThemes->isChecked() ); + + emit configChanged(); +} + +void MediaControlConfig::slotApply() +{ + save(); + enableButtonApply(false); +} + +void MediaControlConfig::slotOk() +{ + save(); + emit closing(); +} + +void MediaControlConfig::slotCancel() +{ + emit closing(); +} + +void MediaControlConfig::slotConfigChanged() +{ + enableButtonApply ( true ); +} + +void MediaControlConfig::slotChangePreview(QListBoxItem *item) +{ + QString skindir = item->text(); + _child->previewPrev->setIconSet(SmallIconSet(locate("themes",skindir+"/prev.png"))); + _child->previewPlay->setIconSet(SmallIconSet(locate("themes",skindir+"/play.png"))); + _child->previewPause->setIconSet(SmallIconSet(locate("themes",skindir+"/pause.png"))); + _child->previewStop->setIconSet(SmallIconSet(locate("themes",skindir+"/stop.png"))); + _child->previewNext->setIconSet(SmallIconSet(locate("themes",skindir+"/next.png"))); +} + +void MediaControlConfig::slotUseThemesToggled(bool on) +{ + _child->themeListBox->setEnabled(on); + _child->previewGroupBox->setEnabled(on); +} + +#include "mediacontrolconfig.moc" diff --git a/kicker-applets/mediacontrol/mediacontrolconfig.h b/kicker-applets/mediacontrol/mediacontrolconfig.h new file mode 100644 index 0000000..5869722 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrolconfig.h @@ -0,0 +1,54 @@ +/*************************************************************************** + mediacontrol configuration dialog + ------------------- + begin : forgot :/ + copyright : (C) 2000-2005 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef MEDIACONTROLCONFIG_H +#define MEDIACONTROLCONFIG_H + +#include "configfrontend.h" +#include <kdialogbase.h> + +class MediaControlConfigWidget; +class ConfigFrontend; +class KConfig; + +class MediaControlConfig: public KDialogBase +{ +Q_OBJECT +public: + MediaControlConfig(ConfigFrontend *cfg, QWidget *parent = 0, const char* name = "MediaControlConfig"); + + void readSkinDir(const QString &dir); + void load(); + void save(); + +signals: + void closing(); + void configChanged(); + +protected slots: + void slotConfigChanged(); + void slotChangePreview(QListBoxItem *item); + void slotUseThemesToggled(bool); + virtual void slotApply(); + virtual void slotOk(); + virtual void slotCancel(); + +private: + ConfigFrontend *_configFrontend; + MediaControlConfigWidget *_child; +}; +#endif // MEDIACONTROLCONFIG_H diff --git a/kicker-applets/mediacontrol/mediacontrolconfigwidget.ui b/kicker-applets/mediacontrol/mediacontrolconfigwidget.ui new file mode 100644 index 0000000..9f5c662 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontrolconfigwidget.ui @@ -0,0 +1,374 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>MediaControlConfigWidget</class> +<comment>Preferences-Dialog for MediaControl </comment> +<author>Stefan Gehn <[email protected]></author> +<widget class="QWidget"> + <property name="name"> + <cstring>MediaControlConfigWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>318</width> + <height>245</height> + </rect> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <property name="toolTip" stdset="0"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string></string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QTabWidget"> + <property name="name"> + <cstring>tabWidget</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>tabGeneral</cstring> + </property> + <attribute name="title"> + <string>&General</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>gbMediaPlayer</cstring> + </property> + <property name="title"> + <string>Media-Player</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KListBox" row="0" column="0"> + <property name="name"> + <cstring>playerListBox</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Select the multimedia player you are using from this list.</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>Layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lmousewheelscrollingamount</cstring> + </property> + <property name="text"> + <string>&Wheel scroll seconds:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>mWheelScrollAmount</cstring> + </property> + </widget> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>mWheelScrollAmount</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>Sets the number of lines a mousewheel will scroll in the current file.</string> + </property> + </widget> + </hbox> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>themes</cstring> + </property> + <attribute name="title"> + <string>&Themes</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>mUseThemes</cstring> + </property> + <property name="text"> + <string>&Use themes</string> + </property> + </widget> + <widget class="KListBox"> + <item> + <property name="text"> + <string>default</string> + </property> + </item> + <property name="name"> + <cstring>themeListBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + <widget class="QGroupBox"> + <property name="name"> + <cstring>previewGroupBox</cstring> + </property> + <property name="title"> + <string>Preview</string> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <property name="whatsThis" stdset="0"> + <string>Shows you how the selected theme will look</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>8</number> + </property> + <property name="spacing"> + <number>2</number> + </property> + <widget class="QToolButton" row="0" column="0"> + <property name="name"> + <cstring>previewPrev</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string><</string> + </property> + </widget> + <widget class="QToolButton" row="0" column="1"> + <property name="name"> + <cstring>previewPlay</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>></string> + </property> + </widget> + <widget class="QToolButton" row="0" column="2"> + <property name="name"> + <cstring>previewPause</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>o</string> + </property> + </widget> + <widget class="QToolButton" row="0" column="3"> + <property name="name"> + <cstring>previewStop</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>O</string> + </property> + </widget> + <widget class="QToolButton" row="0" column="4"> + <property name="name"> + <cstring>previewNext</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>></string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer1_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> + </widget> + </widget> + </hbox> +</widget> +<customwidgets> +</customwidgets> +<includes> + <include location="local" impldecl="in implementation"></include> + <include location="local" impldecl="in declaration"></include> + <include location="global" impldecl="in declaration">knuminput.h</include> + <include location="global" impldecl="in declaration">klistview.h</include> + <include location="global" impldecl="in declaration">klistbox.h</include> +</includes> +<signals> + <signal>toggled(bool)</signal> +</signals> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klistbox.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>klistbox.h</includehint> +</includehints> +</UI> diff --git a/kicker-applets/mediacontrol/mediacontroliface.h b/kicker-applets/mediacontrol/mediacontroliface.h new file mode 100644 index 0000000..5a47fb3 --- /dev/null +++ b/kicker-applets/mediacontrol/mediacontroliface.h @@ -0,0 +1,31 @@ +/*************************************************************************** + dcopinterface for mediacontrol + mainly used to be informed about new settings + ------------------- + begin : Mon Jan 15 21:09:00 MEZ 2001 + copyright : (C) 2001 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef MEDIACONTROLIFACE_H +#define MEDIACONTROLIFACE_H + +#include <dcopobject.h> + +class MediaControlIface : virtual public DCOPObject +{ + K_DCOP + + k_dcop: + virtual void reparseConfig() = 0; +}; + +#endif // MEDIACONTROLIFACE_H diff --git a/kicker-applets/mediacontrol/mpdInterface.cpp b/kicker-applets/mediacontrol/mpdInterface.cpp new file mode 100644 index 0000000..8027f82 --- /dev/null +++ b/kicker-applets/mediacontrol/mpdInterface.cpp @@ -0,0 +1,585 @@ +/*************************************************************************** + Interface to access mpd + ------------------- + begin : Tue Apr 19 18:31:00 BST 2005 + copyright : (C) 2005 by William Robinson + 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "mpdInterface.h" + +#include <cstring> + +#include <qregexp.h> + +#include <kmessagebox.h> +#include <kdebug.h> +#include <kurldrag.h> + +MpdInterface::MpdInterface() +: PlayerInterface() +, sock() +, sock_mutex() +, messagebox_mutex() +, hostname("localhost") +, port(6600) +, slider_timer(0) +, reconnect_timer(0) +{ + connect(&sock, SIGNAL(error(int)), this, SLOT(connectionError(int))); + connect(&sock, SIGNAL(error(int)), this, SLOT(stopSliderClock())); + + connect(&sock, SIGNAL(connected()), this, SLOT(startSliderClock())); + connect(&sock, SIGNAL(connected()), this, SLOT(stopReconnectClock())); + connect(&sock, SIGNAL(connected()), this, SLOT(connected())); + + connect(&sock, SIGNAL(connectionClosed()), this, SLOT(stopSliderClock())); + connect(&sock, SIGNAL(connectionClosed()), this, SLOT(startReconnectClock())); + connect(&sock, SIGNAL(connectionClosed()), this, SIGNAL(playerStopped())); + + reconnect(); +} + +MpdInterface::~MpdInterface() +{ +} + +void MpdInterface::startSliderClock() +{ + if (!slider_timer) + { + //kdDebug(90200) << "Starting slider clock\n"; + slider_timer = startTimer(SLIDER_TIMER_INTERVAL); + } +} + +void MpdInterface::stopSliderClock() +{ + if (slider_timer) + { + //kdDebug(90200) << "Stopping slider clock\n"; + killTimer(slider_timer); + slider_timer=0; + } +} +void MpdInterface::startReconnectClock() +{ + if (!reconnect_timer) + { + //kdDebug(90200) << "Starting Reconnect clock\n"; + reconnect_timer = startTimer(RECONNECT_TIMER_INTERVAL); + } +} + +void MpdInterface::stopReconnectClock() +{ + if (reconnect_timer) + { + //kdDebug(90200) << "Stopping Reconnect clock\n"; + killTimer(reconnect_timer); + reconnect_timer=0; + } +} + + +void MpdInterface::timerEvent(QTimerEvent* te) +{ + if (te->timerId() == slider_timer) updateSlider(); + else if (te->timerId() == reconnect_timer) reconnect(); +} + + +void MpdInterface::reconnect() const +{ + if (sock.state()==QSocket::Idle) + { + sock_mutex.tryLock(); + //kdDebug(90200) << "Connecting to " << hostname.latin1() << ":" << port << "...\n"; + sock.connectToHost(hostname,port); + } +} + +void MpdInterface::connected() +{ + if (fetchOk()) // unlocks + { + //kdDebug(90200) << "Connected ok\n"; + emit playerStarted(); + emit playingStatusChanged(playingStatus()); + } + else + { + //kdDebug(90200) << "Connection error\n"; + emit playerStopped(); + } +} + +void MpdInterface::connectionError(int e) +{ + sock_mutex.unlock(); + emit playerStopped(); + QString message; + if (messagebox_mutex.tryLock()) + { + switch (e) + { + case QSocket::ErrConnectionRefused: + message=i18n("Connection refused to %1:%2.\nIs mpd running?").arg(hostname).arg(port); + break; + case QSocket::ErrHostNotFound: + message=i18n("Host '%1' not found.").arg(hostname); + break; + case QSocket::ErrSocketRead: + message=i18n("Error reading socket."); + break; + default: + message=i18n("Connection error"); + break; + } + // :TODO: KSimpleConfig to prompt for hostname/port values ? + if (KMessageBox::warningContinueCancel( 0, message, + i18n("MediaControl MPD Error"), + i18n("Reconnect"))==KMessageBox::Continue) + { + startReconnectClock(); + } + else + { + stopReconnectClock(); + } + messagebox_mutex.unlock(); + } +} + +bool MpdInterface::dispatch(const char* cmd) const +{ + if (sock.state()==QSocket::Connected && sock_mutex.tryLock()) + { + long cmd_len=strlen(cmd); + //kdDebug(90200) << "sending: " << cmd; + long written=sock.writeBlock(cmd,cmd_len); + if (written==cmd_len) + { + //kdDebug(90200) << "All bytes written\n"; + sock.flush(); + return true; + } + else + { + //kdDebug(90200) << written << '/' << cmd_len << " bytes written\n"; + } + sock.flush(); + } + return false; +} + +bool MpdInterface::fetchLine(QString& res) const +{ + QString errormessage; + while (sock.state()==QSocket::Connected) + { + if (!sock.canReadLine()) + { + sock.waitForMore(20); + continue; + } + res=sock.readLine().stripWhiteSpace(); + //kdDebug(90200) << "received: " << res.latin1() << "\n"; + if (res.startsWith("OK")) + { + sock_mutex.unlock(); + // if theres a message and we clear it and there's no other messagebox + if (!errormessage.isEmpty() + && dispatch("clearerror\n") && fetchOk() + && messagebox_mutex.tryLock()) + { + KMessageBox::error(0,errormessage,i18n("MediaControl MPD Error")); + messagebox_mutex.unlock(); + } + return false; + } + else if (res.startsWith("ACK")) + { + sock_mutex.unlock(); + return false; + } + else if (res.startsWith("error: ")) + { + errormessage=i18n(res.latin1()); + } + else + { + return true; + } + } + sock_mutex.unlock(); + return false; +} + +bool MpdInterface::fetchOk() const +{ + QString res; + while (fetchLine(res)) { } + if (res.startsWith("OK")) + return true; + else + return false; +} + +void MpdInterface::updateSlider() +{ + //kdDebug(90200) << "update slider\n"; + if (!dispatch("status\n")) return; + + QString res; + QRegExp time_re("time: (\\d+):(\\d+)"); + while(fetchLine(res)) + { + if (res.startsWith("state: ")) + { + if (res.endsWith("play")) + { + emit playingStatusChanged(Playing); + } + else if (res.endsWith("pause")) + { + emit playingStatusChanged(Paused); + } + else + { + emit playingStatusChanged(Stopped); + } + } + else if (time_re.search(res)>=0) + { + QStringList timeinfo=time_re.capturedTexts(); + timeinfo.pop_front(); + int elapsed_seconds=timeinfo.first().toInt(); + timeinfo.pop_front(); + int total_seconds=timeinfo.first().toInt(); + emit newSliderPosition(total_seconds,elapsed_seconds); + } + } +} + +void MpdInterface::sliderStartDrag() +{ + stopSliderClock(); +} + +void MpdInterface::sliderStopDrag() +{ + startSliderClock(); +} + +void MpdInterface::jumpToTime(int sec) +{ + reconnect(); + if (!dispatch("status\n")) return; + + long songid=-1; + + QString res; + QRegExp songid_re("songid: (\\d+)"); + while(fetchLine(res)) + { + if (songid_re.search(res)>=0) + { + QStringList songidinfo=songid_re.capturedTexts(); + songidinfo.pop_front(); + songid=songidinfo.first().toInt(); + } + } + + if (songid>-1) + { + if (dispatch(QString("seekid %1 %2\n").arg(songid).arg(sec).latin1())) + { + fetchOk(); // unlocks + } + } +} + +void MpdInterface::playpause() +{ + reconnect(); + if (playingStatus()==Stopped ? dispatch("play\n") : dispatch("pause\n")) + { + fetchOk(); + } +} + +void MpdInterface::stop() +{ + reconnect(); + if (dispatch("stop\n")) fetchOk(); +} + +void MpdInterface::next() +{ + reconnect(); + if (dispatch("next\n")) fetchOk(); +} + +void MpdInterface::prev() +{ + reconnect(); + if (dispatch("previous\n")) fetchOk(); +} + + +void MpdInterface::changeVolume(int delta) +{ + reconnect(); + + if (!dispatch("status\n")) return; + + int volume=-1; + + QString res; + QRegExp volume_re("volume: (\\d+)"); + while(fetchLine(res)) + { + if (volume_re.search(res)>=0) + { + QStringList info=volume_re.capturedTexts(); + info.pop_front(); + volume=info.first().toInt(); + } + } + + if (volume>-1) + { + volume+=delta; + if (volume<0) volume=0; + if (volume>100) volume=100; + if (dispatch(QString("setvol %1\n").arg(volume).latin1())) + { + fetchOk(); + } + } +} + +void MpdInterface::volumeUp() +{ + reconnect(); + changeVolume(5); +} + +void MpdInterface::volumeDown() +{ + reconnect(); + changeVolume(-5); +} + +void MpdInterface::dragEnterEvent(QDragEnterEvent* event) +{ + event->accept( KURLDrag::canDecode(event) ); +} + +void MpdInterface::dropEvent(QDropEvent* event) +{ + reconnect(); + + KURL::List list; + if (KURLDrag::decode(event, list)) + { + if (list.count()==1) // just one file dropped + { + // check to see if its in the playlist already + if (dispatch("playlistid\n")) + { + long songid=-1; + QString file; + QString res; + while(fetchLine(res)) + { + QRegExp file_re("file: (.+)"); + QRegExp id_re("Id: (.+)"); + if (file.isEmpty() && file_re.search(res)>=0) + { + QStringList info=file_re.capturedTexts(); + info.pop_front(); + // if the dropped file ends with the same name, record it + if (list.front().path().endsWith(info.first())) + { + file=info.first().toInt(); + } + } + else if (!file.isEmpty() && id_re.search(res)>=0) + { + // when we have the file, pick up the id (file scomes first) + QStringList info=id_re.capturedTexts(); + info.pop_front(); + songid=info.first().toInt(); + fetchOk(); // skip to the end + break; + } + } + + // found song, so lets play it + if (songid>-1) + { + if (dispatch((QString("playid %1\n").arg(songid)).latin1())) + { + if (fetchOk()) list.pop_front(); + return; + } + } + } + } + + // now if we have got this far, just try to add any files + for (KURL::List::const_iterator i = list.constBegin(); i!=list.constEnd(); ++i) + { + if ((*i).isLocalFile()) + { + QStringList path=QStringList::split("/",(*i).path()); + + while (!path.empty()) + { + if (dispatch((QString("add \"") + +path.join("/").replace("\"","\\\"") + +QString("\"\n")).latin1())) + { + if (fetchOk()) break; + } + path.pop_front(); + } + } + else + { + // :TODO: can handle http:// urls but maybe should check port or something + } + } + } +} + +const QString MpdInterface::getTrackTitle() const +{ + QString result; + + reconnect(); + + if (!dispatch("status\n")) return result; + + long songid=-1; + QString res; + while(fetchLine(res)) + { + QRegExp songid_re("songid: (\\d+)"); + if (songid_re.search(res)>=0) + { + QStringList songidinfo=songid_re.capturedTexts(); + songidinfo.pop_front(); + songid=songidinfo.first().toInt(); + } + } + + if (!(songid>-1)) return result; + + if (!dispatch(QString("playlistid %1\n").arg(songid).latin1())) + return result; + + QString artist; + QString album; + QString title; + QString track; + QString file; + while(fetchLine(res)) + { + QRegExp artist_re("Artist: (.+)"); + QRegExp album_re("Album: (.+)"); + QRegExp track_re("Album: (.+)"); + QRegExp title_re("Title: (.+)"); + QRegExp file_re("file: (.+)"); + if (artist_re.search(res)>=0) + { + QStringList info=artist_re.capturedTexts(); + info.pop_front(); + artist=info.first(); + } + else if (album_re.search(res)>=0) + { + QStringList info=album_re.capturedTexts(); + info.pop_front(); + album=info.first(); + } + else if (title_re.search(res)>=0) + { + QStringList info=title_re.capturedTexts(); + info.pop_front(); + title=info.first(); + } + else if (track_re.search(res)>=0) + { + QStringList info=track_re.capturedTexts(); + info.pop_front(); + track=info.first(); + } + else if (file_re.search(res)>=0) + { + QStringList info=file_re.capturedTexts(); + info.pop_front(); + file=info.first(); + } + } + + if (!artist.isEmpty()) + { + if (!title.isEmpty()) + return artist.append(" - ").append(title); + else if (!album.isEmpty()) + return artist.append(" - ").append(album); + } + else if (!title.isEmpty()) + { + if (!album.isEmpty()) + return album.append(" - ").append(title); + else + return title; + } + else if (!album.isEmpty()) + { + if (!track.isEmpty()) + return album.append(" - ").append(track); + else + return album; + } + return i18n("No tags: %1").arg(file); +} + +int MpdInterface::playingStatus() +{ + //kdDebug(90200) << "looking up playing status\n"; + if (!dispatch("status\n")) return Stopped; + + PlayingStatus status=Stopped; + QString res; + while(fetchLine(res)) + { + if (res.startsWith("state: ")) + { + if (res.endsWith("play")) status=Playing; + else if (res.endsWith("pause")) status=Paused; + else status=Stopped; + } + } + + return status; +} + +#include "mpdInterface.moc" diff --git a/kicker-applets/mediacontrol/mpdInterface.h b/kicker-applets/mediacontrol/mpdInterface.h new file mode 100644 index 0000000..d891586 --- /dev/null +++ b/kicker-applets/mediacontrol/mpdInterface.h @@ -0,0 +1,100 @@ +/*************************************************************************** + this is the class to access mpd from + ------------------- + begin : Tue Apr 19 18:31:00 BST 2005 + copyright : (C) 2005 by William Robinson + 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef MPDINTERFACE_H +#define MPDINTERFACE_H + +#include "playerInterface.h" +#include <qtimer.h> +#include <klocale.h> +#include <qsocket.h> +#include <qmutex.h> + +class MpdInterface +: public PlayerInterface +{ + Q_OBJECT + public: + MpdInterface(); + ~MpdInterface(); + + public slots: + virtual void updateSlider(); + virtual void sliderStartDrag(); + virtual void sliderStopDrag(); + virtual void jumpToTime(int sec); + virtual void playpause(); + virtual void stop(); + virtual void next(); + virtual void prev(); + virtual void volumeUp(); + virtual void volumeDown(); + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual const QString getTrackTitle() const; + virtual int playingStatus(); + + void changeVolume(int delta); + + void connectionError(int e); + void connected(); + + void startSliderClock(); + void stopSliderClock(); + + void startReconnectClock(); + void stopReconnectClock(); + + + protected: + virtual void timerEvent(QTimerEvent* te); + + private: + mutable QSocket sock; + mutable QMutex sock_mutex; + + mutable QMutex messagebox_mutex; + + QString hostname; + int port; + + static const int SLIDER_TIMER_INTERVAL = 500; // ms + int slider_timer; + + static const int RECONNECT_TIMER_INTERVAL = 5000; // ms + int reconnect_timer; + + /** starts connecting and returns, if not connected already. */ + void reconnect() const; + + /** this locks the sock sock_mutex. remember to unlock it. */ + bool dispatch(const char* cmd) const; + + /** fetches everything from the sock to the OK and unlocks the mutex. + returns true if OK, false on anything else. */ + bool fetchOk() const; + + /** fetches a line and returns true, or false if OK or ACK (end of + message). Will unlock the sock_mutex on the end of message. */ + bool fetchLine(QString& res) const; +}; + +#endif // MPDINTERFACE_H diff --git a/kicker-applets/mediacontrol/noatunInterface.cpp b/kicker-applets/mediacontrol/noatunInterface.cpp new file mode 100644 index 0000000..f6cdfc8 --- /dev/null +++ b/kicker-applets/mediacontrol/noatunInterface.cpp @@ -0,0 +1,283 @@ +/*************************************************************************** + Interface to access Noatun + ------------------- + begin : Mon Jan 15 21:09:00 CEST 2001 + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "noatunInterface.h" +#include "noatunInterface.moc" + +#include <kapplication.h> +#include <kdebug.h> +#include <qstringlist.h> +#include <qstrlist.h> +#include <kurldrag.h> + +#define TIMER_FAST 250 + +NoatunInterface::NoatunInterface() : PlayerInterface() +{ + mTimerValue = TIMER_FAST; + mNoatunTimer = new QTimer(this, "mNoatunTimer"); + + connect(mNoatunTimer, SIGNAL(timeout()), SLOT(updateSlider())); + + connect(kapp->dcopClient(), SIGNAL(applicationRegistered(const QCString&)), + SLOT(appRegistered(const QCString&)) ); + + connect(kapp->dcopClient(), SIGNAL(applicationRemoved(const QCString&)), + SLOT(appRemoved(const QCString&))); + + kapp->dcopClient()->setNotifications(true); + QTimer::singleShot(0, this, SLOT(myInit())); +} + +NoatunInterface::~NoatunInterface() +{ + kapp->dcopClient()->setNotifications(false); +} + +void NoatunInterface::myInit() +{ + // Start the timer if noatun is already running + // Needed if user adds applet while running noatun + if ( findRunningNoatun() ) + { + emit playerStarted(); + mNoatunTimer->start(mTimerValue); + } + else + { + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void NoatunInterface::appRegistered(const QCString &appId) +{ + if (appId.contains("noatun",false)) + { + mAppId = appId; + emit playerStarted(); + mNoatunTimer->start(mTimerValue); + } +} + +void NoatunInterface::appRemoved(const QCString &appId) +{ + if (appId.contains("noatun",false)) + { + // is there still another noatun alive? + if (findRunningNoatun()) + return; + mNoatunTimer->stop(); + emit playerStopped(); + emit newSliderPosition(0,0); + } +} + +void NoatunInterface::updateSlider() +{ + // length/time in msecs, -1 means "no playobject in noatun" + int len, time; + QByteArray data, replyData; + QCString replyType; + + if (!kapp->dcopClient()->call(mAppId, "Noatun", "length()", data, replyType, replyData, false, 200)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication Error" << endl; + // -2 is an internal errornumber, might be used later + len = -2; + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> len; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + // -3 is an internal errornumber, might be used later + len = -3; + } + } + + data = 0; + replyData = 0; + replyType = 0; + + if (!kapp->dcopClient()->call(mAppId, "Noatun", "position()", data, + replyType, replyData, false, 200)) + { + //kdDebug(90200) << "mediacontrol: DCOP communication error" << endl; + time = -2; + } + else + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + { + reply >> time; + } + else + { + //kdDebug(90200) << "mediacontrol: unexpected type of DCOP-reply" << endl; + time = -3; + } + } + + if ((time < 0) || (len < 0)) // Noatun isn't playing and thus returns -1 + { + len = 0; + time = 0; + } + emit newSliderPosition(len/1000,time/1000); + emit playingStatusChanged(playingStatus()); +} + +int NoatunInterface::playingStatus() +{ + QByteArray data, replyData; + QCString replyType; + + if (!kapp->dcopClient()->call(mAppId, "Noatun", "state()", data, replyType, + replyData, false, 200)) + { + return Stopped; + } + else + { + int status = 0; + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "int") + reply >> status; + + if (status == 1) + return Paused; + else if (status == 2) + return Playing; + else + return Stopped; + } +} + + +// Drag-n-Drop stuff ================================================================= + +void NoatunInterface::dragEnterEvent(QDragEnterEvent* event) +{ +// kdDebug(90200) << "NoatunInterface::dragEnterEvent()" << endl; + event->accept(KURLDrag::canDecode(event)); +} + +void NoatunInterface::dropEvent(QDropEvent* event) +{ +// kdDebug(90200) << "NoatunInterface::dropEvent()" << endl; + KURL::List list; + if (KURLDrag::decode(event, list)) + { + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << list.toStringList() << false; + kapp->dcopClient()->send(mAppId, "Noatun", "addFile(QStringList,bool)", data); + } +} + +// ==================================================================================== + +void NoatunInterface::sliderStartDrag() +{ + mNoatunTimer->stop(); +} + +void NoatunInterface::sliderStopDrag() +{ + mNoatunTimer->start(mTimerValue); +} + +void NoatunInterface::jumpToTime(int sec) +{ + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << (sec*1000); // noatun wants milliseconds + kapp->dcopClient()->send(mAppId, "Noatun", "skipTo(int)", data); +} + +void NoatunInterface::playpause() +{ + if (!findRunningNoatun()) + startPlayer("noatun"); + kapp->dcopClient()->send(mAppId, "Noatun", "playpause()", QString::null); +} + +void NoatunInterface::stop() +{ + kapp->dcopClient()->send(mAppId, "Noatun", "stop()", QString::null); +} + +void NoatunInterface::next() +{ + // fastForward() is noatun from kde2 + //kapp->dcopClient()->send("noatun", "Noatun", "fastForward()", QString::null); + kapp->dcopClient()->send(mAppId, "Noatun", "forward()", QString::null); +} + +void NoatunInterface::prev() +{ + kapp->dcopClient()->send(mAppId, "Noatun", "back()", QString::null); +} + +void NoatunInterface::volumeUp() +{ + kapp->dcopClient()->send(mAppId, "Noatun", "volumeDown()", QString::null); +} + +void NoatunInterface::volumeDown() +{ + kapp->dcopClient()->send(mAppId, "Noatun", "volumeUp()", QString::null); +} + +const QString NoatunInterface::getTrackTitle() const +{ + QString title(""); + QByteArray data, replyData; + QCString replyType; + if (kapp->dcopClient()->call(mAppId, "Noatun", "title()", data, replyType, + replyData, false, 200)) + { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") + reply >> title; + } + return title; +} + +bool NoatunInterface::findRunningNoatun() +{ + // FIXME: what if we have a dcop app named, let's say, 'noatunfrontend'? + QCStringList allApps = kapp->dcopClient()->registeredApplications(); + QValueList<QCString>::const_iterator iterator; + + for (iterator = allApps.constBegin(); iterator != allApps.constEnd(); ++iterator) + { + if ((*iterator).contains("noatun", false)) + { + mAppId = *iterator; + return true; + } + } + return false; +} diff --git a/kicker-applets/mediacontrol/noatunInterface.h b/kicker-applets/mediacontrol/noatunInterface.h new file mode 100644 index 0000000..99191b5 --- /dev/null +++ b/kicker-applets/mediacontrol/noatunInterface.h @@ -0,0 +1,67 @@ +/*************************************************************************** + Interface to access Noatun + ------------------- + begin : Mon Jan 15 21:09:00 MEZ 2001 + copyright : (C) 2001-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef NOATUNINTERFACE_H +#define NOATUNINTERFACE_H + +#include "playerInterface.h" + +#include <kapplication.h> +#include <dcopclient.h> + +#include <qtimer.h> + +class NoatunInterface : public PlayerInterface +{ + Q_OBJECT + public: + NoatunInterface(); + ~NoatunInterface(); + + public slots: + void updateSlider(); + void sliderStartDrag(); + void sliderStopDrag(); + void jumpToTime(int sec); + void playpause(); + void stop(); + void next(); + void prev(); + void volumeUp(); + void volumeDown(); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); + const QString getTrackTitle() const; + void appRegistered(const QCString &appId); + void appRemoved(const QCString &appId); + int playingStatus(); + + void myInit(void); + + private: + QTimer *mNoatunTimer; + int mTimerValue; + QCString mAppId; + + /** + * Tries to find a DCOP registered instance of Noatun + * Stores the name of the first found instance in appId + * @returns true is instance is found, false otherwise + */ + bool findRunningNoatun(); +}; +#endif diff --git a/kicker-applets/mediacontrol/pics/Makefile.am b/kicker-applets/mediacontrol/pics/Makefile.am new file mode 100644 index 0000000..85ecf9b --- /dev/null +++ b/kicker-applets/mediacontrol/pics/Makefile.am @@ -0,0 +1,2 @@ +# Files to install +SUBDIRS= blueish default fulldecent diff --git a/kicker-applets/mediacontrol/pics/blueish/Makefile.am b/kicker-applets/mediacontrol/pics/blueish/Makefile.am new file mode 100644 index 0000000..5f7d372 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/Makefile.am @@ -0,0 +1,4 @@ +# Files to install +pics_DATA = next.png pause.png play.png prev.png stop.png +# This is where it will all be installed +picsdir = $(kde_datadir)/mediacontrol/blueish diff --git a/kicker-applets/mediacontrol/pics/blueish/next.png b/kicker-applets/mediacontrol/pics/blueish/next.png Binary files differnew file mode 100644 index 0000000..260a033 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/next.png diff --git a/kicker-applets/mediacontrol/pics/blueish/pause.png b/kicker-applets/mediacontrol/pics/blueish/pause.png Binary files differnew file mode 100644 index 0000000..4c62dae --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/pause.png diff --git a/kicker-applets/mediacontrol/pics/blueish/play.png b/kicker-applets/mediacontrol/pics/blueish/play.png Binary files differnew file mode 100644 index 0000000..6e85050 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/play.png diff --git a/kicker-applets/mediacontrol/pics/blueish/prev.png b/kicker-applets/mediacontrol/pics/blueish/prev.png Binary files differnew file mode 100644 index 0000000..d4d8640 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/prev.png diff --git a/kicker-applets/mediacontrol/pics/blueish/stop.png b/kicker-applets/mediacontrol/pics/blueish/stop.png Binary files differnew file mode 100644 index 0000000..05b1d33 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/blueish/stop.png diff --git a/kicker-applets/mediacontrol/pics/default/Makefile.am b/kicker-applets/mediacontrol/pics/default/Makefile.am new file mode 100644 index 0000000..0ab094e --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/Makefile.am @@ -0,0 +1,4 @@ +# Files to install +pics_DATA = next.png pause.png play.png prev.png stop.png +# This is where it will all be installed +picsdir = $(kde_datadir)/mediacontrol/default diff --git a/kicker-applets/mediacontrol/pics/default/next.png b/kicker-applets/mediacontrol/pics/default/next.png Binary files differnew file mode 100644 index 0000000..7c47f76 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/next.png diff --git a/kicker-applets/mediacontrol/pics/default/pause.png b/kicker-applets/mediacontrol/pics/default/pause.png Binary files differnew file mode 100644 index 0000000..6f51172 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/pause.png diff --git a/kicker-applets/mediacontrol/pics/default/play.png b/kicker-applets/mediacontrol/pics/default/play.png Binary files differnew file mode 100644 index 0000000..789065f --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/play.png diff --git a/kicker-applets/mediacontrol/pics/default/prev.png b/kicker-applets/mediacontrol/pics/default/prev.png Binary files differnew file mode 100644 index 0000000..addcfc9 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/prev.png diff --git a/kicker-applets/mediacontrol/pics/default/stop.png b/kicker-applets/mediacontrol/pics/default/stop.png Binary files differnew file mode 100644 index 0000000..e2bf48d --- /dev/null +++ b/kicker-applets/mediacontrol/pics/default/stop.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/Makefile.am b/kicker-applets/mediacontrol/pics/fulldecent/Makefile.am new file mode 100644 index 0000000..6892b15 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/Makefile.am @@ -0,0 +1,4 @@ +# Files to install +pics_DATA = next.png pause.png play.png prev.png stop.png +# This is where it will all be installed +picsdir = $(kde_datadir)/mediacontrol/fulldecent diff --git a/kicker-applets/mediacontrol/pics/fulldecent/README b/kicker-applets/mediacontrol/pics/fulldecent/README new file mode 100644 index 0000000..17fadd0 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/README @@ -0,0 +1,12 @@ +# +# "Sketchy" mediacontrol theme +# (c) 2003 Will Entriken "Full Decent" +# + +This theme is was drawn freehand with GIMP, the original layered gimp file +is included as an XCF file for your modifying pleasure. + +The artwork is released under the terms of the GNU GPL version 2. +The license is available at http://www.gnu.org + +Hope you enjoy!
\ No newline at end of file diff --git a/kicker-applets/mediacontrol/pics/fulldecent/next.png b/kicker-applets/mediacontrol/pics/fulldecent/next.png Binary files differnew file mode 100644 index 0000000..e833248 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/next.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/pause.png b/kicker-applets/mediacontrol/pics/fulldecent/pause.png Binary files differnew file mode 100644 index 0000000..2fb8572 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/pause.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/play.png b/kicker-applets/mediacontrol/pics/fulldecent/play.png Binary files differnew file mode 100644 index 0000000..836c46e --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/play.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/prev.png b/kicker-applets/mediacontrol/pics/fulldecent/prev.png Binary files differnew file mode 100644 index 0000000..7e24e76 --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/prev.png diff --git a/kicker-applets/mediacontrol/pics/fulldecent/source.xcf b/kicker-applets/mediacontrol/pics/fulldecent/source.xcf Binary files differnew file mode 100644 index 0000000..712236a --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/source.xcf diff --git a/kicker-applets/mediacontrol/pics/fulldecent/stop.png b/kicker-applets/mediacontrol/pics/fulldecent/stop.png Binary files differnew file mode 100644 index 0000000..dc26b5f --- /dev/null +++ b/kicker-applets/mediacontrol/pics/fulldecent/stop.png diff --git a/kicker-applets/mediacontrol/playerInterface.cpp b/kicker-applets/mediacontrol/playerInterface.cpp new file mode 100644 index 0000000..cc388c0 --- /dev/null +++ b/kicker-applets/mediacontrol/playerInterface.cpp @@ -0,0 +1,34 @@ +/*************************************************************************** + this is the abstract class to access a player from + ------------------- + begin : Mon Jan 15 21:09:00 CEST 2001 + copyright : (C) 2001-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "playerInterface.h" +#include "playerInterface.moc" +#include <kapplication.h> +#include <kmessagebox.h> +#include <klocale.h> + +PlayerInterface::PlayerInterface() { } // Constructor +PlayerInterface::~PlayerInterface() { } // Destructor + +void PlayerInterface::startPlayer(const QString &desktopname) +{ + if (KApplication::startServiceByDesktopName(desktopname, QStringList(), + 0, 0, 0, "", false) > 0) + { + KMessageBox::error(0, i18n("Could not start media player.")); + } +} diff --git a/kicker-applets/mediacontrol/playerInterface.h b/kicker-applets/mediacontrol/playerInterface.h new file mode 100644 index 0000000..aa4701e --- /dev/null +++ b/kicker-applets/mediacontrol/playerInterface.h @@ -0,0 +1,57 @@ +/*************************************************************************** + this is the abstract class to access a player from + ------------------- + begin : Mon Jan 15 21:09:00 MEZ 2001 + copyright : (C) 2001 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef PLAYERINTERFACE_H +#define PLAYERINTERFACE_H + +#include <qobject.h> +#include <qdragobject.h> + +class PlayerInterface : public QObject +{ + Q_OBJECT + public: + PlayerInterface(); + virtual ~PlayerInterface(); + + enum PlayingStatus { Stopped=0, Playing, Paused }; + + public slots: + virtual void updateSlider()=0; // gets called on timer-timeout + virtual void sliderStartDrag()=0; + virtual void sliderStopDrag()=0; + virtual void jumpToTime( int msec )=0; + virtual void playpause()=0; + virtual void stop()=0; + virtual void next()=0; + virtual void prev()=0; + virtual void volumeUp()=0; + virtual void volumeDown()=0; + virtual void dragEnterEvent(QDragEnterEvent* event)=0; + virtual void dropEvent(QDropEvent* event)=0; + virtual const QString getTrackTitle() const=0; + virtual int playingStatus()=0; + + void startPlayer(const QString &desktopname); + + signals: + void newSliderPosition(int, int); + void playingStatusChanged(int); + void playerStarted(); + void playerStopped(); +}; +#endif diff --git a/kicker-applets/mediacontrol/simplebutton.cpp b/kicker-applets/mediacontrol/simplebutton.cpp new file mode 100644 index 0000000..9daa926 --- /dev/null +++ b/kicker-applets/mediacontrol/simplebutton.cpp @@ -0,0 +1,256 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan <[email protected]> + Copyright (C) 2004-2005 Aaron J. Seigo <[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. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "simplebutton.h" + +#include <qpainter.h> +#include <qstyle.h> + +#include <kapplication.h> +#include <kcursor.h> +#include <kdialog.h> +#include <kglobalsettings.h> +#include <kiconeffect.h> +#include <kicontheme.h> +#include <kipc.h> +#include <kstandarddirs.h> + +SimpleButton::SimpleButton(QWidget *parent, const char *name) + : QButton(parent, name), + m_highlight(false), + m_orientation(Qt::Horizontal) +{ + setBackgroundOrigin( AncestorOrigin ); + + connect( kapp, SIGNAL( settingsChanged( int ) ), + SLOT( slotSettingsChanged( int ) ) ); + connect( kapp, SIGNAL( iconChanged( int ) ), + SLOT( slotIconChanged( int ) ) ); + + kapp->addKipcEventMask( KIPC::SettingsChanged ); + kapp->addKipcEventMask( KIPC::IconChanged ); + + slotSettingsChanged( KApplication::SETTINGS_MOUSE ); +} + +void SimpleButton::setPixmap(const QPixmap &pix) +{ + QButton::setPixmap(pix); + generateIcons(); + update(); +} + +void SimpleButton::setOrientation(Qt::Orientation orientation) +{ + m_orientation = orientation; + update(); +} + +QSize SimpleButton::sizeHint() const +{ + const QPixmap* pm = pixmap(); + + if (!pm) + return QButton::sizeHint(); + else + return QSize(pm->width() + KDialog::spacingHint(), pm->height() + KDialog::spacingHint()); +} + +QSize SimpleButton::minimumSizeHint() const +{ + const QPixmap* pm = pixmap(); + + if (!pm) + return QButton::minimumSizeHint(); + else + return QSize(pm->width(), pm->height()); +} + +void SimpleButton::drawButton( QPainter *p ) +{ + drawButtonLabel(p); +} + +void SimpleButton::drawButtonLabel( QPainter *p ) +{ + if (!pixmap()) + { + return; + } + + QPixmap pix = isEnabled() ? (m_highlight? m_activeIcon : m_normalIcon) : m_disabledIcon; + + if (isOn() || isDown()) + { + pix = pix.convertToImage().smoothScale(pix.width() - 2, + pix.height() - 2); + } + + int h = height(); + int w = width(); + int ph = pix.height(); + int pw = pix.width(); + int margin = KDialog::spacingHint(); + QPoint origin(margin / 2, margin / 2); + + if (ph < (h - margin)) + { + origin.setY((h - ph) / 2); + } + + if (pw < (w - margin)) + { + origin.setX((w - pw) / 2); + } + + p->drawPixmap(origin, pix); +} + +void SimpleButton::generateIcons() +{ + if (!pixmap()) + { + return; + } + + QImage image = pixmap()->convertToImage(); + KIconEffect effect; + + m_normalIcon = effect.apply(image, KIcon::Panel, KIcon::DefaultState); + m_activeIcon = effect.apply(image, KIcon::Panel, KIcon::ActiveState); + m_disabledIcon = effect.apply(image, KIcon::Panel, KIcon::DisabledState); + + updateGeometry(); +} + +void SimpleButton::slotSettingsChanged(int category) +{ + if (category != KApplication::SETTINGS_MOUSE) + { + return; + } + + bool changeCursor = KGlobalSettings::changeCursorOverIcon(); + + if (changeCursor) + { + setCursor(KCursor::handCursor()); + } + else + { + unsetCursor(); + } +} + +void SimpleButton::slotIconChanged( int group ) +{ + if (group != KIcon::Panel) + { + return; + } + + generateIcons(); + update(); +} + +void SimpleButton::enterEvent( QEvent *e ) +{ + m_highlight = true; + + repaint( false ); + QButton::enterEvent( e ); +} + +void SimpleButton::leaveEvent( QEvent *e ) +{ + m_highlight = false; + + repaint( false ); + QButton::enterEvent( e ); +} + +void SimpleButton::resizeEvent( QResizeEvent * ) +{ + generateIcons(); +} + + +SimpleArrowButton::SimpleArrowButton(QWidget *parent, Qt::ArrowType arrow, const char *name) + : SimpleButton(parent, name) +{ + setBackgroundOrigin(AncestorOrigin); + _arrow = arrow; + _inside = false; +} + +QSize SimpleArrowButton::sizeHint() const +{ + return QSize( 12, 12 ); +} + +void SimpleArrowButton::setArrowType(Qt::ArrowType a) +{ + if (_arrow != a) + { + _arrow = a; + update(); + } +} + +Qt::ArrowType SimpleArrowButton::arrowType() const +{ + return _arrow; +} + +void SimpleArrowButton::drawButton( QPainter *p ) +{ + QRect r(1, 1, width() - 2, height() - 2); + + QStyle::PrimitiveElement pe = QStyle::PE_ArrowLeft; + switch (_arrow) + { + case Qt::LeftArrow: pe = QStyle::PE_ArrowLeft; break; + case Qt::RightArrow: pe = QStyle::PE_ArrowRight; break; + case Qt::UpArrow: pe = QStyle::PE_ArrowUp; break; + case Qt::DownArrow: pe = QStyle::PE_ArrowDown; break; + } + + int flags = QStyle::Style_Default | QStyle::Style_Enabled; + if (isDown() || isOn()) flags |= QStyle::Style_Down; + style().drawPrimitive(pe, p, r, colorGroup(), flags); +} + +void SimpleArrowButton::enterEvent( QEvent *e ) +{ + _inside = true; + SimpleButton::enterEvent( e ); + update(); +} + +void SimpleArrowButton::leaveEvent( QEvent *e ) +{ + _inside = false; + SimpleButton::enterEvent( e ); + update(); +} + +#include "simplebutton.moc" + +// vim:ts=4:sw=4:et diff --git a/kicker-applets/mediacontrol/simplebutton.h b/kicker-applets/mediacontrol/simplebutton.h new file mode 100644 index 0000000..5423dff --- /dev/null +++ b/kicker-applets/mediacontrol/simplebutton.h @@ -0,0 +1,89 @@ +/* This file is part of the KDE project + Copyright (C) 2003-2004 Nadeem Hasan <[email protected]> + Copyright (C) 2004-2005 Aaron J. Seigo <[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. + + 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; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SIMPLEBUTTON_H +#define SIMPLEBUTTON_H + +#include <qbutton.h> +#include <qpixmap.h> + +#include <kdemacros.h> + +class KDE_EXPORT SimpleButton : public QButton +{ + Q_OBJECT + + public: + SimpleButton(QWidget *parent, const char *name = 0); + void setPixmap(const QPixmap &pix); + void setOrientation(Qt::Orientation orientaton); + QSize sizeHint() const; + QSize minimumSizeHint() const; + + protected: + void drawButton( QPainter *p ); + void drawButtonLabel( QPainter *p ); + void generateIcons(); + + void enterEvent( QEvent *e ); + void leaveEvent( QEvent *e ); + void resizeEvent( QResizeEvent *e ); + + protected slots: + virtual void slotSettingsChanged( int category ); + virtual void slotIconChanged( int group ); + + private: + bool m_highlight; + QPixmap m_normalIcon; + QPixmap m_activeIcon; + QPixmap m_disabledIcon; + Qt::Orientation m_orientation; + class SimpleButtonPrivate; + SimpleButtonPrivate* d; +}; + +class KDE_EXPORT SimpleArrowButton: public SimpleButton +{ + Q_OBJECT + + public: + SimpleArrowButton(QWidget *parent = 0, Qt::ArrowType arrow = Qt::UpArrow, const char *name = 0); + virtual ~SimpleArrowButton() {}; + QSize sizeHint() const; + + protected: + virtual void enterEvent( QEvent *e ); + virtual void leaveEvent( QEvent *e ); + virtual void drawButton(QPainter *p); + Qt::ArrowType arrowType() const; + + public slots: + void setArrowType(Qt::ArrowType a); + + private: + Qt::ArrowType _arrow; + bool _inside; +}; + + +#endif // HIDEBUTTON_H + +// vim:ts=4:sw=4:et diff --git a/kicker-applets/mediacontrol/xmmsInterface.cpp b/kicker-applets/mediacontrol/xmmsInterface.cpp new file mode 100644 index 0000000..e2512e5 --- /dev/null +++ b/kicker-applets/mediacontrol/xmmsInterface.cpp @@ -0,0 +1,183 @@ +/*************************************************************************** + Interface to access XMMS + ------------------- + begin : Tue Apr 25 11:53:11 CEST 2000 + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_XMMS // only use if there is xmms installed on compiletime + +#include "xmmsInterface.h" +#include "xmmsInterface.moc" +#include <xmms/xmmsctrl.h> +#include <kdebug.h> + +#define TIMER_SLOW 1000 +#define TIMER_FAST 100 +#define XMMS_SESSION 0 + +XmmsInterface::XmmsInterface() : PlayerInterface() +{ + timervalue = TIMER_FAST; + bStartingXMMS = false; + xmms_timer = new QTimer ( this, "xmms_timer" ); + + QObject::connect( xmms_timer, SIGNAL(timeout()), SLOT(updateSlider()) ); + + // Better start the timer as late as possible in initialization + xmms_timer->start ( timervalue ); +} + +XmmsInterface::~XmmsInterface() +{ + delete xmms_timer; +} + +void XmmsInterface::updateSlider ( void ) +{ + if ( !xmms_remote_is_running(XMMS_SESSION) ) + { // XMMS not running + if (timervalue == TIMER_FAST) // timer is running fast + { + emit playerStopped(); + timervalue = TIMER_SLOW; // timer does not need to run fast if XMMS is not running + xmms_timer->changeInterval(timervalue); + emit newSliderPosition(0,0); + } + return; // as XMMS is not running we can leave now + } + + // huh, XMMS is running :) + if (timervalue == TIMER_SLOW) // what? Still running slow? + { + emit playerStarted(); + timervalue = TIMER_FAST; // boost the timer to have better reaction-times for the applet + xmms_timer->changeInterval(timervalue); + } + + int len = xmms_remote_get_playlist_time ( XMMS_SESSION, xmms_remote_get_playlist_pos(XMMS_SESSION) ); + int time = xmms_remote_get_output_time(XMMS_SESSION); + + if (len < 0) + { + len = 0; + time = 0; + } + + emit newSliderPosition(len,time); + emit playingStatusChanged(playingStatus()); +} + + +// Drag-n-Drop stuff ================================================================= + +void XmmsInterface::dragEnterEvent(QDragEnterEvent* event) +{ + event->accept( QTextDrag::canDecode(event) ); +} + +void XmmsInterface::dropEvent(QDropEvent* event) +{ + QString text; +// kdDebug(90200) << "XmmsInterface::dropEvent()" << endl; + if ( QTextDrag::decode(event, text) ) + { + xmms_remote_playlist_add_url_string(XMMS_SESSION, + (gchar *)text.local8Bit().data()); + } +} + +// ==================================================================================== + + +void XmmsInterface::sliderStartDrag() +{ + xmms_timer->stop(); +} + +void XmmsInterface::sliderStopDrag() +{ + xmms_timer->start( timervalue ); +} + +void XmmsInterface::jumpToTime( int msec ) +{ + xmms_remote_jump_to_time(XMMS_SESSION, msec); +} + +void XmmsInterface::playpause() +{ + if (!xmms_remote_is_running(XMMS_SESSION)) + { + if (bStartingXMMS) + return; + startPlayer("xmms"); + bStartingXMMS = true; + QTimer::singleShot(500, this, SLOT(playpause())); + } + else + { + bStartingXMMS = false; + xmms_remote_play_pause(XMMS_SESSION); + } +} + +void XmmsInterface::stop() +{ + xmms_remote_stop(XMMS_SESSION); +} + +void XmmsInterface::next() +{ + xmms_remote_playlist_next(XMMS_SESSION); +} + +void XmmsInterface::prev() +{ + xmms_remote_playlist_prev(XMMS_SESSION); +} + +void XmmsInterface::volumeUp() +{ + const int cur = xmms_remote_get_main_volume(XMMS_SESSION); + xmms_remote_set_main_volume(XMMS_SESSION, cur+1); +} + +void XmmsInterface::volumeDown() +{ + const int cur = xmms_remote_get_main_volume(XMMS_SESSION); + xmms_remote_set_main_volume(XMMS_SESSION, cur-1); +} + +int XmmsInterface::playingStatus() +{ + if (xmms_remote_is_paused(XMMS_SESSION)) + return Paused; + + if (xmms_remote_is_playing(XMMS_SESSION)) + return Playing; + + return Stopped; +} + +const QString XmmsInterface::getTrackTitle() const +{ + return QString::fromLocal8Bit( + xmms_remote_get_playlist_title(XMMS_SESSION, + xmms_remote_get_playlist_pos(XMMS_SESSION))); +} +#endif // HAVE_XMMS diff --git a/kicker-applets/mediacontrol/xmmsInterface.h b/kicker-applets/mediacontrol/xmmsInterface.h new file mode 100644 index 0000000..ca514b2 --- /dev/null +++ b/kicker-applets/mediacontrol/xmmsInterface.h @@ -0,0 +1,59 @@ +/*************************************************************************** + Interface to access XMMS + ------------------- + begin : Tue Apr 25 11:53:11 CEST 2000 + copyright : (C) 2000-2002 by Stefan Gehn + email : metz {AT} gehn {DOT} net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_XMMS // only use if there's xmms installed on compiletime + +#ifndef XMMSINTERFACE_H +#define XMMSINTERFACE_H + +#include "playerInterface.h" +#include <qtimer.h> + +class XmmsInterface : public PlayerInterface +{ + Q_OBJECT + public: + XmmsInterface(); + ~XmmsInterface(); + + public slots: + virtual void updateSlider(); + virtual void sliderStartDrag(); + virtual void sliderStopDrag(); + virtual void jumpToTime(int msec); + virtual void playpause(); + virtual void stop(); + virtual void next(); + virtual void prev(); + virtual void volumeUp(); + virtual void volumeDown(); + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual const QString getTrackTitle() const; + virtual int playingStatus(); + + private: + QTimer *xmms_timer; + int timervalue; + bool bStartingXMMS; +}; +#endif // XMMSINTERFACE_H +#endif // HAVE_XMMS |