1 /*
2  * EffectSelectDialog.cpp - dialog to choose effect plugin
3  *
4  * Copyright (c) 2006-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
5  *
6  * This file is part of LMMS - https://lmms.io
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program (see COPYING); if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301 USA.
22  *
23  */
24 
25 #include "EffectSelectDialog.h"
26 
27 #include "ui_EffectSelectDialog.h"
28 
29 #include "gui_templates.h"
30 #include "embed.h"
31 #include "PluginFactory.h"
32 
33 #include <QLabel>
34 
35 
EffectSelectDialog(QWidget * _parent)36 EffectSelectDialog::EffectSelectDialog( QWidget * _parent ) :
37 	QDialog( _parent ),
38 	ui( new Ui::EffectSelectDialog ),
39 	m_sourceModel(),
40 	m_model(),
41 	m_descriptionWidget( NULL )
42 {
43 	ui->setupUi( this );
44 
45 	setWindowIcon( embed::getIconPixmap( "setup_audio" ) );
46 
47 	// query effects
48 
49 	EffectKeyList subPluginEffectKeys;
50 
51 	for (const Plugin::Descriptor* desc: pluginFactory->descriptors(Plugin::Effect))
52 	{
53 		if( desc->subPluginFeatures )
54 		{
55 			desc->subPluginFeatures->listSubPluginKeys(
56 				// as iterators are always stated to be not
57 				// equal with pointers, we dereference the
58 				// iterator and take the address of the item,
59 				// so we're on the safe side and the compiler
60 				// likely will reduce that to just "it"
61 							desc,
62 							subPluginEffectKeys );
63 		}
64 		else
65 		{
66 			m_effectKeys << EffectKey( desc, desc->name );
67 
68 		}
69 	}
70 
71 	m_effectKeys += subPluginEffectKeys;
72 
73 	// and fill our source model
74 	m_sourceModel.setHorizontalHeaderItem( 0, new QStandardItem( tr( "Name" ) ) );
75 	m_sourceModel.setHorizontalHeaderItem( 1, new QStandardItem( tr( "Type" ) ) );
76 	int row = 0;
77 	for( EffectKeyList::ConstIterator it = m_effectKeys.begin();
78 						it != m_effectKeys.end(); ++it )
79 	{
80 		QString name;
81 		QString type;
82 		if( ( *it ).desc->subPluginFeatures )
83 		{
84 			name = ( *it ).name;
85 			type = ( *it ).desc->displayName;
86 		}
87 		else
88 		{
89 			name = ( *it ).desc->displayName;
90 			type = "LMMS";
91 		}
92 		m_sourceModel.setItem( row, 0, new QStandardItem( name ) );
93 		m_sourceModel.setItem( row, 1, new QStandardItem( type ) );
94 		++row;
95 	}
96 
97 	// setup filtering
98 	m_model.setSourceModel( &m_sourceModel );
99 	m_model.setFilterCaseSensitivity( Qt::CaseInsensitive );
100 
101 	connect( ui->filterEdit, SIGNAL( textChanged( const QString & ) ),
102 				&m_model, SLOT( setFilterFixedString( const QString & ) ) );
103 	connect( ui->filterEdit, SIGNAL( textChanged( const QString & ) ),
104 					this, SLOT( updateSelection() ) );
105 	connect( ui->filterEdit, SIGNAL( textChanged( const QString & ) ),
106 							SLOT( sortAgain() ) );
107 
108 	ui->pluginList->setModel( &m_model );
109 
110 	// setup selection model
111 	QItemSelectionModel * selectionModel = new QItemSelectionModel( &m_model );
112 	ui->pluginList->setSelectionModel( selectionModel );
113 	connect( selectionModel, SIGNAL( currentRowChanged( const QModelIndex &,
114 														const QModelIndex & ) ),
115 			SLOT( rowChanged( const QModelIndex &, const QModelIndex & ) ) );
116 	connect( ui->pluginList, SIGNAL( doubleClicked( const QModelIndex & ) ),
117 				SLOT( acceptSelection() ) );
118 
119 	// try to accept current selection when pressing "OK"
120 	connect( ui->buttonBox, SIGNAL( accepted() ),
121 				this, SLOT( acceptSelection() ) );
122 
123 #if QT_VERSION >= 0x050000
124 #define setResizeMode setSectionResizeMode
125 	ui->filterEdit->setClearButtonEnabled( true );
126 #endif
127 	ui->pluginList->verticalHeader()->setResizeMode(
128 						QHeaderView::ResizeToContents );
129 	ui->pluginList->verticalHeader()->hide();
130 	ui->pluginList->horizontalHeader()->setResizeMode( 0,
131 							QHeaderView::Stretch );
132 	ui->pluginList->horizontalHeader()->setResizeMode( 1,
133 						QHeaderView::ResizeToContents );
134 	ui->pluginList->sortByColumn( 0, Qt::AscendingOrder );
135 #if QT_VERSION >= 0x050000
136 #undef setResizeMode
137 #endif
138 
139 	updateSelection();
140 	show();
141 }
142 
143 
144 
145 
~EffectSelectDialog()146 EffectSelectDialog::~EffectSelectDialog()
147 {
148 	delete ui;
149 }
150 
151 
152 
153 
instantiateSelectedPlugin(EffectChain * _parent)154 Effect * EffectSelectDialog::instantiateSelectedPlugin( EffectChain * _parent )
155 {
156 	if( !m_currentSelection.name.isEmpty() && m_currentSelection.desc )
157 	{
158 		return Effect::instantiate( m_currentSelection.desc->name,
159 										_parent, &m_currentSelection );
160 	}
161 	return NULL;
162 }
163 
164 
165 
166 
acceptSelection()167 void EffectSelectDialog::acceptSelection()
168 {
169 	if( m_currentSelection.isValid() )
170 	{
171 		accept();
172 	}
173 }
174 
175 
176 
177 
rowChanged(const QModelIndex & _idx,const QModelIndex &)178 void EffectSelectDialog::rowChanged( const QModelIndex & _idx,
179 										const QModelIndex & )
180 {
181 	delete m_descriptionWidget;
182 	m_descriptionWidget = NULL;
183 
184 	if( m_model.mapToSource( _idx ).row() < 0 )
185 	{
186 		// invalidate current selection
187 		m_currentSelection = Plugin::Descriptor::SubPluginFeatures::Key();
188 	}
189 	else
190 	{
191 		m_currentSelection = m_effectKeys[m_model.mapToSource( _idx ).row()];
192 	}
193     if( m_currentSelection.desc )
194 	{
195 		m_descriptionWidget = new QWidget;
196 
197         QHBoxLayout *hbox = new QHBoxLayout( m_descriptionWidget );
198 
199         Plugin::Descriptor const & descriptor = *( m_currentSelection.desc );
200 
201         if ( descriptor.logo )
202         {
203             QLabel *logoLabel = new QLabel( m_descriptionWidget );
204             logoLabel->setPixmap( descriptor.logo->pixmap() );
205             logoLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
206 
207             hbox->addWidget( logoLabel );
208             hbox->setAlignment( logoLabel, Qt::AlignTop);
209         }
210 
211         QWidget *textualInfoWidget = new QWidget( m_descriptionWidget );
212 
213         hbox->addWidget(textualInfoWidget);
214 
215         QVBoxLayout * textWidgetLayout = new QVBoxLayout( textualInfoWidget);
216         textWidgetLayout->setMargin( 4 );
217         textWidgetLayout->setSpacing( 0 );
218 
219         if ( m_currentSelection.desc->subPluginFeatures )
220         {
221             QWidget *subWidget = new QWidget(textualInfoWidget);
222             QVBoxLayout * subLayout = new QVBoxLayout( subWidget );
223             subLayout->setMargin( 4 );
224             subLayout->setSpacing( 0 );
225             m_currentSelection.desc->subPluginFeatures->
226                 fillDescriptionWidget( subWidget, &m_currentSelection );
227             for( QWidget * w : subWidget->findChildren<QWidget *>() )
228             {
229                 if( w->parent() == subWidget )
230                 {
231                     subLayout->addWidget( w );
232                 }
233             }
234 
235             textWidgetLayout->addWidget(subWidget);
236         }
237         else
238         {
239             QLabel *label = new QLabel(m_descriptionWidget);
240             QString labelText = "<p><b>" + tr("Name") + ":</b> " + QString::fromUtf8(descriptor.displayName) + "</p>";
241             labelText += "<p><b>" + tr("Description") + ":</b> " + qApp->translate( "pluginBrowser", descriptor.description ) + "</p>";
242             labelText += "<p><b>" + tr("Author") + ":</b> " + QString::fromUtf8(descriptor.author) + "</p>";
243 
244             label->setText(labelText);
245             textWidgetLayout->addWidget(label);
246         }
247 
248         ui->scrollArea->setWidget( m_descriptionWidget );
249 		m_descriptionWidget->show();
250 	}
251 }
252 
253 
254 
255 
sortAgain()256 void EffectSelectDialog::sortAgain()
257 {
258 	ui->pluginList->setSortingEnabled( ui->pluginList->isSortingEnabled() );
259 }
260 
261 
262 
263 
updateSelection()264 void EffectSelectDialog::updateSelection()
265 {
266 	// no valid selection anymore due to changed filter?
267 	if( ui->pluginList->selectionModel()->selection().size() <= 0 )
268 	{
269 		// then select our first item
270 		ui->pluginList->selectionModel()->select( m_model.index( 0, 0 ),
271 					QItemSelectionModel::ClearAndSelect
272 					| QItemSelectionModel::Rows );
273 		rowChanged( m_model.index( 0, 0 ), QModelIndex() );
274 	}
275 }
276 
277 
278 
279 
280 
281