diff --git a/App/AppOptions.cpp b/App/AppOptions.cpp index 85b8e00d7963812358fcb730cf2f5d7de7872df0..5ad2c0545d4a00ae6051c312db9d5287f182b328 100644 --- a/App/AppOptions.cpp +++ b/App/AppOptions.cpp @@ -14,7 +14,9 @@ #include "App/AppOptions.h" #include "GUI/Util/Path.h" +#include <QApplication> #include <QSize> +#include <QMessageBox> #include <QStringList> #include <boost/program_options/config.hpp> #include <boost/program_options/parsers.hpp> @@ -43,12 +45,22 @@ bool isValid(const QSize& win_size) return win_size.width() > 640 && win_size.height() > 480; } +void exitWithGuiMessage(const QString msg) +{ + int argc = 0; + QApplication a(argc, nullptr); + QMessageBox msgBox; + msgBox.setText(msg); + msgBox.exec(); + exit(-1); +} + } // namespace ApplicationOptions::ApplicationOptions(int argc, char** argv) - : m_options_is_consistent(false) { - m_options.add_options()("help,h", "print help message"); + m_options.add_options()("help,h", "print help message and exit"); + m_options.add_options()("version,v", "print version and exit"); m_options.add_options()("with-debug", "run application with debug printout"); m_options.add_options()(geometry, bpo::value<std::string>(), "Main window geometry, e.g. 1600x1000"); @@ -68,19 +80,13 @@ const bpo::variable_value& ApplicationOptions::operator[](const std::string& s) bool ApplicationOptions::find(std::string name) const { - return (m_variables_map.count(name)); -} - -bool ApplicationOptions::isConsistent() const -{ - return m_options_is_consistent; + return m_variables_map.count(name); } //! parse command line arguments void ApplicationOptions::parseCommandLine(int argc, char** argv) { - m_options_is_consistent = false; // parsing command line arguments try { // if positional option description is empty, no command line arguments @@ -96,11 +102,13 @@ void ApplicationOptions::parseCommandLine(int argc, char** argv) // 'notify' raises any errors encountered bpo::notify(m_variables_map); - m_options_is_consistent = true; } catch (std::exception& e) { - // we get here if there is unrecognized options - std::cout << "main() -> " << e.what() << std::endl; - std::cout << m_options << std::endl; + std::stringstream s; + s << "BornAgain was launched with invalid command line option.\n" + << "Parser error message: " << e.what() << ".\n" + << "Available options:\n" + << m_options << "\n"; + exitWithGuiMessage(QString::fromStdString(s.str())); } } @@ -117,30 +125,23 @@ boost::program_options::options_description& ApplicationOptions::getOptions() void ApplicationOptions::processOptions() { if (m_variables_map.count("help")) { - printHelpMessage(); - m_options_is_consistent = false; + std::cout << "BornAgain Graphical User Interface" << std::endl; + std::cout << m_options << std::endl; + exit(0); } else if (m_variables_map.count("version")) { std::cout << "BornAgain-" << GUI::Util::Path::getBornAgainVersionString().toStdString() << std::endl; - m_options_is_consistent = false; + exit(0); } else if (m_variables_map.count(geometry)) { - if (!isValid(mainWindowSize())) { - std::cout << "Wrong window size, try --geometry=1600x900\n"; - m_options_is_consistent = false; - } + if (!isValid(mainWindowSize())) + exitWithGuiMessage("Wrong window size, try --geometry=1600x900\n"); } } -void ApplicationOptions::printHelpMessage() const -{ - std::cout << "BornAgain Graphical User Interface" << std::endl; - std::cout << m_options << std::endl; -} - QSize ApplicationOptions::mainWindowSize() const { QString size_str = QString::fromStdString(m_variables_map[geometry].as<std::string>()); diff --git a/App/AppOptions.h b/App/AppOptions.h index 7c4d7e050bf2bbdd9466c739e2ce0dac3dc3f810..00c7e41e256458085727d10ee9d99db840eba77a 100644 --- a/App/AppOptions.h +++ b/App/AppOptions.h @@ -35,12 +35,14 @@ public: //! access to variable with given name defined in variables container const bpo::variable_value& operator[](const std::string& s) const; + QSize mainWindowSize() const; + + bool disableHighDPISupport() const; + //! Returns true if option with given name has been set bool find(std::string name) const; - //! Returns true if options are consistent (no conflicts, no --help request) - bool isConsistent() const; - +private: //! Parses command line arguments void parseCommandLine(int argc, char** argv); @@ -52,13 +54,6 @@ public: void processOptions(); - void printHelpMessage() const; - - QSize mainWindowSize() const; - - bool disableHighDPISupport() const; - -private: //! true if options are consistent (no conflicts, no --help request) bool m_options_is_consistent; //! options description, to be filled with add() from different program modules diff --git a/App/main.cpp b/App/main.cpp index 8a1e52ca59fa028b2e391b98fd7807de052538d6..e695f20aa7f5d9bdf9b8b646c8b75f9c6a4a27aa 100644 --- a/App/main.cpp +++ b/App/main.cpp @@ -26,15 +26,12 @@ #include <QLocale> #include <QMessageBox> #include <QMetaType> -#include <boost/exception/diagnostic_information.hpp> void messageHandler(QtMsgType, const QMessageLogContext&, const QString&) {} int main(int argc, char* argv[]) { ApplicationOptions options(argc, argv); - if (!options.isConsistent()) - return 0; QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); qRegisterMetaType<QVector<double>>("QVector<double>"); @@ -52,47 +49,30 @@ int main(int argc, char* argv[]) ApplicationSettings applicationSettings; SessionData GSession; - int result; -#if !defined(BUILD_DEBUG) - try { -#endif - qInstallMessageHandler(MessageHandler); + qInstallMessageHandler(MessageHandler); - register1DDataLoaders(); + register1DDataLoaders(); - auto style = applicationSettings.styleToUse(); - applicationSettings.loadStyle(style); + auto style = applicationSettings.styleToUse(); + applicationSettings.loadStyle(style); - QString dir = GUI::Util::Path::appDataFolder(); - if (!QDir().exists(dir)) - QDir().mkpath(dir); + QString dir = GUI::Util::Path::appDataFolder(); + if (!QDir().exists(dir)) + QDir().mkpath(dir); - GSession.instrumentLibrary.load(); + GSession.instrumentLibrary.load(); - MainWindow win; - GUI::Global::mainWindow = &win; - if (options.find("geometry")) - win.resize(options.mainWindowSize()); + MainWindow win; + GUI::Global::mainWindow = &win; + if (options.find("geometry")) + win.resize(options.mainWindowSize()); - win.show(); + win.show(); - result = QApplication::exec(); + int result = QApplication::exec(); - GSession.instrumentLibrary.saveIfModified(); -#if !defined(BUILD_DEBUG) - } catch (...) { - QMessageBox box; - box.setWindowTitle("Fatal error"); - box.setIcon(QMessageBox::Critical); - box.setText("BornAgain encountered a fatal error and can't continue execution.\n\n" - "Diagnostics of error:\n" - + QString::fromStdString(boost::current_exception_diagnostic_information())); - box.addButton("Acknowledge", QMessageBox::AcceptRole); - box.exec(); - result = EXIT_FAILURE; - } -#endif + GSession.instrumentLibrary.saveIfModified(); return result; } diff --git a/Base/Util/FileSystemUtils.cpp b/Base/Util/FileSystemUtils.cpp index d09af3c86026d471e279ab502c0965e29c5ab7b6..8805cfbb2f3452ac0dbf67bf09deb68da24c9fee 100644 --- a/Base/Util/FileSystemUtils.cpp +++ b/Base/Util/FileSystemUtils.cpp @@ -13,6 +13,7 @@ // ************************************************************************************************ #include "Base/Util/FileSystemUtils.h" +#include "Base/Util/StringUtils.h" #include "Base/Util/Assert.h" #include <codecvt> #include <filesystem> @@ -27,6 +28,11 @@ std::string BaseUtils::Filesystem::extension(const std::string& path) return fs::path(path).extension().string(); } +bool BaseUtils::Filesystem::hasExtension(const std::string& path, const std::string& ref_extension) +{ + return BaseUtils::String::to_lower(extension(path)) == ref_extension; +} + std::string BaseUtils::Filesystem::extensions(const std::string& path) { const auto name = BaseUtils::Filesystem::filename(path); diff --git a/Base/Util/FileSystemUtils.h b/Base/Util/FileSystemUtils.h index 596a59eff861bbcf4baaf86f468c01d24f714813..cd0ab62c96e8984ca6ee6476b49991efec66c0ad 100644 --- a/Base/Util/FileSystemUtils.h +++ b/Base/Util/FileSystemUtils.h @@ -31,6 +31,9 @@ namespace BaseUtils::Filesystem { //! "/home/user/filename.int" -> ".int", "/home/user/filename.int.gz" -> ".gz" std::string extension(const std::string& path); +//! Returns true if extension of path, converted to lower case, matches given reference extension +bool hasExtension(const std::string& path, const std::string& ref_extension); + //! Returns extension(s) of given filename. //! "/home/user/filename.int" -> ".int", "/home/user/filename.int.gz" -> ".int.gz" std::string extensions(const std::string& path); diff --git a/Device/InputOutput/DataFormatUtils.cpp b/Device/InputOutput/DataFormatUtils.cpp index c941385ac8b68c5d31059e893b087328488ceb63..0e5172468171e73501d21cfd2723df620c402338 100644 --- a/Device/InputOutput/DataFormatUtils.cpp +++ b/Device/InputOutput/DataFormatUtils.cpp @@ -42,6 +42,16 @@ std::istringstream getAxisStringRepresentation(std::istream& input_stream) return std::istringstream(line); } +std::string uncompressedFilename(const std::string& name) +{ + if (DataUtils::Format::isGZipped(name)) + return name.substr(0, name.size() - GzipExtension.size()); + if (DataUtils::Format::isBZipped(name)) + return name.substr(0, name.size() - BzipExtension.size()); + return name; +} + + //! Creates one of FixedBinAxis from string representation //! FixedBinAxis("axis0", 10, -1, 1) //! ConstKBinAxis("axis0", 10, -1, 1) @@ -114,41 +124,28 @@ bool DataUtils::Format::isCompressed(const std::string& name) bool DataUtils::Format::isGZipped(const std::string& name) { - return BaseUtils::Filesystem::extension(name) == GzipExtension; + return BaseUtils::Filesystem::hasExtension(name, GzipExtension); } bool DataUtils::Format::isBZipped(const std::string& name) { - return BaseUtils::Filesystem::extension(name) == BzipExtension; -} - -//! Returns file main extension (without .gz). - -std::string DataUtils::Format::GetFileMainExtension(const std::string& name) -{ - std::string stripped_name(name); - if (isGZipped(name)) - stripped_name = name.substr(0, name.size() - GzipExtension.size()); - else if (isBZipped(name)) - stripped_name = name.substr(0, name.size() - BzipExtension.size()); - - return BaseUtils::Filesystem::extension(stripped_name); + return BaseUtils::Filesystem::hasExtension(name, BzipExtension); } bool DataUtils::Format::isIntFile(const std::string& file_name) { - return GetFileMainExtension(file_name) == IntExtension; + return BaseUtils::Filesystem::hasExtension(uncompressedFilename(file_name), IntExtension); } bool DataUtils::Format::isNicosFile(const std::string& file_name) { - return GetFileMainExtension(file_name) == NicosExtension; + return BaseUtils::Filesystem::hasExtension(uncompressedFilename(file_name), NicosExtension); } bool DataUtils::Format::isTiffFile(const std::string& file_name) { - return (GetFileMainExtension(file_name) == TiffExtension - || GetFileMainExtension(file_name) == TiffExtension2); + return BaseUtils::Filesystem::hasExtension(uncompressedFilename(file_name), TiffExtension) + || BaseUtils::Filesystem::hasExtension(uncompressedFilename(file_name), TiffExtension2); } //! Creates axis of certain type from input stream diff --git a/Device/InputOutput/DataFormatUtils.h b/Device/InputOutput/DataFormatUtils.h index c53d4e52ed89d3c5ad51c6ae65b6fb2c998005b7..524589a743b3a666b789fc45d5c0be57f960c83d 100644 --- a/Device/InputOutput/DataFormatUtils.h +++ b/Device/InputOutput/DataFormatUtils.h @@ -41,9 +41,6 @@ bool isGZipped(const std::string& name); //! Returns true if name contains *.bz2 extension bool isBZipped(const std::string& name); -//! Returns file extension after stripping '.gz' if any -std::string GetFileMainExtension(const std::string& name); - //! Returns true if file name corresponds to BornAgain native format (compressed or not) bool isIntFile(const std::string& file_name); diff --git a/Tests/Unit/Base/FileSystemUtilsTest.cpp b/Tests/Unit/Base/FileSystemUtilsTest.cpp index 986ee349d6856e581234f65766f3557093dbec8a..50c252f06c477f3002a6b37ed8bad9b9b61a7e8a 100644 --- a/Tests/Unit/Base/FileSystemUtilsTest.cpp +++ b/Tests/Unit/Base/FileSystemUtilsTest.cpp @@ -54,6 +54,20 @@ TEST_F(FileSystemUtilsTest, extension) EXPECT_EQ(BaseUtils::Filesystem::extension("/home/james/file.txt.GZ"), ".GZ"); } +TEST_F(FileSystemUtilsTest, hasExtension) +{ + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("", "")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/", "")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/.", "")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/..", "")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/.hidden", "")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/.hidden.txt", ".txt")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/file.txt", ".txt")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/file.TXT", ".txt")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/file.txt.gz", ".gz")); + EXPECT_TRUE(BaseUtils::Filesystem::hasExtension("/home/james/file.TXT.GZ", ".gz")); +} + TEST_F(FileSystemUtilsTest, extensions) { EXPECT_EQ(BaseUtils::Filesystem::extensions(""), ""); @@ -170,8 +184,8 @@ TEST_F(FileSystemUtilsTest, filesInDirectoryIsFileExists) std::ofstream("file2.txt"); std::ofstream("file3.txt"); - EXPECT_EQ(BaseUtils::Filesystem::filesInDirectory(testCasePath()).size(), 3); // abs - EXPECT_EQ(BaseUtils::Filesystem::filesInDirectory(".").size(), 3); // rel + EXPECT_EQ(BaseUtils::Filesystem::filesInDirectory(testCasePath()).size(), 3uL); // abs + EXPECT_EQ(BaseUtils::Filesystem::filesInDirectory(".").size(), 3uL); // rel const auto files = BaseUtils::Filesystem::filesInDirectory("."); EXPECT_TRUE(std::find(files.begin(), files.end(), "file1.txt") != files.end()); EXPECT_TRUE(std::find(files.begin(), files.end(), "file2.txt") != files.end());