Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgslayoutmanager.cpp
3 : : --------------------
4 : : Date : January 2017
5 : : Copyright : (C) 2017 Nyall Dawson
6 : : Email : nyall dot dawson at gmail dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #include "qgslayoutmanager.h"
17 : : #include "qgslayout.h"
18 : : #include "qgsproject.h"
19 : : #include "qgslogger.h"
20 : : #include "qgslayoutundostack.h"
21 : : #include "qgsprintlayout.h"
22 : : #include "qgsreport.h"
23 : : #include "qgscompositionconverter.h"
24 : : #include "qgsreadwritecontext.h"
25 : : #include "qgsstyleentityvisitor.h"
26 : : #include "qgsruntimeprofiler.h"
27 : : #include <QMessageBox>
28 : :
29 : 5 : QgsLayoutManager::QgsLayoutManager( QgsProject *project )
30 : 5 : : QObject( project )
31 : 5 : , mProject( project )
32 : 10 : {
33 : :
34 : 5 : }
35 : :
36 : 6 : QgsLayoutManager::~QgsLayoutManager()
37 : 6 : {
38 : 3 : clear();
39 : 6 : }
40 : :
41 : 0 : bool QgsLayoutManager::addLayout( QgsMasterLayoutInterface *layout )
42 : : {
43 : 0 : if ( !layout || mLayouts.contains( layout ) )
44 : 0 : return false;
45 : :
46 : : // check for duplicate name
47 : 0 : for ( QgsMasterLayoutInterface *l : std::as_const( mLayouts ) )
48 : : {
49 : 0 : if ( l->name() == layout->name() )
50 : : {
51 : 0 : delete layout;
52 : 0 : return false;
53 : : }
54 : : }
55 : :
56 : : // ugly, but unavoidable for interfaces...
57 : 0 : if ( QgsPrintLayout *l = dynamic_cast< QgsPrintLayout * >( layout ) )
58 : : {
59 : 0 : connect( l, &QgsPrintLayout::nameChanged, this, [this, l]( const QString & newName )
60 : : {
61 : 0 : emit layoutRenamed( l, newName );
62 : 0 : } );
63 : 0 : }
64 : 0 : else if ( QgsReport *r = dynamic_cast< QgsReport * >( layout ) )
65 : : {
66 : 0 : connect( r, &QgsReport::nameChanged, this, [this, r]( const QString & newName )
67 : : {
68 : 0 : emit layoutRenamed( r, newName );
69 : 0 : } );
70 : 0 : }
71 : :
72 : 0 : emit layoutAboutToBeAdded( layout->name() );
73 : 0 : mLayouts << layout;
74 : 0 : emit layoutAdded( layout->name() );
75 : 0 : mProject->setDirty( true );
76 : 0 : return true;
77 : 0 : }
78 : :
79 : 0 : bool QgsLayoutManager::removeLayout( QgsMasterLayoutInterface *layout )
80 : : {
81 : 0 : if ( !layout )
82 : 0 : return false;
83 : :
84 : 0 : if ( !mLayouts.contains( layout ) )
85 : 0 : return false;
86 : :
87 : 0 : QString name = layout->name();
88 : 0 : emit layoutAboutToBeRemoved( name );
89 : 0 : mLayouts.removeAll( layout );
90 : 0 : delete layout;
91 : 0 : emit layoutRemoved( name );
92 : 0 : mProject->setDirty( true );
93 : 0 : return true;
94 : 0 : }
95 : :
96 : 11 : void QgsLayoutManager::clear()
97 : : {
98 : 11 : const QList< QgsMasterLayoutInterface * > layouts = mLayouts;
99 : 11 : for ( QgsMasterLayoutInterface *l : layouts )
100 : : {
101 : 0 : removeLayout( l );
102 : : }
103 : 11 : }
104 : :
105 : 0 : QList<QgsMasterLayoutInterface *> QgsLayoutManager::layouts() const
106 : : {
107 : 0 : return mLayouts;
108 : : }
109 : :
110 : 0 : QList<QgsPrintLayout *> QgsLayoutManager::printLayouts() const
111 : : {
112 : 0 : QList<QgsPrintLayout *> result;
113 : 0 : const QList<QgsMasterLayoutInterface *> _layouts( mLayouts );
114 : 0 : result.reserve( _layouts.size() );
115 : 0 : for ( const auto &layout : _layouts )
116 : : {
117 : 0 : QgsPrintLayout *_item( dynamic_cast<QgsPrintLayout *>( layout ) );
118 : 0 : if ( _item )
119 : 0 : result.push_back( _item );
120 : : }
121 : 0 : return result;
122 : 0 : }
123 : :
124 : 0 : QgsMasterLayoutInterface *QgsLayoutManager::layoutByName( const QString &name ) const
125 : : {
126 : 0 : for ( QgsMasterLayoutInterface *l : mLayouts )
127 : : {
128 : 0 : if ( l->name() == name )
129 : 0 : return l;
130 : : }
131 : 0 : return nullptr;
132 : 0 : }
133 : :
134 : 0 : bool QgsLayoutManager::readXml( const QDomElement &element, const QDomDocument &doc )
135 : : {
136 : 0 : clear();
137 : :
138 : 0 : QDomElement layoutsElem = element;
139 : 0 : if ( element.tagName() != QLatin1String( "Layouts" ) )
140 : : {
141 : 0 : layoutsElem = element.firstChildElement( QStringLiteral( "Layouts" ) );
142 : 0 : }
143 : 0 : if ( layoutsElem.isNull() )
144 : : {
145 : : // handle legacy projects
146 : 0 : layoutsElem = doc.documentElement();
147 : 0 : }
148 : :
149 : : //restore each composer
150 : 0 : bool result = true;
151 : 0 : QDomNodeList composerNodes = element.elementsByTagName( QStringLiteral( "Composer" ) );
152 : 0 : QgsScopedRuntimeProfile profile( tr( "Loading QGIS 2.x compositions" ), QStringLiteral( "projectload" ) );
153 : 0 : for ( int i = 0; i < composerNodes.size(); ++i )
154 : : {
155 : : // This legacy title is the Composer "title" (that can be overridden by the Composition "name")
156 : 0 : QString legacyTitle = composerNodes.at( i ).toElement().attribute( QStringLiteral( "title" ) );
157 : : // Convert compositions to layouts
158 : 0 : QDomNodeList compositionNodes = composerNodes.at( i ).toElement().elementsByTagName( QStringLiteral( "Composition" ) );
159 : 0 : for ( int j = 0; j < compositionNodes.size(); ++j )
160 : : {
161 : 0 : std::unique_ptr< QgsPrintLayout > l( QgsCompositionConverter::createLayoutFromCompositionXml( compositionNodes.at( j ).toElement(), mProject ) );
162 : 0 : if ( l )
163 : : {
164 : 0 : if ( l->name().isEmpty() )
165 : 0 : l->setName( legacyTitle );
166 : :
167 : : // some 2.x projects could end in a state where they had duplicated layout names. This is strictly forbidden in 3.x
168 : : // so check for duplicate name in layouts already added
169 : 0 : int id = 2;
170 : 0 : bool isDuplicateName = false;
171 : 0 : QString originalName = l->name();
172 : 0 : do
173 : : {
174 : 0 : isDuplicateName = false;
175 : 0 : for ( QgsMasterLayoutInterface *layout : std::as_const( mLayouts ) )
176 : : {
177 : 0 : if ( l->name() == layout->name() )
178 : : {
179 : 0 : isDuplicateName = true;
180 : 0 : break;
181 : : }
182 : : }
183 : 0 : if ( isDuplicateName )
184 : : {
185 : 0 : l->setName( QStringLiteral( "%1 %2" ).arg( originalName ).arg( id ) );
186 : 0 : id++;
187 : 0 : }
188 : 0 : }
189 : 0 : while ( isDuplicateName );
190 : :
191 : 0 : bool added = addLayout( l.release() );
192 : 0 : result = added && result;
193 : 0 : }
194 : 0 : }
195 : 0 : }
196 : :
197 : 0 : QgsReadWriteContext context;
198 : 0 : context.setPathResolver( mProject->pathResolver() );
199 : :
200 : 0 : profile.switchTask( tr( "Creating layouts" ) );
201 : :
202 : : // restore layouts
203 : 0 : const QDomNodeList layoutNodes = layoutsElem.childNodes();
204 : 0 : for ( int i = 0; i < layoutNodes.size(); ++i )
205 : : {
206 : 0 : if ( layoutNodes.at( i ).nodeName() != QLatin1String( "Layout" ) )
207 : 0 : continue;
208 : :
209 : 0 : const QString layoutName = layoutNodes.at( i ).toElement().attribute( QStringLiteral( "name" ) );
210 : 0 : QgsScopedRuntimeProfile profile( layoutName, QStringLiteral( "projectload" ) );
211 : :
212 : 0 : std::unique_ptr< QgsPrintLayout > l = std::make_unique< QgsPrintLayout >( mProject );
213 : 0 : l->undoStack()->blockCommands( true );
214 : 0 : if ( !l->readLayoutXml( layoutNodes.at( i ).toElement(), doc, context ) )
215 : : {
216 : 0 : result = false;
217 : 0 : continue;
218 : : }
219 : 0 : l->undoStack()->blockCommands( false );
220 : 0 : if ( !addLayout( l.release() ) )
221 : : {
222 : 0 : result = false;
223 : 0 : }
224 : 0 : }
225 : : //reports
226 : 0 : profile.switchTask( tr( "Creating reports" ) );
227 : 0 : const QDomNodeList reportNodes = element.elementsByTagName( QStringLiteral( "Report" ) );
228 : 0 : for ( int i = 0; i < reportNodes.size(); ++i )
229 : : {
230 : 0 : const QString layoutName = reportNodes.at( i ).toElement().attribute( QStringLiteral( "name" ) );
231 : 0 : QgsScopedRuntimeProfile profile( layoutName, QStringLiteral( "projectload" ) );
232 : :
233 : 0 : std::unique_ptr< QgsReport > r = std::make_unique< QgsReport >( mProject );
234 : 0 : if ( !r->readLayoutXml( reportNodes.at( i ).toElement(), doc, context ) )
235 : : {
236 : 0 : result = false;
237 : 0 : continue;
238 : : }
239 : 0 : if ( !addLayout( r.release() ) )
240 : : {
241 : 0 : result = false;
242 : 0 : }
243 : 0 : }
244 : 0 : return result;
245 : 0 : }
246 : :
247 : 0 : QDomElement QgsLayoutManager::writeXml( QDomDocument &doc ) const
248 : : {
249 : 0 : QDomElement layoutsElem = doc.createElement( QStringLiteral( "Layouts" ) );
250 : :
251 : 0 : QgsReadWriteContext context;
252 : 0 : context.setPathResolver( mProject->pathResolver() );
253 : 0 : for ( QgsMasterLayoutInterface *l : mLayouts )
254 : : {
255 : 0 : QDomElement layoutElem = l->writeLayoutXml( doc, context );
256 : 0 : layoutsElem.appendChild( layoutElem );
257 : 0 : }
258 : 0 : return layoutsElem;
259 : 0 : }
260 : :
261 : 0 : QgsMasterLayoutInterface *QgsLayoutManager::duplicateLayout( const QgsMasterLayoutInterface *layout, const QString &newName )
262 : : {
263 : 0 : if ( !layout )
264 : 0 : return nullptr;
265 : :
266 : 0 : std::unique_ptr< QgsMasterLayoutInterface > newLayout( layout->clone() );
267 : 0 : if ( !newLayout )
268 : : {
269 : 0 : return nullptr;
270 : : }
271 : :
272 : 0 : newLayout->setName( newName );
273 : 0 : QgsMasterLayoutInterface *l = newLayout.get();
274 : 0 : if ( !addLayout( newLayout.release() ) )
275 : : {
276 : 0 : return nullptr;
277 : : }
278 : : else
279 : : {
280 : 0 : return l;
281 : : }
282 : 0 : }
283 : :
284 : 0 : QString QgsLayoutManager::generateUniqueTitle( QgsMasterLayoutInterface::Type type ) const
285 : : {
286 : 0 : QStringList names;
287 : 0 : names.reserve( mLayouts.size() );
288 : 0 : for ( QgsMasterLayoutInterface *l : mLayouts )
289 : : {
290 : 0 : names << l->name();
291 : : }
292 : 0 : QString name;
293 : 0 : int id = 1;
294 : 0 : while ( name.isEmpty() || names.contains( name ) )
295 : 0 : {
296 : 0 : switch ( type )
297 : : {
298 : : case QgsMasterLayoutInterface::PrintLayout:
299 : 0 : name = tr( "Layout %1" ).arg( id );
300 : 0 : break;
301 : : case QgsMasterLayoutInterface::Report:
302 : 0 : name = tr( "Report %1" ).arg( id );
303 : 0 : break;
304 : : }
305 : 0 : id++;
306 : : }
307 : 0 : return name;
308 : 0 : }
309 : :
310 : 0 : bool QgsLayoutManager::accept( QgsStyleEntityVisitorInterface *visitor ) const
311 : : {
312 : 0 : if ( mLayouts.empty() )
313 : 0 : return true;
314 : :
315 : : // NOTE: if visitEnter returns false it means "don't visit the layouts", not "abort all further visitations"
316 : 0 : if ( !visitor->visitEnter( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Layouts, QStringLiteral( "layouts" ), tr( "Layouts" ) ) ) )
317 : 0 : return true;
318 : :
319 : 0 : for ( QgsMasterLayoutInterface *l : mLayouts )
320 : : {
321 : 0 : if ( !l->layoutAccept( visitor ) )
322 : 0 : return false;
323 : : }
324 : :
325 : 0 : if ( !visitor->visitExit( QgsStyleEntityVisitorInterface::Node( QgsStyleEntityVisitorInterface::NodeType::Layouts, QStringLiteral( "layouts" ), tr( "Layouts" ) ) ) )
326 : 0 : return false;
327 : :
328 : 0 : return true;
329 : 0 : }
330 : :
331 : :
332 : :
333 : : //
334 : : // QgsLayoutManagerModel
335 : : //
336 : :
337 : 0 : QgsLayoutManagerModel::QgsLayoutManagerModel( QgsLayoutManager *manager, QObject *parent )
338 : 0 : : QAbstractListModel( parent )
339 : 0 : , mLayoutManager( manager )
340 : 0 : {
341 : 0 : connect( mLayoutManager, &QgsLayoutManager::layoutAboutToBeAdded, this, &QgsLayoutManagerModel::layoutAboutToBeAdded );
342 : 0 : connect( mLayoutManager, &QgsLayoutManager::layoutAdded, this, &QgsLayoutManagerModel::layoutAdded );
343 : 0 : connect( mLayoutManager, &QgsLayoutManager::layoutAboutToBeRemoved, this, &QgsLayoutManagerModel::layoutAboutToBeRemoved );
344 : 0 : connect( mLayoutManager, &QgsLayoutManager::layoutRemoved, this, &QgsLayoutManagerModel::layoutRemoved );
345 : 0 : connect( mLayoutManager, &QgsLayoutManager::layoutRenamed, this, &QgsLayoutManagerModel::layoutRenamed );
346 : 0 : }
347 : :
348 : 0 : int QgsLayoutManagerModel::rowCount( const QModelIndex &parent ) const
349 : : {
350 : 0 : Q_UNUSED( parent )
351 : 0 : return ( mLayoutManager ? mLayoutManager->layouts().count() : 0 ) + ( mAllowEmpty ? 1 : 0 );
352 : 0 : }
353 : :
354 : 0 : QVariant QgsLayoutManagerModel::data( const QModelIndex &index, int role ) const
355 : : {
356 : 0 : if ( index.row() < 0 || index.row() >= rowCount( QModelIndex() ) )
357 : 0 : return QVariant();
358 : :
359 : 0 : const bool isEmpty = index.row() == 0 && mAllowEmpty;
360 : 0 : const int layoutRow = mAllowEmpty ? index.row() - 1 : index.row();
361 : :
362 : 0 : switch ( role )
363 : : {
364 : : case Qt::DisplayRole:
365 : : case Qt::ToolTipRole:
366 : : case Qt::EditRole:
367 : 0 : return !isEmpty && mLayoutManager ? mLayoutManager->layouts().at( layoutRow )->name() : QVariant();
368 : :
369 : : case LayoutRole:
370 : : {
371 : 0 : if ( isEmpty || !mLayoutManager )
372 : 0 : return QVariant();
373 : 0 : else if ( QgsLayout *l = dynamic_cast< QgsLayout * >( mLayoutManager->layouts().at( layoutRow ) ) )
374 : 0 : return QVariant::fromValue( l );
375 : 0 : else if ( QgsReport *r = dynamic_cast< QgsReport * >( mLayoutManager->layouts().at( layoutRow ) ) )
376 : 0 : return QVariant::fromValue( r );
377 : : else
378 : 0 : return QVariant();
379 : : }
380 : :
381 : : case Qt::DecorationRole:
382 : : {
383 : 0 : return isEmpty || !mLayoutManager ? QIcon() : mLayoutManager->layouts().at( layoutRow )->icon();
384 : : }
385 : :
386 : : default:
387 : 0 : return QVariant();
388 : : }
389 : 0 : }
390 : :
391 : 0 : bool QgsLayoutManagerModel::setData( const QModelIndex &index, const QVariant &value, int role )
392 : : {
393 : 0 : if ( !index.isValid() || role != Qt::EditRole )
394 : : {
395 : 0 : return false;
396 : : }
397 : 0 : if ( index.row() >= mLayoutManager->layouts().count() )
398 : : {
399 : 0 : return false;
400 : : }
401 : :
402 : 0 : if ( index.row() == 0 && mAllowEmpty )
403 : 0 : return false;
404 : :
405 : 0 : if ( value.toString().isEmpty() )
406 : 0 : return false;
407 : :
408 : 0 : QgsMasterLayoutInterface *layout = layoutFromIndex( index );
409 : 0 : if ( !layout )
410 : 0 : return false;
411 : :
412 : : //has name changed?
413 : 0 : bool changed = layout->name() != value.toString();
414 : 0 : if ( !changed )
415 : 0 : return true;
416 : :
417 : : //check if name already exists
418 : 0 : QStringList layoutNames;
419 : 0 : const QList< QgsMasterLayoutInterface * > layouts = QgsProject::instance()->layoutManager()->layouts();
420 : 0 : for ( QgsMasterLayoutInterface *l : layouts )
421 : : {
422 : 0 : layoutNames << l->name();
423 : : }
424 : 0 : if ( layoutNames.contains( value.toString() ) )
425 : : {
426 : : //name exists!
427 : 0 : QMessageBox::warning( nullptr, tr( "Rename Layout" ), tr( "There is already a layout named “%1”." ).arg( value.toString() ) );
428 : 0 : return false;
429 : : }
430 : :
431 : 0 : layout->setName( value.toString() );
432 : 0 : return true;
433 : 0 : }
434 : :
435 : 0 : Qt::ItemFlags QgsLayoutManagerModel::flags( const QModelIndex &index ) const
436 : : {
437 : 0 : Qt::ItemFlags flags = QAbstractListModel::flags( index );
438 : : #if 0 // double-click is now used for opening the layout
439 : : if ( index.isValid() )
440 : : {
441 : : return flags | Qt::ItemIsEditable;
442 : : }
443 : : else
444 : : {
445 : : return flags;
446 : : }
447 : : #endif
448 : 0 : return flags;
449 : : }
450 : :
451 : 0 : QgsMasterLayoutInterface *QgsLayoutManagerModel::layoutFromIndex( const QModelIndex &index ) const
452 : : {
453 : 0 : if ( index.row() == 0 && mAllowEmpty )
454 : 0 : return nullptr;
455 : :
456 : 0 : if ( QgsPrintLayout *l = qobject_cast< QgsPrintLayout * >( qvariant_cast<QObject *>( data( index, LayoutRole ) ) ) )
457 : 0 : return l;
458 : 0 : else if ( QgsReport *r = qobject_cast< QgsReport * >( qvariant_cast<QObject *>( data( index, LayoutRole ) ) ) )
459 : 0 : return r;
460 : : else
461 : 0 : return nullptr;
462 : 0 : }
463 : :
464 : 0 : QModelIndex QgsLayoutManagerModel::indexFromLayout( QgsMasterLayoutInterface *layout ) const
465 : : {
466 : 0 : if ( !mLayoutManager )
467 : : {
468 : 0 : return QModelIndex();
469 : : }
470 : :
471 : 0 : const int r = mLayoutManager->layouts().indexOf( layout );
472 : 0 : if ( r < 0 )
473 : 0 : return QModelIndex();
474 : :
475 : 0 : QModelIndex idx = index( mAllowEmpty ? r + 1 : r, 0, QModelIndex() );
476 : 0 : if ( idx.isValid() )
477 : : {
478 : 0 : return idx;
479 : : }
480 : :
481 : 0 : return QModelIndex();
482 : 0 : }
483 : :
484 : 0 : void QgsLayoutManagerModel::setAllowEmptyLayout( bool allowEmpty )
485 : : {
486 : 0 : if ( allowEmpty == mAllowEmpty )
487 : 0 : return;
488 : :
489 : 0 : if ( allowEmpty )
490 : : {
491 : 0 : beginInsertRows( QModelIndex(), 0, 0 );
492 : 0 : mAllowEmpty = true;
493 : 0 : endInsertRows();
494 : 0 : }
495 : : else
496 : : {
497 : 0 : beginRemoveRows( QModelIndex(), 0, 0 );
498 : 0 : mAllowEmpty = false;
499 : 0 : endRemoveRows();
500 : : }
501 : 0 : }
502 : :
503 : 0 : void QgsLayoutManagerModel::layoutAboutToBeAdded( const QString & )
504 : : {
505 : 0 : int row = mLayoutManager->layouts().count() + ( mAllowEmpty ? 1 : 0 );
506 : 0 : beginInsertRows( QModelIndex(), row, row );
507 : 0 : }
508 : :
509 : 0 : void QgsLayoutManagerModel::layoutAboutToBeRemoved( const QString &name )
510 : : {
511 : 0 : QgsMasterLayoutInterface *l = mLayoutManager->layoutByName( name );
512 : 0 : int row = mLayoutManager->layouts().indexOf( l ) + ( mAllowEmpty ? 1 : 0 );
513 : 0 : if ( row >= 0 )
514 : 0 : beginRemoveRows( QModelIndex(), row, row );
515 : 0 : }
516 : :
517 : 0 : void QgsLayoutManagerModel::layoutAdded( const QString & )
518 : : {
519 : 0 : endInsertRows();
520 : 0 : }
521 : :
522 : 0 : void QgsLayoutManagerModel::layoutRemoved( const QString & )
523 : : {
524 : 0 : endRemoveRows();
525 : 0 : }
526 : :
527 : 0 : void QgsLayoutManagerModel::layoutRenamed( QgsMasterLayoutInterface *layout, const QString & )
528 : : {
529 : 0 : int row = mLayoutManager->layouts().indexOf( layout ) + ( mAllowEmpty ? 1 : 0 );
530 : 0 : QModelIndex index = createIndex( row, 0 );
531 : 0 : emit dataChanged( index, index, QVector<int>() << Qt::DisplayRole );
532 : 0 : }
533 : :
534 : : //
535 : : // QgsLayoutManagerProxyModel
536 : : //
537 : :
538 : 0 : QgsLayoutManagerProxyModel::QgsLayoutManagerProxyModel( QObject *parent )
539 : 0 : : QSortFilterProxyModel( parent )
540 : 0 : {
541 : 0 : setDynamicSortFilter( true );
542 : 0 : sort( 0 );
543 : 0 : setSortCaseSensitivity( Qt::CaseInsensitive );
544 : 0 : }
545 : :
546 : 0 : bool QgsLayoutManagerProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
547 : : {
548 : 0 : const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
549 : 0 : const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
550 : 0 : if ( leftText.isEmpty() )
551 : 0 : return true;
552 : 0 : if ( rightText.isEmpty() )
553 : 0 : return false;
554 : :
555 : 0 : return QString::localeAwareCompare( leftText, rightText ) < 0;
556 : 0 : }
557 : :
558 : 0 : bool QgsLayoutManagerProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
559 : : {
560 : 0 : QgsLayoutManagerModel *model = qobject_cast< QgsLayoutManagerModel * >( sourceModel() );
561 : 0 : if ( !model )
562 : 0 : return false;
563 : :
564 : 0 : QgsMasterLayoutInterface *layout = model->layoutFromIndex( model->index( sourceRow, 0, sourceParent ) );
565 : 0 : if ( !layout )
566 : 0 : return model->allowEmptyLayout();
567 : :
568 : 0 : if ( !mFilterString.trimmed().isEmpty() )
569 : : {
570 : 0 : if ( !layout->name().contains( mFilterString, Qt::CaseInsensitive ) )
571 : 0 : return false;
572 : 0 : }
573 : :
574 : 0 : switch ( layout->layoutType() )
575 : : {
576 : : case QgsMasterLayoutInterface::PrintLayout:
577 : 0 : return mFilters & FilterPrintLayouts;
578 : : case QgsMasterLayoutInterface::Report:
579 : 0 : return mFilters & FilterReports;
580 : : }
581 : 0 : return false;
582 : 0 : }
583 : :
584 : 0 : QgsLayoutManagerProxyModel::Filters QgsLayoutManagerProxyModel::filters() const
585 : : {
586 : 0 : return mFilters;
587 : : }
588 : :
589 : 0 : void QgsLayoutManagerProxyModel::setFilters( Filters filters )
590 : : {
591 : 0 : mFilters = filters;
592 : 0 : invalidateFilter();
593 : 0 : }
594 : :
595 : 0 : void QgsLayoutManagerProxyModel::setFilterString( const QString &filter )
596 : : {
597 : 0 : mFilterString = filter;
598 : 0 : invalidateFilter();
599 : 0 : }
|