diff --git a/static/reports/cppcheck/master/0.html b/static/reports/cppcheck/master/0.html index ea4429938..7ec6ea0dc 100644 --- a/static/reports/cppcheck/master/0.html +++ b/static/reports/cppcheck/master/0.html @@ -1,1327 +1,1299 @@ - Cppcheck - HTML report - digiKam-master-rev-74ed235f83 + Cppcheck - HTML report - digiKam-master-rev-a04a0335ac
  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
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
-579
-580
-581
-582
-583
-584
-585
-586
-587
-588
-589
-590
-591
-592
-593
/* ============================================================
+579
/* ============================================================
  *
  * This file is a part of digiKam project
  * http://www.digikam.org
  *
- * Date        : 2009-05-04
- * Description : Various operations on images
+ * Date        : 2008-05-12
+ * Description : Access to copy-right info of an item in the database
  *
- * Copyright (C) 2002-2005 by Renchi Raju <renchi dot raju at gmail dot com>
- * Copyright (C) 2002-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
- * Copyright (C) 2006-2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
- * Copyright (C) 2009-2010 by Andi Clemens <andi dot clemens at gmail dot com>
- *
- * This program is free software; you can redistribute it
- * and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation;
- * either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * ============================================================ */
+ * Copyright (C) 2008-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2009-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include "itemcopyright.h"
 
-#include "imageviewutilities.h"
+// Qt includes
 
-// Qt includes
+#include <QLocale>
 
-#include <QFileInfo>
-#include <QStringRef>
-#include <QUrl>
-
-// KDE includes
-
-#include <kwindowsystem.h>
-
-// Local includes
+// Local includes
+
+#include "coredb.h"
+#include "coredbaccess.h"
+#include "itemscanner.h"
+#include "template.h"
+
+namespace Digikam
+{
 
-#include "digikam_debug.h"
-#include "album.h"
-#include "albummanager.h"
-#include "albumselectdialog.h"
-#include "applicationsettings.h"
-#include "deletedialog.h"
-#include "dio.h"
-#include "iteminfo.h"
-#include "imagewindow.h"
-#include "lighttablewindow.h"
-#include "loadingcacheinterface.h"
-#include "queuemgrwindow.h"
-#include "thumbnailloadthread.h"
-#include "fileactionmngr.h"
-#include "dfileoperations.h"
-#include "coredb.h"
-#include "coredbaccess.h"
+class Q_DECL_HIDDEN ItemCopyrightCache
+{
+public:
+
+    explicit ItemCopyrightCache(ItemCopyright* const object)
+        : object(object)
+    {
+        // set this as cache
+        object->m_cache = this;
+        // read all properties
+        infos = CoreDbAccess().db()->getItemCopyright(object->m_id, QString());
+    }
+
+    ~ItemCopyrightCache()
+    {
+        object->m_cache = 0;
+    }
 
-namespace Digikam
-{
-
-ImageViewUtilities::ImageViewUtilities(QWidget* const parentWidget)
-    : QObject(parentWidget)
-{
-    m_widget = parentWidget;
-
-    connect(this, SIGNAL(signalImagesDeleted(QList<qlonglong>)),
-            AlbumManager::instance(), SLOT(slotImagesDeleted(QList<qlonglong>)));
-}
-
-void ImageViewUtilities::setAsAlbumThumbnail(Album* album,
-                                             const ItemInfo& itemInfo)
-{
-    if (!album)
-    {
-        return;
-    }
-
-    if (album->type() == Album::PHYSICAL)
-    {
-        PAlbum* const palbum = static_cast<PAlbum*>(album);
-
-        QString err;
-        AlbumManager::instance()->updatePAlbumIcon(palbum, itemInfo.id(), err);
-    }
-    else if (album->type() == Album::TAG)
-    {
-        TAlbum* const talbum = static_cast<TAlbum*>(album);
-
-        QString err;
-        AlbumManager::instance()->updateTAlbumIcon(talbum, QString(), itemInfo.id(), err);
-    }
-}
-
-void ImageViewUtilities::rename(const QUrl& imageUrl,
-                                const QString& newName,
-                                bool overwrite)
-{
-    if (imageUrl.isEmpty() || !imageUrl.isLocalFile() || newName.isEmpty())
-    {
-        return;
-    }
-
-    DIO::rename(imageUrl, newName, overwrite);
-}
-
-bool ImageViewUtilities::deleteImages(const QList<ItemInfo>& infos,
-                                      const DeleteMode deleteMode)
-{
-    if (infos.isEmpty())
-    {
-        return false;
-    }
-
-    QList<ItemInfo> deleteInfos = infos;
+    QList<CopyrightInfo> infos;
+
+private:
+
+    ItemCopyright* object;
+};
+
+// -------------------------------------------------------------------------------------------
+
+ItemCopyright::ItemCopyright(qlonglong imageid)
+    : m_id(imageid),
+      m_cache(0)
+{
+}
+
+ItemCopyright::ItemCopyright()
+    : m_id(0),
+      m_cache(0)
+{
+}
+
+ItemCopyright::ItemCopyright(const ItemCopyright& other)
+    : m_id(other.m_id),
+      m_cache(0)
+{
+    // the cache is only short-lived, to keep complexity low
+}
+
+ItemCopyright::~ItemCopyright()
+{
+    delete m_cache;
+    m_cache = 0;
+}
+
+ItemCopyright& ItemCopyright::operator=(const ItemCopyright& other)
+{
+    delete m_cache;
+    m_cache = 0;
+
+    m_id = other.m_id;
+    return *this;
+}
+
+void ItemCopyright::replaceFrom(const ItemCopyright& source)
+{
+    if (!m_id)
+    {
+        return;
+    }
+
+    CoreDbAccess access;
+    access.db()->removeItemCopyrightProperties(m_id);
+
+    if (!source.m_id)
+    {
+        return;
+    }
 
-    QList<QUrl> urlList;
-    QList<qlonglong> imageIds;
-
-    // Buffer the urls for deletion and imageids for notification of the AlbumManager
-    foreach (const ItemInfo& info, deleteInfos)
-    {
-        urlList  << info.fileUrl();
-        imageIds << info.id();
-    }
-
-    DeleteDialog dialog(m_widget);
-
-    DeleteDialogMode::DeleteMode deleteDialogMode = DeleteDialogMode::NoChoiceTrash;
+    QList<CopyrightInfo> infos = access.db()->getItemCopyright(source.m_id, QString());
+
+    foreach (const CopyrightInfo& info, infos)
+    {
+        access.db()->setItemCopyrightProperty(m_id, info.property, info.value,
+                                               info.extraValue, CoreDB::PropertyNoConstraint);
+    }
+}
+
+QStringList ItemCopyright::creator() const
+{
+    QList<CopyrightInfo> infos = copyrightInfos(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator));
+    QStringList list;
 
-    if (deleteMode == ImageViewUtilities::DeletePermanently)
+    foreach (const CopyrightInfo& info, infos)
     {
-        deleteDialogMode = DeleteDialogMode::NoChoiceDeletePermanently;
+        list << info.value;
     }
 
-    if (!dialog.confirmDeleteList(urlList, DeleteDialogMode::Files, deleteDialogMode))
-    {
-        return false;
-    }
-
-    const bool useTrash = !dialog.shouldDelete();
+    return list;
+}
+
+void ItemCopyright::setCreator(const QString& creator, ReplaceMode mode)
+{
+    CoreDB::CopyrightPropertyUnique uniqueness;
 
-    DIO::del(deleteInfos, useTrash);
-
-    // Signal the Albummanager about the ids of the deleted images.
-    emit signalImagesDeleted(imageIds);
-
-    return true;
-}
-
-void ImageViewUtilities::deleteImagesDirectly(const QList<ItemInfo>& infos,
-                                              const DeleteMode deleteMode)
-{
-    // This method deletes the selected items directly, without confirmation.
-    // It is not used in the default setup.
-
-    if (infos.isEmpty())
-    {
-        return;
-    }
-
-    QList<qlonglong> imageIds;
-
-    foreach (const ItemInfo& info, infos)
-    {
-        imageIds << info.id();
-    }
-
-    const bool useTrash = (deleteMode == ImageViewUtilities::DeleteUseTrash);
+    if (mode == ReplaceAllEntries)
+    {
+        uniqueness = CoreDB::PropertyUnique;
+    }
+    else
+    {
+        uniqueness = CoreDB::PropertyNoConstraint;
+    }
+
+    CoreDbAccess().db()->setItemCopyrightProperty(m_id, ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator),
+                                                   creator, QString(), uniqueness);
+}
+
+void ItemCopyright::removeCreators()
+{
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator));
+}
+
+QString ItemCopyright::provider() const
+{
+    return readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider));
+}
+
+void ItemCopyright::setProvider(const QString& provider)
+{
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider), provider);
+}
 
-    DIO::del(infos, useTrash);
-
-    // Signal the Albummanager about the ids of the deleted images.
-    emit signalImagesDeleted(imageIds);
-}
-
-void ImageViewUtilities::notifyFileContentChanged(const QList<QUrl>& urls)
-{
-    foreach (const QUrl& url, urls)
-    {
-        QString path = url.toLocalFile();
-        ThumbnailLoadThread::deleteThumbnail(path);
-        // clean LoadingCache as well - be pragmatic, do it here.
-        LoadingCacheInterface::fileChanged(path);
-    }
-}
-
-void ImageViewUtilities::createNewAlbumForInfos(const QList<ItemInfo>& infos,
-                                                Album* currentAlbum)
-{
-    if (infos.isEmpty())
-    {
-        return;
-    }
+void ItemCopyright::removeProvider()
+{
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider));
+}
+
+QString ItemCopyright::copyrightNotice(const QString& languageCode)
+{
+    return readLanguageProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice), languageCode);
+}
+
+MetaEngine::AltLangMap ItemCopyright::allCopyrightNotices()
+{
+    return readLanguageProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice));
+}
+
+void ItemCopyright::setCopyrightNotice(const QString& notice, const QString& languageCode, ReplaceMode mode)
+{
+    setLanguageProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice), notice, languageCode, mode);
+}
+
+void ItemCopyright::removeCopyrightNotices()
+{
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice));
+}
 
-    if (currentAlbum && currentAlbum->type() != Album::PHYSICAL)
-    {
-        currentAlbum = 0;
-    }
+QString ItemCopyright::rightsUsageTerms(const QString& languageCode)
+{
+    return readLanguageProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms), languageCode);
+}
 
-    QString header(i18n("<p>Please select the destination album from the digiKam library to "
-                        "move the selected images into.</p>"));
-
-    Album* const album = AlbumSelectDialog::selectAlbum(m_widget, static_cast<PAlbum*>(currentAlbum), header);
+MetaEngine::AltLangMap ItemCopyright::allRightsUsageTerms()
+{
+    return readLanguageProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms));
+}
 
-    if (!album)
-    {
-        return;
-    }
+void ItemCopyright::setRightsUsageTerms(const QString& term, const QString& languageCode, ReplaceMode mode)
+{
+    setLanguageProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms), term, languageCode, mode);
+}
 
-    DIO::move(infos, (PAlbum*)album);
-}
-
-void ImageViewUtilities::insertToLightTableAuto(const QList<ItemInfo>& all,
-                                                const QList<ItemInfo>& selected,
-                                                const ItemInfo& current)
+void ItemCopyright::removeRightsUsageTerms()
+{
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms));
+}
+
+QString ItemCopyright::source()
 {
-    ItemInfoList list   = ItemInfoList(selected);
-    ItemInfo singleInfo = current;
+    return readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource));
+}
 
-    if (list.isEmpty() || (list.size() == 1 && LightTableWindow::lightTableWindow()->isEmpty()))
-    {
-        list = ItemInfoList(all);
-    }
+void ItemCopyright::setSource(const QString& source)
+{
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource), source);
+}
 
-    if (singleInfo.isNull() && !list.isEmpty())
-    {
-        singleInfo = list.first();
-    }
+void ItemCopyright::removeSource()
+{
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource));
+}
 
-    insertToLightTable(list, current, list.size() <= 1);
-}
-
-void ImageViewUtilities::insertToLightTable(const QList<ItemInfo>& list,
-                                            const ItemInfo& current,
-                                            bool addTo)
+QString ItemCopyright::creatorJobTitle() const
+{
+    return readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle));
+}
+
+void ItemCopyright::setCreatorJobTitle(const QString& title)
 {
-    LightTableWindow* const ltview = LightTableWindow::lightTableWindow();
-
-    // If addTo is false, the light table will be emptied before adding
-    // the images.
-    ltview->loadItemInfos(ItemInfoList(list), current, addTo);
-    ltview->setLeftRightItems(ItemInfoList(list), addTo);
-
-    if (ltview->isHidden())
-    {
-        ltview->show();
-    }
-
-    if (ltview->isMinimized())
-    {
-        KWindowSystem::unminimizeWindow(ltview->winId());
-    }
-
-    KWindowSystem::activateWindow(ltview->winId());
-}
-
-void ImageViewUtilities::insertToQueueManager(const QList<ItemInfo>& list, const ItemInfo& current, bool newQueue)
-{
-    Q_UNUSED(current);
-
-    QueueMgrWindow* const bqmview = QueueMgrWindow::queueManagerWindow();
-
-    if (bqmview->isHidden())
-    {
-        bqmview->show();
-    }
-
-    if (bqmview->isMinimized())
-    {
-        KWindowSystem::unminimizeWindow(bqmview->winId());
-    }
-
-    KWindowSystem::activateWindow(bqmview->winId());
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle), title);
+}
+
+void ItemCopyright::removeCreatorJobTitle()
+{
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle));
+}
+
+QString ItemCopyright::instructions()
+{
+    return readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions));
+}
+
+void ItemCopyright::setInstructions(const QString& instructions)
+{
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions), instructions);
+}
+
+void ItemCopyright::removeInstructions()
+{
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions));
+}
+
+IptcCoreContactInfo ItemCopyright::contactInfo()
+{
+    IptcCoreContactInfo info;
+    info.city          = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity));
+    info.country       = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry));
+    info.address       = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress));
+    info.postalCode    = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode));
+    info.provinceState = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState));
+    info.email         = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail));
+    info.phone         = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone));
+    info.webUrl        = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl));
+
+    return info;
+}
 
