File indexing completed on 2025-01-05 03:58:35
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2009-12-01 0007 * Description : Widget for displaying HTML in the backends - QtWebKit version 0008 * 0009 * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2009-2011 by Michael G. Hansen <mike at mghansen dot de> 0011 * SPDX-FileCopyrightText: 2015 by Mohamed_Anwer <m_dot_anwer at gmx dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "htmlwidget_qwebkit.h" 0018 0019 // Qt includes 0020 0021 #include <QTimer> 0022 #include <QResizeEvent> 0023 #include <QWebSettings> 0024 #include <qwebframe.h> 0025 0026 // Local includes 0027 0028 #include "digikam_debug.h" 0029 0030 namespace Digikam 0031 { 0032 0033 class Q_DECL_HIDDEN HTMLWidget::Private 0034 { 0035 public: 0036 0037 explicit Private() 0038 : parent (nullptr), 0039 isReady (false), 0040 selectionStatus (false), 0041 firstSelectionPoint (), 0042 intermediateSelectionPoint (), 0043 firstSelectionScreenPoint (), 0044 intermediateSelectionScreenPoint() 0045 { 0046 } 0047 0048 QWidget* parent; 0049 bool isReady; 0050 0051 bool selectionStatus; 0052 GeoCoordinates firstSelectionPoint; 0053 GeoCoordinates intermediateSelectionPoint; 0054 QPoint firstSelectionScreenPoint; 0055 QPoint intermediateSelectionScreenPoint; 0056 }; 0057 0058 HTMLWidget::HTMLWidget(QWidget* const parent) 0059 : QWebView(parent), 0060 d (new Private()), 0061 s (nullptr) 0062 { 0063 d->parent = parent; 0064 setAcceptDrops(false); 0065 setFocusPolicy(Qt::WheelFocus); 0066 setRenderHint(QPainter::TextAntialiasing); 0067 page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); 0068 0069 settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true); 0070 settings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, true); 0071 settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true); 0072 settings()->setAttribute(QWebSettings::LocalStorageEnabled, true); 0073 0074 d->parent->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0075 0076 connect(this, SIGNAL(loadProgress(int)), 0077 this, SLOT(progress(int))); 0078 0079 connect(this, SIGNAL(loadFinished(bool)), 0080 this, SLOT(slotHTMLCompleted(bool))); 0081 0082 connect(this, SIGNAL(statusBarMessage(QString)), 0083 this, SLOT(slotScanForJSMessages(QString))); 0084 0085 if (d->parent) 0086 { 0087 d->parent->installEventFilter(this); 0088 } 0089 } 0090 0091 HTMLWidget::~HTMLWidget() 0092 { 0093 delete d; 0094 } 0095 0096 void HTMLWidget::progress(int progress) 0097 { 0098 qCDebug(DIGIKAM_GEOIFACE_LOG) << "Maps Loading Progress: " << progress << "%"; 0099 } 0100 0101 void HTMLWidget::slotHTMLCompleted(bool ok) 0102 { 0103 qCDebug(DIGIKAM_GEOIFACE_LOG) << "Map Loading Completed: " << ok; 0104 d->isReady = ok; 0105 0106 Q_EMIT signalJavaScriptReady(); 0107 } 0108 0109 void HTMLWidget::mousePressEvent(QMouseEvent* e) 0110 { 0111 slotScanForJSMessages(QLatin1String("(event)")); 0112 QWebView::mousePressEvent(e); 0113 } 0114 0115 void HTMLWidget::mouseReleaseEvent(QMouseEvent* e) 0116 { 0117 if (s->currentMouseMode == MouseModeRegionSelection) 0118 { 0119 if (!d->firstSelectionPoint.hasCoordinates()) 0120 { 0121 runScript2Coordinates(QString::fromLatin1("kgeomapPixelToLatLng(%1, %2);") 0122 .arg(e->x()) 0123 .arg(e->y()), 0124 &d->firstSelectionPoint); 0125 0126 d->firstSelectionScreenPoint = QPoint(e->x(), e->y()); 0127 } 0128 else 0129 { 0130 runScript2Coordinates(QString::fromLatin1("kgeomapPixelToLatLng(%1, %2);") 0131 .arg(e->x()) 0132 .arg(e->y()), 0133 &d->intermediateSelectionPoint); 0134 0135 d->intermediateSelectionScreenPoint = QPoint(e->x(), e->y()); 0136 0137 qreal lonWest, latNorth, lonEast, latSouth; 0138 0139 if (d->firstSelectionScreenPoint.x() < d->intermediateSelectionScreenPoint.x()) 0140 { 0141 lonWest = d->firstSelectionPoint.lon(); 0142 lonEast = d->intermediateSelectionPoint.lon(); 0143 } 0144 else 0145 { 0146 lonEast = d->firstSelectionPoint.lon(); 0147 lonWest = d->intermediateSelectionPoint.lon(); 0148 } 0149 0150 if (d->firstSelectionScreenPoint.y() < d->intermediateSelectionScreenPoint.y()) 0151 { 0152 latNorth = d->firstSelectionPoint.lat(); 0153 latSouth = d->intermediateSelectionPoint.lat(); 0154 } 0155 else 0156 { 0157 latNorth = d->intermediateSelectionPoint.lat(); 0158 latSouth = d->firstSelectionPoint.lat(); 0159 } 0160 0161 runScript(QLatin1String("kgeomapRemoveTemporarySelectionRectangle();")); 0162 runScript(QString::fromLatin1("kgeomapSetSelectionRectangle(%1, %2, %3, %4);") 0163 .arg(lonWest) 0164 .arg(latNorth) 0165 .arg(lonEast) 0166 .arg(latSouth)); 0167 0168 const GeoCoordinates::Pair selectionCoordinates( 0169 GeoCoordinates(latNorth, lonWest), 0170 GeoCoordinates(latSouth, lonEast)); 0171 0172 d->firstSelectionPoint.clear(); 0173 d->intermediateSelectionPoint.clear(); 0174 0175 Q_EMIT selectionHasBeenMade(selectionCoordinates); 0176 } 0177 } 0178 0179 slotScanForJSMessages(QLatin1String("(event)")); 0180 QWebView::mouseReleaseEvent(e); 0181 } 0182 0183 void HTMLWidget::mouseMoveEvent(QMouseEvent *e) 0184 { 0185 if ((s->currentMouseMode == MouseModeRegionSelection) && 0186 d->firstSelectionPoint.hasCoordinates()) 0187 { 0188 runScript2Coordinates(QString::fromLatin1("kgeomapPixelToLatLng(%1, %2);") 0189 .arg(e->x()) 0190 .arg(e->y()), 0191 &d->intermediateSelectionPoint); 0192 0193 d->intermediateSelectionScreenPoint = QPoint(e->x(), e->y()); 0194 0195 qCDebug(DIGIKAM_GEOIFACE_LOG) << d->firstSelectionScreenPoint << QLatin1Char(' ') 0196 << d->intermediateSelectionScreenPoint; 0197 0198 qreal lonWest, latNorth, lonEast, latSouth; 0199 0200 if (d->firstSelectionScreenPoint.x() < d->intermediateSelectionScreenPoint.x()) 0201 { 0202 lonWest = d->firstSelectionPoint.lon(); 0203 lonEast = d->intermediateSelectionPoint.lon(); 0204 } 0205 else 0206 { 0207 lonEast = d->firstSelectionPoint.lon(); 0208 lonWest = d->intermediateSelectionPoint.lon(); 0209 } 0210 0211 if (d->firstSelectionScreenPoint.y() < d->intermediateSelectionScreenPoint.y()) 0212 { 0213 latNorth = d->firstSelectionPoint.lat(); 0214 latSouth = d->intermediateSelectionPoint.lat(); 0215 } 0216 else 0217 { 0218 latNorth = d->intermediateSelectionPoint.lat(); 0219 latSouth = d->firstSelectionPoint.lat(); 0220 } 0221 0222 runScript(QString::fromLatin1("kgeomapSetTemporarySelectionRectangle(%1, %2, %3, %4);") 0223 .arg(lonWest) 0224 .arg(latNorth) 0225 .arg(lonEast) 0226 .arg(latSouth)); 0227 } 0228 0229 QWebView::mouseMoveEvent(e); 0230 } 0231 0232 void HTMLWidget::slotScanForJSMessages(const QString& message) 0233 { 0234 if (message != QLatin1String("(event)")) 0235 { 0236 return; 0237 } 0238 0239 //qCDebug(DIGIKAM_GEOIFACE_LOG) << message; 0240 0241 const QString eventBufferString = runScript(QLatin1String("kgeomapReadEventStrings();")).toString(); 0242 0243 if (eventBufferString.isEmpty()) 0244 { 0245 return; 0246 } 0247 0248 const QStringList events = eventBufferString.split(QLatin1Char('|')); 0249 0250 Q_EMIT signalHTMLEvents(events); 0251 } 0252 0253 /** 0254 * @brief Wrapper around executeScript to catch more errors 0255 */ 0256 QVariant HTMLWidget::runScript(const QString& scriptCode, bool /*async*/) 0257 { 0258 GEOIFACE_ASSERT(d->isReady); 0259 0260 if (!d->isReady) 0261 { 0262 return QVariant(); 0263 } 0264 0265 //qCDebug(DIGIKAM_GEOIFACE_LOG) << scriptCode; 0266 0267 return page()->mainFrame()->evaluateJavaScript(scriptCode); 0268 } 0269 0270 /** 0271 * @brief Execute a script which returns coordinates and parse these 0272 */ 0273 bool HTMLWidget::runScript2Coordinates(const QString& scriptCode, GeoCoordinates* const coordinates) 0274 { 0275 const QVariant scriptResult = runScript(scriptCode); 0276 0277 return GeoIfaceHelperParseLatLonString(scriptResult.toString(), coordinates); 0278 } 0279 0280 bool HTMLWidget::eventFilter(QObject* object, QEvent* event) 0281 { 0282 if (d->parent && (object == d->parent)) 0283 { 0284 if (event->type() == QEvent::Resize) 0285 { 0286 QResizeEvent* const resizeEvent = dynamic_cast<QResizeEvent*>(event); 0287 0288 if (resizeEvent) 0289 { 0290 resize(resizeEvent->size()); 0291 } 0292 } 0293 } 0294 0295 return false; 0296 } 0297 0298 void HTMLWidget::setSelectionRectangle(const GeoCoordinates::Pair& searchCoordinates) 0299 { 0300 if (!searchCoordinates.first.hasCoordinates()) 0301 { 0302 runScript(QLatin1String("kgeomapRemoveSelectionRectangle();")); 0303 return; 0304 } 0305 0306 qreal West = searchCoordinates.first.lon(); 0307 qreal North = searchCoordinates.first.lat(); 0308 qreal East = searchCoordinates.second.lon(); 0309 qreal South = searchCoordinates.second.lat(); 0310 0311 runScript(QString::fromLatin1("kgeomapSetSelectionRectangle(%1, %2, %3, %4);") 0312 .arg(West).arg(North).arg(East).arg(South)); 0313 } 0314 0315 void HTMLWidget::removeSelectionRectangle() 0316 { 0317 runScript(QLatin1String("kgeomapRemoveSelectionRectangle();")); 0318 } 0319 0320 void HTMLWidget::mouseModeChanged(const GeoMouseModes mouseMode) 0321 { 0322 const bool inSelectionMode = (mouseMode == MouseModeRegionSelection); 0323 0324 if (inSelectionMode) 0325 { 0326 d->firstSelectionPoint.clear(); 0327 d->intermediateSelectionPoint.clear(); 0328 runScript(QString::fromLatin1("kgeomapSelectionModeStatus(%1);").arg(inSelectionMode)); 0329 } 0330 else 0331 { 0332 runScript(QString::fromLatin1("kgeomapSelectionModeStatus(%1);").arg(inSelectionMode)); 0333 } 0334 } 0335 0336 void HTMLWidget::centerOn(const qreal west, const qreal north, 0337 const qreal east, const qreal south, 0338 const bool useSaneZoomLevel) 0339 { 0340 /* 0341 qCDebug(DIGIKAM_GEOIFACE_LOG) << "West:" << west 0342 << " North:" << north 0343 << " East:" << east 0344 << " South:" << south; 0345 */ 0346 runScript(QString::fromLatin1("kgeomapSetMapBoundaries(%1, %2, %3, %4, %5);") 0347 .arg(west) 0348 .arg(north) 0349 .arg(east) 0350 .arg(south) 0351 .arg(useSaneZoomLevel ? 1 : 0)); 0352 } 0353 0354 void HTMLWidget::setSharedGeoIfaceObject(GeoIfaceSharedData* const sharedData) 0355 { 0356 s = sharedData; 0357 } 0358 0359 } // namespace Digikam 0360 0361 #include "moc_htmlwidget_qwebkit.cpp"