Isis 3.0 Programmer Reference
Back | Home
TableMainWindow.cpp
1 #include "TableMainWindow.h"
2 
3 #include <iostream>
4 
5 #include <QAction>
6 #include <QStatusBar>
7 #include <QDockWidget>
8 #include <QFileDialog>
9 #include <QMenuBar>
10 #include <QMessageBox>
11 #include <QSettings>
12 #include <QTableWidget>
13 #include <QToolBar>
14 
15 
16 namespace Isis {
23  TableMainWindow::TableMainWindow(QString title, QWidget *parent) : MainWindow(title, parent) {
24  p_parent = parent;
25 
26  p_title = title;
27  p_table = NULL;
28  p_visibleColumns = -1;
29  p_currentRow = 0;
30  p_currentIndex = 0;
31  createTable();
32 
33  setObjectName(title);
34  readSettings(QSize(500, 300));
35  }
36 
37 
38  TableMainWindow::~TableMainWindow() {
39  }
40 
41 
42  void TableMainWindow::clear() {
43  writeSettings();
44  p_table->clear();
45  p_listWidget->clear();
46  p_table->setRowCount(0);
47  p_table->setColumnCount(0);
48  }
49 
50 
51  QList<QListWidgetItem *> TableMainWindow::itemList() const {
53 
54  if (p_listWidget)
55  result = p_listWidget->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard);
56 
57  return result;
58  }
59 
60 
68 #if defined(__APPLE__)
69  setWindowFlags(Qt::Tool);
70 #endif
71 
72 #ifndef __APPLE__
73  setWindowFlags(Qt::Dialog);
74 #endif
75 
76  statusBar()->setSizeGripEnabled(true);
77  // Create the table widget
78  p_table = new QTableWidget(this);
79  p_table->setAlternatingRowColors(true);
80  setCentralWidget(p_table);
81 
82  // Create the dock area
83  p_dock = new QDockWidget("Columns", this);
84  p_dock->setObjectName("dock");
85  p_dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
86  p_dock->setMinimumWidth(190);
87  p_listWidget = new QListWidget(p_dock);
88  p_dock->setWidget(p_listWidget);
89  addDockWidget(Qt::LeftDockWidgetArea, p_dock, Qt::Vertical);
90  connect(p_listWidget, SIGNAL(itemChanged(QListWidgetItem *)),
91  this, SLOT(syncColumns()));
92 
93  // Create the file menu
94  QMenuBar *menuBar = this->menuBar();
95  QMenu *fileMenu = menuBar->addMenu("&File");
96 
97  p_save = new QAction(this);
98  p_save->setText("Save...");
99  p_save->setShortcut(Qt::CTRL + Qt::Key_S);
100  connect(p_save, SIGNAL(triggered()), this, SLOT(saveTable()));
101  p_save->setDisabled(true);
102 
103  QAction *saveas = new QAction(this);
104  saveas->setText("Save As...");
105  connect(saveas, SIGNAL(triggered()), this, SLOT(saveAsTable()));
106 
107  QAction *load = new QAction(this);
108  load->setText("Load...");
109  connect(load, SIGNAL(triggered()), this, SLOT(loadTable()));
110 
111  QAction *del = new QAction(this);
112  del->setText("Delete Selected Row(s)");
113  del->setShortcut(Qt::Key_Delete);
114  connect(del, SIGNAL(triggered()), this, SLOT(deleteRows()));
115 
116  QAction *clear = new QAction(this);
117  clear->setText("Clear table");
118  connect(clear, SIGNAL(triggered()), this, SLOT(clearTable()));
119 
120  QAction *close = new QAction(this);
121  close->setText("Close");
122  connect(close, SIGNAL(triggered()), this, SLOT(hide()));
123 
124  fileMenu->addAction(p_save);
125  fileMenu->addAction(saveas);
126  fileMenu->addAction(load);
127  fileMenu->addAction(del);
128  fileMenu->addAction(clear);
129  fileMenu->addAction(close);
130 
131  //2009-01-12
132  //If we have the Mainwindow flag set to Qt::Tool so that on Macs the
133  //table window always stays on top, then we can not access the
134  //menu bar to the table window, so we need to add the file options
135  //for the table to the tool bar.
136 #if defined(__APPLE__)
137  QToolBar *toolBar = new QToolBar();
138  toolBar->setObjectName("ToolBar");
139  toolBar->addAction(p_save);
140  toolBar->addAction(saveas);
141  toolBar->addAction(load);
142  toolBar->addAction(del);
143  toolBar->addAction(clear);
144  toolBar->addAction(close);
145  this->addToolBar(toolBar);
146 #endif
147 
148  // Create the view menu
149  QMenu *viewMenu = menuBar->addMenu("&View");
150  QAction *cols = new QAction(this);
151  cols->setText("Columns");
152  connect(cols, SIGNAL(triggered()), p_dock, SLOT(show()));
153  viewMenu->addAction(cols);
154 
155  this->setMenuBar(menuBar);
156  installEventFilter(this);
157  }
158 
159 
166  void TableMainWindow::setStatusMessage(QString message) {
167  this->statusBar()->showMessage(message);
168  }
169 
170 
183  void TableMainWindow::addToTable(bool setOn, const QString &heading,
184  const QString &menuText, int insertAt,
185  Qt::Orientation o, QString toolTip) {
186  // Insert the new column
187  int startCol = p_table->columnCount();
188 
189  for(int i = 0; !heading.section(":", i, i).isEmpty(); i++) {
190  QString htext = heading.section(":", i, i);
191 
192  int destinationColumn = insertAt;
193 
194  if (insertAt >= 0) {
195  p_table->insertColumn(insertAt);
196  }
197  else {
198  destinationColumn = startCol + i;
199  p_table->insertColumn(startCol + i);
200  }
201  QTableWidgetItem *header = new QTableWidgetItem(htext);
202  if (insertAt >= 0) {
203 
204  if (o == Qt::Horizontal) {
205  p_table->setHorizontalHeaderItem(insertAt, header);
206  }
207  else {
208  p_table->setVerticalHeaderItem(insertAt, header);
209  }
210  }
211  else {
212 
213  if (o == Qt::Horizontal) {
214  p_table->setHorizontalHeaderItem(startCol + i, header);
215  }
216  else {
217  p_table->setVerticalHeaderItem(startCol + i, header);
218  }
219  }
220 
221  p_table->setColumnWidth(destinationColumn,
222  QFontMetrics(header->font()).width(header->text()) + 20);
223  // Removed: rounding and int?
224  // qRound(QFontMetrics(header->font()).width(header->text()) + 20));
225  }
226 
227  int endCol = p_table->columnCount() - 1;
228 
229  // Insert the column name into the columns dock area
230  if (!menuText.isEmpty()) {
231  QListWidgetItem *item = new QListWidgetItem();
232 
233  item->setText(menuText);
234  if (toolTip.isEmpty()) {
235  item->setToolTip(heading);
236  }
237  else {
238  item->setToolTip(toolTip);
239  }
240 
241  if (insertAt >= 0) {
242  p_listWidget->insertItem(insertAt, item);
243  }
244  else {
245  p_listWidget->insertItem(endCol, item);
246  }
247 
248  item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
249 
250  readItemSettings(menuText, item, setOn);
251 
252  p_startColumn.push_back(startCol);
253  p_endColumn.push_back(endCol);
254 
255  readItemSettings(heading, item, setOn);
256  }
257  }
258 
259 
266  if (this->isHidden()) {
267  return;
268  }
269 
270  p_visibleColumns = 0;
271  for(int i = 0; i < p_listWidget->count(); i++) {
272  QListWidgetItem *item = p_listWidget->item(i);
273  int index = itemList().indexOf(item);
274 
275  if (index != -1) {
276  for(int col = p_startColumn[index]; col <= p_endColumn[index]; col++) {
277 
278  if (item->checkState() == Qt::Checked) {
279  p_table->setColumnHidden(col, false);
281  }
282  else {
283  p_table->setColumnHidden(col, true);
284  }
285 
286  }
287  }
288  }
289  }
290 
291 
298  if (!isHidden()) {
299  p_visibleColumns = 0;
300  for (int i = 0; i < p_listWidget->count(); i++) {
301  QListWidgetItem *item = p_listWidget->item(i);
302  int index = itemList().indexOf(item);
303 
304  if (index != -1) {
305 
306  for (int col = p_startColumn[index];
307  col <= p_endColumn[index];
308  col++) {
309 
310  if (item->checkState() == Qt::Checked) {
311  p_table->setRowHidden(col, false);
313  }
314  else {
315  p_table->setRowHidden(col, true);
316  }
317 
318  }
319  }
320  }
321  }
322  }
323 
324 
331  if (p_table != NULL) {
332  p_table->setColumnCount(p_table->columnCount() - 1);
333 
334  bool vis = p_table->isVisible();
335  p_table = NULL;
336  p_listWidget = NULL;
337  close();
338 
339  if (vis) showTable();
340  }
341  }
342 
343 
350  syncColumns();
351  if (p_table == NULL) createTable();
352  this->show();
353  }
354 
355 
361  if (p_table->rowCount() == 0) return;
362  for(int r = 0; r < p_table->rowCount(); r++) {
363  for(int c = 0; c < p_table->columnCount(); c++) {
364  p_table->item(r, c)->setText("");
365  }
366  }
367 
368  p_table->scrollToItem(p_table->item(0, 0), QAbstractItemView::PositionAtTop);
369  p_currentRow = 0;
370  p_currentIndex = 0;
371  }
372 
373 
381  QList<QTableWidgetItem *> list = p_table->selectedItems();
383 
384  for(int i = 0; i < list.size(); i++) {
385  if (selectedRows.size() == 0) {
386  selectedRows.push_back(p_table->row(list[i]));
387  }
388  else if (!selectedRows.contains(p_table->row(list[i]))) {
389  selectedRows.push_back(p_table->row(list[i]));
390  }
391  }
392 
393  qSort(selectedRows.begin(), selectedRows.end());
394  for(int d = selectedRows.size(); d > 0; d--) {
395  p_table->removeRow(selectedRows[d-1]);
396  }
397 
398  // get the number of rows that are filled in
399  int filledRows = 0;
400  for(int r = 0; r < p_table->rowCount(); r++) {
401  for(int c = 0; c < p_table->columnCount(); c++) {
402  if (!p_table->item(r, c) || p_table->item(r, c)->text() != "") {
403  filledRows++;
404  break;
405  }
406  }
407  }
408 
409  p_currentRow = filledRows;
410  }
411 
412 
419  if (!this->isVisible()) return;
420 
421  for(int c = 0; c < p_table->columnCount(); c++) {
422  p_table->item(row, c)->setText("");
423  }
424  }
425 
432  QString fn = QFileDialog::getSaveFileName((QWidget *)parent(),
433  "Choose filename to save under",
434  ".",
435  "Text Files (*.txt)");
436  QString filename;
437 
438  //Make sure the filename is valid
439  if (!fn.isEmpty()) {
440  if (!fn.endsWith(".txt")) {
441  filename = fn + ".txt";
442  }
443  else {
444  filename = fn;
445  }
446  }
447  //The user cancelled, or the filename is empty
448  else {
449  return;
450  }
451 
452  p_currentFile.setFileName(filename);
453 
454  p_save->setEnabled(true);
455  saveTable();
456  }
457 
463  if (p_currentFile.fileName().isEmpty()) return;
464 
465  //if (p_currentFile.exists()) p_currentFile.remove();
466  bool success = p_currentFile.open(QIODevice::WriteOnly);
467  if (!success) {
468  QMessageBox::critical((QWidget *)parent(),
469  "Error", "Cannot open file, please check permissions");
470  p_currentFile.setFileName("");
471  p_save->setDisabled(true);
472  return;
473  }
474 
475  QString currentText;
476  QTextStream t(&p_currentFile);
477  QString line = "";
478  bool first = true;
479 
480  //Write each column's header to the first line in CSV format
481  for(int i = 0; i < p_table->columnCount(); i++) {
482  if (!p_table->isColumnHidden(i)) {
483  QTableWidgetItem *header = p_table->horizontalHeaderItem(i);
484  QString temp = header->text();
485  temp.replace("\n", " ");
486  if (first) {
487  line = line + "\"" + temp + "\"";
488  first = false;
489  }
490  else {
491  line = line + ",\"" + temp + "\"";
492  }
493  }
494  }
495  //Add the headers to the file
496  t << line << endl;
497 
498  //Add each row to the file
499  for(int i = 0; i < p_table->rowCount(); i++) {
500  bool first = true;
501  line = "";
502 
503  //Add each column to the line
504  for(int j = 0; j < p_table->columnCount(); j++) {
505 
506  if (!p_table->isColumnHidden(j)) {
507  if (p_table->item(i, j) == 0) break;
508  currentText = p_table->item(i, j)->text();
509 
510  if (first) {
511  line = line + currentText;
512  first = false;
513  }
514  else {
515  line = line + "," + currentText;
516  }
517  }
518  }
519  //If the line is not empty, add it to the file
520  if (line.split(",", QString::SkipEmptyParts).count() != 0)
521  t << line << endl;
522  }
523  p_currentFile.close();
524  this->setWindowTitle(p_title + " : " + p_currentFile.fileName());
525  }
526 
527 
537  void TableMainWindow::readItemSettings(QString heading,
538  QListWidgetItem *item, bool defaultChecked) {
539  QSettings settings(settingsFileName(), QSettings::NativeFormat);
540 
541  QString itemTitle = "item-" + item->text();
542  Qt::CheckState defaultState = defaultChecked? Qt::Checked : Qt::Unchecked;
543  Qt::CheckState state = (Qt::CheckState)
544  settings.value(itemTitle, defaultState).toInt();
545  item->setCheckState(state);
546  }
547 
548 
557  if (p_listWidget) {
558  QSettings settings(settingsFileName(), QSettings::NativeFormat);
559 
560  foreach (QListWidgetItem *item, itemList()) {
561  QString itemTitle = "item-" + item->text();
562  settings.setValue(itemTitle, item->checkState());
563  }
564  }
565  }
566 
567 
573  QString fn = QFileDialog::getOpenFileName((QWidget *)parent(),
574  "Select file to load",
575  ".",
576  "Text Files (*.txt)");
577 
578  //If the user cancelled or the filename is empty return
579  if (fn.isEmpty()) return;
580 
581  p_currentFile.setFileName(fn);
582  p_save->setEnabled(true);
583 
584  bool success = p_currentFile.open(QIODevice::ReadOnly);
585  if (!success) {
586  QMessageBox::critical((QWidget *)parent(),
587  "Error", "Cannot open file, please check permissions");
588  p_currentFile.setFileName("");
589  p_save->setDisabled(true);
590  return;
591  }
592 
593  clearTable();
594 
595  QList<int> column = QList<int>();
596 
597  //Set all headers to be hidden
598  for(int i = 0; i < p_listWidget->count() ; i++) {
599  p_listWidget->item(i)->setCheckState(Qt::Unchecked);
600  }
601 
602  // Strip headers off the table into the temp string
603  QString temp = p_currentFile.readLine();
604  temp.remove("Positive ");
605  temp.remove("\"");
606  temp.remove("\n");
607  QStringList list = temp.split(",");
608 
609  // Loop through checking header names and setting relevant columns visible
610  for(int i = 0; i < list.count(); i++) {
611  for(int j = 0; j < itemList().size(); j++) {
612  QListWidgetItem *item = itemList()[j];
613 
614  //Special cases
615  if (item->text() == "Ground Range" && (list[i] == "Start Latitude" || list[i] == "Start Longitude" ||
616  list[i] == "End Latitude" || list[i] == "End Longitude")) {
617  item->setCheckState(Qt::Checked);
618  break;
619  }
620  if (item->text() == "Pixel Range" && (list[i] == "Start Sample" || list[i] == "Start Line" ||
621  list[i] == "End Sample" || list[i] == "End Line")) {
622  item->setCheckState(Qt::Checked);
623  break;
624  }
625  if (item->text() == "Pixel Range" && (list[i] == "Sample" || list[i] == "Line")) {
626  item->setCheckState(Qt::Checked);
627  break;
628  }
629  if (item->text() == "Sample:Line" && (list[i] == "Sample" || list[i] == "Line")) {
630  item->setCheckState(Qt::Checked);
631  break;
632  }
633  if (item->text() == "Planetocentric Lat" && list[i] == "Planetocentric Latitude") {
634  item->setCheckState(Qt::Checked);
635  break;
636  }
637  if (item->text() == "Planetographic Lat" && list[i] == "Planetographic Latitude") {
638  item->setCheckState(Qt::Checked);
639  break;
640  }
641  if (item->text() == "Projected X:Projected Y" && (list[i] == "Projected X" || list[i] == "Projected Y")) {
642  item->setCheckState(Qt::Checked);
643  break;
644  }
645  if (item->text() == "Radius" && list[i] == "Local Radius") {
646  item->setCheckState(Qt::Checked);
647  break;
648  }
649  if (item->text() == "XYZ" && (list[i] == "Point X" || list[i] == "Point Y" || list[i] == "Point Z")) {
650  item->setCheckState(Qt::Checked);
651  break;
652  }
653  if (item->text() == "Ra:Dec" && (list[i] == "Right Ascension" || list[i] == "Declination")) {
654  item->setCheckState(Qt::Checked);
655  break;
656  }
657  if (item->text() == "Spacecraft Position" && (list[i] == "Spacecraft X" || list[i] == "Spacecraft Y" || list[i] == "Spacecraft Z")) {
658  item->setCheckState(Qt::Checked);
659  break;
660  }
661  if (item->text() == "Ephemeris Time" && list[i] == "Ephemeris Time") {
662  item->setCheckState(Qt::Checked);
663  break;
664  }
665  if (item->text() == "Local Solar Time" && list[i] == "Local Solar Time") {
666  item->setCheckState(Qt::Checked);
667  break;
668  }
669  if (item->text() == "Segments Sum" && list[i] == "Segments Sum km") {
670  item->setCheckState(Qt::Checked);
671  break;
672  }
673  //End special cases
674 
675 
676  if (item->text() == list[i]) {
677  item->setCheckState(Qt::Checked);
678  break;
679  }
680  }
681 
682  // Loop through column headers to try to find a match
683  bool match = false;
684  for(int cols = 0; cols < p_table->columnCount(); cols++) {
685  QString header = p_table->horizontalHeaderItem(cols)->text();
686 
687  header.remove("Positive");
688  header.remove("\n");
689  header.remove(" ");
690 
691  list[i].remove(" ");
692 
693  if (header == list[i]) {
694  column.push_back(cols);
695  match = true;
696  break;
697 
698  }
699  }
700  if (!match) column.push_back(-1);
701  }
702 
703  // Read data into table
704  QString str = p_currentFile.readLine();
705 
706  while(str.count() != 0) {
707  // Do we need more rows?
708  if (p_currentRow + 1 > p_table->rowCount()) {
709  p_table->insertRow(p_currentRow);
710  for(int c = 0; c < p_table->columnCount(); c++) {
711  QTableWidgetItem *item = new QTableWidgetItem("");
712  p_table->setItem(p_currentRow, c, item);
713  if (c == 0) p_table->scrollToItem(item);
714  }
715  }
716 
717  str.remove("\n");
718 
719  QStringList list = str.split(",");
720 
721  for(int i = 0; i < column.size(); i++) {
722  QTableWidgetItem *newItem = new QTableWidgetItem(list[i]);
723  if (column[i] != -1) {
724  p_table->setItem(p_currentRow, column[i], newItem);
725  }
726  }
727  p_currentRow++;
728  p_currentIndex++;
729 
730 
731  str = p_currentFile.readLine();
732  }
733 
734  p_currentFile.close();
735  this->setWindowTitle(p_title + " : " + fn);
736  emit fileLoaded();
737  }
738 
739 
747  bool TableMainWindow::eventFilter(QObject *o, QEvent *e) {
748  switch(e->type()) {
749  case QEvent::Close: {
750  this->writeSettings();
751  }
752 
753  default: {
754  return false;
755  }
756  }
757  }
758 
759 
766  void TableMainWindow::closeEvent(QCloseEvent *event) {
767  MainWindow::closeEvent(event);
768  writeSettings();
769  event->accept();
770  }
771 
772 
779  void TableMainWindow::hideEvent(QHideEvent *event) {
780 // this->writeSettings();
781  }
782 
783 
792  p_trackItems = track;
793  }
794 
795 
803  return p_trackItems;
804  }
805 
806 
813  p_currentRow = row;
814  }
815 
816 
822  void TableMainWindow::setCurrentIndex(int currentIndex) {
824  }
825 
826 }
virtual void readSettings(QSize defaultSize=QSize())
This method ensure that the settings get written even if the Main window was only hidden...
Definition: MainWindow.cpp:80
QAction * p_save
Action to save the table to the current file.
void setStatusMessage(QString message)
sets the status message in the lower lefthand corner of the window.
bool eventFilter(QObject *o, QEvent *e)
This event filter is installed in the constructor.
void saveAsTable()
This method will select a file, set it as the current file and save the table.
int p_currentIndex
Current index.
QFile p_currentFile
The current file.
void clearRow(int row)
This method clears the text of the given row.
void deleteColumn(int item)
This method deletes a column from the table.
void hideEvent(QHideEvent *event)
int selectedRows() const
Returns the selected rows.
bool trackListItems()
Returns whether or not we should track items.
void createTable()
This creates the table main window.
void deleteRows()
This method is called when the user selects a row or rows uses the delete button or selects the delet...
bool p_trackItems
Boolean to track items.
void saveTable()
This method allows the user to save the data from the table to the current file.
void setTrackListItems(bool track=false)
If this property is true, the class will keep track of the checked/unchecked items in the dock area w...
void readItemSettings(QString heading, QListWidgetItem *item, bool defaultChecked)
This method reads the &#39;checked&#39; settings on the items listed in the dock area which determine which t...
QList< int > p_endColumn
List of end columns.
int p_currentRow
Current row.
QPointer< QListWidget > p_listWidget
List widget.
virtual void closeEvent(QCloseEvent *event)
This method is overridden so that we can be sure to write the current settings of the Main window...
Definition: MainWindow.cpp:37
void closeEvent(QCloseEvent *event)
void writeSettings() const
This overriden method is called when the Tablemainwindow is closed or hidden to write the size and lo...
void syncColumns()
This method hides and shows the columns according to which items the user has selected to be view-abl...
int p_visibleColumns
Number of visible columns.
void setCurrentRow(int row)
Sets the current row to row.
TableMainWindow(QString title, QWidget *parent=0)
Constructs a new TableMainWindow object.
QString p_title
The title string.
void clearTable()
This method clears all items from each row and column.
void loadTable()
This method loads a text file into the table.
int currentIndex() const
Returns the current index.
Base class for the Qisis main windows.
Definition: MainWindow.h:24
void fileLoaded()
Signal emitted when a file has loaded.
void addToTable(bool setOn, const QString &heading, const QString &menuText="", int insertAt=-1, Qt::Orientation o=Qt::Horizontal, QString toolTip="")
Adds a new column to the table when a new curve is added to the plot.
QList< int > p_startColumn
List of start columns.
void showTable()
This method checks to see if the table has been created.
QTableWidget * p_table
The table.
QWidget * p_parent
The parent widget.
QDockWidget * p_dock
The dock widget.
void setCurrentIndex(int currentIndex)
Sets the current index to currentIndex.
void syncRows()
Use this method to sync the table with the dock widget list if the table orientation is horizontal...

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:30:25