mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 19:02:53 +00:00

since Katie requires compiler with C++11 support the shared pointer checks could be ommited Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
460 lines
15 KiB
C++
460 lines
15 KiB
C++
/*
|
|
* KMix -- KDE's full featured mini mixer
|
|
*
|
|
*
|
|
* Copyright (C) 1996-2004 Christian Esken <esken@kde.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library 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 "dialogviewconfiguration.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <QCheckBox>
|
|
#include <QPushButton>
|
|
#include <QLabel>
|
|
#include <QScrollArea>
|
|
#include <QVBoxLayout>
|
|
#include <QGridLayout>
|
|
|
|
#include <kdebug.h>
|
|
#include <kdialog.h>
|
|
#include <klocale.h>
|
|
#include <kvbox.h>
|
|
|
|
#include "gui/guiprofile.h"
|
|
#include "gui/mixdevicewidget.h"
|
|
#include "core/ControlManager.h"
|
|
#include "core/mixdevice.h"
|
|
#include "core/mixer.h"
|
|
|
|
DialogViewConfigurationItem::DialogViewConfigurationItem(QListWidget *parent) :
|
|
QListWidgetItem(parent)
|
|
{
|
|
kDebug() << "DialogViewConfigurationItem() default constructor";
|
|
refreshItem();
|
|
}
|
|
|
|
|
|
|
|
DialogViewConfigurationItem::DialogViewConfigurationItem(QListWidget *parent, QString id, bool shown, QString name, int splitted, const QString& iconName) :
|
|
QListWidgetItem(parent), _id(id), _shown(shown), _name(name), _splitted(splitted), _iconName(iconName)
|
|
{
|
|
refreshItem();
|
|
}
|
|
|
|
void DialogViewConfigurationItem::refreshItem()
|
|
{
|
|
setFlags((flags() | Qt::ItemIsDragEnabled) & ~Qt::ItemIsDropEnabled);
|
|
setText(_name);
|
|
setIcon(KIconLoader::global()->loadIcon( _iconName, KIconLoader::Small, KIconLoader::SizeSmallMedium ) );
|
|
setData(Qt::ToolTipRole, _id); // a hack. I am giving up to do it right
|
|
setData(Qt::DisplayRole, _name);
|
|
}
|
|
|
|
/**
|
|
* Serializer. Used for DnD.
|
|
*/
|
|
static QDataStream & operator<< ( QDataStream & s, const DialogViewConfigurationItem & item ) {
|
|
s << item._id;
|
|
s << item._shown;
|
|
s << item._name;
|
|
s << item._splitted;
|
|
s << item._iconName;
|
|
//kDebug() << "<< serialize << " << s;
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* Deserializer. Used for DnD.
|
|
*/
|
|
static QDataStream & operator>> ( QDataStream & s, DialogViewConfigurationItem & item ) {
|
|
QString id;
|
|
s >> id;
|
|
item._id = id;
|
|
bool shown;
|
|
s >> shown;
|
|
item._shown = shown;
|
|
QString name;
|
|
s >> name;
|
|
item._name = name;
|
|
int splitted;
|
|
s >> splitted;
|
|
item._splitted = splitted;
|
|
QString iconName;
|
|
s >> iconName;
|
|
item._iconName = iconName;
|
|
//kDebug() << ">> deserialize >> " << id << name << iconName;
|
|
return s;
|
|
}
|
|
|
|
DialogViewConfigurationWidget::DialogViewConfigurationWidget(QWidget *parent)
|
|
: QListWidget(parent),
|
|
m_activeList(true)
|
|
{
|
|
setDragDropMode(QAbstractItemView::DragDrop);
|
|
setDropIndicatorShown(true);
|
|
setAcceptDrops(true);
|
|
setSelectionMode(QAbstractItemView::SingleSelection);
|
|
setDragEnabled(true);
|
|
viewport()->setAcceptDrops(true);
|
|
setAlternatingRowColors(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
QMimeData* DialogViewConfigurationWidget::mimeData(const QList<QListWidgetItem*> items) const
|
|
{
|
|
if (items.isEmpty())
|
|
return 0;
|
|
QMimeData* mimedata = new QMimeData();
|
|
|
|
DialogViewConfigurationItem* item = 0;
|
|
QByteArray data;
|
|
{
|
|
QDataStream stream(&data, QIODevice::WriteOnly);
|
|
// we only support single selection
|
|
item = static_cast<DialogViewConfigurationItem *>(items.first());
|
|
stream << *item;
|
|
}
|
|
|
|
bool active = isActiveList();
|
|
mimedata->setData("application/x-kde-action-list", data);
|
|
mimedata->setData("application/x-kde-source-treewidget", active ? "active" : "inactive");
|
|
|
|
return mimedata;
|
|
}
|
|
|
|
bool DialogViewConfigurationWidget::dropMimeData(int index, const QMimeData * mimeData, Qt::DropAction /*action*/)
|
|
{
|
|
const QByteArray data = mimeData->data("application/x-kde-action-list");
|
|
if (data.isEmpty())
|
|
return false;
|
|
QDataStream stream(data);
|
|
const bool sourceIsActiveList = mimeData->data("application/x-kde-source-treewidget") == "active";
|
|
|
|
DialogViewConfigurationItem* item = new DialogViewConfigurationItem(0); // needs parent, use this temporarily
|
|
stream >> *item;
|
|
item->refreshItem();
|
|
emit dropped(this, index, item, sourceIsActiveList);
|
|
return true;
|
|
}
|
|
|
|
DialogViewConfiguration::DialogViewConfiguration( QWidget*, ViewBase& view)
|
|
: KDialog( 0),
|
|
_view(view)
|
|
{
|
|
setCaption( i18n( "Configure Channels" ) );
|
|
setButtons( Ok|Cancel );
|
|
setDefaultButton( Ok );
|
|
frame = new QWidget( this );
|
|
frame->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding);
|
|
|
|
setMainWidget( frame );
|
|
|
|
// The _layout will hold two items: The title and the Drag-n-Drop area
|
|
_layout = new QVBoxLayout(frame );
|
|
_layout->setMargin( 0 );
|
|
_layout->setSpacing(KDialog::spacingHint());
|
|
|
|
// --- HEADER ---
|
|
qlb = new QLabel( i18n("Configuration of the channels. Drag icon to update."), frame );
|
|
_layout->addWidget(qlb);
|
|
|
|
_glayout = new QGridLayout();
|
|
_layout->addLayout(_glayout);
|
|
|
|
_qlw = 0;
|
|
_qlwInactive = 0;
|
|
createPage();
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Drop an item from one list to the other
|
|
*/
|
|
void DialogViewConfiguration::slotDropped ( DialogViewConfigurationWidget* list, int index, DialogViewConfigurationItem* item, bool sourceIsActiveList )
|
|
{
|
|
//kDebug() << "dropped item (index" << index << "): " << item->_id << item->_shown << item->_name << item->_splitted << item->_iconName;
|
|
|
|
if ( list == _qlw ) {
|
|
//DialogViewConfigurationItem* after = index > 0 ? static_cast<DialogViewConfigurationItem *>(list->item(index-1)) : 0;
|
|
|
|
//kDebug() << "after" << after->text() << after->internalTag();
|
|
if ( sourceIsActiveList ) {
|
|
// has been dragged within the active list (moved).
|
|
_qlw->insertItem ( index, item );
|
|
//moveActive(item, after);
|
|
} else {
|
|
// dragged from the inactive list to the active list
|
|
_qlw->insertItem ( index, item );
|
|
//insertActive(item, after, true);
|
|
}
|
|
}
|
|
else if ( list == _qlwInactive ) {
|
|
// has been dragged to the inactive list -> remove from the active list.
|
|
//removeActive(item);
|
|
_qlwInactive->insertItem ( index, item );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void DialogViewConfiguration::addSpacer(int row, int col)
|
|
{
|
|
QWidget *dummy = new QWidget();
|
|
dummy->setFixedWidth(4);
|
|
_glayout->addWidget(dummy,row,col);
|
|
}
|
|
|
|
|
|
void DialogViewConfiguration::moveSelection(DialogViewConfigurationWidget* from, DialogViewConfigurationWidget* to)
|
|
{
|
|
foreach ( QListWidgetItem* item, from->selectedItems() )
|
|
{
|
|
QListWidgetItem *clonedItem = item->clone();
|
|
to->addItem ( clonedItem );
|
|
to->setCurrentItem(clonedItem);
|
|
delete item;
|
|
}
|
|
}
|
|
|
|
void DialogViewConfiguration::moveSelectionToActiveList()
|
|
{
|
|
moveSelection(_qlwInactive, _qlw);
|
|
}
|
|
|
|
void DialogViewConfiguration::moveSelectionToInactiveList()
|
|
{
|
|
moveSelection(_qlw, _qlwInactive);
|
|
}
|
|
|
|
void DialogViewConfiguration::selectionChangedActive()
|
|
{
|
|
// bool activeIsNotEmpty = _qlw->selectedItems().isEmpty();
|
|
moveRightButton->setEnabled(! _qlw->selectedItems().isEmpty());
|
|
moveLeftButton->setEnabled(false);
|
|
}
|
|
|
|
void DialogViewConfiguration::selectionChangedInactive()
|
|
{
|
|
moveLeftButton->setEnabled(! _qlwInactive->selectedItems().isEmpty());
|
|
moveRightButton->setEnabled(false);
|
|
}
|
|
|
|
/**
|
|
* Create basic widgets of the Dialog.
|
|
*/
|
|
void DialogViewConfiguration::createPage()
|
|
{
|
|
QList<QWidget *> &mdws = _view._mdws;
|
|
|
|
QLabel *l1 = new QLabel( i18n("Visible channels") );
|
|
_glayout->addWidget(l1,0,0);
|
|
|
|
QLabel *l2 = new QLabel( i18n("Available channels") );
|
|
_glayout->addWidget(l2,0,6);
|
|
|
|
_qlwInactive = new DialogViewConfigurationWidget(frame);
|
|
_qlwInactive->setDragDropMode(QAbstractItemView::DragDrop);
|
|
_qlwInactive->setActiveList(false);
|
|
_glayout->addWidget(_qlwInactive,1,6);
|
|
connect(_qlwInactive, SIGNAL(dropped(DialogViewConfigurationWidget*,int,DialogViewConfigurationItem*,bool)),
|
|
this , SLOT(slotDropped(DialogViewConfigurationWidget*,int,DialogViewConfigurationItem*,bool)));
|
|
|
|
addSpacer(1,1);
|
|
const KIcon& icon = KIcon( QLatin1String( "arrow-left" ));
|
|
moveLeftButton = new QPushButton(icon, "");
|
|
moveLeftButton->setEnabled(false);
|
|
_glayout->addWidget(moveLeftButton,1,2);
|
|
connect(moveLeftButton, SIGNAL(clicked(bool)), SLOT(moveSelectionToActiveList()));
|
|
addSpacer(1,3);
|
|
|
|
const KIcon& icon2 = KIcon( QLatin1String( "arrow-right" ));
|
|
moveRightButton = new QPushButton(icon2, "");
|
|
moveRightButton->setEnabled(false);
|
|
_glayout->addWidget(moveRightButton,1,4);
|
|
connect(moveRightButton, SIGNAL(clicked(bool)), SLOT(moveSelectionToInactiveList()));
|
|
addSpacer(1,5);
|
|
|
|
_qlw = new DialogViewConfigurationWidget(frame);
|
|
_glayout->addWidget(_qlw,1,0);
|
|
connect(_qlw , SIGNAL(dropped(DialogViewConfigurationWidget*,int,DialogViewConfigurationItem*,bool)),
|
|
this , SLOT(slotDropped(DialogViewConfigurationWidget*,int,DialogViewConfigurationItem*,bool)));
|
|
|
|
// --- CONTROLS IN THE GRID ------------------------------------
|
|
//QPalette::ColorRole bgRole;
|
|
for ( int i=0; i<mdws.count(); ++i )
|
|
{
|
|
//if ( i%2 == 0) bgRole = QPalette::Base; else bgRole = QPalette::AlternateBase;
|
|
QWidget *qw = mdws[i];
|
|
if ( qw->inherits("MixDeviceWidget") ) {
|
|
MixDeviceWidget *mdw = static_cast<MixDeviceWidget*>(qw);
|
|
std::shared_ptr<MixDevice> md = mdw->mixDevice();
|
|
QString mdName = md->readableName();
|
|
|
|
int splitted = -1;
|
|
if ( ! md->isEnum() ) {
|
|
splitted = ( md->playbackVolume().count() > 1) || ( md->captureVolume().count() > 1 ) ;
|
|
}
|
|
|
|
//kDebug() << "add DialogViewConfigurationItem: " << mdName << " visible=" << mdw->isVisible() << "splitted=" << splitted;
|
|
if ( mdw->isVisible() ) {
|
|
new DialogViewConfigurationItem(_qlw, md->id(), mdw->isVisible(), mdName, splitted, mdw->mixDevice()->iconName());
|
|
}
|
|
else {
|
|
new DialogViewConfigurationItem(_qlwInactive, md->id(), mdw->isVisible(), mdName, splitted, mdw->mixDevice()->iconName());
|
|
}
|
|
|
|
/*
|
|
if ( ! md->isEnum() && ( ( md->playbackVolume().count() > 1) || ( md->captureVolume().count() > 1) ) ) {
|
|
cb = new QCheckBox( "", vboxForScrollView ); // split
|
|
cb->setBackgroundRole(bgRole);
|
|
cb->setAutoFillBackground(true);
|
|
_qSplitCB.append(cb);
|
|
cb->setChecked( ! mdw->isStereoLinked() );
|
|
grid->addWidget(cb,1+i,1);
|
|
}
|
|
else {
|
|
_qSplitCB.append(0);
|
|
}
|
|
*/
|
|
/*
|
|
if ( ! md->isEnum() && ( md->playbackVolume().count() + md->captureVolume().count() >0 ) ) {
|
|
cb = new QCheckBox( "", vboxForScrollView ); // limit
|
|
cb->setBackgroundRole(bgRole);
|
|
cb->setAutoFillBackground(true);
|
|
_qLimitCB.append(cb);
|
|
grid->addWidget(cb,1+i,2);
|
|
}
|
|
else {
|
|
*/
|
|
//_qLimitCB.append(0);
|
|
/*}*/
|
|
} // is not enum
|
|
} // for all MDW's
|
|
|
|
|
|
connect(_qlwInactive, SIGNAL(itemSelectionChanged()),
|
|
this , SLOT(selectionChangedInactive()));
|
|
connect(_qlw, SIGNAL(itemSelectionChanged()),
|
|
this , SLOT(selectionChangedActive()));
|
|
|
|
// scrollArea->updateGeometry();
|
|
updateGeometry();
|
|
connect( this, SIGNAL(okClicked()) , this, SLOT(apply()) );
|
|
|
|
#ifndef QT_NO_ACCESSIBILITY
|
|
moveLeftButton->setAccessibleName( i18n("Show the selected channel") );
|
|
moveRightButton->setAccessibleName( i18n("Hide the selected channel") );
|
|
_qlw->setAccessibleName( i18n("Visible channels") );
|
|
_qlwInactive->setAccessibleName( i18n("Available channels") );
|
|
#endif
|
|
}
|
|
|
|
DialogViewConfiguration::~DialogViewConfiguration()
|
|
{
|
|
}
|
|
|
|
|
|
void DialogViewConfiguration::apply()
|
|
{
|
|
// --- We have a 3-Step Apply of the Changes -------------------------------
|
|
|
|
// -1- Update view and profile *****************************************
|
|
GUIProfile* prof = _view.guiProfile();
|
|
GUIProfile::ControlSet& oldControlset = prof->getControls();
|
|
GUIProfile::ControlSet newControlset;
|
|
|
|
QAbstractItemModel* model;
|
|
model = _qlw->model();
|
|
prepareControls(model, true, oldControlset, newControlset);
|
|
model = _qlwInactive->model();
|
|
prepareControls(model, false, oldControlset, newControlset);
|
|
|
|
// -2- Copy all mandatory "catch-all" controls form the old to the new ControlSet *******
|
|
foreach ( ProfControl* pctl, oldControlset)
|
|
{
|
|
if ( pctl->isMandatory() ) {
|
|
ProfControl* newCtl = new ProfControl(*pctl);
|
|
newCtl->show = "full"; // The user has selected controls => mandatory controls are now only necessary in extended or full mode
|
|
newControlset.push_back(newCtl);
|
|
}
|
|
}
|
|
|
|
prof->setControls(newControlset);
|
|
prof->finalizeProfile();
|
|
prof->setDirty();
|
|
|
|
// --- Step 3: Tell the view, that it has changed (probably it needs some "polishing" ---
|
|
if ( _view.getMixers().size() == 1 )
|
|
ControlManager::instance().announce(_view.getMixers().first()->id(), ControlChangeType::ControlList, QString("View Configuration Dialog"));
|
|
else
|
|
ControlManager::instance().announce(QString(), ControlChangeType::ControlList, QString("View Configuration Dialog"));
|
|
}
|
|
|
|
void DialogViewConfiguration::prepareControls(QAbstractItemModel* model, bool isActiveView, GUIProfile::ControlSet& oldCtlSet, GUIProfile::ControlSet& newCtlSet)
|
|
{
|
|
int numRows = model->rowCount();
|
|
for (int row = 0; row < numRows; ++row) {
|
|
// -1- Extract the value from the model ***************************
|
|
QModelIndex index = model->index(row, 0);
|
|
QVariant vdci;
|
|
vdci = model->data(index, Qt::ToolTipRole); // TooltipRole stores the ID (well, thats not really clean design, but it works)
|
|
QString ctlId = vdci.toString();
|
|
|
|
|
|
// -2- Find the mdw, und update it **************************
|
|
foreach ( QWidget *qw, _view._mdws )
|
|
{
|
|
MixDeviceWidget *mdw = dynamic_cast<MixDeviceWidget*>(qw);
|
|
if ( !mdw ) {
|
|
continue;
|
|
}
|
|
|
|
if ( mdw->mixDevice()->id() == ctlId ) {
|
|
mdw->setVisible(isActiveView);
|
|
break;
|
|
} // mdw was found
|
|
} // find mdw
|
|
|
|
|
|
// -3- Insert it in the new ControlSet **************************
|
|
// kDebug() << "Should add to new ControlSet: " << ctlId;
|
|
foreach ( ProfControl* control, oldCtlSet)
|
|
{
|
|
//kDebug() << " checking " << control->id;
|
|
QRegExp idRegexp(control->id);
|
|
if ( ctlId.contains(idRegexp) ) {
|
|
// found. Create a copy
|
|
ProfControl* newCtl = new ProfControl(*control);
|
|
newCtl->id = '^' + ctlId + '$'; // Replace the (possible generic) regexp by the actual ID
|
|
// We have made this an an actual control. As it is derived (from e.g. ".*") it is NOT mandatory.
|
|
newCtl->setMandatory(false);
|
|
newCtl->setVisible(isActiveView);
|
|
newCtlSet.push_back(newCtl);
|
|
// kDebug() << "Added to new ControlSet (done): " << newCtl->id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#include "moc_dialogviewconfiguration.cpp"
|
|
|