libyui-ncurses  2.57.2
NCTable.h
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  Copyright (C) 2020 SUSE LLC
4  This library is free software; you can redistribute it and/or modify
5  it under the terms of the GNU Lesser General Public License as
6  published by the Free Software Foundation; either version 2.1 of the
7  License, or (at your option) version 3.0 of the License. This library
8  is distributed in the hope that it will be useful, but WITHOUT ANY
9  WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
11  License for more details. You should have received a copy of the GNU
12  Lesser General Public License along with this library; if not, write
13  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
14  Floor, Boston, MA 02110-1301 USA
15 */
16 
17 
18 /*-/
19 
20  File: NCTable.h
21 
22  Authors: Michael Andres <ma@suse.de>
23  Stefan Hundhammer <shundhammer@suse.de>
24 
25 /-*/
26 
27 #ifndef NCTable_h
28 #define NCTable_h
29 
30 #include <yui/YTable.h>
31 #include "NCPadWidget.h"
32 #include "NCTablePad.h"
33 #include "NCTableSort.h"
34 
35 
36 /**
37  * A table with rows and columns. Items may be nested.
38  *
39  * See also
40  * https://github.com/libyui/libyui-ncurses/blob/master/doc/nctable-and-nctree.md
41  */
42 class NCTable : public YTable, public NCPadWidget
43 {
44  friend std::ostream & operator<<( std::ostream & str, const NCTable & obj );
45 
46 public:
47 
48  NCTable( YWidget * parent,
49  YTableHeader * tableHeader,
50  bool multiSelection = false );
51 
52  virtual ~NCTable();
53 
54  /**
55  * Set the table header (the first line inside the table) as strings.
56  **/
57  void setHeader( const std::vector<std::string>& head );
58 
59  /**
60  * Get the table headers (the first line inside the table) as strings.
61  * Alignment flags are removed.
62  **/
63  std::vector<std::string> getHeader() const;
64 
65  /**
66  * Add items.
67  *
68  * Reimplemented from YSelectionWidget to optimize sorting.
69  **/
70  virtual void addItems( const YItemCollection & itemCollection );
71 
72  /**
73  * Add one item.
74  *
75  * Implemented from YSelectionWidget.
76  **/
77  virtual void addItem( YItem *yitem )
78  { addItem( yitem, NCTableLine::S_NORMAL ); }
79 
80  /**
81  * Add one item with the specified state and redraw the table.
82  *
83  * This overloaded version is first defined here and also used in
84  * NCPopupTable. Notice that this does not have a default value for the
85  * 'state' parameter to avoid clashing with the addItem( YItem * ) version
86  * inherited from YSelectionWidget which might be used from C++
87  * applications using libyui.
88  **/
89  virtual void addItem( YItem * yitem,
90  NCTableLine::STATE state );
91 
92  /**
93  * Delete all items and clear the pad.
94  *
95  * Implemented from YSelectionWidget.
96  **/
97  virtual void deleteAllItems();
98 
99  /**
100  * Get the index of the current item (the item under the cursor)
101  * or -1 if there is none.
102  **/
103  virtual int getCurrentIndex() const;
104 
105  /**
106  * Get the index of the current item (the item under the cursor)
107  * or -1 if there is none, i.e. the table is empty.
108  *
109  * FIXME: This is a misnomer of epic proportions. This should be named
110  * getCurrentIndex(). A method called getCurrentItem() should return the
111  * item (i.e. a pointer or a reference), not an index! But since this is
112  * all over the place in derived classes and in libyui-ncurses-pkg as well,
113  * this is not a trivial thing to fix.
114  **/
115  virtual int getCurrentItem() const;
116 
117  /**
118  * Return a pointer to the current item (the item under the cursor)
119  * or 0 if there is none, i.e. the table is empty.
120  *
121  * FIXME: This is what getCurrentItem() should really be.
122  **/
123  YItem * getCurrentItemPointer();
124 
125  /**
126  * Set the current item to the specified index.
127  **/
128  virtual void setCurrentItem( int index );
129 
130  /**
131  * Scroll to the first item.
132  **/
133  virtual void scrollToFirstItem();
134 
135  /**
136  * Select or deselect an item.
137  *
138  * Implemented from YSelectionWidget.
139  **/
140  virtual void selectItem( YItem *yitem, bool selected );
141 
142  /**
143  * Select the current item (the item under the cursor).
144  **/
145  void selectCurrentItem();
146 
147  /**
148  * Deselect all items.
149  *
150  * Implemented from YSelectionWidget.
151  **/
152  virtual void deselectAllItems();
153 
154  /**
155  * Keyboard input handler.
156  *
157  * This is the starting point for handling key events. From here, key
158  * events are propagated to the pad and to the items.
159  *
160  * Implemented from NCWidget.
161  **/
162  virtual NCursesEvent wHandleInput( wint_t key );
163 
164  /**
165  * libyui geometry management:
166  * Return the preferred width for this widget.
167  *
168  * Implemented from YWidget.
169  **/
170  virtual int preferredWidth();
171 
172  /**
173  * libyui geometry management:
174  * Return the preferred height for this widget.
175  *
176  * Implemented from YWidget.
177  **/
178  virtual int preferredHeight();
179 
180  /**
181  * libyui geometry management:
182  * Apply the width and height assigned from the parent layout widget.
183  *
184  * Implemented from YWidget.
185  **/
186  virtual void setSize( int newWidth, int newHeight );
187 
188  /**
189  * Set the label (the caption) above the table.
190  *
191  * YTable does not specify a label because a table has a whole row of
192  * headers.
193  **/
194  virtual void setLabel( const std::string & nlabel );
195 
196  /**
197  * Enable or disable this widget.
198  *
199  * Implemented from YWidget.
200  **/
201  virtual void setEnabled( bool do_bv );
202 
203  /**
204  * Set the keyboard focus to this widget.
205  *
206  * Implemented from YWidget.
207  **/
208  virtual bool setKeyboardFocus()
209  {
210  if ( !grabFocus() )
211  return YWidget::setKeyboardFocus();
212 
213  return true;
214  }
215 
216  /**
217  * Select an item by its hotkey.
218  * Used only in NCPopupTable::wHandleHotkey().
219  **/
220  bool setItemByKey( int key );
221 
222  /**
223  * Set the column separator character.
224  * Used only in NCPopupTable and in NCFileSelection.
225  **/
226  void SetSepChar( const chtype colSepchar )
227  { myPad()->SetSepChar( colSepchar ); }
228 
229  /**
230  * Set the separator width.
231  * Used only in NCPopupTable.
232  **/
233  void SetSepWidth( const unsigned sepwidth )
234  { myPad()->SetSepWidth( sepwidth ); }
235 
236  /**
237  * Set the hotkey column (?).
238  * Used only in NCPopupTable.
239  **/
240  void SetHotCol( int hcol )
241  { myPad()->SetHotCol( hcol ); }
242 
243  /**
244  * Flag: Is this a big list?
245  **/
246  bool bigList() const { return _bigList; }
247 
248  /**
249  * Set the "big list" flag.
250  **/
251  void setBigList( bool big ) { _bigList = big; }
252 
253  /**
254  * Remove all hotkeys from the pad.
255  **/
256  void stripHotkeys() { myPad()->stripHotkeys(); }
257 
258  /**
259  * Set a sorting strategy. This class takes ownership.
260  **/
261  void setSortStrategy( NCTableSortStrategyBase * newStrategy );
262 
263  /**
264  * Return the current sorting strategy.
265  **/
266  NCTableSortStrategyBase * sortStrategy() const { return _sortStrategy; }
267 
268 
269 protected:
270 
271  /**
272  * Code location for logging.
273  *
274  * Implemented from NCWidget.
275  **/
276  virtual const char * location() const { return "NCTable"; }
277 
278  /**
279  * Create an empty pad and set its background.
280  **/
281  virtual NCPad * CreatePad();
282 
283  /**
284  * Return the TreePad that belongs to this widget.
285  *
286  * Overloaded from NCPadWidget to narrow the type to the actual one used in
287  * this widget.
288  **/
289  virtual NCTablePad * myPad() const
290  { return dynamic_cast<NCTablePad*>( NCPadWidget::myPad() ); }
291 
292  /**
293  * Internal overloaded version of addItem().
294  *
295  * This creates a visual representation of the new table line consisting of
296  * individual cells. If 'preventRedraw' is 'false', the table is redrawn;
297  * otherwise, it is up to the caller to redraw the table.
298  *
299  * This is used in addItem( yitem ) and addItems( itemCollection ) in this
300  * class, but also in the derived NCFileSelection and NCPkgTable classes.
301  **/
302  virtual void addItem( YItem * yitem,
303  bool preventRedraw,
304  NCTableLine::STATE state = NCTableLine::S_NORMAL );
305 
306  /**
307  * Add a pad line (an NCTableLine) for 'yitem' and recurse into any of its
308  * children (and grandchildren etc.).
309  *
310  * Make sure to update _nestedItems (by iterating over all the YItems)
311  * before the first one is added so they will reserve some screen space for
312  * the tree hierarchy line graphics (using the prefix placeholder).
313  *
314  * This can realistically only be done when bulk-adding all YItems at
315  * once. If they are added one by one, the first few may not have any
316  * children, so their corresponding pad lines will not reserve screen space
317  * for the prefix, leading to ugly results.
318  *
319  * If there is no item nesting at all, this does not matter, of course.
320  **/
321  virtual void addPadLine( NCTableLine * parentLine,
322  YItem * yitem,
323  bool preventRedraw,
324  NCTableLine::STATE state = NCTableLine::S_NORMAL );
325 
326 
327  /**
328  * Build or rebuild the pad lines: Clear the pad, iterate over all YItems
329  * and add a corresponding NCTableLine to the pad. This recurses into any
330  * child YItems.
331  *
332  * This does not redraw the pad. Do that from the outside.
333  **/
334  void rebuildPadLines();
335 
336  /**
337  * Rebuild the table header line.
338  **/
339  void rebuildHeaderLine();
340 
341  /**
342  * Return the NCurses alignment string for the alignment of the
343  * specified column: One of "L", "C", "R" (Left, Center, Right).
344  **/
345  NCstring alignmentStr( int col );
346 
347  /**
348  * Return 'true' if any item in the item collection has any children,
349  * 'false' otherwise.
350  **/
351  bool hasNestedItems( const YItemCollection & itemCollection ) const;
352 
353  bool hasNestedItems( YItemConstIterator begin,
354  YItemConstIterator end ) const;
355 
356  /**
357  * Optimization for NCurses from libyui:
358  * Notification that multiple changes are about to come.
359  *
360  * Implemented from YWidget.
361  **/
362  virtual void startMultipleChanges() { startMultidraw(); }
363 
364  /**
365  * Optimization for NCurses from libyui:
366  * Notification that multiple changes are now finished.
367  *
368  * Implemented from YWidget.
369  **/
370  virtual void doneMultipleChanges() { stopMultidraw(); }
371 
372  /**
373  * Toggle the current item between selected and not selected.
374  **/
375  void toggleCurrentItem();
376 
377  /**
378  * Notification that a cell has now changed content:
379  * Set that cell's content also in the corresponding table line.
380  **/
381  void cellChanged( const YTableCell * cell );
382 
383  /**
384  * Change the cell with item index 'index' and column no. 'col' to 'newText'.
385  **/
386  void setCell( int index, int col, const std::string & newText );
387 
388  /**
389  * Recursively iterate over items and assign each one a unique item index.
390  *
391  * As long as the items don't have any child items, each one simply gets
392  * its initial position in the item collection. When there are children,
393  * however, there will be gaps between the index of one toplevel item and
394  * the next.
395  *
396  * It is generally unsafe to make assumptions about the indices except that
397  * they are unique within one table, and an item will keep its initial
398  * index, no matter how the table is sorted.
399  *
400  * The indices restart from 0 after the table has been cleared, i.e. after
401  * deleteAllItems() or at the start of setItems().
402  **/
403  void assignIndex( YItemConstIterator begin,
404  YItemConstIterator end );
405 
406  /**
407  * Assign an item a unique index.
408  **/
409  void assignIndex( YItem * item );
410 
411  /**
412  * Interactive sorting by a user-selected column:
413  *
414  * Open a popup with the (non-empty) column headers and let the user choose
415  * one for sorting.
416  **/
417  void interactiveSort();
418 
419  /**
420  * Sort the items by column no. 'sortCol' with the current sort strategy.
421  *
422  * This sorts the YItems and recreates all NCTableLines.
423  * All YItem pointers remain valid, but the NCTableLines do not.
424  **/
425  void sortItems( int sortCol, bool reverse = false );
426 
427  /**
428  * Sort the YItems between 'begin' and 'end' using the current sort
429  * strategy.
430  **/
431  void sortYItems( YItemIterator begin,
432  YItemIterator end );
433 
434 private:
435 
436  // Disable unwanted assignment opearator and copy constructor
437 
438  NCTable & operator=( const NCTable & );
439  NCTable( const NCTable & );
440 
441 
442  //
443  // Data members
444  //
445 
446  // Number of non-data prefix columns for things like the multi-selection
447  // indicator ("[ ]" / "[x]")
448  int _prefixCols;
449 
450  bool _nestedItems;
451  bool _bigList;
452  bool _multiSelect;
453 
454  int _lastSortCol;
455  bool _sortReverse;
456  NCTableSortStrategyBase * _sortStrategy; //< owned
457 };
458 
459 
460 std::ostream & operator<<( std::ostream & stream, const YItem * item );
461 
462 
463 #endif // NCTable_h
NCstring
A string with an optional hot key.
Definition: NCstring.h:36
NCTable::myPad
virtual NCTablePad * myPad() const
Return the TreePad that belongs to this widget.
Definition: NCTable.h:289
NCTable::stripHotkeys
void stripHotkeys()
Remove all hotkeys from the pad.
Definition: NCTable.h:256
NCTable::selectCurrentItem
void selectCurrentItem()
Select the current item (the item under the cursor).
Definition: NCTable.cc:463
NCTable::sortItems
void sortItems(int sortCol, bool reverse=false)
Sort the items by column no.
Definition: NCTable.cc:702
NCTable::location
virtual const char * location() const
Code location for logging.
Definition: NCTable.h:276
NCTable::setSortStrategy
void setSortStrategy(NCTableSortStrategyBase *newStrategy)
Set a sorting strategy.
Definition: NCTable.cc:750
NCTable::CreatePad
virtual NCPad * CreatePad()
Create an empty pad and set its background.
Definition: NCTable.cc:540
NCTable::scrollToFirstItem
virtual void scrollToFirstItem()
Scroll to the first item.
Definition: NCTable.cc:399
NCTable::addPadLine
virtual void addPadLine(NCTableLine *parentLine, YItem *yitem, bool preventRedraw, NCTableLine::STATE state=NCTableLine::S_NORMAL)
Add a pad line (an NCTableLine) for 'yitem' and recurse into any of its children (and grandchildren e...
Definition: NCTable.cc:259
NCTable::addItems
virtual void addItems(const YItemCollection &itemCollection)
Add items.
Definition: NCTable.cc:210
NCTablePad
An NCPad for an NCTable.
Definition: NCTablePad.h:62
NCTable::getCurrentIndex
virtual int getCurrentIndex() const
Get the index of the current item (the item under the cursor) or -1 if there is none.
Definition: NCTable.cc:391
NCTable::assignIndex
void assignIndex(YItemConstIterator begin, YItemConstIterator end)
Recursively iterate over items and assign each one a unique item index.
NCTable::getHeader
std::vector< std::string > getHeader() const
Get the table headers (the first line inside the table) as strings.
Definition: NCTable.cc:196
NCTableSortStrategyBase
Support classes for sorting by column in a table for use in an NCTablePad.
Definition: NCTableSort.h:36
NCTable::selectItem
virtual void selectItem(YItem *yitem, bool selected)
Select or deselect an item.
Definition: NCTable.cc:412
NCTable::startMultipleChanges
virtual void startMultipleChanges()
Optimization for NCurses from libyui: Notification that multiple changes are about to come.
Definition: NCTable.h:362
NCTable::preferredHeight
virtual int preferredHeight()
libyui geometry management: Return the preferred height for this widget.
Definition: NCTable.cc:507
NCTable::alignmentStr
NCstring alignmentStr(int col)
Return the NCurses alignment string for the alignment of the specified column: One of "L",...
Definition: NCTable.cc:113
NCTable::deleteAllItems
virtual void deleteAllItems()
Delete all items and clear the pad.
Definition: NCTable.cc:353
NCTable
A table with rows and columns.
Definition: NCTable.h:43
NCTable::SetSepWidth
void SetSepWidth(const unsigned sepwidth)
Set the separator width.
Definition: NCTable.h:233
NCTable::getCurrentItemPointer
YItem * getCurrentItemPointer()
Return a pointer to the current item (the item under the cursor) or 0 if there is none,...
Definition: NCTable.cc:380
NCTable::setHeader
void setHeader(const std::vector< std::string > &head)
Set the table header (the first line inside the table) as strings.
Definition: NCTable.cc:181
NCTable::interactiveSort
void interactiveSort()
Interactive sorting by a user-selected column:
Definition: NCTable.cc:639
NCTable::getCurrentItem
virtual int getCurrentItem() const
Get the index of the current item (the item under the cursor) or -1 if there is none,...
Definition: NCTable.cc:365
NCTable::setSize
virtual void setSize(int newWidth, int newHeight)
libyui geometry management: Apply the width and height assigned from the parent layout widget.
Definition: NCTable.cc:514
NCTable::bigList
bool bigList() const
Flag: Is this a big list?
Definition: NCTable.h:246
NCPad
A virtual window with a real viewport (which is NCursesWindow) and a scrolling mechanism.
Definition: NCPad.h:113
NCTable::setEnabled
virtual void setEnabled(bool do_bv)
Enable or disable this widget.
Definition: NCTable.cc:527
NCTable::rebuildPadLines
void rebuildPadLines()
Build or rebuild the pad lines: Clear the pad, iterate over all YItems and add a corresponding NCTabl...
Definition: NCTable.cc:320
NCTable::toggleCurrentItem
void toggleCurrentItem()
Toggle the current item between selected and not selected.
Definition: NCTable.cc:630
NCTable::rebuildHeaderLine
void rebuildHeaderLine()
Rebuild the table header line.
Definition: NCTable.cc:86
NCTable::SetHotCol
void SetHotCol(int hcol)
Set the hotkey column (?).
Definition: NCTable.h:240
NCTable::SetSepChar
void SetSepChar(const chtype colSepchar)
Set the column separator character.
Definition: NCTable.h:226
NCTable::setLabel
virtual void setLabel(const std::string &nlabel)
Set the label (the caption) above the table.
Definition: NCTable.cc:520
NCPadWidget::myPad
virtual NCPad * myPad() const
Return the current pad.
Definition: NCPadWidget.h:64
NCTable::cellChanged
void cellChanged(const YTableCell *cell)
Notification that a cell has now changed content: Set that cell's content also in the corresponding t...
Definition: NCTable.cc:155
NCTable::setBigList
void setBigList(bool big)
Set the "big list" flag.
Definition: NCTable.h:251
NCTable::setKeyboardFocus
virtual bool setKeyboardFocus()
Set the keyboard focus to this widget.
Definition: NCTable.h:208
NCTableLine
One line in a NCTable with multiple cells and an optional tree hierarchy.
Definition: NCTableItem.h:68
NCTable::setCurrentItem
virtual void setCurrentItem(int index)
Set the current item to the specified index.
Definition: NCTable.cc:406
NCTable::sortStrategy
NCTableSortStrategyBase * sortStrategy() const
Return the current sorting strategy.
Definition: NCTable.h:266
NCTable::sortYItems
void sortYItems(YItemIterator begin, YItemIterator end)
Sort the YItems between 'begin' and 'end' using the current sort strategy.
Definition: NCTable.cc:733
NCTable::hasNestedItems
bool hasNestedItems(const YItemCollection &itemCollection) const
Return 'true' if any item in the item collection has any children, 'false' otherwise.
Definition: NCTable.cc:334
NCTable::assignIndex
void assignIndex(YItem *item)
Assign an item a unique index.
NCTable::setCell
void setCell(int index, int col, const std::string &newText)
Change the cell with item index 'index' and column no.
Definition: NCTable.cc:129
NCTable::addItem
virtual void addItem(YItem *yitem)
Add one item.
Definition: NCTable.h:77
NCursesEvent
Definition: NCurses.h:73
NCTable::setItemByKey
bool setItemByKey(int key)
Select an item by its hotkey.
Definition: NCTable.cc:534
NCPadWidget
Base class for widgets with scrollable contents.
Definition: NCPadWidget.h:40
NCTable::deselectAllItems
virtual void deselectAllItems()
Deselect all items.
Definition: NCTable.cc:472
NCTable::doneMultipleChanges
virtual void doneMultipleChanges()
Optimization for NCurses from libyui: Notification that multiple changes are now finished.
Definition: NCTable.h:370
NCTable::preferredWidth
virtual int preferredWidth()
libyui geometry management: Return the preferred width for this widget.
Definition: NCTable.cc:500
NCTable::wHandleInput
virtual NCursesEvent wHandleInput(wint_t key)
Keyboard input handler.
Definition: NCTable.cc:556