summaryrefslogtreecommitdiffstats
blob: 3e20e2322b40c354e9c673349daa828964b4188b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * Copyright (c) 2010-2017 Isode Limited.
 * All rights reserved.
 * See the COPYING file for more information.
 */

#include <cstdlib>
#include <iostream>
#include <locale>
#include <memory>
#include <sstream>

#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/version.hpp>

#include <QApplication>
#include <QLocale>
#include <QStringList>
#include <QTextCodec>
#include <QTranslator>

#include <Swiften/Base/Path.h>

#include <Swift/Controllers/ApplicationInfo.h>
#include <Swift/Controllers/BuildVersion.h>
#include <Swift/Controllers/Translator.h>

#include <SwifTools/Application/PlatformApplicationPathProvider.h>
#include <SwifTools/CrashReporter.h>

#include <Swift/QtUI/QtSwift.h>
#include <Swift/QtUI/QtSwiftUtil.h>
#include <Swift/QtUI/QtTranslator.h>

int main(int argc, char* argv[]) {
    Swift::PlatformApplicationPathProvider applicationPathProvider(SWIFT_APPLICATION_NAME);

    // Set crash report prefix to include date and version.
    std::stringstream prefix;

    // This date_facet will be cleaned up by the stringstream.
    auto outputFacet = new boost::gregorian::date_facet();
    outputFacet->format("%Y-%m-%d");
    prefix.imbue(std::locale(std::locale::classic(), outputFacet));

    prefix << buildVersion << "_" << boost::gregorian::date(boost::gregorian::day_clock::local_day()) << "_";

    Swift::CrashReporter crashReporter(applicationPathProvider.getDataDir() / "crashes", prefix.str());

#if QT_VERSION < 0x050000
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif

    // Parse program options
    boost::program_options::options_description desc = Swift::QtSwift::getOptionsDescription();
    boost::program_options::variables_map vm;
    try {
        boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
    } catch (const boost::program_options::unknown_option& option) {
#if BOOST_VERSION >= 104200
        std::cout << "Ignoring unknown option " << option.get_option_name() << " but continuing." <<  std::endl;
#else
        std::cout << "Error: " << option.what() << " (continuing)" <<  std::endl;
#endif
    }
    boost::program_options::notify(vm);
    if (vm.count("help") > 0) {
        std::cout << SWIFT_APPLICATION_NAME << " is an instant messaging client for the XMPP network." << std::endl;
        std::cout << std::endl;
        std::cout << "Usage: " << argv[0] << " [OPTIONS]..." << std::endl;
        std::cout << std::endl;
        std::cout << desc << std::endl;
        return 1;
    }
    if (vm.count("version") > 0) {
        std::cout << SWIFT_APPLICATION_NAME << " " << buildVersion << std::endl;
        return 0;
    }

    // Translation
#if QT_VERSION < 0x050000
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
#endif
    boost::filesystem::path someTranslationPath = applicationPathProvider.getResourcePath("/translations/swift_en.qm");

    QTranslator qtTranslator;
    if (!someTranslationPath.empty()) {
#if QT_VERSION >= 0x040800
        std::string language;
        if (vm.count("language") > 0) {
            try {
                language = vm["language"].as<std::string>();
            } catch (const boost::bad_any_cast&) {
            }
        }
        if (!language.empty()) {
            qtTranslator.load(QString(SWIFT_APPLICATION_NAME).toLower() + "_" + P2QSTRING(language), P2QSTRING(Swift::pathToString(someTranslationPath.parent_path())));
        }
        else {
            qtTranslator.load(QLocale::system(), QString(SWIFT_APPLICATION_NAME).toLower(), "_", P2QSTRING(Swift::pathToString(someTranslationPath.parent_path())));
        }
#else
        //std::cout << "Loading " << std::string(QLocale::system().name().toUtf8()) << std::endl;
        qtTranslator.load(QString(SWIFT_APPLICATION_NAME).toLower() + "_" + QLocale::system().name(), P2QSTRING(Swift::pathToString(someTranslationPath)));
#endif
    }

    QApplication app(argc, argv);

    app.installTranslator(&qtTranslator);
    QtTranslator swiftTranslator;
    Swift::Translator::setInstance(&swiftTranslator);

#if QT_VERSION < 0x050501
    /*  According to Qt documenation, Qt is suppsoed to set the applications layout
     *  direction based on the translatable QT_LAYOUT_DIRECTION string. There is a
     *  bug in Qt prior version 5.5.1, i.e. QTBUG-43447, thus we set the layout
     *  direction manually based on the tranlsated QT_LAYOUT_DIRECTION string.
     */
    app.setLayoutDirection(QGuiApplication::tr("QT_LAYOUT_DIRECTION") == QLatin1String("RTL") ? Qt::RightToLeft : Qt::LeftToRight);
#endif

    Swift::QtSwift swift(vm);
    int result = app.exec();

    Swift::Translator::setInstance(nullptr);

    return result;
}