#pragma once #include class QBoxLayout; class QHBoxLayout; class QKeyEvent; class QString; // Base of every modal the player meets while playing (REQ-UI-MODAL-CHROME). A modal is // not an operating system window here: it is an ordinary child widget, hosted and placed // by the ModalLayer that also paints the dim it sits on, so it has no title bar, no // window border, and no window-manager close. What a window used to supply, this class // supplies instead -- the panel background, the drawn header, and the dismissal gestures. // // It stays a QDialog for accept()/reject()/result() and the Escape handling built into // them; only the window-ness is dropped (Qt::Widget flags). Nothing calls exec() on it: // ModalLayer::execute() runs the modal loop, so that the layer knows what is open. class ModalDialog : public QDialog { Q_OBJECT public: explicit ModalDialog(QWidget* parent = nullptr); // Whether Q and a click outside this dialog dismiss it (REQ-UI-DIALOG-DISMISS). One // predicate for both gestures because they reach exactly the same dialogs. The // default refuses both, so a dialog takes the gestures only by saying so: the two // name dialogs must let Q through as a character, and the schematic choice dialog // has no way out but choosing (REQ-DEF-SCHEMATIC-DROP). virtual bool isDismissible() const; public slots: // What a dismissal does, whichever gesture asked for it. Cancelling is the default; // a dialog with modes of its own overrides this to back out of them one at a time // (ShipLayoutDialog, REQ-UI-DIALOG-DISMISS). virtual void requestDismiss(); protected: // Adds the drawn header row -- the title, and a close button at the far right when // asked for -- as the first row of mainLayout, and returns it so a subclass can // insert its own widgets after the title (REQ-UI-MODAL-CHROME). The close button // rejects the dialog, which is what the window-manager close used to do. QHBoxLayout* addHeader(QBoxLayout* mainLayout, const QString& title, bool withCloseButton); void keyPressEvent(QKeyEvent* event) override; };