libyui  3.12.1
YSelectionWidget.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: YSelectionWidget.cc
20 
21  Author: Stefan Hundhammer <shundhammer@suse.de>
22 
23 /-*/
24 
25 
26 #define YUILogComponent "ui"
27 #include "YUILog.h"
28 
29 #include <algorithm>
30 #include "YSelectionWidget.h"
31 #include "YUIException.h"
32 #include "YApplication.h"
33 
34 using std::string;
35 
36 
38 {
39  YSelectionWidgetPrivate( const string & label,
40  bool enforceSingleSelection,
41  bool recursiveSelection )
42  : label( label )
43  , enforceSingleSelection( enforceSingleSelection )
44  , enforceInitialSelection( true )
45  , recursiveSelection ( recursiveSelection )
46  {}
47 
48  string label;
49  bool enforceSingleSelection;
50  bool enforceInitialSelection;
51  bool recursiveSelection;
52  string iconBasePath;
53  YItemCollection itemCollection;
54 };
55 
56 
57 
58 
60  const string & label,
61  bool enforceSingleSelection ,
62  bool recursiveSelection )
63  : YWidget( parent )
64  , priv( new YSelectionWidgetPrivate( label, enforceSingleSelection, recursiveSelection ) )
65 {
66  YUI_CHECK_NEW( priv );
67 
69  YUI_THROW( YUIException( "recursiveSelection is only available for multiSelection Widgets."));
70 
71 }
72 
73 
75 {
77 }
78 
79 
81 {
83 
84  while ( it != itemsEnd() )
85  {
86  YItem * item = *it;
87  ++it;
88  delete item;
89 
90  // No need to check for item->hasChildren() and iterate recursively
91  // over the children: The item will take care of its children in its
92  // destructor.
93  }
94 
95  priv->itemCollection.clear();
96 }
97 
98 
100 {
101  return priv->label;
102 }
103 
104 
105 void YSelectionWidget::setLabel( const string & newLabel )
106 {
107  priv->label = newLabel;
108 }
109 
110 
112 {
113  return priv->enforceSingleSelection;
114 }
115 
116 
118 {
119  if ( priv->enforceSingleSelection )
120  priv->enforceInitialSelection = newVal;
121 }
122 
123 
125 {
126  return priv->enforceInitialSelection && priv->enforceSingleSelection;
127 }
128 
129 
131 {
132  return priv->recursiveSelection;
133 }
134 
135 
136 
137 void YSelectionWidget::setEnforceSingleSelection( bool enforceSingleSelection )
138 {
139  priv->enforceSingleSelection = enforceSingleSelection;
140 }
141 
142 
143 void YSelectionWidget::setShortcutString( const std::string & str )
144 {
145  setLabel( str );
146  shortcutChanged();
147 }
148 
149 
150 void YSelectionWidget::setIconBasePath( const string & basePath )
151 {
152  priv->iconBasePath = basePath;
153 }
154 
155 
157 {
158  return priv->iconBasePath;
159 }
160 
161 
162 string YSelectionWidget::iconFullPath( const string & iconName ) const
163 {
164  string fullPath;
165 
166  if ( ! iconName.empty() )
167  {
168  if ( iconName[0] == '/' )
169  return iconName;
170 
171  if ( priv->iconBasePath.empty() ||
172  priv->iconBasePath[0] != '/' )
173  {
174  return YUI::yApp()->iconLoader()->findIcon( iconName );
175  }
176 
177  fullPath += priv->iconBasePath + "/" + iconName;
178  }
179 
180  return fullPath;
181 }
182 
183 
184 string YSelectionWidget::iconFullPath( YItem * item ) const
185 {
186  if ( item )
187  return iconFullPath( item->iconName() );
188  else
189  return "";
190 }
191 
192 
194 {
195  YUI_CHECK_PTR( item );
196 
197  if ( item->parent() )
198  {
199  YUI_THROW( YUIException( "Item already owned by parent item -"
200  " call addItem() only for toplevel items!" ) );
201  }
202 
203  // Add the new item to the item list
204 
205  priv->itemCollection.push_back( item );
206  item->setIndex( priv->itemCollection.size() - 1 );
207 
208  // yuiDebug() << "Adding item \"" << item->label() << "\"" << endl;
209 
210  //
211  // Enforce single selection (if applicable)
212  //
213 
214  if ( priv->enforceSingleSelection )
215  {
216  YItem * newItemSelected = 0;
217 
218  if ( item->selected() )
219  {
220  newItemSelected = item;
221  }
222  else
223  {
224  newItemSelected = findSelectedItem( item->childrenBegin(),
225  item->childrenEnd() );
226  }
227 
228  if ( newItemSelected )
229  {
230  // This looks expensive, but it is not: Even though deselectAllItems()
231  // searches the complete item list and deselects them all.
232  //
233  // This prevents that the calling application does this systematically wrong
234  // and sets the "selected" flag for more items or children.
235 
237  newItemSelected->setSelected( true );
238  }
239 
240 
241  if ( priv->enforceInitialSelection )
242  {
243  // Make sure there is one item selected initially.
244  //
245  // If any other subsequently added items are to be selected, they will
246  // override this initial selection.
247 
248  if ( priv->itemCollection.size() == 1 )
249  item->setSelected( true );
250  }
251  }
252 }
253 
254 
255 void YSelectionWidget::addItem( const string & itemLabel,
256  const string & iconName,
257  bool selected )
258 {
259  YItem * item = new YItem( itemLabel, iconName, selected );
260  YUI_CHECK_NEW( item );
261  addItem( item );
262 }
263 
264 
265 void YSelectionWidget::addItem( const string & itemLabel, bool selected )
266 {
267  addItem( itemLabel, "", selected );
268 }
269 
270 
271 void YSelectionWidget::addItems( const YItemCollection & itemCollection )
272 {
273  OptimizeChanges below( *this ); // Delay screen updates until this block is left
274  priv->itemCollection.reserve( priv->itemCollection.size() + itemCollection.size() );
275 
276  for ( YItemConstIterator it = itemCollection.begin();
277  it != itemCollection.end();
278  ++it )
279  {
280  addItem( *it );
281 
282  // No need to check for (*it)->hasChildren() and iterate recursively
283  // over the children: Any children of this item simply remain in this
284  // item's YItemCollection.
285  }
286 }
287 
288 
291 {
292  return priv->itemCollection.begin();
293 }
294 
297 {
298  return priv->itemCollection.begin();
299 }
300 
301 
304 {
305  return priv->itemCollection.end();
306 }
307 
308 
311 {
312  return priv->itemCollection.end();
313 }
314 
315 
317 {
318  return ! priv->itemCollection.empty();
319 }
320 
321 
323 {
324  return priv->itemCollection.size();
325 }
326 
327 
328 YItem *
330 {
331  if ( priv->itemCollection.empty() )
332  return 0;
333  else
334  return priv->itemCollection.front();
335 }
336 
337 
338 YItem *
339 YSelectionWidget::itemAt( int index ) const
340 {
341  if ( index < 0 || index >= (int) priv->itemCollection.size() )
342  return 0;
343 
344  return priv->itemCollection[ index ];
345 }
346 
347 
348 YItem *
350 {
351  return findSelectedItem( itemsBegin(), itemsEnd() );
352 }
353 
354 
355 YItem *
357  YItemConstIterator end )
358 {
359  for ( YItemConstIterator it = begin; it != end; ++it )
360  {
361  const YItem * item = *it;
362 
363  if ( item->selected() )
364  {
365  return *it;
366  }
367  if ( item->hasChildren() )
368  {
370  item->childrenEnd() );
371  if ( selectedItem )
372  {
373  // yuiDebug() << "Selected item: \"" << selectedItem->label() << "\"" << endl;
374  return selectedItem;
375  }
376  }
377  }
378 
379  return 0;
380 }
381 
382 
385 {
388 
389  return selectedItems;
390 }
391 
392 
393 void
395  YItemConstIterator begin,
396  YItemConstIterator end )
397 {
398  for ( YItemConstIterator it = begin; it != end; ++it )
399  {
400  YItem * item = *it;
401 
402  if ( item->selected() )
403  selectedItems.push_back( item );
404 
405  if ( item->hasChildren() )
406  {
408  item->childrenBegin(),
409  item->childrenEnd() );
410  }
411  }
412 }
413 
414 
416 {
417  return selectedItem() != 0;
418 }
419 
420 
421 void YSelectionWidget::selectItem( YItem * item, bool selected )
422 {
423  YUI_CHECK_PTR( item );
424 
425  if ( ! itemsContain( item ) )
426  YUI_THROW( YUIException( "Item does not belong to this widget" ) );
427 
428  if ( priv->enforceSingleSelection && selected )
429  {
430  YItem * oldSelectedItem = selectedItem();
431 
432  if ( oldSelectedItem )
433  oldSelectedItem->setSelected( false );
434  }
435 
436 
437  if ( recursiveSelection() && item->hasChildren() )
438  {
439  for ( YItemIterator it = item->childrenBegin(); it != item->childrenEnd(); ++it )
440  {
441  YItem * item = *it;
442  selectItem(item, selected );
443  item->setSelected( selected );
444  }
445  }
446 
447  item->setSelected( selected );
448 }
449 
450 
451 void YSelectionWidget::setItemStatus( YItem * item, int status )
452 {
453  selectItem( item, status != 0 );
454 }
455 
456 
457 bool YSelectionWidget::itemsContain( YItem * wantedItem ) const
458 {
459  return itemsContain( wantedItem, itemsBegin(), itemsEnd() );
460 }
461 
462 
463 
464 bool
466  YItemConstIterator begin,
467  YItemConstIterator end ) const
468 {
469  for ( YItemConstIterator it = begin; it != end; ++it )
470  {
471  const YItem * item = *it;
472 
473  if ( item == wantedItem )
474  return true;
475 
476  if ( item->hasChildren() )
477  {
478  if ( itemsContain( wantedItem,
479  item->childrenBegin(),
480  item->childrenEnd() ) )
481  {
482  return true;
483  }
484  }
485  }
486 
487  return false;
488 }
489 
490 
492 {
494 }
495 
496 
498  YItemIterator end )
499 {
500  for ( YItemConstIterator it = begin; it != end; ++it )
501  {
502  YItem * item = *it;
503 
504  item->setSelected( false );
505 
506  if ( item->hasChildren() )
507  deselectAllItems( item->childrenBegin(), item->childrenEnd() );
508  }
509 }
510 
511 
512 YItem *
513 YSelectionWidget::findItem( const string & wantedItemLabel ) const
514 {
515  return findItem( wantedItemLabel, itemsBegin(), itemsEnd() );
516 }
517 
518 
519 YItem *
520 YSelectionWidget::findItem( const string & wantedItemLabel,
521  YItemConstIterator begin,
522  YItemConstIterator end ) const
523 {
524  for ( YItemConstIterator it = begin; it != end; ++it )
525  {
526  YItem * item = *it;
527 
528  if ( item->label() == wantedItemLabel )
529  return item;
530 
531  if ( item->hasChildren() )
532  {
533  YItem * wantedItem = findItem( wantedItemLabel,
534  item->childrenBegin(),
535  item->childrenEnd() );
536  if ( wantedItem )
537  return wantedItem;
538  }
539  }
540 
541  return 0;
542 }
543 
544 
546 {
547  yuiMilestone() << "Items:" << endl;
548 
549  for ( YItemConstIterator it = itemsBegin(); it != itemsEnd(); ++it )
550  {
551  string status;
552 
553  switch ( (*it)->status() )
554  {
555  case 0: status = "[ ]"; break;
556  case 1: status = "[x]"; break;
557  default:
558  {
559  char buffer[80];
560  sprintf( buffer, "[%d]", (*it)->status() );
561  status = buffer;
562  }
563  }
564 
565  yuiMilestone() << " " << status << " "
566  << (*it)->label()
567  << endl;
568  }
569 
570  yuiMilestone() << "---" << endl;
571 }
YItem::label
std::string label() const
Return this item's label.
Definition: YItem.h:97
YWidget
Abstract base class of all UI widgets.
Definition: YWidget.h:55
YSelectionWidget::selectedItems
virtual YItemCollection selectedItems()
Return all selected items.
Definition: YSelectionWidget.cc:384
YWidget::end
YWidgetListIterator end()
A helper for the range-based "for" loop.
Definition: YWidget.h:245
YItem::setIndex
void setIndex(int index)
Set this item's index.
Definition: YItem.h:148
YSelectionWidget::setShortcutString
virtual void setShortcutString(const std::string &str)
Set the string of this widget that holds the keyboard shortcut.
Definition: YSelectionWidget.cc:143
YItemIterator
YItemCollection::iterator YItemIterator
Mutable iterator over YItemCollection.
Definition: YItem.h:42
YItemCollection
std::vector< YItem * > YItemCollection
Collection of pointers to YItem.
Definition: YItem.h:39
YSelectionWidget::setItemStatus
virtual void setItemStatus(YItem *item, int status)
Set the status of an item.
Definition: YSelectionWidget.cc:451
YSelectionWidget::hasSelectedItem
bool hasSelectedItem()
Return 'true' if any item is selected.
Definition: YSelectionWidget.cc:415
YItem::childrenBegin
virtual YItemIterator childrenBegin()
Return an iterator that points to the first child item of this item.
Definition: YItem.h:201
YSelectionWidget::~YSelectionWidget
virtual ~YSelectionWidget()
Destructor.
Definition: YSelectionWidget.cc:74
YItem::selected
bool selected() const
Return 'true' if this item is currently selected.
Definition: YItem.h:122
YSelectionWidgetPrivate
Definition: YSelectionWidget.cc:38
YItem::iconName
std::string iconName() const
Return this item's icon name.
Definition: YItem.h:107
YSelectionWidget::itemsEnd
YItemIterator itemsEnd()
Return an iterator that points behind the last item.
Definition: YSelectionWidget.cc:303
YSelectionWidget::selectedItem
virtual YItem * selectedItem()
Return the (first) selected item or 0 if none is selected.
Definition: YSelectionWidget.cc:349
YSelectionWidget::findItem
YItem * findItem(const std::string &itemLabel) const
Find the (first) item with the specified label.
Definition: YSelectionWidget.cc:513
YWidget::begin
YWidgetListIterator begin()
A helper for the range-based "for" loop.
Definition: YWidget.h:238
YSelectionWidget::label
std::string label() const
Return this widget's label (the caption above the item list).
Definition: YSelectionWidget.cc:99
YApplication::iconLoader
YIconLoader * iconLoader()
Return the icon loader.
Definition: YApplication.cc:107
YItem::parent
virtual YItem * parent() const
Return this item's parent item or 0 if it is a toplevel item.
Definition: YItem.h:218
YSelectionWidget::hasItems
bool hasItems() const
Return 'true' if this widget has any items.
Definition: YSelectionWidget.cc:316
YSelectionWidget::deselectAllItems
virtual void deselectAllItems()
Deselect all items.
Definition: YSelectionWidget.cc:491
YSelectionWidget::enforceSingleSelection
bool enforceSingleSelection() const
Return 'true' if this base class should enforce single selection.
Definition: YSelectionWidget.cc:111
YSelectionWidget::iconBasePath
std::string iconBasePath() const
Return this widget's base path where to look up icons as set with setIconBasePath().
Definition: YSelectionWidget.cc:156
YSelectionWidget::enforceInitialSelection
bool enforceInitialSelection() const
Return 'true' if this class enforces an initial selection.
Definition: YSelectionWidget.cc:124
YItem::hasChildren
virtual bool hasChildren() const
Return 'true' if this item has any child items.
Definition: YItem.h:182
YSelectionWidget::iconFullPath
std::string iconFullPath(const std::string &iconName) const
Return the full path + file name for the specified icon name.
Definition: YSelectionWidget.cc:162
YSelectionWidget::firstItem
YItem * firstItem() const
Return the first item or 0 if there is none.
Definition: YSelectionWidget.cc:329
YSelectionWidget::setEnforceSingleSelection
void setEnforceSingleSelection(bool on)
Set single selection mode on or off.
Definition: YSelectionWidget.cc:137
YSelectionWidget::recursiveSelection
bool recursiveSelection() const
Return 'true' if this base class should select children recursively.
Definition: YSelectionWidget.cc:130
YSelectionWidget::setLabel
virtual void setLabel(const std::string &newLabel)
Change this widget's label (the caption above the item list).
Definition: YSelectionWidget.cc:105
YItem::setSelected
void setSelected(bool sel=true)
Select or unselect this item.
Definition: YItem.h:129
YSelectionWidget::itemAt
YItem * itemAt(int index) const
Return the item at index 'index' (from 0) or 0 if there is no such item.
Definition: YSelectionWidget.cc:339
YSelectionWidget::findSelectedItem
YItem * findSelectedItem(YItemConstIterator begin, YItemConstIterator end)
Recursively try to find the first selected item between iterators 'begin' and 'end'.
Definition: YSelectionWidget.cc:356
YSelectionWidget::itemsBegin
YItemIterator itemsBegin()
Return an iterator that points to the first item.
Definition: YSelectionWidget.cc:290
YSelectionWidget::selectItem
virtual void selectItem(YItem *item, bool selected=true)
Select or deselect an item.
Definition: YSelectionWidget.cc:421
YSelectionWidget::setIconBasePath
void setIconBasePath(const std::string &basePath)
Set this widget's base path where to look up icons.
Definition: YSelectionWidget.cc:150
YSelectionWidget::dumpItems
void dumpItems() const
Dump all items and their selection state to the log.
Definition: YSelectionWidget.cc:545
OptimizeChanges
Helper class that calls startMultipleChanges() in its constructor and cares about the necessary call ...
Definition: YWidget_OptimizeChanges.h:45
YSelectionWidget::setEnforceInitialSelection
void setEnforceInitialSelection(bool on)
In single selection mode, enforce selecting an initial item ('true' by default).
Definition: YSelectionWidget.cc:117
YSelectionWidget::YSelectionWidget
YSelectionWidget(YWidget *parent, const std::string &label, bool enforceSingleSelection, bool recursiveSelection=false)
Constructor.
Definition: YSelectionWidget.cc:59
YSelectionWidget::deleteAllItems
virtual void deleteAllItems()
Delete all items.
Definition: YSelectionWidget.cc:80
YItem::childrenEnd
virtual YItemIterator childrenEnd()
Return an iterator that points after the last child item of this item.
Definition: YItem.h:210
YSelectionWidget::addItems
virtual void addItems(const YItemCollection &itemCollection)
Add multiple items.
Definition: YSelectionWidget.cc:271
YSelectionWidget::shortcutChanged
virtual void shortcutChanged()
Notification that any shortcut of any item was changed by the shortcut conflict manager YShortcutMana...
Definition: YSelectionWidget.h:292
YSelectionWidget::itemsCount
int itemsCount() const
Return the number of items.
Definition: YSelectionWidget.cc:322
YSelectionWidget::addItem
virtual void addItem(YItem *item_disown)
Add one item.
Definition: YSelectionWidget.cc:193
YSelectionWidget::itemsContain
bool itemsContain(YItem *item) const
Return 'true' if this widget's items contain the specified item.
Definition: YSelectionWidget.cc:457
YUIException
Base class for UI Exceptions.
Definition: YUIException.h:298
YSelectionWidget::findSelectedItems
void findSelectedItems(YItemCollection &selectedItems, YItemConstIterator begin, YItemConstIterator end)
Recursively find all selected items between iterators 'begin' and 'end' and add each of them to the '...
Definition: YSelectionWidget.cc:394
YItemConstIterator
YItemCollection::const_iterator YItemConstIterator
Const iterator over YItemCollection.
Definition: YItem.h:45
YItem
Simple item class for SelectionBox, ComboBox, MultiSelectionBox etc.
Definition: YItem.h:56