15.1.353. tablet_qt/menulib/menuheader.cpp

/*
    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/>.
*/

// #define DEBUG_SLOTS

#include "menuheader.h"
#include <QAbstractButton>
#include <QLabel>
#include "common/cssconst.h"
#include "common/uiconst.h"
#include "dbobjects/patient.h"
#include "layouts/flowlayouthfw.h"
#include "layouts/layouts.h"
#include "lib/sizehelpers.h"
#include "lib/uifunc.h"
#include "menu/singleuseroptionsmenu.h"
#include "widgets/basewidget.h"
#include "widgets/clickablelabelwordwrapwide.h"
#include "widgets/horizontalline.h"
#include "widgets/imagebutton.h"
#include "widgets/labelwordwrapwide.h"


MenuHeader::MenuHeader(QWidget* parent,
                       CamcopsApp& app,
                       const bool top,
                       const QString& title,
                       const QString& icon_filename,
                       const bool debug_allowed)
    : QWidget(parent),
      m_app(app),
      m_button_needs_upload(nullptr),  // waste of effort; constructed as nullptr
      m_button_debug(nullptr),
      m_button_view(nullptr),
      m_button_edit(nullptr),
      m_button_delete(nullptr),
      m_button_add(nullptr),
      m_button_locked(nullptr),
      m_button_unlocked(nullptr),
      m_button_privileged(nullptr),
      m_patient_info(nullptr),
      m_no_patient(nullptr),
      m_single_user_options(nullptr)
{
    auto mainlayout = new VBoxLayout();
    setLayout(mainlayout);

    // ------------------------------------------------------------------------
    // Main row
    // ------------------------------------------------------------------------

    // Left
    m_top_bar = new BaseWidget();
    m_top_bar->setSizePolicy(sizehelpers::expandingFixedHFWPolicy());
    auto toprowlayout = new HBoxLayout();
    m_top_bar->setLayout(toprowlayout);
    mainlayout->addWidget(m_top_bar);

    const Qt::Alignment button_align = Qt::AlignHCenter | Qt::AlignTop;
    const Qt::Alignment text_align = Qt::AlignLeft | Qt::AlignVCenter;

    // - Back button (unless top)
    if (!top) {
        QAbstractButton* back = new ImageButton(uiconst::CBS_BACK);
        toprowlayout->addWidget(back, 0, button_align);
        connect(back, &QAbstractButton::clicked,
                this, &MenuHeader::backClicked,
                Qt::UniqueConnection);
    }

    // Spacing
    toprowlayout->addStretch();

    // Centre

    // - Icon for current menu
    m_icon = new QLabel();
    setIcon(icon_filename, false);
    toprowlayout->addWidget(m_icon, 0, button_align);

    // - Title
    m_title_label = new LabelWordWrapWide(title);
    m_title_label->setAlignment(text_align);
    m_title_label->setObjectName(cssconst::MENU_WINDOW_TITLE);
    toprowlayout->addWidget(m_title_label, 0, text_align);

    // Spacing
    toprowlayout->addStretch();

    // Right-hand icons ("verbs")
    auto rh_icons = new FlowLayoutHfw();
    toprowlayout->addLayout(rh_icons);
    rh_icons->setHorizontalAlignmentOfContents(Qt::AlignRight);

    // - Debug
    if (debug_allowed) {
        m_button_debug = new QPushButton(tr("Dump layout"));
        connect(m_button_debug, &QAbstractButton::clicked,
                this, &MenuHeader::debugLayout);
        rh_icons->addWidget(m_button_debug, text_align);
    }

    // - Task verb buttons
    m_button_finish_flag = new ImageButton(uiconst::CBS_FINISHFLAG);
    m_button_view = new ImageButton(uiconst::CBS_ZOOM);
    m_button_edit = new ImageButton(uiconst::CBS_EDIT);
    m_button_delete = new ImageButton(uiconst::CBS_DELETE);
    m_button_add = new ImageButton(uiconst::CBS_ADD);
    rh_icons->addWidget(m_button_finish_flag, button_align);
    rh_icons->addWidget(m_button_view, button_align);
    rh_icons->addWidget(m_button_edit, button_align);
    rh_icons->addWidget(m_button_delete, button_align);
    rh_icons->addWidget(m_button_add, button_align);
    offerFinishFlag();
    offerView();
    offerEditDelete();
    offerAdd();
    connect(m_button_finish_flag, &QAbstractButton::clicked,
            this, &MenuHeader::finishFlagClicked);
    connect(m_button_view, &QAbstractButton::clicked,
            this, &MenuHeader::viewClicked);
    connect(m_button_edit, &QAbstractButton::clicked,
            this, &MenuHeader::editClicked);
    connect(m_button_delete, &QAbstractButton::clicked,
            this, &MenuHeader::deleteClicked);
    connect(m_button_add, &QAbstractButton::clicked,
            this, &MenuHeader::addClicked);

    // - Needs upload ("upload")
    m_button_needs_upload = new ImageButton(uiconst::ICON_UPLOAD);
    rh_icons->addWidget(m_button_needs_upload, button_align);
    needsUploadChanged(m_app.needsUpload());
    connect(m_button_needs_upload, &QAbstractButton::clicked,
            &m_app, &CamcopsApp::upload);

    // - Locked/unlocked/privileged
    m_button_locked = new ImageButton(uiconst::CBS_LOCKED);
    m_button_unlocked = new ImageButton(uiconst::CBS_UNLOCKED);
    m_button_privileged = new ImageButton(uiconst::CBS_PRIVILEGED);
    rh_icons->addWidget(m_button_locked, button_align);
    rh_icons->addWidget(m_button_unlocked, button_align);
    rh_icons->addWidget(m_button_privileged, button_align);
    lockStateChanged(m_app.lockstate());
    connect(m_button_locked, &QAbstractButton::clicked,
            &m_app, &CamcopsApp::unlock);
    connect(m_button_unlocked, &QAbstractButton::clicked,
            &m_app, &CamcopsApp::lock);
    connect(m_button_privileged, &QAbstractButton::clicked,
            &m_app, &CamcopsApp::unlock);

    // ------------------------------------------------------------------------
    // Horizontal line
    // ------------------------------------------------------------------------
    auto horizline = new HorizontalLine(uiconst::HEADER_HLINE_WIDTH);
    horizline->setObjectName(cssconst::HEADER_HORIZONTAL_LINE);
    mainlayout->addWidget(horizline);

    // ------------------------------------------------------------------------
    // Selected patient
    // ------------------------------------------------------------------------
    auto patient_bar = new BaseWidget();
    patient_bar->setSizePolicy(sizehelpers::expandingFixedHFWPolicy());
    auto patientlayout = new HBoxLayout();
    patient_bar->setLayout(patientlayout);
    mainlayout->addWidget(patient_bar);

    m_patient_info = new LabelWordWrapWide();
    m_patient_info->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    m_patient_info->setObjectName(cssconst::MENU_HEADER_PATIENT_INFO);
    patientlayout->addWidget(m_patient_info, 0, text_align);

    if (m_app.isSingleUserMode()) {
        m_no_patient = new ClickableLabelWordWrapWide(tr("Register me"));
        m_no_patient->setObjectName(cssconst::MENU_HEADER_SINGLE_USER_BUTTONS);
        connect(m_no_patient, &QAbstractButton::clicked,
                this, &MenuHeader::registerPatient);
    } else {
        m_no_patient = new ClickableLabelWordWrapWide(tr("No patient selected"));
        m_no_patient->setObjectName(cssconst::MENU_HEADER_NO_PATIENT);
    }

    m_no_patient->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    patientlayout->addWidget(m_no_patient, 0, text_align);
    patientlayout->addStretch();

    if (top && m_app.isSingleUserMode()) {
        m_single_user_options = new ClickableLabelWordWrapWide(tr("More options"));
        m_single_user_options->setObjectName(cssconst::MENU_HEADER_SINGLE_USER_BUTTONS);
        connect(m_single_user_options, &QAbstractButton::clicked,
                this, &MenuHeader::openOptionsMenu);
        patientlayout->addWidget(m_single_user_options, 0, Qt::AlignRight);
    }

    setPatientDetails(m_app.selectedPatient());

    setCrippled(false);

    // ========================================================================
    // Incoming signals
    // ========================================================================
    connect(&m_app, &CamcopsApp::lockStateChanged,
            this, &MenuHeader::lockStateChanged,
            Qt::UniqueConnection);
    connect(&m_app, &CamcopsApp::selectedPatientChanged,
            this, &MenuHeader::selectedPatientChanged,
            Qt::UniqueConnection);
    connect(&m_app, &CamcopsApp::selectedPatientDetailsChanged,
            this, &MenuHeader::selectedPatientDetailsChanged,
            Qt::UniqueConnection);
    connect(&m_app, &CamcopsApp::needsUploadChanged,
            this, &MenuHeader::needsUploadChanged,
            Qt::UniqueConnection);
}


