|
|
|
/* ============================================================
|
|
|
|
*
|
|
|
|
* This file is a part of digiKam project
|
|
|
|
* http://www.digikam.org
|
|
|
|
*
|
|
|
|
* Date : 2004-07-01
|
|
|
|
* Description : dialog to edit and create digiKam Tags
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004-2005 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.
|
|
|
|
*
|
|
|
|
* ============================================================ */
|
|
|
|
|
|
|
|
// TQt includes.
|
|
|
|
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
|
|
|
|
// KDE includes.
|
|
|
|
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kicondialog.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <tdeversion.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kseparator.h>
|
|
|
|
#include <klistview.h>
|
|
|
|
|
|
|
|
// Local includes.
|
|
|
|
|
|
|
|
#include "ddebug.h"
|
|
|
|
#include "album.h"
|
|
|
|
#include "searchtextbar.h"
|
|
|
|
#include "syncjob.h"
|
|
|
|
#include "tageditdlg.h"
|
|
|
|
#include "tageditdlg.moc"
|
|
|
|
|
|
|
|
namespace Digikam
|
|
|
|
{
|
|
|
|
|
|
|
|
class TagsListCreationErrorDialog : public KDialogBase
|
|
|
|
{
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
TagsListCreationErrorDialog(TQWidget* parent, const TQMap<TQString, TQString>& errMap);
|
|
|
|
~TagsListCreationErrorDialog(){};
|
|
|
|
};
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class TagEditDlgPriv
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
TagEditDlgPriv()
|
|
|
|
{
|
|
|
|
titleEdit = 0;
|
|
|
|
iconButton = 0;
|
|
|
|
resetIconButton = 0;
|
|
|
|
mainRootAlbum = 0;
|
|
|
|
topLabel = 0;
|
|
|
|
create = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool create;
|
|
|
|
|
|
|
|
TQLabel *topLabel;
|
|
|
|
|
|
|
|
TQString icon;
|
|
|
|
|
|
|
|
TQPushButton *iconButton;
|
|
|
|
TQPushButton *resetIconButton;
|
|
|
|
|
|
|
|
TAlbum *mainRootAlbum;
|
|
|
|
SearchTextBar *titleEdit;
|
|
|
|
};
|
|
|
|
|
|
|
|
TagEditDlg::TagEditDlg(TQWidget *parent, TAlbum* album, bool create)
|
|
|
|
: KDialogBase(parent, 0, true, 0, Help|Ok|Cancel, Ok, true)
|
|
|
|
{
|
|
|
|
d = new TagEditDlgPriv;
|
|
|
|
d->mainRootAlbum = album;
|
|
|
|
d->create = create;
|
|
|
|
|
|
|
|
setHelp("tagscreation.anchor", "digikam");
|
|
|
|
if (d->create) setCaption(i18n("New Tag"));
|
|
|
|
else setCaption(i18n("Edit Tag"));
|
|
|
|
|
|
|
|
TQWidget *page = makeMainWidget();
|
|
|
|
TQGridLayout* grid = new TQGridLayout(page, 5, 4, 0, spacingHint());
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
TQLabel *logo = new TQLabel(page);
|
|
|
|
KIconLoader* iconLoader = TDEApplication::kApplication()->iconLoader();
|
|
|
|
logo->setPixmap(iconLoader->loadIcon("digikam", KIcon::NoGroup, 96, KIcon::DefaultState, 0, true));
|
|
|
|
|
|
|
|
d->topLabel = new TQLabel(page);
|
|
|
|
d->topLabel->setAlignment(TQt::AlignAuto | TQt::AlignVCenter | TQt::SingleLine);
|
|
|
|
|
|
|
|
KSeparator *line = new KSeparator (Horizontal, page);
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
TQLabel *titleLabel = new TQLabel(page);
|
|
|
|
titleLabel->setText(i18n("&Title:"));
|
|
|
|
|
|
|
|
d->titleEdit = new SearchTextBar(page, "TagEditDlgTitleEdit", i18n("Enter tag name here..."));
|
|
|
|
titleLabel->setBuddy(d->titleEdit);
|
|
|
|
|
|
|
|
TQLabel *tipLabel = new TQLabel(page);
|
|
|
|
tipLabel->setTextFormat(TQt::RichText);
|
|
|
|
tipLabel->setText(i18n("<qt><p>To create new tags, you can use the following rules:</p>"
|
|
|
|
"<p><ul><li>'/' can be used to create a tags hierarchy.<br>"
|
|
|
|
"Ex.: <i>\"Country/City/Paris\"</i></li>"
|
|
|
|
"<li>',' can be used to create more than one tags hierarchy at the same time.<br>"
|
|
|
|
"Ex.: <i>\"City/Paris, Monument/Notre-Dame\"</i></li>"
|
|
|
|
"<li>If a tag hierarchy starts with '/', root tag album is used as parent.</li></ul></p></qt>"
|
|
|
|
));
|
|
|
|
|
|
|
|
if (d->create)
|
|
|
|
{
|
|
|
|
AlbumList tList = AlbumManager::instance()->allTAlbums();
|
|
|
|
for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it)
|
|
|
|
{
|
|
|
|
TAlbum *tag = dynamic_cast<TAlbum*>(*it);
|
|
|
|
d->titleEdit->lineEdit()->completionObject()->addItem(tag->tagPath());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->titleEdit->setText(d->mainRootAlbum->title());
|
|
|
|
tipLabel->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQLabel *iconTextLabel = new TQLabel(page);
|
|
|
|
iconTextLabel->setText(i18n("&Icon:"));
|
|
|
|
|
|
|
|
d->iconButton = new TQPushButton(page);
|
|
|
|
d->iconButton->setFixedSize(40, 40);
|
|
|
|
iconTextLabel->setBuddy(d->iconButton);
|
|
|
|
|
|
|
|
// In create mode, by default assign the icon of the parent (if not root) to this new tag.
|
|
|
|
if (d->create && !d->mainRootAlbum->isRoot())
|
|
|
|
d->icon = d->mainRootAlbum->icon();
|
|
|
|
else
|
|
|
|
d->icon = d->mainRootAlbum->icon();
|
|
|
|
|
|
|
|
d->iconButton->setIconSet(SyncJob::getTagThumbnail(d->icon, 20));
|
|
|
|
|
|
|
|
d->resetIconButton = new TQPushButton(SmallIcon("reload_page"), i18n("Reset"), page);
|
|
|
|
if (d->create) d->resetIconButton->hide();
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
grid->addMultiCellWidget(logo, 0, 3, 0, 0);
|
|
|
|
grid->addMultiCellWidget(d->topLabel, 0, 0, 1, 4);
|
|
|
|
grid->addMultiCellWidget(line, 1, 1, 1, 4);
|
|
|
|
grid->addMultiCellWidget(tipLabel, 2, 2, 1, 4);
|
|
|
|
grid->addMultiCellWidget(titleLabel, 3, 3, 1, 1);
|
|
|
|
grid->addMultiCellWidget(d->titleEdit, 3, 3, 2, 4);
|
|
|
|
grid->addMultiCellWidget(iconTextLabel, 4, 4, 1, 1);
|
|
|
|
grid->addMultiCellWidget(d->iconButton, 4, 4, 2, 2);
|
|
|
|
grid->addMultiCellWidget(d->resetIconButton, 4, 4, 3, 3);
|
|
|
|
grid->setColStretch(4, 10);
|
|
|
|
grid->setRowStretch(5, 10);
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
connect(d->iconButton, TQT_SIGNAL(clicked()),
|
|
|
|
this, TQT_SLOT(slotIconChanged()));
|
|
|
|
|
|
|
|
connect(d->resetIconButton, TQT_SIGNAL(clicked()),
|
|
|
|
this, TQT_SLOT(slotIconResetClicked()));
|
|
|
|
|
|
|
|
connect(d->titleEdit->lineEdit(), TQT_SIGNAL(textChanged(const TQString&)),
|
|
|
|
this, TQT_SLOT(slotTitleChanged(const TQString&)));
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
slotTitleChanged(d->titleEdit->text());
|
|
|
|
d->titleEdit->lineEdit()->setFocus();
|
|
|
|
adjustSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
TagEditDlg::~TagEditDlg()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TagEditDlg::title() const
|
|
|
|
{
|
|
|
|
return d->titleEdit->text();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString TagEditDlg::icon() const
|
|
|
|
{
|
|
|
|
return d->icon;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TagEditDlg::slotIconResetClicked()
|
|
|
|
{
|
|
|
|
d->icon = TQString("tag");
|
|
|
|
d->iconButton->setIconSet(SyncJob::getTagThumbnail(d->icon, 20));
|
|
|
|
}
|
|
|
|
|
|
|
|
void TagEditDlg::slotIconChanged()
|
|
|
|
{
|
|
|
|
#if KDE_IS_VERSION(3,3,0)
|
|
|
|
KIconDialog dlg(this);
|
|
|
|
dlg.setup(KIcon::NoGroup, KIcon::Application, false, 20, false, false, false);
|
|
|
|
TQString icon = dlg.openDialog();
|
|
|
|
#else
|
|
|
|
TQString icon = KIconDialog::getIcon(KIcon::NoGroup, KIcon::Application, false, 20);
|
|
|
|
if (icon.startsWith("/"))
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (icon.isEmpty() || icon == d->icon)
|
|
|
|
return;
|
|
|
|
|
|
|
|
d->icon = icon;
|
|
|
|
d->iconButton->setIconSet(SyncJob::getTagThumbnail(d->icon, 20));
|
|
|
|
}
|
|
|
|
|
|
|
|
void TagEditDlg::slotTitleChanged(const TQString& newtitle)
|
|
|
|
{
|
|
|
|
TQString tagName = d->mainRootAlbum->tagPath();
|
|
|
|
if (tagName.endsWith("/") && !d->mainRootAlbum->isRoot())
|
|
|
|
tagName.truncate(tagName.length()-1);
|
|
|
|
|
|
|
|
if (d->create)
|
|
|
|
{
|
|
|
|
if (d->titleEdit->text().startsWith("/"))
|
|
|
|
{
|
|
|
|
d->topLabel->setText(i18n("<qt><b>Create New Tag</b></qt>"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->topLabel->setText(i18n("<qt><b>Create New Tag in<br>"
|
|
|
|
"<i>\"%1\"</i></b></qt>").arg(tagName));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->topLabel->setText(i18n("<qt><b>Properties of Tag<br>"
|
|
|
|
"<i>\"%1\"</i></b></qt>").arg(tagName));
|
|
|
|
}
|
|
|
|
|
|
|
|
enableButtonOK(!newtitle.isEmpty());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TagEditDlg::tagEdit(TQWidget *parent, TAlbum* album, TQString& title, TQString& icon)
|
|
|
|
{
|
|
|
|
TagEditDlg dlg(parent, album);
|
|
|
|
|
|
|
|
bool valRet = dlg.exec();
|
|
|
|
if (valRet == TQDialog::Accepted)
|
|
|
|
{
|
|
|
|
title = dlg.title();
|
|
|
|
icon = dlg.icon();
|
|
|
|
}
|
|
|
|
|
|
|
|
return valRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TagEditDlg::tagCreate(TQWidget *parent, TAlbum* album, TQString& title, TQString& icon)
|
|
|
|
{
|
|
|
|
TagEditDlg dlg(parent, album, true);
|
|
|
|
|
|
|
|
bool valRet = dlg.exec();
|
|
|
|
if (valRet == TQDialog::Accepted)
|
|
|
|
{
|
|
|
|
title = dlg.title();
|
|
|
|
icon = dlg.icon();
|
|
|
|
}
|
|
|
|
|
|
|
|
return valRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
AlbumList TagEditDlg::createTAlbum(TAlbum *mainRootAlbum, const TQString& tagStr, const TQString& icon,
|
|
|
|
TQMap<TQString, TQString>& errMap)
|
|
|
|
{
|
|
|
|
errMap.clear();
|
|
|
|
AlbumList createdTagsList;
|
|
|
|
|
|
|
|
// Check if new tags are include in a list of tags hierarchy separated by ','.
|
|
|
|
// Ex: /Country/France/people,/City/France/Paris
|
|
|
|
|
|
|
|
TQStringList tagsHierarchies = TQStringList::split(",", tagStr);
|
|
|
|
if (tagsHierarchies.isEmpty())
|
|
|
|
return createdTagsList;
|
|
|
|
|
|
|
|
for (TQStringList::const_iterator it = tagsHierarchies.begin(); it != tagsHierarchies.end(); ++it)
|
|
|
|
{
|
|
|
|
TQString hierarchy = (*it).stripWhiteSpace();
|
|
|
|
if (!hierarchy.isEmpty())
|
|
|
|
{
|
|
|
|
// Check if new tags is a hierarchy of tags separated by '/'.
|
|
|
|
|
|
|
|
TAlbum *root = 0;
|
|
|
|
|
|
|
|
if (hierarchy.startsWith("/") || !mainRootAlbum)
|
|
|
|
root = AlbumManager::instance()->findTAlbum(0);
|
|
|
|
else
|
|
|
|
root = mainRootAlbum;
|
|
|
|
|
|
|
|
TQStringList tagsList = TQStringList::split("/", hierarchy);
|
|
|
|
DDebug() << tagsList << endl;
|
|
|
|
|
|
|
|
if (!tagsList.isEmpty())
|
|
|
|
{
|
|
|
|
for (TQStringList::iterator it2 = tagsList.begin(); it2 != tagsList.end(); ++it2)
|
|
|
|
{
|
|
|
|
TQString tagPath, errMsg;
|
|
|
|
TQString tag = (*it2).stripWhiteSpace();
|
|
|
|
if (root->isRoot())
|
|
|
|
tagPath = TQString("/%1").arg(tag);
|
|
|
|
else
|
|
|
|
tagPath = TQString("%1/%2").arg(root->tagPath()).arg(tag);
|
|
|
|
|
|
|
|
DDebug() << tag << " :: " << tagPath << endl;
|
|
|
|
|
|
|
|
if (!tag.isEmpty())
|
|
|
|
{
|
|
|
|
// Tag already exist ?
|
|
|
|
TAlbum* album = AlbumManager::instance()->findTAlbum(tagPath);
|
|
|
|
if (!album)
|
|
|
|
{
|
|
|
|
root = AlbumManager::instance()->createTAlbum(root, tag, icon, errMsg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
root = album;
|
|
|
|
if (*it2 == tagsList.last())
|
|
|
|
errMap.insert(tagPath, i18n("Tag name already exists"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (root)
|
|
|
|
createdTagsList.append(root);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sanity check if tag creation failed.
|
|
|
|
if (!root)
|
|
|
|
{
|
|
|
|
errMap.insert(tagPath, errMsg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return createdTagsList;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TagEditDlg::showtagsListCreationError(TQWidget* parent, const TQMap<TQString, TQString>& errMap)
|
|
|
|
{
|
|
|
|
if (!errMap.isEmpty())
|
|
|
|
{
|
|
|
|
TagsListCreationErrorDialog dlg(parent, errMap);
|
|
|
|
dlg.exec();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TagsListCreationErrorDialog::TagsListCreationErrorDialog(TQWidget* parent, const TQMap<TQString, TQString>& errMap)
|
|
|
|
: KDialogBase(parent, 0, true, 0, Help|Ok, Ok, false)
|
|
|
|
{
|
|
|
|
setHelp("tagscreation.anchor", "digikam");
|
|
|
|
setCaption(i18n("Tag creation Error"));
|
|
|
|
|
|
|
|
TQWidget* box = makeMainWidget();
|
|
|
|
TQVBoxLayout* vLay = new TQVBoxLayout(box);
|
|
|
|
|
|
|
|
TQLabel *label = new TQLabel(i18n("Error been occured during Tag creation:"), box);
|
|
|
|
TDEListView *listView = new TDEListView(box);
|
|
|
|
listView->addColumn(i18n("Tag Path"));
|
|
|
|
listView->addColumn(i18n("Error"));
|
|
|
|
listView->setResizeMode(TQListView::LastColumn);
|
|
|
|
|
|
|
|
vLay->addWidget(label);
|
|
|
|
vLay->addWidget(listView);
|
|
|
|
vLay->setMargin(0);
|
|
|
|
vLay->setSpacing(0);
|
|
|
|
|
|
|
|
for (TQMap<TQString, TQString>::const_iterator it = errMap.begin() ; it != errMap.end() ; ++it)
|
|
|
|
new TDEListViewItem(listView, it.key(), it.data());
|
|
|
|
|
|
|
|
adjustSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Digikam
|