FlightGear next
MessageBox.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2 #include "config.h"
3#endif
4
5#include <simgear/simgear_config.h>
6
7#include <cstdlib>
8
9#include "MessageBox.hxx"
10
11#include <Main/fg_props.hxx>
12#include <Main/globals.hxx>
13#include <Viewer/renderer.hxx>
14#include <GUI/new_gui.hxx>
16
17#include <osgViewer/Viewer>
18
19#include <simgear/structure/commands.hxx>
20
21#ifdef SG_WINDOWS
22 #include <windows.h>
23
24#include <osgViewer/GraphicsWindow>
25#include <osgViewer/api/Win32/GraphicsWindowWin32>
26#endif
27
28#if defined(SG_MAC)
29
30// externs from CocoaMessageBox.mm
32cocoaFatalMessage(const std::string& msg, const std::string& text);
33
35cocoaMessageBox(const std::string& msg, const std::string& text);
36
37#endif
38
39#ifdef HAVE_QT
40 #include "QtMessageBox.hxx"
41#endif
42
43using namespace simgear::strutils;
44
45namespace {
46
47static bool static_isHeadless = false;
48
49bool isCanvasImplementationRegistered()
50{
51 if (!globals) {
52 return false;
53 }
54
55 SGCommandMgr* cmd = globals->get_commands();
56 return (cmd->getCommand("canvas-message-box") != NULL);
57}
58
59#if defined(SG_WINDOWS)
60
62{
63 osgViewer::Viewer::Windows windows;
64 if (!globals || !globals->get_renderer() || !globals->get_renderer()->getViewerBase()) {
65 return 0;
66 }
67
68 globals->get_renderer()->getViewerBase()->getWindows(windows);
69 osgViewer::Viewer::Windows::const_iterator it = windows.begin();
70 for(; it != windows.end(); ++it) {
71 if (strcmp((*it)->className(), "GraphicsWindowWin32")) {
72 continue;
73 }
74
75 osgViewer::GraphicsWindowWin32* platformWin =
76 static_cast<osgViewer::GraphicsWindowWin32*>(*it);
77 return platformWin->getHWND();
78 }
79
80 return 0;
81}
82
84win32MessageBox(const std::string& caption,
85 const std::string& msg,
86 const std::string& moreText)
87{
88 // during early startup (aircraft / fg-data validation) there is no
89 // osgViewer so no HWND.
90 HWND ownerWindow = getMainViewerHWND();
91 std::string fullMsg(msg);
92 if (!moreText.empty()) {
93 fullMsg += "\n\n" + moreText;
94 }
95
96 UINT mbType = MB_OK;
97 std::wstring wMsg(convertUtf8ToWString(fullMsg)),
98 wCap(convertUtf8ToWString(caption));
99
100 ::MessageBoxExW(ownerWindow, wMsg.c_str(), wCap.c_str(),
101 mbType, 0 /* system lang */);
102
104}
105
106#endif
107
108} // anonymous namespace
109
110namespace flightgear
111{
112
113void setHeadlessMode(bool headless)
114{
115 static_isHeadless = headless;
116}
117
119{
120 return static_isHeadless;
121}
122
123MessageBoxResult modalMessageBox(const std::string& caption,
124 const std::string& msg,
125 const std::string& moreText)
126{
127 // Headless mode.
128 if (static_isHeadless) {
129 SG_LOG(SG_HEADLESS, SG_ALERT, "ModalMessageBox Caption: \"" << caption << "\"");
130 SG_LOG(SG_HEADLESS, SG_ALERT, "ModalMessageBox Message: \"" << msg << "\"");
131 if (!moreText.empty())
132 SG_LOG(SG_HEADLESS, SG_ALERT, "ModalMessageBox More text: \"" << moreText << "\"");
133 return MSG_BOX_OK;
134 }
135
136 // prefer canvas
137 if (isCanvasImplementationRegistered()) {
138 SGPropertyNode_ptr args(new SGPropertyNode);
139 args->setStringValue("caption", caption);
140 args->setStringValue("message", msg);
141 args->setStringValue("more", moreText);
142 globals->get_commands()->execute("canvas-message-box", args, nullptr);
143
144 // how to make it modal?
145
146 return MSG_BOX_OK;
147 }
148
149#if defined(SG_WINDOWS)
150 return win32MessageBox(caption, msg, moreText);
151#elif defined(SG_MAC)
152 return cocoaMessageBox(msg, moreText);
153#elif defined(HAVE_QT)
154 return QtMessageBox(caption, msg, moreText, false);
155#else
156 std::string s = caption + ": "+ msg;
157 if (!moreText.empty()) {
158 s += "\n( " + moreText + ")";
159 }
160
161 auto gui = globals->get_subsystem<NewGUI>();
162 if (!gui || (fgGetBool("/sim/rendering/initialized", false) == false)) {
163 SG_LOG(SG_GENERAL, SG_POPUP, s);
164 } else {
165 SGPropertyNode_ptr dlg = gui->getDialogProperties("popup");
166 dlg->setStringValue("text/label", s );
167 gui->showDialog("popup");
168 }
169 return MSG_BOX_OK;
170#endif
171}
172
174 const std::string& msg,
175 const std::string& moreText,
176 bool reportToSentry)
177{
178 if (reportToSentry) {
180 }
181
182 // Headless mode.
183 if (static_isHeadless) {
184 SG_LOG(SG_HEADLESS, SG_ALERT, "Fatal Error: \"" << caption << "\"");
185 SG_LOG(SG_HEADLESS, SG_ALERT, "Error Message: \"" << msg << "\"");
186 if (!moreText.empty())
187 SG_LOG(SG_HEADLESS, SG_ALERT, "\tMore text: \"" << moreText << "\"");
188 return MSG_BOX_OK;
189 }
190
191#if defined(SG_WINDOWS)
192 return win32MessageBox(caption, msg, moreText);
193#elif defined(SG_MAC)
194 return cocoaFatalMessage(msg, moreText);
195#elif defined(HAVE_QT)
196 return QtMessageBox(caption, msg, moreText, true);
197#else
198 std::string s = "FATAL: "+ msg;
199 if (!moreText.empty()) {
200 s += "\n( " + moreText + ")";
201 }
202 if (fgGetBool("/sim/rendering/initialized", false) == false) {
203 std::cerr << s << std::endl;
204 } else {
205 auto _gui = globals->get_subsystem<NewGUI>();
206 SGPropertyNode_ptr dlg = _gui->getDialogProperties("popup");
207 dlg->setStringValue("text/label", s );
208 _gui->showDialog("popup");
209 }
210 return MSG_BOX_OK;
211#endif
212}
213
214[[noreturn]] void fatalMessageBoxThenExit(
215 const std::string& caption,
216 const std::string& msg,
217 const std::string& moreText,
218 int exitStatus,
219 bool reportToSentry)
220{
221 SG_LOG(SG_GENERAL, SG_ALERT, msg);
222 fatalMessageBoxWithoutExit(caption, msg, moreText, reportToSentry);
223 // we can't use exit() here or QGuiApplication crashes
224 // let's instead throw a sepcial exception which we catch
225 // in boostrap.
226 throw FatalErrorException{};
227}
228
229} // of namespace flightgear
static HWND getMainViewerHWND()
flightgear::MessageBoxResult QtMessageBox(const std::string &caption, const std::string &msg, const std::string &moreText, bool fatal)
XML-configured GUI subsystem.
Definition new_gui.hxx:31
virtual SGPropertyNode_ptr getDialogProperties(const std::string &name)
Get dialog property tree's root node.
Definition new_gui.cxx:384
FGGlobals * globals
Definition globals.cxx:142
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
Definition Addon.cxx:53
MessageBoxResult modalMessageBox(const std::string &caption, const std::string &msg, const std::string &moreText)
MessageBoxResult fatalMessageBoxWithoutExit(const std::string &caption, const std::string &msg, const std::string &moreText, bool reportToSentry)
bool isHeadlessMode()
void fatalMessageBoxThenExit(const std::string &caption, const std::string &msg, const std::string &moreText, int exitStatus, bool reportToSentry)
void sentryReportFatalError(const std::string &, const std::string &)
void setHeadlessMode(bool headless)
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
Definition proptest.cpp:25