-    if (newQueue)
-    {
-        bqmview->loadItemInfosToNewQueue(ItemInfoList(list));
-    }
-    else
-    {
-        bqmview->loadItemInfosToCurrentQueue(ItemInfoList(list));
-    }
-}
-
-void ImageViewUtilities::insertSilentToQueueManager(const QList<ItemInfo>& list,
-                                                    const ItemInfo& /*current*/,
-                                                    int queueid)
+void ItemCopyright::setContactInfo(const IptcCoreContactInfo& info)
+{
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity), info.city);
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry), info.country);
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress), info.address);
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode), info.postalCode);
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState), info.provinceState);
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail), info.email);
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone), info.phone);
+    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl), info.webUrl);
+}
+
+void ItemCopyright::removeContactInfo()
 {
-    QueueMgrWindow* const bqmview = QueueMgrWindow::queueManagerWindow();
-    bqmview->loadItemInfos(ItemInfoList(list), queueid);
-}
-
-void ImageViewUtilities::openInfos(const ItemInfo& info,
-                                   const QList<ItemInfo>& allInfosToOpen,
-                                   Album* currentAlbum)
-{
-    if (info.isNull())
-    {
-        return;
-    }
-
-    QFileInfo fi(info.filePath());
-    QString imagefilter = ApplicationSettings::instance()->getImageFileFilter();
-    imagefilter        += ApplicationSettings::instance()->getRawFileFilter();
-
-    // If the current item is not an image file.
-    if ( !imagefilter.contains(fi.suffix().toLower()) )
-    {
-        // Openonly the first one from the list.
-        openInfosWithDefaultApplication(QList<ItemInfo>() << info);
-        return;
-    }
-
-    // Run digiKam ImageEditor with all image from current Album.
-
-    ImageWindow* const imview = ImageWindow::imageWindow();
-
-    imview->disconnect(this);
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity));
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry));
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress));
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode));
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState));
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail));
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone));
+    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl));
+}
+
+void ItemCopyright::fillTemplate(Template& t)
+{
+    ItemCopyrightCache cache(this);
+
+    t.setAuthors(author());
+    t.setAuthorsPosition(authorsPosition());
+    t.setCredit(credit());
+    t.setCopyright(allCopyrightNotices());
+    t.setRightUsageTerms(allRightsUsageTerms());
+    t.setSource(source());
+    t.setInstructions(instructions());
+    t.setContactInfo(contactInfo());
+}
+
+void ItemCopyright::setFromTemplate(const Template& t)
+{
+    foreach (const QString& author, t.authors()) // krazy:exclude=foreach
+    {
+        setAuthor(author, ItemCopyright::AddEntryToExisting);
+    }
 
-    connect(imview, SIGNAL(signalURLChanged(QUrl)),
-            this, SIGNAL(editorCurrentUrlChanged(QUrl)));
-
-    imview->loadItemInfos(ItemInfoList(allInfosToOpen), info,
-                           currentAlbum ? i18n("Album \"%1\"", currentAlbum->title())
-                                        : QString());
-
-    if (imview->isHidden())
-    {
-        imview->show();
-    }
-
-    if (imview->isMinimized())
-    {
-        KWindowSystem::unminimizeWindow(imview->winId());
-    }
-
-    KWindowSystem::activateWindow(imview->winId());
-}
-
-void ImageViewUtilities::openInfosWithDefaultApplication(const QList<ItemInfo>& infos)
-{
-    if (infos.isEmpty())
-    {
-        return;
-    }
-
-    QList<QUrl> urls;
-
-    foreach (const ItemInfo& inf, infos)
-    {
-        urls << inf.fileUrl();
-    }
-
-    DFileOperations::openFilesWithDefaultApplication(urls);
-}
-
-namespace
-{
-
-bool lessThanByTimeForItemInfo(const ItemInfo& a, const ItemInfo& b)
-{
-    return a.dateTime() < b.dateTime();
-}
-
-bool lowerThanByNameForItemInfo(const ItemInfo& a, const ItemInfo& b)
-{
-    return a.name() < b.name();
-}
-
-bool lowerThanBySizeForItemInfo(const ItemInfo& a, const ItemInfo& b)
-{
-    return a.fileSize() < b.fileSize();
-}
-
-} // namespace
-
-void ImageViewUtilities::createGroupByTimeFromInfoList(const ItemInfoList& itemInfoList)
-{
-    QList<ItemInfo> groupingList = itemInfoList;
-    // sort by time
-    std::stable_sort(groupingList.begin(), groupingList.end(), lessThanByTimeForItemInfo);
+    setCredit(t.credit());
+
+    MetaEngine::AltLangMap copyrights = t.copyright();
+    MetaEngine::AltLangMap::const_iterator it;
+
+    for (it = copyrights.constBegin() ; it != copyrights.constEnd() ; ++it)
+    {
+        setRights(it.value(), it.key(), ItemCopyright::AddEntryToExisting);
+    }
+
+    MetaEngine::AltLangMap usages = t.rightUsageTerms();
+    MetaEngine::AltLangMap::const_iterator it2;
+
+    for (it2 = usages.constBegin() ; it2 != usages.constEnd() ; ++it2)
+    {
+        setRightsUsageTerms(it2.value(), it2.key(), ItemCopyright::AddEntryToExisting);
+    }
+
+    setSource(t.source());
+    setAuthorsPosition(t.authorsPosition());
+    setInstructions(t.instructions());
+    setContactInfo(t.contactInfo());
+}
+
+void ItemCopyright::removeAll()
+{
+    ItemCopyrightCache cache(this);
+
+    removeCreators();
+    removeProvider();
+    removeCopyrightNotices();
+    removeRightsUsageTerms();
+    removeSource();
+    removeCreatorJobTitle();
+    removeInstructions();
+    removeContactInfo();
+}
+
+CopyrightInfo ItemCopyright::copyrightInfo(const QString& property) const
+{
+    if (m_cache)
+    {
+        foreach (const CopyrightInfo& info, m_cache->infos)
+        {
+            if (info.property == property)
+            {
+                return info;
+            }
+        }
+    }
+    else
+    {
+        QList<CopyrightInfo> infos = CoreDbAccess().db()->getItemCopyright(m_id, property);
+
+        if (!infos.isEmpty())
+        {
+            return infos.first();
+        }
+    }
+
+    return CopyrightInfo();
+}
 
-    QList<ItemInfo>::iterator it, it2;
-
-    for (it = groupingList.begin() ; it != groupingList.end() ; )
+QList<CopyrightInfo> ItemCopyright::copyrightInfos(const QString& property) const
+{
+    if (m_cache)
     {
-        const ItemInfo& leader = *it;
-        QList<ItemInfo> group;
-        QDateTime time         = it->dateTime();
-
-        if (time.isValid())
-        {
-            for (it2 = it + 1 ; it2 != groupingList.end() ; ++it2)
-            {
-                if (qAbs(time.secsTo(it2->dateTime())) < 2)
-                {
-                    group << *it2;
-                }
-                else
-                {
-                    break;
-                }
-            }
-        }
-        else
-        {
-            ++it;
-            continue;
-        }
-
-        // increment to next item not put in the group
-        it = it2;
-
-        if (!group.isEmpty())
-        {
-            FileActionMngr::instance()->addToGroup(leader, group);
-        }
-    }
-}
-
-void ImageViewUtilities::createGroupByFilenameFromInfoList(const ItemInfoList& itemInfoList)
-{
-    QList<ItemInfo> groupingList = itemInfoList;
-    // sort by Name
-    std::stable_sort(groupingList.begin(), groupingList.end(), lowerThanByNameForItemInfo);
-
-    QList<ItemInfo>::iterator it, it2;
-
-    for (it = groupingList.begin() ; it != groupingList.end() ; )
-    {
-        QList<ItemInfo> group;
-        QString fname = it->name().left(it->name().lastIndexOf(QLatin1Char('.')));
-        // don't know the leader yet so put first element also in group
-        group << *it;
-
-        for (it2 = it + 1 ; it2 != groupingList.end() ; ++it2)
-        {
-            QString fname2 = it2->name().left(it2->name().lastIndexOf(QLatin1Char('.')));
+        QList<CopyrightInfo> infos;
+
+        foreach (const CopyrightInfo& info, m_cache->infos)
+        {
+            if (info.property == property)
+            {
+                infos << info;
+            }
+        }
+
+        return infos;
+    }
+    else
+    {
+        return CoreDbAccess().db()->getItemCopyright(m_id, property);
+    }
+}
+
+QString ItemCopyright::readSimpleProperty(const QString& property) const
+{
+    return copyrightInfo(property).value;
+}
+
+void ItemCopyright::setSimpleProperty(const QString& property, const QString& value)
+{
+    CoreDbAccess().db()->setItemCopyrightProperty(m_id, property, value, QString(), CoreDB::PropertyUnique);
+}
+
+QString ItemCopyright::readLanguageProperty(const QString& property, const QString& languageCode)
+{
+    QList<CopyrightInfo> infos = copyrightInfos(property);
+    int index                  = languageMatch(infos, languageCode);
+
+    if (index == -1)
+    {
+        return QString();
+    }
+    else
+    {
+        return infos.at(index).value;
+    }
+}
+
+MetaEngine::AltLangMap ItemCopyright::readLanguageProperties(const QString& property)
+{
+    MetaEngine::AltLangMap map;
+    QList<CopyrightInfo> infos = copyrightInfos(property);
+
+    foreach (const CopyrightInfo& info, infos)
+    {
+        map[info.extraValue] = info.value;
+    }
 
-            if (fname == fname2)
-            {
-                group << *it2;
-            }
-            else
-            {
-                break;
-            }
-        }
-
-        // increment to next item not put in the group
-        it = it2;
-
-        if (group.count() > 1)
-        {
-            // sort by filesize and take smallest as leader
-            std::stable_sort(group.begin(), group.end(), lowerThanBySizeForItemInfo);
-            const ItemInfo& leader = group.takeFirst();
-            FileActionMngr::instance()->addToGroup(leader, group);
-        }
-    }
-}
+    return map;
+}
+
+void ItemCopyright::setLanguageProperty(const QString& property, const QString& value,
+                                         const QString& languageCode, ReplaceMode mode)
+{
+    CoreDB::CopyrightPropertyUnique uniqueness;
+
+    if (mode == ReplaceAllEntries)
+    {
+        uniqueness = CoreDB::PropertyUnique;
+    }
+    else if (mode == ReplaceLanguageEntry)
+    {
+        uniqueness = CoreDB::PropertyExtraValueUnique;
+    }
+    else
+    {
+        uniqueness = CoreDB::PropertyNoConstraint;
+    }
+
+    QString language = languageCode;
 
-namespace
-{
-
-struct NumberInFilenameMatch
-{
-    NumberInFilenameMatch()
-        : value(0),
-          containsValue(false)
-    {
-    }
-
-    NumberInFilenameMatch(const QString& filename)
-        : NumberInFilenameMatch()
-    {
-        if (filename.isEmpty())
-        {
-            return;
-        }
+    if (language.isNull())
+    {
+        language = QLatin1String("x-default");
+    }
+
+    CoreDbAccess().db()->setItemCopyrightProperty(m_id, property, value, language, uniqueness);
+}
+
+void ItemCopyright::removeProperties(const QString& property)
+{
+    // if we have a cache, find out if anything need to be done at all
+    if (m_cache && copyrightInfo(property).isNull())
+    {
+        return;
+    }
+
+    CoreDbAccess().db()->removeItemCopyrightProperties(m_id, property);
+}
 
-        auto firstDigit = std::find_if(filename.begin(), filename.end(),
-                                            [](const QChar& c)
-                                            {
-                                                return c.isDigit();
-                                            });
-
-        prefix = filename.leftRef(std::distance(filename.begin(), firstDigit));
-
-        if (firstDigit == filename.end())
-        {
-            return;
-        }
-
-        auto lastDigit = std::find_if(firstDigit, filename.end(),
-                                            [](const QChar& c)
-                                            {
-                                                return !c.isDigit();
-                                            });
+void ItemCopyright::removeLanguageProperty(const QString& property, const QString& languageCode)
+{
+    if (m_cache && copyrightInfo(property).isNull())
+    {
+        return;
+    }
+
+    CoreDbAccess().db()->removeItemCopyrightProperties(m_id, property, languageCode);
+}
+
+int ItemCopyright::languageMatch(const QList<CopyrightInfo> infos, const QString& languageCode) const
+{
+    QString langCode;
+    QString fullCode = languageCode;
+
+    if (languageCode.isNull())
+    {
+        // find local language
 
-        value  = filename.midRef(prefix.size(),
-                                 std::distance(firstDigit,
-                                               lastDigit)).toULongLong(&containsValue);
-
-        suffix = filename.midRef(std::distance(lastDigit, filename.end()));
-    }
-
-    bool directlyPreceeds(NumberInFilenameMatch const& other) const
-    {
-        if (!containsValue || !other.containsValue)
-        {
-            return false;
-        }
+        QString spec     = QLocale().name().toLower();
+        QString langCode = spec.left(spec.indexOf(QLatin1Char('_'))) + QLatin1Char('-');
+        QString fullCode = spec.replace(QLatin1Char('_'), QLatin1Char('-'));
+    }
+    else if (languageCode == QLatin1String("x-default"))
+    {
+        langCode = languageCode;
+    }
+    else
+    {
+        // en-us => en-
+        langCode = languageCode.section(QLatin1Char('-'), 0, 0, QString::SectionIncludeTrailingSep);
+    }
 
-        if (prefix != other.prefix)
-        {
-            return false;
-        }
-
-        if (suffix != other.suffix)
-        {
-            return false;
-        }
-
-        return value+1 == other.value;
+    int fullCodeMatch, langCodeMatch, defaultCodeMatch, firstMatch;
+    fullCodeMatch    = -1;
+    langCodeMatch    = -1;
+    defaultCodeMatch = -1;
+    firstMatch       = -1;
+
+    (void)firstMatch; // Remove clang warning.
+
+    if (infos.isEmpty())
+    {
+        return -1;
     }
-
-    qulonglong value;
-    QStringRef prefix;
-    QStringRef suffix;
-    bool containsValue;
-};
-
-bool imageMatchesTimelapseGroup(const ItemInfoList& group, const ItemInfo& itemInfo)
-{
-    if (group.size() < 2)
-    {
-        return true;
-    }
-
-    auto const timeBetweenPhotos      = qAbs(group.first().dateTime()
-                                                          .secsTo(group.last()
-                                                          .dateTime())) / (group.size()-1);
-
-    auto const predictedNextTimestamp = group.last().dateTime()
-                                                    .addSecs(timeBetweenPhotos);
-
-    return (qAbs(itemInfo.dateTime().secsTo(predictedNextTimestamp)) <= 1);
-}
-
-} // namespace
-
-void ImageViewUtilities::createGroupByTimelapseFromInfoList(const ItemInfoList& itemInfoList)
-{
-    if (itemInfoList.size() < 3)
-    {
-        return;
-    }
+    else
+    {
+        firstMatch = 0; // index of first entry - at least we have one
+    }
+
+    // First we search for a full match
+    // Second for a match of the language code
+    // Third for the default code
+    // Fourth we return the first comment
+
+    QLatin1String defaultCode("x-default");
+
+    for (int i = 0 ; i < infos.size() ; ++i)
+    {
+        const CopyrightInfo& info = infos.at(i);
+
+        if (info.extraValue == fullCode)
+        {
+            fullCodeMatch = i;
+            break;
+        }
+        else if (info.extraValue.startsWith(langCode) && langCodeMatch == -1)
+        {
+            langCodeMatch = i;
+        }
+        else if (info.extraValue == defaultCode)
+        {
+            defaultCodeMatch = i;
+        }
+    }
+
+    int chosen = fullCodeMatch;
 
-    ItemInfoList groupingList = itemInfoList;
-
-    std::stable_sort(groupingList.begin(), groupingList.end(), lowerThanByNameForItemInfo);
-
-    NumberInFilenameMatch previousNumberMatch;
-    ItemInfoList group;
-
-    for (const auto& itemInfo : groupingList)
-    {
-        NumberInFilenameMatch numberMatch(itemInfo.name());
-
-        // if this is an end of currently processed group
-        if (!previousNumberMatch.directlyPreceeds(numberMatch) || !imageMatchesTimelapseGroup(group, itemInfo))
-        {
-            if (group.size() > 2)
-            {
-                FileActionMngr::instance()->addToGroup(group.takeFirst(), group);
-            }
-
-            group.clear();
-        }
-
-        group.append(itemInfo);
-        previousNumberMatch = std::move(numberMatch);
-    }
-
-    if (group.size() > 2)
-    {
-        FileActionMngr::instance()->addToGroup(group.takeFirst(), group);
-    }
-}
-
-} // namespace Digikam
+    if (chosen == -1)
+    {
+        chosen = langCodeMatch;
+    }
+
+    if (chosen == -1)
+    {
+        chosen = defaultCodeMatch;
+    }
+
+    if (chosen == -1)
+    {
+        chosen = firstMatch;
+    }
+
+    return chosen;
+}
+
+} // namespace Digikam
 
diff --git a/static/reports/cppcheck/master/1.html b/static/reports/cppcheck/master/1.html index 172f9ee3e..f128eae1f 100644 --- a/static/reports/cppcheck/master/1.html +++ b/static/reports/cppcheck/master/1.html @@ -1,1299 +1,717 @@ - Cppcheck - HTML report - digiKam-master-rev-74ed235f83 + Cppcheck - HTML report - digiKam-master-rev-a04a0335ac
  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
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-551
-552
-553
-554
-555
-556
-557
-558
-559
-560
-561
-562
-563
-564
-565
-566
-567
-568
-569
-570
-571
-572
-573
-574
-575
-576
-577
-578
-579
/* ============================================================
+288
/* ============================================================
  *
  * This file is a part of digiKam project
  * http://www.digikam.org
  *
- * Date        : 2008-05-12
- * Description : Access to copy-right info of an item in the database
+ * Date        : 2007-06-21
+ * Description : Shared data with reference counting and explicit sharing
  *
- * Copyright (C) 2008-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
- * Copyright (C) 2009-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 1992-2006 Trolltech ASA.
+ * Copyright (C) 2007-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
  * Public License as published by the Free Software Foundation;
  * either version 2, or (at your option)
  * any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * ============================================================ */
 
