You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/noatun/modules/kjofol-skin/kjtextdisplay.cpp

651 lines
16 KiB

/***************************************************************************
kjtexdisplay.cpp
---------------------------------------------
Displays for time and other things
using fonts provided by KJFont
---------------------------------------------
Maintainer: Stefan Gehn <sgehn@gmx.net>
***************************************************************************/
// local includes
#include "kjtextdisplay.h"
#include "kjfont.h"
#include "kjprefs.h"
// kde includes
#include <tdelocale.h>
#include <kdebug.h>
#include <kpixmap.h>
#include <kurl.h>
#include <krun.h>
#include <kmimemagic.h>
// arts-includes, needed for pitch
#include <artsmodules.h>
#include <arts/reference.h>
#include <arts/soundserver.h>
#include <arts/kmedia2.h>
// noatun includes
#include <noatun/player.h>
#include <noatun/engine.h>
/*******************************************
* KJFilename
*******************************************/
KJFilename::KJFilename(const TQStringList &l, KJLoader *p)
: TQObject(0), KJWidget(p), mBack(0)
{
int x = l[1].toInt();
int y = l[2].toInt();
int xs = l[3].toInt() - x;
int ys = l[4].toInt() - y;
// fix for all those weird skins where the filenamewindow has more
// height than needed for the font
// ( ... usually resulting in garbage on-screen )
if ( ys > (textFont().fontHeight()) )
ys = textFont().fontHeight();
// background under filename-scroller
TQPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
setRect(x,y,xs,ys);
// how far it moves per cycle
// TODO: make that configurable for the user
//mDistance = 1;
// mDistance = (int)(textFont().fontWidth()/2);
readConfig();
prepareString(i18n("Welcome to Noatun").local8Bit());
killTimers();
}
KJFilename::~KJFilename()
{
delete mBack;
}
void KJFilename::paint(TQPainter *p, const TQRect &)
{
TQPixmap temp ( rect().width(), rect().height() );
// draw background into buffer
bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
// draw font into buffer
bitBlt( &temp, 0, 0, &mView, 0, 0, rect().width(), rect().height(), TQt::CopyROP);
// and draw it on screen
bitBlt(p->device(), rect().topLeft(), &temp,
TQRect(0,0,-1,-1), TQt::CopyROP);
}
void KJFilename::timerEvent(TQTimerEvent *)
{
int height = mView.height();
int width = mView.width();
TQBitmap cycleMask ( mDistance, height ); // temporary-space for moving parts of the mask
TQPixmap cycle ( mDistance, height ); // temporary-space for moving parts of the pixmap
TQBitmap newMask ( *mView.mask() ); // save old mask
// copy mask like the same way we're doing it with the pixmap
// a mask does not get copied on a bitblt automatically, we have to do
// it "by hand"
bitBlt(&cycleMask, 0,0, &newMask, 0,0, mDistance, height, TQt::CopyROP);
bitBlt(&newMask, 0,0, &newMask, mDistance, 0, width-mDistance, height, TQt::CopyROP);
bitBlt(&newMask, width-mDistance, 0, &cycleMask, 0,0, mDistance, height, TQt::CopyROP);
bitBlt(&cycle, 0,0, &mView, 0,0, mDistance, height, TQt::CopyROP);
bitBlt(&mView, 0,0, &mView, mDistance, 0, width-mDistance, height, TQt::CopyROP);
bitBlt(&mView, width-mDistance, 0, &cycle, 0,0, mDistance, height, TQt::CopyROP);
// apply the newly created mask
mView.setMask(newMask);
repaint();
}
bool KJFilename::mousePress(const TQPoint &)
{
return true;
}
void KJFilename::mouseRelease(const TQPoint &, bool in)
{
if (!in) // only do something if users is still inside the button
return;
if ( !napp->player()->current() )
return;
KURL dirURL = napp->player()->current().url().upURL();
KMimeMagicResult *result = KMimeMagic::self()->findFileType( dirURL.path() );
// TODO: Maybe test for protocol type?
// if ( napp->player()->current().url().protocol() == "file" )
if ( result->isValid() )
KRun::runURL ( dirURL, result->mimeType() );
}
void KJFilename::readConfig()
{
kdDebug(66666) << "KJFilename::readConfig()" << endl;
mDistance = (int)( textFont().fontWidth() * KJLoader::kjofol->prefs()->titleMovingDistance() );
if ( mDistance <= 0 )
mDistance = 1;
mTimerUpdates = KJLoader::kjofol->prefs()->titleMovingUpdates();
textFont().recalcSysFont();
mLastTitle=""; // invalidate title so it gets repainted on next timeUpdate()
}
void KJFilename::prepareString(const TQCString &str)
{
killTimers(); // i.e. stop timers
mView = textFont().draw(str, rect().width());
startTimer(mTimerUpdates);
}
void KJFilename::timeUpdate(int)
{
if ( !napp->player()->current() ) // just for safety
return;
TQCString title = TQCString( napp->player()->current().title().local8Bit() );
if ( title == mLastTitle )
return;
mLastTitle = title;
TQCString timestring = napp->player()->lengthString().local8Bit();
timestring = timestring.mid(timestring.find('/')+1);
prepareString ( title + " (" + timestring + ") ");
}
TQString KJFilename::tip()
{
if ( !napp->player()->current() ) // just for safety
return i18n("Filename");
else
return napp->player()->current().url().prettyURL();
}
/*******************************************
* KJTime
*******************************************/
KJTime::KJTime(const TQStringList &l, KJLoader *p)
: KJWidget(p), mBack(0)
{
int x = l[1].toInt();
int y = l[2].toInt();
int xs = l[3].toInt() - x;
int ys = l[4].toInt() - y;
// fix for all those weird skins where the timewindow
// has more space than needed for the font
int maxNeededHeight = timeFont().fontHeight();
if ( ys > maxNeededHeight )
ys = maxNeededHeight;
// five digits + spacing between them
int maxNeededWidth = ( 5 *timeFont().fontWidth() ) + ( 4 * timeFont().fontSpacing() );
if ( xs > maxNeededWidth )
xs = maxNeededWidth;
// background under time-display
TQPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
setRect(x,y,xs,ys);
readConfig();
prepareString("00:00");
}
KJTime::~KJTime()
{
delete mBack;
}
void KJTime::paint(TQPainter *p, const TQRect &)
{
// kdDebug(66666) << "KJTime::paint(TQPainter *p, const TQRect &)" << endl;
TQPixmap temp ( rect().width(), rect().height() );
// draw background into buffer
bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
// draw time-display into buffer (that's a pixmap with a mask applied)
bitBlt( &temp, 0, 0, &mTime, 0, 0, rect().width(), rect().height(), TQt::CopyROP);
// and draw it on screen
bitBlt(p->device(), rect().topLeft(), &temp,
TQRect(0,0, rect().width(), rect().height()), TQt::CopyROP);
}
bool KJTime::mousePress(const TQPoint &)
{
return true;
}
void KJTime::mouseRelease(const TQPoint &, bool in)
{
if (!in) // only do something if users is still inside the button
return;
countDown = !countDown;
napp->setDisplayRemaining( countDown );
// KJLoader::kjofol->prefs()->setTimeCountMode( countDown );
}
void KJTime::readConfig()
{
// kdDebug(66666) << "KJTime::readConfig()" << endl;
countDown = napp->displayRemaining();
timeFont().recalcSysFont();
mLastTime=""; // invalidate time so it gets repainted on next timeUpdate()
}
TQString KJTime::lengthString ( void )
{
int pos = 0;
TQString posString;
int secs = 0,
seconds = 0,
minutes = 0,
hours = 0;
if ( countDown )
{ // current remaining time
pos = napp->player()->getLength() - napp->player()->getTime();
}
else
{ // current time
pos = napp->player()->getTime();
}
if ( pos < 0 )
{
posString = "00:00";
}
else
{ // get the position
secs = pos / 1000; // convert milliseconds -> seconds
seconds = secs % 60;
minutes = (secs - seconds) / 60;
hours = minutes / 60;
minutes %= 60; // remove the hours from minutes ;)
// cerr << " " << hours << ":" << minutes << ":" << seconds << endl;
// if ( hours > 0 ) // looks ugly :)
if ( (napp->player()->getLength()/1000) >= 3600 ) // displays hh:mm if file is long
{
posString.sprintf("%d:%.2d", hours, minutes);
}
else // displays mm:ss
{
posString.sprintf("%.2d:%.2d", minutes, seconds);
}
}
return posString;
}
void KJTime::timeUpdate(int)
{
// kdDebug(66666) << "START KJTime::timeUpdate(int)" << endl;
if (!napp->player()->current())
return;
prepareString( (lengthString()).latin1() );
// kdDebug(66666) << "END KJTime::timeUpdate(int)" << endl;
}
void KJTime::prepareString(const TQCString &str)
{
// kdDebug(66666) << "START KJTime::prepareString(const TQCString &str)" << endl;
if ( str == mLastTime )
return;
mLastTime = str;
mTime = timeFont().draw(str, rect().width());
repaint();
// kdDebug(66666) << "END KJTime::prepareString(const TQCString &str)" << endl;
}
TQString KJTime::tip()
{
if ( countDown )
return i18n("Play time left");
else
return i18n("Current play time");
}
/*******************************************
* KJVolumeText
*******************************************/
KJVolumeText::KJVolumeText(const TQStringList &l, KJLoader *p)
: KJWidget(p), mBack(0)
{
int x=l[1].toInt();
int y=l[2].toInt();
int xs=l[3].toInt()-x;
int ys=l[4].toInt()-y;
// fix for all those weird skins where the timewindow has more space than needed for the font
if ( ys > (volumeFont().fontHeight()) )
ys = volumeFont().fontHeight();
// 3 digits for volume (1-100)
// + spaces according to spacing
// + percentage letter (seems to be 1px wider than a normal char)
int tempWidth = (3*volumeFont().fontWidth()) + (2*volumeFont().fontSpacing()) + ((volumeFont().fontWidth()+1));
if ( xs > ( tempWidth ) )
xs = tempWidth;
// background under volumetext-display
TQPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
setRect(x,y,xs,ys);
prepareString("100%");
}
KJVolumeText::~KJVolumeText()
{
delete mBack;
}
void KJVolumeText::paint(TQPainter *p, const TQRect &)
{
TQPixmap temp ( rect().width(), rect().height() );
// draw background into buffer
bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
// draw time-display into buffer
bitBlt( &temp, 0, 0, &mVolume, 0, 0, rect().width(), rect().height(), TQt::CopyROP);
// and draw it on screen
bitBlt(p->device(), rect().topLeft(), &temp,
TQRect(0,0,-1,-1), TQt::CopyROP);
}
bool KJVolumeText::mousePress(const TQPoint &)
{
return false;
}
void KJVolumeText::readConfig()
{
volumeFont().recalcSysFont();
mLastVolume=""; // invalidate value so it gets repainted on next timeUpdate()
}
void KJVolumeText::timeUpdate(int)
{
TQCString volume;
if (!napp->player()->current())
return;
volume.sprintf("%d%%", napp->player()->volume() ); // FIXME: is sprintf safe to use?
prepareString(volume);
}
void KJVolumeText::prepareString(const TQCString &str)
{
if ( str == mLastVolume )
return;
mLastVolume = str;
mVolume = volumeFont().draw(str, rect().width());
repaint();
}
TQString KJVolumeText::tip()
{
return i18n("Volume");
}
/*******************************************
* KJPitchText
*******************************************/
KJPitchText::KJPitchText(const TQStringList &l, KJLoader *p)
: KJWidget(p), mBack(0)
{
int x = l[1].toInt();
int y = l[2].toInt();
int xs = l[3].toInt() - x;
int ys = l[4].toInt() - y;
// fix for all those weird skins where the timewindow has more space than needed for the font
if ( ys > (pitchFont().fontHeight()) )
ys = pitchFont().fontHeight();
// 3 digits for volume (1-100), spaces according to spacing and percentage letter
int tempWidth = (3*pitchFont().fontWidth()) + (2*pitchFont().fontSpacing());
if ( xs > tempWidth )
xs = tempWidth;
// background under time-display
TQPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
setRect(x,y,xs,ys);
prepareString("100");
}
KJPitchText::~KJPitchText()
{
delete mBack;
}
void KJPitchText::paint(TQPainter *p, const TQRect &)
{
TQPixmap temp ( rect().width(), rect().height() );
// draw background into buffer
bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
// draw time-display into buffer
bitBlt( &temp, 0, 0, &mSpeed, 0, 0, rect().width(), rect().height(), TQt::CopyROP);
// and draw it on screen
bitBlt(p->device(), rect().topLeft(), &temp, TQRect(0,0,-1,-1), TQt::CopyROP);
}
bool KJPitchText::mousePress(const TQPoint &)
{
return true;
}
void KJPitchText::mouseRelease(const TQPoint &, bool in)
{
if (!in)
return;
Arts::PlayObject playobject = napp->player()->engine()->playObject();
Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject);
if (pitchable.isNull())
return;
pitchable.speed( 1.00f ); // reset pitch
}
void KJPitchText::readConfig()
{
pitchFont().recalcSysFont();
mLastPitch=""; // invalidate value so it gets repainted on next timeUpdate()
}
void KJPitchText::timeUpdate(int)
{
TQCString speed;
if (!napp->player()->current())
return;
Arts::PlayObject playobject = napp->player()->engine()->playObject();
Arts::PitchablePlayObject pitchable = Arts::DynamicCast(playobject);
if (pitchable.isNull())
return;
speed.setNum ( (int) ((float)pitchable.speed()*(float)100) );
prepareString ( speed );
}
void KJPitchText::prepareString(const TQCString &str)
{
if ( str == mLastPitch )
return;
mLastPitch = str;
mSpeed = pitchFont().draw(str, rect().width());
repaint();
}
TQString KJPitchText::tip()
{
return i18n("Pitch");
}
/*******************************************
* KJFileInfo
*******************************************/
KJFileInfo::KJFileInfo(const TQStringList &l, KJLoader *p)
: KJWidget(p), mBack(0)
{
mInfoType = l[0]; // type of info-display
int x = l[1].toInt();
int y = l[2].toInt();
int xs = l[3].toInt() - x;
int ys = l[4].toInt() - y;
// fix for all those weird skins where the timewindow
// has more space than needed for the font
int maxNeededHeight = timeFont().fontHeight();
if ( ys > maxNeededHeight )
ys = maxNeededHeight;
// five digits + spacing between them
int maxNeededWidth = ( 3 *timeFont().fontWidth() ) + ( 2 * timeFont().fontSpacing() );
if ( xs > maxNeededWidth )
xs = maxNeededWidth;
// background under info-display
TQPixmap tmp = p->pixmap(p->item("backgroundimage")[1]);
mBack = new KPixmap ( TQSize(xs,ys) );
bitBlt( mBack, 0, 0, &tmp, x, y, xs, ys, TQt::CopyROP );
setRect(x,y,xs,ys);
prepareString("");
}
KJFileInfo::~KJFileInfo()
{
delete mBack;
}
void KJFileInfo::paint(TQPainter *p, const TQRect &)
{
TQPixmap temp ( rect().width(), rect().height() );
// draw background into buffer
bitBlt ( &temp, 0, 0, mBack, 0, 0, -1, -1, TQt::CopyROP );
// draw time-display into buffer (that's a pixmap with a mask applied)
bitBlt( &temp, 0, 0, &mTime, 0, 0, rect().width(), rect().height(), TQt::CopyROP);
// and draw it on screen
bitBlt(p->device(), rect().topLeft(), &temp,
TQRect(0,0, rect().width(), rect().height()), TQt::CopyROP);
}
bool KJFileInfo::mousePress(const TQPoint &)
{
return false;
}
void KJFileInfo::readConfig()
{
textFont().recalcSysFont();
mLastTime=""; // invalidate value so it gets repainted on next timeUpdate()
}
void KJFileInfo::timeUpdate(int)
{
if (!napp->player()->current())
return;
const PlaylistItem &item = napp->player()->current();
TQString prop;
if ( mInfoType == "mp3khzwindow" )
{
prop = item.property("samplerate");
prop.truncate(2); // we just want 44 instead of 44100
}
else if ( mInfoType == "mp3kbpswindow" )
{
prop = item.property("bitrate");
}
else // for safety: no infoType we know of
return;
if (prop.isNull())
prop="";
prepareString( prop.latin1() );
}
void KJFileInfo::prepareString(const TQCString &str)
{
if ( str == mLastTime )
return;
mLastTime = str;
mTime = textFont().draw(str, rect().width());
repaint();
}
TQString KJFileInfo::tip()
{
if ( mInfoType == "mp3khzwindow" )
return i18n("Sample rate in kHz");
else if ( mInfoType == "mp3kbpswindow" )
return i18n("Bitrate in kbps");
return TQString();
}
#include "kjtextdisplay.moc"