C++ – How to implement a database TableView like thing in C++

boostcdesign-patternsrelational-databasesql

How can I implement a TableView like thing in C++?

I want to emulating a tiny relation database like thing in C++. I have data tables, and I want to transform it somehow, so I need a TableView like class. I want filtering, sorting, freely add and remove items and transforming (ex. view as UPPERCASE and so on). The whole thing is inside a GUI application, so datatables and views are attached to a GUI (or HTML or something).

So how can I identify an item in the view? How can I signal it when the table is changed? Is there some design pattern for this?

Here is a simple table, and a simple data item:

#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>

using boost::multi_index_container;
using namespace boost::multi_index;

struct Data
{
  Data() {}
  int id;
  std::string name;
};

struct row{};
struct id{};
struct name{};

typedef boost::multi_index_container<
  Data,
  indexed_by<
    random_access<tag<row> >,
    ordered_unique<tag<id>, member<Data, int, &Data::id> >,
    ordered_unique<tag<name>, member<Data, std::string, &Data::name> >
  >
> TDataTable;

class DataTable
{
public:
  typedef Data item_type;
  typedef TDataTable::value_type value_type;
  typedef TDataTable::const_reference const_reference;
  typedef TDataTable::index<row>::type TRowIndex;
  typedef TDataTable::index<id>::type TIdIndex;
  typedef TDataTable::index<name>::type TNameIndex;
  typedef TRowIndex::iterator iterator;

  DataTable() :
    row_index(rule_table.get<row>()),
    id_index(rule_table.get<id>()),
    name_index(rule_table.get<name>()),
    row_index_writeable(rule_table.get<row>())
  {
  }

  TDataTable::const_reference operator[](TDataTable::size_type n) const
  { return rule_table[n]; }

  std::pair<iterator,bool> push_back(const value_type& x)
  { return row_index_writeable.push_back(x); }

  iterator erase(iterator position)
  { return row_index_writeable.erase(position); }

  bool replace(iterator position,const value_type& x)
  { return row_index_writeable.replace(position, x); }

  template<typename InputIterator> void rearrange(InputIterator first)
  { return row_index_writeable.rearrange(first); }

  void print_table() const;

  unsigned size() const
  { return row_index.size(); }

  TDataTable rule_table;
  const TRowIndex& row_index;
  const TIdIndex& id_index;
  const TNameIndex& name_index;
private:
  TRowIndex& row_index_writeable;
};

class DataTableView
{
  DataTableView(const DataTable& source_table) {}
  // How can I implement this?
  // I want filtering, sorting, signaling upper GUI layer, and sorting, and ...
};

int main()
{
  Data data1;
  data1.id = 1;
  data1.name = "name1";
  Data data2;
  data2.id = 2;
  data2.name = "name2";

  DataTable table;
  table.push_back(data1);
  DataTable::iterator it1 = table.row_index.iterator_to(table[0]);
  table.erase(it1);
  table.push_back(data1);
  Data new_data(table[0]);
  new_data.name = "new_name";
  table.replace(table.row_index.iterator_to(table[0]), new_data);
  for (unsigned i = 0; i < table.size(); ++i)
    std::cout << table[i].name << std::endl;

#if 0
  // using scenarios:
  DataTableView table_view(table);
  table_view.fill_from_source(); // synchronization with source
  table_view.remove(data_item1); // remove item from view
  table_view.add(data_item2); // add item from source table
  table_view.filter(filterfunc); // filtering
  table_view.sort(sortfunc); // sorting

  // modifying from source_able, hot to signal the table_view?
  // FYI: Table view is atteched to a GUI item
  table.erase(data);
  table.replace(data);
#endif

  return 0;
}

Best Answer

If your using the QT SDK you can use the QTableView. You could also look at the source code for QTableView to get an idea how to build your own TableView class.