-#include "itemcopyright.h"
-
-// Qt includes
-
-#include <QLocale>
-
-// Local includes
-
-#include "coredb.h"
-#include "coredbaccess.h"
-#include "itemscanner.h"
-#include "template.h"
-
-namespace Digikam
-{
-
-class Q_DECL_HIDDEN ItemCopyrightCache
-{
-public:
-
-    explicit ItemCopyrightCache(ItemCopyright* const object)
-        : object(object)
-    {
-        // set this as cache
-        object->m_cache = this;
-        // read all properties
-        infos = CoreDbAccess().db()->getItemCopyright(object->m_id, QString());
+#ifndef DIGIKAM_DSHARED_DATA_H
+#define DIGIKAM_DSHARED_DATA_H
+
+// Qt includes
+
+#include <QtGlobal>
+
+// Local includes
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class DIGIKAM_EXPORT DSharedData
+{
+    /**
+     * Classes that are used with a DSharedDataPointer shall inherit from
+     * this class.
+     */
+public:
+
+    QAtomicInt ref;
+
+    inline DSharedData()
+        : ref(0)
+    {
     }
 
-    ~ItemCopyrightCache()
-    {
-        object->m_cache = 0;
+    inline DSharedData(const DSharedData&)
+        : ref(0)
+    {
     }
 
-    QList<CopyrightInfo> infos;
-
-private:
-
-    ItemCopyright* object;
-};
-
-// -------------------------------------------------------------------------------------------
+    /**
+     * Returns true if the reference count is not 0.
+     * For the normal use case, you do not need this method.
+     */
+    inline bool isReferenced() const
+    {
+        return (int)ref > 0;
+    }
 
-ItemCopyright::ItemCopyright(qlonglong imageid)
-    : m_id(imageid),
-      m_cache(0)
-{
-}
-
-ItemCopyright::ItemCopyright()
-    : m_id(0),
-      m_cache(0)
-{
-}
+    inline bool hasMoreReferences() const
+    {
+        return (int)ref != 1;
+    }
+
+private:
+    // using the assignment operator would lead to corruption in the ref-counting
+    DSharedData& operator=(const DSharedData&);
+};
+
+// --------------------------------------------------------------------------------------
 
-ItemCopyright::ItemCopyright(const ItemCopyright& other)
-    : m_id(other.m_id),
-      m_cache(0)
-{
-    // the cache is only short-lived, to keep complexity low
-}
-
-ItemCopyright::~ItemCopyright()
-{
-    delete m_cache;
-    m_cache = 0;
-}
-
-ItemCopyright& ItemCopyright::operator=(const ItemCopyright& other)
-{
-    delete m_cache;
-    m_cache = 0;
-
-    m_id = other.m_id;
-    return *this;
-}
-
-void ItemCopyright::replaceFrom(const ItemCopyright& source)
-{
-    if (!m_id)
-    {
-        return;
-    }
-
-    CoreDbAccess access;
-    access.db()->removeItemCopyrightProperties(m_id);
-
-    if (!source.m_id)
-    {
-        return;
-    }
-
-    QList<CopyrightInfo> infos = access.db()->getItemCopyright(source.m_id, QString());
-
-    foreach (const CopyrightInfo& info, infos)
-    {
-        access.db()->setItemCopyrightProperty(m_id, info.property, info.value,
-                                               info.extraValue, CoreDB::PropertyNoConstraint);
-    }
-}
-
-QStringList ItemCopyright::creator() const
-{
-    QList<CopyrightInfo> infos = copyrightInfos(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator));
-    QStringList list;
-
-    foreach (const CopyrightInfo& info, infos)
-    {
-        list << info.value;
-    }
-
-    return list;
-}
-
-void ItemCopyright::setCreator(const QString& creator, ReplaceMode mode)
-{
-    CoreDB::CopyrightPropertyUnique uniqueness;
+template <class T> class DSharedDataPointer
+{
+
+public:
+
+    /**
+     * Use this class to store pointers to a shared data object, which
+     * inherits DSharedData.
+     * This class is inspired by QSharedDataPointer, but differs in two points:
+     * - it provides "explicit sharing": A change to the data affects all classes
+     *   keeping a pointer to the shared data. No automatic copying is done.
+     * - no method "detach()" is provided, acknowledging the fact that the
+     *   copy constructor of class T may not be used.
+     */
+
+    /**
+     * Various operators for accessing the pointer const and non-const
+     */
+    inline T& operator*()
+    {
+        return *d;
+    }
+
+    inline const T& operator*() const
+    {
+        return *d;
+    }
+
+    inline T* operator->()
+    {
+        return d;
+    }
+
+    inline const T* operator->() const
+    {
+        return d;
+    }
+
+    inline operator T* ()
+    {
+        return d;
+    }
+
+    inline operator const T* () const
+    {
+        return d;
+    }
+
+    inline T* data()
+    {
+        return d;
+    }
+
+    inline const T* data() const
+    {
+        return d;
+    }
+
+    inline const T* constData() const
+    {
+        return d;
+    }
 
-    if (mode == ReplaceAllEntries)
-    {
-        uniqueness = CoreDB::PropertyUnique;
-    }
-    else
-    {
-        uniqueness = CoreDB::PropertyNoConstraint;
-    }
-
-    CoreDbAccess().db()->setItemCopyrightProperty(m_id, ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator),
-                                                   creator, QString(), uniqueness);
-}
-
-void ItemCopyright::removeCreators()
-{
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator));
-}
-
-QString ItemCopyright::provider() const
-{
-    return readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider));
-}
-
-void ItemCopyright::setProvider(const QString& provider)
-{
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider), provider);
-}
-
-void ItemCopyright::removeProvider()
-{
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider));
-}
-
-QString ItemCopyright::copyrightNotice(const QString& languageCode)
-{
-    return readLanguageProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice), languageCode);
-}
-
-MetaEngine::AltLangMap ItemCopyright::allCopyrightNotices()
-{
-    return readLanguageProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice));
-}
+    /**
+     * This method carries out a const_cast, so it returns a non-const pointer
+     * from a const DSharedDataPointer.
+     * Typically, this should only be used if you know it should be used
+     * (to implement a lazy loading caching technique or similar)
+     */
+    inline T* constCastData() const
+    {
+        return const_cast<T*>(d);
+    }
+
+    inline bool operator==(const DSharedDataPointer<T>& other) const
+    {
+        return d == other.d;
+    }
+
+    inline bool operator!=(const DSharedDataPointer<T>& other) const
+    {
+        return d != other.d;
+    }
+
+    inline DSharedDataPointer()
+    {
+        d = 0;
+    }
+
+    explicit inline DSharedDataPointer(T* const data)
+        : d(data)
+    {
+        if (d)
+        {
+            d->ref.ref();
+        }
+    }
+
+    inline ~DSharedDataPointer()
+    {
+        if (d && !d->ref.deref())
+        {
+            delete d;
+        }
+    }
 
-void ItemCopyright::setCopyrightNotice(const QString& notice, const QString& languageCode, ReplaceMode mode)
-{
-    setLanguageProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice), notice, languageCode, mode);
-}
-
-void ItemCopyright::removeCopyrightNotices()
-{
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice));
-}
-
-QString ItemCopyright::rightsUsageTerms(const QString& languageCode)
-{
-    return readLanguageProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms), languageCode);
-}
+    inline DSharedDataPointer(const DSharedDataPointer<T>& o)
+        : d(o.d)
+    {
+        if (d)
+        {
+            d->ref.ref();
+        }
+    }
+
+    inline DSharedDataPointer<T>& operator=(const DSharedDataPointer<T>& o)<--- Member variable 'DSharedDataPointer::d' is not assigned a value in 'DSharedDataPointer::operator='.
+    {
+        delete assign(o);
+        return *this;
+    }
 
-MetaEngine::AltLangMap ItemCopyright::allRightsUsageTerms()
-{
-    return readLanguageProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms));
-}
-
-void ItemCopyright::setRightsUsageTerms(const QString& term, const QString& languageCode, ReplaceMode mode)
-{
-    setLanguageProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms), term, languageCode, mode);
-}
-
-void ItemCopyright::removeRightsUsageTerms()
-{
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms));
-}
-
-QString ItemCopyright::source()
-{
-    return readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource));
-}
-
-void ItemCopyright::setSource(const QString& source)
-{
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource), source);
-}
+    inline DSharedDataPointer& operator=(T* const o)
+    {
+        delete assign(o);
+        return *this;
+    }
+
+    /**
+     * The assign operator is like operator=,
+     * with the difference that the old pointer is not deleted
+     * if its reference count is 0, but returned.
+     * Use this if you need to do your own deleting, if e.g.
+     * the object need to be removed from a list or a cache.
+     * @returns A T object with reference count 0, which may be deleted;
+     *          or 0 if no object need to be dropped.
+     */
+    inline T* assign(const DSharedDataPointer<T>& o)
+    {
+        if (o.d != d)
+        {
+            // reference new value
+            if (o.d)
+            {
+                o.d->ref.ref();
+            }
 
-void ItemCopyright::removeSource()
-{
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource));
-}
+            // store old value
+            T* x = d;
+            // assign new value
+            d    = o.d;
 
-QString ItemCopyright::creatorJobTitle() const
-{
-    return readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle));
-}
-
-void ItemCopyright::setCreatorJobTitle(const QString& title)
-{
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle), title);
-}
-
-void ItemCopyright::removeCreatorJobTitle()
-{
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle));
-}
-
-QString ItemCopyright::instructions()
-{
-    return readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions));
-}
-
-void ItemCopyright::setInstructions(const QString& instructions)
-{
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions), instructions);
-}
-
-void ItemCopyright::removeInstructions()
-{
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions));
-}
-
-IptcCoreContactInfo ItemCopyright::contactInfo()
-{
-    IptcCoreContactInfo info;
-    info.city          = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity));
-    info.country       = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry));
-    info.address       = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress));
-    info.postalCode    = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode));
-    info.provinceState = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState));
-    info.email         = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail));
-    info.phone         = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone));
-    info.webUrl        = readSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl));
-
-    return info;
-}
+            // dereference old value,
+            // return value and ownership if dereferenced
+            if (x && !x->ref.deref())
+            {
+                return x;
+            }
+        }
+
+        return 0;
+    }
+
+    inline T* assign(T* const o)
+    {
+        if (o != d)
+        {
+            // reference new value
+            if (o)
+            {
+                o->ref.ref();
+            }
+
+            // store old value
+            T* x = d;
+            // assign new value
+            d    = o;
+
+            // dereference old value,
+            // return value and ownership if dereferenced
+            if (x && !x->ref.deref())
+            {
+                return x;
+            }
+        }
+
+        return 0;
+    }
+
+    /**
+     * Semantics like assign, but no new pointer is assigned to this.
+     */
+    inline T* unassign()
+    {
+        return assign(0);
+    }
 
-void ItemCopyright::setContactInfo(const IptcCoreContactInfo& info)
-{
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity), info.city);
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry), info.country);
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress), info.address);
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode), info.postalCode);
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState), info.provinceState);
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail), info.email);
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone), info.phone);
-    setSimpleProperty(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl), info.webUrl);
-}
+    inline bool operator!() const
+    {
+        return !d;
+    }
+
+private:
+
+    T* d;
+};
+
+} // namespace Digikam
 
-void ItemCopyright::removeContactInfo()
-{
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity));
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry));
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress));
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode));
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState));
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail));
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone));
-    removeProperties(ItemScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl));
-}
-
-void ItemCopyright::fillTemplate(Template& t)
-{
-    ItemCopyrightCache cache(this);
-
-    t.setAuthors(author());
-    t.setAuthorsPosition(authorsPosition());
-    t.setCredit(credit());
-    t.setCopyright(allCopyrightNotices());
-    t.setRightUsageTerms(allRightsUsageTerms());
-    t.setSource(source());
-    t.setInstructions(instructions());
-    t.setContactInfo(contactInfo());
-}
-
-void ItemCopyright::setFromTemplate(const Template& t)
-{
-    foreach (const QString& author, t.authors()) // krazy:exclude=foreach
-    {
-        setAuthor(author, ItemCopyright::AddEntryToExisting);
-    }
-
-    setCredit(t.credit());
-
-    MetaEngine::AltLangMap copyrights = t.copyright();
-    MetaEngine::AltLangMap::const_iterator it;
-
-    for (it = copyrights.constBegin() ; it != copyrights.constEnd() ; ++it)
-    {
-        setRights(it.value(), it.key(), ItemCopyright::AddEntryToExisting);
-    }
-
-    MetaEngine::AltLangMap usages = t.rightUsageTerms();
-    MetaEngine::AltLangMap::const_iterator it2;
-
-    for (it2 = usages.constBegin() ; it2 != usages.constEnd() ; ++it2)
-    {
-        setRightsUsageTerms(it2.value(), it2.key(), ItemCopyright::AddEntryToExisting);
-    }
-
-    setSource(t.source());
-    setAuthorsPosition(t.authorsPosition());
-    setInstructions(t.instructions());
-    setContactInfo(t.contactInfo());
-}
-
-void ItemCopyright::removeAll()
-{
-    ItemCopyrightCache cache(this);
-
-    removeCreators();
-    removeProvider();
-    removeCopyrightNotices();
-    removeRightsUsageTerms();
-    removeSource();
-    removeCreatorJobTitle();
-    removeInstructions();
-    removeContactInfo();
-}
-
-CopyrightInfo ItemCopyright::copyrightInfo(const QString& property) const
-{
-    if (m_cache)
-    {
-        foreach (const CopyrightInfo& info, m_cache->infos)
-        {
-            if (info.property == property)
-            {
-                return info;
-            }
-        }
-    }
-    else
-    {
-        QList<CopyrightInfo> infos = CoreDbAccess().db()->getItemCopyright(m_id, property);
-
-        if (!infos.isEmpty())
-        {
-            return infos.first();
-        }
-    }
-
-    return CopyrightInfo();
-}
-
-QList<CopyrightInfo> ItemCopyright::copyrightInfos(const QString& property) const
-{
-    if (m_cache)
-    {
-        QList<CopyrightInfo> infos;
-
-        foreach (const CopyrightInfo& info, m_cache->infos)
-        {
-            if (info.property == property)
-            {
-                infos << info;
-            }
-        }
-
-        return infos;
-    }
-    else
-    {
-        return CoreDbAccess().db()->getItemCopyright(m_id, property);
-    }
-}
-
-QString ItemCopyright::readSimpleProperty(const QString& property) const
-{
-    return copyrightInfo(property).value;
-}
-
-void ItemCopyright::setSimpleProperty(const QString& property, const QString& value)
-{
-    CoreDbAccess().db()->setItemCopyrightProperty(m_id, property, value, QString(), CoreDB::PropertyUnique);
-}
-
-QString ItemCopyright::readLanguageProperty(const QString& property, const QString& languageCode)
-{
-    QList<CopyrightInfo> infos = copyrightInfos(property);
-    int index                  = languageMatch(infos, languageCode);
-
-    if (index == -1)
-    {
-        return QString();
-    }
-    else
-    {
-        return infos.at(index).value;
-    }
-}
-
-MetaEngine::AltLangMap ItemCopyright::readLanguageProperties(const QString& property)
-{
-    MetaEngine::AltLangMap map;
-    QList<CopyrightInfo> infos = copyrightInfos(property);
-
-    foreach (const CopyrightInfo& info, infos)
-    {
-        map[info.extraValue] = info.value;
-    }
-
-    return map;
-}
-
-void ItemCopyright::setLanguageProperty(const QString& property, const QString& value,
-                                         const QString& languageCode, ReplaceMode mode)
-{
-    CoreDB::CopyrightPropertyUnique uniqueness;
-
-    if (mode == ReplaceAllEntries)
-    {
-        uniqueness = CoreDB::PropertyUnique;
-    }
-    else if (mode == ReplaceLanguageEntry)
-    {
-        uniqueness = CoreDB::PropertyExtraValueUnique;
-    }
-    else
-    {
-        uniqueness = CoreDB::PropertyNoConstraint;
-    }
-
-    QString language = languageCode;
-
-    if (language.isNull())
-    {
-        language = QLatin1String("x-default");
-    }
-
-    CoreDbAccess().db()->setItemCopyrightProperty(m_id, property, value, language, uniqueness);
-}
-
-void ItemCopyright::removeProperties(const QString& property)
-{
-    // if we have a cache, find out if anything need to be done at all
-    if (m_cache && copyrightInfo(property).isNull())
-    {
-        return;
-    }
-
-    CoreDbAccess().db()->removeItemCopyrightProperties(m_id, property);
-}
-
-void ItemCopyright::removeLanguageProperty(const QString& property, const QString& languageCode)
-{
-    if (m_cache && copyrightInfo(property).isNull())
-    {
-        return;
-    }
-
-    CoreDbAccess().db()->removeItemCopyrightProperties(m_id, property, languageCode);
-}
-
-int ItemCopyright::languageMatch(const QList<CopyrightInfo> infos, const QString& languageCode) const
-{
-    QString langCode;
-    QString fullCode = languageCode;
-
-    if (languageCode.isNull())
-    {
-        // find local language
-
-        QString spec     = QLocale().name().toLower();
-        QString langCode = spec.left(spec.indexOf(QLatin1Char('_'))) + QLatin1Char('-');
-        QString fullCode = spec.replace(QLatin1Char('_'), QLatin1Char('-'));
-    }
-    else if (languageCode == QLatin1String("x-default"))
-    {
-        langCode = languageCode;
-    }
-    else
-    {
-        // en-us => en-
-        langCode = languageCode.section(QLatin1Char('-'), 0, 0, QString::SectionIncludeTrailingSep);
-    }
-
-    int fullCodeMatch, langCodeMatch, defaultCodeMatch, firstMatch;
-    fullCodeMatch    = -1;
-    langCodeMatch    = -1;
-    defaultCodeMatch = -1;
-    firstMatch       = -1;
-
-    (void)firstMatch; // Remove clang warning.
-
-    if (infos.isEmpty())
-    {
-        return -1;
-    }
-    else
-    {
-        firstMatch = 0; // index of first entry - at least we have one
-    }
-
-    // First we search for a full match
-    // Second for a match of the language code
-    // Third for the default code
-    // Fourth we return the first comment
-
-    QLatin1String defaultCode("x-default");
-
-    for (int i = 0 ; i < infos.size() ; ++i)
-    {
-        const CopyrightInfo& info = infos.at(i);
-
-        if (info.extraValue == fullCode)
-        {
-            fullCodeMatch = i;
-            break;
-        }
-        else if (info.extraValue.startsWith(langCode) && langCodeMatch == -1)
-        {
-            langCodeMatch = i;
-        }
-        else if (info.extraValue == defaultCode)
-        {
-            defaultCodeMatch = i;
-        }
-    }
-
-    int chosen = fullCodeMatch;
-
-    if (chosen == -1)
-    {
-        chosen = langCodeMatch;
-    }
-
-    if (chosen == -1)
-    {
-        chosen = defaultCodeMatch;
-    }
-
-    if (chosen == -1)
-    {
-        chosen = firstMatch;
-    }
-
-    return chosen;
-}
-
-} // namespace Digikam
+#endif // DIGIKAM_DSHARED_DATA_H
 
