15.1.998. tablet_qt/widgets/openablewidget.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_OPENABLE_WIDGET_LAYOUT  // Dumps layout when widget shown
// #define DEBUG_PRESS_D_TO_DUMP
// #define DEBUG_RESIZE

#include "openablewidget.h"
#include <QGraphicsView>
#include <QKeyEvent>
#include <QResizeEvent>
#include <QVBoxLayout>
#include "lib/sizehelpers.h"
#include "lib/uifunc.h"

#ifdef DEBUG_OPENABLE_WIDGET_LAYOUT
#include "qobjects/showwatcher.h"
#endif
#ifdef DEBUG_PRESS_D_TO_DUMP
#include "lib/layoutdumper.h"
#endif
#ifdef DEBUG_RESIZE
#include "layouts/qtlayouthelpers.h"
#endif


OpenableWidget::OpenableWidget(QWidget* parent) :
    QWidget(parent),
    m_subwidget(nullptr),
    m_wants_fullscreen(false),
    m_escape_key_can_abort(true),
    m_escape_aborts_without_confirmation(false)
{
#ifdef DEBUG_OPENABLE_WIDGET_LAYOUT
    auto showwatcher = new ShowWatcher(this, true);
    Q_UNUSED(showwatcher)
#endif
}


void OpenableWidget::build()
{
    QWidget* widget = m_subwidget.data();
    auto openable_widget = dynamic_cast<OpenableWidget*>(widget);
    if (openable_widget) {
        openable_widget->build();
    }
}


bool OpenableWidget::wantsFullscreen() const
{
    return m_wants_fullscreen;
}


void OpenableWidget::setWantsFullscreen(const bool fullscreen)
{
    m_wants_fullscreen = fullscreen;
}


void OpenableWidget::setWidgetAsOnlyContents(QWidget* widget,
                                             const int margin,
                                             const bool fullscreen,
                                             const bool esc_can_abort)
{
    // Remove any existing layout
    m_subwidget = nullptr;
    QLayout* l = layout();
    delete l;
    // https://stackoverflow.com/questions/7528680/how-to-delete-an-already-existing-layout-on-a-widget
    // https://stackoverflow.com/questions/6731331/is-it-still-safe-to-delete-nullptr-in-c0x

    auto vl = new QVBoxLayout(this);
    setLayout(vl);
    vl->setContentsMargins(margin, margin, margin, margin);
    vl->addWidget(widget);

    m_subwidget = widget;

    // Full screen?
    setWantsFullscreen(fullscreen);  // in case we're not shown yet
    // In case we're already showing:
    if (fullscreen) {
        emit enterFullscreen();
    } else {
        emit leaveFullscreen();
    }

    // Escape key behaviour?
    // - Note that one reason not to have multiple widgets active but not
    //   shown is performance; another is defining which grabs the Escape key
    //   (or other keys); a third is connecting up all the signals correctly.
    setEscapeKeyCanAbort(esc_can_abort, false);
}


bool OpenableWidget::escapeKeyCanAbort() const
{
    return m_escape_key_can_abort;
}


void OpenableWidget::setEscapeKeyCanAbort(const bool esc_can_abort,
                                          const bool without_confirmation)
{
    m_escape_key_can_abort = esc_can_abort;
    m_escape_aborts_without_confirmation = without_confirmation;
}


void OpenableWidget::resizeEvent(QResizeEvent* event)
{
#ifdef DEBUG_RESIZE
    qDebug().nospace()
            << Q_FUNC_INFO
            << ": resized to " << event->size()
            << "; minimumSizeHint() " << minimumSizeHint()
            << "; qSmartMinSize(this) " << qtlayouthelpers::qSmartMinSize(this);
#else
    Q_UNUSED(event)
#endif
}


void OpenableWidget::keyPressEvent(QKeyEvent* event)
{
    if (!event) {
        return;
    }
    const int key = event->key();
    const QEvent::Type type = event->type();
    if (key == Qt::Key_Escape && type == QEvent::KeyPress) {
        // Escape key pressed
        if (m_escape_key_can_abort) {
            if (m_escape_aborts_without_confirmation ||
                    uifunc::confirm(tr("Abort: are you sure?"),
                                    tr("Abort?"),
                                    "", "", this)) {
                // User confirms: abort
                emit aborting();
                emit finished();
            }
        }
    }
#ifdef DEBUG_PRESS_D_TO_DUMP
    if (key == Qt::Key_D && type == QEvent::KeyPress) {
        layoutdumper::dumpWidgetHierarchy(this);
    }
#endif
}