AlgorithmSelector.cpp 12.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
/*
 *	(c) LSIIT, UMR CNRS/UdS
 *	Authors: O. Gnevaux, F. Larue.
 *
 *	See licence.txt for additional information.
 */


#include "GLViewer.h"
#include "AlgorithmSelector.h"
#include "ui_AlgorithmSelector.h"
12
#include "UIMultiProgressDialog.h"
13
14
15
16
17
18
19
20
21
#include <QLabel>




AlgorithmSelector::AlgorithmSelector(QWidget *parent) :
    QWidget( parent ),
    m_ui( new Ui::AlgorithmSelector ),
    m_SelectedTool( NULL ),
22
23
    m_SelectedToolParam( NULL ),
    m_CurrentToolProgress( NULL )
24
25
26
27
28
29
30
31
32
{
    m_ui->setupUi(this);
    m_ui->groupToolDescription->hide();

    connect( m_ui->buttonApplyTool, SIGNAL(clicked()), this, SLOT(emitApplySignal()) );

    m_CategoryButtonGroup = new QButtonGroup( this );
    connect( m_CategoryButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(selectCategory(int)) );

33
34
35
    m_ToolsByCategory.resize( ToolCategory::categoryCount() );
    m_LastUsedInCategory.resize( ToolCategory::categoryCount() );
    for( int i=0; i<ToolCategory::categoryCount(); ++i )
36
37
38
39
40
41
        m_LastUsedInCategory[i] = 0;
}


AlgorithmSelector::~AlgorithmSelector()
{
42
    delete m_CurrentToolProgress;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    delete m_ui;
}


void AlgorithmSelector::changeEvent(QEvent *e)
{
    QWidget::changeEvent( e );
    switch( e->type() )
    {
        case QEvent::LanguageChange: m_ui->retranslateUi(this); break;
        default: break;
    }
}


void AlgorithmSelector::populateTools( ToolInterface *plugin )
{
    QList<int> toolIds;
    plugin->toolIds( toolIds );

    foreach( int i, toolIds )
    {
65
66
        int categoryId = plugin->category(i);
        if( ToolCategory::isCategoryDeclared(categoryId) )
67
68
69
70
71
        {
            ToolDescriptor tool;
            tool.plugin = plugin;
            tool.id     = i;
            tool.param  = new UIParamSet( "Tool options", this );
72
            plugin->declareParameters( i, *tool.param );
73
            tool.param->SetHidden();
74
			//tool.param->setMaximumWidth(360);
75

76
77
            connect( tool.param, SIGNAL(parameterUpdated(UIParam*)), tool.plugin, SLOT(updateParameter(UIParam*)) );

78
            foreach( UIParamAction* act, tool.param->GetActions() )
79
                connect( act->Widget(), SIGNAL(clicked(bool)), this, SLOT(emitActionSignal()) );
80

81
            m_ToolsByName[ plugin->name(i) ] = tool;
82
83
84
85
86
87
88
            m_ToolsByCategory[categoryId].push_back( tool );
            m_ui->widgetToolGroupBoxes->layout()->addWidget( tool.param );
        }
    }
}


89
90
91
92
93
94
95
96
void AlgorithmSelector::releaseAllTools()
{
    for( auto &category : m_ToolsByCategory )
        for( auto &tool : category )
            delete tool.param;
}


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
void AlgorithmSelector::finalizeTools()
{
    // Sort tools by name for each category.
    for( QVector<QVector<ToolDescriptor>>::iterator category=m_ToolsByCategory.begin(); category!=m_ToolsByCategory.end(); ++category )
    {
        QMap<QString,ToolDescriptor> toolByName;
        foreach( ToolDescriptor tool, *category )
            toolByName[tool.plugin->name(tool.id)] = tool;

        category->clear();

        for( QMap<QString,ToolDescriptor>::iterator tool=toolByName.begin(); tool!=toolByName.end(); ++tool )
            category->push_back( *tool );
    }


    /** For each non-empty category, a pannel similar to the following one is created and added to the category widget.
     *      +--------------+
     *      | +----------+ |
     *      | |  Button  | |
     *      | |   with   | |
     *      | |   icon   | |
     *      | +----------+ |
     *      |     Label    |
     *      +--------------+
     */

124
125
126
    QPushButton *firstCategoryButton = NULL;
    int firstCategoryId = -1;

127
    for( int categoryId : ToolCategory::categoryIds() )
128
129
        if( !m_ToolsByCategory[categoryId].empty() )
        {
130
            QVBoxLayout *l = new QVBoxLayout();
131
132
133
134
135
136
137
138
139
            l->setAlignment( Qt::AlignHCenter );
            l->setContentsMargins( 0, 0, 0, 0 );
            l->setSpacing( 0 );

            QPushButton *categoryButton = new QPushButton( ToolCategory::categoryIcon(categoryId), QString() );
            categoryButton->setContentsMargins( 0, 0, 0, 0 );
            categoryButton->setIconSize( QSize(80,80) );
            categoryButton->setFlat( true );
            categoryButton->setMinimumSize( 80, 80 );
140
            categoryButton->setMaximumSize( 80, 80 );
141
            categoryButton->setCheckable( true );
142
            l->addWidget( categoryButton, 0, Qt::AlignHCenter );
143
144
            m_CategoryButtonGroup->addButton( categoryButton, categoryId );

145
146
147
148
149
150
            if( !firstCategoryButton )
            {
                firstCategoryButton = categoryButton;
                firstCategoryId = categoryId;
            }

151
            QLabel *categoryLabel = new QLabel( ToolCategory::categoryName(categoryId) );
152
            QFont f = QApplication::font();
153
154
155
            f.setPointSize( 7 );
            categoryLabel->setFont( f );
            categoryLabel->setAlignment( Qt::AlignHCenter );
156
            //categoryLabel->setWordWrap( true );
157
            l->addWidget( categoryLabel, 0, Qt::AlignHCenter );
158
159
160
161
162
163
164
165
166

            QWidget *categoryPannel = new QWidget();
            categoryPannel->setLayout( l );

            QGridLayout *allCategories = (QGridLayout*) m_ui->widgetCategories->layout();
            int i = allCategories->count();
            allCategories->addWidget( categoryPannel, i>>2, i&3 );
        }

167
168
169
170
171
172
173
	m_ui->widgetCategories->layout()->setAlignment(Qt::AlignHCenter | Qt::AlignTop);

    if( firstCategoryButton )
    {
        firstCategoryButton->setChecked( true );
        selectCategory( firstCategoryId );
    }
174
175
176
}


