QGIS API Documentation  3.23.0-Master (c716e02dd3)
qgssearchwidgettoolbutton.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssearchwidgettoolbutton.cpp
3  -----------------------------
4  Date : May 2016
5  Copyright : (C) 2016 Nyall Dawson
6  Email : nyall dot dawson at gmail.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 
17 #include "qgsapplication.h"
18 #include <QMenu>
19 
21  : QToolButton( parent )
22  , mAvailableFilterFlags( QgsSearchWidgetWrapper::EqualTo | QgsSearchWidgetWrapper::NotEqualTo | QgsSearchWidgetWrapper::CaseInsensitive )
23  , mDefaultFilterFlags( QgsSearchWidgetWrapper::EqualTo )
24  , mFilterFlags( QgsSearchWidgetWrapper::EqualTo )
25 
26 {
27  setFocusPolicy( Qt::StrongFocus );
28  setPopupMode( QToolButton::InstantPopup );
29 
30  mMenu = new QMenu( this );
31  connect( mMenu, &QMenu::aboutToShow, this, &QgsSearchWidgetToolButton::aboutToShowMenu );
32  setMenu( mMenu );
33 
34  // sets initial appearance
35  updateState();
36 }
37 
38 void QgsSearchWidgetToolButton::setAvailableFlags( QgsSearchWidgetWrapper::FilterFlags flags )
39 {
40  mFilterFlags &= flags;
41  mAvailableFilterFlags = flags;
42  mDefaultFilterFlags = mDefaultFilterFlags & flags;
43  updateState();
44 }
45 
46 void QgsSearchWidgetToolButton::setDefaultFlags( QgsSearchWidgetWrapper::FilterFlags flags )
47 {
48  mDefaultFilterFlags = flags & mAvailableFilterFlags;
49 }
50 
51 void QgsSearchWidgetToolButton::setActiveFlags( QgsSearchWidgetWrapper::FilterFlags flags )
52 {
53  // sanitize list
54  QgsSearchWidgetWrapper::FilterFlags newFlags;
55 
56  // only accept a single exclusive flag
57  const auto exclusiveFilterFlags { QgsSearchWidgetWrapper::exclusiveFilterFlags() };
58  for ( const QgsSearchWidgetWrapper::FilterFlag flag : exclusiveFilterFlags )
59  {
60  if ( !( mAvailableFilterFlags & flag ) )
61  {
62  //unsupported
63  continue;
64  }
65  if ( flags & flag )
66  {
67  newFlags |= flag;
68  break;
69  }
70  }
71  const auto nonExclusiveFilterFlags { QgsSearchWidgetWrapper::nonExclusiveFilterFlags() };
72  for ( const QgsSearchWidgetWrapper::FilterFlag flag : nonExclusiveFilterFlags )
73  {
74  if ( !( mAvailableFilterFlags & flag ) )
75  {
76  //unsupported
77  continue;
78  }
79 
80  if ( flags & flag )
81  newFlags |= flag;
82  }
83 
84  mFilterFlags = newFlags;
85 
86  updateState();
87 }
88 
90 {
91  if ( !( flag & mAvailableFilterFlags ) )
92  return;
93 
94  if ( QgsSearchWidgetWrapper::nonExclusiveFilterFlags().contains( flag ) )
95  {
96  if ( flag & mFilterFlags )
97  mFilterFlags &= ~flag;
98  else
99  mFilterFlags |= flag;
100  }
101  else
102  {
103  // clear other exclusive flags
104  const auto exclusiveFilterFlags { QgsSearchWidgetWrapper::exclusiveFilterFlags() };
105  for ( const QgsSearchWidgetWrapper::FilterFlag exclusiveFlag : exclusiveFilterFlags )
106  {
107  mFilterFlags &= ~exclusiveFlag;
108  }
109  // and set new exclusive flag
110  mFilterFlags |= flag;
111  }
112 
113  updateState();
114 }
115 
117 {
118  const auto exclusiveFilterFlags { QgsSearchWidgetWrapper::exclusiveFilterFlags() };
119  for ( const QgsSearchWidgetWrapper::FilterFlag flag : exclusiveFilterFlags )
120  {
121  if ( mFilterFlags & flag )
122  return true;
123  }
124  return false;
125 }
126 
127 void QgsSearchWidgetToolButton::aboutToShowMenu()
128 {
129  mMenu->clear();
130  bool fieldActive = false;
131  const auto exclusiveFilterFlags { QgsSearchWidgetWrapper::exclusiveFilterFlags() };
132  for ( const QgsSearchWidgetWrapper::FilterFlag flag : exclusiveFilterFlags )
133  {
134  if ( !( mAvailableFilterFlags & flag ) )
135  {
136  //unsupported
137  continue;
138  }
139 
140  QAction *action = mMenu->addAction( QgsSearchWidgetWrapper::toString( flag ) );
141  connect( action, &QAction::triggered, this, &QgsSearchWidgetToolButton::actionSelected );
142  action->setData( flag );
143  action->setCheckable( true );
144  if ( mFilterFlags & flag )
145  {
146  fieldActive = true;
147  action->setChecked( true );
148  }
149  }
150 
151  QAction *clearAction = mMenu->addAction( tr( "Exclude Field" ) );
152  connect( clearAction, &QAction::triggered, this, &QgsSearchWidgetToolButton::setInactive );
153  clearAction->setCheckable( true );
154  clearAction->setChecked( !fieldActive );
155  if ( mMenu->actions().count() > 0 )
156  {
157  mMenu->insertAction( mMenu->actions().at( 0 ), clearAction );
158  mMenu->insertSeparator( mMenu->actions().at( 1 ) );
159  }
160  else
161  mMenu->addAction( clearAction );
162 
163  mMenu->addSeparator();
164 
165  const auto nonExclusiveFilterFlags { QgsSearchWidgetWrapper::nonExclusiveFilterFlags() };
166  for ( const QgsSearchWidgetWrapper::FilterFlag flag : nonExclusiveFilterFlags )
167  {
168  if ( !( mAvailableFilterFlags & flag ) )
169  {
170  //unsupported
171  continue;
172  }
173 
174  QAction *action = mMenu->addAction( QgsSearchWidgetWrapper::toString( flag ) );
175  connect( action, &QAction::triggered, this, &QgsSearchWidgetToolButton::actionSelected );
176  action->setData( flag );
177  action->setCheckable( true );
178  if ( mFilterFlags & flag )
179  action->setChecked( true );
180  }
181 }
182 
183 void QgsSearchWidgetToolButton::actionSelected()
184 {
185  const QgsSearchWidgetWrapper::FilterFlag flag = static_cast< QgsSearchWidgetWrapper::FilterFlag >( qobject_cast< QAction * >( sender() )->data().toInt() );
186  toggleFlag( flag );
187 }
188 
189 void QgsSearchWidgetToolButton::searchWidgetValueChanged()
190 {
191  setActive();
192 }
193 
195 {
196  if ( !isActive() )
197  return;
198 
199  QgsSearchWidgetWrapper::FilterFlags newFlags;
200  const auto nonExclusiveFilterFlags { QgsSearchWidgetWrapper::nonExclusiveFilterFlags() };
201  for ( const QgsSearchWidgetWrapper::FilterFlag flag : nonExclusiveFilterFlags )
202  {
203  if ( !( mAvailableFilterFlags & flag ) || !( mFilterFlags & flag ) )
204  continue;
205  newFlags |= flag;
206  }
207  mFilterFlags = newFlags;
208  updateState();
209 }
210 
212 {
213  if ( isActive() )
214  return;
215 
216  const auto exclusiveFilterFlags { QgsSearchWidgetWrapper::exclusiveFilterFlags() };
217  for ( const QgsSearchWidgetWrapper::FilterFlag flag : exclusiveFilterFlags )
218  {
219  if ( mDefaultFilterFlags & flag )
220  {
221  toggleFlag( flag );
222  return;
223  }
224  }
225 }
226 
227 void QgsSearchWidgetToolButton::updateState()
228 {
229  bool active = false;
230  QStringList toolTips;
231  const auto exclusiveFilterFlags { QgsSearchWidgetWrapper::exclusiveFilterFlags() };
232  for ( const QgsSearchWidgetWrapper::FilterFlag flag : exclusiveFilterFlags )
233  {
234  if ( mFilterFlags & flag )
235  {
236  toolTips << QgsSearchWidgetWrapper::toString( flag );
237  active = true;
238  }
239  }
240  const auto nonExclusiveFilterFlags { QgsSearchWidgetWrapper::nonExclusiveFilterFlags() };
241  for ( const QgsSearchWidgetWrapper::FilterFlag flag : nonExclusiveFilterFlags )
242  {
243  if ( mFilterFlags & flag )
244  {
245  toolTips << QgsSearchWidgetWrapper::toString( flag ).toLower();
246  }
247  }
248 
249  if ( active )
250  {
251  const QString text = toolTips.join( QLatin1String( ", " ) );
252  setText( text );
253  setToolTip( text );
254  }
255  else
256  {
257  setText( tr( "Exclude Field" ) );
258  setToolTip( QString() );
259  }
260 
261  emit activeFlagsChanged( mFilterFlags );
262 }
void setInactive()
Sets the search widget as inactive, ie do not search the corresponding field.
void setActiveFlags(QgsSearchWidgetWrapper::FilterFlags flags)
Sets the current active filter flags for the widget.
void setDefaultFlags(QgsSearchWidgetWrapper::FilterFlags flags)
Sets the default filter flags to show in the widget.
void activeFlagsChanged(QgsSearchWidgetWrapper::FilterFlags flags)
Emitted when the active flags selected in the widget is changed.
QgsSearchWidgetToolButton(QWidget *parent=nullptr)
Constructor for QgsSearchWidgetToolButton.
void toggleFlag(QgsSearchWidgetWrapper::FilterFlag flag)
Toggles an individual active filter flag for the widget.
void setAvailableFlags(QgsSearchWidgetWrapper::FilterFlags flags)
Sets the available filter flags to show in the widget.
bool isActive() const
Returns true if the widget is set to be included in the search.
void setActive()
Sets the search widget as active by selecting the first available search type.
Shows a search widget on a filter form.
FilterFlag
Flags which indicate what types of filtering and searching is possible using the widget.
static QList< QgsSearchWidgetWrapper::FilterFlag > nonExclusiveFilterFlags()
Returns a list of non-exclusive filter flags, which can be combined with other flags (e....
static QList< QgsSearchWidgetWrapper::FilterFlag > exclusiveFilterFlags()
Returns a list of exclusive filter flags, which cannot be combined with other flags (e....
static QString toString(QgsSearchWidgetWrapper::FilterFlag flag)
Returns a translated string representing a filter flag.