1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2006-12-20
7  * Description : a widget to display a welcome page
8  *               on root album.
9  *
10  * Copyright (C) 2006-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
11  * Copyright (C) 2009-2011 by Andi Clemens <andi dot clemens at gmail dot com>
12  * Copyright (C) 2015      by Mohamed_Anwer <m_dot_anwer at gmx dot com>
13  *
14  * This program is free software; you can redistribute it
15  * and/or modify it under the terms of the GNU General
16  * Public License as published by the Free Software Foundation;
17  * either version 2, or (at your option)
18  * any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * ============================================================ */
26 
27 #include "welcomepageview.h"
28 
29 // Qt includes
30 
31 #include <QFile>
32 #include <QFileInfo>
33 #include <QTimer>
34 #include <QWidget>
35 #include <QApplication>
36 #include <QStandardPaths>
37 
38 #ifdef HAVE_QWEBENGINE
39 #   include <QtWebEngineWidgetsVersion>
40 #endif
41 
42 // KDE includes
43 
44 #include <klocalizedstring.h>
45 
46 // Local includes
47 
48 #include "digikam_debug.h"
49 #include "digikam_version.h"
50 #include "daboutdata.h"
51 #include "thememanager.h"
52 #include "webbrowserdlg.h"
53 
54 namespace Digikam
55 {
56 
57 #ifdef HAVE_QWEBENGINE
58 
WelcomePageViewPage(QObject * const parent)59 WelcomePageViewPage::WelcomePageViewPage(QObject* const parent)
60     : QWebEnginePage(parent)
61 {
62 }
63 
~WelcomePageViewPage()64 WelcomePageViewPage::~WelcomePageViewPage()
65 {
66 }
67 
acceptNavigationRequest(const QUrl & url,QWebEnginePage::NavigationType type,bool)68 bool WelcomePageViewPage::acceptNavigationRequest(const QUrl& url, QWebEnginePage::NavigationType type, bool)
69 {
70     if (type == QWebEnginePage::NavigationTypeLinkClicked)
71     {
72         emit linkClicked(url);
73 
74         return false;
75     }
76 
77     return true;
78 }
79 
80 // ----------------------------------------------------------------------------
81 
WelcomePageView(QWidget * const parent)82 WelcomePageView::WelcomePageView(QWidget* const parent)
83     : QWebEngineView(parent)
84 
85 #else
86 
87 WelcomePageView::WelcomePageView(QWidget* const parent)
88     : QWebView(parent)
89 
90 #endif
91 
92 {
93     setFocusPolicy(Qt::WheelFocus);
94 
95 #ifndef HAVE_QWEBENGINE
96 
97     page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
98     setRenderHint(QPainter::TextAntialiasing);
99 
100 #endif
101 
102     setContextMenuPolicy(Qt::NoContextMenu);
103     setContentsMargins(QMargins());
104 
105 #ifdef HAVE_QWEBENGINE
106 
107     WelcomePageViewPage* const wpage = new WelcomePageViewPage(this);
108     setPage(wpage);
109 
110 #   if QTWEBENGINEWIDGETS_VERSION >= QT_VERSION_CHECK(5, 7, 0)
111 
112     settings()->setAttribute(QWebEngineSettings::WebGLEnabled, false);
113     settings()->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled, false);
114 
115 #   endif
116 
117 #endif
118 
119     // ------------------------------------------------------------
120 
121 #ifdef HAVE_QWEBENGINE
122 
123     connect(wpage, SIGNAL(linkClicked(QUrl)),
124             this, SLOT(slotUrlOpen(QUrl)));
125 
126 #else
127 
128     connect(this, SIGNAL(linkClicked(QUrl)),
129             this, SLOT(slotUrlOpen(QUrl)));
130 
131 #endif
132 
133     connect(ThemeManager::instance(), SIGNAL(signalThemeChanged()),
134             this, SLOT(slotThemeChanged()));
135 
136     QTimer::singleShot(0, this, SLOT(slotThemeChanged()));
137 }
138 
~WelcomePageView()139 WelcomePageView::~WelcomePageView()
140 {
141 }
142 
slotUrlOpen(const QUrl & url)143 void WelcomePageView::slotUrlOpen(const QUrl& url)
144 {
145     WebBrowserDlg* const browser = new WebBrowserDlg(url, qApp->activeWindow());
146     browser->show();
147 }
148 
featuresTabContent() const149 QStringList WelcomePageView::featuresTabContent() const
150 {
151     QStringList newFeatures;
152     newFeatures << i18n("More than 1300 user-reports closed on bugzilla.");
153     newFeatures << i18n("New Neural Network engine based on OpenCV Deep Learning module to detect and recognize faces.");
154     newFeatures << i18n("Update Slideshow to plugin with new shuffle mode.");
155     newFeatures << i18n("Add new theme Html5Responsive for HtmlGallery plugin.");
156     newFeatures << i18n("New plugin ImageMosaicWall to create an image based on a bunch of other photos.");
157     newFeatures << i18n("add new batch queue manager tool to fix hot pixels from images.");
158     newFeatures << i18n("add new batch queue manager tool to apply texture over images.");
159     newFeatures << i18n("Face Scan dialog contents is now simplified and embedded into left sidebar.");
160     newFeatures << i18n("Add support for Gimp XCF files >= 2.10.");
161     newFeatures << i18n("Add Flatpak bundle support for Linux platforms.");
162     newFeatures << i18n("Table-view is now able to show digiKam Tag-Paths properties.");
163     newFeatures << i18n("Add option to write geolocation information in file metadata.");
164     newFeatures << i18n("Add color label support for advanced metadata settings.");
165     newFeatures << i18n("Add Exif, Iptc, and Xmp read support for HEIF images.");
166     newFeatures << i18n("Improved support for UNC network paths under Windows.");
167     newFeatures << i18n("Improved support for Unicode paths under Windows.");
168     newFeatures << i18n("Apple bundle is now relocatable and compatible with macOS BigSur.");
169     newFeatures << i18n("New online version checker and downloader to automatize upgrade under Windows and macOS.");
170     newFeatures << i18n("Better support of astro FITS image format including metadata extraction support to populate the database.");
171     newFeatures << i18n("Use last Exiv2 0.27.4 in all bundles with Base Media File metadata read and write support (HEIF, AVIF).");
172     newFeatures << i18n("Find duplicates items is now process in parallel using multi-cores.");
173     newFeatures << i18n("New tool to export items to iNaturatist web service.");
174     newFeatures << i18n("New metadata viewer based on ExifTool.");
175     newFeatures << i18n("Integration of  Google Summer of Code project 2021 "
176                         "<a href=\"https://community.kde.org/GSoC/2021/StatusReports/PhuocKhanhLE\">Image Quality Sorter</a>.");
177     newFeatures << i18n("New tool to share items on the network with a Motion JPEG stream server.");
178     newFeatures << i18n("Showfoto has a new left sidebar hosting a folder-view to quickly explore images from local file system.");
179     newFeatures << i18n("Update internal RAW engine to last Libraw 0.20.2 (snapshot 20210827) including Canon CR3 and Sony A7R4 support.");
180     newFeatures << i18n("New camera supported: "
181                         "Canon CR3, PowerShot G5 X Mark II, G7 X Mark III, SX70 HS, EOS R, EOS RP, EOS 90D, EOS 250D, EOS M6 Mark II, EOS M50, EOS M200, EOS 1DX Mark III (lossless files only) "
182                         "DJI Mavic Air, Air2, Osmo Action, "
183                         "FujiFilm Fujifilm compressed/16bit, GFX 100, X-A7, X-Pro3, X100V, X-T4, X-T200, "
184                         "GoPro Fusion, HERO5, HERO6, HERO7, HERO8, "
185                         "Hasselblad L1D-20c, X1D II 50C, "
186                         "Leica D-LUX7, Q-P, Q2, V-LUX5, C-Lux / CAM-DC25, SL2, M10 Monochrom, "
187                         "Nikon D780, Z50, P950, "
188                         "Olympus TG-6, E-M5 Mark III, E-PL10, E-M1 Mark III, "
189                         "Panasonic Panasonic 14-bit, DC-FZ1000 II, DC-G90, DC-S1, DC-S1R, DC-S1H, DC-TZ95, "
190                         "PhaseOne IQ4 150MP, "
191                         "Rapsberry Pi RAW+JPEG format, "
192                         "Ricoh GR III, "
193                         "Sony A7R IV, A9 II, ILCE-6100, ILCE-6600, RX0 II, RX100 VII, "
194                         "Zenit M, "
195                         "also multiple modern smartphones.");
196 
197     // Add new features here...
198 
199     newFeatures << i18n("...and much more.");
200 
201     QString featureItems;
202 
203     for (int i = 0 ; i < newFeatures.count() ; ++i)
204     {
205         featureItems += i18n("<li>%1</li>\n", newFeatures.at(i));
206     }
207 
208     QString tabHeader  = i18n("New Features");
209     QString tabContent =
210         i18n("<h3>%1</h3><ul>%2</ul>",
211              i18n("Some of the new features in this release of digiKam include (compared to digiKam 6.x):"),
212              featureItems);
213 
214     return QStringList() << tabHeader << tabContent;
215 }
216 
aboutTabContent() const217 QStringList WelcomePageView::aboutTabContent() const
218 {
219     QString tabHeader  = i18n("About");
220     QString tabContent =
221         i18n("<h3>%1</h3><h3>%2</h3><ul>%3</ul>",
222              i18n("digiKam is an open source photo management program designed to import, organize, enhance, search and export your digital images to and from your computer."),
223              i18n("Currently, you are in the Album view mode of digiKam. Albums are the places where your files are stored, and are identical to the folders on your hard disk."),
224              i18n("<li>%1</li><li>%2</li>",
225                   i18n("digiKam has many powerful features which are described in the <a href=\"https://docs.kde.org/?application=digikam&branch=trunk5\">documentation</a>"),
226                   i18n("The <a href=\"https://www.digikam.org\">digiKam homepage</a> provides information about new versions of digiKam.")));
227 
228     return QStringList() << tabHeader << tabContent;
229 }
230 
fileToString(const QString & aFileName) const231 QByteArray WelcomePageView::fileToString(const QString& aFileName) const
232 {
233     QByteArray   result;
234     QFileInfo    info(aFileName);
235     unsigned int readLen;
236     unsigned int len = info.size();
237     QFile        file(aFileName);
238 
239     if (aFileName.isEmpty() || (len == 0)   ||
240         !info.exists()      || info.isDir() || !info.isReadable() ||
241         !file.open(QIODevice::Unbuffered|QIODevice::ReadOnly))
242     {
243         return QByteArray();
244     }
245 
246     result.resize(len + 2);
247     readLen = file.read(result.data(), len);
248     file.close();
249 
250     if (result[len-1] != '\n')
251     {
252         result[len++] = '\n';
253         ++readLen;
254     }
255 
256     result[len] = '\0';
257 
258     if (readLen < len)
259     {
260         return QByteArray();
261     }
262 
263     return result;
264 }
265 
slotThemeChanged()266 void WelcomePageView::slotThemeChanged()
267 {
268     QString appTitle         = i18n("digiKam");
269     QString slogan           = DAboutData::digiKamSlogan();
270     QString locationHtml     = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/about/main.html"));
271     QString content          = QString::fromUtf8(fileToString(locationHtml));
272     content                  = content.arg(appTitle)
273                                       .arg(slogan)
274                                       .arg(i18n("Welcome to digiKam %1", QLatin1String(digikam_version)))
275                                       .arg(featuresTabContent().value(0))
276                                       .arg(aboutTabContent().value(0))
277                                       .arg(i18n("Background Image Credits"))
278                                       .arg(featuresTabContent().value(1))
279                                       .arg(aboutTabContent().value(1));
280 
281     //qCDebug(DIGIKAM_GENERAL_LOG) << content;
282 
283     setHtml(content, QUrl::fromLocalFile(locationHtml));
284 }
285 
286 } // namespace Digikam
287