1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2004-11-22
7  * Description : showFoto is a stand alone version of image
8  *               editor with no support of digiKam database.
9  *
10  * Copyright (C) 2004-2005 by Renchi Raju <renchi dot raju at gmail dot com>
11  * Copyright (C) 2004-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
12  *
13  * This program is free software; you can redistribute it
14  * and/or modify it under the terms of the GNU General
15  * Public License as published by the Free Software Foundation;
16  * either version 2, or (at your option)
17  * any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * ============================================================ */
25 
26 #include "digikam_config.h"
27 
28 // Qt includes
29 
30 #include <QDir>
31 #include <QFile>
32 #include <QSettings>
33 #include <QTranslator>
34 #include <QMessageBox>
35 #include <QApplication>
36 #include <QStandardPaths>
37 #include <QCommandLineParser>
38 #include <QCommandLineOption>
39 
40 // KDE includes
41 
42 #include <klocalizedstring.h>
43 #include <ksharedconfig.h>
44 #include <kconfiggroup.h>
45 #include <kaboutdata.h>
46 
47 // ImageMagick includes
48 
49 #if defined(Q_CC_CLANG)
50 #   pragma clang diagnostic push
51 #   pragma clang diagnostic ignored "-Wkeyword-macro"
52 #endif
53 
54 #ifdef HAVE_IMAGE_MAGICK
55 #   include <Magick++.h>
56 using namespace Magick;
57 #endif
58 
59 #if defined(Q_CC_CLANG)
60 #   pragma clang diagnostic pop
61 #endif
62 
63 // Local includes
64 
65 #include "digikam_debug.h"
66 #include "digikam_globals.h"
67 #include "digikam_version.h"
68 #include "filesdownloader.h"
69 #include "systemsettings.h"
70 #include "metaengine.h"
71 #include "daboutdata.h"
72 #include "showfoto.h"
73 
74 #ifdef Q_OS_WIN
75 #   include <windows.h>
76 #   include <shellapi.h>
77 #   include <objbase.h>
78 #endif
79 
80 using namespace Digikam;
81 
main(int argc,char * argv[])82 int main(int argc, char* argv[])
83 {
84     SystemSettings system(QLatin1String("showfoto"));
85     system.readSettings();
86 
87     QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps,
88                                    system.useHighDpiPixmaps);
89 
90     if (system.useHighDpiScaling)
91     {
92         QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
93     }
94     else
95     {
96         QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
97     }
98 
99 #ifdef HAVE_QWEBENGINE
100 
101     QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
102 
103 #endif
104 
105     QApplication app(argc, argv);
106 
107     digikamSetDebugFilterRules();
108 
109     tryInitDrMingw();
110 
111 #ifdef HAVE_IMAGE_MAGICK
112 
113     InitializeMagick(nullptr);
114 
115 #endif
116 
117     // if we have some local breeze icon resource, prefer it
118 
119     DXmlGuiWindow::setupIconTheme();
120 
121     KLocalizedString::setApplicationDomain("digikam");
122 
123     KAboutData aboutData(QLatin1String("showfoto"),     // component name
124                          i18nc("@title", "Showfoto"),   // display name
125                          digiKamVersion());             // NOTE: showFoto version = digiKam version
126 
127     aboutData.setShortDescription(QString::fromUtf8("%1 - %2").arg(DAboutData::digiKamSlogan()).arg(DAboutData::digiKamFamily()));
128     aboutData.setLicense(KAboutLicense::GPL);
129     aboutData.setCopyrightStatement(DAboutData::copyright());
130     aboutData.setOtherText(additionalInformation());
131     aboutData.setHomepage(DAboutData::webProjectUrl().url());
132     aboutData.setProductName(QByteArray("digikam/showfoto"));   // For bugzilla
133     aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"),
134                             i18nc("EMAIL OF TRANSLATORS", "Your emails"));
135 
136     DAboutData::authorsRegistration(aboutData);
137 
138     QCommandLineParser parser;
139     KAboutData::setApplicationData(aboutData);
140     aboutData.setupCommandLine(&parser);
141     parser.addPositionalArgument(QLatin1String("files"),
142                                  i18nc("command line option", "File(s) or folder(s) to open"),
143                                  QLatin1String("[file(s) or folder(s)]"));
144     parser.process(app);
145     aboutData.processCommandLine(&parser);
146 
147     KSharedConfig::Ptr config = KSharedConfig::openConfig();
148     KConfigGroup group        = config->group(QLatin1String("ImageViewer Settings"));
149     QString iconTheme         = group.readEntry(QLatin1String("Icon Theme"), QString());
150     QString colorTheme        = group.readEntry(QLatin1String("Theme"), QString::fromLatin1("Standard"));
151 
152 #if defined Q_OS_WIN || defined Q_OS_MACOS
153 
154     bool loadTranslation = true;
155 
156 #else
157 
158     bool loadTranslation = isRunningInAppImageBundle();
159 
160 #endif
161 
162     QString transPath = QStandardPaths::locate(QStandardPaths::DataLocation,
163                                                QLatin1String("translations"),
164                                                QStandardPaths::LocateDirectory);
165 
166     if (loadTranslation && !transPath.isEmpty())
167     {
168         QString klanguagePath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) +
169                                 QLatin1Char('/') + QLatin1String("klanguageoverridesrc");
170 
171         qCDebug(DIGIKAM_GENERAL_LOG) << "Qt translations path:" << transPath;
172 
173         QLocale locale;
174 
175         if (!klanguagePath.isEmpty())
176         {
177             QSettings settings(klanguagePath, QSettings::IniFormat);
178             settings.beginGroup(QLatin1String("Language"));
179             QString language = settings.value(qApp->applicationName(), QString()).toString();
180             settings.endGroup();
181 
182             if (!language.isEmpty())
183             {
184                 locale = QLocale(language.split(QLatin1Char(':')).first());
185             }
186         }
187 
188         QStringList qtCatalogs;
189         qtCatalogs << QLatin1String("qt");
190         qtCatalogs << QLatin1String("qtbase");
191         qtCatalogs << QLatin1String("qt_help");
192 
193         foreach (const QString& catalog, qtCatalogs)
194         {
195             QTranslator* const translator = new QTranslator(&app);
196 
197             if (translator->load(locale, catalog, QLatin1String("_"), transPath))
198             {
199                 qCDebug(DIGIKAM_GENERAL_LOG) << "Loaded locale:" << locale.name()
200                                              << "from catalog:"  << catalog;
201 
202                 app.installTranslator(translator);
203             }
204             else
205             {
206                 delete translator;
207             }
208         }
209     }
210 
211     MetaEngine::initializeExiv2();
212 
213     // Force to use application icon for non plasma desktop as Unity for ex.
214 
215     QApplication::setWindowIcon(QIcon::fromTheme(QLatin1String("showfoto"), app.windowIcon()));
216 
217 #ifdef Q_OS_WIN
218 
219     if (QSysInfo::currentCpuArchitecture().contains(QLatin1String("64")) &&
220         !QSysInfo::buildCpuArchitecture().contains(QLatin1String("64")))
221     {
222         QMessageBox::critical(qApp->activeWindow(),
223                               qApp->applicationName(),
224                               i18nc("#info", "<p>You are running Showfoto as a 32-bit version on a 64-bit Windows.</p>"
225                                     "<p>Please install the 64-bit version of Showfoto to get "
226                                     "a better experience with Showfoto.</p>"));
227     }
228 
229 #endif
230 
231     QList<QUrl> urlList;
232     QStringList urls = parser.positionalArguments();
233 
234     foreach (const QString& url, urls)
235     {
236         urlList.append(QUrl::fromLocalFile(url));
237     }
238 
239     parser.clearPositionalArguments();
240 
241     if (!iconTheme.isEmpty())
242     {
243         QIcon::setThemeName(iconTheme);
244     }
245 
246     // Workaround for the automatic icon theme color
247     // in KF-5.80/KF-5.88, depending on the color scheme.
248     // Note: In a Plasma environment, use the showFoto icon theme setting from the system.
249 
250     if (
251         (colorTheme == QLatin1String("White Balance")) ||
252         (colorTheme == QLatin1String("Standard"))      ||
253         (colorTheme == QLatin1String("High Key"))      ||
254         (colorTheme == QLatin1String("Breeze"))
255        )
256     {
257         qApp->setPalette(QPalette(Qt::white));
258     }
259     else
260     {
261         qApp->setPalette(QPalette(Qt::darkGray));
262     }
263 
264 #ifdef Q_OS_WIN
265 
266     // Necessary to open native open with dialog on windows
267 
268     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
269 
270 #endif
271 
272     ShowFoto::Showfoto* const w = new ShowFoto::Showfoto(urlList);
273 
274     // If application storage place in home directory to save customized XML settings files do not exist, create it,
275     // else QFile will not able to create new files as well.
276 
277     if (!QFile::exists(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)))
278     {
279         QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
280     }
281 
282     // If application cache place in home directory to save cached files do not exist, create it.
283 
284     if (!QFile::exists(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)))
285     {
286         QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
287     }
288 
289     w->show();
290 
291     QPointer<FilesDownloader> floader = new FilesDownloader(qApp->activeWindow());
292 
293     if (!floader->checkDownloadFiles())
294     {
295         floader->startDownload();
296     }
297 
298     int ret = app.exec();
299 
300 #ifdef Q_OS_WIN
301 
302     // Necessary to open native open with dialog on windows
303 
304     CoUninitialize();
305 
306 #endif
307 
308 #ifdef HAVE_IMAGE_MAGICK
309 #   if MagickLibVersion >= 0x693
310 
311     TerminateMagick();
312 
313 #   endif
314 #endif
315 
316     return ret;
317 }
318