/*
Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
This file is part of CamCOPS.
CamCOPS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CamCOPS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
*/
// By Joe Kearney, Rudolf Cardinal.
#include "gbogres.h"
#include "maths/mathfunc.h"
#include "lib/datetime.h"
#include "lib/stringfunc.h"
#include "questionnairelib/namevalueoptions.h"
#include "questionnairelib/qudatetime.h"
#include "questionnairelib/questionnaire.h"
#include "questionnairelib/quheading.h"
#include "questionnairelib/quhorizontalcontainer.h"
#include "questionnairelib/quhorizontalline.h"
#include "questionnairelib/qumcq.h"
#include "questionnairelib/quspacer.h"
#include "questionnairelib/qutext.h"
#include "questionnairelib/qutextedit.h"
#include "tasklib/taskfactory.h"
#include "tasklib/taskregistrar.h"
#include "taskxtra/gbocommon.h"
using mathfunc::noneNullOrEmpty;
using stringfunc::strseq;
const QString GboGReS::GBOGRES_TABLENAME("gbogres");
const QString FN_DATE("date"); // NB SQL keyword too; doesn't matter
const QString FN_GOAL_1_DESC("goal_1_description");
const QString FN_GOAL_2_DESC("goal_2_description");
const QString FN_GOAL_3_DESC("goal_3_description");
const QString FN_GOAL_OTHER("other_goals");
const QString FN_COMPLETED_BY("completed_by");
const QString FN_COMPLETED_BY_OTHER("completed_by_other");
const QString TAG_OTHER("other");
void initializeGboGReS(TaskFactory& factory)
{
static TaskRegistrar<GboGReS> registered(factory);
}
GboGReS::GboGReS(CamcopsApp& app, DatabaseManager& db, const int load_pk) :
Task(app, db, GBOGRES_TABLENAME, false, false, false), // ... anon, clin, resp
m_questionnaire(nullptr)
{
addField(FN_DATE, QMetaType::fromType<QDate>());
addField(FN_GOAL_1_DESC, QMetaType::fromType<QString>());
addField(FN_GOAL_2_DESC, QMetaType::fromType<QString>());
addField(FN_GOAL_3_DESC, QMetaType::fromType<QString>());
addField(FN_GOAL_OTHER, QMetaType::fromType<QString>());
addField(FN_COMPLETED_BY, QMetaType::fromType<int>());
addField(FN_COMPLETED_BY_OTHER, QMetaType::fromType<QString>());
load(load_pk); // MUST ALWAYS CALL from derived Task constructor.
// Extra initialization:
if (load_pk == dbconst::NONEXISTENT_PK) {
setValue(FN_DATE, datetime::nowDate(), false);
}
}
// ============================================================================
// Class info
// ============================================================================
QString GboGReS::shortname() const
{
return "GBO-GReS";
}
QString GboGReS::longname() const
{
return tr("Goal-Based Outcomes – 1 – Goal Record Sheet");
}
QString GboGReS::description() const
{
return tr("For recording goals of therapy.");
}
QString GboGReS::infoFilenameStem() const
{
return xstringTaskname();
}
QString GboGReS::xstringTaskname() const
{
return "gbo";
}
// ============================================================================
// Instance info
// ============================================================================
bool GboGReS::isComplete() const
{
if (anyValuesNullOrEmpty({FN_DATE, FN_GOAL_1_DESC, FN_COMPLETED_BY})) {
return false;
}
if (value(FN_COMPLETED_BY) == gbocommon::AGENT_OTHER
&& valueIsNullOrEmpty(FN_COMPLETED_BY_OTHER)) {
return false;
}
return true;
}
QStringList GboGReS::summary() const
{
return QStringList{
QString("Date: <b>%1</b>.").arg(
datetime::dateToIso(valueDate(FN_DATE))),
QString("Goals set: <b>%1</b>%2.").arg(numGoalsDescription(),
extraGoalsDescription()),
};
}
QStringList GboGReS::detail() const
{
QStringList detail = summary();
int i = 0;
for (auto field : {FN_GOAL_1_DESC, FN_GOAL_2_DESC, FN_GOAL_3_DESC}) {
++i;
if (!valueIsNullOrEmpty(field)) {
detail.push_back(QString("Goal %1: <b>%2</b>.").arg(
QString::number(i),
value(field).toString()));
}
}
if (!valueIsNullOrEmpty(FN_GOAL_OTHER)) {
detail.push_back(QString("Extra goals: <b>%1</b>")
.arg(value(FN_GOAL_OTHER).toString()));
}
detail.push_back(QString("Completed by: <b>%1</b>.").arg(completedBy()));
return detail;
}
OpenableWidget* GboGReS::editor(const bool read_only)
{
const NameValueOptions completed_by_options = NameValueOptions{
{ xstring("agent_1"), gbocommon::AGENT_PATIENT },
{ xstring("agent_2"), gbocommon::AGENT_PARENT_CARER },
{ xstring("agent_3"), gbocommon::AGENT_CLINICIAN },
{ xstring("agent_4"), gbocommon::AGENT_OTHER }
};
const QString goal_desc = xstring("goal_desc");
QuPagePtr page(new QuPage{
(new QuHorizontalContainer{
new QuHeading(xstring("date")),
(new QuDateTime(fieldRef(FN_DATE))
)->setMode(QuDateTime::DefaultDate)
->setOfferNowButton(true),
}),
(new QuText(xstring("gres_stem")))->setBold(true),
new QuSpacer(),
new QuHeading(xstring("goal_1")),
new QuText(goal_desc),
new QuTextEdit(fieldRef(FN_GOAL_1_DESC)),
new QuSpacer(),
new QuHeading(xstring("goal_2")),
new QuText(goal_desc),
new QuTextEdit(fieldRef(FN_GOAL_2_DESC, false)),
new QuSpacer(),
new QuHeading(xstring("goal_3")),
new QuText(goal_desc),
new QuTextEdit(fieldRef(FN_GOAL_3_DESC, false)),
new QuSpacer(),
(new QuText(xstring("goal_other")))->setBold(true),
new QuTextEdit(fieldRef(FN_GOAL_OTHER, false)),
new QuSpacer(),
(new QuText(xstring("completed_by")))->setBold(true),
(new QuMcq(fieldRef(FN_COMPLETED_BY), completed_by_options))
->setHorizontal(true)
->setAsTextButton(true),
(new QuTextEdit(fieldRef(FN_COMPLETED_BY_OTHER), false))->addTag(TAG_OTHER),
new QuSpacer(),
new QuHorizontalLine(),
new QuSpacer(),
(new QuText(xstring("copyright")))->setItalic()
});
page->setTitle(longname());
m_questionnaire = new Questionnaire(m_app, {page});
m_questionnaire->setReadOnly(read_only);
connect(fieldRef(FN_COMPLETED_BY).data(), &FieldRef::valueChanged,
this, &GboGReS::updateMandatory);
updateMandatory();
return m_questionnaire;
}
// ============================================================================
// Task-specific calculations
// ============================================================================
void GboGReS::updateMandatory()
{
const bool required = valueInt(FN_COMPLETED_BY) == gbocommon::AGENT_OTHER;
fieldRef(FN_COMPLETED_BY_OTHER)->setMandatory(required);
if (!m_questionnaire) {
return;
}
m_questionnaire->setVisibleByTag(TAG_OTHER, required);
}
QString GboGReS::numGoalsDescription() const
{
int goal_n = 0;
for (auto field : {FN_GOAL_1_DESC, FN_GOAL_2_DESC, FN_GOAL_3_DESC}) {
if (!valueIsNullOrEmpty(field)) {
++goal_n;
}
}
return QString::number(goal_n);
}
QString GboGReS::extraGoalsDescription() const
{
QString extra = "";
if (!valueIsNullOrEmpty(FN_GOAL_OTHER)) {
extra = " <i>(with additional goals set)</i>";
}
return extra;
}
QString GboGReS::completedBy() const
{
return gbocommon::agentDescription(valueInt(FN_COMPLETED_BY),
valueString(FN_COMPLETED_BY_OTHER));
}