OpenWalnut  1.5.0dev
WPropertySelectionWidget.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <cmath>
26 #include <string>
27 
28 #include <QPalette>
29 #include <QListWidgetItem>
30 #include <QPushButton>
31 #include <QToolButton>
32 #include <QScrollBar>
33 
34 #include "core/common/WLogger.h"
35 #include "core/common/WPropertyVariable.h"
36 #include "core/common/WItemSelector.h"
37 #include "core/common/WItemSelection.h"
38 
39 #include "../WGuiConsts.h"
40 #include "../WQtGui.h"
41 #include "../WMainWindow.h"
42 
43 #include "WPropertySelectionWidget.h"
44 
45 /**
46  * This function ensure a maximum icon site by scaling large pixmaps. Pixmaps smaller than the maximum size are not scaled.
47  *
48  * \param pix the pixmap to scale if needed.
49  *
50  * \return the maybe scaled pixmap.
51  */
52 QPixmap ensureSize( QPixmap pix )
53 {
54  // maximum size
55  int maxW = WMIN_WIDGET_HEIGHT;
56  int maxH = WMIN_WIDGET_HEIGHT;
57 
58  if( ( pix.width() > maxW ) || ( pix.height() > maxH ) )
59  {
60  return pix.scaled( maxW, maxH, Qt::KeepAspectRatio );
61  }
62 
63  // no scaling needed
64  return pix;
65 }
66 
67 WPropertySelectionWidget::WPropertySelectionWidget( WPropSelection property, QGridLayout* propertyGrid, QWidget* parent ):
68  WPropertyWidget( property, propertyGrid, parent ),
69  m_selectionProperty( property ),
70  m_layout( &m_parameterWidgets ),
71  m_update( false )
72 {
73  // initialize members
74  m_combo = NULL;
75  m_list = NULL;
76  m_layout.setMargin( WGLOBAL_MARGIN );
77  m_layout.setSpacing( WGLOBAL_SPACING );
78 
79  // initialize the proper widget
80  // Lists are used if the selection of multiple elements is allowed
81  if( m_selectionProperty->countConstraint( PC_SELECTONLYONE ) != 0 )
82  {
83  m_combo = new QComboBox( &m_parameterWidgets );
84  m_combo->setMinimumHeight( WMIN_WIDGET_HEIGHT );
85 
86  // layout
87  m_layout.addWidget( m_combo, 0, 0 );
88 
89  // connect
90  connect( m_combo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( comboSelectionChanged( int ) ) );
91  }
92  else
93  {
94  m_list = new QListWidget( &m_parameterWidgets );
95  m_list->setSelectionMode( QAbstractItemView::ExtendedSelection );
96 
97  // layout
98  m_layout.addWidget( m_list, 0, 0 );
99 
100  // add a select-all button
101  QToolButton* selAllButton = new QToolButton( this );
102  QAction* act = new QAction( WQtGui::getMainWindow()->getIconManager()->getIcon( "select_all" ), "Select All", this );
103  connect( act, SIGNAL( triggered( bool ) ), m_list, SLOT( selectAll() ) );
104  selAllButton->setDefaultAction( act );
105  selAllButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
106  selAllButton->setMinimumHeight( WMIN_WIDGET_HEIGHT );
107  selAllButton->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed ) );
108 
109  m_layout.addWidget( selAllButton, 1, 0 );
110 
111  // connect
112  connect( m_list, SIGNAL( itemSelectionChanged() ), this, SLOT( listSelectionChanged() ) );
113  }
114 
115  // Information Output ( Property Purpose = PV_PURPOSE_INFORMATION )
116  // In this case -> use some disabled lists/combos here
117  if( m_property->getPurpose() == PV_PURPOSE_INFORMATION )
118  {
119  m_informationWidgets.setLayout( &m_layout );
120 
121  if( m_list )
122  {
123  m_list->setEnabled( false );
124  }
125  else
126  {
127  m_combo->setEnabled( false );
128  }
129  }
130  else
131  {
132  m_parameterWidgets.setLayout( &m_layout );
133  }
134 
135  // set the initial values
136  update();
137 }
138 
140 {
141  // cleanup
142 }
143 
145 {
146  m_update = true;
147 
149 
150  // we need to read-lock the whole selection to ensure that the underlying selection can't be changed while creating the items
151  s.lock();
152  // we also need to check whether the selector is valid. Only valid selectors are allowed to use. You can check validity by calling
153  // WItemSelector::isValid. The simpler way is to get a new selector directly as selectors in properties are always valid (due to the
154  // WPropertyConstraintIsValid - constraint).
155  // NOTE: do NOT overwrite the current selector in "s" as it keeps the lock.
156  WItemSelector sValid = m_selectionProperty->get();
157 
158  //apply selection
159  if( m_combo )
160  {
161  disconnect( m_combo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( comboSelectionChanged( int ) ) );
162 
163  m_combo->clear();
164 
165  // add all items from the selection set:
166  for( size_t i = 0; i < sValid.sizeAll(); ++i )
167  {
168  m_combo->addItem( QString::fromStdString( sValid.atAll( i )->getName() ) );
169  // if there is an icon -> show it
170  if( sValid.atAll( i )->getIcon() )
171  {
172  // scale the pixmap to a maximum size if larger
173  QPixmap pix = ensureSize( QPixmap( sValid.atAll( i )->getIcon() ) );
174 
175  // set icon
176  m_combo->setItemIcon( i, QIcon( pix ) );
177  m_combo->setIconSize( QSize( pix.width(), pix.height() ) );
178  }
179  }
180 
181  // mark the currently selected item. Just take care that there might be no item selected.
182  if( sValid.size() == 0 )
183  {
184  m_combo->setCurrentIndex( -1 );
185  }
186  else
187  {
188  // as there is the SELECTONLYONE constraint -> if something is selected, it always is the first one
189  m_combo->setCurrentIndex( sValid.getItemIndexOfSelected( 0 ) );
190  }
191 
192  connect( m_combo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( comboSelectionChanged( int ) ) );
193  }
194  else
195  {
196  disconnect( m_list, SIGNAL( itemSelectionChanged() ), this, SLOT( listSelectionChanged() ) );
197 
198  int scrollPosition = m_list->verticalScrollBar()->sliderPosition();
199 
200  m_list->clearSelection();
201  m_list->clear();
202 
203  // add all items from the selection set:
204  for( size_t i = 0; i < sValid.sizeAll(); ++i )
205  {
206  // Create a custom widget which contains the name and description
207  QWidget* widget = new QWidget( m_list );
208  QHBoxLayout* layoutWidget = new QHBoxLayout();
209  layoutWidget->setContentsMargins( 5, 0, 0, 0 );
210  layoutWidget->setSpacing( 0 );
211  layoutWidget->setSizeConstraint( QLayout::SetMaximumSize );
212  widget->setLayout( layoutWidget );
213 
214  QWidget* innerWidget = new QWidget( widget );
215  QVBoxLayout* layoutInnerWidget = new QVBoxLayout();
216  layoutInnerWidget->setContentsMargins( 5, 0, 0, 0 );
217  layoutInnerWidget->setSpacing( 0 );
218  layoutInnerWidget->setSizeConstraint( QLayout::SetMaximumSize );
219  innerWidget->setLayout( layoutInnerWidget );
220 
221  // if there is an icon -> show it
222  if( sValid.atAll( i )->getIcon() )
223  {
224  QLabel* icon = new QLabel();
225  QSizePolicy sizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred ); // <-- scale it down
226  icon->setSizePolicy( sizePolicy );
227  icon->setPixmap( ensureSize( QPixmap( sValid.atAll( i )->getIcon() ) ) );
228  layoutWidget->addWidget( icon );
229  }
230 
231  // Add Name and Description
232  layoutInnerWidget->addWidget( new QLabel( "<b>" + QString::fromStdString( sValid.atAll( i )->getName() )+ "</b>" ) );
233  // if there is no description -> no widget added to save space
234  if( !sValid.atAll( i )->getDescription().empty() )
235  {
236  layoutInnerWidget->addWidget( new QLabel( QString::fromStdString( sValid.atAll( i )->getDescription() ) ) );
237  }
238 
239  layoutWidget->addWidget( innerWidget );
240 
241  // add Item
242  QListWidgetItem* item = new QListWidgetItem();
243  item->setSizeHint( widget->sizeHint() );
244  m_list->addItem( item );
245  m_list->setItemWidget( item, widget );
246  m_list->setMinimumHeight( widget->height() * 3.5 );
247  }
248 
249  // select all items
250  for( size_t i = 0; i < sValid.size(); ++i )
251  {
252  m_list->item( sValid.getItemIndexOfSelected( i ) )->setSelected( true );
253  }
254 
255  m_list->verticalScrollBar()->setSliderPosition( scrollPosition );
256 
257  connect( m_list, SIGNAL( itemSelectionChanged() ), this, SLOT( listSelectionChanged() ) );
258  }
259 
260  m_update = false;
261 }
262 
264 {
265  // grab the list of selected indices, it is easy here as it always is one
267  l.push_back( index );
268 
269  // new selector
270  WItemSelector ns = m_selectionProperty->get().newSelector( l );
271 
272  // set it
273  // NOTE: set automatically checks the validity of the value
274  invalidate( !m_selectionProperty->set( ns ) );
275 }
276 
278 {
279  // unfortunately this slot is also called if the selection gets changed by the program. We are not interested in this case.
280  if( m_update )
281  {
282  return;
283  }
284 
285  // grab the list of selected indices
287 
288  // go through the item list
289  for( int i = 0; i < m_list->count(); ++i )
290  {
291  if( m_list->item( i )->isSelected() )
292  {
293  l.push_back( i );
294  }
295  }
296 
297  // create new selector
298  WItemSelector ns = m_selectionProperty->get().newSelector( l );
299 
300  // set it
301  // NOTE: set automatically checks the validity of the value
302  invalidate( !m_selectionProperty->set( ns ) );
303 }
304 
This class represents a subset of a WItemSelection.
Definition: WItemSelector.h:53
std::vector< size_t > IndexList
The type used for storing index lists.
Definition: WItemSelector.h:59
virtual size_t size() const
The number of selected items.
virtual size_t sizeAll() const
Gives the count of elements in the set of selectable items.
virtual const std::shared_ptr< WItemSelectionItem > atAll(size_t index) const
Gets the item with the given index from the WItemSelection.
void lock()
Read locks the underlying selection.
virtual size_t getItemIndexOfSelected(size_t index) const
Helps to get the index of an selected item in the WItemSelection.
WPropSelection m_selectionProperty
The integer property represented by this widget.
QListWidget * m_list
The list holding all items.
WPropertySelectionWidget(WPropSelection property, QGridLayout *propertyGrid, QWidget *parent=0)
Constructor.
virtual ~WPropertySelectionWidget()
Destructor.
QGridLayout m_layout
Layout used to position the label and the checkbox.
QComboBox * m_combo
The combobox holding all items.
void listSelectionChanged()
Called whenever the selection in m_list has changed.
bool m_update
True if a selection update is currently in progress.
virtual void update()
Called whenever the widget should update.
void comboSelectionChanged(int index)
Selection of the combobox has changed.
Class building the base for all widgets representing properties.
std::shared_ptr< WPropertyBase > m_property
The property handled by the widget.
QWidget m_informationWidgets
The widget containing a layout and provides the widgets for showing information properties.
QWidget m_parameterWidgets
The widget containing a layout and provides the edit widgets for the property.
virtual void invalidate(bool invalid=true)
This method marks this widget as invalid.
static WMainWindow * getMainWindow()
Returns the current main window instance or NULL if not existent.
Definition: WQtGui.cpp:88