void MenuHeader::setTitle(const QString& title)
{
    if (!m_title_label) {
        return;
    }
    m_title_label->setText(title);
}


void MenuHeader::setIcon(const QString& icon_filename)
{
    setIcon(icon_filename, true);
}


void MenuHeader::setIcon(const QString& icon_filename, bool call_show_or_hide)
{
    uifunc::setLabelToIcon(m_icon, icon_filename);
    if (call_show_or_hide) {
        if (icon_filename.isEmpty()) {
            m_icon->hide();
        } else {
            m_icon->show();
        }
    }
}


void MenuHeader::setCrippled(const bool crippled)
{
    if (m_top_bar) {
        m_top_bar->setObjectName(crippled ? cssconst::MENU_HEADER_CRIPPLED
                                          : "");
    }
}


void MenuHeader::lockStateChanged(const CamcopsApp::LockState lockstate)
{
    m_button_locked->setVisible(lockstate == CamcopsApp::LockState::Locked);
    m_button_unlocked->setVisible(lockstate == CamcopsApp::LockState::Unlocked);
    m_button_privileged->setVisible(lockstate == CamcopsApp::LockState::Privileged);
}


void MenuHeader::needsUploadChanged(const bool needs_upload)
{
    m_button_needs_upload->setVisible(needs_upload);
}


