File indexing completed on 2023-09-24 08:19:51
0001 /* ============================================================ 0002 * 0003 * This file is a part of KDE project 0004 * 0005 * 0006 * Date : 2009-05-22 0007 * Description : Flickr/23HQ file list view and items. 0008 * 0009 * Copyright (C) 2009 by Pieter Edelman <pieter dot edelman at gmx dot net> 0010 * 0011 * This program is free software; you can redistribute it 0012 * and/or modify it under the terms of the GNU General 0013 * Public License as published by the Free Software Foundation; 0014 * either version 2, or (at your option) any later version. 0015 * 0016 * This program is distributed in the hope that it will be useful, 0017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0019 * GNU General Public License for more details. 0020 * 0021 * ============================================================ */ 0022 0023 #include "flickrlist.h" 0024 0025 // Qt includes 0026 0027 #include <QApplication> 0028 #include <QComboBox> 0029 #include <QPainter> 0030 0031 // KDE includes 0032 0033 #include <klocalizedstring.h> 0034 0035 // Local includes 0036 0037 #include "kipiplugins_debug.h" 0038 #include "comboboxdelegate.h" 0039 0040 namespace KIPIFlickrPlugin 0041 { 0042 0043 FlickrList::FlickrList(QWidget* const parent, bool is_23) 0044 : KPImagesList(parent), 0045 m_public(Qt::Unchecked), 0046 m_family(Qt::Unchecked), 0047 m_friends(Qt::Unchecked), 0048 m_safetyLevel(FlickrList::SAFE), 0049 m_contentType(FlickrList::PHOTO), 0050 m_userIsEditing(false), 0051 m_is23(is_23) 0052 { 0053 // Catch a click on the items. 0054 connect(listView(), SIGNAL(itemClicked(QTreeWidgetItem*,int)), 0055 this, SLOT(slotItemClicked(QTreeWidgetItem*,int))); 0056 0057 // Catch it if the items change. 0058 connect(listView(), SIGNAL(itemChanged(QTreeWidgetItem*,int)), 0059 this, SLOT(slotItemChanged(QTreeWidgetItem*,int))); 0060 } 0061 0062 void FlickrList::setPublic(Qt::CheckState isPublic) 0063 { 0064 /* Change the general public flag for photos in the list. */ 0065 m_public = isPublic; 0066 setPermissionState(PUBLIC, isPublic); 0067 } 0068 0069 void FlickrList::setFamily(Qt::CheckState isFamily) 0070 { 0071 /* Change the general family flag for photos in the list. */ 0072 m_family = isFamily; 0073 setPermissionState(FAMILY, m_family); 0074 } 0075 0076 void FlickrList::setFriends(Qt::CheckState isFriends) 0077 { 0078 /* Change the general friends flag for photos in the list. */ 0079 m_friends = isFriends; 0080 setPermissionState(FRIENDS, m_friends); 0081 } 0082 0083 void FlickrList::setSafetyLevels(SafetyLevel safetyLevel) 0084 { 0085 /* Change the general safety level for photos in the list. */ 0086 m_safetyLevel = safetyLevel; 0087 0088 if (safetyLevel != MIXEDLEVELS) 0089 { 0090 for (int i = 0; i < listView()->topLevelItemCount(); ++i) 0091 { 0092 FlickrListViewItem* const lvItem = dynamic_cast<FlickrListViewItem*>(listView()->topLevelItem(i)); 0093 0094 if (lvItem) 0095 lvItem->setSafetyLevel(m_safetyLevel); 0096 } 0097 } 0098 } 0099 0100 void FlickrList::setContentTypes(ContentType contentType) 0101 { 0102 /* Change the general content type for photos in the list. */ 0103 m_contentType = contentType; 0104 0105 if (contentType != MIXEDTYPES) 0106 { 0107 for (int i = 0; i < listView()->topLevelItemCount(); ++i) 0108 { 0109 FlickrListViewItem* const lvItem = dynamic_cast<FlickrListViewItem*>(listView()->topLevelItem(i)); 0110 0111 if (lvItem) 0112 lvItem->setContentType(m_contentType); 0113 } 0114 } 0115 } 0116 0117 void FlickrList::setPermissionState(FieldType type, Qt::CheckState state) 0118 { 0119 /* When the state of one of the three permission levels changes, distribute 0120 * the global change to each individual photo. */ 0121 0122 if (state != Qt::PartiallyChecked) 0123 { 0124 for (int i = 0; i < listView()->topLevelItemCount(); ++i) 0125 { 0126 FlickrListViewItem* const lvItem = dynamic_cast<FlickrListViewItem*>(listView()->topLevelItem(i)); 0127 0128 if (lvItem) 0129 { 0130 if (type == PUBLIC) 0131 { 0132 lvItem->setPublic(state); 0133 } 0134 else if (type == FAMILY) 0135 { 0136 lvItem->setFamily(state); 0137 } 0138 else if (type == FRIENDS) 0139 { 0140 lvItem->setFriends(state); 0141 } 0142 } 0143 } 0144 } 0145 } 0146 0147 void FlickrList::slotItemClicked(QTreeWidgetItem* item, int column) 0148 { 0149 // If a click occurs from one of the three permission checkbox columns, 0150 // it means something has changed in the permissions. 0151 if ((column == PUBLIC) || (column == FAMILY) || (column == FRIENDS)) 0152 { 0153 singlePermissionChanged(item, column); 0154 } 0155 // If a click occurs in the Safety Level or Content Type column, it means 0156 // that editing should start on these items. 0157 else if ((column == static_cast<int>(FlickrList::SAFETYLEVEL)) || (column == static_cast<int>(FlickrList::CONTENTTYPE))) 0158 { 0159 m_userIsEditing = true; 0160 ComboBoxDelegate* const cbDelegate = dynamic_cast<ComboBoxDelegate*>(listView()->itemDelegateForColumn(column)); 0161 0162 if (cbDelegate) 0163 { 0164 cbDelegate->startEditing(item, column); 0165 } 0166 } 0167 } 0168 0169 void FlickrList::slotItemChanged(QTreeWidgetItem* item, int column) 0170 { 0171 // If an item in the Safety Level or Content Type column changes, it should 0172 // be distributed further. 0173 if ((column == SAFETYLEVEL) || (column == CONTENTTYPE)) 0174 { 0175 singleComboBoxChanged(item, column); 0176 } 0177 } 0178 0179 void FlickrList::singlePermissionChanged(QTreeWidgetItem* item, int column) 0180 { 0181 /* Callback for when the user clicks a checkbox in one of the permission 0182 * columns. */ 0183 0184 if ((column == PUBLIC) || (column == FAMILY) || (column == FRIENDS)) 0185 { 0186 // Call the toggled() method of the item on which the selection 0187 // occurred. 0188 FlickrListViewItem* const lvItem = dynamic_cast<FlickrListViewItem*>(item); 0189 0190 if (lvItem) 0191 { 0192 lvItem->toggled(); 0193 0194 // Count the number of set checkboxes for the selected column. 0195 int numChecked = 0; 0196 0197 for (int i = 0; i < listView()->topLevelItemCount(); ++i) 0198 { 0199 FlickrListViewItem* const titem = dynamic_cast<FlickrListViewItem*>(listView()->topLevelItem(i)); 0200 0201 if (titem) 0202 { 0203 if (((column == PUBLIC) && (titem->isPublic())) || 0204 ((column == FAMILY) && (titem->isFamily())) || 0205 ((column == FRIENDS) && (titem->isFriends()))) 0206 { 0207 numChecked += 1; 0208 } 0209 } 0210 } 0211 0212 // Determine the new state. 0213 Qt::CheckState state = Qt::PartiallyChecked; 0214 0215 if (numChecked == 0) 0216 { 0217 state = Qt::Unchecked; 0218 } 0219 else if (numChecked == listView()->topLevelItemCount()) 0220 { 0221 state = Qt::Checked; 0222 } 0223 0224 // If needed, signal the change. 0225 if ((column == PUBLIC) && (state != m_public)) 0226 { 0227 setPublic(state); 0228 Q_EMIT signalPermissionChanged(PUBLIC, state); 0229 } 0230 0231 if ((column == FAMILY) && (state != m_family)) 0232 { 0233 setFamily(state); 0234 Q_EMIT signalPermissionChanged(FAMILY, state); 0235 } 0236 0237 if ((column == FRIENDS) && (state != m_friends)) 0238 { 0239 setFriends(state); 0240 Q_EMIT signalPermissionChanged(FRIENDS, state); 0241 } 0242 } 0243 } 0244 } 0245 0246 void FlickrList::singleComboBoxChanged(QTreeWidgetItem* item, int column) 0247 { 0248 /* Callback for when one of the comboboxes for Safety Level or Content 0249 * Type changes. */ 0250 0251 // Make sure to only process changes from user editing, because this 0252 // function also responds to programmatic changes, which it causes itself 0253 // again. 0254 if (((column == SAFETYLEVEL) || (column == CONTENTTYPE)) && m_userIsEditing) 0255 { 0256 // The user has stopped editing. 0257 m_userIsEditing = false; 0258 0259 // Convert the value from the model to the setting for the 0260 // FlickrListViewItem. 0261 FlickrListViewItem* const lvItem = dynamic_cast<FlickrListViewItem*>(item); 0262 0263 if (lvItem) 0264 { 0265 int data = lvItem->data(column, Qt::DisplayRole).toInt(); 0266 0267 if (column == SAFETYLEVEL) 0268 { 0269 lvItem->setSafetyLevel(static_cast<SafetyLevel>(data)); 0270 } 0271 else if (column == CONTENTTYPE) 0272 { 0273 lvItem->setContentType(static_cast<ContentType>(data)); 0274 } 0275 0276 // Determine how much photos are set to different Safety Levels/Content 0277 // Types. 0278 QMap<int, int> nums = QMap<int, int>(); 0279 0280 for (int i = 0; i < listView()->topLevelItemCount(); ++i) 0281 { 0282 FlickrListViewItem* const titem = dynamic_cast<FlickrListViewItem*>(listView()->topLevelItem(i)); 0283 0284 if (titem) 0285 { 0286 if (column == SAFETYLEVEL) 0287 { 0288 nums[lvItem->safetyLevel()]++; 0289 } 0290 else if (column == CONTENTTYPE) 0291 { 0292 nums[lvItem->contentType()]++; 0293 } 0294 } 0295 } 0296 0297 // If there's only one Safety Level or Content Type, make everything 0298 // uniform 0299 if (nums.count() == 1) 0300 { 0301 QMapIterator<int, int> i(nums); 0302 i.next(); 0303 0304 if (column == SAFETYLEVEL) 0305 { 0306 SafetyLevel safetyLevel = static_cast<SafetyLevel>(i.key()); 0307 setSafetyLevels(safetyLevel); 0308 Q_EMIT signalSafetyLevelChanged(safetyLevel); 0309 } 0310 else if (column == CONTENTTYPE) 0311 { 0312 ContentType contentType = static_cast<ContentType>(i.key()); 0313 setContentTypes(contentType); 0314 Q_EMIT signalContentTypeChanged(contentType); 0315 } 0316 } 0317 // If there are different Safety Levels/Content Types among the photos, 0318 // signal that. 0319 else 0320 { 0321 if (column == SAFETYLEVEL) 0322 { 0323 setSafetyLevels(MIXEDLEVELS); 0324 Q_EMIT signalSafetyLevelChanged(MIXEDLEVELS); 0325 } 0326 else if (column == CONTENTTYPE) 0327 { 0328 setContentTypes(MIXEDTYPES); 0329 Q_EMIT signalContentTypeChanged(MIXEDTYPES); 0330 } 0331 } 0332 } 0333 } 0334 } 0335 0336 void FlickrList::slotAddImages(const QList<QUrl>& list) 0337 { 0338 /* Replaces the ImagesList::slotAddImages method, so that 0339 * FlickrListViewItems can be added instead of ImagesListViewItems */ 0340 0341 // Figure out which permissions should be used. If permissions are set to 0342 // intermediate, default to the most public option. 0343 bool isPublic, isFamily, isFriends; 0344 (m_public == Qt::PartiallyChecked) ? isPublic = true : isPublic = m_public; 0345 (m_family == Qt::PartiallyChecked) ? isFamily = true : isFamily = m_family; 0346 (m_friends == Qt::PartiallyChecked) ? isFriends = true : isFriends = m_friends; 0347 0348 // Figure out safety level and content type. If these are intermediate, use 0349 // the Flickr defaults. 0350 SafetyLevel safetyLevel; 0351 ContentType contentType; 0352 (m_safetyLevel == MIXEDLEVELS) ? safetyLevel = SAFE : safetyLevel = m_safetyLevel; 0353 (m_contentType == MIXEDTYPES) ? contentType = PHOTO : contentType = m_contentType; 0354 0355 // Figure out which of the supplied URL's should actually be added and which 0356 // of them already exist. 0357 bool found; 0358 QList<QUrl> added_urls; 0359 QList<QUrl>::const_iterator it; 0360 0361 for (it = list.constBegin(); it != list.constEnd(); ++it) 0362 { 0363 QUrl imageUrl = *it; 0364 found = false; 0365 0366 for (int i = 0; i < listView()->topLevelItemCount(); ++i) 0367 { 0368 FlickrListViewItem* const currItem = dynamic_cast<FlickrListViewItem*>(listView()->topLevelItem(i)); 0369 0370 if (currItem && currItem->url() == imageUrl) 0371 { 0372 found = true; 0373 break; 0374 } 0375 } 0376 0377 if (!found) 0378 { 0379 qCDebug(KIPIPLUGINS_LOG) << "Insterting new item " << imageUrl.fileName(); 0380 new FlickrListViewItem(listView(), imageUrl, m_is23, 0381 isPublic, isFamily, isFriends, 0382 safetyLevel, contentType); 0383 added_urls.append(imageUrl); 0384 } 0385 } 0386 0387 // Duplicate the signalImageListChanged of the ImageWindow, to enable the 0388 // upload button again. 0389 Q_EMIT signalImageListChanged(); 0390 } 0391 0392 // ------------------------------------------------------------------------------------------------ 0393 0394 FlickrListViewItem::FlickrListViewItem(KPImagesListView* const view, 0395 const QUrl& url, 0396 bool is23 = false, 0397 bool accessPublic = true, 0398 bool accessFamily = true, 0399 bool accessFriends = true, 0400 FlickrList::SafetyLevel safetyLevel = FlickrList::SAFE, 0401 FlickrList::ContentType contentType = FlickrList::PHOTO) 0402 : KPImagesListViewItem(view, url), 0403 m_is23(is23) 0404 { 0405 /* Initialize the FlickrListViewItem with the ImagesListView and a QUrl 0406 * object pointing to the location on disk. 0407 * If the photo is meant for 23HQ, the service_23 flag should be set to 0408 * true. 0409 * The access_public, access_family and access_friends flags determine if 0410 * the public, family and friends permissions of this particular photo. */ 0411 0412 // Set the flags for checkboxes to appear 0413 setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsEnabled); 0414 0415 // Set the text and checkbox for the public column. 0416 setCheckState(static_cast<KPImagesListView::ColumnType>(FlickrList::PUBLIC), accessPublic ? Qt::Checked : Qt::Unchecked); 0417 0418 // Set the tooltips to guide the user to the mass settings options. 0419 setToolTip(static_cast<KPImagesListView::ColumnType>(FlickrList::PUBLIC), 0420 i18n("Check if photo should be publicly visible or use Upload " 0421 "Options tab to specify this for all images")); 0422 setToolTip(static_cast<KPImagesListView::ColumnType>(FlickrList::FAMILY), 0423 i18n("Check if photo should be visible to family or use Upload " 0424 "Options tab to specify this for all images")); 0425 setToolTip(static_cast<KPImagesListView::ColumnType>(FlickrList::FRIENDS), 0426 i18n("Check if photo should be visible to friends or use " 0427 "Upload Options tab to specify this for all images")); 0428 setToolTip(static_cast<KPImagesListView::ColumnType>(FlickrList::SAFETYLEVEL), 0429 i18n("Indicate the safety level for the photo or use Upload " 0430 "Options tab to specify this for all images")); 0431 setToolTip(static_cast<KPImagesListView::ColumnType>(FlickrList::CONTENTTYPE), 0432 i18n("Indicate what kind of image this is or use Upload " 0433 "Options tab to specify this for all images")); 0434 0435 // Set the other checkboxes. 0436 setFamily(accessFamily); 0437 setFriends(accessFriends); 0438 setPublic(accessPublic); 0439 setSafetyLevel(safetyLevel); 0440 setContentType(contentType); 0441 0442 // Extra per image tags handling. 0443 setToolTip(static_cast<KPImagesListView::ColumnType>( 0444 FlickrList::TAGS), 0445 i18n("Add extra tags per image or use Upload Options tab to " 0446 "add tags for all images")); 0447 //m_tagLineEdit = new QLineEdit(view); 0448 //m_tagLineEdit->setToolTip(i18n("Enter extra tags, separated by commas.")); 0449 //view->setItemWidget(this, static_cast<KPImagesListView::ColumnType>( 0450 // FlickrList::TAGS), m_tagLineEdit); 0451 updateItemWidgets(); 0452 } 0453 0454 FlickrListViewItem::~FlickrListViewItem() 0455 { 0456 0457 } 0458 0459 void FlickrListViewItem::updateItemWidgets() 0460 { 0461 m_tagLineEdit = new QLineEdit(view()); 0462 m_tagLineEdit->setToolTip(i18n("Enter extra tags, separated by commas.")); 0463 view()->setItemWidget(this, static_cast<KPImagesListView::ColumnType>( 0464 FlickrList::TAGS), m_tagLineEdit); 0465 } 0466 0467 QStringList FlickrListViewItem::extraTags() const 0468 { 0469 return m_tagLineEdit->text().split(QLatin1Char(','), Qt::SkipEmptyParts); 0470 } 0471 0472 void FlickrListViewItem::toggled() 0473 { 0474 // The m_family and m_friends states should be set first, so that the 0475 // setPublic method has the proper values to work with. 0476 if (!m_is23) 0477 { 0478 if (data(FlickrList::FAMILY, Qt::CheckStateRole) != QVariant()) 0479 { 0480 setFamily(checkState(static_cast<KPImagesListView::ColumnType>(FlickrList::FAMILY))); 0481 } 0482 0483 if (data(FlickrList::FRIENDS, Qt::CheckStateRole) != QVariant()) 0484 { 0485 setFriends(checkState(static_cast<KPImagesListView::ColumnType>(FlickrList::FRIENDS))); 0486 } 0487 } 0488 0489 setPublic(checkState(static_cast<KPImagesListView::ColumnType>(FlickrList::PUBLIC))); 0490 } 0491 0492 void FlickrListViewItem::setPublic(bool status) 0493 { 0494 /* Set the public status of the entry. If public is true, hide the 0495 * family and friends checkboxes, otherwise, make them appear. */ 0496 0497 // Set the status. 0498 m_public = status; 0499 0500 // Toggle the family and friends checkboxes, if applicable. 0501 if (!m_is23) 0502 { 0503 if (m_public) 0504 { 0505 // Hide the checkboxes by feeding them a null QVariant for the 0506 // CheckStateRole. This might seem like a hack, but it was described in 0507 // some lost old Qt FAQ, now e.g. told in https://forum.qt.io/topic/85204/how-to-hide-checkbox-of-qstandarditem 0508 setData(static_cast<KPImagesListView::ColumnType>(FlickrList::FAMILY), Qt::CheckStateRole, QVariant()); 0509 setData(static_cast<KPImagesListView::ColumnType>(FlickrList::FRIENDS), Qt::CheckStateRole, QVariant()); 0510 } 0511 else 0512 { 0513 // Show the checkboxes. 0514 setCheckState(static_cast<KPImagesListView::ColumnType>(FlickrList::FAMILY), m_family ? Qt::Checked : Qt::Unchecked); 0515 setCheckState(static_cast<KPImagesListView::ColumnType>(FlickrList::FRIENDS), m_friends ? Qt::Checked : Qt::Unchecked); 0516 } 0517 } 0518 0519 // Toggle the public checkboxes 0520 if (m_public) 0521 { 0522 setCheckState(FlickrList::PUBLIC, Qt::Checked); 0523 } 0524 else 0525 { 0526 setCheckState(FlickrList::PUBLIC, Qt::Unchecked); 0527 } 0528 0529 qCDebug(KIPIPLUGINS_LOG) << "Public status set to" << m_public; 0530 } 0531 0532 void FlickrListViewItem::setFamily(bool status) 0533 { 0534 /* Set the family status. */ 0535 m_family = status; 0536 0537 if ((!m_is23) && (data(FlickrList::FAMILY, Qt::CheckStateRole) != QVariant())) 0538 { 0539 setCheckState(FlickrList::FAMILY, m_family ? Qt::Checked : Qt::Unchecked); 0540 } 0541 0542 qCDebug(KIPIPLUGINS_LOG) << "Family status set to" << m_family; 0543 } 0544 0545 void FlickrListViewItem::setFriends(bool status) 0546 { 0547 /* Set the family status. */ 0548 m_friends = status; 0549 0550 if ((!m_is23) && (data(FlickrList::FRIENDS, Qt::CheckStateRole) != QVariant())) 0551 { 0552 setCheckState(FlickrList::FRIENDS, m_friends ? Qt::Checked : Qt::Unchecked); 0553 } 0554 0555 qCDebug(KIPIPLUGINS_LOG) << "Friends status set to" << m_friends; 0556 } 0557 0558 void FlickrListViewItem::setSafetyLevel(FlickrList::SafetyLevel safetyLevel) 0559 { 0560 m_safetyLevel = safetyLevel; 0561 setData(FlickrList::SAFETYLEVEL, Qt::DisplayRole, QVariant(safetyLevel)); 0562 qCDebug(KIPIPLUGINS_LOG) << "Safety level set to" << safetyLevel; 0563 } 0564 0565 void FlickrListViewItem::setContentType(FlickrList::ContentType contentType) 0566 { 0567 m_contentType = contentType; 0568 setData(FlickrList::CONTENTTYPE, Qt::DisplayRole, QVariant(contentType)); 0569 qCDebug(KIPIPLUGINS_LOG) << "Content type set to" << contentType; 0570 } 0571 0572 bool FlickrListViewItem::isPublic() const 0573 { 0574 /* Return whether the photo is public. */ 0575 return m_public; 0576 } 0577 0578 bool FlickrListViewItem::isFamily() const 0579 { 0580 /* Return whether the photo is accessible for family. */ 0581 return m_family; 0582 } 0583 0584 bool FlickrListViewItem::isFriends() const 0585 { 0586 /* Return whether the photo is accessible for friends. */ 0587 return m_friends; 0588 } 0589 0590 FlickrList::SafetyLevel FlickrListViewItem::safetyLevel() const 0591 { 0592 return m_safetyLevel; 0593 } 0594 0595 FlickrList::ContentType FlickrListViewItem::contentType() const 0596 { 0597 return m_contentType; 0598 } 0599 0600 } // namespace KIPIFlickrPlugin 0601 0602 #include "moc_flickrlist.cpp"