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.
367 lines
9.9 KiB
367 lines
9.9 KiB
/* ============================================================
|
|
*
|
|
* This file is a part of digiKam project
|
|
* http://www.digikam.org
|
|
*
|
|
* Date : 2004-09-07
|
|
* Description : a pop-up menu implementation to display a
|
|
* hierarchical view of digiKam tags.
|
|
*
|
|
* Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
|
|
* Copyright (C) 2006-2008 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.
|
|
*
|
|
* ============================================================ */
|
|
|
|
#define ADDTAGID 10000
|
|
|
|
// TQt includes.
|
|
|
|
#include <tqpixmap.h>
|
|
#include <tqstring.h>
|
|
#include <tqpainter.h>
|
|
#include <tqstyle.h>
|
|
#include <tqvaluelist.h>
|
|
#include <tqpixmap.h>
|
|
#include <tqvaluevector.h>
|
|
|
|
// KDE includes.
|
|
|
|
#include <tdeapplication.h>
|
|
#include <kiconloader.h>
|
|
#include <tdelocale.h>
|
|
#include <tdemessagebox.h>
|
|
|
|
// Local includes.
|
|
|
|
#include "ddebug.h"
|
|
#include "albumiconview.h"
|
|
#include "albumiconitem.h"
|
|
#include "albummanager.h"
|
|
#include "albumdb.h"
|
|
#include "album.h"
|
|
#include "syncjob.h"
|
|
#include "tageditdlg.h"
|
|
#include "tagspopupmenu.h"
|
|
#include "tagspopupmenu.moc"
|
|
|
|
namespace Digikam
|
|
{
|
|
|
|
class TagsPopupCheckedMenuItem : public TQCustomMenuItem
|
|
{
|
|
public:
|
|
|
|
TagsPopupCheckedMenuItem(TQPopupMenu* popup, const TQString& txt, const TQPixmap& pix)
|
|
: TQCustomMenuItem(), m_popup(popup), m_txt(txt), m_pix(pix)
|
|
{
|
|
}
|
|
|
|
virtual TQSize sizeHint()
|
|
{
|
|
TQFont fn = m_popup->font();
|
|
TQFontMetrics fm(fn);
|
|
int w = fm.width(m_txt) + 5 + kapp->style().pixelMetric(TQStyle::PM_IndicatorWidth, 0);
|
|
int h = TQMAX(fm.height(), m_pix.height());
|
|
return TQSize( w, h );
|
|
}
|
|
|
|
virtual void paint(TQPainter* p, const TQColorGroup& cg, bool act, bool enabled,
|
|
int x, int y, int w, int h )
|
|
{
|
|
p->save();
|
|
p->setPen(act ? cg.highlightedText() : cg.highlight());
|
|
p->drawText(x, y, w, h, TQt::AlignLeft|TQt::AlignVCenter, m_txt);
|
|
p->restore();
|
|
|
|
if (!m_pix.isNull())
|
|
{
|
|
TQRect pixRect(x/2 - m_pix.width()/2, y, m_pix.width(), m_pix.height());
|
|
p->drawPixmap( pixRect.topLeft(), m_pix );
|
|
}
|
|
|
|
int checkWidth = kapp->style().pixelMetric(TQStyle::PM_IndicatorWidth, 0);
|
|
int checkHeight = kapp->style().pixelMetric(TQStyle::PM_IndicatorHeight, 0);
|
|
|
|
TQStyle::SFlags flags = TQStyle::Style_Default;
|
|
flags |= TQStyle::Style_On;
|
|
if (enabled)
|
|
flags |= TQStyle::Style_Enabled;
|
|
if (act)
|
|
flags |= TQStyle::Style_Active;
|
|
|
|
TQFont fn = m_popup->font();
|
|
TQFontMetrics fm(fn);
|
|
TQRect r(x + 5 + fm.width(m_txt), y + (h/2-checkHeight/2), checkWidth, checkHeight);
|
|
kapp->style().drawPrimitive(TQStyle::PE_CheckMark, p, r, cg, flags);
|
|
}
|
|
|
|
private:
|
|
|
|
TQPopupMenu *m_popup;
|
|
|
|
TQString m_txt;
|
|
|
|
TQPixmap m_pix;
|
|
};
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
class TagsPopupMenuPriv
|
|
{
|
|
public:
|
|
|
|
TagsPopupMenuPriv(){}
|
|
|
|
int addToID;
|
|
|
|
TQPixmap addTagPix;
|
|
|
|
TQValueList<int> assignedTags;
|
|
TQValueList<TQ_LLONG> selectedImageIDs;
|
|
|
|
TagsPopupMenu::Mode mode;
|
|
};
|
|
|
|
TagsPopupMenu::TagsPopupMenu(const TQValueList<TQ_LLONG>& selectedImageIDs, int addToID, Mode mode)
|
|
: TQPopupMenu(0)
|
|
{
|
|
d = new TagsPopupMenuPriv;
|
|
d->selectedImageIDs = selectedImageIDs;
|
|
d->addToID = addToID;
|
|
d->mode = mode;
|
|
|
|
TDEIconLoader *iconLoader = TDEApplication::kApplication()->iconLoader();
|
|
d->addTagPix = iconLoader->loadIcon("tag",
|
|
TDEIcon::NoGroup,
|
|
TDEIcon::SizeSmall,
|
|
TDEIcon::DefaultState,
|
|
0, true);
|
|
|
|
connect(this, TQ_SIGNAL(aboutToShow()),
|
|
this, TQ_SLOT(slotAboutToShow()));
|
|
|
|
connect(this, TQ_SIGNAL(activated(int)),
|
|
this, TQ_SLOT(slotActivated(int)));
|
|
}
|
|
|
|
TagsPopupMenu::~TagsPopupMenu()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void TagsPopupMenu::clearPopup()
|
|
{
|
|
d->assignedTags.clear();
|
|
clear();
|
|
}
|
|
|
|
TQPopupMenu* TagsPopupMenu::buildSubMenu(int tagid)
|
|
{
|
|
AlbumManager* man = AlbumManager::instance();
|
|
TAlbum* album = man->findTAlbum(tagid);
|
|
if (!album)
|
|
return 0;
|
|
|
|
TQPopupMenu* popup = new TQPopupMenu(this);
|
|
|
|
connect(popup, TQ_SIGNAL(activated(int)),
|
|
this, TQ_SLOT(slotActivated(int)));
|
|
|
|
if (d->mode == ASSIGN)
|
|
{
|
|
popup->insertItem(d->addTagPix, i18n("Add New Tag..."), ADDTAGID + album->id());
|
|
popup->insertSeparator();
|
|
|
|
TQPixmap pix = SyncJob::getTagThumbnail(album);
|
|
if ((d->mode == ASSIGN) && (d->assignedTags.contains(album->id())))
|
|
{
|
|
popup->insertItem(new TagsPopupCheckedMenuItem(popup, album->title(), pix),
|
|
d->addToID + album->id());
|
|
}
|
|
else
|
|
{
|
|
popup->insertItem(pix, album->title(), d->addToID + album->id());
|
|
}
|
|
|
|
if (album->firstChild())
|
|
{
|
|
popup->insertSeparator();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!album->isRoot())
|
|
{
|
|
TQPixmap pix = SyncJob::getTagThumbnail(album);
|
|
popup->insertItem(pix, album->title(), d->addToID + album->id());
|
|
popup->insertSeparator();
|
|
}
|
|
}
|
|
|
|
iterateAndBuildMenu(popup, album);
|
|
|
|
return popup;
|
|
}
|
|
|
|
void TagsPopupMenu::slotAboutToShow()
|
|
{
|
|
clearPopup();
|
|
|
|
AlbumManager* man = AlbumManager::instance();
|
|
|
|
if (d->mode == REMOVE || d->mode == DISPLAY)
|
|
{
|
|
if (d->selectedImageIDs.isEmpty())
|
|
return;
|
|
|
|
d->assignedTags = man->albumDB()->getItemCommonTagIDs(d->selectedImageIDs);
|
|
|
|
if (d->assignedTags.isEmpty())
|
|
return;
|
|
|
|
// also add the parents of the assigned tags
|
|
IntList tList;
|
|
for (IntList::iterator it = d->assignedTags.begin();
|
|
it != d->assignedTags.end(); ++it)
|
|
{
|
|
TAlbum* album = man->findTAlbum(*it);
|
|
if (album)
|
|
{
|
|
Album* a = album->parent();
|
|
while (a)
|
|
{
|
|
tList.append(a->id());
|
|
a = a->parent();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (IntList::iterator it = tList.begin();
|
|
it != tList.end(); ++it)
|
|
{
|
|
d->assignedTags.append(*it);
|
|
}
|
|
}
|
|
else if (d->mode == ASSIGN)
|
|
{
|
|
if (d->selectedImageIDs.count() == 1)
|
|
{
|
|
d->assignedTags = man->albumDB()->getItemCommonTagIDs(d->selectedImageIDs);
|
|
}
|
|
}
|
|
|
|
TAlbum* album = man->findTAlbum(0);
|
|
if (!album)
|
|
return;
|
|
|
|
if (d->mode == ASSIGN)
|
|
{
|
|
insertItem(d->addTagPix, i18n("Add New Tag..."), ADDTAGID);
|
|
if (album->firstChild())
|
|
{
|
|
insertSeparator();
|
|
}
|
|
}
|
|
|
|
iterateAndBuildMenu(this, album);
|
|
}
|
|
|
|
// for qHeapSort
|
|
typedef TQPair<TQString, Album*> TagsMenuSortType;
|
|
bool operator<(const TagsMenuSortType &lhs, const TagsMenuSortType &rhs)
|
|
{
|
|
return lhs.first < rhs.first;
|
|
}
|
|
|
|
void TagsPopupMenu::iterateAndBuildMenu(TQPopupMenu *menu, TAlbum *album)
|
|
{
|
|
TQValueVector<TagsMenuSortType> sortedTags;
|
|
|
|
for (Album* a = album->firstChild(); a; a = a->next())
|
|
{
|
|
sortedTags.push_back(qMakePair(a->title(), a));
|
|
}
|
|
|
|
qHeapSort(sortedTags);
|
|
|
|
for (TQValueVector<TagsMenuSortType>::Iterator i = sortedTags.begin(); i != sortedTags.end(); ++i)
|
|
{
|
|
Album *a = i->second;
|
|
|
|
if (d->mode == REMOVE || d->mode == DISPLAY)
|
|
{
|
|
IntList::iterator it = tqFind(d->assignedTags.begin(),
|
|
d->assignedTags.end(), a->id());
|
|
if (it == d->assignedTags.end())
|
|
continue;
|
|
}
|
|
|
|
TQPixmap pix = SyncJob::getTagThumbnail((TAlbum*)a);
|
|
TQString t = a->title();
|
|
t.replace('&',"&&");
|
|
|
|
if (a->firstChild())
|
|
{
|
|
menu->insertItem(pix, t, buildSubMenu(a->id()));
|
|
}
|
|
else
|
|
{
|
|
if ((d->mode == ASSIGN) && (d->assignedTags.contains(a->id())))
|
|
{
|
|
menu->insertItem(new TagsPopupCheckedMenuItem(this, a->title(), pix),
|
|
d->addToID + a->id());
|
|
}
|
|
else
|
|
{
|
|
menu->insertItem(pix, t, d->addToID + a->id());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TagsPopupMenu::slotActivated(int id)
|
|
{
|
|
if (id >= ADDTAGID)
|
|
{
|
|
int tagID = id - ADDTAGID;
|
|
|
|
AlbumManager* man = AlbumManager::instance();
|
|
TAlbum* parent = man->findTAlbum(tagID);
|
|
if (!parent)
|
|
{
|
|
DWarning() << "Failed to find album with id "
|
|
<< tagID << endl;
|
|
return;
|
|
}
|
|
|
|
TQString title, icon;
|
|
if (!TagEditDlg::tagCreate(kapp->activeWindow(), parent, title, icon))
|
|
return;
|
|
|
|
TQMap<TQString, TQString> errMap;
|
|
AlbumList tList = TagEditDlg::createTAlbum(parent, title, icon, errMap);
|
|
TagEditDlg::showtagsListCreationError(kapp->activeWindow(), errMap);
|
|
|
|
for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it)
|
|
emit signalTagActivated((*it)->id());
|
|
}
|
|
else
|
|
{
|
|
int tagID = id - d->addToID;
|
|
emit signalTagActivated(tagID);
|
|
}
|
|
}
|
|
|
|
} // namespace Digikam
|