1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3     SPDX-FileCopyrightText: 2002-2021 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
4 */
5 
6 // app includes
7 #include "debug_utils.h"
8 #include "uml.h"
9 #include "version.h"
10 #include "umldoc.h"
11 #include "cmdlineexportallviewsevent.h"
12 #include "umlviewimageexportermodel.h"
13 #include "umbrellosettings.h"
14 
15 // kde includes
16 #if QT_VERSION > 0x050000
17 // prevent including of <kaboutdata.h>
18 #define KABOUTDATA_H
19 #include <k4aboutdata.h>
20 #define KAboutData K4AboutData
21 #include <KCrash>
22 #else
23 #include <kaboutdata.h>
24 #endif
25 
26 #include <kapplication.h>
27 #include <kcmdlineargs.h>
28 #include <kconfig.h>
29 #include <KLocalizedString>
30 #include <ktip.h>
31 #include <KUrl>
32 
33 // KF5 uses i18n
34 #define i18n ki18n
35 
36 #include <stdio.h>
37 
38 void getFiles(QStringList& files, const QString& path, QStringList& filters);
39 
40 /**
41  * Determines if the application GUI should be shown based on command line arguments.
42  * @todo Add options to use the documentation generators from command line.
43  *
44  * @param args The command line arguments given.
45  * @return True if the GUI should be shown, false otherwise.
46  */
showGUI(KCmdLineArgs * args)47 bool showGUI(KCmdLineArgs *args)
48 {
49     if (args->getOptionList("export").size() > 0 || args->isSet("export-formats")) {
50         return false;
51     }
52     return true;
53 }
54 
55 /**
56  * Initializes the document used by the application.
57  * If a file was specified in command line arguments, opens that file. Else, it
58  * opens the last opened file, or a new file if there isn't any "last file used"
59  * in the configuration.
60  *
61  * @param args The command line arguments given.
62  */
initDocument(KCmdLineArgs * args,Uml::ProgrammingLanguage::Enum progLang)63 void initDocument(KCmdLineArgs *args, Uml::ProgrammingLanguage::Enum progLang)
64 {
65     if (args->count()) {
66         UMLApp::app()->openDocumentFile(args->url(0));
67     } else {
68         bool last = UmbrelloSettings::loadlast();
69         QString file = UmbrelloSettings::lastFile();
70         if(last && !file.isEmpty()) {
71             UMLApp::app()->openDocumentFile(KUrl(file));
72         } else {
73             UMLApp::app()->newDocument();
74             if (progLang != Uml::ProgrammingLanguage::Reserved)
75                 UMLApp::app()->setActiveLanguage(progLang);
76         }
77     }
78 }
79 
80 /**
81  * Export all the views in the document using the command line args set by the user.
82  * Errors that occurred while exporting, if any, are shown using uError().
83  *
84  * @param args The command line arguments given.
85  * @param exportOpt A list containing all the "export" arguments given.
86  */
87 
exportAllViews(KCmdLineArgs * args,const QStringList & exportOpt)88 void exportAllViews(KCmdLineArgs *args, const QStringList &exportOpt)
89 {
90     QString extension(exportOpt.last());
91     uDebug() << "extension: " << extension;
92 
93     // export to the specified directory, or the directory where the file is saved
94     // if no directory was specified
95     QUrl directory;
96     QStringList directoryOpt = args->getOptionList("directory");
97     if (directoryOpt.size() > 0) {
98         directory = KCmdLineArgs::makeURL(directoryOpt.last().toLocal8Bit());
99     } else {
100         QFileInfo fi(UMLApp::app()->document()->url().toLocalFile());
101         directory = QUrl::fromLocalFile(fi.absolutePath());
102     }
103 
104     bool useFolders = args->isSet("use-folders");
105 
106     uDebug() << "directory: " << directory;
107 
108     // the event is posted so when the Qt loop begins it's processed. UMLApp process this event executing
109     // the method it provides for exporting the views. Once all the views were exported, a quit event
110     // is sent and the app finishes without user interaction
111     kapp->postEvent(UMLApp::app(), new CmdLineExportAllViewsEvent(extension, directory, useFolders));
112 }
113 
main(int argc,char * argv[])114 int main(int argc, char *argv[])
115 {
116     KAboutData aboutData("umbrello",
117                          0,
118                          i18n("Umbrello UML Modeller"),
119                          umbrelloVersion(),
120                          i18n("Umbrello – Visual development environment for software, "
121                               "based on the industry standard Unified Modelling Language (UML).<br/>"
122                               "See also <a href=\"http://www.omg.org/spec/\">http://www.omg.org/spec/</a>."),
123                          KAboutData::License_GPL,
124                          i18n("Copyright © 2001 Paul Hensgen,\nCopyright © 2002-2021 Umbrello UML Modeller Authors"),
125                          KLocalizedString(),
126                          "http://umbrello.kde.org/");
127     aboutData.addAuthor(i18n("Paul Hensgen"), i18n("Author of initial version."), "phensgen@users.sourceforge.net");
128     aboutData.addAuthor(i18n("Umbrello UML Modeller Authors"), KLocalizedString(), "umbrello-devel@kde.org");
129 
130     // authors with more than 200 commits: git shortlog -seu | sort -g
131     aboutData.addCredit(i18n("Oliver Kellogg"),
132                         i18n("Bug fixing, porting work, code cleanup, new features."),
133                         "okellogg@users.sourceforge.net");
134     aboutData.addCredit(i18n("Ralf Habacker"),
135                         i18n("Bug fixing, porting work, code cleanup, new features."),
136                         "ralf.habacker@freenet.de");
137     aboutData.addCredit(i18n("Andi Fischer"),
138                         i18n("Porting work, code cleanup, new features."),
139                         "andi.fischer@hispeed.ch");
140     aboutData.addCredit(i18n("Jonathan Riddell"),
141                         i18n("Current maintainer."),
142                         "jr@jriddell.org");
143     aboutData.addCredit(i18n("Brian Thomas"),
144                         i18n("A lot of work for C++ and Java code generation. Codeeditor."),
145                         "thomas@mail630.gsfc.nasa.gov");
146 
147     KCmdLineArgs::init(argc, argv, &aboutData);
148     KCmdLineOptions options;
149     options.add("+[File]", i18n("File to open"));
150     options.add("export <extension>", i18n("export diagrams to extension and exit"));
151     options.add("export-formats", i18n("list available export extensions"));
152     options.add("directory <url>", i18n("the local directory to save the exported diagrams in"), I18N_NOOP("the directory of the file"));
153     options.add("import-files", i18n("import files"));
154     options.add("languages", i18n("list supported languages"));
155     options.add("use-folders", i18n("keep the tree structure used to store the views in the document in the target directory"));
156     options.add("import-directory <dir>", i18n("import files from directory <dir>"));
157     for (int i = Uml::ProgrammingLanguage::ActionScript; i <= Uml::ProgrammingLanguage::Reserved; i++) {
158         Uml::ProgrammingLanguage::Enum pl = Uml::ProgrammingLanguage::fromInt(i);
159         QByteArray optionString = "set-language-" + Uml::ProgrammingLanguage::toString(pl).toLower().toLocal8Bit();
160         options.add(optionString, i18n("set active language"));
161     }
162     KCmdLineArgs::addCmdLineOptions(options); // Add our own options.
163     KApplication app;
164     KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
165 #if QT_VERSION > 0x050000
166     KCrash::initialize();
167     KLocalizedString::setApplicationDomain("umbrello");
168     Q_INIT_RESOURCE(ui);
169 #endif
170 
171     Q_INIT_RESOURCE(icons);
172     app.setLayoutDirection(UmbrelloSettings::rightToLeftUI() ? Qt::RightToLeft : Qt::LeftToRight);
173     QPointer<UMLApp> uml;
174     if (app.isSessionRestored()) {
175         kRestoreMainWindows< UMLApp >();
176     } else {
177         if (args->isSet("export-formats")) {
178             foreach(const QString& type, UMLViewImageExporterModel::supportedImageTypes())
179                 fprintf(stdout, "%s\n", qPrintable(type));
180             return 0;
181         } else if (args->isSet("languages")) {
182             for (int i = Uml::ProgrammingLanguage::ActionScript; i <= Uml::ProgrammingLanguage::Reserved; i++) {
183                 Uml::ProgrammingLanguage::Enum pl = Uml::ProgrammingLanguage::fromInt(i);
184                 fprintf(stdout, "%s\n", qPrintable(Uml::ProgrammingLanguage::toString(pl)));
185             }
186             return 0;
187         }
188 
189         uml = new UMLApp();
190         app.processEvents();
191 
192         if (showGUI(args)) {
193             uml->show();
194         }
195 
196         Uml::ProgrammingLanguage::Enum lang = Uml::ProgrammingLanguage::Reserved;
197         for(int i = Uml::ProgrammingLanguage::ActionScript; i < Uml::ProgrammingLanguage::Reserved; i++) {
198             Uml::ProgrammingLanguage::Enum pl = Uml::ProgrammingLanguage::fromInt(i);
199             QByteArray langString = "set-language-";
200             langString += Uml::ProgrammingLanguage::toString(pl).toLower().toLocal8Bit();
201             if (args->isSet(langString)) {
202                 lang = Uml::ProgrammingLanguage::fromInt(i);
203             }
204         }
205 
206         if (args->isSet("import-files") && args->count() > 0) {
207             QStringList importList;
208             for (int i = 0; i < args->count(); i++)
209                 importList.append(args->url(i).toLocalFile());
210             uml->newDocument();
211             if (lang != Uml::ProgrammingLanguage::Reserved)
212                 uml->setActiveLanguage(lang);
213             uml->importFiles(importList);
214         }
215         else if (args->isSet("import-directory")) {
216             uml->newDocument();
217             if (lang != Uml::ProgrammingLanguage::Reserved)
218                 uml->setActiveLanguage(lang);
219             QStringList filter = Uml::ProgrammingLanguage::toExtensions(uml->activeLanguage());
220             QString dir = args->getOption("import-directory");
221             QStringList listFile;
222             getFiles(listFile, dir, filter);
223             uml->importFiles(listFile, dir);
224         }
225         else {
226             initDocument(args, lang);
227         }
228 
229         // export option
230         QStringList exportOpt = args->getOptionList("export");
231         if (exportOpt.size() > 0) {
232              exportAllViews(args, exportOpt);
233         }
234     }
235     int result = app.exec();
236     delete uml;
237     return result;
238 }
239