Factor out the shared parts of the agent action manager setup.
[kdepim.git] / kalarm / soundpicker.cpp
blobfe68a9fa4d36d39dd9fe9d3cc4ca00885c00f04e
1 /*
2 * soundpicker.cpp - widget to select a sound file or a beep
3 * Program: kalarm
4 * Copyright © 2002-2011 by David Jarvie <djarvie@kde.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "kalarm.h"
23 #include "combobox.h"
24 #include "functions.h"
25 #include "kalarmapp.h"
26 #include "pushbutton.h"
27 #include "sounddlg.h"
28 #include "soundpicker.moc"
30 #include <kglobal.h>
31 #include <klocale.h>
32 #include <kfiledialog.h>
33 #include <kstandarddirs.h>
34 #include <kiconloader.h>
35 #include <khbox.h>
36 #include <phonon/backendcapabilities.h>
37 #include <kdebug.h>
39 #include <QTimer>
40 #include <QLabel>
41 #include <QHBoxLayout>
44 static QMap<Preferences::SoundType, int> indexes; // mapping from sound type to combo index
47 // Collect these widget labels together to ensure consistent wording and
48 // translations across different modules.
49 QString SoundPicker::i18n_label_Sound() { return i18nc("@label:listbox Listbox providing audio options", "Sound:"); }
50 QString SoundPicker::i18n_combo_None() { return i18nc("@item:inlistbox No sound", "None"); }
51 QString SoundPicker::i18n_combo_Beep() { return i18nc("@item:inlistbox", "Beep"); }
52 QString SoundPicker::i18n_combo_Speak() { return i18nc("@item:inlistbox", "Speak"); }
53 QString SoundPicker::i18n_combo_File() { return i18nc("@item:inlistbox", "Sound file"); }
56 SoundPicker::SoundPicker(QWidget* parent)
57 : QFrame(parent),
58 mRevertType(false)
60 QHBoxLayout* soundLayout = new QHBoxLayout(this);
61 soundLayout->setMargin(0);
62 soundLayout->setSpacing(KDialog::spacingHint());
63 mTypeBox = new KHBox(this); // this is to control the QWhatsThis text display area
64 mTypeBox->setMargin(0);
65 mTypeBox->setSpacing(KDialog::spacingHint());
67 QLabel* label = new QLabel(i18n_label_Sound(), mTypeBox);
68 label->setFixedSize(label->sizeHint());
70 // Sound type combo box
71 // The order of combo box entries must correspond with the 'Type' enum.
72 if (indexes.isEmpty())
74 indexes[Preferences::Sound_None] = 0;
75 indexes[Preferences::Sound_Beep] = 1;
76 indexes[Preferences::Sound_File] = 2;
77 indexes[Preferences::Sound_Speak] = 3;
80 mTypeCombo = new ComboBox(mTypeBox);
81 mTypeCombo->addItem(i18n_combo_None()); // index None
82 mTypeCombo->addItem(i18n_combo_Beep()); // index Beep
83 mTypeCombo->addItem(i18n_combo_File()); // index PlayFile
84 mSpeakShowing = !theApp()->speechEnabled();
85 showSpeak(!mSpeakShowing); // index Speak (only displayed if appropriate)
86 connect(mTypeCombo, SIGNAL(activated(int)), SLOT(slotTypeSelected(int)));
87 connect(mTypeCombo, SIGNAL(currentIndexChanged(int)), SIGNAL(changed()));
88 label->setBuddy(mTypeCombo);
89 soundLayout->addWidget(mTypeBox);
91 // Sound file picker button
92 mFilePicker = new PushButton(this);
93 mFilePicker->setIcon(KIcon(SmallIcon("audio-x-generic")));
94 int size = mFilePicker->sizeHint().height();
95 mFilePicker->setFixedSize(size, size);
96 connect(mFilePicker, SIGNAL(clicked()), SLOT(slotPickFile()));
97 mFilePicker->setToolTip(i18nc("@info:tooltip", "Configure sound file"));
98 mFilePicker->setWhatsThis(i18nc("@info:whatsthis", "Configure a sound file to play when the alarm is displayed."));
99 soundLayout->addWidget(mFilePicker);
101 // Initialise the file picker button state and tooltip
102 mTypeCombo->setCurrentIndex(indexes[Preferences::Sound_None]);
103 mFilePicker->setEnabled(false);
106 /******************************************************************************
107 * Set the read-only status of the widget.
109 void SoundPicker::setReadOnly(bool readOnly)
111 // Don't set the sound file picker read-only since it still needs to
112 // display the read-only SoundDlg.
113 mTypeCombo->setReadOnly(readOnly);
114 mReadOnly = readOnly;
117 /******************************************************************************
118 * Show or hide the Speak option.
120 void SoundPicker::showSpeak(bool show)
122 if (!theApp()->speechEnabled())
123 show = false; // speech capability is not installed
124 if (show == mSpeakShowing)
125 return; // no change
126 if (!show && mTypeCombo->currentIndex() == indexes[Preferences::Sound_Speak])
127 mTypeCombo->setCurrentIndex(indexes[Preferences::Sound_None]);
128 if (mTypeCombo->count() == indexes[Preferences::Sound_Speak]+1)
129 mTypeCombo->removeItem(indexes[Preferences::Sound_Speak]); // precaution in case of mix-ups
130 QString whatsThis;
131 QString opt1 = i18nc("@info:whatsthis", "<interface>%1</interface>: the message is displayed silently.", i18n_combo_None());
132 QString opt2 = i18nc("@info:whatsthis", "<interface>%1</interface>: a simple beep is sounded.", i18n_combo_Beep());
133 QString opt3 = i18nc("@info:whatsthis", "<interface>%1</interface>: an audio file is played. You will be prompted to choose the file and set play options.", i18n_combo_File());
134 if (show)
136 mTypeCombo->addItem(i18n_combo_Speak());
137 QString opt4 = i18nc("@info:whatsthis", "<interface>%1</interface>: the message text is spoken.", i18n_combo_Speak());
138 whatsThis = i18nc("@info:whatsthis Combination of multiple whatsthis items",
139 "<para>Choose a sound to play when the message is displayed:"
140 "<list><item>%1</item>"
141 "<item>%2</item>"
142 "<item>%3</item>"
143 "<item>%4</item></list></para>", opt1, opt2, opt3, opt4);
145 else
146 whatsThis = i18nc("@info:whatsthis Combination of multiple whatsthis items",
147 "<para>Choose a sound to play when the message is displayed:"
148 "<list><item>%1</item>"
149 "<item>%2</item>"
150 "<item>%3</item></list></para>", opt1, opt2, opt3);
151 mTypeBox->setWhatsThis(whatsThis);
152 mSpeakShowing = show;
155 /******************************************************************************
156 * Return the currently selected option.
158 Preferences::SoundType SoundPicker::sound() const
160 int current = mTypeCombo->currentIndex();
161 for (QMap<Preferences::SoundType, int>::ConstIterator it = indexes.constBegin(); it != indexes.constEnd(); ++it)
162 if (it.value() == current)
163 return it.key();
164 return Preferences::Sound_None;
167 /******************************************************************************
168 * Return the selected sound file, if the File option is selected.
169 * Returns empty URL if File is not currently selected.
171 KUrl SoundPicker::file() const
173 return (mTypeCombo->currentIndex() == indexes[Preferences::Sound_File]) ? mFile : KUrl();
176 /******************************************************************************
177 * Return the specified volumes (range 0 - 1).
178 * Returns < 0 if beep is currently selected, or if 'set volume' is not selected.
180 float SoundPicker::volume(float& fadeVolume, int& fadeSeconds) const
182 if (mTypeCombo->currentIndex() == indexes[Preferences::Sound_File] && !mFile.isEmpty())
184 fadeVolume = mFadeVolume;
185 fadeSeconds = mFadeSeconds;
186 return mVolume;
188 else
190 fadeVolume = -1;
191 fadeSeconds = 0;
192 return -1;
196 /******************************************************************************
197 * Return the pause between sound file repetitions is selected.
198 * Reply = pause in seconds, or -1 if repetition is not selected or beep is selected.
200 int SoundPicker::repeatPause() const
202 return mTypeCombo->currentIndex() == indexes[Preferences::Sound_File] && !mFile.isEmpty() ? mRepeatPause : -1;
205 /******************************************************************************
206 * Initialise the widget's state.
208 void SoundPicker::set(Preferences::SoundType type, const QString& f, float volume, float fadeVolume, int fadeSeconds, int repeatPause)
210 if (type == Preferences::Sound_File && f.isEmpty())
211 type = Preferences::Sound_Beep;
212 mFile = KUrl(f);
213 mVolume = volume;
214 mFadeVolume = fadeVolume;
215 mFadeSeconds = fadeSeconds;
216 mRepeatPause = repeatPause;
217 mTypeCombo->setCurrentIndex(indexes[type]); // this doesn't trigger slotTypeSelected()
218 mFilePicker->setEnabled(type == Preferences::Sound_File);
219 mTypeCombo->setToolTip(type == Preferences::Sound_File ? mFile.prettyUrl() : QString());
220 mLastType = type;
223 /******************************************************************************
224 * Called when the sound option is changed.
226 void SoundPicker::slotTypeSelected(int id)
228 Preferences::SoundType newType = Preferences::Sound_None;
229 for (QMap<Preferences::SoundType, int>::ConstIterator it = indexes.constBegin(); it != indexes.constEnd(); ++it)
231 if (it.value() == id)
233 newType = it.key();
234 break;
237 if (newType == mLastType || mRevertType)
238 return;
239 if (mLastType == Preferences::Sound_File)
241 mFilePicker->setEnabled(false);
242 mTypeCombo->setToolTip(QString());
244 else if (newType == Preferences::Sound_File)
246 if (mFile.isEmpty())
248 slotPickFile();
249 if (mFile.isEmpty())
250 return; // revert to previously selected type
252 mFilePicker->setEnabled(true);
253 mTypeCombo->setToolTip(mFile.prettyUrl());
255 mLastType = newType;
258 /******************************************************************************
259 * Called when the file picker button is clicked.
261 void SoundPicker::slotPickFile()
263 KUrl oldfile = mFile;
264 KUrl file = mFile;
265 SoundDlg dlg(mFile.prettyUrl(), mVolume, mFadeVolume, mFadeSeconds, mRepeatPause, i18nc("@title:window", "Sound File"), this);
266 dlg.setReadOnly(mReadOnly);
267 bool accepted = (dlg.exec() == QDialog::Accepted);
268 if (mReadOnly)
269 return;
270 if (accepted)
272 float volume, fadeVolume;
273 int fadeTime;
274 dlg.getVolume(volume, fadeVolume, fadeTime);
275 file = dlg.getFile();
276 mRepeatPause = dlg.repeatPause();
277 mVolume = volume;
278 mFadeVolume = fadeVolume;
279 mFadeSeconds = fadeTime;
281 if (!file.isEmpty())
283 mFile = file;
284 mDefaultDir = dlg.defaultDir();
286 if (mFile.isEmpty())
288 // No audio file is selected, so revert to previously selected option
289 #if 0
290 // Remove mRevertType, setLastType(), #include QTimer
291 // But wait a moment until setting the radio button, or it won't work.
292 mRevertType = true; // prevent sound dialog popping up twice
293 QTimer::singleShot(0, this, SLOT(setLastType()));
294 #else
295 mTypeCombo->setCurrentIndex(indexes[mLastType]);
296 #endif
297 mTypeCombo->setToolTip(QString());
299 else
300 mTypeCombo->setToolTip(mFile.prettyUrl());
301 if (accepted || mFile != oldfile)
302 emit changed();
305 /******************************************************************************
306 * Select the previously selected sound type.
308 void SoundPicker::setLastType()
310 mTypeCombo->setCurrentIndex(indexes[mLastType]);
311 mRevertType = false;
314 /******************************************************************************
315 * Display a dialog to choose a sound file, initially highlighting any
316 * specified file. 'initialFile' must be a full path name or URL.
317 * 'defaultDir' is updated to the directory containing the chosen file.
318 * Reply = URL selected. If none is selected, URL.isEmpty() is true.
320 QString SoundPicker::browseFile(QString& defaultDir, const QString& initialFile)
322 static QString kdeSoundDir; // directory containing KDE sound files
323 if (defaultDir.isEmpty())
325 if (kdeSoundDir.isNull())
326 kdeSoundDir = KGlobal::dirs()->findResourceDir("sound", "KDE-Sys-Warning.ogg");
327 defaultDir = kdeSoundDir;
329 QString filter = Phonon::BackendCapabilities::availableMimeTypes().join(" ");
330 return KAlarm::browseFile(i18nc("@title:window", "Choose Sound File"), defaultDir, initialFile, filter, KFile::ExistingOnly, 0);
333 // vim: et sw=4: