summaryrefslogtreecommitdiffstats
path: root/kalarm/soundpicker.cpp
blob: 485f0fdb19863ff6332abe0263566dcf9c0611a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/*
 *  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 <kfiledialog.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.").tqarg("<b>" + i18n_None() + "</b>")
	                  + "<br>" + i18n("%1: a simple beep is sounded.").tqarg("<b>" + i18n_Beep() + "</b>")
	                  + "<br>" + i18n("%1: an audio file is played. You will be prompted to choose the file and set play options.").tqarg("<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.").tqarg("<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 = KGlobal::dirs()->findResourceDir("sound", "KDE_Notify.wav");
		defaultDir = kdeSoundDir;
	}
#ifdef WITHOUT_ARTS
	TQString filter = TQString::fromLatin1("*.wav *.mp3 *.ogg|%1\n*|%2").tqarg(i18n("Sound Files")).tqarg(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");
}