177
bool AlgorithmSelector::selectCategory( int categoryId )
178
{
179
180
181
    if( !ToolCategory::isCategoryDeclared(categoryId) )
        return false;

182
183
184
185
186
187
188
189
190
191
192
193
194
195
    disconnect( m_ui->comboAvailableTools, SIGNAL(currentIndexChanged(int)), this, SLOT(selectTool(int)) );

    m_SelectedCategory = categoryId;
    int lastUsedId = m_LastUsedInCategory[categoryId];

    // Populate the combobox with the names of all tools associated to the selected category.
    m_ui->comboAvailableTools->clear();
    foreach( ToolDescriptor tool, m_ToolsByCategory[categoryId] )
        m_ui->comboAvailableTools->addItem( tool.plugin->name(tool.id) );

    m_ui->comboAvailableTools->setCurrentIndex( lastUsedId );
    selectTool( lastUsedId );

    connect( m_ui->comboAvailableTools, SIGNAL(currentIndexChanged(int)), this, SLOT(selectTool(int)) );
196
197

    return true;
198
199
200
}


201
bool AlgorithmSelector::selectTool( int n )
202
203
204
{
    if( m_SelectedToolParam )
    {
205
        m_SelectedToolParam->SetHidden();
206
207
208
        m_SelectedToolParam = NULL;
    }

209
210
211
    if( n >= m_ToolsByCategory[m_SelectedCategory].size() )
        return false;

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
    if( n >= 0 )
    {
        m_SelectedTool = &m_ToolsByCategory[m_SelectedCategory][n];

        QString description = m_SelectedTool->plugin->description( m_SelectedTool->id );
        if( description.isNull() || description.isEmpty() )
            m_ui->groupToolDescription->hide();
        else
        {
            m_ui->groupToolDescription->show();
            m_ui->labelToolDescription->setText( description );
            m_ui->labelToolDescription->setEnabled( true );

            QVector<QString> acceptedTypes;
            m_SelectedTool->plugin->acceptedDataTypes( m_SelectedTool->id, acceptedTypes );
            if( acceptedTypes.empty() )
                m_ui->labelToolDescription->setToolTip( "" );
            else
            {
                QString toolTip = "Accepted items:";
                foreach( QString t, acceptedTypes )
                    toolTip += QString("\n") + t;
                m_ui->labelToolDescription->setToolTip( toolTip );
            }
        }

238
        if( !m_SelectedTool->param->IsEmpty() )
239
240
        {
            m_SelectedToolParam = m_SelectedTool->param;
241
            m_SelectedToolParam->SetVisible();
242
243
244
245
246
247
248
249
250
        }

        m_LastUsedInCategory[m_SelectedCategory] = n;
    }
    else
    {
        m_ui->groupToolDescription->hide();
        m_SelectedTool = NULL;
    }
251
252

    return true;
253
254
255
}


256
QString AlgorithmSelector::state() const
257
{
258
259
260
261
262
263
264
265
266
267
    QString stateValue;

    stateValue += QString::number(m_SelectedCategory) + ";";
    stateValue += QString::number(m_ui->comboAvailableTools->currentIndex());
    for( auto v : m_LastUsedInCategory )
        stateValue += ";" + QString::number(v);
    
    return stateValue;
}