diff --git a/static/reports/cppcheck/master/2.html b/static/reports/cppcheck/master/2.html index e5e6a6b24..d53e74f5b 100644 --- a/static/reports/cppcheck/master/2.html +++ b/static/reports/cppcheck/master/2.html @@ -1,717 +1,1869 @@ - Cppcheck - HTML report - digiKam-master-rev-74ed235f83 + Cppcheck - HTML report - digiKam-master-rev-a04a0335ac
  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
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
-288
/* ============================================================
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
/* ============================================================
  *
  * This file is a part of digiKam project
  * http://www.digikam.org
  *
- * Date        : 2007-06-21
- * Description : Shared data with reference counting and explicit sharing
+ * Date        : 2015-08-17
+ * Description : Helper class for Image Description Editor Tab
  *
- * Copyright (C) 1992-2006 Trolltech ASA.
- * Copyright (C) 2007-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2015 by Veaceslav Munteanu <veaceslav dot munteanu90 at gmail dot com>
+
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
  * Public License as published by the Free Software Foundation;
  * either version 2, or (at your option)
  * any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * ============================================================ */
 
-#ifndef DIGIKAM_DSHARED_DATA_H
-#define DIGIKAM_DSHARED_DATA_H
-
-// Qt includes
-
-#include <QtGlobal>
-
-// Local includes
-
-#include "digikam_export.h"
-
-namespace Digikam
-{
-
-class DIGIKAM_EXPORT DSharedData
-{
-    /**
-     * Classes that are used with a DSharedDataPointer shall inherit from
-     * this class.
-     */
-public:
+#include "disjointmetadata.h"
+
+// Qt includes
+
+#include <QMap>
+#include <QStringList>
+#include <QDateTime>
+#include <QMutexLocker>
+#include <QtAlgorithms>
+
+// Local includes
+
+#include "captionvalues.h"
+#include "template.h"
+#include "templatemanager.h"
+#include "tagscache.h"
+#include "coredbaccess.h"
+#include "itemcomments.h"
+#include "iteminfo.h"
+#include "coredbwatch.h"
+#include "metadatahub.h"
 
-    QAtomicInt ref;
-
-    inline DSharedData()
-        : ref(0)
-    {
-    }
-
-    inline DSharedData(const DSharedData&)
-        : ref(0)
-    {
-    }
-
-    /**
-     * Returns true if the reference count is not 0.
-     * For the normal use case, you do not need this method.
-     */
-    inline bool isReferenced() const
-    {
-        return (int)ref > 0;
-    }
-
-    inline bool hasMoreReferences() const
-    {
-        return (int)ref != 1;
-    }
-
-private:
-    // using the assignment operator would lead to corruption in the ref-counting
-    DSharedData& operator=(const DSharedData&);
-};
-
-// --------------------------------------------------------------------------------------
-
-template <class T> class DSharedDataPointer
-{
-
-public:
-
-    /**
-     * Use this class to store pointers to a shared data object, which
-     * inherits DSharedData.
-     * This class is inspired by QSharedDataPointer, but differs in two points:
-     * - it provides "explicit sharing": A change to the data affects all classes
-     *   keeping a pointer to the shared data. No automatic copying is done.
-     * - no method "detach()" is provided, acknowledging the fact that the
-     *   copy constructor of class T may not be used.
-     */
-
-    /**
-     * Various operators for accessing the pointer const and non-const
-     */
-    inline T& operator*()
-    {
-        return *d;
-    }
-
-    inline const T& operator*() const
-    {
-        return *d;
-    }
+namespace Digikam
+{
+
+// This class was split from Private to be able to use the automatic C++ copy constructor
+// (Private contains a QMutex and is thus non-copyable)
+class Q_DECL_HIDDEN DisjointMetadataDataFields
+{
+public:
+
+    DisjointMetadataDataFields()
+        : dateTimeChanged  (false),
+          titlesChanged(false),
+          commentsChanged(false),
+          pickLabelChanged(false),
+          colorLabelChanged(false),
+          ratingChanged(false),
+          templateChanged(false),
+          tagsChanged(false),
+          withoutTags(false),
+          pickLabel(-1),
+          highestPickLabel(-1),
+          colorLabel(-1),
+          highestColorLabel(-1),
+          rating(-1),
+          highestRating(-1),
+          count(0),
+          dateTimeStatus(DisjointMetadata::MetadataInvalid),
+          titlesStatus(DisjointMetadata::MetadataInvalid),
+          commentsStatus(DisjointMetadata::MetadataInvalid),
+          pickLabelStatus(DisjointMetadata::MetadataInvalid),
+          colorLabelStatus(DisjointMetadata::MetadataInvalid),
+          ratingStatus(DisjointMetadata::MetadataInvalid),
+          templateStatus(DisjointMetadata::MetadataInvalid),
+          invalid(false)
+    {
+    }
+
+    bool                                dateTimeChanged;
+    bool                                titlesChanged;
+    bool                                commentsChanged;
+    bool                                pickLabelChanged;
+    bool                                colorLabelChanged;
+    bool                                ratingChanged;
+    bool                                templateChanged;
+    bool                                tagsChanged;
+    bool                                withoutTags;
+
+    int                                 pickLabel;
+    int                                 highestPickLabel;
+    int                                 colorLabel;
+    int                                 highestColorLabel;
+    int                                 rating;
+    int                                 highestRating;
+    int                                 count;
+
+    QDateTime                           dateTime;
+    QDateTime                           lastDateTime;
+
+    CaptionsMap                         titles;
+    CaptionsMap                         comments;
 
-    inline T* operator->()
-    {
-        return d;
-    }
-
-    inline const T* operator->() const
-    {
-        return d;
-    }
-
-    inline operator T* ()
-    {
-        return d;
-    }
-
-    inline operator const T* () const
-    {
-        return d;
-    }
+    Template                            metadataTemplate;
+
+    QMap<int, DisjointMetadata::Status> tags;
+
+    QStringList                         tagList;
+
+    QMultiMap<QString, QVariant>        faceTagsList;
+
+    DisjointMetadata::Status            dateTimeStatus;
+    DisjointMetadata::Status            titlesStatus;
+    DisjointMetadata::Status            commentsStatus;
+    DisjointMetadata::Status            pickLabelStatus;
+    DisjointMetadata::Status            colorLabelStatus;
+    DisjointMetadata::Status            ratingStatus;
+    DisjointMetadata::Status            templateStatus;
+
+    QList<int>                          tagIds;
+    bool                                invalid;
+};
 
-    inline T* data()
-    {
-        return d;
-    }
-
-    inline const T* data() const
-    {
-        return d;
-    }
-
-    inline const T* constData() const
+class Q_DECL_HIDDEN DisjointMetadata::Private : public DisjointMetadataDataFields
+{
+public:
+
+    explicit Private()
+    {
+    }
+
+    // use the automatic copy constructor
+    explicit Private(const Private& other)
+        : DisjointMetadataDataFields(other)
     {
-        return d;
-    }
-
-    /**
-     * This method carries out a const_cast, so it returns a non-const pointer
-     * from a const DSharedDataPointer.
-     * Typically, this should only be used if you know it should be used
-     * (to implement a lazy loading caching technique or similar)
-     */
-    inline T* constCastData() const
-    {
-        return const_cast<T*>(d);
-    }
-
-    inline bool operator==(const DSharedDataPointer<T>& other) const
-    {
-        return d == other.d;
-    }
-
-    inline bool operator!=(const DSharedDataPointer<T>& other) const
-    {
-        return d != other.d;
-    }
-
-    inline DSharedDataPointer()
-    {
-        d = 0;
-    }
+    }
+
+    QMutex mutex;
+
+public:
+
+    template <class T> void loadSingleValue(const T& data,
+                                            T& storage,
+                                            DisjointMetadata::Status& status);
+    void makeConnections(DisjointMetadata* q);
+};
+
+void DisjointMetadata::Private::makeConnections(DisjointMetadata *q)
+{
+    QObject::connect(TagsCache::instance(), SIGNAL(tagDeleted(int)),
+                     q, SLOT(slotTagDeleted(int)),
+                     Qt::DirectConnection);
+
+    QObject::connect(CoreDbAccess::databaseWatch(), SIGNAL(databaseChanged()),
+                     q, SLOT(slotInvalidate()));
+}
+
+DisjointMetadata::DisjointMetadata(QObject *parent)
+    : QObject(parent),
+      d(new Private())
+{
+    d->makeConnections(this);
+}
 
-    explicit inline DSharedDataPointer(T* const data)
-        : d(data)
-    {
-        if (d)
-        {
-            d->ref.ref();
-        }
-    }
-
-    inline ~DSharedDataPointer()
-    {
-        if (d && !d->ref.deref())
-        {
-            delete d;
-        }
-    }
-
-    inline DSharedDataPointer(const DSharedDataPointer<T>& o)
-        : d(o.d)
-    {
-        if (d)
-        {
-            d->ref.ref();
-        }
-    }
-
-    inline DSharedDataPointer<T>& operator=(const DSharedDataPointer<T>& o)<--- Member variable 'DSharedDataPointer::d' is not assigned a value in 'DSharedDataPointer::operator='.
-    {
-        delete assign(o);
-        return *this;
-    }
-
-    inline DSharedDataPointer& operator=(T* const o)
-    {
-        delete assign(o);
-        return *this;
-    }
-
-    /**
-     * The assign operator is like operator=,
-     * with the difference that the old pointer is not deleted
-     * if its reference count is 0, but returned.
-     * Use this if you need to do your own deleting, if e.g.
-     * the object need to be removed from a list or a cache.
-     * @returns A T object with reference count 0, which may be deleted;
-     *          or 0 if no object need to be dropped.
-     */
-    inline T* assign(const DSharedDataPointer<T>& o)
-    {
-        if (o.d != d)
-        {
-            // reference new value
-            if (o.d)
-            {
-                o.d->ref.ref();
-            }
-
-            // store old value
-            T* x = d;
-            // assign new value
-            d    = o.d;
-
-            // dereference old value,
-            // return value and ownership if dereferenced
-            if (x && !x->ref.deref())
-            {
-                return x;
-            }
-        }
-
-        return 0;
-    }
-
-    inline T* assign(T* const o)
-    {
-        if (o != d)
-        {
-            // reference new value
-            if (o)
-            {
-                o->ref.ref();
-            }
-
-            // store old value
-            T* x = d;
-            // assign new value
-            d    = o;
-
-            // dereference old value,
-            // return value and ownership if dereferenced
-            if (x && !x->ref.deref())
-            {
-                return x;
-            }
-        }
-
-        return 0;
-    }
+DisjointMetadata::DisjointMetadata(const DisjointMetadata& other)
+    : QObject(other.parent()),
+      d(new Private(*other.d))
+{
+    d->makeConnections(this);
+}
+
+DisjointMetadata::~DisjointMetadata()
+{
+    delete d;
+}
+
+DisjointMetadata& DisjointMetadata::operator=(const DisjointMetadata& other)
+{
+    delete d;
+    d = new Private(*other.d);
+    return *this;
+}
+
+void DisjointMetadata::reset()
+{
+    delete d;
+    d =  new Private();
+}
+
+void DisjointMetadata::load(const ItemInfo& info)
+{
+    CaptionsMap commentMap;
+    CaptionsMap titleMap;
+
+    {
+        CoreDbAccess access;
+        ItemComments comments = info.imageComments(access);
+        commentMap             = comments.toCaptionsMap();
+        titleMap               = comments.toCaptionsMap(DatabaseComment::Title);
+    }
+
+    Template tref = info.metadataTemplate();
+    Template t    = TemplateManager::defaultManager()->findByContents(tref);
+    //qCDebug(DIGIKAM_GENERAL_LOG) << "Found Metadata Template: " << t.templateTitle();
+
+    load(info.dateTime(),
+         titleMap,
+         commentMap,
+         info.colorLabel(),
+         info.pickLabel(),
+         info.rating(),
+         t.isNull() ? tref : t);
+
+    loadTags(info.tagIds());
+}
+
+//-----------------------------Status -------------------------
+
+DisjointMetadata::Status DisjointMetadata::dateTimeStatus() const
+{
+    return d->dateTimeStatus;
+}
+
+DisjointMetadata::Status DisjointMetadata::titlesStatus() const
+{
+    return d->titlesStatus;
+}
+
+DisjointMetadata::Status DisjointMetadata::commentsStatus() const
+{
+    return d->commentsStatus;
+}
+
+DisjointMetadata::Status DisjointMetadata::pickLabelStatus() const
+{
+    return d->pickLabelStatus;
+}
+
+DisjointMetadata::Status DisjointMetadata::colorLabelStatus() const
+{
+    return d->colorLabelStatus;
+}
+
+DisjointMetadata::Status DisjointMetadata::ratingStatus() const
+{
+    return d->ratingStatus;
+}
+
+DisjointMetadata::Status DisjointMetadata::templateStatus() const
+{
+    return d->templateStatus;
+}
+
+DisjointMetadata::Status DisjointMetadata::tagStatus(int albumId) const
+{
+    return d->tags.value(albumId, DisjointMetadata::MetadataInvalid);
+}
+
+DisjointMetadata::Status DisjointMetadata::tagStatus(const QString& tagPath) const
+{
+    return tagStatus(TagsCache::instance()->tagForPath(tagPath));
+}
 
-    /**
-     * Semantics like assign, but no new pointer is assigned to this.
-     */
-    inline T* unassign()
-    {
-        return assign(0);
-    }
-
-    inline bool operator!() const
-    {
-        return !d;
-    }
-
-private:
-
-    T* d;
-};
-
-} // namespace Digikam
-
-#endif // DIGIKAM_DSHARED_DATA_H
+//---- Changed status ---------------------
+
+bool DisjointMetadata::dateTimeChanged() const
+{
+    return d->dateTimeChanged;
+}
+
+bool DisjointMetadata::titlesChanged() const
+{
+    return d->titlesChanged;
+}
+
+bool DisjointMetadata::commentsChanged() const
+{
+    return d->commentsChanged;
+}
+
+bool DisjointMetadata::pickLabelChanged() const
+{
+    return d->pickLabelChanged;
+}
+
+bool DisjointMetadata::colorLabelChanged() const
+{
+    return d->colorLabelChanged;
+}
+
+bool DisjointMetadata::ratingChanged() const
+{
+    return d->ratingChanged;
+}
+
+bool DisjointMetadata::templateChanged() const
+{
+    return d->templateChanged;
+}
+
+bool DisjointMetadata::tagsChanged() const
+{
+    return d->tagsChanged;
+}
+
+void DisjointMetadata::setDateTime(const QDateTime& dateTime, DisjointMetadata::Status status)
+{
+    d->dateTimeStatus  = status;
+    d->dateTime        = dateTime;
+    d->dateTimeChanged = true;
+}
+
+void DisjointMetadata::setTitles(const CaptionsMap& titles, DisjointMetadata::Status status)
+{
+    d->titlesStatus  = status;
+    d->titles        = titles;
+    d->titlesChanged = true;
+}
+
+void DisjointMetadata::setComments(const CaptionsMap& comments, DisjointMetadata::Status status)
+{
+    d->commentsStatus  = status;
+    d->comments        = comments;
+    d->commentsChanged = true;
+}
+
+void DisjointMetadata::setPickLabel(int pickId, DisjointMetadata::Status status)
+{
+    d->pickLabelStatus  = status;
+    d->pickLabel        = pickId;
+    d->pickLabelChanged = true;
+}
+
+void DisjointMetadata::setColorLabel(int colorId, DisjointMetadata::Status status)
+{
+    d->colorLabelStatus  = status;
+    d->colorLabel        = colorId;
+    d->colorLabelChanged = true;
+}
+
+void DisjointMetadata::setRating(int rating, DisjointMetadata::Status status)
+{
+    d->ratingStatus   = status;
+    d->rating         = rating;
+    d->ratingChanged  = true;
+}
+
+void DisjointMetadata::setMetadataTemplate(const Template& t, DisjointMetadata::Status status)
+{
+    d->templateStatus   = status;
+    d->metadataTemplate = t;
+    d->templateChanged  = true;
+}
+
+void DisjointMetadata::setTag(int albumID, DisjointMetadata::Status status)
+{
+    d->tags[albumID] = status;
+    d->tagsChanged = true;
+}
+
+void DisjointMetadata::resetChanged()
+{
+    d->dateTimeChanged   = false;
+    d->titlesChanged     = false;
+    d->commentsChanged   = false;
+    d->pickLabelChanged  = false;
+    d->colorLabelChanged = false;
+    d->ratingChanged     = false;
+    d->templateChanged   = false;
+    d->tagsChanged       = false;
+}
+
+bool DisjointMetadata::write(ItemInfo info, WriteMode writeMode)
+{
+    applyChangeNotifications();
+
+    bool changed = false;
+
+    // find out in advance if we have something to write - needed for FullWriteIfChanged mode
+    bool saveTitle      = (d->titlesStatus     == MetadataAvailable);
+    bool saveComment    = (d->commentsStatus   == MetadataAvailable);
+    bool saveDateTime   = (d->dateTimeStatus   == MetadataAvailable);
+    bool savePickLabel  = (d->pickLabelStatus  == MetadataAvailable);
+    bool saveColorLabel = (d->colorLabelStatus == MetadataAvailable);
+    bool saveRating     = (d->ratingStatus     == MetadataAvailable);
+    bool saveTemplate   = (d->templateStatus   == MetadataAvailable);
+    bool saveTags       = true;
+
+    bool writeAllFields;
+
+    if (writeMode == FullWrite)
+    {
+        writeAllFields = true;
+    }
+    else if (writeMode == FullWriteIfChanged)
+    {
+        writeAllFields = (
+                             (saveTitle      && d->titlesChanged)     ||
+                             (saveComment    && d->commentsChanged)   ||
+                             (saveDateTime   && d->dateTimeChanged)   ||
+                             (savePickLabel  && d->pickLabelChanged)  ||
+                             (saveColorLabel && d->colorLabelChanged) ||
+                             (saveRating     && d->ratingChanged)     ||
+                             (saveTemplate   && d->templateChanged)   ||
+                             (saveTags       && d->tagsChanged)
+                         );
+    }
+    else // PartialWrite
+    {
+        writeAllFields = false;
+    }
+
+    if (saveTitle && (writeAllFields || d->titlesChanged))
+    {
+        CoreDbAccess access;
+        ItemComments comments = info.imageComments(access);
+        comments.replaceComments(d->titles, DatabaseComment::Title);
+        changed                = true;
+    }
+
+    if (saveComment && (writeAllFields || d->commentsChanged))
+    {
+        CoreDbAccess access;
+        ItemComments comments = info.imageComments(access);
+        comments.replaceComments(d->comments);
+        changed                = true;
+    }
+
+    if (saveDateTime && (writeAllFields || d->dateTimeChanged))
+    {
+        info.setDateTime(d->dateTime);
+        changed = true;
+    }
+
+    if (savePickLabel && (writeAllFields || d->pickLabelChanged))
+    {
+        info.setPickLabel(d->pickLabel);
+        changed = true;
+    }
+
+    if (saveColorLabel && (writeAllFields || d->colorLabelChanged))
+    {
+        info.setColorLabel(d->colorLabel);
+        changed = true;
+    }
+
+    if (saveRating && (writeAllFields || d->ratingChanged))
+    {
+        info.setRating(d->rating);
+        changed = true;
+    }
+
+    if (saveTemplate && writeAllFields)
+    {
+        QString title = d->metadataTemplate.templateTitle();
+
+        if (title == Template::removeTemplateTitle())
+        {
+            info.removeMetadataTemplate();
+        }
+
+        if (title.isEmpty())
+        {
+            // Nothing to do.
+        }
+        else
+        {
+            info.setMetadataTemplate(d->metadataTemplate);
+        }
+
+        changed = true;
+    }
+
+    if (writeAllFields || d->tagsChanged)
+    {
+        QList<int> keys = d->tags.keys();
+
+        foreach (int key, keys)
+        {
+            if (d->tags.value(key) == DisjointMetadata::MetadataAvailable)
+            {
+                info.setTag(key);
+                changed = true;
+            }
+
+            if (d->tags.value(key) == DisjointMetadata::MetadataInvalid)
+            {
+                info.removeTag(key);
+                changed = true;
+            }
+        }
+    }
+
+    return changed;
+}
+
+bool DisjointMetadata::willWriteMetadata(DisjointMetadata::WriteMode writeMode, const MetaEngineSettingsContainer& settings) const
+{
+    // This is the same logic as in write(DMetadata) but without actually writing.
+    // Adapt if the method above changes
+    bool saveTitle      = (settings.saveComments   && d->titlesStatus     == MetadataAvailable);
+    bool saveComment    = (settings.saveComments   && d->commentsStatus   == MetadataAvailable);
+    bool saveDateTime   = (settings.saveDateTime   && d->dateTimeStatus   == MetadataAvailable);
+    bool savePickLabel  = (settings.savePickLabel  && d->pickLabelStatus  == MetadataAvailable);
+    bool saveColorLabel = (settings.saveColorLabel && d->colorLabelStatus == MetadataAvailable);
+    bool saveRating     = (settings.saveRating     && d->ratingStatus     == MetadataAvailable);
+    bool saveTemplate   = (settings.saveTemplate   && d->templateStatus   == MetadataAvailable);
+    bool saveTags       = settings.saveTags;
+
+    bool writeAllFields;
+
+    if (writeMode == FullWrite)
+    {
+        writeAllFields = true;
+    }
+    else if (writeMode == FullWriteIfChanged)
+    {
+        writeAllFields = (
+                             (saveTitle      && d->titlesChanged)     ||
+                             (saveComment    && d->commentsChanged)   ||
+                             (saveDateTime   && d->dateTimeChanged)   ||
+                             (savePickLabel  && d->pickLabelChanged)  ||
+                             (saveColorLabel && d->colorLabelChanged) ||
+                             (saveRating     && d->ratingChanged)     ||
+                             (saveTemplate   && d->templateChanged)   ||
+                             (saveTags       && d->tagsChanged)
+                         );
+    }
+    else // PartialWrite
+    {
+        writeAllFields = false;
+    }
+
+    return (
+               (saveTitle      && (writeAllFields || d->titlesChanged))     ||
+               (saveComment    && (writeAllFields || d->commentsChanged))   ||
+               (saveDateTime   && (writeAllFields || d->dateTimeChanged))   ||
+               (savePickLabel  && (writeAllFields || d->pickLabelChanged))  ||
+               (saveColorLabel && (writeAllFields || d->colorLabelChanged)) ||
+               (saveRating     && (writeAllFields || d->ratingChanged))     ||
+               (saveTags       && (writeAllFields || d->tagsChanged))       ||
+               (saveTemplate   && (writeAllFields || d->templateChanged))
+           );
+}
+
+int DisjointMetadata::changedFlags()
+{
+    int value = 0;
+
+    if (d->titlesChanged)
+        value |= MetadataHub::WRITE_TITLE;
+    if (d->commentsChanged)
+        value |= MetadataHub::WRITE_COMMENTS;
+    if (d->dateTimeChanged)
+        value |= MetadataHub::WRITE_DATETIME;
+    if (d->pickLabelChanged)
+        value |= MetadataHub::WRITE_PICKLABEL;
+    if (d->colorLabelChanged)
+        value |= MetadataHub::WRITE_COLORLABEL;
+    if (d->ratingChanged)
+        value |= MetadataHub::WRITE_RATING;
+    if (d->tagsChanged)
+        value |= MetadataHub::WRITE_TAGS;
+    if (d->templateChanged)
+        value |= MetadataHub::WRITE_TEMPLATE;
+
+    return value;
+}
+
+void DisjointMetadata::load(const QDateTime& dateTime,const CaptionsMap& titles,
+                            const CaptionsMap& comment, int colorLabel,
+                            int pickLabel, int rating, const Template& t)
+{
+    if (dateTime.isValid())
+    {
+        d->loadSingleValue<QDateTime>(dateTime, d->dateTime,d->dateTimeStatus);
+    }
+
+    d->loadSingleValue<int>(pickLabel, d->pickLabel, d->pickLabelStatus);
+
+    d->loadSingleValue<int>(colorLabel, d->colorLabel, d->colorLabelStatus);
+
+    d->loadSingleValue<int>(rating, d->rating,d->ratingStatus);
+
+    d->loadSingleValue<CaptionsMap>(titles, d->titles, d->titlesStatus);
+
+    d->loadSingleValue<CaptionsMap>(comment, d->comments, d->commentsStatus);
+
+    d->loadSingleValue<Template>(t, d->metadataTemplate, d->templateStatus);
+}
+
+void DisjointMetadata::loadTags(const QList<int>& tagIds)
+{
+    QList<int> loadedTagIds;
+
+    foreach (int tagId, tagIds)
+    {
+        if (!TagsCache::instance()->isInternalTag(tagId))
+        {
+            loadedTagIds << tagId;
+        }
+    }
+
+    if (loadedTagIds.isEmpty())
+    {
+        if (!d->withoutTags)
+        {
+            QMap<int, DisjointMetadata::Status>::iterator it;
+
+            for (it = d->tags.begin() ; it != d->tags.end() ; ++it)
+            {
+                it.value() = MetadataDisjoint;
+            }
+
+            d->withoutTags = true;
+        }
+
+        return;
+    }
+
+    // If tags map is empty, set them all as Available
+
+    if (d->tags.isEmpty())
+    {
+        foreach (int tagId, loadedTagIds)
+        {
+            if (d->withoutTags)
+            {
+                d->tags[tagId] = MetadataDisjoint;
+            }
+            else
+            {
+                d->tags[tagId] = MetadataAvailable;
+            }
+        }
+
+        return;
+    }
+
+    std::sort(loadedTagIds.begin(), loadedTagIds.end());
+    // We search for metadata available tags, and
+    // it is not present in current list, set it to
+    // disjoint
+
+    QMap<int, DisjointMetadata::Status>::iterator it;
+
+    for (it = d->tags.begin() ; it != d->tags.end() ; ++it)
+    {
+        if (it.value() == MetadataAvailable)
+        {
+            if (qBinaryFind(loadedTagIds.begin(), loadedTagIds.end(), it.key()) == loadedTagIds.end())
+            {
+                it.value() = MetadataDisjoint;
+            }
+        }
+    }
+
+    // new tags which are not yet in the set,
+    // are added as Disjoint
+    foreach (int tagId, loadedTagIds)
+    {
+        if (!d->tags.contains(tagId))
+        {
+            d->tags[tagId] = MetadataDisjoint;
+        }
+    }
+}
+
+void DisjointMetadata::notifyTagDeleted(int id)
+{
+    d->tags.remove(id);
+}
+
+void DisjointMetadata::slotTagDeleted(int tagId)
+{
+    QMutexLocker locker(&d->mutex);
+    d->tagIds << tagId;
+}
+
+void DisjointMetadata::slotInvalidate()
+{
+    QMutexLocker locker(&d->mutex);
+    d->invalid = true;
+}
+
+void DisjointMetadata::applyChangeNotifications()
+{
+    if (d->invalid)
+    {
+        reset();
+    }
+
+    QList<int> tagIds;
+    {
+        QMutexLocker locker(&d->mutex);
+        tagIds = d->tagIds;
+        d->tagIds.clear();
+    }
+
+    foreach (int tagId, tagIds)
+    {
+        notifyTagDeleted(tagId);
+    }
+}
+
+
+QDateTime DisjointMetadata::dateTime() const
+{
+    return d->dateTime;
+}
+
+CaptionsMap DisjointMetadata::titles() const
+{
+    return d->titles;
+}
+
+CaptionsMap DisjointMetadata::comments() const
+{
+    return d->comments;
+}
+
+int DisjointMetadata::pickLabel() const
+{
+    return d->pickLabel;
+}
+
+int DisjointMetadata::colorLabel() const
+{
+    return d->colorLabel;
+}
+
+int DisjointMetadata::rating() const
+{
+    return d->rating;
+}
+
+Template DisjointMetadata::metadataTemplate() const
+{
+    return d->metadataTemplate;
+}
+
+void DisjointMetadata::dateTimeInterval(QDateTime& lowest, QDateTime& highest) const
+{
+    switch (d->dateTimeStatus)
+    {
+        case MetadataInvalid:
+            lowest = highest = QDateTime();
+            break;
+        case MetadataAvailable:
+            lowest = highest = d->dateTime;
+            break;
+        case MetadataDisjoint:
+            lowest  = d->dateTime;
+            highest = d->lastDateTime;
+            break;
+    }
+}
+
+void DisjointMetadata::pickLabelInterval(int& lowest, int& highest) const
+{
+    switch (d->pickLabelStatus)
+    {
+        case MetadataInvalid:
+            lowest = highest = -1;
+            break;
+        case MetadataAvailable:
+            lowest = highest = d->pickLabel;
+            break;
+        case MetadataDisjoint:
+            lowest  = d->pickLabel;
+            highest = d->highestPickLabel;
+            break;
+    }
+}
+
+void DisjointMetadata::colorLabelInterval(int& lowest, int& highest) const
+{
+    switch (d->colorLabelStatus)
+    {
+        case MetadataInvalid:
+            lowest = highest = -1;
+            break;
+        case MetadataAvailable:
+            lowest = highest = d->colorLabel;
+            break;
+        case MetadataDisjoint:
+            lowest  = d->colorLabel;
+            highest = d->highestColorLabel;
+            break;
+    }
+}
+
+void DisjointMetadata::ratingInterval(int& lowest, int& highest) const
+{
+    switch (d->ratingStatus)
+    {
+        case MetadataInvalid:
+            lowest = highest = -1;
+            break;
+        case MetadataAvailable:
+            lowest = highest = d->rating;
+            break;
+        case MetadataDisjoint:
+            lowest  = d->rating;
+            highest = d->highestRating;
+            break;
+    }
+}
+
+QStringList DisjointMetadata::keywords() const
+{
+    QStringList tagList;
+
+    QList<int> keys = d->tags.keys();
+
+    foreach (int key, keys)
+    {
+        if (d->tags.value(key) == MetadataAvailable)
+        {
+            tagList.append(TagsCache::instance()->tagPath(key, TagsCache::NoLeadingSlash));
+        }
+    }
+
+    return tagList;
+}
+
+QMap<int, DisjointMetadata::Status> DisjointMetadata::tags() const
+{
+    // DatabaseMode == ManagedTags is assumed
+    return d->tags;
+}
+
+template <class T> void DisjointMetadata::Private::loadSingleValue(const T& data, T& storage,
+                                                                   DisjointMetadata::Status& status)
+{
+    switch (status)
+    {
+        case DisjointMetadata::MetadataInvalid:
+            storage = data;
+            status  = DisjointMetadata::MetadataAvailable;
+            break;
+
+        case DisjointMetadata::MetadataAvailable:
+
+            // we have two values. If they are equal, status is unchanged
+            if (data == storage)
+            {
+                break;
+            }
+
+            // they are not equal. We need to enter the disjoint state.
+            status = DisjointMetadata::MetadataDisjoint;
+            break;
+
+        case DisjointMetadata::MetadataDisjoint:
+            break;
+    }
+}
+
+} // namespace Digikam
 
