2
* KMix -- KDE's full featured mini mixer
5
* Copyright (C) 1996-2004 Christian Esken <esken@kde.org>
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Library General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Library General Public License for more details.
17
* You should have received a copy of the GNU Library General Public
18
* License along with this program; if not, write to the Free
19
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
//#define TEST_MIXDEVICE_COMPOSITE
23
#undef TEST_MIXDEVICE_COMPOSITE
25
#ifdef TEST_MIXDEVICE_COMPOSITE
27
#warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28
#warning !!! MIXDEVICE COMPOSITE TESTING IS ACTIVATED !!!
29
#warning !!! THIS IS PRE-ALPHA CODE! !!!
30
#warning !!! DO NOT SHIP KMIX IN THIS STATE !!!
31
#warning !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
36
#include "viewsliders.h"
37
#include "gui/guiprofile.h"
39
#include "mdwslider.h"
40
#include "core/mixdevicecomposite.h"
41
#include "core/mixer.h"
42
#include "verticaltext.h"
49
#include <QVBoxLayout>
50
#include <QHBoxLayout>
51
//#include <QFormLayout>
56
* Generic View implementation. This can hold now all kinds of controls (not just Sliders, as
57
* the class name suggests).
59
ViewSliders::ViewSliders(QWidget* parent, const char* name, Mixer* mixer, ViewBase::ViewFlags vflags, GUIProfile *guiprof, KActionCollection *actColl)
60
: ViewBase(parent, name, mixer, Qt::FramelessWindowHint, vflags, guiprof, actColl)
63
if ( _vflags & ViewBase::Vertical ) {
64
_layoutMDW = new QVBoxLayout(this);
65
_layoutMDW->setAlignment(Qt::AlignLeft|Qt::AlignTop);
66
_layoutSliders = new QVBoxLayout();
67
_layoutSliders->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);
71
_layoutMDW = new QHBoxLayout(this);
72
_layoutMDW->setAlignment(Qt::AlignHCenter|Qt::AlignTop);
73
_layoutSliders = new QHBoxLayout();
74
_layoutSliders->setAlignment(Qt::AlignHCenter|Qt::AlignTop);
75
// Place enums in an own box right from the sliders.
77
_layoutSliders->setContentsMargins(0,0,0,0);
78
_layoutSliders->setSpacing(0);
79
_layoutMDW->setContentsMargins(0,0,0,0);
80
_layoutMDW->setSpacing(0);
81
_layoutMDW->addItem( _layoutSliders );
86
ViewSliders::~ViewSliders()
88
qDeleteAll(_separators);
93
QWidget* ViewSliders::add(MixDevice *md)
96
Qt::Orientation orientation = (_vflags & ViewBase::Vertical) ? Qt::Horizontal : Qt::Vertical;
100
if ( md->isEnum() ) {
102
md, // MixDevice (parameter)
103
orientation, // Orientation
106
, md->controlProfile()
108
if ( _layoutEnum == 0 ) {
109
// lazily creation of Layout for the first enum
110
_layoutEnum = new QVBoxLayout(); // new QFormLayout();
111
_layoutMDW->addLayout( _layoutEnum );
113
_layoutEnum->addWidget(mdw);
116
// add a separator before the device
117
QFrame *_frm = new QFrame(this);
118
if ( orientation == Qt::Vertical)
119
_frm->setFrameStyle(QFrame::VLine | QFrame::Sunken);
121
_frm->setFrameStyle(QFrame::HLine | QFrame::Sunken);
122
_separators.insert(md->id(),_frm);
123
_layoutSliders->addWidget(_frm);
125
md, // MixDevice (parameter)
126
true, // Show Mute LED
127
true, // Show Record LED
129
orientation, // Orientation
132
, md->controlProfile()
134
_layoutSliders->addWidget(mdw);
135
// QHBoxLayout* lay = ::qobject_cast<QHBoxLayout*>(_layoutSliders);
137
// lay->addSpacing(2);
139
// qobject_cast<QVBoxLayout*>(_layoutSliders)->addSpacing(2);
147
void ViewSliders::_setMixSet()
149
const MixSet& mixset = _mixer->getMixSet();
151
if ( _mixer->isDynamic() ) {
152
// We will be recreating our sliders, so make sure we trash all the separators too.
153
qDeleteAll(_separators);
155
// Our _layoutSliders now should only contain spacer widgets from the addSpacing() calls in add() above.
156
// We need to trash those too otherwise all sliders gradually migrate away from the edge :p
158
while ( ( li = _layoutSliders->takeAt(0) ) )
163
#ifdef TEST_MIXDEVICE_COMPOSITE
164
QList<MixDevice*> mds; // For temporary test
167
// This method iterates the controls from the Profile
168
// Each control is checked, whether it is also contained in the mixset, and
169
// applicable for this kind of View. If yes, the control is accepted and inserted.
171
foreach ( ProfControl* control, _guiprof->getControls() )
173
//ProfControl* control = *it;
174
// The TabName of the control matches this View name (!! attention: Better use some ID, due to i18n() )
177
QRegExp idRegexp(control->id);
178
//bool isExactRegexp = control->id.startsWith('^') && control->id.endsWith('$'); // for optimizing
179
//isExactRegexp &= ( ! control->id.contains(".*") ); // For now. Might be removed in the future, as it cannot be done properly !!!
180
//kDebug(67100) << "ViewSliders::setMixSet(): Check GUIProfile id==" << control->id << "\n";
181
// The following for-loop could be simplified by using a std::find_if
182
for ( int i=0; i<mixset.count(); i++ ) {
183
MixDevice *md = mixset[i];
184
if ( md->id().contains(idRegexp) )
186
// Match found (by name)
187
if ( _mixSet->contains( md ) ) continue; // dup check
189
// Now check whether subcontrols match
190
bool subcontrolPlaybackWanted = (control->useSubcontrolPlayback() && md->playbackVolume().hasVolume());
191
bool subcontrolCaptureWanted = (control->useSubcontrolCapture() && md->captureVolume().hasVolume());
192
bool subcontrolEnumWanted = (control->useSubcontrolEnum() && md->isEnum());
193
bool subcontrolWanted = subcontrolPlaybackWanted | subcontrolCaptureWanted | subcontrolEnumWanted;
194
bool splitWanted = control->isSplit();
196
if ( !subcontrolWanted ) continue;
198
md->setControlProfile(control);
199
if ( !control->name.isNull() ) {
200
// Apply the custom name from the profile
201
md->setReadableName(control->name); // @todo: This is the wrong place. It only applies to controls in THIS type of view
203
if ( !control->getSwitchtype().isNull() ) {
204
if ( control->getSwitchtype() == "On" )
205
md->playbackVolume().setSwitchType(Volume::OnSwitch);
206
else if ( control->getSwitchtype() == "Off" )
207
md->playbackVolume().setSwitchType(Volume::OffSwitch);
211
#ifdef TEST_MIXDEVICE_COMPOSITE
212
if ( md->id() == "Front:0" || md->id() == "Surround:0") { mds.append(md); } // For temporary test
216
// We use no "break;" ,as multiple devices could match
217
//if ( isExactRegexp ) break; // Optimize! In this case, we can actually break the loop
219
} // loop for finding a suitable MixDevice
221
// There is something in the Profile, that doesn't correspond to a Mixer control
222
//kDebug(67100) << "ViewSliders::setMixSet(): No such control '" << control->id << "'in the mixer . Please check the GUIProfile\n";
224
} // iteration over all controls from the Profile
226
#ifdef TEST_MIXDEVICE_COMPOSITE
227
// This is currently hardcoded, and instead must be read as usual from the Profile
228
MixDeviceComposite *mdc = new MixDeviceComposite(_mixer, "Composite_Test", mds, "A Composite Control #1", MixDevice::KMIX_COMPOSITE);
229
QString ctlId("Composite_Test");
230
QString ctlMatchAll("*");
231
ProfControl* pctl = new ProfControl(ctlId, ctlMatchAll);
232
mdc->setControlProfile(pctl);
233
_mixSet->append(mdc);
238
void ViewSliders::constructionFinished() {
239
configurationUpdate();
243
void ViewSliders::configurationUpdate() {
244
// Adjust height of top part by setting it to the maximum of all mdw's
245
bool haveCaptureLEDs = false;
247
bool haveMuteButtons = false;
248
for ( int i=0; i<_mdws.count(); i++ ) {
249
MDWSlider* mdw = ::qobject_cast<MDWSlider*>(_mdws[i]);
250
if ( mdw && mdw->isVisibleTo(this) ) {
251
if ( mdw->labelExtentHint() > labelExtent ) labelExtent = mdw->labelExtentHint();
252
haveCaptureLEDs = haveCaptureLEDs || mdw->hasCaptureLED();
253
haveMuteButtons = haveMuteButtons || mdw->hasMuteButton();
256
//kDebug(67100) << "topPartExtent is " << topPartExtent;
257
bool firstVisibleControlFound = false;
258
for ( int i=0; i<_mdws.count(); i++ ) {
259
MDWSlider* mdw = ::qobject_cast<MDWSlider*>(_mdws[i]);
261
mdw->setLabelExtent(labelExtent);
262
mdw->setMuteButtonSpace(haveMuteButtons);
263
mdw->setCaptureLEDSpace(haveCaptureLEDs);
264
bool thisControlIsVisible = mdw->isVisibleTo(this);
265
bool showSeparator = ( firstVisibleControlFound && thisControlIsVisible);
266
if ( _separators.contains( mdw->mixDevice()->id() )) {
267
QFrame* sep = _separators[mdw->mixDevice()->id()];
268
sep->setVisible(showSeparator);
270
if ( thisControlIsVisible ) firstVisibleControlFound=true;
273
_layoutMDW->activate();
276
void ViewSliders::refreshVolumeLevels() {
277
// kDebug(67100) << "ViewSliders::refreshVolumeLevels()\n";
279
for ( int i=0; i<_mdws.count(); i++ ) {
280
QWidget *mdwx = _mdws[i];
282
kError(67100) << "ViewSliders::refreshVolumeLevels(): mdw == 0\n";
283
break; // sanity check (normally the lists are set up correctly)
286
MixDeviceWidget* mdw = ::qobject_cast<MixDeviceWidget*>(mdwx);
287
if ( mdw != 0 ) { // sanity check
289
#ifdef TEST_MIXDEVICE_COMPOSITE
290
// --- start --- The following 4 code lines should be moved to a more
291
// generic place, as it only works in this View. But it
292
// should also work in the ViewDockareaPopup and everywhere else.
293
MixDeviceComposite* mdc = ::qobject_cast<MixDeviceComposite*>(mdw->mixDevice());
303
kError(67100) << "ViewSliders::refreshVolumeLevels(): mdw is not a MixDeviceWidget\n";
304
// no slider. Cannot happen in theory => skip it
310
#include "viewsliders.moc"