AlgorithmSelector.cpp 14.8 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
#include <QLabel>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "ScriptParser.h"




QString AlgorithmSelector::ToolDescriptor::getName() const
{
    return plugin? plugin->name(id) : script->GetName();
}

QString AlgorithmSelector::ToolDescriptor::getDescription() const
{
    return plugin? plugin->description(id) : script->GetDescription();
}

void AlgorithmSelector::ToolDescriptor::getAcceptedDataTypes( QVector<QString> &types ) const
{
    if( plugin )
        plugin->acceptedDataTypes( id, types );
}
34
35
36
37
38
39
40
41




AlgorithmSelector::AlgorithmSelector(QWidget *parent) :
    QWidget( parent ),
    m_ui( new Ui::AlgorithmSelector ),
    m_SelectedTool( NULL ),
42
43
    m_SelectedToolParam( NULL ),
    m_CurrentToolProgress( NULL )
44
45
46
47
48
49
50
51
52
{
    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)) );

53
54
55
    m_ToolsByCategory.resize( ToolCategory::categoryCount() );
    m_LastUsedInCategory.resize( ToolCategory::categoryCount() );
    for( int i=0; i<ToolCategory::categoryCount(); ++i )
56
57
58
59
60
61
        m_LastUsedInCategory[i] = 0;
}


AlgorithmSelector::~AlgorithmSelector()
{
62
63
    for( auto &tool : m_ToolsByName )
        delete tool.script;
64
    delete m_CurrentToolProgress;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    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 )
    {
87
88
        int categoryId = plugin->category(i);
        if( ToolCategory::isCategoryDeclared(categoryId) )
89
90
91
92
93
        {
            ToolDescriptor tool;
            tool.plugin = plugin;
            tool.id     = i;
            tool.param  = new UIParamSet( "Tool options", this );
94
            plugin->declareParameters( i, *tool.param );
95
            tool.param->SetHidden();
96
			//tool.param->setMaximumWidth(360);
97

98
99
            connect( tool.param, SIGNAL(parameterUpdated(UIParam*)), tool.plugin, SLOT(updateParameter(UIParam*)) );

100
            foreach( UIParamAction* act, tool.param->GetActions() )
101
                connect( act->Widget(), SIGNAL(clicked(bool)), this, SLOT(emitActionSignal()) );
102

103
            m_ToolsByName[ plugin->name(i) ] = tool;
104
105
106
107
108
109
110
            m_ToolsByCategory[categoryId].push_back( tool );
            m_ui->widgetToolGroupBoxes->layout()->addWidget( tool.param );
        }
    }
}


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
bool AlgorithmSelector::populateTools( const QString &scriptFileName )
{
    ScriptParser *script = new ScriptParser();
    script->SetAvailableTools( this );

    if( !script->ParseFile(scriptFileName) )
    {
        delete script;
        return false;
    }

    bool categoryDeclared = false;
    int categoryId = -1;
    for( int i=0; i<ToolCategory::categoryCount(); ++i )
        if( script->GetCategory() == ToolCategory::categoryName(i) )
        {
            categoryId = i;
            categoryDeclared = true;
            break;
        }

    if( categoryDeclared )
    {
        ToolDescriptor tool;
        tool.script = script;
        tool.param  = new UIParamSet( "Tool options", this );
        //plugin->declareParameters( i, *tool.param );
        tool.param->SetHidden();
        //tool.param->setMaximumWidth(360);

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

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

        m_ToolsByName[ script->GetName() ] = tool;
        m_ToolsByCategory[categoryId].push_back( tool );
        m_ui->widgetToolGroupBoxes->layout()->addWidget( tool.param );
    }

    return true;
}


155
156
157
158
159
160
161
162
void AlgorithmSelector::releaseAllTools()
{
    for( auto &category : m_ToolsByCategory )
        for( auto &tool : category )
            delete tool.param;
}