void MenuHeader::selectedPatientChanged(const Patient* patient)
{
#ifdef DEBUG_SLOTS
    qDebug() << Q_FUNC_INFO << "[this:" << this << "]";
#endif
    setPatientDetails(patient);
}


void MenuHeader::selectedPatientDetailsChanged(const Patient* patient)
{
#ifdef DEBUG_SLOTS
    qDebug() << Q_FUNC_INFO << "[this:" << this << "]";
#endif
    setPatientDetails(patient);
}


void MenuHeader::setPatientDetails(const Patient* patient)
{
    const bool selected = patient != nullptr;
    QString info;

    if (selected) {
        if (m_app.isSingleUserMode()) {
            info = patient->oneLineHtmlSimpleString();
        } else {
            info = patient->oneLineHtmlDetailString();
        }
    }
#ifdef DEBUG_SLOTS
    qDebug() << Q_FUNC_INFO << info << "[patient:" << patient << "]";
#endif
    m_patient_info->setText(info);
    m_no_patient->setVisible(!selected);
    m_patient_info->setVisible(selected);
}


void MenuHeader::offerView(const bool offer_view)
{
    m_button_view->setVisible(offer_view);
}


void MenuHeader::offerEditDelete(const bool offer_edit,
                                 const bool offer_delete)
{
    m_button_edit->setVisible(offer_edit);
    m_button_delete->setVisible(offer_delete);
}


void MenuHeader::offerAdd(const bool offer_add)
{
    m_button_add->setVisible(offer_add);
}


void MenuHeader::offerFinishFlag(const bool offer_finish_flag)
{
    m_button_finish_flag->setVisible(offer_finish_flag);
}


void MenuHeader::openOptionsMenu()
{
    m_app.openSubWindow(new SingleUserOptionsMenu(m_app));
}


void MenuHeader::registerPatient()
{
    m_app.registerPatientWithServer();
}