SGL
gtable.h
1 /*
2  * File: gtable.h
3  * --------------
4  * This file exports the GTable class for a graphical editable 2D table.
5  *
6  * @author Marty Stepp
7  * @version 2021/04/09
8  * - added sgl namespace
9  * @version 2021/04/03
10  * - removed dependency on custom collections
11  * @version 2018/08/23
12  * - renamed to gtable.h to replace Java version
13  * @version 2018/07/17
14  * - initial version, based on gtable.h
15  * @since 2018/07/17
16  */
17 
18 
19 #ifndef _gtable_h
20 #define _gtable_h
21 
22 #include <map>
23 #include <string>
24 #include <QAbstractItemModel>
25 #include <QBrush>
26 #include <QFont>
27 #include <QItemSelection>
28 #include <QStyledItemDelegate>
29 #include <QTableWidget>
30 
31 #include "ginteractor.h"
32 #include "gobjects.h"
33 #include "gtypes.h"
34 
35 namespace sgl {
36 
37 struct GTableIndex;
38 class _Internal_QTableWidget;
39 
56 class GTable : public GInteractor {
57 public:
66  COLUMN_HEADER_NONE, // headers will not show
67  COLUMN_HEADER_EXCEL, // A, B, ..., Z, AA, AB, ...
68  COLUMN_HEADER_NUMERIC // 1, 2, 3, ...
69  };
70 
78  GTable(int rows = 0, int columns = 0, double width = 0, double height = 0,
79  QWidget* parent = nullptr);
80 
81  ~GTable() override;
82 
87  virtual void autofitColumnWidths();
88 
92  virtual void clear();
93 
98  virtual void clearCell(int row, int column);
99 
103  virtual void clearFormatting();
104 
108  virtual void clearCellFormatting(int row, int column);
109 
114  virtual void clearSelection();
115 
119  virtual void fill(const string& text);
120 
125  virtual string get(int row, int column) const;
126 
131  virtual ColumnHeaderStyle getColumnHeaderStyle() const;
132 
138  virtual double getColumnWidth(int column) const;
139 
140  /* @inherit */
141  _Internal_QWidget* getInternalWidget() const override;
142 
148  virtual double getRowHeight(int row) const;
149 
154  virtual GTableIndex getSelectedCell() const;
155 
161  virtual void getSelectedCell(int& row, int& column) const;
162 
167  virtual string getSelectedCellValue() const;
168 
173  virtual int getSelectedColumn() const;
174 
179  virtual int getSelectedRow() const;
180 
181  /* @inherit */
182  string getType() const override;
183 
184  /* @inherit */
185  QWidget* getWidget() const override;
186 
190  virtual bool hasSelectedCell() const;
191 
196  virtual int height() const;
197 
203  virtual bool inTableBounds(int row, int column) const;
204 
209  virtual bool isEditable() const;
210 
215  virtual int numCols() const;
216 
221  virtual int numRows() const;
222 
227  virtual void removeTableListener();
228 
229  /* @inherit */
230  void requestFocus() override;
231 
237  virtual void resize(int numRows, int numCols);
238 
243  virtual bool rowColumnHeadersVisible() const;
244 
252  virtual void select(int row, int column);
253 
258  virtual void set(int row, int column, const string& text);
259 
264  void setBackground(int rgb) override;
265 
270  void setBackground(const string& color) override;
271 
277  virtual void setCellAlignment(int row, int column, HorizontalAlignment alignment);
278 
285  virtual void setCellBackground(int row, int column, int color);
286 
293  virtual void setCellBackground(int row, int column, const string& color);
294 
301  virtual void setCellFont(int row, int column, const string& font);
302 
309  virtual void setCellForeground(int row, int column, int color);
310 
317  virtual void setCellForeground(int row, int column, const string& color);
318 
324  void setColor(int rgb) override;
325 
331  void setColor(const string& color) override;
332 
338  virtual void setColumnAlignment(int column, HorizontalAlignment alignment);
339 
346  virtual void setColumnBackground(int column, int color);
347 
354  virtual void setColumnBackground(int column, const string& color);
355 
362  virtual void setColumnFont(int column, const string& font);
363 
370  virtual void setColumnForeground(int column, int color);
371 
378  virtual void setColumnForeground(int column, const string& color);
379 
385  virtual void setColumnWidth(int column, double width);
386 
391  virtual void setColumnHeaderStyle(ColumnHeaderStyle style);
392 
397  virtual void setEditable(bool editable);
398 
405  virtual void setEditorValue(int row, int column, const string& text);
406 
410  void setFont(const QFont& font) override;
411 
416  void setFont(const string& font) override;
417 
423  void setForeground(int rgb) override;
424 
430  void setForeground(const string& color) override;
431 
436  virtual void setHorizontalAlignment(HorizontalAlignment alignment);
437 
443  virtual void setRowAlignment(int row, HorizontalAlignment alignment);
444 
451  virtual void setRowBackground(int row, int rgb);
452 
459  virtual void setRowBackground(int row, const string& color);
460 
467  virtual void setRowFont(int row, const string& font);
468 
475  virtual void setRowForeground(int row, int rgb);
476 
483  virtual void setRowForeground(int row, const string& color);
484 
489  virtual void setRowColumnHeadersVisible(bool visible);
490 
496  virtual void setRowHeight(int row, double width);
497 
502  virtual void setSelectedCellValue(const string& text);
503 
508  virtual void setTableListener(GEventListener func);
509 
514  virtual void setTableListener(GEventListenerVoid func);
515 
520  virtual int width() const;
521 
522 private:
523  Q_DISABLE_COPY(GTable)
524 
525  // Represents cascading styles on a cell, row, column, or table.
526  struct TableStyle {
527  int background;
528  int foreground;
529  string font;
530  HorizontalAlignment alignment;
531  // TODO: borders?
532 
533  TableStyle() {
534  background = 0;
535  foreground = 0;
536  font = "";
537  alignment = ALIGN_LEFT;
538  }
539 
540  bool isSet() const {
541  return background >= 0
542  && foreground >= 0
543  && !font.empty()
544  && alignment >= 0;
545  }
546 
547  void mergeWith(const TableStyle& other) {
548  if (other.background >= 0) {
549  background = other.background;
550  }
551  if (other.foreground >= 0) {
552  foreground = other.foreground;
553  }
554  if (!other.font.empty()) {
555  font = other.font;
556  }
557  if (other.alignment >= 0) {
558  alignment = other.alignment;
559  }
560  }
561 
562  TableStyle mergedWith(const TableStyle& other) {
563  TableStyle copy = *this;
564  copy.mergeWith(other);
565  return copy;
566  }
567 
568  static TableStyle unset() {
569  TableStyle style;
570  style.background = -1;
571  style.foreground = -1;
572  style.font = "";
573  style.alignment = (HorizontalAlignment) -1;
574  return style;
575  }
576  };
577 
578  // static variables for default formatting:
579  // background/foreground colors
580  // font
581  // alignment
582  static TableStyle _defaultCellStyle;
583 
584  // member variables
585  _Internal_QTableWidget* _iqtableview;
586  ColumnHeaderStyle _columnHeaderStyle;
587 
588  // styles on table, rows, columns, cells
589  std::map<int, TableStyle> _rowStyles;
590  std::map<int, TableStyle> _columnStyles;
591  TableStyle _globalCellStyle;
592 
593  void applyStyleToCell(int row, int column, const TableStyle& style);
594 
595  /*
596  * @throw ErrorException if the given row/column values are out of bounds.
597  */
598  void checkColumn(const string& member, int column) const;
599  void checkIndex(const string& member, int row, int column) const;
600  void checkRow(const string& member, int row) const;
601 
602  void ensureColumnStyle(int column);
603  void ensureDefaultFormatting() const; // const hack
604  void ensureGlobalCellStyle();
605  void ensureRowStyle(int row);
606  TableStyle getMergedStyleForCell(int row, int column);
607 
608  // Internal setters for cell formatting.
609  virtual void setCellAlignmentInternal(int row, int column, HorizontalAlignment alignment);
610  virtual void setCellBackgroundInternal(int row, int column, int color);
611  virtual void setCellFontInternal(int row, int column, const string& font);
612  virtual void setCellForegroundInternal(int row, int column, int color);
613 
614  static string toExcelColumnName(int col);
615 
616  void updateColumnHeaders();
617 
618  friend class _Internal_QTableWidget;
619 };
620 
625 class _Internal_QItemDelegate : public QStyledItemDelegate {
626  Q_OBJECT
627 
628 public:
629  _Internal_QItemDelegate(QObject* parent = nullptr);
630  virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
631  virtual void destroyEditor(QWidget* editor, const QModelIndex& index) const;
632  virtual QWidget* getEditor() const;
633 
634 private:
635  QWidget* _editor;
636 };
637 
638 
643 class _Internal_QTableWidget : public QTableWidget, public _Internal_QWidget {
644  Q_OBJECT
645 
646 public:
647  _Internal_QTableWidget(GTable* gtable, int rows, int columns, QWidget* parent = nullptr);
648  void detach() override;
649  bool edit(const QModelIndex& index, QAbstractItemView::EditTrigger trigger, QEvent* event) override;
650  virtual QWidget* getEditor() const;
651  virtual _Internal_QItemDelegate* getItemDelegate() const;
652  virtual bool isEditing() const;
653  void closeEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint) override;
654  void keyPressEvent(QKeyEvent* event) override;
655  QSize sizeHint() const override;
656 
657 public slots:
658  void handleCellChange(int row, int column);
659  void handleCellDoubleClick(int row, int column);
660  void handleSelectionChange(const QItemSelection& selected, const QItemSelection& deselected);
661 
662 private:
663  GTable* _gtable;
664  _Internal_QItemDelegate* _delegate;
665  int _lastKeyPressed;
666 
667  void fireTableEvent(EventType eventType, const string& eventName, int row = -1, int col = -1);
668 
669  friend class GTable;
670 };
671 
684 struct GTableIndex {
685 public:
686 
691  GTableIndex(int row, int col);
692 
696  GTableIndex();
697 
701  string toString() const;
702 
703  /* row and column data - may be directly accessed or modified */
704  int row;
705  int col;
706 };
707 
711 string to_string(const GTableIndex& value);
712 
716 bool operator <(const GTableIndex& loc1, const GTableIndex& loc2);
717 bool operator <=(const GTableIndex& loc1, const GTableIndex& loc2);
718 bool operator ==(const GTableIndex& loc1, const GTableIndex& loc2);
719 bool operator !=(const GTableIndex& loc1, const GTableIndex& loc2);
720 bool operator >(const GTableIndex& loc1, const GTableIndex& loc2);
721 bool operator >=(const GTableIndex& loc1, const GTableIndex& loc2);
722 
726 std::ostream& operator <<(std::ostream& out, const GTableIndex& loc);
727 std::istream& operator >>(std::istream& input, GTableIndex& loc);
728 
729 } // namespace sgl
730 
731 #endif // _gtable_h
This is a small structure representing a row and column in a table.
Definition: gtable.h:684
virtual void setCellAlignment(int row, int column, HorizontalAlignment alignment)
Sets the horizontal alignment of the given cell.
Definition: gtable.cpp:400
virtual int getSelectedRow() const
Returns the row of the cell that is currently selected, or -1 if no cell is currently selected...
Definition: gtable.cpp:258
virtual void setColumnFont(int column, string font)
Sets the text font of the given column to the given RGB color.
Definition: gtable.cpp:498
Definition: gtable.h:66
HorizontalAlignment
The supported kinds of horizontal alignment of a widget or onscreen object.
Definition: gtypes.h:136
void setFont(const QFont &font) override
Sets the font used to display each cell&#39;s text.
Definition: gtable.cpp:585
virtual void setCellBackground(int row, int column, int color)
Sets the background color of the given cell to the given color.
Definition: gtable.cpp:413
bool operator>=(const GTableIndex &loc1, const GTableIndex &loc2)
Definition: gtable.cpp:1089
virtual int height() const
Returns the number of rows in the table.
Definition: gtable.cpp:275
ColumnHeaderStyle
Styles of column header labels that can be shown.
Definition: gtable.h:65
void setColor(int rgb) override
Sets the color used for the text of each cell.
Definition: gtable.cpp:456
GTable(int rows=0, int columns=0, double width=0, double height=0, QWidget* parent=nullptr)
Constructs a new table with the given dimensions and (optional) size.
Definition: gtable.cpp:49
virtual int numCols() const
Returns the number of columns in the table.
Definition: gtable.cpp:287
virtual GTableIndex getSelectedCell() const
Returns the row and column of the cell that is currently selected.
Definition: gtable.cpp:229
std::ostream & operator<<(std::ostream &out, const GEvent &event)
Writes the given event to the given output stream.
Definition: gevent.cpp:494
virtual void autofitColumnWidths()
Changes widths of all columns to be perfectly large enough to fit their contents. ...
Definition: gtable.cpp:76
virtual void setEditorValue(int row, int column, string text)
Modifies the value in the cell that is currently being edited to store the given text.
Definition: gtable.cpp:572
virtual void removeTableListener()
Removes the table listener from this button so that it will no longer call it when events occur...
Definition: gtable.cpp:295
bool operator>(const GTableIndex &loc1, const GTableIndex &loc2)
Definition: gtable.cpp:1085
virtual void setColumnForeground(int column, int color)
Sets the foreground/text color of the given column to the given color.
Definition: gtable.cpp:513
void requestFocus() override
Transfers keyboard focus to this interactor.
Definition: gtable.cpp:306
virtual void setRowForeground(int row, int rgb)
Sets the foreground/text color of the given row to the given color.
Definition: gtable.cpp:723
virtual void fill(string text)
Sets every cell in the table to have the given value.
Definition: gtable.cpp:180
GTableIndex()
Constructs a default location 0, 0.
Definition: gtable.cpp:1056
virtual int numRows() const
Returns the number of rows in the table.
Definition: gtable.cpp:291
virtual string getSelectedCellValue() const
Returns the text in the cell that is currently selected.
Definition: gtable.cpp:245
virtual void setEditable(bool editable)
Sets whether cells of the table can be edited.
Definition: gtable.cpp:558
virtual void setHorizontalAlignment(HorizontalAlignment alignment)
Sets the horizontal alignment of the text in all cells in the table.
Definition: gtable.cpp:648
std::function< void(GEvent)> GEventListener
Types for the event listener functions to be passed to various interactors.
Definition: gevent.h:38
Definition: console.h:45
bool operator==(const GTableIndex &loc1, const GTableIndex &loc2)
Definition: gtable.cpp:1077
This abstract class is the superclass for all graphical interactors.
Definition: ginteractor.h:52
virtual void setTableListener(GEventListener func)
Sets the given function to be called when events occur in this table.
Definition: gtable.cpp:767
string getType() const override
Returns a string representing the class name of this interactor, such as "GButton" or "GCheckBox"...
Definition: gtable.cpp:262
void setBackground(int rgb) override
Sets the background color that appears behind each cell.
Definition: gtable.cpp:368
virtual double getRowHeight(int row) const
Returns the height of the given row index in pixels.
Definition: gtable.cpp:224
virtual bool hasSelectedCell() const
Returns true if a cell is currently selected.
Definition: gtable.cpp:270
virtual void clearFormatting()
Removes any per-cell/column/row formatting that has been applied to the table.
Definition: gtable.cpp:113
virtual bool isEditable() const
Returns whether cells of the table can be edited.
Definition: gtable.cpp:283
A GTable represents a graphical editable 2D table, like a mediocre facsimile of an Excel spreadsheet...
Definition: gtable.h:56
void setForeground(int rgb) override
Sets the color used for the text of each cell.
Definition: gtable.cpp:616
virtual void clearCellFormatting(int row, int column)
Removes any formatting that has been applied to the given cell.
Definition: gtable.cpp:129
virtual bool rowColumnHeadersVisible() const
Returns whether row and column headers are shown in the table.
Definition: gtable.cpp:347
bool operator<=(const GTableIndex &loc1, const GTableIndex &loc2)
Definition: gtable.cpp:1073
virtual void setColumnBackground(int column, int color)
Sets the background color of the given column to the given color.
Definition: gtable.cpp:479
virtual void setColumnAlignment(int column, HorizontalAlignment alignment)
Sets the horizontal alignment of the given column.
Definition: gtable.cpp:464
std::function< void()> GEventListenerVoid
Types for the event listener functions to be passed to various interactors.
Definition: gevent.h:44
virtual void clearSelection()
Deselects any currently selected cell.
Definition: gtable.cpp:149
virtual void setColumnHeaderStyle(ColumnHeaderStyle style)
Sets the column headers to use the given style.
Definition: gtable.cpp:532
virtual double getColumnWidth(int column) const
Returns the width of the given column index in pixels.
Definition: gtable.cpp:201
virtual void setRowHeight(int row, double width)
Sets the given row index to have the given height in pixels.
Definition: gtable.cpp:750
bool operator<(const GTableIndex &loc1, const GTableIndex &loc2)
Relational operators for comparing table locations.
Definition: gtable.cpp:1068
virtual bool inTableBounds(int row, int column) const
Returns true if the given 0-based row/column index is within the bounds of the table.
Definition: gtable.cpp:279
virtual void clearCell(int row, int column)
Sets the given cell to store an empty string value.
Definition: gtable.cpp:108
string to_string(const GTableIndex &value)
Returns a string representation of this location, such as "r2c17".
Definition: gtable.cpp:1064
QWidget* getWidget() const override
Returns a direct pointer to the internal Qt widget being wrapped by this interactor.
Definition: gtable.cpp:266
virtual void setColumnWidth(int column, double width)
Sets the given column index to have the given width in pixels.
Definition: gtable.cpp:548
EventType
Defines the event subtypes for all events.
Definition: gevent.h:74
int col
Definition: gtable.h:705
virtual void setSelectedCellValue(string text)
Sets the text in the cell that is currently selected.
Definition: gtable.cpp:760
virtual void setRowFont(int row, string font)
Sets the text font of the given row to the given font.
Definition: gtable.cpp:708
virtual void setRowColumnHeadersVisible(bool visible)
Sets whether row and column headers should be shown in the table.
Definition: gtable.cpp:743
virtual int getSelectedColumn() const
Returns the column of the cell that is currently selected, or -1 if no cell is currently selected...
Definition: gtable.cpp:254
virtual void setRowAlignment(int row, HorizontalAlignment alignment)
Sets the horizontal alignment of the given row.
Definition: gtable.cpp:674
virtual void resize(int numRows, int numCols)
Modifies the table to have the given number of rows and columns.
Definition: gtable.cpp:317
virtual void setCellFont(int row, int column, string font)
Sets the text font of the given cell to the given RGB color.
Definition: gtable.cpp:428
virtual void setCellForeground(int row, int column, int color)
Sets the foreground/text color of the given cell to the given color.
Definition: gtable.cpp:439
virtual void clear()
Sets all cells in the table to store an empty string value.
Definition: gtable.cpp:100
std::istream & operator>>(std::istream &input, GTableIndex &loc)
Definition: gtable.cpp:1097
virtual void setRowBackground(int row, int rgb)
Sets the background color of the given row to the given RGB color.
Definition: gtable.cpp:689
Definition: gtypes.h:138
virtual void select(int row, int column)
Sets the given cell to become currently selected, replacing any previous selection.
Definition: gtable.cpp:352
int row
Definition: gtable.h:704
bool operator!=(const GTableIndex &loc1, const GTableIndex &loc2)
Definition: gtable.cpp:1081
string toString() const
Returns a string representation of this location, such as "r2c17".
Definition: gtable.cpp:1058
virtual ColumnHeaderStyle getColumnHeaderStyle() const
Returns the column headers to use the given style.
Definition: gtable.cpp:197
Definition: gtable.h:68
virtual int width() const
Returns the number of columns in the table.
Definition: gtable.cpp:822
Definition: gtable.h:67
~GTable() override
Definition: gtable.cpp:63
_Internal_QWidget* getInternalWidget() const override
Returns a direct pointer to the internal Qt widget being wrapped by this interactor.
Definition: gtable.cpp:206