163
164
165
void AlgorithmSelector::finalizeTools()
{
    // Sort tools by name for each category.
166
    for( auto &category : m_ToolsByCategory )
167
168
    {
        QMap<QString,ToolDescriptor> toolByName;
169
170
        for( ToolDescriptor &tool : category )
            toolByName[tool.getName()] = tool;
171

172
        category.clear();
173

174
175
        for( auto &tool : toolByName )
            category.push_back( tool );
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    }


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

190
191
192
    QPushButton *firstCategoryButton = NULL;
    int firstCategoryId = -1;

193
    for( int categoryId : ToolCategory::categoryIds() )
194
195
        if( !m_ToolsByCategory[categoryId].empty() )
        {
196
            QVBoxLayout *l = new QVBoxLayout();
197
198
199
200
201
202
203
204
205
            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 );
206
            categoryButton->setMaximumSize( 80, 80 );
207
            categoryButton->setCheckable( true );
208
            l->addWidget( categoryButton, 0, Qt::AlignHCenter );
209
210
            m_CategoryButtonGroup->addButton( categoryButton, categoryId );

211
212
213
214
215
216
            if( !firstCategoryButton )
            {
                firstCategoryButton = categoryButton;
                firstCategoryId = categoryId;
            }

217
            QLabel *categoryLabel = new QLabel( ToolCategory::categoryName(categoryId) );
218
            QFont f = QApplication::font();
219
220
221
            f.setPointSize( 7 );
            categoryLabel->setFont( f );
            categoryLabel->setAlignment( Qt::AlignHCenter );
222
            //categoryLabel->setWordWrap( true );
223
            l->addWidget( categoryLabel, 0, Qt::AlignHCenter );
224
225
226
227
228
229
230
231
232

            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 );
        }

233
234
235
236
237
238
239
	m_ui->widgetCategories->layout()->setAlignment(Qt::AlignHCenter | Qt::AlignTop);

    if( firstCategoryButton )
    {
        firstCategoryButton->setChecked( true );
        selectCategory( firstCategoryId );
    }
240
241
242
}


243
bool AlgorithmSelector::selectCategory( int categoryId )
244
{
245
246
247
    if( !ToolCategory::isCategoryDeclared(categoryId) )
        return false;

248
249
250
251
252
253
254
255
    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] )
256
257
258
259
260
261
    {
        if( tool.script )
            m_ui->comboAvailableTools->addItem( QIcon(":/images/resources/iconScript.png"), tool.getName() );
        else
            m_ui->comboAvailableTools->addItem( tool.getName() );
    }
262
263
264
265
266

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

    connect( m_ui->comboAvailableTools, SIGNAL(currentIndexChanged(int)), this, SLOT(selectTool(int)) );
267
268

    return true;
269
270
271
}


272
bool AlgorithmSelector::selectTool( int n )
273
274
275
{
    if( m_SelectedToolParam )
    {
276
        m_SelectedToolParam->SetHidden();
277
278
279
        m_SelectedToolParam = NULL;
    }

280
281
282
    if( n >= m_ToolsByCategory[m_SelectedCategory].size() )
        return false;

283
284
285
286
    if( n >= 0 )
    {
        m_SelectedTool = &m_ToolsByCategory[m_SelectedCategory][n];

287
        QString description = m_SelectedTool->getDescription();
288
289
290
291
292
293
294
295
296
        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;
297
            m_SelectedTool->getAcceptedDataTypes(acceptedTypes);
298
299
300
301
302
303
304
305
306
307
308
            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 );
            }
        }

309
        if( !m_SelectedTool->param->IsEmpty() )
310
311
        {
            m_SelectedToolParam = m_SelectedTool->param;
312
            m_SelectedToolParam->SetVisible();
313
314
315
316
317
318
319
320
321
        }

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

    return true;
324
325
326
}


327
QString AlgorithmSelector::state() const
328
{
329
330
331
332
333
334
335
336
337
338
    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;
}

339

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
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 )
359
    {
360
361
362
363
        v = tokens.front().toInt( &ok );
        if( !ok )
            return false;
        tokens.pop_front();
364
    }
365
366
367
368
369
370
371
372
373
374

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

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

    m_LastUsedInCategory = lastUsedInCategory;

    return true;
375
376
377
}


