SampleEditor

From FarsightWiki
Jump to: navigation, search

The SampleEditor program (checkout from the FARSIGHT repository) is implemented by using the QT's model/view architecture. This web page is prepared to help one to implement their code by using this model. (Please visit these pages for additional information:

 * ALISA shows how we implement  QT's Model/View Architecture in FARSIGHT, specifically in the NucleusEditor module. 
 * EVS presents Edit-based Validation and Model-View Programming)

Contents

Why do we need to use this architecture?

In general, there are many applications that follow some of the steps listed below:

  1. Read Some Input - Read the data from a file, from the command line, or from the program itself
  2. Present the Data Using Different Views - Show it with a table, draw a scatter plott, or display some columns by using a histogram
  3. Edit the Data in the Views - reflect the changes to all the other views, update them properly
  4. Compute some features
  5. Write/Store the Results - into a file, or to the screen

In Farsight, our modules follow the similar patterns to process the data. In order to implement these steps, many different solutions might be provided. The major problem with this approach is that for every unique solution, the programmer needs to implement their specialized viewers. An alternative and a better solution is to base your application onto the model/view architecture that we have already implemented. The advantage is that your module will be able to view the data with a small amount of extra programming by using the different viewers that are part of our libraries.

We show, in the SampleEditor program, how this idea works. For simplicity, we view the data by using only three viewers. Here are the screen shots of these views from the SampleEditor program:

  1. Table View
SETableView.JPG
  1. Scatter Plot View
SEPlotView.JPG


In this architecture, any changes in one of the views will be reflected to the other views immidiately.

Steps

Declaration

Here is the main class that we defined for the SampleEditor:

 class SampleEditor : public QMainWindow
 {
   Q_OBJECT;
 public:
   SampleEditor(QWidget * parent = 0, Qt::WindowFlags flags = 0);
 
 //Use this declaration to load your data 
 private slots:
   void loadFile(void);
 signals:    
 private:
   // Setup the GUI 
   void createMenus();
   void createStatusBar();
   QMenu *fileMenu;
   QAction *loadAction;
   // Define the QT model - two models are necessary, one for the data, and the other one for the selections 
   QStandardItemModel *model;
   QItemSelectionModel *selModel;
   // Define the views - We have three views in this case 
   QTableView *table;
   PlotWindow *plot;
   HistoWindow *histo;
  };

Definitions

  • 1. Define the constructor for your editor
 SampleEditor::SampleEditor(QWidget * parent, Qt::WindowFlags flags) : QMainWindow(parent,flags)
 {
   model = NULL;
   selModel = NULL;
   plot = NULL;
   histo = NULL;
   createMenus();
   createStatusBar();
   table = new QTableView();
   setCentralWidget(table);
   setWindowTitle(tr("Sample Editor"));
   this->resize(500,500);
 }
  • 2. Define the GUI Elements
 // Here we just show a message in the status bar when loading
 void SampleEditor::createStatusBar()
 {
   QLabel *statusLabel = new QLabel(tr(" Ready"));
   statusBar()->addWidget(statusLabel, 1);
 }
 //  We define the Menu 
 void SampleEditor::createMenus()
 {
   //FIRST HANDLE FILE MENU
   fileMenu = menuBar()->addMenu(tr("&File"));
   loadAction = new QAction(tr("Load File..."), this);
   loadAction->setStatusTip(tr("Load to table from text file"));
   connect(loadAction, SIGNAL(triggered()), this, SLOT(loadFile()));
   fileMenu->addAction(loadAction);
 }
  • 3. Load the data and create the associated views
 void SampleEditor::loadFile()
 {
   // Read the data here. In this case, we don't read the data from a file or from the 
   // command line. But it is not much different as you expect.
   // We first construct the column names of the table view
   // This table has 10 columns 
   std::vector<QString> headers;
   for(int i=0; i<10; ++i)
     {
        headers.push_back("Header " + QString::number(i));
     }
   // We write 100 numbers into a vector. You could read your data from a file first!       
   int numRows = 100;
   std::vector< std::vector< double > > data;
   for(int i=0; i<numRows; ++i)
   {
      std::vector<double> row;
      row.assign(10,i);
      data.push_back(row);
    }
    // Now put data into Model: 
    // The data and the selection models should be brand new. Check if there are existing ones
    if(selModel)
       delete selModel;
    if(model)
       delete model;
    // First create the model. Set the number of columns, and read their names 
    model = new QStandardItemModel;
    selModel = new QItemSelectionModel(model);
    model->clear();
    model->setColumnCount(headers.size());
    for(int i=0; i<(int)headers.size(); ++i)
      {
         model->setHeaderData(i, Qt::Horizontal, headers.at(i));
      }
    // write the data into the model 
    for (int row=0; row<(int)numRows; ++row)
      {
        model->insertRow(row);
        for(int col=0; col<(int)headers.size(); ++col)
           {
             model->setData(model->index(row, col), data.at(row).at(col));
           }
      }
    // Define the selections and relate it to your model 
    table->setModel(model);
    table->setSelectionModel(selModel); 
    table->update();
    // It is now time to create your views. First define the scatter plot view 
    if(plot)
      {
        plot->close();
        delete plot;
      }
    // Don't forget to relate it to the selection model 
    plot = new PlotWindow(selModel);
    plot->show();
    // Create the histogram view 
    if(histo)
      {
        histo->close();
        delete histo;
      }
    histo = new HistoWindow(selModel);
    histo->show();

}

This page was prepared by Aytekin Vargun (with Isaac Abbott's and Jon Luisi's contributions)

Personal tools