2 * soundpicker.cpp - widget to select a sound file or a beep
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.
24 #include "functions.h"
25 #include "kalarmapp.h"
26 #include "pushbutton.h"
28 #include "soundpicker.moc"
32 #include <kfiledialog.h>
33 #include <kstandarddirs.h>
34 #include <kiconloader.h>
36 #include <phonon/backendcapabilities.h>
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
)
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
)
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
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());
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>"
143 "<item>%4</item></list></para>", opt1
, opt2
, opt3
, opt4
);
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>"
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
)
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
;
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
;
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());
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
)
237 if (newType
== mLastType
|| mRevertType
)
239 if (mLastType
== Preferences::Sound_File
)
241 mFilePicker
->setEnabled(false);
242 mTypeCombo
->setToolTip(QString());
244 else if (newType
== Preferences::Sound_File
)
250 return; // revert to previously selected type
252 mFilePicker
->setEnabled(true);
253 mTypeCombo
->setToolTip(mFile
.prettyUrl());
258 /******************************************************************************
259 * Called when the file picker button is clicked.
261 void SoundPicker::slotPickFile()
263 KUrl oldfile
= 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
);
272 float volume
, fadeVolume
;
274 dlg
.getVolume(volume
, fadeVolume
, fadeTime
);
275 file
= dlg
.getFile();
276 mRepeatPause
= dlg
.repeatPause();
278 mFadeVolume
= fadeVolume
;
279 mFadeSeconds
= fadeTime
;
284 mDefaultDir
= dlg
.defaultDir();
288 // No audio file is selected, so revert to previously selected option
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()));
295 mTypeCombo
->setCurrentIndex(indexes
[mLastType
]);
297 mTypeCombo
->setToolTip(QString());
300 mTypeCombo
->setToolTip(mFile
.prettyUrl());
301 if (accepted
|| mFile
!= oldfile
)
305 /******************************************************************************
306 * Select the previously selected sound type.
308 void SoundPicker::setLastType()
310 mTypeCombo
->setCurrentIndex(indexes
[mLastType
]);
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);