9 #include <QApplication>
10 #include <QSplashScreen>
12 #include <QCommandLineParser>
13 #include <QDesktopWidget>
14 #include <QFontDatabase>
16 #include <QPushButton>
17 #include <QNetworkAccessManager>
18 #include <QNetworkReply>
19 #include <QJsonDocument>
23 #include <QDesktopServices>
37 #include "ui_changelog_dialog.h"
39 #ifdef COMPILED_WITH_CATKIN
42 #ifdef COMPILED_WITH_AMENT
43 #include <rclcpp/rclcpp.hpp>
47 QString(
"%1.%2.%3").arg(PJ_MAJOR_VERSION).arg(PJ_MINOR_VERSION).arg(PJ_PATCH_VERSION);
51 QStringList online_version = str.split(
'.');
52 if (online_version.size() != 3)
56 int major = online_version[0].toInt();
57 int minor = online_version[1].toInt();
58 int patch = online_version[2].toInt();
59 return major * 10000 + minor * 100 + patch;
64 QDialog* dialog =
new QDialog();
65 auto ui =
new Ui::ChangelogDialog();
68 QObject::connect(ui->buttonChangelog, &QPushButton::clicked, dialog, [](
bool) {
69 QDesktopServices::openUrl(QUrl(
"https://bit.ly/plotjuggler-update"));
71 settings.setValue(
"Changelog/first", false);
74 QObject::connect(ui->checkBox, &QCheckBox::toggled, dialog, [](
bool toggle) {
76 settings.setValue(
"Changelog/dont", toggle);
86 qDebug() <<
"reply error";
90 QString answer = reply->readAll();
91 QJsonDocument document = QJsonDocument::fromJson(answer.toUtf8());
92 QJsonObject
data = document.object();
93 QString url =
data[
"html_url"].toString();
94 QString name =
data[
"name"].toString();
95 QString tag_name =
data[
"tag_name"].toString();
99 settings.value(
"NewRelease/dontShowThisVersion",
VERSION_STRING).toString();
103 if (online_number > current_number && online_number > dontshow_number)
113 srand(
time(
nullptr));
116 const int last_image_num = 94;
117 int n = rand() % (last_image_num + 2);
118 if (n > last_image_num)
124 std::set<int> previous_set;
125 std::list<int> previous_nums;
127 QStringList previous_list = settings.value(
"previousFunnyMemesList").toStringList();
128 for (
auto str : previous_list)
130 int num = str.toInt();
131 previous_set.insert(num);
132 previous_nums.push_back(num);
136 while (previous_set.count(n) != 0)
141 while (previous_nums.size() >= 10)
143 previous_nums.pop_front();
145 previous_nums.push_back(n);
147 QStringList new_list;
148 for (
int num : previous_nums)
150 new_list.push_back(QString::number(num));
153 settings.setValue(
"previousFunnyMemesList", new_list);
154 auto filename = QString(
"://resources/memes/meme_%1.jpg").arg(n, 2, 10, QChar(
'0'));
155 return QPixmap(filename);
160 #ifdef PJ_DEFAULT_ARGS
163 std::vector<std::string> new_args;
164 new_args.push_back(
args.front());
171 for (
auto cmdline_arg : default_cmdline_args)
175 cmdline_arg = cmdline_arg.replace(
"_0x20_",
" ", Qt::CaseSensitive);
176 cmdline_arg = cmdline_arg.replace(
"_0x3b_",
";", Qt::CaseSensitive);
177 new_args.push_back(strdup(cmdline_arg.toLocal8Bit().data()));
182 for (
size_t i = 1; i <
args.size(); ++i)
184 new_args.push_back(
args[i]);
194 int main(
int argc,
char* argv[])
196 std::vector<std::string>
args;
198 #if !defined(COMPILED_WITH_CATKIN) && !defined(COMPILED_WITH_AMENT)
199 for (
int i = 0; i < argc; i++)
201 args.push_back(argv[i]);
203 #elif defined(COMPILED_WITH_CATKIN)
205 #elif defined(COMPILED_WITH_AMENT)
206 args = rclcpp::remove_ros_arguments(argc, argv);
211 int new_argc =
args.size();
212 std::vector<char*> new_argv;
213 for (
int i = 0; i < new_argc; i++)
218 QApplication app(new_argc, new_argv.data());
222 QCoreApplication::setOrganizationName(
"PlotJuggler");
223 QCoreApplication::setApplicationName(
"PlotJuggler-3");
224 QSettings::setDefaultFormat(QSettings::IniFormat);
228 if (!settings.isWritable())
230 qDebug() <<
"ERROR: the file [" << settings.fileName()
231 <<
"] is not writable. This may happen when you run PlotJuggler with sudo. "
232 "Change the permissions of the file (\"sudo chmod 666 <file_name>\"on "
239 TransformFactory::registerTransform<FirstDerivative>();
240 TransformFactory::registerTransform<ScaleTransform>();
241 TransformFactory::registerTransform<MovingAverageFilter>();
242 TransformFactory::registerTransform<MovingRMS>();
243 TransformFactory::registerTransform<OutlierRemovalFilter>();
244 TransformFactory::registerTransform<IntegralTransform>();
245 TransformFactory::registerTransform<AbsoluteTransform>();
246 TransformFactory::registerTransform<MovingVarianceFilter>();
247 TransformFactory::registerTransform<SamplesCountFilter>();
250 QCommandLineParser
parser;
251 parser.setApplicationDescription(
"PlotJuggler: the time series visualization"
252 " tool that you deserve ");
253 parser.addVersionOption();
256 QCommandLineOption nosplash_option(QStringList() <<
"n"
258 "Don't display the splashscreen");
259 parser.addOption(nosplash_option);
261 QCommandLineOption test_option(QStringList() <<
"t"
263 "Generate test curves at startup");
264 parser.addOption(test_option);
266 QCommandLineOption loadfile_option(QStringList() <<
"d"
268 "Load a file containing data",
"file_path");
269 parser.addOption(loadfile_option);
271 QCommandLineOption layout_option(QStringList() <<
"l"
273 "Load a file containing the layout configuration",
275 parser.addOption(layout_option);
277 QCommandLineOption publish_option(QStringList() <<
"p"
279 "Automatically start publisher when loading the "
281 parser.addOption(publish_option);
283 QCommandLineOption folder_option(QStringList() <<
"plugin_folders",
284 "Add semicolon-separated list of folders where you "
286 "for additional plugins.",
288 parser.addOption(folder_option);
290 QCommandLineOption buffersize_option(QStringList() <<
"buffer_size",
291 QCoreApplication::translate(
"main",
"Change the "
299 QCoreApplication::translate(
"main",
"seconds"));
301 parser.addOption(buffersize_option);
303 QCommandLineOption nogl_option(QStringList() <<
"disable_opengl",
"Disable OpenGL "
312 parser.addOption(nogl_option);
314 QCommandLineOption enabled_plugins_option(QStringList() <<
"enabled_plugins",
315 "Limit the loaded plugins to ones in the "
316 "semicolon-separated list",
318 parser.addOption(enabled_plugins_option);
320 QCommandLineOption disabled_plugins_option(QStringList() <<
"disabled_plugins",
321 "Do not load any of the plugins in the "
322 "semicolon separated list",
324 parser.addOption(disabled_plugins_option);
326 QCommandLineOption skin_path_option(QStringList() <<
"skin_path",
327 "New \"skin\". Refer to the sample in "
328 "[plotjuggler_app/resources/skin]",
330 parser.addOption(skin_path_option);
332 QCommandLineOption start_streamer(QStringList() <<
"start_streamer",
333 "Automatically start a Streaming Plugin with the "
335 "file_name (no extension)");
336 parser.addOption(start_streamer);
338 QCommandLineOption window_title(QStringList() <<
"window_title",
"Set the window title",
340 parser.addOption(window_title);
344 if (
parser.isSet(publish_option) && !
parser.isSet(layout_option))
346 std::cerr <<
"Option [ -p / --publish ] is invalid unless [ -l / --layout ] is used "
352 if (
parser.isSet(enabled_plugins_option) &&
parser.isSet(disabled_plugins_option))
354 std::cerr <<
"Option [ --enabled_plugins ] and [ --disabled_plugins ] can't be used "
360 if (
parser.isSet(nogl_option))
362 settings.setValue(
"Preferences::use_opengl",
false);
365 if (
parser.isSet(skin_path_option))
367 QDir path(
parser.value(skin_path_option));
370 qDebug() <<
"Skin path [" <<
parser.value(skin_path_option) <<
"] not found";
375 QIcon app_icon(
"://resources/plotjuggler.svg");
376 QApplication::setWindowIcon(app_icon);
378 QNetworkAccessManager manager_new_release;
379 QObject::connect(&manager_new_release, &QNetworkAccessManager::finished,
382 QNetworkRequest request_new_release;
383 request_new_release.setUrl(QUrl(
"https://api.github.com/repos/facontidavide/"
384 "PlotJuggler/releases/latest"));
385 manager_new_release.get(request_new_release);
402 bool first_changelog = settings.value(
"Changelog/first",
true).toBool();
403 bool dont_changelog = settings.value(
"Changelog/dont",
false).toBool();
405 if (first_changelog && !dont_changelog)
409 else if (!
parser.isSet(nosplash_option) &&
410 !(
parser.isSet(loadfile_option) ||
parser.isSet(layout_option)))
415 if (
parser.isSet(skin_path_option))
417 QDir path(
parser.value(skin_path_option));
418 QFile splash = path.filePath(
"pj_splashscreen.png");
421 main_pixmap = QPixmap(splash.fileName());
425 if (main_pixmap.isNull())
430 QSplashScreen splash(main_pixmap, Qt::WindowStaysOnTopHint);
431 QDesktopWidget* desktop = QApplication::desktop();
432 const int scrn = desktop->screenNumber();
433 const QPoint currentDesktopsCenter = desktop->availableGeometry(scrn).center();
434 splash.move(currentDesktopsCenter - splash.rect().center());
439 auto deadline = QDateTime::currentDateTime().addMSecs(500);
440 while (QDateTime::currentDateTime() < deadline)
447 deadline = QDateTime::currentDateTime().addMSecs(3000);
448 while (QDateTime::currentDateTime() < deadline && !splash.isHidden())
461 if (
parser.isSet(start_streamer))
466 QNetworkAccessManager manager_message;
467 QObject::connect(&manager_message, &QNetworkAccessManager::finished,
468 [window](QNetworkReply* reply) {
473 QString answer = reply->readAll();
474 QJsonDocument document = QJsonDocument::fromJson(answer.toUtf8());
475 QJsonObject
data = document.object();
476 QString message =
data[
"message"].toString();
480 QNetworkRequest request_message;
481 request_message.setUrl(QUrl(
"https://fastapi-example-7kz3.onrender.com"));
482 manager_message.get(request_message);