void SpacesInteriorPartitionsGridController::addColumns(const QString &category, std::vector<QString> & fields)
  {
    // always show name and selected columns
    fields.insert(fields.begin(), { NAME, SELECTED });

    m_baseConcepts.clear();

    for (const auto &field : fields) {

      if (field == NAME) {
        addNameLineEditColumn(Heading(QString(NAME), false, false),
          false,
          false,
          CastNullAdapter<model::Space>(&model::Space::name),
          CastNullAdapter<model::Space>(&model::Space::setName)
          );
      }
      else {

          std::function<std::vector<model::ModelObject>(const model::Space &)> allInteriorPartitionSurfaceGroups(
            [](const model::Space &t_space) {
            std::vector<model::ModelObject> allModelObjects;
            auto interiorPartitionSurfaceGroups = t_space.interiorPartitionSurfaceGroups();
            allModelObjects.insert(allModelObjects.end(), interiorPartitionSurfaceGroups.begin(), interiorPartitionSurfaceGroups.end());
            return allModelObjects;
          }
          );

          std::function<std::vector<model::ModelObject>(const model::Space &)> allInteriorPartitionSurfaces(
            [allInteriorPartitionSurfaceGroups](const model::Space &t_space) {
            std::vector<model::ModelObject> allModelObjects;
            for (auto interiorPartitionSurfaceGroup : allInteriorPartitionSurfaceGroups(t_space)) {
              auto interiorPartitionSurfaces = interiorPartitionSurfaceGroup.cast<model::InteriorPartitionSurfaceGroup>().interiorPartitionSurfaces();
              for (auto interiorPartitionSurface : interiorPartitionSurfaces) {
                allModelObjects.push_back(interiorPartitionSurface);
              }
            }
            return allModelObjects;
          }
          );

          std::function<std::vector<boost::optional<model::ModelObject> >(const model::Space &)> allInteriorPartitionSurfaceInteriorPartitionSurfaceGroups(
            [allInteriorPartitionSurfaceGroups](const model::Space &t_space) {
            std::vector<boost::optional<model::ModelObject> > allModelObjects;
            for (auto interiorPartitionSurfaceGroup : allInteriorPartitionSurfaceGroups(t_space)) {
              auto interiorPartitionSurfaces = interiorPartitionSurfaceGroup.cast<model::InteriorPartitionSurfaceGroup>().interiorPartitionSurfaces();
              for (auto interiorPartitionSurface : interiorPartitionSurfaces) {
                auto group = interiorPartitionSurface.interiorPartitionSurfaceGroup();
                if (group) {
                  allModelObjects.push_back(*group);
                }
                else {
                  allModelObjects.emplace_back();
                }
              }
            }
            return allModelObjects;
          }
          );

        if (field == SELECTED) {
          auto checkbox = QSharedPointer<QCheckBox>(new QCheckBox());
          checkbox->setToolTip("Check to select all rows");
          connect(checkbox.data(), &QCheckBox::stateChanged, this, &SpacesInteriorPartitionsGridController::selectAllStateChanged);
          connect(checkbox.data(), &QCheckBox::stateChanged, this->gridView(), &OSGridView::gridRowSelectionChanged);

          addSelectColumn(Heading(QString(SELECTED), false, false, checkbox), "Check to select this row",
            DataSource(
            allInteriorPartitionSurfaces,
            true
            )
            );
        }
        else if (field == INTERIORPARTITIONGROUPNAME) {
          addNameLineEditColumn(Heading(QString(INTERIORPARTITIONGROUPNAME), true, false),
            false,
            false,
            CastNullAdapter<model::InteriorPartitionSurfaceGroup>(&model::InteriorPartitionSurfaceGroup::name),
            CastNullAdapter<model::InteriorPartitionSurfaceGroup>(&model::InteriorPartitionSurfaceGroup::setName),
            boost::optional<std::function<void(model::InteriorPartitionSurfaceGroup *)>>(),
            DataSource(
            allInteriorPartitionSurfaceInteriorPartitionSurfaceGroups,
            true)
            );
        }
        else if (field == INTERIORPARTITIONNAME) {
          addNameLineEditColumn(Heading(QString(INTERIORPARTITIONNAME), true, false),
          false,
          false,
          CastNullAdapter<model::InteriorPartitionSurface>(&model::InteriorPartitionSurface::name),
          CastNullAdapter<model::InteriorPartitionSurface>(&model::InteriorPartitionSurface::setName),
          boost::optional<std::function<void(model::InteriorPartitionSurface *)>>(),
          DataSource(
          allInteriorPartitionSurfaces,
          true)
          );
        }
        else if (field == CONSTRUCTIONNAME) {
          m_constructionColumn = 4;
          addDropZoneColumn(Heading(QString(CONSTRUCTIONNAME), true, false),
            CastNullAdapter<model::InteriorPartitionSurface>(&model::InteriorPartitionSurface::construction),
            CastNullAdapter<model::InteriorPartitionSurface>(&model::InteriorPartitionSurface::setConstruction),
            boost::optional<std::function<void(model::InteriorPartitionSurface*)> >(NullAdapter(&model::InteriorPartitionSurface::resetConstruction)),
            boost::optional<std::function<bool(model::InteriorPartitionSurface*)> >(NullAdapter(&model::InteriorPartitionSurface::isConstructionDefaulted)),
            DataSource(
            allInteriorPartitionSurfaces,
            true
            )
            );
        }
        else if (field == CONVERTTOINTERNALMASS) {
          addCheckBoxColumn(Heading(QString(CONVERTTOINTERNALMASS), true, false),
            std::string("Check to enable convert to InternalMass."),
            NullAdapter(&model::InteriorPartitionSurface::converttoInternalMass),
            NullAdapter(&model::InteriorPartitionSurface::setConverttoInternalMass),
            DataSource(
            allInteriorPartitionSurfaces,
            true
            )
            );
        }
        else if (field == SURFACEAREA) {
          std::function<bool(model::InteriorPartitionSurface *, double)> setter(
            [](model::InteriorPartitionSurface *t_interiorPartitionSurface, double t_arg) {
            return t_interiorPartitionSurface->setSurfaceArea(t_arg);
          }
          );

          addValueEditColumn(Heading(QString(SURFACEAREA)),
            CastNullAdapter<model::InteriorPartitionSurface>(&model::InteriorPartitionSurface::surfaceArea),
            setter//,
            //boost::optional<std::function<void(model::ModelObject *)>>(),
            //boost::optional<std::function<bool(model::ModelObject *)>>()//,
            //DataSource(
            //allInteriorPartitionSurfaces,
            //true
            //)
            );

          //boost::optional<double> surfaceArea() const; // TODO this optional is causing troubles
          //bool setSurfaceArea(boost::optional<double> surfaceArea);
          //bool setSurfaceArea(double surfaceArea);
          //void resetSurfaceArea();

        }
        else if (field == DAYLIGHTINGSHELFNAME) {
          //boost::optional<DaylightingDeviceShelf> daylightingDeviceShelf() const;

        }
        else {
          // unhandled
          OS_ASSERT(false);
        }
      }
    }
  }
  void FacilityShadingGridController::addColumns(const QString &category, std::vector<QString> & fields)
  {
    // always show name and selected columns
    // show type next to name, since it comes from the groups
    fields.insert(fields.begin(), { NAME, TYPE, SELECTED });

    m_baseConcepts.clear();

    for (const auto &field : fields) {

      if (field == NAME) {
        addNameLineEditColumn(Heading(QString(NAME), false, false),
          false,
          false,
          CastNullAdapter<model::ShadingSurfaceGroup>(&model::ShadingSurfaceGroup::name),
          CastNullAdapter<model::ShadingSurfaceGroup>(&model::ShadingSurfaceGroup::setName)
          );
      }
      // Evan note: TODO to correctly use this column we need a new control --
      // a dropzone for spaces, and a combo box with site and building as choices
      else if (field == TYPE) {
        std::function<std::vector<std::string>()> choices(
          []() {
          std::vector<std::string> choices{  "Site", "Building", "Space" };
          return choices;
        }
        );

        addComboBoxColumn(Heading(QString(TYPE)),
          std::function<std::string(const std::string &)>(static_cast<std::string(*)(const std::string&)>(&openstudio::toString)),
          choices,
          CastNullAdapter<model::ShadingSurfaceGroup>(&model::ShadingSurfaceGroup::shadingSurfaceType),
          CastNullAdapter<model::ShadingSurfaceGroup>(&model::ShadingSurfaceGroup::setShadingSurfaceType),
          boost::optional<std::function<void(model::ShadingSurfaceGroup*)>>(),
          boost::optional<std::function<bool(model::ShadingSurfaceGroup*)>>()
          );
      }
      else {

        std::function<std::vector<model::ModelObject>(const model::ShadingSurfaceGroup &)> allShadingSurfaces(
          [](const model::ShadingSurfaceGroup &t_shadingSurfaceGroup) {
          std::vector<model::ModelObject> allModelObjects;
          auto shadingSurfaces = t_shadingSurfaceGroup.shadingSurfaces();
          allModelObjects.insert(allModelObjects.end(), shadingSurfaces.begin(), shadingSurfaces.end());
          return allModelObjects;
        }
        );

        if (field == SELECTED) {
          auto checkbox = QSharedPointer<QCheckBox>(new QCheckBox());
          checkbox->setToolTip("Check to select all rows");
          connect(checkbox.data(), &QCheckBox::stateChanged, this, &FacilityShadingGridController::selectAllStateChanged);
          connect(checkbox.data(), &QCheckBox::stateChanged, this->gridView(), &OSGridView::gridRowSelectionChanged);

          addSelectColumn(Heading(QString(SELECTED), false, false, checkbox), "Check to select this row",
            DataSource(
            allShadingSurfaces,
            true
            )
            );
        }
        else if (field == SHADINGSURFACENAME) {
          addLoadNameColumn(Heading(QString(SHADINGSURFACENAME), true, false),
            CastNullAdapter<model::ShadingSurface>(&model::ShadingSurface::name),
            CastNullAdapter<model::ShadingSurface>(&model::ShadingSurface::setName),
            boost::optional<std::function<void(model::ShadingSurface *)>>(
            std::function<void(model::ShadingSurface *)>(
            [](model::ShadingSurface *t_ss)
          {
            t_ss->remove();
          }
            )
            ),
            DataSource(
            allShadingSurfaces,
            true
            )
            );
        }
        else if (field == CONSTRUCTIONNAME) {
          addDropZoneColumn(Heading(QString(CONSTRUCTIONNAME), true, false),
            CastNullAdapter<model::ShadingSurface>(&model::ShadingSurface::construction),
            CastNullAdapter<model::ShadingSurface>(&model::ShadingSurface::setConstruction),
            boost::optional<std::function<void(model::ShadingSurface*)> >(NullAdapter(&model::ShadingSurface::resetConstruction)),
            boost::optional<std::function<bool(model::ShadingSurface*)> >(NullAdapter(&model::ShadingSurface::isConstructionDefaulted)),
            DataSource(
            allShadingSurfaces,
            true
            )
            );
        }
        else if (field == TRANSMITTANCESCHEDULENAME) {
          std::function<bool(model::ShadingSurface *, const model::Schedule &)> setter(
            [](model::ShadingSurface *t_shadingSurface, const model::Schedule &t_schedule) {
            auto copy = t_schedule;
            return t_shadingSurface->setTransmittanceSchedule(copy);
          }
          );

          addDropZoneColumn(Heading(QString(TRANSMITTANCESCHEDULENAME), true, false),
            CastNullAdapter<model::ShadingSurface>(&model::ShadingSurface::transmittanceSchedule),
            setter,
            boost::optional<std::function<void(model::ShadingSurface*)>>(CastNullAdapter<model::ShadingSurface>(&model::ShadingSurface::resetTransmittanceSchedule)),
            boost::optional<std::function<bool(model::ShadingSurface*)> >(),
            DataSource(
            allShadingSurfaces,
            true
            )
            );
        }
        else {
          // unhandled
          OS_ASSERT(false);
        }
      }
    }
  }