kalarm

soundpicker.cpp

00001 /*
00002  *  soundpicker.cpp  -  widget to select a sound file or a beep
00003  *  Program:  kalarm
00004  *  Copyright © 2002,2004-2006 by David Jarvie <software@astrojar.org.uk>
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License along
00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
00018  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "kalarm.h"
00022 
00023 #include <qlayout.h>
00024 #include <qregexp.h>
00025 #include <qtooltip.h>
00026 #include <qtimer.h>
00027 #include <qlabel.h>
00028 #include <qhbox.h>
00029 #include <qwhatsthis.h>
00030 
00031 #include <kglobal.h>
00032 #include <klocale.h>
00033 #include <kfiledialog.h>
00034 #include <kstandarddirs.h>
00035 #include <kiconloader.h>
00036 #ifndef WITHOUT_ARTS
00037 #include <arts/kplayobjectfactory.h>
00038 #endif
00039 #include <kdebug.h>
00040 
00041 #include "combobox.h"
00042 #include "functions.h"
00043 #include "kalarmapp.h"
00044 #include "pushbutton.h"
00045 #include "sounddlg.h"
00046 #include "soundpicker.moc"
00047 
00048 
00049 // Collect these widget labels together to ensure consistent wording and
00050 // translations across different modules.
00051 QString SoundPicker::i18n_Sound()       { return i18n("An audio sound", "Sound"); }
00052 QString SoundPicker::i18n_None()        { return i18n("None"); }
00053 QString SoundPicker::i18n_Beep()        { return i18n("Beep"); }
00054 QString SoundPicker::i18n_Speak()       { return i18n("Speak"); }
00055 QString SoundPicker::i18n_File()        { return i18n("Sound file"); }
00056 
00057 
00058 SoundPicker::SoundPicker(QWidget* parent, const char* name)
00059     : QFrame(parent, name)
00060 {
00061     setFrameStyle(QFrame::NoFrame);
00062     QHBoxLayout* soundLayout = new QHBoxLayout(this, 0, KDialog::spacingHint());
00063     mTypeBox = new QHBox(this);    // this is to control the QWhatsThis text display area
00064     mTypeBox->setSpacing(KDialog::spacingHint());
00065 
00066     QLabel* label = new QLabel(i18n("An audio sound", "&Sound:"), mTypeBox);
00067     label->setFixedSize(label->sizeHint());
00068 
00069     // Sound type combo box
00070     // The order of combo box entries must correspond with the 'Type' enum.
00071     mTypeCombo = new ComboBox(false, mTypeBox);
00072     mTypeCombo->insertItem(i18n_None());     // index NONE
00073     mTypeCombo->insertItem(i18n_Beep());     // index BEEP
00074     mTypeCombo->insertItem(i18n_File());     // index PLAY_FILE
00075     mSpeakShowing = !theApp()->speechEnabled();
00076     showSpeak(!mSpeakShowing);               // index SPEAK (only displayed if appropriate)
00077     connect(mTypeCombo, SIGNAL(activated(int)), SLOT(slotTypeSelected(int)));
00078     label->setBuddy(mTypeCombo);
00079     soundLayout->addWidget(mTypeBox);
00080 
00081     // Sound file picker button
00082     mFilePicker = new PushButton(this);
00083     mFilePicker->setPixmap(SmallIcon("playsound"));
00084     mFilePicker->setFixedSize(mFilePicker->sizeHint());
00085     connect(mFilePicker, SIGNAL(clicked()), SLOT(slotPickFile()));
00086     QWhatsThis::add(mFilePicker, i18n("Configure a sound file to play when the alarm is displayed."));
00087     soundLayout->addWidget(mFilePicker);
00088 
00089     // Initialise the file picker button state and tooltip
00090     mTypeCombo->setCurrentItem(NONE);
00091     mFilePicker->setEnabled(false);
00092 }
00093 
00094 /******************************************************************************
00095 * Set the read-only status of the widget.
00096 */
00097 void SoundPicker::setReadOnly(bool readOnly)
00098 {
00099     mTypeCombo->setReadOnly(readOnly);
00100 #ifdef WITHOUT_ARTS
00101     mFilePicker->setReadOnly(readOnly);
00102 #endif
00103     mReadOnly = readOnly;
00104 }
00105 
00106 /******************************************************************************
00107 * Show or hide the Speak option.
00108 */
00109 void SoundPicker::showSpeak(bool show)
00110 {
00111     if (!theApp()->speechEnabled())
00112         show = false;    // speech capability is not installed
00113     if (show == mSpeakShowing)
00114         return;    // no change
00115     QString whatsThis = "<p>" + i18n("Choose a sound to play when the message is displayed.")
00116                       + "<br>" + i18n("%1: the message is displayed silently.").arg("<b>" + i18n_None() + "</b>")
00117                       + "<br>" + i18n("%1: a simple beep is sounded.").arg("<b>" + i18n_Beep() + "</b>")
00118                       + "<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>");
00119     if (!show  &&  mTypeCombo->currentItem() == SPEAK)
00120         mTypeCombo->setCurrentItem(NONE);
00121     if (mTypeCombo->count() == SPEAK+1)
00122         mTypeCombo->removeItem(SPEAK);    // precaution in case of mix-ups
00123     if (show)
00124     {
00125         mTypeCombo->insertItem(i18n_Speak());
00126         whatsThis += "<br>" + i18n("%1: the message text is spoken.").arg("<b>" + i18n_Speak() + "</b>") + "</p>";
00127     }
00128     QWhatsThis::add(mTypeBox, whatsThis + "</p>");
00129     mSpeakShowing = show;
00130 }
00131 
00132 /******************************************************************************
00133 * Return the currently selected option.
00134 */
00135 SoundPicker::Type SoundPicker::sound() const
00136 {
00137     return static_cast<SoundPicker::Type>(mTypeCombo->currentItem());
00138 }
00139 
00140 /******************************************************************************
00141 * Return the selected sound file, if the File option is selected.
00142 * Returns null string if File is not currently selected.
00143 */
00144 QString SoundPicker::file() const
00145 {
00146     return (mTypeCombo->currentItem() == PLAY_FILE) ? mFile : QString::null;
00147 }
00148 
00149 /******************************************************************************
00150 * Return the specified volumes (range 0 - 1).
00151 * Returns < 0 if beep is currently selected, or if 'set volume' is not selected.
00152 */
00153 float SoundPicker::volume(float& fadeVolume, int& fadeSeconds) const
00154 {
00155     if (mTypeCombo->currentItem() == PLAY_FILE  &&  !mFile.isEmpty())
00156     {
00157         fadeVolume  = mFadeVolume;
00158         fadeSeconds = mFadeSeconds;
00159         return mVolume;
00160     }
00161     else
00162     {
00163         fadeVolume  = -1;
00164         fadeSeconds = 0;
00165         return -1;
00166     }
00167 }
00168 
00169 /******************************************************************************
00170 * Return whether sound file repetition is selected, if the main checkbox is checked.
00171 * Returns false if beep is currently selected.
00172 */
00173 bool SoundPicker::repeat() const
00174 {
00175     return mTypeCombo->currentItem() == PLAY_FILE  &&  !mFile.isEmpty()  &&  mRepeat;
00176 }
00177 
00178 /******************************************************************************
00179 * Initialise the widget's state.
00180 */
00181 void SoundPicker::set(SoundPicker::Type type, const QString& f, float volume, float fadeVolume, int fadeSeconds, bool repeat)
00182 {
00183     if (type == PLAY_FILE  &&  f.isEmpty())
00184         type = BEEP;
00185     mFile        = f;
00186     mVolume      = volume;
00187     mFadeVolume  = fadeVolume;
00188     mFadeSeconds = fadeSeconds;
00189     mRepeat      = repeat;
00190     QToolTip::add(mFilePicker, mFile);
00191     mTypeCombo->setCurrentItem(type);  // this doesn't trigger slotTypeSelected()
00192     mFilePicker->setEnabled(type == PLAY_FILE);
00193     mLastType = type;
00194 }
00195 
00196 /******************************************************************************
00197 * Called when the sound option is changed.
00198 */
00199 void SoundPicker::slotTypeSelected(int id)
00200 {
00201     Type newType = static_cast<Type>(id);
00202     if (newType == mLastType)
00203         return;
00204     if (mLastType == PLAY_FILE)
00205         mFilePicker->setEnabled(false);
00206     else if (newType == PLAY_FILE)
00207     {
00208         if (mFile.isEmpty())
00209         {
00210             slotPickFile();
00211             if (mFile.isEmpty())
00212                 return;    // revert to previously selected type
00213         }
00214         mFilePicker->setEnabled(true);
00215     }
00216     mLastType = newType;
00217 }
00218 
00219 /******************************************************************************
00220 * Called when the file picker button is clicked.
00221 */
00222 void SoundPicker::slotPickFile()
00223 {
00224 #ifdef WITHOUT_ARTS
00225     QString url = browseFile(mDefaultDir, mFile);
00226     if (!url.isEmpty())
00227         mFile = url;
00228 #else
00229     QString file = mFile;
00230     SoundDlg dlg(mFile, mVolume, mFadeVolume, mFadeSeconds, mRepeat, i18n("Sound File"), this, "soundDlg");
00231     dlg.setReadOnly(mReadOnly);
00232     bool accepted = (dlg.exec() == QDialog::Accepted);
00233     if (mReadOnly)
00234         return;
00235     if (accepted)
00236     {
00237         float volume, fadeVolume;
00238         int   fadeTime;
00239         file         = dlg.getFile();
00240         mRepeat      = dlg.getSettings(volume, fadeVolume, fadeTime);
00241         mVolume      = volume;
00242         mFadeVolume  = fadeVolume;
00243         mFadeSeconds = fadeTime;
00244     }
00245     if (!file.isEmpty())
00246     {
00247         mFile       = file;
00248         mDefaultDir = dlg.defaultDir();
00249     }
00250 #endif
00251     QToolTip::add(mFilePicker, mFile);
00252     if (mFile.isEmpty())
00253     {
00254         // No audio file is selected, so revert to previously selected option
00255         mTypeCombo->setCurrentItem(mLastType);
00256     }
00257 }
00258 
00259 /******************************************************************************
00260 * Display a dialogue to choose a sound file, initially highlighting any
00261 * specified file. 'initialFile' must be a full path name or URL.
00262 * 'defaultDir' is updated to the directory containing the chosen file.
00263 * Reply = URL selected. If none is selected, URL.isEmpty() is true.
00264 */
00265 QString SoundPicker::browseFile(QString& defaultDir, const QString& initialFile)
00266 {
00267     static QString kdeSoundDir;     // directory containing KDE sound files
00268     if (defaultDir.isEmpty())
00269     {
00270         if (kdeSoundDir.isNull())
00271             kdeSoundDir = KGlobal::dirs()->findResourceDir("sound", "KDE_Notify.wav");
00272         defaultDir = kdeSoundDir;
00273     }
00274 #ifdef WITHOUT_ARTS
00275     QString filter = QString::fromLatin1("*.wav *.mp3 *.ogg|%1\n*|%2").arg(i18n("Sound Files")).arg(i18n("All Files"));
00276 #else
00277     QStringList filters = KDE::PlayObjectFactory::mimeTypes();
00278     QString filter = filters.join(" ");
00279 #endif
00280     return KAlarm::browseFile(i18n("Choose Sound File"), defaultDir, initialFile, filter, KFile::ExistingOnly, 0, "pickSoundFile");
00281 }
KDE Home | KDE Accessibility Home | Description of Access Keys