ArmarXGuiApp.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* ArmarX is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License version 2 as
6* published by the Free Software Foundation.
7*
8* ArmarX is distributed in the hope that it will be useful, but
9* WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*
16* @package ArmarX::Component::ArmarXGui
17* @author David Ruscheweyh (david.ruscheweyh at student.kit dot edu)
18* @author Kai Welke (welke at kit dot edu)
19* @copyright 2011 Humanoids Group, HIS, KITh
20* @license http://www.gnu.org/licenses/gpl-2.0.txt
21* GNU General Public License
22*/
23
24#include "ArmarXGuiApp.h"
25
26#include <iostream>
27#include <optional>
28
29#include <QHostInfo>
30#include <QListWidget>
31#include <QMessageBox>
32#include <QTextCodec>
33#include <QTime>
34
35#include <SimoxUtility/algorithm/string.h>
36#include <SimoxUtility/algorithm/string/string_tools.h>
37
41
42namespace armarx
43{
45
48 {
50 "LoadPlugins", "", "List of paths to GuiPlugin-Libs (semi-colon seperated)");
52 "GuiConfigFile", "", "Path to config file, that should be loaded on startup");
53 defineOptionalProperty<bool>("DisablePreloading",
54 false,
55 "Disables the preloading of widgets. Can be helpful if some "
56 "preloaded widget crashes the gui.");
57 }
58
59 ArmarXGuiApp::ArmarXGuiApp(int& argc, char** argv) :
60 qApplication(nullptr), argc(argc), argv(argv)
61 {
62 qApplication = new ArmarXQApplication(argc, argv);
63
64 // Set text encoding to UTF-8 (otherwise, umlauts display wrongly in, e.g., the log viewer)
65 QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
66 }
67
69 {
70 // std::cout << "FINISH" << std::endl;
71 }
72
73 void
75 Ice::PropertiesPtr properties)
76 {
77 this->registry = registry;
78 }
79
80 int
81 ArmarXGuiApp::run(int argc, char* argv[])
82 {
83 if (!ArmarXManager::CheckIceConnection(communicator(), false))
84 {
85 if (QMessageBox::question(nullptr,
86 "ArmarX is not running",
87 "ArmarX is not running - do you want me to start it now?",
88 QMessageBox::No,
89 QMessageBox::Yes) == QMessageBox::Yes)
90 {
91 int result = startArmarX();
92 if (result != 0)
93 {
94 return result;
95 }
96 }
97 else
98 {
99 return 1;
100 }
101 }
102 setName(makeName());
103 return armarx::Application::run(argc, argv);
104 }
105
106 int
108 {
109 // init SoDB and Qt, SoQt::init also creates an application object
110 SoDB::init();
111 SoQt::init(argc, argv, "ArmarXGuiApp*1123");
112
113 // enable Coin3D extension: transparent settings without color
114 (void)coin_setenv("COIN_SEPARATE_DIFFUSE_TRANSPARENCY_OVERRIDE", "1", TRUE);
115
116 {
117 const std::vector<std::string> packageNames = getArmarXPackageNames();
118 QString configToLoad;
119 if (getProperty<std::string>("GuiConfigFile").isSet())
120 {
121 configToLoad =
122 QString::fromStdString(getProperty<std::string>("GuiConfigFile").getValue());
123 }
124
125 // create top-level widget
126 mainWindow = new ArmarXMainWindow(registry,
127 packageNames,
128 configToLoad,
129 getProperty<bool>("DisablePreloading").getValue());
130 connect(mainWindow, SIGNAL(closeRequest()), this, SLOT(closeRequest_sent()));
131 }
132 {
133 // parse properties
134 std::string plugins = getProperty<std::string>("LoadPlugins").getValue();
135 std::vector<std::string> pluginList = Split(plugins, ",");
136 for (auto iter = pluginList.begin(); iter != pluginList.end(); ++iter)
137 {
138 if (!iter->empty())
139 {
140 ARMARX_VERBOSE << "Loading plugin: " << iter->c_str() << std::endl;
141 mainWindow->loadPlugin(iter->c_str());
142 }
143 }
144 }
145 std::cout << "Started ArmarXGui App" << std::endl;
146
147 armarxManagerTask = new RunningTask<ArmarXGuiApp>(
148 this, &ArmarXGuiApp::runArmarXManager, "ArmarXManagerWaitThread");
149 armarxManagerTask->start();
150
151 mainWindow->show();
152 mainWindow->appendFileToWindowTitle();
153
154 ARMARX_INFO << "Now showing main window";
155 int result = qApplication->exec();
156
157 // exit SoQt and Qt
158 interruptCallback(0); // signal to the application it should terminate the ice connection
159
160 armarXManager->waitForShutdown();
161
162 // Shutdown.
163 qApplication->quit();
164 delete mainWindow;
165
166 SoQt::done();
167 delete qApplication;
168 qApplication = 0;
169
170 return result;
171 }
172
173 void
174 ArmarXGuiApp::closeRequest_sent()
175 {
176 }
177
178 void
179 ArmarXGuiApp::runArmarXManager()
180 {
181 getArmarXManager()->waitForShutdown();
182
183 if (qApplication)
184 {
185 qApplication->quit();
186 }
187 }
188
189 int
190 ArmarXGuiApp::startArmarX()
191 {
192 CMakePackageFinder armarx_core("ArmarXCore");
193 CMakePackageFinder armarx_memoryx("MemoryX");
194
195 int res;
196 if (armarx_core.packageFound())
197 {
198 res = system(
199 std::string(armarx_core.getBinaryDir() + std::string("/armarx start")).c_str());
200 }
201 else
202 {
203 res = system("armarx start");
204 }
205 res = WEXITSTATUS(res);
206 if (res == EXIT_SUCCESS)
207 {
208 ARMARX_INFO_S << "Started ArmarX successfully!";
209 if (armarx_memoryx.packageFound())
210 {
211 if (armarx_core.packageFound())
212 {
213 res = system(std::string(armarx_core.getBinaryDir() +
214 std::string("/armarx memory start"))
215 .c_str());
216 }
217 else
218 {
219 res = system("armarx memory assureRunning");
220 }
221 res = WEXITSTATUS(res);
222 if (res == EXIT_FAILURE)
223 {
224 QMessageBox::warning(nullptr,
225 "ArmarX Error",
226 "Could not start MongoDB! See terminal output for more "
227 "information. The GUI will now started anyway.");
228 return 0;
229 }
230 }
231 }
232 else
233 {
234 QMessageBox::critical(
235 nullptr,
236 "ArmarX Error",
237 "Could not start ArmarX! See terminal output for more information.");
238 return 1;
239 }
240 return 0;
241 }
242
243 static QString
244 getUserName()
245 {
246 QString username = qgetenv("USER");
247 if (username.isEmpty())
248 {
249 username = qgetenv("USERNAME");
250 }
251 return username;
252 }
253
254 static QString
255 getUserNameAtHostName(const QString& delimiter, const QString& at)
256 {
257 const QString hostname = QHostInfo::localHostName();
258 QString user = getUserName();
259 if (user.isEmpty())
260 {
261 return hostname;
262 }
263 else
264 {
265 return user + delimiter + at + delimiter + hostname;
266 }
267 }
268
269 std::string
270 ArmarXGuiApp::makeName()
271 {
272 std::vector<std::string> items{"ArmarXGui"};
273 items.push_back(getUserNameAtHostName("-", "at").toStdString());
274 items.push_back(DateTime::Now().toDateTimeString());
275
276 std::string name = simox::alg::join(items, "_");
277
278 return name;
279 }
280
281 bool
282 ArmarXQApplication::notify(QObject* obj, QEvent* ev)
283 {
284 try
285 {
286 return QApplication::notify(obj, ev);
287 }
288 catch (std::exception& e)
289 {
290 ARMARX_ERROR_S << "Exception caught:\n" << armarx::GetHandledExceptionString();
291 emit exceptionCaught(QString::fromStdString(armarx::GetHandledExceptionString()));
293 }
294
295 return false;
296 }
297
298 void
299 ArmarXQApplication::showException(QString exceptionReason)
300 {
301 QStringList infos = exceptionReason.split("Backtrace:");
302 QListWidget* list = exceptionDialogHandler.listWidgetExceptions;
303 auto item = new QListWidgetItem("[" + QTime::currentTime().toString() + "] " +
304 infos.first().trimmed());
305 item->setToolTip(exceptionReason);
306 list->addItem(item);
307 list->scrollToBottom();
308
309 if (!exceptionDialogHandler.checkBoxDoNotShowAgain->isChecked())
310 {
311 exceptionDialog.show();
312 }
313 /*
314 QStringList infos = exceptionReason.split("Backtrace:");
315 QMessageBox box;
316 box.setIcon(QMessageBox::Warning);
317 box.setWindowTitle("An exception occured!");
318 box.setText("An exception was caught!\n" + infos.first());
319 if(infos.size() > 1)
320 box.setDetailedText(infos.last());
321 box.exec();
322 */
323 }
324
325 ArmarXQApplication::ArmarXQApplication(int& argc, char** argv) : QApplication(argc, argv)
326 {
327 const auto guiWindowBaseName = QString{"ArmarX"} + " @ " + QHostInfo::localHostName();
328 setApplicationName(guiWindowBaseName);
329
330 {
331 const char* envArmarxWorkspace = std::getenv("ARMARX_WORKSPACE_NAME");
332 if (envArmarxWorkspace == nullptr)
333 {
334 envArmarxWorkspace = std::getenv("ARMARX_WORKSPACE");
335 }
336
337 QString applicationDisplayName;
338 if (envArmarxWorkspace != nullptr)
339 {
340 applicationDisplayName += "[▽" + QString(envArmarxWorkspace) + "] ";
341 }
342 applicationDisplayName += getUserNameAtHostName(" ", "@");
343 setApplicationDisplayName(applicationDisplayName);
344 }
345
346 connect(this,
347 SIGNAL(exceptionCaught(QString)),
348 this,
349 SLOT(showException(QString)),
350 Qt::QueuedConnection);
352 QListWidget* list = exceptionDialogHandler.listWidgetExceptions;
353 connect(exceptionDialogHandler.pushButtonClearHistory,
354 SIGNAL(clicked()),
355 list,
356 SLOT(clear()),
357 Qt::QueuedConnection);
358 }
359
363
364} // namespace armarx
ApplicationPropertyDefinitions(std::string prefix)
int run(int argc, char *argv[]) override
Ice::Application replacement for the main function.
std::vector< std::string > getArmarXPackageNames()
getDefaultPackageNames returns the value of the ArmarX.DefaultPackages property It splits the string ...
ArmarXManagerPtr getArmarXManager()
void setName(const std::string &name)
Set name of the application.
void interruptCallback(int signal) override
Cleans up connections with IceStorm before terminating the app.
ArmarXGuiAppPropertyDefinitions(std::string prefix)
void setup(const ManagedIceObjectRegistryInterfacePtr &registry, Ice::PropertiesPtr properties) override
Configures the app, sets Qt up.
int run(int argc, char *argv[]) override
ArmarXGuiApp(int &argc=ArmarXGuiApp::globalargc, char **argv=NULL)
Constructs and initialized an ArmarXGuiApp.
int exec(const ArmarXManagerPtr &armarXManager) override
Runs the Qt Event Loop.
The ArmarXMainWindow class.
static bool CheckIceConnection(const Ice::CommunicatorPtr &communicator, bool printHint)
Ui_ExceptionDialog exceptionDialogHandler
ArmarXQApplication(int &argc, char **argv)
bool notify(QObject *obj, QEvent *ev) override
void exceptionCaught(QString exceptionReason)
void showException(QString exceptionReason)
static DateTime Now()
Definition DateTime.cpp:51
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
Property< PropertyType > getProperty(const std::string &name)
Property creation and retrieval.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR_S
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:216
#define ARMARX_INFO_S
Definition Logging.h:202
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
::IceInternal::Handle<::Ice::Properties > PropertiesPtr
This file is part of ArmarX.
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< ArmarXManager > ArmarXManagerPtr
IceUtil::Handle< ManagedIceObjectRegistryInterface > ManagedIceObjectRegistryInterfacePtr
Definition Application.h:83
std::string GetHandledExceptionString()
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
static void ClearExceptionBacktrace()
Definition trace.cpp:100