|
|
|
/*
|
|
|
|
* soundpicker.cpp - widget to select a sound file or a beep
|
|
|
|
* Program: kalarm
|
|
|
|
* Copyright © 2002,2004-2007 by David Jarvie <software@astrojar.org.uk>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kalarm.h"
|
|
|
|
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqhbox.h>
|
|
|
|
#include <tqwhatsthis.h>
|
|
|
|
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <tdefiledialog.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#ifndef WITHOUT_ARTS
|
|
|
|
#include <arts/kplayobjectfactory.h>
|
|
|
|
#endif
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include "combobox.h"
|
|
|
|
#include "functions.h"
|
|
|
|
#include "kalarmapp.h"
|
|
|
|
#include "pushbutton.h"
|
|
|
|
#include "sounddlg.h"
|
|
|
|
#include "soundpicker.moc"
|
|
|
|
|
|
|
|
|
|
|
|
// Collect these widget labels together to ensure consistent wording and
|
|
|
|
// translations across different modules.
|
|
|
|
TQString SoundPicker::i18n_Sound() { return i18n("An audio sound", "Sound"); }
|
|
|
|
TQString SoundPicker::i18n_None() { return i18n("None"); }
|
|
|
|
TQString SoundPicker::i18n_Beep() { return i18n("Beep"); }
|
|
|
|
TQString SoundPicker::i18n_Speak() { return i18n("Speak"); }
|
|
|
|
TQString SoundPicker::i18n_File() { return i18n("Sound file"); }
|
|
|
|
|
|
|
|
|
|
|
|
SoundPicker::SoundPicker(TQWidget* parent, const char* name)
|
|
|
|
: TQFrame(parent, name)
|
|
|
|
{
|
|
|
|
setFrameStyle(TQFrame::NoFrame);
|
|
|
|
TQHBoxLayout* soundLayout = new TQHBoxLayout(this, 0, KDialog::spacingHint());
|
|
|
|
mTypeBox = new TQHBox(this); // this is to control the TQWhatsThis text display area
|
|
|
|
mTypeBox->setSpacing(KDialog::spacingHint());
|
|
|
|
|
|
|
|
TQLabel* label = new TQLabel(i18n("An audio sound", "&Sound:"), mTypeBox);
|
|
|
|
label->setFixedSize(label->sizeHint());
|
|
|
|
|
|
|
|
// Sound type combo box
|
|
|
|
// The order of combo box entries must correspond with the 'Type' enum.
|
|
|
|
mTypeCombo = new ComboBox(false, mTypeBox);
|
|
|
|
mTypeCombo->insertItem(i18n_None()); // index NONE
|
|
|
|
mTypeCombo->insertItem(i18n_Beep()); // index BEEP
|
|
|
|
mTypeCombo->insertItem(i18n_File()); // index PLAY_FILE
|
|
|
|
mSpeakShowing = !theApp()->speechEnabled();
|
|
|
|
showSpeak(!mSpeakShowing); // index SPEAK (only displayed if appropriate)
|
|
|
|
connect(mTypeCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotTypeSelected(int)));
|
|
|
|
label->setBuddy(mTypeCombo);
|
|
|
|
soundLayout->addWidget(mTypeBox);
|
|
|
|
|
|
|
|
// Sound file picker button
|
|
|
|
mFilePicker = new PushButton(this);
|
|
|
|
mFilePicker->setPixmap(SmallIcon("playsound"));
|
|
|
|
mFilePicker->setFixedSize(mFilePicker->sizeHint());
|
|
|
|
connect(mFilePicker, TQT_SIGNAL(clicked()), TQT_SLOT(slotPickFile()));
|
|
|
|
TQToolTip::add(mFilePicker, i18n("Configure sound file"));
|
|
|
|
TQWhatsThis::add(mFilePicker, i18n("Configure a sound file to play when the alarm is displayed."));
|
|
|
|
soundLayout->addWidget(mFilePicker);
|
|
|
|
|
|
|
|
// Initialise the file picker button state and tooltip
|
|
|
|
mTypeCombo->setCurrentItem(NONE);
|
|
|
|
mFilePicker->setEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Set the read-only status of the widget.
|
|
|
|
*/
|
|
|
|
void SoundPicker::setReadOnly(bool readOnly)
|
|
|
|
{
|
|
|
|
mTypeCombo->setReadOnly(readOnly);
|
|
|
|
#ifdef WITHOUT_ARTS
|
|
|
|
mFilePicker->setReadOnly(readOnly);
|
|
|
|
#endif
|
|
|
|
mReadOnly = readOnly;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Show or hide the Speak option.
|
|
|
|
*/
|
|
|
|
void SoundPicker::showSpeak(bool show)
|
|
|
|
{
|
|
|
|
if (!theApp()->speechEnabled())
|
|
|
|
show = false; // speech capability is not installed
|
|
|
|
if (show == mSpeakShowing)
|
|
|
|
return; // no change
|
|
|
|
TQString whatsThis = "<p>" + i18n("Choose a sound to play when the message is displayed.")
|
|
|
|
+ "<br>" + i18n("%1: the message is displayed silently.").arg("<b>" + i18n_None() + "</b>")
|
|
|
|
+ "<br>" + i18n("%1: a simple beep is sounded.").arg("<b>" + i18n_Beep() + "</b>")
|
|
|
|
+ "<br>" + i18n("%1: an audio file is played. You will be prompted to choose the file and set play options.").arg("<b>" + i18n_File() + "</b>");
|
|
|
|
if (!show && mTypeCombo->currentItem() == SPEAK)
|
|
|
|
mTypeCombo->setCurrentItem(NONE);
|
|
|
|
if (mTypeCombo->count() == SPEAK+1)
|
|
|
|
mTypeCombo->removeItem(SPEAK); // precaution in case of mix-ups
|
|
|
|
if (show)
|
|
|
|
{
|
|
|
|
mTypeCombo->insertItem(i18n_Speak());
|
|
|
|
whatsThis += "<br>" + i18n("%1: the message text is spoken.").arg("<b>" + i18n_Speak() + "</b>") + "</p>";
|
|
|
|
}
|
|
|
|
TQWhatsThis::add(mTypeBox, whatsThis + "</p>");
|
|
|
|
mSpeakShowing = show;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Return the currently selected option.
|
|
|
|
*/
|
|
|
|
SoundPicker::Type SoundPicker::sound() const
|
|
|
|
{
|
|
|
|
return static_cast<SoundPicker::Type>(mTypeCombo->currentItem());
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Return the selected sound file, if the File option is selected.
|
|
|
|
* Returns null string if File is not currently selected.
|
|
|
|
*/
|
|
|
|
TQString SoundPicker::file() const
|
|
|
|
{
|
|
|
|
return (mTypeCombo->currentItem() == PLAY_FILE) ? mFile : TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Return the specified volumes (range 0 - 1).
|
|
|
|
* Returns < 0 if beep is currently selected, or if 'set volume' is not selected.
|
|
|
|
*/
|
|
|
|
float SoundPicker::volume(float& fadeVolume, int& fadeSeconds) const
|
|
|
|
{
|
|
|
|
if (mTypeCombo->currentItem() == PLAY_FILE && !mFile.isEmpty())
|
|
|
|
{
|
|
|
|
fadeVolume = mFadeVolume;
|
|
|
|
fadeSeconds = mFadeSeconds;
|
|
|
|
return mVolume;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fadeVolume = -1;
|
|
|
|
fadeSeconds = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Return whether sound file repetition is selected, if the main checkbox is checked.
|
|
|
|
* Returns false if beep is currently selected.
|
|
|
|
*/
|
|
|
|
bool SoundPicker::repeat() const
|
|
|
|
{
|
|
|
|
return mTypeCombo->currentItem() == PLAY_FILE && !mFile.isEmpty() && mRepeat;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Initialise the widget's state.
|
|
|
|
*/
|
|
|
|
void SoundPicker::set(SoundPicker::Type type, const TQString& f, float volume, float fadeVolume, int fadeSeconds, bool repeat)
|
|
|
|
{
|
|
|
|
if (type == PLAY_FILE && f.isEmpty())
|
|
|
|
type = BEEP;
|
|
|
|
mFile = f;
|
|
|
|
mVolume = volume;
|
|
|
|
mFadeVolume = fadeVolume;
|
|
|
|
mFadeSeconds = fadeSeconds;
|
|
|
|
mRepeat = repeat;
|
|
|
|
mTypeCombo->setCurrentItem(type); // this doesn't trigger slotTypeSelected()
|
|
|
|
mFilePicker->setEnabled(type == PLAY_FILE);
|
|
|
|
if (type == PLAY_FILE)
|
|
|
|
TQToolTip::add(mTypeCombo, mFile);
|
|
|
|
else
|
|
|
|
TQToolTip::remove(mTypeCombo);
|
|
|
|
mLastType = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Called when the sound option is changed.
|
|
|
|
*/
|
|
|
|
void SoundPicker::slotTypeSelected(int id)
|
|
|
|
{
|
|
|
|
Type newType = static_cast<Type>(id);
|
|
|
|
if (newType == mLastType)
|
|
|
|
return;
|
|
|
|
TQString tooltip;
|
|
|
|
if (mLastType == PLAY_FILE)
|
|
|
|
{
|
|
|
|
mFilePicker->setEnabled(false);
|
|
|
|
TQToolTip::remove(mTypeCombo);
|
|
|
|
}
|
|
|
|
else if (newType == PLAY_FILE)
|
|
|
|
{
|
|
|
|
if (mFile.isEmpty())
|
|
|
|
{
|
|
|
|
slotPickFile();
|
|
|
|
if (mFile.isEmpty())
|
|
|
|
return; // revert to previously selected type
|
|
|
|
}
|
|
|
|
mFilePicker->setEnabled(true);
|
|
|
|
TQToolTip::add(mTypeCombo, mFile);
|
|
|
|
}
|
|
|
|
mLastType = newType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Called when the file picker button is clicked.
|
|
|
|
*/
|
|
|
|
void SoundPicker::slotPickFile()
|
|
|
|
{
|
|
|
|
#ifdef WITHOUT_ARTS
|
|
|
|
TQString url = browseFile(mDefaultDir, mFile);
|
|
|
|
if (!url.isEmpty())
|
|
|
|
mFile = url;
|
|
|
|
#else
|
|
|
|
TQString file = mFile;
|
|
|
|
SoundDlg dlg(mFile, mVolume, mFadeVolume, mFadeSeconds, mRepeat, i18n("Sound File"), this, "soundDlg");
|
|
|
|
dlg.setReadOnly(mReadOnly);
|
|
|
|
bool accepted = (dlg.exec() == TQDialog::Accepted);
|
|
|
|
if (mReadOnly)
|
|
|
|
return;
|
|
|
|
if (accepted)
|
|
|
|
{
|
|
|
|
float volume, fadeVolume;
|
|
|
|
int fadeTime;
|
|
|
|
file = dlg.getFile();
|
|
|
|
mRepeat = dlg.getSettings(volume, fadeVolume, fadeTime);
|
|
|
|
mVolume = volume;
|
|
|
|
mFadeVolume = fadeVolume;
|
|
|
|
mFadeSeconds = fadeTime;
|
|
|
|
}
|
|
|
|
if (!file.isEmpty())
|
|
|
|
{
|
|
|
|
mFile = file;
|
|
|
|
mDefaultDir = dlg.defaultDir();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (mFile.isEmpty())
|
|
|
|
{
|
|
|
|
// No audio file is selected, so revert to previously selected option
|
|
|
|
mTypeCombo->setCurrentItem(mLastType);
|
|
|
|
TQToolTip::remove(mTypeCombo);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
TQToolTip::add(mTypeCombo, mFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* Display a dialogue to choose a sound file, initially highlighting any
|
|
|
|
* specified file. 'initialFile' must be a full path name or URL.
|
|
|
|
* 'defaultDir' is updated to the directory containing the chosen file.
|
|
|
|
* Reply = URL selected. If none is selected, URL.isEmpty() is true.
|
|
|
|
*/
|
|
|
|
TQString SoundPicker::browseFile(TQString& defaultDir, const TQString& initialFile)
|
|
|
|
{
|
|
|
|
static TQString kdeSoundDir; // directory containing KDE sound files
|
|
|
|
if (defaultDir.isEmpty())
|
|
|
|
{
|
|
|
|
if (kdeSoundDir.isNull())
|
|
|
|
kdeSoundDir = TDEGlobal::dirs()->findResourceDir("sound", "KDE_Notify.wav");
|
|
|
|
defaultDir = kdeSoundDir;
|
|
|
|
}
|
|
|
|
#ifdef WITHOUT_ARTS
|
|
|
|
TQString filter = TQString::fromLatin1("*.wav *.mp3 *.ogg|%1\n*|%2").arg(i18n("Sound Files")).arg(i18n("All Files"));
|
|
|
|
#else
|
|
|
|
TQStringList filters = KDE::PlayObjectFactory::mimeTypes();
|
|
|
|
TQString filter = filters.join(" ");
|
|
|
|
#endif
|
|
|
|
return KAlarm::browseFile(i18n("Choose Sound File"), defaultDir, initialFile, filter, KFile::ExistingOnly, 0, "pickSoundFile");
|
|
|
|
}
|