File indexing completed on 2025-01-19 03:59:39

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-01-20
0007  * Description : User interface for searches
0008  *
0009  * SPDX-FileCopyrightText: 2008-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "searchgroup_p.h"
0017 
0018 namespace Digikam
0019 {
0020 
0021 SearchGroup::SearchGroup(SearchView* const parent)
0022     : AbstractSearchGroupContainer(parent),
0023       m_view                      (parent),
0024       m_layout                    (nullptr),
0025       m_label                     (nullptr),
0026       m_subgroupLayout            (nullptr),
0027       m_groupType                 (FirstGroup)
0028 {
0029 }
0030 
0031 void SearchGroup::setup(Type type)
0032 {
0033     m_groupType = type;
0034 
0035     m_layout    = new QVBoxLayout;
0036     m_layout->setContentsMargins(QMargins());
0037     m_layout->setSpacing(0);
0038 
0039     m_label     = new SearchGroupLabel(m_view, m_groupType, this);
0040     m_layout->addWidget(m_label);
0041 
0042     connect(m_label, SIGNAL(removeClicked()),
0043             this, SIGNAL(removeRequested()));
0044 
0045     SearchFieldGroup*      group = nullptr;
0046     SearchFieldGroupLabel* label = nullptr;
0047 
0048     // To prevent Cppcheck warnings.
0049     (void)group;
0050     (void)label;
0051 
0052     // ----- //
0053 
0054     group    = new SearchFieldGroup(this);
0055     group->addField(SearchField::createField(QLatin1String("keyword"), group));
0056     m_fieldGroups << group;
0057     m_layout->addWidget(group);
0058 
0059     // this group has no label. Need to show, else it is hidden forever
0060 
0061     group->setFieldsVisible(true);
0062 
0063     // ----- //
0064 
0065     label = new SearchFieldGroupLabel(this);
0066     label->setTitle(i18n("File, Album, Tags"));
0067     group = new SearchFieldGroup(this);
0068     group->setLabel(label);
0069 
0070     group->addField(SearchField::createField(QLatin1String("albumid"),         group));
0071     group->addField(SearchField::createField(QLatin1String("albumname"),       group));
0072     group->addField(SearchField::createField(QLatin1String("albumcollection"), group));
0073     group->addField(SearchField::createField(QLatin1String("tagid"),           group));
0074     group->addField(SearchField::createField(QLatin1String("tagname"),         group));
0075     group->addField(SearchField::createField(QLatin1String("nottagged"),       group));
0076     group->addField(SearchField::createField(QLatin1String("filename"),        group));
0077 
0078     m_fieldLabels << label;
0079     m_fieldGroups << group;
0080     m_layout->addWidget(label);
0081     m_layout->addWidget(group);
0082 
0083     // ----- //
0084 
0085     label = new SearchFieldGroupLabel(this);
0086     label->setTitle(i18n("Picture Properties"));
0087     group = new SearchFieldGroup(this);
0088     group->setLabel(label);
0089 
0090     group->addField(SearchField::createField(QLatin1String("creationdate"),     group));
0091     group->addField(SearchField::createField(QLatin1String("creationtime"),     group));
0092     group->addField(SearchField::createField(QLatin1String("rating"),           group));
0093     group->addField(SearchField::createField(QLatin1String("labels"),           group));
0094     group->addField(SearchField::createField(QLatin1String("dimension"),        group));
0095     group->addField(SearchField::createField(QLatin1String("pageorientation"),  group));
0096     group->addField(SearchField::createField(QLatin1String("width"),            group));
0097     group->addField(SearchField::createField(QLatin1String("height"),           group));
0098     group->addField(SearchField::createField(QLatin1String("aspectratioimg"),   group));
0099     group->addField(SearchField::createField(QLatin1String("pixelsize"),        group));
0100     group->addField(SearchField::createField(QLatin1String("format"),           group));
0101     group->addField(SearchField::createField(QLatin1String("colordepth"),       group));
0102     group->addField(SearchField::createField(QLatin1String("colormodel"),       group));
0103     group->addField(SearchField::createField(QLatin1String("modificationdate"), group));
0104     group->addField(SearchField::createField(QLatin1String("digitizationdate"), group));
0105     group->addField(SearchField::createField(QLatin1String("filesize"),         group));
0106     group->addField(SearchField::createField(QLatin1String("bytesize"),         group));
0107     group->addField(SearchField::createField(QLatin1String("monthday"),         group));
0108 
0109     m_fieldLabels << label;
0110     m_fieldGroups << group;
0111     m_layout->addWidget(label);
0112     m_layout->addWidget(group);
0113 
0114     // ----- //
0115 
0116     label = new SearchFieldGroupLabel(this);
0117     label->setTitle(i18n("Audio/Video Properties"));
0118     group = new SearchFieldGroup(this);
0119     group->setLabel(label);
0120 
0121     group->addField(SearchField::createField(QLatin1String("videoaspectratio"),      group));
0122     group->addField(SearchField::createField(QLatin1String("videoduration"),         group));
0123     group->addField(SearchField::createField(QLatin1String("videoframerate"),        group));
0124     group->addField(SearchField::createField(QLatin1String("videocodec"),            group));
0125     group->addField(SearchField::createField(QLatin1String("videoaudiobitrate"),     group));
0126     group->addField(SearchField::createField(QLatin1String("videoaudiochanneltype"), group));
0127     group->addField(SearchField::createField(QLatin1String("videoaudioCodec"),       group));
0128 
0129     m_fieldLabels << label;
0130     m_fieldGroups << group;
0131     m_layout->addWidget(label);
0132     m_layout->addWidget(group);
0133 
0134     // ----- //
0135 
0136     label = new SearchFieldGroupLabel(this);
0137     label->setTitle(i18n("Caption, Comment, Title"));
0138     group = new SearchFieldGroup(this);
0139     group->setLabel(label);
0140 
0141     group->addField(SearchField::createField(QLatin1String("creator"),       group));
0142     group->addField(SearchField::createField(QLatin1String("comment"),       group));
0143     group->addField(SearchField::createField(QLatin1String("commentauthor"), group));
0144     group->addField(SearchField::createField(QLatin1String("headline"),      group));
0145     group->addField(SearchField::createField(QLatin1String("title"),         group));
0146     group->addField(SearchField::createField(QLatin1String("emptytext"),     group));
0147 
0148     m_fieldLabels << label;
0149     m_fieldGroups << group;
0150     m_layout->addWidget(label);
0151     m_layout->addWidget(group);
0152 
0153     // ----- //
0154 
0155     label = new SearchFieldGroupLabel(this);
0156     label->setTitle(i18n("Photograph Information"));
0157     group = new SearchFieldGroup(this);
0158     group->setLabel(label);
0159 
0160     group->addField(SearchField::createField(QLatin1String("make"),                         group));
0161     group->addField(SearchField::createField(QLatin1String("model"),                        group));
0162     group->addField(SearchField::createField(QLatin1String("lenses"),                       group));
0163     group->addField(SearchField::createField(QLatin1String("aperture"),                     group));
0164     group->addField(SearchField::createField(QLatin1String("focallength"),                  group));
0165     group->addField(SearchField::createField(QLatin1String("focallength35"),                group));
0166     group->addField(SearchField::createField(QLatin1String("exposuretime"),                 group));
0167     group->addField(SearchField::createField(QLatin1String("exposureprogram"),              group));
0168     group->addField(SearchField::createField(QLatin1String("exposuremode"),                 group));
0169     group->addField(SearchField::createField(QLatin1String("sensitivity"),                  group));
0170     group->addField(SearchField::createField(QLatin1String("orientation"),                  group));
0171     group->addField(SearchField::createField(QLatin1String("flashmode"),                    group));
0172     group->addField(SearchField::createField(QLatin1String("whitebalance"),                 group));
0173     group->addField(SearchField::createField(QLatin1String("whitebalancecolortemperature"), group));
0174     group->addField(SearchField::createField(QLatin1String("meteringmode"),                 group));
0175     group->addField(SearchField::createField(QLatin1String("subjectdistance"),              group));
0176     group->addField(SearchField::createField(QLatin1String("subjectdistancecategory"),      group));
0177 
0178     m_fieldLabels << label;
0179     m_fieldGroups << group;
0180     m_layout->addWidget(label);
0181     m_layout->addWidget(group);
0182 
0183     // ----- //
0184 
0185     label = new SearchFieldGroupLabel(this);
0186     label->setTitle(i18n("Geographic position"));
0187     group = new SearchFieldGroup(this);
0188     group->setLabel(label);
0189 
0190 /*
0191     group->addField(SearchField::createField("latitude", group));
0192     group->addField(SearchField::createField("longitude", group));
0193 */
0194     group->addField(SearchField::createField(QLatin1String("altitude"),      group));
0195     group->addField(SearchField::createField(QLatin1String("nogps"),         group));
0196     group->addField(SearchField::createField(QLatin1String("country"),       group));
0197     group->addField(SearchField::createField(QLatin1String("provinceState"), group));
0198     group->addField(SearchField::createField(QLatin1String("city"),          group));
0199     group->addField(SearchField::createField(QLatin1String("location"),      group));
0200 
0201     m_fieldLabels << label;
0202     m_fieldGroups << group;
0203     m_layout->addWidget(label);
0204     m_layout->addWidget(group);
0205 
0206     // ----- //
0207 
0208     label = new SearchFieldGroupLabel(this);
0209     label->setTitle(i18n("Face regions"));
0210     group = new SearchFieldGroup(this);
0211     group->setLabel(label);
0212 
0213     group->addField(SearchField::createField(QLatin1String("faceregionscount"), group));
0214     group->addField(SearchField::createField(QLatin1String("nofaceregions"),    group));
0215 
0216     m_fieldLabels << label;
0217     m_fieldGroups << group;
0218     m_layout->addWidget(label);
0219     m_layout->addWidget(group);
0220 
0221     // ----- //
0222 
0223     // prepare subgroup layout
0224 
0225     QHBoxLayout* const indentLayout = new QHBoxLayout;
0226     indentLayout->setContentsMargins(QMargins());
0227     indentLayout->setSpacing(0);
0228 
0229     QStyleOption option;
0230     option.initFrom(this);
0231     int indent = 5 * style()->pixelMetric(QStyle::PM_LayoutLeftMargin, &option, this);
0232     indent     = qMax(indent, 20);
0233     indentLayout->addSpacing(indent);
0234 
0235     m_subgroupLayout = new QVBoxLayout;
0236     m_subgroupLayout->setContentsMargins(QMargins());
0237     m_subgroupLayout->setSpacing(0);
0238 
0239     indentLayout->addLayout(m_subgroupLayout);
0240 
0241     m_layout->addLayout(indentLayout);
0242 
0243     // ----- //
0244 
0245     m_layout->addStretch(1);
0246     setLayout(m_layout);
0247 
0248     // ----- //
0249 
0250     // initialization as empty group
0251 
0252     reset();
0253 }
0254 
0255 void SearchGroup::read(SearchXmlCachingReader& reader)
0256 {
0257     reset();
0258 
0259     m_label->setGroupOperator(reader.groupOperator());
0260     m_label->setDefaultFieldOperator(reader.defaultFieldOperator());
0261 
0262     startReadingGroups(reader);
0263 
0264     while (!reader.atEnd())
0265     {
0266         reader.readNext();
0267 
0268         if (reader.isEndElement())
0269         {
0270             break;
0271         }
0272 
0273         // subgroup
0274 
0275         if (reader.isGroupElement())
0276         {
0277             readGroup(reader);
0278         }
0279 
0280         if (reader.isFieldElement())
0281         {
0282             QString name = reader.fieldName();
0283 
0284             SearchField* field           = nullptr;
0285             SearchFieldGroup* fieldGroup = nullptr;
0286 
0287             Q_FOREACH (fieldGroup, m_fieldGroups)
0288             {
0289                 if (fieldGroup)
0290                 {
0291                     if ((field = fieldGroup->fieldForName(name)))
0292                     {
0293                         // cppcheck-suppress useStlAlgorithm
0294                         break;
0295                     }
0296                 }
0297             }
0298 
0299             if (field)
0300             {
0301                 field->read(reader);
0302                 fieldGroup->markField(field);
0303                 fieldGroup->setFieldsVisible(true);
0304             }
0305             else
0306             {
0307                 qCWarning(DIGIKAM_GENERAL_LOG) << "Unhandled search field in XML with field name" << name;
0308                 reader.readToEndOfElement();
0309             }
0310         }
0311     }
0312 
0313     finishReadingGroups();
0314 }
0315 
0316 SearchGroup* SearchGroup::createSearchGroup()
0317 {
0318     // create a sub group - view is the same
0319 
0320     SearchGroup* const group = new SearchGroup(m_view);
0321     group->setup(SearchGroup::ChainGroup);
0322 
0323     return group;
0324 }
0325 
0326 void SearchGroup::addGroupToLayout(SearchGroup* group)
0327 {
0328     // insert in front of the stretch
0329 
0330     m_subgroupLayout->addWidget(group);
0331 }
0332 
0333 void SearchGroup::write(SearchXmlWriter& writer)
0334 {
0335     writer.writeGroup();
0336     writer.setGroupOperator(m_label->groupOperator());
0337     writer.setDefaultFieldOperator(m_label->defaultFieldOperator());
0338 
0339     Q_FOREACH (SearchFieldGroup* const fieldGroup, m_fieldGroups)
0340     {
0341         fieldGroup->write(writer);
0342     }
0343 
0344     // take care for subgroups
0345 
0346     writeGroups(writer);
0347 
0348     writer.finishGroup();
0349 }
0350 
0351 void SearchGroup::reset()
0352 {
0353     Q_FOREACH (SearchFieldGroup* const fieldGroup, m_fieldGroups)
0354     {
0355         fieldGroup->reset();
0356     }
0357 
0358     m_label->setGroupOperator(SearchXml::standardGroupOperator());
0359     m_label->setDefaultFieldOperator(SearchXml::standardFieldOperator());
0360 }
0361 
0362 SearchGroup::Type SearchGroup::groupType() const
0363 {
0364     return m_groupType;
0365 }
0366 
0367 QList<QRect> SearchGroup::startupAnimationArea() const
0368 {
0369     QList<QRect> rects;
0370 
0371     // from subgroups;
0372 
0373     rects += startupAnimationAreaOfGroups();
0374 
0375     // field groups
0376 
0377     Q_FOREACH (SearchFieldGroup* fieldGroup, m_fieldGroups)
0378     {
0379         // cppcheck-suppress useStlAlgorithm
0380         rects += fieldGroup->areaOfMarkedFields();
0381     }
0382 
0383     // adjust position relative to parent
0384 
0385     for (QList<QRect>::iterator it = rects.begin() ; it != rects.end() ; ++it)
0386     {
0387         (*it).translate(pos());
0388     }
0389 
0390     return rects;
0391 }
0392 
0393 } // namespace Digikam
0394 
0395 #include "moc_searchgroup.cpp"