DigiKam – digital photo management application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1042 lines
27KB

  1. /* ============================================================
  2. *
  3. * This file is a part of digiKam project
  4. * http://www.digikam.org
  5. *
  6. * Date : 2005-03-22
  7. * Descritpion : tags folder view.
  8. *
  9. * Copyright (C) 2005-2006 by Joern Ahrens <joern.ahrens@kdemail.net>
  10. * Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
  11. * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmx dot net>
  12. *
  13. * This program is free software; you can redistribute it
  14. * and/or modify it under the terms of the GNU General
  15. * Public License as published by the Free Software Foundation;
  16. * either version 2, or (at your option)
  17. * any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * ============================================================ */
  25. // TQt includes.
  26. #include <tqpainter.h>
  27. #include <tqcursor.h>
  28. #include <tqlistview.h>
  29. // KDE includes.
  30. #include <tdepopupmenu.h>
  31. #include <tdelocale.h>
  32. #include <tdeabc/stdaddressbook.h>
  33. #include <kiconloader.h>
  34. #include <tdeapplication.h>
  35. #include <tdemessagebox.h>
  36. // Local includes.
  37. #include "ddebug.h"
  38. #include "album.h"
  39. #include "albumdb.h"
  40. #include "albummanager.h"
  41. #include "albumsettings.h"
  42. #include "albumlister.h"
  43. #include "syncjob.h"
  44. #include "tageditdlg.h"
  45. #include "dragobjects.h"
  46. #include "folderitem.h"
  47. #include "dio.h"
  48. #include "imageattributeswatch.h"
  49. #include "imageinfo.h"
  50. #include "metadatahub.h"
  51. #include "albumthumbnailloader.h"
  52. #include "statusprogressbar.h"
  53. #include "tagfolderview.h"
  54. #include "tagfolderview.moc"
  55. // X11 includes.
  56. extern "C"
  57. {
  58. #include <X11/Xlib.h>
  59. }
  60. namespace Digikam
  61. {
  62. class TagFolderViewItem : public FolderItem
  63. {
  64. public:
  65. TagFolderViewItem(TQListView *parent, TAlbum *album);
  66. TagFolderViewItem(TQListViewItem *parent, TAlbum *album);
  67. TAlbum* album() const;
  68. int id() const;
  69. void refresh();
  70. void setOpen(bool o);
  71. void setCount(int count);
  72. int count();
  73. private:
  74. int m_count;
  75. TAlbum *m_album;
  76. };
  77. TagFolderViewItem::TagFolderViewItem(TQListView *parent, TAlbum *album)
  78. : FolderItem(parent, album->title())
  79. {
  80. setDragEnabled(true);
  81. m_album = album;
  82. m_count = 0;
  83. }
  84. TagFolderViewItem::TagFolderViewItem(TQListViewItem *parent, TAlbum *album)
  85. : FolderItem(parent, album->title())
  86. {
  87. setDragEnabled(true);
  88. m_album = album;
  89. m_count = 0;
  90. }
  91. void TagFolderViewItem::refresh()
  92. {
  93. if (!m_album) return;
  94. if (AlbumSettings::instance()->getShowFolderTreeViewItemsCount() &&
  95. dynamic_cast<TagFolderViewItem*>(parent()))
  96. {
  97. if (isOpen())
  98. setText(0, TQString("%1 (%2)").arg(m_album->title()).arg(m_count));
  99. else
  100. {
  101. int countRecursive = m_count;
  102. AlbumIterator it(m_album);
  103. while ( it.current() )
  104. {
  105. TagFolderViewItem *item = (TagFolderViewItem*)it.current()->extraData(listView());
  106. if (item)
  107. countRecursive += item->count();
  108. ++it;
  109. }
  110. setText(0, TQString("%1 (%2)").arg(m_album->title()).arg(countRecursive));
  111. }
  112. }
  113. else
  114. {
  115. setText(0, m_album->title());
  116. }
  117. }
  118. void TagFolderViewItem::setOpen(bool o)
  119. {
  120. TQListViewItem::setOpen(o);
  121. refresh();
  122. }
  123. TAlbum* TagFolderViewItem::album() const
  124. {
  125. return m_album;
  126. }
  127. int TagFolderViewItem::id() const
  128. {
  129. return m_album ? m_album->id() : 0;
  130. }
  131. void TagFolderViewItem::setCount(int count)
  132. {
  133. m_count = count;
  134. refresh();
  135. }
  136. int TagFolderViewItem::count()
  137. {
  138. return m_count;
  139. }
  140. //-----------------------------------------------------------------------------
  141. class TagFolderViewPriv
  142. {
  143. public:
  144. TagFolderViewPriv()
  145. {
  146. ABCMenu = 0;
  147. albumMan = 0;
  148. }
  149. TQPopupMenu *ABCMenu;
  150. AlbumManager *albumMan;
  151. };
  152. TagFolderView::TagFolderView(TQWidget *parent)
  153. : FolderView(parent, "TagFolderView")
  154. {
  155. d = new TagFolderViewPriv();
  156. d->albumMan = AlbumManager::instance();
  157. addColumn(i18n("My Tags"));
  158. setResizeMode(TQListView::LastColumn);
  159. setRootIsDecorated(false);
  160. setAcceptDrops(true);
  161. viewport()->setAcceptDrops(true);
  162. // ------------------------------------------------------------------------
  163. connect(d->albumMan, TQT_SIGNAL(signalTAlbumsDirty(const TQMap<int, int>&)),
  164. this, TQT_SLOT(slotRefresh(const TQMap<int, int>&)));
  165. connect(d->albumMan, TQT_SIGNAL(signalAlbumAdded(Album*)),
  166. this, TQT_SLOT(slotAlbumAdded(Album*)));
  167. connect(d->albumMan, TQT_SIGNAL(signalAlbumDeleted(Album*)),
  168. this, TQT_SLOT(slotAlbumDeleted(Album*)));
  169. connect(d->albumMan, TQT_SIGNAL(signalAlbumRenamed(Album*)),
  170. this, TQT_SLOT(slotAlbumRenamed(Album*)));
  171. connect(d->albumMan, TQT_SIGNAL(signalAlbumsCleared()),
  172. this, TQT_SLOT(slotAlbumsCleared()));
  173. connect(d->albumMan, TQT_SIGNAL(signalAlbumIconChanged(Album*)),
  174. this, TQT_SLOT(slotAlbumIconChanged(Album*)));
  175. connect(d->albumMan, TQT_SIGNAL(signalTAlbumMoved(TAlbum*, TAlbum*)),
  176. this, TQT_SLOT(slotAlbumMoved(TAlbum*, TAlbum*)));
  177. // ------------------------------------------------------------------------
  178. AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance();
  179. connect(loader, TQT_SIGNAL(signalThumbnail(Album *, const TQPixmap&)),
  180. this, TQT_SLOT(slotGotThumbnailFromIcon(Album *, const TQPixmap&)));
  181. connect(loader, TQT_SIGNAL(signalFailed(Album *)),
  182. this, TQT_SLOT(slotThumbnailLost(Album *)));
  183. connect(loader, TQT_SIGNAL(signalReloadThumbnails()),
  184. this, TQT_SLOT(slotReloadThumbnails()));
  185. connect(this, TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
  186. TQT_SLOT(slotContextMenu(TQListViewItem*, const TQPoint&, int)));
  187. connect(this, TQT_SIGNAL(selectionChanged()),
  188. this, TQT_SLOT(slotSelectionChanged()));
  189. }
  190. TagFolderView::~TagFolderView()
  191. {
  192. saveViewState();
  193. delete d;
  194. }
  195. void TagFolderView::slotTextTagFilterChanged(const TQString& filter)
  196. {
  197. if (filter.isEmpty())
  198. {
  199. collapseView();
  200. return;
  201. }
  202. TQString search = filter.lower();
  203. bool atleastOneMatch = false;
  204. AlbumList tList = d->albumMan->allTAlbums();
  205. for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it)
  206. {
  207. TAlbum* talbum = (TAlbum*)(*it);
  208. // don't touch the root Album
  209. if (talbum->isRoot())
  210. continue;
  211. bool match = talbum->title().lower().contains(search);
  212. bool doesExpand = false;
  213. if (!match)
  214. {
  215. // check if any of the parents match the search
  216. Album* parent = talbum->parent();
  217. while (parent && !parent->isRoot())
  218. {
  219. if (parent->title().lower().contains(search))
  220. {
  221. match = true;
  222. break;
  223. }
  224. parent = parent->parent();
  225. }
  226. }
  227. if (!match)
  228. {
  229. // check if any of the children match the search
  230. AlbumIterator it(talbum);
  231. while (it.current())
  232. {
  233. if ((*it)->title().lower().contains(search))
  234. {
  235. match = true;
  236. doesExpand = true;
  237. break;
  238. }
  239. ++it;
  240. }
  241. }
  242. TagFolderViewItem* viewItem = (TagFolderViewItem*) talbum->extraData(this);
  243. if (match)
  244. {
  245. atleastOneMatch = true;
  246. if (viewItem)
  247. {
  248. viewItem->setVisible(true);
  249. viewItem->setOpen(doesExpand);
  250. }
  251. }
  252. else
  253. {
  254. if (viewItem)
  255. {
  256. viewItem->setVisible(false);
  257. viewItem->setOpen(false);
  258. }
  259. }
  260. }
  261. emit signalTextTagFilterMatch(atleastOneMatch);
  262. }
  263. void TagFolderView::slotAlbumAdded(Album *album)
  264. {
  265. if(!album)
  266. return;
  267. TAlbum *tag = dynamic_cast<TAlbum*>(album);
  268. if(!tag)
  269. return;
  270. TagFolderViewItem *item;
  271. if(tag->isRoot())
  272. {
  273. item = new TagFolderViewItem(this, tag);
  274. tag->setExtraData(this, item);
  275. // Toplevel tags are all children of root, and should always be visible - set root to open
  276. item->setOpen(true);
  277. }
  278. else
  279. {
  280. TagFolderViewItem *parent =
  281. (TagFolderViewItem*)tag->parent()->extraData(this);
  282. if (!parent)
  283. {
  284. DWarning() << k_funcinfo << " Failed to find parent for Tag "
  285. << tag->title() << endl;
  286. return;
  287. }
  288. item = new TagFolderViewItem(parent, tag);
  289. tag->setExtraData(this, item);
  290. }
  291. setTagThumbnail(tag);
  292. }
  293. void TagFolderView::slotAlbumDeleted(Album *album)
  294. {
  295. if(!album)
  296. return;
  297. TAlbum *tag = dynamic_cast<TAlbum*>(album);
  298. if(!tag)
  299. return;
  300. TagFolderViewItem *item = (TagFolderViewItem*)album->extraData(this);
  301. if(item)
  302. {
  303. TagFolderViewItem *itemParent = dynamic_cast<TagFolderViewItem*>(item->parent());
  304. if(itemParent)
  305. itemParent->takeItem(item);
  306. else
  307. takeItem(item);
  308. delete item;
  309. }
  310. }
  311. void TagFolderView::slotAlbumsCleared()
  312. {
  313. clear();
  314. }
  315. void TagFolderView::slotAlbumMoved(TAlbum* tag, TAlbum* newParent)
  316. {
  317. if (!tag || !newParent)
  318. return;
  319. TagFolderViewItem* item = (TagFolderViewItem*)tag->extraData(this);
  320. if (!item)
  321. return;
  322. if (item->parent())
  323. {
  324. TQListViewItem* oldPItem = item->parent();
  325. oldPItem->takeItem(item);
  326. }
  327. else
  328. {
  329. takeItem(item);
  330. }
  331. TagFolderViewItem* newPItem = (TagFolderViewItem*)newParent->extraData(this);
  332. if (newPItem)
  333. newPItem->insertItem(item);
  334. else
  335. insertItem(item);
  336. }
  337. void TagFolderView::slotAlbumRenamed(Album* album)
  338. {
  339. if (!album)
  340. return;
  341. TAlbum* tag = dynamic_cast<TAlbum*>(album);
  342. if (!tag)
  343. return;
  344. TagFolderViewItem* item = (TagFolderViewItem*)(tag->extraData(this));
  345. if (item)
  346. item->refresh();
  347. }
  348. void TagFolderView::setTagThumbnail(TAlbum *album)
  349. {
  350. if(!album)
  351. return;
  352. TagFolderViewItem* item = (TagFolderViewItem*) album->extraData(this);
  353. if(!item)
  354. return;
  355. AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance();
  356. TQPixmap icon;
  357. if (!loader->getTagThumbnail(album, icon))
  358. {
  359. if (icon.isNull())
  360. {
  361. item->setPixmap(0, loader->getStandardTagIcon(album));
  362. }
  363. else
  364. {
  365. TQPixmap blendedIcon = loader->blendIcons(loader->getStandardTagIcon(), icon);
  366. item->setPixmap(0, blendedIcon);
  367. }
  368. }
  369. else
  370. {
  371. // for the time being, set standard icon
  372. item->setPixmap(0, loader->getStandardTagIcon(album));
  373. }
  374. }
  375. void TagFolderView::slotGotThumbnailFromIcon(Album *album, const TQPixmap& thumbnail)
  376. {
  377. if(!album || album->type() != Album::TAG)
  378. return;
  379. TagFolderViewItem* item = (TagFolderViewItem*)album->extraData(this);
  380. if(!item)
  381. return;
  382. AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance();
  383. TQPixmap blendedIcon = loader->blendIcons(loader->getStandardTagIcon(), thumbnail);
  384. item->setPixmap(0, blendedIcon);
  385. }
  386. void TagFolderView::slotThumbnailLost(Album *)
  387. {
  388. // we already set the standard icon before loading
  389. }
  390. void TagFolderView::slotReloadThumbnails()
  391. {
  392. AlbumList tList = d->albumMan->allTAlbums();
  393. for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it)
  394. {
  395. TAlbum* tag = (TAlbum*)(*it);
  396. setTagThumbnail(tag);
  397. }
  398. }
  399. void TagFolderView::slotAlbumIconChanged(Album* album)
  400. {
  401. if(!album || album->type() != Album::TAG)
  402. return;
  403. setTagThumbnail((TAlbum *)album);
  404. }
  405. void TagFolderView::slotSelectionChanged()
  406. {
  407. if (!active())
  408. return;
  409. TQListViewItem* selItem = 0;
  410. TQListViewItemIterator it(this);
  411. while (it.current())
  412. {
  413. if (it.current()->isSelected())
  414. {
  415. selItem = it.current();
  416. break;
  417. }
  418. ++it;
  419. }
  420. if (!selItem)
  421. {
  422. d->albumMan->setCurrentAlbum(0);
  423. return;
  424. }
  425. TagFolderViewItem *tagitem = dynamic_cast<TagFolderViewItem*>(selItem);
  426. if(!tagitem)
  427. {
  428. d->albumMan->setCurrentAlbum(0);
  429. return;
  430. }
  431. d->albumMan->setCurrentAlbum(tagitem->album());
  432. }
  433. void TagFolderView::slotContextMenu(TQListViewItem *item, const TQPoint &, int)
  434. {
  435. d->ABCMenu = new TQPopupMenu;
  436. connect( d->ABCMenu, TQT_SIGNAL( aboutToShow() ),
  437. this, TQT_SLOT( slotABCContextMenu() ) );
  438. TagFolderViewItem *tag = dynamic_cast<TagFolderViewItem*>(item);
  439. TDEPopupMenu popmenu(this);
  440. popmenu.insertTitle(SmallIcon("digikam"), i18n("My Tags"));
  441. popmenu.insertItem(SmallIcon("tag-new"), i18n("New Tag..."), 10);
  442. popmenu.insertItem(SmallIcon("tag-addressbook"), i18n("Create Tag From AddressBook"), d->ABCMenu);
  443. if(tag && tag->parent())
  444. {
  445. popmenu.insertItem(SmallIcon("tag-properties"), i18n("Edit Tag Properties..."), 11);
  446. popmenu.insertItem(SmallIcon("tag-reset"), i18n("Reset Tag Icon"), 13);
  447. popmenu.insertSeparator(-1);
  448. popmenu.insertItem(SmallIcon("tag-delete"), i18n("Delete Tag"), 12);
  449. }
  450. int choice = popmenu.exec((TQCursor::pos()));
  451. switch( choice )
  452. {
  453. case 10:
  454. {
  455. tagNew(tag);
  456. break;
  457. }
  458. case 11:
  459. {
  460. tagEdit(tag);
  461. break;
  462. }
  463. case 12:
  464. {
  465. tagDelete(tag);
  466. break;
  467. }
  468. case 13:
  469. {
  470. TQString errMsg;
  471. d->albumMan->updateTAlbumIcon(tag->album(), TQString("tag"), 0, errMsg);
  472. break;
  473. }
  474. default:
  475. break;
  476. }
  477. if ( choice > 100 )
  478. {
  479. tagNew( tag, d->ABCMenu->text( choice ), "tag-people" );
  480. }
  481. delete d->ABCMenu;
  482. d->ABCMenu = 0;
  483. }
  484. void TagFolderView::slotABCContextMenu()
  485. {
  486. d->ABCMenu->clear();
  487. int counter = 100;
  488. TDEABC::AddressBook* ab = TDEABC::StdAddressBook::self();
  489. TQStringList names;
  490. for ( TDEABC::AddressBook::Iterator it = ab->begin(); it != ab->end(); ++it )
  491. {
  492. names.push_back(it->formattedName());
  493. }
  494. qHeapSort(names);
  495. for ( TQStringList::Iterator it = names.begin(); it != names.end(); ++it )
  496. {
  497. TQString name = *it;
  498. if ( !name.isNull() )
  499. d->ABCMenu->insertItem( name, ++counter );
  500. }
  501. if (counter == 100)
  502. {
  503. d->ABCMenu->insertItem( i18n("No AddressBook entries found"), ++counter );
  504. d->ABCMenu->setItemEnabled( counter, false );
  505. }
  506. }
  507. void TagFolderView::tagNew()
  508. {
  509. TagFolderViewItem *item = dynamic_cast<TagFolderViewItem*>(selectedItem());
  510. tagNew(item);
  511. }
  512. void TagFolderView::tagNew( TagFolderViewItem *item, const TQString& _title, const TQString& _icon )
  513. {
  514. TQString title = _title;
  515. TQString icon = _icon;
  516. TAlbum *parent;
  517. if(!item)
  518. parent = d->albumMan->findTAlbum(0);
  519. else
  520. parent = item->album();
  521. if (title.isNull())
  522. {
  523. if(!TagEditDlg::tagCreate(TQT_TQWIDGET(kapp->activeWindow()), parent, title, icon))
  524. return;
  525. }
  526. TQMap<TQString, TQString> errMap;
  527. AlbumList tList = TagEditDlg::createTAlbum(parent, title, icon, errMap);
  528. TagEditDlg::showtagsListCreationError(TQT_TQWIDGET(kapp->activeWindow()), errMap);
  529. for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it)
  530. {
  531. TagFolderViewItem* item = (TagFolderViewItem*)(*it)->extraData(this);
  532. if (item)
  533. ensureItemVisible(item);
  534. }
  535. }
  536. void TagFolderView::tagEdit()
  537. {
  538. TagFolderViewItem *item = dynamic_cast<TagFolderViewItem*>(selectedItem());
  539. tagEdit(item);
  540. }
  541. void TagFolderView::tagEdit(TagFolderViewItem *item)
  542. {
  543. if(!item)
  544. return;
  545. TAlbum *tag = item->album();
  546. if(!tag)
  547. return;
  548. TQString title, icon;
  549. if(!TagEditDlg::tagEdit(TQT_TQWIDGET(kapp->activeWindow()), tag, title, icon))
  550. return;
  551. if(tag->title() != title)
  552. {
  553. TQString errMsg;
  554. if(!d->albumMan->renameTAlbum(tag, title, errMsg))
  555. KMessageBox::error(0, errMsg);
  556. else
  557. item->refresh();
  558. }
  559. if(tag->icon() != icon)
  560. {
  561. TQString errMsg;
  562. if (!d->albumMan->updateTAlbumIcon(tag, icon, 0, errMsg))
  563. KMessageBox::error(0, errMsg);
  564. else
  565. setTagThumbnail(tag);
  566. }
  567. }
  568. void TagFolderView::tagDelete()
  569. {
  570. TagFolderViewItem *item = dynamic_cast<TagFolderViewItem*>(selectedItem());
  571. tagDelete(item);
  572. }
  573. void TagFolderView::tagDelete(TagFolderViewItem *item)
  574. {
  575. if(!item)
  576. return;
  577. TAlbum *tag = item->album();
  578. if (!tag || tag->isRoot())
  579. return;
  580. // find number of subtags
  581. int children = 0;
  582. AlbumIterator iter(tag);
  583. while(iter.current())
  584. {
  585. children++;
  586. ++iter;
  587. }
  588. if(children)
  589. {
  590. int result = KMessageBox::warningContinueCancel(this,
  591. i18n("Tag '%1' has one subtag. "
  592. "Deleting this will also delete "
  593. "the subtag. "
  594. "Do you want to continue?",
  595. "Tag '%1' has %n subtags. "
  596. "Deleting this will also delete "
  597. "the subtags. "
  598. "Do you want to continue?",
  599. children).arg(tag->title()));
  600. if(result != KMessageBox::Continue)
  601. return;
  602. }
  603. TQString message;
  604. LLongList assignedItems = d->albumMan->albumDB()->getItemIDsInTag(tag->id());
  605. if (!assignedItems.isEmpty())
  606. {
  607. message = i18n("Tag '%1' is assigned to one item. "
  608. "Do you want to continue?",
  609. "Tag '%1' is assigned to %n items. "
  610. "Do you want to continue?",
  611. assignedItems.count()).arg(tag->title());
  612. }
  613. else
  614. {
  615. message = i18n("Delete '%1' tag?").arg(tag->title());
  616. }
  617. int result = KMessageBox::warningContinueCancel(0, message,
  618. i18n("Delete Tag"),
  619. KGuiItem(i18n("Delete"),
  620. "edit-delete"));
  621. if(result == KMessageBox::Continue)
  622. {
  623. TQString errMsg;
  624. if (!d->albumMan->deleteTAlbum(tag, errMsg))
  625. KMessageBox::error(0, errMsg);
  626. }
  627. }
  628. TQDragObject* TagFolderView::dragObject()
  629. {
  630. TagFolderViewItem *item = dynamic_cast<TagFolderViewItem*>(dragItem());
  631. if(!item)
  632. return 0;
  633. if(!item->parent())
  634. return 0;
  635. TagDrag *t = new TagDrag(item->album()->id(), this);
  636. t->setPixmap(*item->pixmap(0));
  637. return t;
  638. }
  639. bool TagFolderView::acceptDrop(const TQDropEvent *e) const
  640. {
  641. TQPoint vp = contentsToViewport(e->pos());
  642. TagFolderViewItem *itemDrop = dynamic_cast<TagFolderViewItem*>(itemAt(vp));
  643. TagFolderViewItem *itemDrag = dynamic_cast<TagFolderViewItem*>(dragItem());
  644. if(TagDrag::canDecode(e) || TagListDrag::canDecode(e))
  645. {
  646. // Allow dragging at the root, to move the tag to the root
  647. if(!itemDrop)
  648. return true;
  649. // Dragging an item on itself makes no sense
  650. if(itemDrag == itemDrop)
  651. return false;
  652. // Dragging a parent on its child makes no sense
  653. if(itemDrag && itemDrag->album()->isAncestorOf(itemDrop->album()))
  654. return false;
  655. return true;
  656. }
  657. if (ItemDrag::canDecode(e) && itemDrop && itemDrop->parent())
  658. {
  659. // Only other possibility is image items being dropped
  660. // And allow this only if there is a Tag to be dropped
  661. // on and also the Tag is not root.
  662. return true;
  663. }
  664. return false;
  665. }
  666. void TagFolderView::contentsDropEvent(TQDropEvent *e)
  667. {
  668. FolderView::contentsDropEvent(e);
  669. if(!acceptDrop(e))
  670. return;
  671. TQPoint vp = contentsToViewport(e->pos());
  672. TagFolderViewItem *itemDrop = dynamic_cast<TagFolderViewItem*>(itemAt(vp));
  673. if (!itemDrop)
  674. return;
  675. if(TagDrag::canDecode(e))
  676. {
  677. TQByteArray ba = e->encodedData("digikam/tag-id");
  678. TQDataStream ds(ba, IO_ReadOnly);
  679. int tagID;
  680. ds >> tagID;
  681. TAlbum* talbum = d->albumMan->findTAlbum(tagID);
  682. if(!talbum)
  683. return;
  684. if (talbum == itemDrop->album())
  685. return;
  686. TDEPopupMenu popMenu(this);
  687. popMenu.insertTitle(SmallIcon("digikam"), i18n("My Tags"));
  688. popMenu.insertItem(SmallIcon("goto"), i18n("&Move Here"), 10);
  689. popMenu.insertSeparator(-1);
  690. popMenu.insertItem(SmallIcon("cancel"), i18n("C&ancel"), 20);
  691. popMenu.setMouseTracking(true);
  692. int id = popMenu.exec(TQCursor::pos());
  693. if(id == 10)
  694. {
  695. TAlbum *newParentTag = 0;
  696. if (!itemDrop)
  697. {
  698. // move dragItem to the root
  699. newParentTag = d->albumMan->findTAlbum(0);
  700. }
  701. else
  702. {
  703. // move dragItem as child of dropItem
  704. newParentTag = itemDrop->album();
  705. }
  706. TQString errMsg;
  707. if (!d->albumMan->moveTAlbum(talbum, newParentTag, errMsg))
  708. {
  709. KMessageBox::error(this, errMsg);
  710. }
  711. if(itemDrop && !itemDrop->isOpen())
  712. itemDrop->setOpen(true);
  713. }
  714. return;
  715. }
  716. if (ItemDrag::canDecode(e))
  717. {
  718. TAlbum *destAlbum = itemDrop->album();
  719. TAlbum *srcAlbum;
  720. KURL::List urls;
  721. KURL::List kioURLs;
  722. TQValueList<int> albumIDs;
  723. TQValueList<int> imageIDs;
  724. if (!ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs))
  725. return;
  726. if (urls.isEmpty() || kioURLs.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty())
  727. return;
  728. // all the albumids will be the same
  729. int albumID = albumIDs.first();
  730. srcAlbum = d->albumMan->findTAlbum(albumID);
  731. if (!srcAlbum)
  732. {
  733. DWarning() << "Could not find source album of drag"
  734. << endl;
  735. return;
  736. }
  737. int id = 0;
  738. char keys_return[32];
  739. XQueryKeymap(x11Display(), keys_return);
  740. int key_1 = XKeysymToKeycode(x11Display(), 0xFFE3);
  741. int key_2 = XKeysymToKeycode(x11Display(), 0xFFE4);
  742. if(srcAlbum == destAlbum)
  743. {
  744. // Setting the dropped image as the album thumbnail
  745. // If the ctrl key is pressed, when dropping the image, the
  746. // thumbnail is set without a popup menu
  747. if (((keys_return[key_1 / 8]) && (1 << (key_1 % 8))) ||
  748. ((keys_return[key_2 / 8]) && (1 << (key_2 % 8))))
  749. {
  750. id = 12;
  751. }
  752. else
  753. {
  754. TDEPopupMenu popMenu(this);
  755. popMenu.insertTitle(SmallIcon("digikam"), i18n("My Tags"));
  756. popMenu.insertItem(i18n("Set as Tag Thumbnail"), 12);
  757. popMenu.insertSeparator(-1);
  758. popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") );
  759. popMenu.setMouseTracking(true);
  760. id = popMenu.exec(TQCursor::pos());
  761. }
  762. if(id == 12)
  763. {
  764. TQString errMsg;
  765. d->albumMan->updateTAlbumIcon(destAlbum, TQString(), imageIDs.first(), errMsg);
  766. }
  767. return;
  768. }
  769. // If a ctrl key is pressed while dropping the drag object,
  770. // the tag is assigned to the images without showing a
  771. // popup menu.
  772. if (((keys_return[key_1 / 8]) && (1 << (key_1 % 8))) ||
  773. ((keys_return[key_2 / 8]) && (1 << (key_2 % 8))))
  774. {
  775. id = 10;
  776. }
  777. else
  778. {
  779. TDEPopupMenu popMenu(this);
  780. popMenu.insertTitle(SmallIcon("digikam"), i18n("My Tags"));
  781. popMenu.insertItem( SmallIcon("tag"), i18n("Assign Tag '%1' to Items")
  782. .arg(destAlbum->prettyURL()), 10) ;
  783. popMenu.insertSeparator(-1);
  784. popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") );
  785. popMenu.setMouseTracking(true);
  786. id = popMenu.exec(TQCursor::pos());
  787. }
  788. if (id == 10)
  789. {
  790. emit signalProgressBarMode(StatusProgressBar::ProgressBarMode,
  791. i18n("Assigning image tags. Please wait..."));
  792. AlbumLister::instance()->blockSignals(true);
  793. d->albumMan->albumDB()->beginTransaction();
  794. int i=0;
  795. for (TQValueList<int>::const_iterator it = imageIDs.begin();
  796. it != imageIDs.end(); ++it)
  797. {
  798. // create temporary ImageInfo object
  799. ImageInfo info(*it);
  800. MetadataHub hub;
  801. hub.load(&info);
  802. hub.setTag(destAlbum, true);
  803. hub.write(&info, MetadataHub::PartialWrite);
  804. hub.write(info.filePath(), MetadataHub::FullWriteIfChanged);
  805. emit signalProgressValue((int)((i++/(float)imageIDs.count())*100.0));
  806. kapp->processEvents();
  807. }
  808. AlbumLister::instance()->blockSignals(false);
  809. d->albumMan->albumDB()->commitTransaction();
  810. ImageAttributesWatch::instance()->imagesChanged(destAlbum->id());
  811. emit signalProgressBarMode(StatusProgressBar::TextMode, TQString());
  812. }
  813. }
  814. }
  815. void TagFolderView::selectItem(int id)
  816. {
  817. TAlbum* tag = d->albumMan->findTAlbum(id);
  818. if(!tag)
  819. return;
  820. TagFolderViewItem *item =
  821. (TagFolderViewItem*)tag->extraData(this);
  822. if(item)
  823. {
  824. setSelected(item, true);
  825. ensureItemVisible(item);
  826. }
  827. }
  828. void TagFolderView::refresh()
  829. {
  830. TQListViewItemIterator it(this);
  831. while (it.current())
  832. {
  833. TagFolderViewItem* item = dynamic_cast<TagFolderViewItem*>(*it);
  834. if (item)
  835. item->refresh();
  836. ++it;
  837. }
  838. }
  839. void TagFolderView::slotRefresh(const TQMap<int, int>& tagsStatMap)
  840. {
  841. TQListViewItemIterator it(this);
  842. while (it.current())
  843. {
  844. TagFolderViewItem* item = dynamic_cast<TagFolderViewItem*>(*it);
  845. if (item)
  846. {
  847. if (item->album())
  848. {
  849. int id = item->id();
  850. TQMap<int, int>::const_iterator it2 = tagsStatMap.find(id);
  851. if ( it2 != tagsStatMap.end() )
  852. item->setCount(it2.data());
  853. }
  854. }
  855. ++it;
  856. }
  857. refresh();
  858. }
  859. } // namespace Digikam