378
379
380
381
382
383
384
385
386
387
388
389
390
void AlgorithmSelector::emitApplySignal()
{
	if( m_SelectedTool )
	{
		m_ActionId = QString();
		emit askItemsToApplyToolOn();
	}
}


void AlgorithmSelector::emitActionSignal()
{
    m_ActionId = QString();
391
    foreach( UIParamAction* act, m_SelectedTool->param->GetActions() )
392
393
        if( act->Widget() == (QPushButton*)sender() )
            m_ActionId = act->Id();
394
395
396
397
398
399

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


400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
void AlgorithmSelector::applyToolOn( ToolDescriptor *tool,
                                     const QList<GenericUIData*> &items,
                                     UIMainWindow *mainwin,
                                     GLViewer *glviewer,
                                     UIProject *project )
{
    ToolDescriptor *selectedBackup = m_SelectedTool;
    m_SelectedTool = tool;

    applyCurrentToolOn(items, mainwin, glviewer, project);

    m_SelectedTool = selectedBackup;
}


415
void AlgorithmSelector::applyCurrentToolOn( const QList<GenericUIData*> &items,
416
                                            UIMainWindow *mainwin,
417
                                            GLViewer *glviewer,
418
                                            UIProject *project )
419
420
421
{
    if( m_SelectedTool )
    {
422
423
424
        m_ToolContext.mainwin  = mainwin;
        m_ToolContext.glviewer = glviewer;
        m_ToolContext.project  = project;
425

426
427
428
429
430
        bool executionOk = true;
        if( m_SelectedTool->plugin )
        {
            QVector<QString> acceptedTypes;
            m_SelectedTool->plugin->acceptedDataTypes( m_SelectedTool->id, acceptedTypes );
431

432
433
434
            QMap<QString,int> acceptedTypeIds;
            for( int i=0; i<acceptedTypes.size(); ++i )
                acceptedTypeIds[ acceptedTypes[i] ] = i;
435

436
437
            UIToolDataSet dataSet;
            dataSet.items.resize( acceptedTypes.size() );
438

439
440
441
442
443
444
            for( GenericUIData *m : items )
            {
                auto found = acceptedTypeIds.find( m->GetTypeString() );
                if( found != acceptedTypeIds.end() )
                    dataSet.items[ found.value() ].push_back( m );
            }
445

446
447
            connect( m_SelectedTool->plugin, SIGNAL(notifyCreateProgressBars(int)), this, SLOT(createProgressBars(int)) );
            connect( m_SelectedTool->plugin, SIGNAL(notifyDeleteProgressBars()), this, SLOT(deleteProgressBars()) );
448

449
450
            if( project )
                project->StartNewDataTracking();
451

452
453
454
455
            if( m_ActionId.isNull() )
                executionOk = m_SelectedTool->plugin->exec( m_SelectedTool->id, dataSet, *m_SelectedTool->param, m_ToolContext );
            else
                executionOk = m_SelectedTool->plugin->execAction( m_SelectedTool->id, m_ActionId, dataSet, *m_SelectedTool->param, m_ToolContext );
456

457
458
            if( project )
                project->StopNewDataTracking();
459

460
461
462
463
464
465
466
467
            disconnect( m_SelectedTool->plugin, SIGNAL(notifyCreateProgressBars(int)), this, SLOT(createProgressBars(int)) );
            disconnect( m_SelectedTool->plugin, SIGNAL(notifyDeleteProgressBars()), this, SLOT(deleteProgressBars()) );
            deleteProgressBars();
        }
        else if( m_SelectedTool->script )
        {
            executionOk = m_SelectedTool->script->RunScript( m_ToolContext );
        }
468

469
470
471
        emit toolExecutionFinished( executionOk );
    }
}
472
473
474
475
476
477
478
479
480
481
482


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) );

483
        connect( m_SelectedTool->plugin, SIGNAL(notifyProgressBar(unsigned int,QString,int,QString)), m_CurrentToolProgress, SLOT(setBar(unsigned int,QString,int,QString)) );
484
485
486
487
488
489
490
491
492
493
494
495
496
497
        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;
    }
}