268

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
bool AlgorithmSelector::setState( const QString &stateValue )
{
    QStringList tokens = stateValue.split( ';' );
    if( tokens.size() != m_LastUsedInCategory.size()+2 )
        return false;

    bool ok;
    int selectedCategory = tokens.front().toInt( &ok );
    if( !ok )
        return false;
    tokens.pop_front();

    int selectedTool = tokens.front().toInt( &ok );
    if( !ok )
        return false;
    tokens.pop_front();

    QVector<int> lastUsedInCategory( m_LastUsedInCategory.size() );
    for( auto &v : lastUsedInCategory )
288
    {
289
290
291
292
        v = tokens.front().toInt( &ok );
        if( !ok )
            return false;
        tokens.pop_front();
293
    }
294
295
296
297
298
299
300
301
302
303

    m_CategoryButtonGroup->button( selectedCategory )->setChecked( true );
    selectCategory( selectedCategory );

    m_ui->comboAvailableTools->setCurrentIndex( selectedTool );
    selectTool( selectedTool );

    m_LastUsedInCategory = lastUsedInCategory;

    return true;
304
305
306
}


307
308
309
310
311
312
313
314
315
316
317
318
319
void AlgorithmSelector::emitApplySignal()
{
	if( m_SelectedTool )
	{
		m_ActionId = QString();
		emit askItemsToApplyToolOn();
	}
}


void AlgorithmSelector::emitActionSignal()
{
    m_ActionId = QString();
320
    foreach( UIParamAction* act, m_SelectedTool->param->GetActions() )
321
322
        if( act->Widget() == (QPushButton*)sender() )
            m_ActionId = act->Id();
323
324
325
326
327
328
329

    if( !m_ActionId.isNull() )
        emit askItemsToApplyToolOn();
}


void AlgorithmSelector::applyCurrentToolOn( const QList<GenericUIData*> &items,
330
                                            UIMainWindow *mainwin,
331
                                            GLViewer *glviewer,
332
                                            UIProject *project )
333
334
335
{
    if( m_SelectedTool )
    {
336
337
338
        m_ToolContext.mainwin  = mainwin;
        m_ToolContext.glviewer = glviewer;
        m_ToolContext.project  = project;
339
340
341

        QVector<QString> acceptedTypes;
        m_SelectedTool->plugin->acceptedDataTypes( m_SelectedTool->id, acceptedTypes );
342

343
344
345
346
        QMap<QString,int> acceptedTypeIds;
        for( int i=0; i<acceptedTypes.size(); ++i )
            acceptedTypeIds[ acceptedTypes[i] ] = i;

347
348
        UIToolDataSet dataSet;
        dataSet.items.resize( acceptedTypes.size() );
349

350
        for( GenericUIData *m : items )
351
        {
352
353
354
            auto found = acceptedTypeIds.find( m->GetTypeString() );
            if( found != acceptedTypeIds.end() )
                dataSet.items[ found.value() ].push_back( m );
355
356
        }

357
358
359
        connect( m_SelectedTool->plugin, SIGNAL(notifyCreateProgressBars(int)), this, SLOT(createProgressBars(int)) );
        connect( m_SelectedTool->plugin, SIGNAL(notifyDeleteProgressBars()), this, SLOT(deleteProgressBars()) );

360
361
        bool executionOk;
        if( m_ActionId.isNull() )
362
            executionOk = m_SelectedTool->plugin->exec( m_SelectedTool->id, dataSet, *m_SelectedToolParam, m_ToolContext );
363
        else
364
            executionOk = m_SelectedTool->plugin->execAction( m_SelectedTool->id, m_ActionId, dataSet, *m_SelectedToolParam, m_ToolContext );
365

366
367
368
        disconnect( m_SelectedTool->plugin, SIGNAL(notifyCreateProgressBars(int)), this, SLOT(createProgressBars(int)) );
        disconnect( m_SelectedTool->plugin, SIGNAL(notifyDeleteProgressBars()), this, SLOT(deleteProgressBars()) );
        deleteProgressBars();
369

370
371
372
        emit toolExecutionFinished( executionOk );
    }
}
373
374
375
376
377
378
379
380
381
382
383


void AlgorithmSelector::createProgressBars( int n )
{
    deleteProgressBars();

    if( n > 0 )
    {
        m_CurrentToolProgress = new UIMultiProgressDialog( n, m_ToolContext.mainwin );
        m_CurrentToolProgress->setWindowTitle( m_SelectedTool->plugin->name(m_SelectedTool->id) );

384
        connect( m_SelectedTool->plugin, SIGNAL(notifyProgressBar(unsigned int,QString,int,QString)), m_CurrentToolProgress, SLOT(setBar(unsigned int,QString,int,QString)) );
385
386
387
388
389
390
391
392
393
394
395
396
397
398
        connect( m_SelectedTool->plugin, SIGNAL(notifyProgressValue(unsigned int,int)), m_CurrentToolProgress, SLOT(setProgress(unsigned int,int)) );
    }
}


void AlgorithmSelector::deleteProgressBars()
{
    if( m_CurrentToolProgress )
    {
        m_CurrentToolProgress->close();
        m_CurrentToolProgress->deleteLater();
        m_CurrentToolProgress = NULL;
    }
}