diff --git a/static/reports/cppcheck/master/3.html b/static/reports/cppcheck/master/3.html index 83debf99d..a5aa89079 100644 --- a/static/reports/cppcheck/master/3.html +++ b/static/reports/cppcheck/master/3.html @@ -1,1869 +1,701 @@ - Cppcheck - HTML report - digiKam-master-rev-74ed235f83 + Cppcheck - HTML report - digiKam-master-rev-a04a0335ac
  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
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-551
-552
-553
-554
-555
-556
-557
-558
-559
-560
-561
-562
-563
-564
-565
-566
-567
-568
-569
-570
-571
-572
-573
-574
-575
-576
-577
-578
-579
-580
-581
-582
-583
-584
-585
-586
-587
-588
-589
-590
-591
-592
-593
-594
-595
-596
-597
-598
-599
-600
-601
-602
-603
-604
-605
-606
-607
-608
-609
-610
-611
-612
-613
-614
-615
-616
-617
-618
-619
-620
-621
-622
-623
-624
-625
-626
-627
-628
-629
-630
-631
-632
-633
-634
-635
-636
-637
-638
-639
-640
-641
-642
-643
-644
-645
-646
-647
-648
-649
-650
-651
-652
-653
-654
-655
-656
-657
-658
-659
-660
-661
-662
-663
-664
-665
-666
-667
-668
-669
-670
-671
-672
-673
-674
-675
-676
-677
-678
-679
-680
-681
-682
-683
-684
-685
-686
-687
-688
-689
-690
-691
-692
-693
-694
-695
-696
-697
-698
-699
-700
-701
-702
-703
-704
-705
-706
-707
-708
-709
-710
-711
-712
-713
-714
-715
-716
-717
-718
-719
-720
-721
-722
-723
-724
-725
-726
-727
-728
-729
-730
-731
-732
-733
-734
-735
-736
-737
-738
-739
-740
-741
-742
-743
-744
-745
-746
-747
-748
-749
-750
-751
-752
-753
-754
-755
-756
-757
-758
-759
-760
-761
-762
-763
-764
-765
-766
-767
-768
-769
-770
-771
-772
-773
-774
-775
-776
-777
-778
-779
-780
-781
-782
-783
-784
-785
-786
-787
-788
-789
-790
-791
-792
-793
-794
-795
-796
-797
-798
-799
-800
-801
-802
-803
-804
-805
-806
-807
-808
-809
-810
-811
-812
-813
-814
-815
-816
-817
-818
-819
-820
-821
-822
-823
-824
-825
-826
-827
-828
-829
-830
-831
-832
-833
-834
-835
-836
-837
-838
-839
-840
-841
-842
-843
-844
-845
-846
-847
-848
-849
-850
-851
-852
-853
-854
-855
-856
-857
-858
-859
-860
-861
-862
-863
-864
/* ============================================================
+280
/* ============================================================
  *
  * This file is a part of digiKam project
  * http://www.digikam.org
  *
- * Date        : 2015-08-17
- * Description : Helper class for Image Description Editor Tab
+ * Date        : 2007-02-13
+ * Description : Layouting photos on a page
  *
- * Copyright (C) 2015 by Veaceslav Munteanu <veaceslav dot munteanu90 at gmail dot com>
-
+ * Copyright (C) 2007-2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
  * Public License as published by the Free Software Foundation;
- * either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * ============================================================ */
-
-#include "disjointmetadata.h"
-
-// Qt includes
-
-#include <QMap>
-#include <QStringList>
-#include <QDateTime>
-#include <QMutexLocker>
-#include <QtAlgorithms>
-
-// Local includes
-
-#include "captionvalues.h"
-#include "template.h"
-#include "templatemanager.h"
-#include "tagscache.h"
-#include "coredbaccess.h"
-#include "itemcomments.h"
-#include "iteminfo.h"
-#include "coredbwatch.h"
-#include "metadatahub.h"
-
-namespace Digikam
-{
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include "atkinspagelayouttree.h"
+
+// C++ includes
+
+#include <cmath>
+
+// Qt includes
+
+#include <QList>
+
+// Local includes
+
+#include "atkinspagelayoutnode.h"
+
+namespace Digikam
+{
+
+AtkinsPageLayoutTree::AtkinsPageLayoutTree(double aspectRatioPage,
+                                           double absoluteAreaPage)
+    : m_root(0),
+      m_count(0),
+      m_aspectRatioPage(aspectRatioPage),
+      m_absoluteAreaPage(absoluteAreaPage)
+{
+}
 
-// This class was split from Private to be able to use the automatic C++ copy constructor
-// (Private contains a QMutex and is thus non-copyable)
-class Q_DECL_HIDDEN DisjointMetadataDataFields
-{
-public:
-
-    DisjointMetadataDataFields()
-        : dateTimeChanged  (false),
-          titlesChanged(false),
-          commentsChanged(false),
-          pickLabelChanged(false),
-          colorLabelChanged(false),
-          ratingChanged(false),
-          templateChanged(false),
-          tagsChanged(false),
-          withoutTags(false),
-          pickLabel(-1),
-          highestPickLabel(-1),
-          colorLabel(-1),
-          highestColorLabel(-1),
-          rating(-1),
-          highestRating(-1),
-          count(0),
-          dateTimeStatus(DisjointMetadata::MetadataInvalid),
-          titlesStatus(DisjointMetadata::MetadataInvalid),
-          commentsStatus(DisjointMetadata::MetadataInvalid),
-          pickLabelStatus(DisjointMetadata::MetadataInvalid),
-          colorLabelStatus(DisjointMetadata::MetadataInvalid),
-          ratingStatus(DisjointMetadata::MetadataInvalid),
-          templateStatus(DisjointMetadata::MetadataInvalid),
-          invalid(false)
-    {
-    }
-
-    bool                                dateTimeChanged;
-    bool                                titlesChanged;
-    bool                                commentsChanged;
-    bool                                pickLabelChanged;
-    bool                                colorLabelChanged;
-    bool                                ratingChanged;
-    bool                                templateChanged;
-    bool                                tagsChanged;
-    bool                                withoutTags;
-
-    int                                 pickLabel;
-    int                                 highestPickLabel;
-    int                                 colorLabel;
-    int                                 highestColorLabel;
-    int                                 rating;
-    int                                 highestRating;
-    int                                 count;
+AtkinsPageLayoutTree::AtkinsPageLayoutTree(const AtkinsPageLayoutTree& other)
+{
+    (*this) = other;
+}
+
+AtkinsPageLayoutTree& AtkinsPageLayoutTree::operator=(const AtkinsPageLayoutTree& other)
+{
+    delete m_root;
+    m_root             = new AtkinsPageLayoutNode(*(other.m_root));
+    m_count            = other.m_count;
+    m_aspectRatioPage  = other.m_aspectRatioPage;
+    m_absoluteAreaPage = other.m_absoluteAreaPage;
+
+    return *this;
+}
+
+AtkinsPageLayoutTree::~AtkinsPageLayoutTree()
+{
+    delete m_root;
+}
+
+int AtkinsPageLayoutTree::addImage(double aspectRatio,
+                                   double relativeArea)
+{
+    int index = m_count;
+
+    if (!m_root)
+    {
+        m_root = new AtkinsPageLayoutNode(aspectRatio,
+                                          relativeArea,
+                                          index);
+        m_count++;
+        return index;
+    }
+
+    // Section 2.1
+    AtkinsPageLayoutNode* bestTree = NULL;
+    double highScore               = 0;
+
+    for (int i = 0 ; i < m_count ; ++i)
+    {
+        for (int horizontal = 0 ; horizontal < 2 ; ++horizontal)
+        {
+            // create temporary tree
+            AtkinsPageLayoutNode* candidateTree          = new AtkinsPageLayoutNode(*m_root);
+
+            // select the subtree which will be replace by a new internal node
+            AtkinsPageLayoutNode* const candidateSubtree = candidateTree->nodeForIndex(i);
+
+            // find parent node
+            AtkinsPageLayoutNode* const parentNode       = candidateTree->parentOf(candidateSubtree);
 
-    QDateTime                           dateTime;
-    QDateTime                           lastDateTime;
-
-    CaptionsMap                         titles;
-    CaptionsMap                         comments;
-
-    Template                            metadataTemplate;
-
-    QMap<int, DisjointMetadata::Status> tags;
-
-    QStringList                         tagList;
-
-    QMultiMap<QString, QVariant>        faceTagsList;
-
-    DisjointMetadata::Status            dateTimeStatus;
-    DisjointMetadata::Status            titlesStatus;
-    DisjointMetadata::Status            commentsStatus;
-    DisjointMetadata::Status            pickLabelStatus;
-    DisjointMetadata::Status            colorLabelStatus;
-    DisjointMetadata::Status            ratingStatus;
-    DisjointMetadata::Status            templateStatus;
-
-    QList<int>                          tagIds;
-    bool                                invalid;
-};
+            // create new terminal node
+            AtkinsPageLayoutNode* const newTerminalNode  = new AtkinsPageLayoutNode(aspectRatio,
+                                                                                    relativeArea,
+                                                                                    index);
+
+            // create new internal node
+            AtkinsPageLayoutNode* const newInternalNode  = new AtkinsPageLayoutNode(candidateSubtree,
+                                                                                    newTerminalNode,
+                                                                                    horizontal,
+                                                                                    index+1);
+
+            // replace in tree
+            if (parentNode)
+            {
+                // replace in tree
+                parentNode->takeAndSetChild(candidateSubtree, newInternalNode);
+            }
+            else
+            {
+                // candidateTree is candidateSubtree is root
+                candidateTree = newInternalNode;
+            }
+
+            // recompute sizes
+            candidateTree->computeRelativeSizes();
 
-class Q_DECL_HIDDEN DisjointMetadata::Private : public DisjointMetadataDataFields
-{
-public:
-
-    explicit Private()
-    {
-    }
-
-    // use the automatic copy constructor
-    explicit Private(const Private& other)
-        : DisjointMetadataDataFields(other)
-    {
-    }
-
-    QMutex mutex;
-
-public:
+            double candidateScore = score(candidateTree, m_count+2);
+
+            if (candidateScore > highScore)
+            {
+                highScore = candidateScore;
+                delete bestTree;
+                bestTree  = candidateTree;
+            }
+            else
+            {
+                delete candidateTree;
+            }
+        }
+    }
+
+    delete m_root;
+    m_root = bestTree;
 
-    template <class T> void loadSingleValue(const T& data,
-                                            T& storage,
-                                            DisjointMetadata::Status& status);
-    void makeConnections(DisjointMetadata* q);
-};
-
-void DisjointMetadata::Private::makeConnections(DisjointMetadata *q)
-{
-    QObject::connect(TagsCache::instance(), SIGNAL(tagDeleted(int)),
-                     q, SLOT(slotTagDeleted(int)),
-                     Qt::DirectConnection);
-
-    QObject::connect(CoreDbAccess::databaseWatch(), SIGNAL(databaseChanged()),
-                     q, SLOT(slotInvalidate()));
-}
+    if (m_root)
+        m_root->computeDivisions();
+
+    m_count += 2;
+    return index;
+}
+
+// Section 2.2.1
+double AtkinsPageLayoutTree::score(AtkinsPageLayoutNode* const root,
+                                   int nodeCount)
+{
+    if (!root)
+        return 0;
+
+    double areaSum = 0;
 
-DisjointMetadata::DisjointMetadata(QObject *parent)
-    : QObject(parent),
-      d(new Private())
-{
-    d->makeConnections(this);
-}
-
-DisjointMetadata::DisjointMetadata(const DisjointMetadata& other)
-    : QObject(other.parent()),
-      d(new Private(*other.d))
-{
-    d->makeConnections(this);
-}
-
-DisjointMetadata::~DisjointMetadata()
-{
-    delete d;
-}
-
-DisjointMetadata& DisjointMetadata::operator=(const DisjointMetadata& other)
-{
-    delete d;
-    d = new Private(*other.d);
-    return *this;
-}
-
-void DisjointMetadata::reset()
-{
-    delete d;
-    d =  new Private();
-}
-
-void DisjointMetadata::load(const ItemInfo& info)
-{
-    CaptionsMap commentMap;
-    CaptionsMap titleMap;
+    for (int i = 0 ; i < nodeCount ; ++i)
+    {
+        AtkinsPageLayoutNode* const node = root->nodeForIndex(i);
+
+        if (node->type() == AtkinsPageLayoutNode::TerminalNode)
+            areaSum += node->relativeArea();
+    }
+
+    double minRatioPage = root->aspectRatio() < m_aspectRatioPage ? root->aspectRatio()
+                                                                  : m_aspectRatioPage;
+    double maxRatioPage = root->aspectRatio() > m_aspectRatioPage ? root->aspectRatio()
+                                                                  : m_aspectRatioPage;
+
+    return G() * (areaSum / root->relativeArea()) * (minRatioPage / maxRatioPage);
+}
+
+// Section 2.2.2
+double AtkinsPageLayoutTree::G() const
+{
+    return 0.95 * 0.95;
+}
+
+// Section 2.2.2
+double AtkinsPageLayoutTree::absoluteArea(AtkinsPageLayoutNode* const node)
+{
+    // min(a_pbb, a_page), max(a_pbb, a_page)
+    double minRatioPage     = m_root->aspectRatio() < m_aspectRatioPage ? m_root->aspectRatio()
+                                                                        : m_aspectRatioPage;
+    double maxRatioPage     = m_root->aspectRatio() > m_aspectRatioPage ? m_root->aspectRatio()
+                                                                        : m_aspectRatioPage;
+
+    // A_pbb
+    double absoluteAreaRoot = m_absoluteAreaPage * minRatioPage / maxRatioPage;
+
+    if (node == m_root)
+        return absoluteAreaRoot;
 
-    {
-        CoreDbAccess access;
-        ItemComments comments = info.imageComments(access);
-        commentMap             = comments.toCaptionsMap();
-        titleMap               = comments.toCaptionsMap(DatabaseComment::Title);
-    }
-
-    Template tref = info.metadataTemplate();
-    Template t    = TemplateManager::defaultManager()->findByContents(tref);
-    //qCDebug(DIGIKAM_GENERAL_LOG) << "Found Metadata Template: " << t.templateTitle();
+    // A_i
+    return G() * node->relativeArea() / m_root->relativeArea() * absoluteAreaRoot;
+}
+
+QRectF AtkinsPageLayoutTree::drawingArea(int index, const QRectF& absoluteRectPage)
+{
+    AtkinsPageLayoutNode* const node = m_root->nodeForIndex(index);
+
+    if (!node)
+        return QRectF();
 
-    load(info.dateTime(),
-         titleMap,
-         commentMap,
-         info.colorLabel(),
-         info.pickLabel(),
-         info.rating(),
-         t.isNull() ? tref : t);
-
-    loadTags(info.tagIds());
-}
-
-//-----------------------------Status -------------------------
-
-DisjointMetadata::Status DisjointMetadata::dateTimeStatus() const
-{
-    return d->dateTimeStatus;
-}
-
-DisjointMetadata::Status DisjointMetadata::titlesStatus() const
-{
-    return d->titlesStatus;
-}
-
-DisjointMetadata::Status DisjointMetadata::commentsStatus() const
-{
-    return d->commentsStatus;
-}
-
-DisjointMetadata::Status DisjointMetadata::pickLabelStatus() const
-{
-    return d->pickLabelStatus;
-}
-
-DisjointMetadata::Status DisjointMetadata::colorLabelStatus() const
-{
-    return d->colorLabelStatus;
-}
-
-DisjointMetadata::Status DisjointMetadata::ratingStatus() const
-{
-    return d->ratingStatus;
-}
-
-DisjointMetadata::Status DisjointMetadata::templateStatus() const
-{
-    return d->templateStatus;
-}
-
-DisjointMetadata::Status DisjointMetadata::tagStatus(int albumId) const
-{
-    return d->tags.value(albumId, DisjointMetadata::MetadataInvalid);
-}
-
-DisjointMetadata::Status DisjointMetadata::tagStatus(const QString& tagPath) const
-{
-    return tagStatus(TagsCache::instance()->tagForPath(tagPath));
+    // find out the "line of ancestry" of the node
+    QList<AtkinsPageLayoutNode*> treePath;
+    AtkinsPageLayoutNode* parent = node;
+
+    while (parent)
+    {
+        treePath.prepend(parent);
+        parent = m_root->parentOf(parent);
+    }
+
+    // find out the rect of the page bounding box (the rect of the root node in the page rect)
+    QRectF absoluteRect = rectInRect(absoluteRectPage,
+                                     m_root->aspectRatio(),
+                                     absoluteArea(m_root));
+
+    // go along the line of ancestry and narrow down the bounding rectangle,
+    // as described in section 2.2.2
+    for (int i = 0 ; i < treePath.count() - 1 ; ++i)
+    {
+        AtkinsPageLayoutNode* const parent = treePath[i];
+        AtkinsPageLayoutNode* const child  = treePath[i+1]; // only iterating to count-1
+
+        if (parent->type() == AtkinsPageLayoutNode::VerticalDivision) // side by side
+        {
+            double leftWidth = absoluteRect.width() * parent->division();
+
+            if (child == parent->leftChild())
+            {
+                absoluteRect.setWidth(leftWidth);
+            }
+            else // right child
+            {
+                double rightWidth = absoluteRect.width() - leftWidth;
+                absoluteRect.setWidth(rightWidth);
+                absoluteRect.translate(leftWidth, 0);
+            }
+        }
+        else // horizontal division: one on top of the other
+        {
+            // left child is topmost
+            double upperHeight = absoluteRect.height() * parent->division();
+
+            if (child == parent->leftChild())
+            {
+                absoluteRect.setHeight(upperHeight);
+            }
+            else // right child
+            {
+                double lowerHeight = absoluteRect.height() - upperHeight;
+                absoluteRect.setHeight(lowerHeight);
+                absoluteRect.translate(0, upperHeight);
+            }
+        }
+    }
+
+    return rectInRect(absoluteRect, node->aspectRatio(), absoluteArea(node));
 }
 
-//---- Changed status ---------------------
-
-bool DisjointMetadata::dateTimeChanged() const
+QRectF AtkinsPageLayoutTree::rectInRect(const QRectF &rect,
+                                        double aspectRatio,
+                                        double absoluteArea)
 {
-    return d->dateTimeChanged;
-}
-
-bool DisjointMetadata::titlesChanged() const
-{
-    return d->titlesChanged;
+    double width  = std::sqrt(absoluteArea / aspectRatio);
+    double height = std::sqrt(absoluteArea * aspectRatio);
+    double x      = rect.x() + (rect.width()  - width)  / 2;
+    double y      = rect.y() + (rect.height() - height) / 2;
+
+    return QRectF(x, y, width, height);
 }
 
-bool DisjointMetadata::commentsChanged() const
-{
-    return d->commentsChanged;
-}
-
-bool DisjointMetadata::pickLabelChanged() const
-{
-    return d->pickLabelChanged;
-}
-
-bool DisjointMetadata::colorLabelChanged() const
-{
-    return d->colorLabelChanged;
-}
-
-bool DisjointMetadata::ratingChanged() const
-{
-    return d->ratingChanged;
-}
-
-bool DisjointMetadata::templateChanged() const
-{
-    return d->templateChanged;
-}
-
-bool DisjointMetadata::tagsChanged() const
-{
-    return d->tagsChanged;
-}
-
-void DisjointMetadata::setDateTime(const QDateTime& dateTime, DisjointMetadata::Status status)
-{
-    d->dateTimeStatus  = status;
-    d->dateTime        = dateTime;
-    d->dateTimeChanged = true;
-}
-
-void DisjointMetadata::setTitles(const CaptionsMap& titles, DisjointMetadata::Status status)
-{
-    d->titlesStatus  = status;
-    d->titles        = titles;
-    d->titlesChanged = true;
-}
-
-void DisjointMetadata::setComments(const CaptionsMap& comments, DisjointMetadata::Status status)
-{
-    d->commentsStatus  = status;
-    d->comments        = comments;
-    d->commentsChanged = true;
-}
-
-void DisjointMetadata::setPickLabel(int pickId, DisjointMetadata::Status status)
-{
-    d->pickLabelStatus  = status;
-    d->pickLabel        = pickId;
-    d->pickLabelChanged = true;
-}
-
-void DisjointMetadata::setColorLabel(int colorId, DisjointMetadata::Status status)
-{
-    d->colorLabelStatus  = status;
-    d->colorLabel        = colorId;
-    d->colorLabelChanged = true;
-}
-
-void DisjointMetadata::setRating(int rating, DisjointMetadata::Status status)
-{
-    d->ratingStatus   = status;
-    d->rating         = rating;
-    d->ratingChanged  = true;
-}
-
-void DisjointMetadata::setMetadataTemplate(const Template& t, DisjointMetadata::Status status)
-{
-    d->templateStatus   = status;
-    d->metadataTemplate = t;
-    d->templateChanged  = true;
-}
-
-void DisjointMetadata::setTag(int albumID, DisjointMetadata::Status status)
-{
-    d->tags[albumID] = status;
-    d->tagsChanged = true;
-}
-
-void DisjointMetadata::resetChanged()
-{
-    d->dateTimeChanged   = false;
-    d->titlesChanged     = false;
-    d->commentsChanged   = false;
-    d->pickLabelChanged  = false;
-    d->colorLabelChanged = false;
-    d->ratingChanged     = false;
-    d->templateChanged   = false;
-    d->tagsChanged       = false;
-}
-
-bool DisjointMetadata::write(ItemInfo info, WriteMode writeMode)
-{
-    applyChangeNotifications();
-
-    bool changed = false;
-
-    // find out in advance if we have something to write - needed for FullWriteIfChanged mode
-    bool saveTitle      = (d->titlesStatus     == MetadataAvailable);
-    bool saveComment    = (d->commentsStatus   == MetadataAvailable);
-    bool saveDateTime   = (d->dateTimeStatus   == MetadataAvailable);
-    bool savePickLabel  = (d->pickLabelStatus  == MetadataAvailable);
-    bool saveColorLabel = (d->colorLabelStatus == MetadataAvailable);
-    bool saveRating     = (d->ratingStatus     == MetadataAvailable);
-    bool saveTemplate   = (d->templateStatus   == MetadataAvailable);
-    bool saveTags       = true;
-
-    bool writeAllFields;
-
-    if (writeMode == FullWrite)
-    {
-        writeAllFields = true;
-    }
-    else if (writeMode == FullWriteIfChanged)
-    {
-        writeAllFields = (
-                             (saveTitle      && d->titlesChanged)     ||
-                             (saveComment    && d->commentsChanged)   ||
-                             (saveDateTime   && d->dateTimeChanged)   ||
-                             (savePickLabel  && d->pickLabelChanged)  ||
-                             (saveColorLabel && d->colorLabelChanged) ||
-                             (saveRating     && d->ratingChanged)     ||
-                             (saveTemplate   && d->templateChanged)   ||
-                             (saveTags       && d->tagsChanged)
-                         );
-    }
-    else // PartialWrite
-    {
-        writeAllFields = false;
-    }
-
-    if (saveTitle && (writeAllFields || d->titlesChanged))
-    {
-        CoreDbAccess access;
-        ItemComments comments = info.imageComments(access);
-        comments.replaceComments(d->titles, DatabaseComment::Title);
-        changed                = true;
-    }
-
-    if (saveComment && (writeAllFields || d->commentsChanged))
-    {
-        CoreDbAccess access;
-        ItemComments comments = info.imageComments(access);
-        comments.replaceComments(d->comments);
-        changed                = true;
-    }
-
-    if (saveDateTime && (writeAllFields || d->dateTimeChanged))
-    {
-        info.setDateTime(d->dateTime);
-        changed = true;
-    }
-
-    if (savePickLabel && (writeAllFields || d->pickLabelChanged))
-    {
-        info.setPickLabel(d->pickLabel);
-        changed = true;
-    }
-
-    if (saveColorLabel && (writeAllFields || d->colorLabelChanged))
-    {
-        info.setColorLabel(d->colorLabel);
-        changed = true;
-    }
-
-    if (saveRating && (writeAllFields || d->ratingChanged))
-    {
-        info.setRating(d->rating);
-        changed = true;
-    }
-
-    if (saveTemplate && writeAllFields)
-    {
-        QString title = d->metadataTemplate.templateTitle();
-
-        if (title == Template::removeTemplateTitle())
-        {
-            info.removeMetadataTemplate();
-        }
-
-        if (title.isEmpty())
-        {
-            // Nothing to do.
-        }
-        else
-        {
-            info.setMetadataTemplate(d->metadataTemplate);
-        }
-
-        changed = true;
-    }
-
-    if (writeAllFields || d->tagsChanged)
-    {
-        QList<int> keys = d->tags.keys();
-
-        foreach (int key, keys)
-        {
-            if (d->tags.value(key) == DisjointMetadata::MetadataAvailable)
-            {
-                info.setTag(key);
-                changed = true;
-            }
-
-            if (d->tags.value(key) == DisjointMetadata::MetadataInvalid)
-            {
-                info.removeTag(key);
-                changed = true;
-            }
-        }
-    }
-
-    return changed;
-}
-
-bool DisjointMetadata::willWriteMetadata(DisjointMetadata::WriteMode writeMode, const MetaEngineSettingsContainer& settings) const
-{
-    // This is the same logic as in write(DMetadata) but without actually writing.
-    // Adapt if the method above changes
-    bool saveTitle      = (settings.saveComments   && d->titlesStatus     == MetadataAvailable);
-    bool saveComment    = (settings.saveComments   && d->commentsStatus   == MetadataAvailable);
-    bool saveDateTime   = (settings.saveDateTime   && d->dateTimeStatus   == MetadataAvailable);
-    bool savePickLabel  = (settings.savePickLabel  && d->pickLabelStatus  == MetadataAvailable);
-    bool saveColorLabel = (settings.saveColorLabel && d->colorLabelStatus == MetadataAvailable);
-    bool saveRating     = (settings.saveRating     && d->ratingStatus     == MetadataAvailable);
-    bool saveTemplate   = (settings.saveTemplate   && d->templateStatus   == MetadataAvailable);
-    bool saveTags       = settings.saveTags;
-
-    bool writeAllFields;
-
-    if (writeMode == FullWrite)
-    {
-        writeAllFields = true;
-    }
-    else if (writeMode == FullWriteIfChanged)
-    {
-        writeAllFields = (
-                             (saveTitle      && d->titlesChanged)     ||
-                             (saveComment    && d->commentsChanged)   ||
-                             (saveDateTime   && d->dateTimeChanged)   ||
-                             (savePickLabel  && d->pickLabelChanged)  ||
-                             (saveColorLabel && d->colorLabelChanged) ||
-                             (saveRating     && d->ratingChanged)     ||
-                             (saveTemplate   && d->templateChanged)   ||
-                             (saveTags       && d->tagsChanged)
-                         );
-    }
-    else // PartialWrite
-    {
-        writeAllFields = false;
-    }
-
-    return (
-               (saveTitle      && (writeAllFields || d->titlesChanged))     ||
-               (saveComment    && (writeAllFields || d->commentsChanged))   ||
-               (saveDateTime   && (writeAllFields || d->dateTimeChanged))   ||
-               (savePickLabel  && (writeAllFields || d->pickLabelChanged))  ||
-               (saveColorLabel && (writeAllFields || d->colorLabelChanged)) ||
-               (saveRating     && (writeAllFields || d->ratingChanged))     ||
-               (saveTags       && (writeAllFields || d->tagsChanged))       ||
-               (saveTemplate   && (writeAllFields || d->templateChanged))
-           );
-}
-
-int DisjointMetadata::changedFlags()
-{
-    int value = 0;
-
-    if (d->titlesChanged)
-        value |= MetadataHub::WRITE_TITLE;
-    if (d->commentsChanged)
-        value |= MetadataHub::WRITE_COMMENTS;
-    if (d->dateTimeChanged)
-        value |= MetadataHub::WRITE_DATETIME;
-    if (d->pickLabelChanged)
-        value |= MetadataHub::WRITE_PICKLABEL;
-    if (d->colorLabelChanged)
-        value |= MetadataHub::WRITE_COLORLABEL;
-    if (d->ratingChanged)
-        value |= MetadataHub::WRITE_RATING;
-    if (d->tagsChanged)
-        value |= MetadataHub::WRITE_TAGS;
-    if (d->templateChanged)
-        value |= MetadataHub::WRITE_TEMPLATE;
-
-    return value;
-}
-
-void DisjointMetadata::load(const QDateTime& dateTime,const CaptionsMap& titles,
-                            const CaptionsMap& comment, int colorLabel,
-                            int pickLabel, int rating, const Template& t)
-{
-    if (dateTime.isValid())
-    {
-        d->loadSingleValue<QDateTime>(dateTime, d->dateTime,d->dateTimeStatus);
-    }
-
-    d->loadSingleValue<int>(pickLabel, d->pickLabel, d->pickLabelStatus);
-
-    d->loadSingleValue<int>(colorLabel, d->colorLabel, d->colorLabelStatus);
-
-    d->loadSingleValue<int>(rating, d->rating,d->ratingStatus);
-
-    d->loadSingleValue<CaptionsMap>(titles, d->titles, d->titlesStatus);
-
-    d->loadSingleValue<CaptionsMap>(comment, d->comments, d->commentsStatus);
-
-    d->loadSingleValue<Template>(t, d->metadataTemplate, d->templateStatus);
-}
-
-void DisjointMetadata::loadTags(const QList<int>& tagIds)
-{
-    QList<int> loadedTagIds;
-
-    foreach (int tagId, tagIds)
-    {
-        if (!TagsCache::instance()->isInternalTag(tagId))
-        {
-            loadedTagIds << tagId;
-        }
-    }
-
-    if (loadedTagIds.isEmpty())
-    {
-        if (!d->withoutTags)
-        {
-            QMap<int, DisjointMetadata::Status>::iterator it;
-
-            for (it = d->tags.begin() ; it != d->tags.end() ; ++it)
-            {
-                it.value() = MetadataDisjoint;
-            }
-
-            d->withoutTags = true;
-        }
-
-        return;
-    }
-
-    // If tags map is empty, set them all as Available
-
-    if (d->tags.isEmpty())
-    {
-        foreach (int tagId, loadedTagIds)
-        {
-            if (d->withoutTags)
-            {
-                d->tags[tagId] = MetadataDisjoint;
-            }
-            else
-            {
-                d->tags[tagId] = MetadataAvailable;
-            }
-        }
-
-        return;
-    }
-
-    std::sort(loadedTagIds.begin(), loadedTagIds.end());
-    // We search for metadata available tags, and
-    // it is not present in current list, set it to
-    // disjoint
-
-    QMap<int, DisjointMetadata::Status>::iterator it;
-
-    for (it = d->tags.begin() ; it != d->tags.end() ; ++it)
-    {
-        if (it.value() == MetadataAvailable)
-        {
-            if (qBinaryFind(loadedTagIds.begin(), loadedTagIds.end(), it.key()) == loadedTagIds.end())
-            {
-                it.value() = MetadataDisjoint;
-            }
-        }
-    }
-
-    // new tags which are not yet in the set,
-    // are added as Disjoint
-    foreach (int tagId, loadedTagIds)
-    {
-        if (!d->tags.contains(tagId))
-        {
-            d->tags[tagId] = MetadataDisjoint;
-        }
-    }
-}
-
-void DisjointMetadata::notifyTagDeleted(int id)
-{
-    d->tags.remove(id);
-}
-
-void DisjointMetadata::slotTagDeleted(int tagId)
-{
-    QMutexLocker locker(&d->mutex);
-    d->tagIds << tagId;
-}
-
-void DisjointMetadata::slotInvalidate()
-{
-    QMutexLocker locker(&d->mutex);
-    d->invalid = true;
-}
-
-void DisjointMetadata::applyChangeNotifications()
-{
-    if (d->invalid)
-    {
-        reset();
-    }
-
-    QList<int> tagIds;
-    {
-        QMutexLocker locker(&d->mutex);
-        tagIds = d->tagIds;
-        d->tagIds.clear();
-    }
-
-    foreach (int tagId, tagIds)
-    {
-        notifyTagDeleted(tagId);
-    }
-}
-
-
-QDateTime DisjointMetadata::dateTime() const
-{
-    return d->dateTime;
-}
-
-CaptionsMap DisjointMetadata::titles() const
-{
-    return d->titles;
-}
-
-CaptionsMap DisjointMetadata::comments() const
-{
-    return d->comments;
-}
-
-int DisjointMetadata::pickLabel() const
-{
-    return d->pickLabel;
-}
-
-int DisjointMetadata::colorLabel() const
-{
-    return d->colorLabel;
-}
-
-int DisjointMetadata::rating() const
-{
-    return d->rating;
-}
-
-Template DisjointMetadata::metadataTemplate() const
-{
-    return d->metadataTemplate;
-}
-
-void DisjointMetadata::dateTimeInterval(QDateTime& lowest, QDateTime& highest) const
-{
-    switch (d->dateTimeStatus)
-    {
-        case MetadataInvalid:
-            lowest = highest = QDateTime();
-            break;
-        case MetadataAvailable:
-            lowest = highest = d->dateTime;
-            break;
-        case MetadataDisjoint:
-            lowest  = d->dateTime;
-            highest = d->lastDateTime;
-            break;
-    }
-}
-
-void DisjointMetadata::pickLabelInterval(int& lowest, int& highest) const
-{
-    switch (d->pickLabelStatus)
-    {
-        case MetadataInvalid:
-            lowest = highest = -1;
-            break;
-        case MetadataAvailable:
-            lowest = highest = d->pickLabel;
-            break;
-        case MetadataDisjoint:
-            lowest  = d->pickLabel;
-            highest = d->highestPickLabel;
-            break;
-    }
-}
-
-void DisjointMetadata::colorLabelInterval(int& lowest, int& highest) const
-{
-    switch (d->colorLabelStatus)
-    {
-        case MetadataInvalid:
-            lowest = highest = -1;
-            break;
-        case MetadataAvailable:
-            lowest = highest = d->colorLabel;
-            break;
-        case MetadataDisjoint:
-            lowest  = d->colorLabel;
-            highest = d->highestColorLabel;
-            break;
-    }
-}
-
-void DisjointMetadata::ratingInterval(int& lowest, int& highest) const
-{
-    switch (d->ratingStatus)
-    {
-        case MetadataInvalid:
-            lowest = highest = -1;
-            break;
-        case MetadataAvailable:
-            lowest = highest = d->rating;
-            break;
-        case MetadataDisjoint:
-            lowest  = d->rating;
-            highest = d->highestRating;
-            break;
-    }
-}
-
-QStringList DisjointMetadata::keywords() const
-{
-    QStringList tagList;
-
-    QList<int> keys = d->tags.keys();
-
-    foreach (int key, keys)
-    {
-        if (d->tags.value(key) == MetadataAvailable)
-        {
-            tagList.append(TagsCache::instance()->tagPath(key, TagsCache::NoLeadingSlash));
-        }
-    }
-
-    return tagList;
-}
-
-QMap<int, DisjointMetadata::Status> DisjointMetadata::tags() const
-{
-    // DatabaseMode == ManagedTags is assumed
-    return d->tags;
-}
-
-template <class T> void DisjointMetadata::Private::loadSingleValue(const T& data, T& storage,
-                                                                   DisjointMetadata::Status& status)
-{
-    switch (status)
-    {
-        case DisjointMetadata::MetadataInvalid:
-            storage = data;
-            status  = DisjointMetadata::MetadataAvailable;
-            break;
-
-        case DisjointMetadata::MetadataAvailable:
-
-            // we have two values. If they are equal, status is unchanged
-            if (data == storage)
-            {
-                break;
-            }
-
-            // they are not equal. We need to enter the disjoint state.
-            status = DisjointMetadata::MetadataDisjoint;
-            break;
-
-        case DisjointMetadata::MetadataDisjoint:
-            break;
-    }
-}
-
-} // namespace Digikam
+} // Namespace Digikam
 
diff --git a/static/reports/cppcheck/master/4.html b/static/reports/cppcheck/master/4.html deleted file mode 100644 index 707f71655..000000000 --- a/static/reports/cppcheck/master/4.html +++ /dev/null @@ -1,701 +0,0 @@ - - - - - - Cppcheck - HTML report - digiKam-master-rev-74ed235f83 - - - - - - - -
-
  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
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
/* ============================================================
- *
- * This file is a part of digiKam project
- * http://www.digikam.org
- *
- * Date        : 2007-02-13
- * Description : Layouting photos on a page
- *
- * Copyright (C) 2007-2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
- * Copyright (C) 2006-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
- *
- * This program is free software; you can redistribute it
- * and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation;
- * either version 2, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * ============================================================ */
-
-#include "atkinspagelayouttree.h"
-
-// C++ includes
-
-#include <cmath>
-
-// Qt includes
-
-#include <QList>
-
-// Local includes
-
-#include "atkinspagelayoutnode.h"
-
-namespace Digikam
-{
-
-AtkinsPageLayoutTree::AtkinsPageLayoutTree(double aspectRatioPage,
-                                           double absoluteAreaPage)
-    : m_root(0),
-      m_count(0),
-      m_aspectRatioPage(aspectRatioPage),
-      m_absoluteAreaPage(absoluteAreaPage)
-{
-}
-
-AtkinsPageLayoutTree::AtkinsPageLayoutTree(const AtkinsPageLayoutTree& other)
-{
-    (*this) = other;
-}
-
-AtkinsPageLayoutTree& AtkinsPageLayoutTree::operator=(const AtkinsPageLayoutTree& other)
-{
-    delete m_root;
-    m_root             = new AtkinsPageLayoutNode(*(other.m_root));
-    m_count            = other.m_count;
-    m_aspectRatioPage  = other.m_aspectRatioPage;
-    m_absoluteAreaPage = other.m_absoluteAreaPage;
-
-    return *this;
-}
-
-AtkinsPageLayoutTree::~AtkinsPageLayoutTree()
-{
-    delete m_root;
-}
-
-int AtkinsPageLayoutTree::addImage(double aspectRatio,
-                                   double relativeArea)
-{
-    int index = m_count;
-
-    if (!m_root)
-    {
-        m_root = new AtkinsPageLayoutNode(aspectRatio,
-                                          relativeArea,
-                                          index);
-        m_count++;
-        return index;
-    }
-
-    // Section 2.1
-    AtkinsPageLayoutNode* bestTree = NULL;
-    double highScore               = 0;
-
-    for (int i = 0 ; i < m_count ; ++i)
-    {
-        for (int horizontal = 0 ; horizontal < 2 ; ++horizontal)
-        {
-            // create temporary tree
-            AtkinsPageLayoutNode* candidateTree          = new AtkinsPageLayoutNode(*m_root);
-
-            // select the subtree which will be replace by a new internal node
-            AtkinsPageLayoutNode* const candidateSubtree = candidateTree->nodeForIndex(i);
-
-            // find parent node
-            AtkinsPageLayoutNode* const parentNode       = candidateTree->parentOf(candidateSubtree);
-
-            // create new terminal node
-            AtkinsPageLayoutNode* const newTerminalNode  = new AtkinsPageLayoutNode(aspectRatio,
-                                                                                    relativeArea,
-                                                                                    index);
-
-            // create new internal node
-            AtkinsPageLayoutNode* const newInternalNode  = new AtkinsPageLayoutNode(candidateSubtree,
-                                                                                    newTerminalNode,
-                                                                                    horizontal,
-                                                                                    index+1);
-
-            // replace in tree
-            if (parentNode)
-            {
-                // replace in tree
-                parentNode->takeAndSetChild(candidateSubtree, newInternalNode);
-            }
-            else
-            {
-                // candidateTree is candidateSubtree is root
-                candidateTree = newInternalNode;
-            }
-
-            // recompute sizes
-            candidateTree->computeRelativeSizes();
-
-            double candidateScore = score(candidateTree, m_count+2);
-
-            if (candidateScore > highScore)
-            {
-                highScore = candidateScore;
-                delete bestTree;
-                bestTree  = candidateTree;
-            }
-            else
-            {
-                delete candidateTree;
-            }
-        }
-    }
-
-    delete m_root;
-    m_root = bestTree;
-
-    if (m_root)
-        m_root->computeDivisions();
-
-    m_count += 2;
-    return index;
-}
-
-// Section 2.2.1
-double AtkinsPageLayoutTree::score(AtkinsPageLayoutNode* const root,
-                                   int nodeCount)
-{
-    if (!root)
-        return 0;
-
-    double areaSum = 0;
-
-    for (int i = 0 ; i < nodeCount ; ++i)
-    {
-        AtkinsPageLayoutNode* const node = root->nodeForIndex(i);
-
-        if (node->type() == AtkinsPageLayoutNode::TerminalNode)
-            areaSum += node->relativeArea();
-    }
-
-    double minRatioPage = root->aspectRatio() < m_aspectRatioPage ? root->aspectRatio()
-                                                                  : m_aspectRatioPage;
-    double maxRatioPage = root->aspectRatio() > m_aspectRatioPage ? root->aspectRatio()
-                                                                  : m_aspectRatioPage;
-
-    return G() * (areaSum / root->relativeArea()) * (minRatioPage / maxRatioPage);
-}
-
-// Section 2.2.2
-double AtkinsPageLayoutTree::G() const
-{
-    return 0.95 * 0.95;
-}
-
-// Section 2.2.2
-double AtkinsPageLayoutTree::absoluteArea(AtkinsPageLayoutNode* const node)
-{
-    // min(a_pbb, a_page), max(a_pbb, a_page)
-    double minRatioPage     = m_root->aspectRatio() < m_aspectRatioPage ? m_root->aspectRatio()
-                                                                        : m_aspectRatioPage;
-    double maxRatioPage     = m_root->aspectRatio() > m_aspectRatioPage ? m_root->aspectRatio()
-                                                                        : m_aspectRatioPage;
-
-    // A_pbb
-    double absoluteAreaRoot = m_absoluteAreaPage * minRatioPage / maxRatioPage;
-
-    if (node == m_root)
-        return absoluteAreaRoot;
-
-    // A_i
-    return G() * node->relativeArea() / m_root->relativeArea() * absoluteAreaRoot;
-}
-
-QRectF AtkinsPageLayoutTree::drawingArea(int index, const QRectF& absoluteRectPage)
-{
-    AtkinsPageLayoutNode* const node = m_root->nodeForIndex(index);
-
-    if (!node)
-        return QRectF();
-
-    // find out the "line of ancestry" of the node
-    QList<AtkinsPageLayoutNode*> treePath;
-    AtkinsPageLayoutNode* parent = node;
-
-    while (parent)
-    {
-        treePath.prepend(parent);
-        parent = m_root->parentOf(parent);
-    }
-
-    // find out the rect of the page bounding box (the rect of the root node in the page rect)
-    QRectF absoluteRect = rectInRect(absoluteRectPage,
-                                     m_root->aspectRatio(),
-                                     absoluteArea(m_root));
-
-    // go along the line of ancestry and narrow down the bounding rectangle,
-    // as described in section 2.2.2
-    for (int i = 0 ; i < treePath.count() - 1 ; ++i)
-    {
-        AtkinsPageLayoutNode* const parent = treePath[i];
-        AtkinsPageLayoutNode* const child  = treePath[i+1]; // only iterating to count-1
-
-        if (parent->type() == AtkinsPageLayoutNode::VerticalDivision) // side by side
-        {
-            double leftWidth = absoluteRect.width() * parent->division();
-
-            if (child == parent->leftChild())
-            {
-                absoluteRect.setWidth(leftWidth);
-            }
-            else // right child
-            {
-                double rightWidth = absoluteRect.width() - leftWidth;
-                absoluteRect.setWidth(rightWidth);
-                absoluteRect.translate(leftWidth, 0);
-            }
-        }
-        else // horizontal division: one on top of the other
-        {
-            // left child is topmost
-            double upperHeight = absoluteRect.height() * parent->division();
-
-            if (child == parent->leftChild())
-            {
-                absoluteRect.setHeight(upperHeight);
-            }
-            else // right child
-            {
-                double lowerHeight = absoluteRect.height() - upperHeight;
-                absoluteRect.setHeight(lowerHeight);
-                absoluteRect.translate(0, upperHeight);
-            }
-        }
-    }
-
-    return rectInRect(absoluteRect, node->aspectRatio(), absoluteArea(node));
-}
-
-QRectF AtkinsPageLayoutTree::rectInRect(const QRectF &rect,
-                                        double aspectRatio,
-                                        double absoluteArea)
-{
-    double width  = std::sqrt(absoluteArea / aspectRatio);
-    double height = std::sqrt(absoluteArea * aspectRatio);
-    double x      = rect.x() + (rect.width()  - width)  / 2;
-    double y      = rect.y() + (rect.height() - height) / 2;
-
-    return QRectF(x, y, width, height);
-}
-
-} // Namespace Digikam
-
-
-
- - - diff --git a/static/reports/cppcheck/master/index.html b/static/reports/cppcheck/master/index.html index f17a67110..7ed4e45fe 100644 --- a/static/reports/cppcheck/master/index.html +++ b/static/reports/cppcheck/master/index.html @@ -1,95 +1,93 @@ - Cppcheck - HTML report - digiKam-master-rev-74ed235f83 + Cppcheck - HTML report - digiKam-master-rev-a04a0335ac
- - - - - - - - - - + + + + + + + +
LineIdCWESeverityMessage
*
unmatchedSuppressioninformationUnmatched suppression: ConfigurationNotChecked
unmatchedSuppressioninformationUnmatched suppression: purgedConfiguration
unmatchedSuppressioninformationUnmatched suppression: toomanyconfigs
unmatchedSuppressioninformationUnmatched suppression: unusedStructMember
unmatchedSuppressioninformationUnmatched suppression: unusedVariable
../../core/app/items/imageviewutilities.cpp
475noExplicitConstructor398styleStruct 'NumberInFilenameMatch' has a constructor with 1 argument that is not explicit.
../../core/libs/database/item/containers/itemcopyright.cpp
93operatorEqToSelf398warning'operator=' should check for assignment to self to avoid problems with dynamic memory.
../../core/libs/dimg/dshareddata.h
195operatorEqVarError398warningMember variable 'DSharedDataPointer::d' is not assigned a value in 'DSharedDataPointer::operator='.
../../core/libs/properties/captions/disjointmetadata.cpp
181operatorEqToSelf398warning'operator=' should check for assignment to self to avoid problems with dynamic memory.
../../core/utilities/assistants/printcreator/tools/atkinspagelayouttree.cpp
55operatorEqToSelf398warning'operator=' should check for assignment to self to avoid problems with dynamic memory.
../../core/libs/database/item/containers/itemcopyright.cpp
93operatorEqToSelf398warning'operator=' should check for assignment to self to avoid problems with dynamic memory.
../../core/libs/dimg/dshareddata.h
195operatorEqVarError398warningMember variable 'DSharedDataPointer::d' is not assigned a value in 'DSharedDataPointer::operator='.
../../core/libs/properties/captions/disjointmetadata.cpp
181operatorEqToSelf398warning'operator=' should check for assignment to self to avoid problems with dynamic memory.
../../core/utilities/assistants/printcreator/tools/atkinspagelayouttree.cpp
55operatorEqToSelf398warning'operator=' should check for assignment to self to avoid problems with dynamic memory.
diff --git a/static/reports/cppcheck/master/stats.html b/static/reports/cppcheck/master/stats.html index 43a609cb2..0ecc60cd4 100644 --- a/static/reports/cppcheck/master/stats.html +++ b/static/reports/cppcheck/master/stats.html @@ -1,65 +1,65 @@ - Cppcheck - HTML report - digiKam-master-rev-74ed235f83 + Cppcheck - HTML report - digiKam-master-rev-a04a0335ac