(C++) QtMatrix
February 24, 2017 · View on GitHub
(C++) QtMatrix



QtMatrix is a Qt class to display an Matrix.
Technical facts
./CppQtMatrix/CppQtMatrix.pri
INCLUDEPATH += \ ../../Classes/CppQtMatrix SOURCES += \ ../../Classes/CppQtMatrix/qtmatrix.cpp HEADERS += \ ../../Classes/CppQtMatrix/qtmatrix.h OTHER_FILES += \ ../../Classes/CppQtMatrix/Licence.txt
./CppQtMatrix/qtmatrix.h
#ifndef QTMATRIX_H #define QTMATRIX_H #include <string> #include <vector> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Weffc++" #include <boost/numeric/ublas/matrix.hpp> #include <boost/numeric/ublas/vector.hpp> #pragma GCC diagnostic pop struct QTableWidget; namespace ribi { ///Helper class for matrix operations struct QtMatrix { ///Obtain the version of this class static std::string GetVersion() noexcept; ///Obtain the version history of this class static std::vector<std::string> GetVersionHistory() noexcept; ///Write a uBLAS matrix of doubles to a QTableWidget static void MatrixToTable(const boost::numeric::ublas::matrix<double>& m, QTableWidget * const table); ///Write a vector of doubles to a QTableWidget static void StdVectorDoubleToTable(const std::vector<double>& v, QTableWidget * const table); ///Write a vector of strings to a QTableWidget static void StrVectorToTable(const std::vector<std::string>& v, QTableWidget * const table); ///Test these functions static void Test() noexcept; ///Convert a QTableWidget to a uBLAS matrix of doubles static const boost::numeric::ublas::matrix<double> ToMatrix(const QTableWidget * const table); ///Convert a QTableWidget to a vector of strings static std::vector<std::string> ToStrVector(const QTableWidget * const table); ///Convert a QTableWidget to a uBLAS vector of doubles static const boost::numeric::ublas::vector<double> ToVector(const QTableWidget * const table); ///Write a uBLAS vector of doubles to a QTableWidget static void UblasVectorDoubleToTable(const boost::numeric::ublas::vector<double>& v, QTableWidget * const table); }; } //~namespace ribi #endif // QTMATRIX_H
./CppQtMatrix/qtmatrix.cpp
#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include "qtmatrix.h" #include <cassert> #include <boost/lexical_cast.hpp> #include <boost/numeric/conversion/cast.hpp> #include <QTableWidget> #include "trace.h" #pragma GCC diagnostic pop std::string ribi::QtMatrix::GetVersion() noexcept { return "1.1"; } std::vector<std::string> ribi::QtMatrix::GetVersionHistory() noexcept { return { "2013-04-28: version 1.0: initial version", "2013-05-13: version 1.1: improved support for empty tables/vectors/matrices" }; } void ribi::QtMatrix::MatrixToTable(const boost::numeric::ublas::matrix<double>& m, QTableWidget * const table) { // assert(table); //assert(m.size1() >= 0); //Inevitable for std::size_t //assert(m.size2() >= 0); //Inevitable for std::size_t const std::size_t n_rows = m.size1(); const std::size_t n_cols = m.size2(); table->setRowCount( boost::numeric_cast<int>(m.size1())); table->setColumnCount(boost::numeric_cast<int>(m.size2())); assert(table->rowCount() == boost::numeric_cast<int>(m.size1())); assert(table->columnCount() == boost::numeric_cast<int>(m.size2())); for (std::size_t row=0; row!=n_rows; ++row) { for (std::size_t col=0; col!=n_cols; ++col) { QTableWidgetItem * const item = new QTableWidgetItem; assert(row < m.size1()); assert(col < m.size2()); item->setText(boost::lexical_cast<std::string>(m(row,col)).c_str()); table->setItem(row,col,item); } } // assert((m.size1() == 0 && m.size2() == 0) || boost::numeric::ublas::detail::equals(ToMatrix(table),m,0.00001,0.00001)); } void ribi::QtMatrix::StrVectorToTable(const std::vector<std::string>& v, QTableWidget * const table) { assert(table); if (v.empty()) { table->setRowCount(0); table->setColumnCount(0); return; } assert(!v.empty()); const int sz = boost::numeric_cast<int>(v.size()); table->setRowCount(sz); table->setColumnCount(1); assert(table->rowCount() == sz); assert(table->columnCount() == 1); for (int i=0; i!=sz; ++i) { QTableWidgetItem * const item = new QTableWidgetItem; assert(item); assert(i < boost::numeric_cast<int>(v.size())); assert(i < table->rowCount()); assert(table->rowCount() == sz); const std::string s = v[i]; item->setText(s.c_str()); assert(table->rowCount() == sz); table->setItem(i,0,item); assert(table); assert(table->rowCount() == sz); //FAILS??? } assert(table->rowCount() == sz); assert(ribi::QtMatrix::ToStrVector(table) == v); } void ribi::QtMatrix::StdVectorDoubleToTable(const std::vector<double>& v, QTableWidget * const table) { boost::numeric::ublas::vector<double> w(v.size()); assert(w.size() == v.size()); std::copy(v.begin(),v.end(),w.begin()); assert(v.empty() || v[0] == w(0)); assert(v.size() < 1 || v[1] == w(1)); assert(v.size() < 2 || v[2] == w(2)); assert(v.size() < 3 || v[3] == w(3)); UblasVectorDoubleToTable(w,table); } void ribi::QtMatrix::Test() noexcept { { static bool is_tested{false}; if (is_tested) return; is_tested = true; } #ifdef REALLY_WANNA_CHECK_2463986504397503 { const std::vector<std::string> v = {}; QTableWidget * const table = new QTableWidget; StrVectorToTable(v,table); assert(table->rowCount() == 0); assert(table->columnCount() == 0); } { const std::vector<std::string> v = { "X" }; QTableWidget * const table = new QTableWidget; StrVectorToTable(v,table); assert(table->rowCount() == 1); assert(table->columnCount() == 1); } { const std::vector<std::string> v = { "A","B" }; QTableWidget * const table = new QTableWidget; StrVectorToTable(v,table); assert(table->rowCount() == 2); assert(table->columnCount() == 1); } { const std::vector<std::string> v = { "A","BB","CCC" }; QTableWidget * const table = new QTableWidget; StrVectorToTable(v,table); assert(table->rowCount() == 3); assert(table->columnCount() == 1); } #endif } const boost::numeric::ublas::matrix<double> ribi::QtMatrix::ToMatrix(const QTableWidget * const table) { assert(table); const int n_rows = table->rowCount(); //n_rows can be zero const int n_cols = table->columnCount(); //n_cols can be zero boost::numeric::ublas::matrix<double> v(n_rows,n_cols); for(int col=0;col!=n_cols;++col) { for(int row=0;row!=n_rows;++row) { assert(row < boost::numeric_cast<int>(v.size1())); assert(col < boost::numeric_cast<int>(v.size2())); const auto item = table->item(row,col); if (item) { const std::string text = item->text().toStdString(); v(row,col) = boost::lexical_cast<double>(text); } else { v(row,col) = 0.0; } } } return v; } std::vector<std::string> ribi::QtMatrix::ToStrVector(const QTableWidget * const table) { assert(table); if (table->rowCount() == 0) { return std::vector<std::string>(); } assert(table->columnCount() == 1); const int n_rows = table->rowCount(); //n_rows can be zero std::vector<std::string> v; for (int row=0; row!=n_rows; ++row) { assert(row < table->rowCount()); const QTableWidgetItem * const item = table->item(row,0); const std::string s = item ? item->text().toStdString() : std::string(); v.push_back(s); } assert(table->rowCount() == boost::numeric_cast<int>(v.size())); return v; } const boost::numeric::ublas::vector<double> ribi::QtMatrix::ToVector(const QTableWidget * const table) { assert(table); const int n_rows = table->rowCount(); //n_rows can be zero boost::numeric::ublas::vector<double> v(n_rows); for(int row=0;row!=n_rows;++row) { const auto item = table->item(row,0); if (item) { const std::string text = item->text().toStdString(); assert(row < boost::numeric_cast<int>(v.size())); v(row) = boost::lexical_cast<double>(text); } else { assert(row < boost::numeric_cast<int>(v.size())); v(row) = 0.0; } } return v; } void ribi::QtMatrix::UblasVectorDoubleToTable(const boost::numeric::ublas::vector<double>& v, QTableWidget * const table) { assert(table); if (v.empty()) { table->setRowCount(0); table->setColumnCount(0); return; } assert(!v.empty()); table->setRowCount(boost::numeric_cast<int>(v.size())); table->setColumnCount(1); assert(table->rowCount() == boost::numeric_cast<int>(v.size())); assert(table->columnCount() == 1); const int sz = boost::numeric_cast<int>(v.size()); for (int i=0; i!=sz; ++i) { QTableWidgetItem * const item = new QTableWidgetItem; assert(item); assert(i < boost::numeric_cast<int>(v.size())); assert(i < table->rowCount()); try { const std::string s = boost::lexical_cast<std::string>(v[i]); item->setText(s.c_str()); } catch(boost::bad_lexical_cast& e) { assert(!"Should never get here: conversion from double to std::string must always succeed"); } table->setItem(i,0,item); } assert(boost::numeric::ublas::detail::equals(ToVector(table),v,0.00001,0.00001)); }