20 #include <QDialogButtonBox>
22 #include <QListWidget>
23 #include <QListWidgetItem>
24 #include <QMessageBox>
28 #include <QStackedWidget>
30 #include <QStandardItem>
32 #include <QHeaderView>
44 : QDialog( parent, fl )
45 , mOptsKey( settingsKey )
46 , mSettings( settings )
81 if ( title.isEmpty() )
88 if (
auto *lLayout = layout() )
90 lLayout->setContentsMargins( 0, 0, 0, 0 );
94 mOptListWidget = findChild<QListWidget *>( QStringLiteral(
"mOptionsListWidget" ) );
95 mOptTreeView = findChild<QTreeView *>( QStringLiteral(
"mOptionsTreeView" ) );
105 QFrame *optionsFrame = findChild<QFrame *>( QStringLiteral(
"mOptionsFrame" ) );
106 mOptStackedWidget = findChild<QStackedWidget *>( QStringLiteral(
"mOptionsStackedWidget" ) );
107 mOptSplitter = findChild<QSplitter *>( QStringLiteral(
"mOptionsSplitter" ) );
108 mOptButtonBox = findChild<QDialogButtonBox *>( QStringLiteral(
"buttonBox" ) );
109 QFrame *buttonBoxFrame = findChild<QFrame *>( QStringLiteral(
"mButtonBoxFrame" ) );
110 mSearchLineEdit = findChild<QgsFilterLineEdit *>( QStringLiteral(
"mSearchLineEdit" ) );
133 optView->setFrameStyle( QFrame::NoFrame );
136 optionsFrame->layout()->setContentsMargins( 0, frameMargin, frameMargin, frameMargin );
137 QVBoxLayout *layout =
static_cast<QVBoxLayout *
>( optionsFrame->layout() );
139 if ( buttonBoxFrame )
141 buttonBoxFrame->layout()->setContentsMargins( 0, 0, 0, 0 );
142 layout->insertWidget( layout->count(), buttonBoxFrame );
152 disconnect(
mOptButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
153 connect(
mOptButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
154 disconnect(
mOptButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
155 connect(
mOptButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
164 connect(
mOptTreeView->selectionModel(), &QItemSelectionModel::selectionChanged,
mOptStackedWidget, [ = ](
const QItemSelection &,
const QItemSelection & )
166 const QModelIndexList selected = mOptTreeView->selectionModel()->selectedIndexes();
167 if ( selected.isEmpty() )
170 const QModelIndex index = mTreeProxyModel->mapToSource( selected.at( 0 ) );
172 if ( !mOptTreeModel || !mOptTreeModel->itemFromIndex( index )->isSelectable() )
175 mOptStackedWidget->setCurrentIndex( mTreeProxyModel->sourceIndexToPageNumber( index ) );
213 if ( !title.isEmpty() )
230 optView->setMaximumWidth(
231 mSettings->value( QStringLiteral(
"/Windows/%1/splitState" ).arg(
mOptsKey ) ).isNull() ? 150 : 16777215 );
233 optView->setAttribute( Qt::WA_MacShowFocusRect,
false );
245 l->setContentsMargins( 0, 0, 0, 0 );
252 int curIndx =
mSettings->value( QStringLiteral(
"/Windows/%1/tab" ).arg(
mOptsKey ), 0 ).toInt();
273 setListToItemAtIndex( curIndx );
276 void QgsOptionsDialogBase::setListToItemAtIndex(
int index )
295 QSizePolicy::Policy policy = QSizePolicy::Ignored;
298 policy = QSizePolicy::MinimumExpanding;
318 if ( currentPage->objectName() == page )
333 QListWidgetItem *item =
new QListWidgetItem();
334 item->setIcon( icon );
335 item->setText( title );
336 item->setToolTip( tooltip );
341 QStandardItem *item =
new QStandardItem( icon, title );
342 item->setToolTip( tooltip );
345 QStandardItem *parentItem =
nullptr;
348 QStringList parents = path;
349 while ( !parents.empty() )
351 const QString parentPath = parents.takeFirst();
353 QModelIndex thisParent;
354 for (
int row = 0; row <
mOptTreeModel->rowCount( parent ); ++row )
356 const QModelIndex index =
mOptTreeModel->index( row, 0, parent );
357 if ( index.data().toString().compare( parentPath, Qt::CaseInsensitive ) == 0
358 || index.data( Qt::UserRole + 1 ).toString().compare( parentPath, Qt::CaseInsensitive ) == 0 )
366 if ( !thisParent.isValid() )
368 QStandardItem *newParentItem =
new QStandardItem( parentPath );
369 newParentItem->setToolTip( parentPath );
370 newParentItem->setSelectable(
false );
372 parentItem->appendRow( newParentItem );
375 parentItem = newParentItem;
387 parentItem->appendRow( item );
388 const QModelIndex newIndex =
mOptTreeModel->indexFromItem( item );
407 if ( currentPage->objectName() == before )
413 QListWidgetItem *item =
new QListWidgetItem();
414 item->setIcon( icon );
415 item->setText( title );
416 item->setToolTip( tooltip );
421 QModelIndex sourceIndexBefore =
mTreeProxyModel->pageNumberToSourceIndex( page );
422 QList< QModelIndex > sourceBeforeIndices;
423 while ( sourceIndexBefore.parent().isValid() )
425 sourceBeforeIndices.insert( 0, sourceIndexBefore );
426 sourceIndexBefore = sourceIndexBefore.parent();
428 sourceBeforeIndices.insert( 0, sourceIndexBefore );
430 QStringList parentPaths = path;
432 QModelIndex parentIndex;
433 QStandardItem *parentItem =
nullptr;
434 while ( !parentPaths.empty() )
436 QString thisPath = parentPaths.takeFirst();
437 QModelIndex sourceIndex = !sourceBeforeIndices.isEmpty() ? sourceBeforeIndices.takeFirst() : QModelIndex();
439 if ( sourceIndex.data().toString().compare( thisPath, Qt::CaseInsensitive ) == 0
440 || sourceIndex.data( Qt::UserRole + 1 ).toString().compare( thisPath, Qt::CaseInsensitive ) == 0 )
442 parentIndex = sourceIndex;
447 QStandardItem *newParentItem =
new QStandardItem( thisPath );
448 newParentItem->setToolTip( thisPath );
449 newParentItem->setSelectable(
false );
450 if ( sourceIndex.isValid() )
454 parentItem->insertRow( sourceIndex.row(), newParentItem );
456 mOptTreeModel->insertRow( sourceIndex.row(), newParentItem );
462 parentItem->appendRow( newParentItem );
466 parentItem = newParentItem;
470 QStandardItem *item =
new QStandardItem( icon, title );
471 item->setToolTip( tooltip );
474 if ( sourceBeforeIndices.empty() )
475 parentItem->appendRow( item );
478 parentItem->insertRow( sourceBeforeIndices.at( 0 ).row(), item );
493 addPage( title, tooltip, icon, widget, path );
498 const int minimumTextLength = 3;
515 if (
mOptListWidget->item( r )->text().contains( text, Qt::CaseInsensitive ) )
521 mOptListWidget->setRowHidden( r, text.length() >= minimumTextLength );
527 if ( rsw.first->searchHighlight( text.length() >= minimumTextLength ? text : QString() ) )
535 QMap< int, bool > hiddenPages;
538 hiddenPages.insert( r, text.length() >= minimumTextLength );
541 std::function<void(
const QModelIndex & )> traverseModel;
543 traverseModel = [&](
const QModelIndex & parent )
545 for (
int row = 0; row <
mOptTreeModel->rowCount( parent ); ++row )
547 const QModelIndex currentIndex =
mOptTreeModel->index( row, 0, parent );
548 if ( currentIndex.data().toString().contains( text, Qt::CaseInsensitive ) )
550 hiddenPages.insert(
mTreeProxyModel->sourceIndexToPageNumber( currentIndex ), false );
552 traverseModel( currentIndex );
555 traverseModel( QModelIndex() );
559 if ( rsw.first->searchHighlight( text.length() >= minimumTextLength ? text : QString() ) )
561 hiddenPages.insert( rsw.second,
false );
564 for (
auto it = hiddenPages.constBegin(); it != hiddenPages.constEnd(); ++it )
569 if (
mOptTreeView && text.length() >= minimumTextLength )
595 if ( !
mTreeProxyModel->filterAcceptsRow( currentSourceIndex.row(), currentSourceIndex.parent() ) )
597 std::function<QModelIndex(
const QModelIndex & )> traverseModel;
598 traverseModel = [&](
const QModelIndex & parent ) -> QModelIndex
602 const QModelIndex proxyIndex =
mTreeProxyModel->index( row, 0, parent );
603 const QModelIndex sourceIndex =
mTreeProxyModel->mapToSource( proxyIndex );
604 if (
mOptTreeModel->itemFromIndex( sourceIndex )->isSelectable() )
610 QModelIndex res = traverseModel( proxyIndex );
615 return QModelIndex();
618 const QModelIndex firstVisibleSourceIndex = traverseModel( QModelIndex() );
620 if ( firstVisibleSourceIndex.isValid() )
647 const QList< QWidget * > widgets =
mOptStackedWidget->widget( i )->findChildren<QWidget *>();
648 for ( QWidget *w : widgets )
651 QHash<QWidget *, QgsOptionsDialogHighlightWidget *> customHighlightWidgets;
659 if ( customHighlightWidgets.contains( w ) )
661 shw = customHighlightWidgets.value( w );
670 QgsDebugMsgLevel( QStringLiteral(
"Registering: %1" ).arg( w->objectName() ), 4 );
684 res->setToolTip( tooltip );
712 QDialog::showEvent( e );
720 QDialog::paintEvent( e );
727 if ( !itemText.isEmpty() )
729 setWindowTitle( QStringLiteral(
"%1 %2 %3" )
731 .arg( QChar( 0x2014 ) )
748 if ( optView->maximumWidth() != 16777215 )
749 optView->setMaximumWidth( 16777215 );
753 int iconWidth = optView->iconSize().width();
754 int snapToIconWidth = iconWidth + 32;
757 mIconOnly = ( splitSizes.at( 0 ) <= snapToIconWidth );
760 int newWidth = optView->verticalScrollBar()->isVisible() ? iconWidth + 22 : iconWidth + 9;
761 bool diffWidth = optView->minimumWidth() != newWidth;
764 optView->setMinimumWidth( newWidth );
766 if (
mIconOnly && ( diffWidth || optView->width() != newWidth ) )
768 splitSizes[1] = splitSizes.at( 1 ) - ( splitSizes.at( 0 ) - newWidth );
769 splitSizes[0] = newWidth;
816 if ( ( *it ).second == index )
825 QMessageBox::warning(
nullptr, tr(
"Missing Objects" ),
826 tr(
"Base options dialog could not be initialized.\n\n"
827 "Missing some of the .ui template objects:\n" )
828 +
" mOptionsListWidget,\n mOptionsStackedWidget,\n mOptionsSplitter,\n mOptionsListFrame",
835 QgsOptionsProxyModel::QgsOptionsProxyModel( QObject *parent )
836 : QSortFilterProxyModel( parent )
838 setDynamicSortFilter(
true );
841 void QgsOptionsProxyModel::setPageHidden(
int page,
bool hidden )
843 mHiddenPages[ page ] = hidden;
847 QModelIndex QgsOptionsProxyModel::pageNumberToSourceIndex(
int page )
const
849 QStandardItemModel *itemModel = qobject_cast< QStandardItemModel * >( sourceModel() );
851 return QModelIndex();
853 int pagesRemaining = page;
854 std::function<QModelIndex(
const QModelIndex & )> traversePages;
857 traversePages = [&](
const QModelIndex & parent ) -> QModelIndex
859 for (
int row = 0; row < itemModel->rowCount( parent ); ++row )
861 const QModelIndex currentIndex = itemModel->index( row, 0, parent );
862 if ( itemModel->itemFromIndex( currentIndex )->isSelectable() )
864 if ( pagesRemaining == 0 )
867 else pagesRemaining--;
870 const QModelIndex res = traversePages( currentIndex );
874 return QModelIndex();
877 return traversePages( QModelIndex() );
880 int QgsOptionsProxyModel::sourceIndexToPageNumber(
const QModelIndex &index )
const
882 QStandardItemModel *itemModel = qobject_cast< QStandardItemModel * >( sourceModel() );
888 std::function<int(
const QModelIndex & )> traverseModel;
891 traverseModel = [&](
const QModelIndex & parent ) ->
int
893 for (
int row = 0; row < itemModel->rowCount( parent ); ++row )
895 const QModelIndex currentIndex = itemModel->index( row, 0, parent );
896 if ( currentIndex == index )
899 if ( itemModel->itemFromIndex( currentIndex )->isSelectable() )
902 const int res = traverseModel( currentIndex );
909 return traverseModel( QModelIndex() );
912 bool QgsOptionsProxyModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
914 QStandardItemModel *itemModel = qobject_cast< QStandardItemModel * >( sourceModel() );
918 const QModelIndex sourceIndex = sourceModel()->index( source_row, 0, source_parent );
920 const int pageNumber = sourceIndexToPageNumber( sourceIndex );
921 if ( !mHiddenPages.value( pageNumber,
false ) )
924 if ( sourceModel()->hasChildren( sourceIndex ) )
927 for (
int row = 0; row < sourceModel()->rowCount( sourceIndex ); ++row )
929 if ( filterAcceptsRow( row, sourceIndex ) )