/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2006-02-21
 * Description : a generic list view widget to
 *               display metadata
 *
 * 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 <tqtimer.h>
#include <tqptrlist.h>
#include <tqpalette.h>
#include <tqheader.h>
#include <tqwhatsthis.h>

// KDE includes.

#include <tdelocale.h>

// Local includes.

#include "mdkeylistviewitem.h"
#include "metadatalistviewitem.h"
#include "metadatalistview.h"
#include "metadatalistview.moc"

namespace Digikam
{

MetadataListView::MetadataListView(TQWidget* parent)
                : TQListView(parent)
{
    header()->hide();
    addColumn("Name");    // No need i18n here.
    addColumn("Value");   // No need i18n here.
    setItemMargin(0);
    setAllColumnsShowFocus(true);
    setResizeMode(TQListView::AllColumns);
    // Vertical scroll bar is always disable to give more
    // free space to metadata content
    setVScrollBarMode(TQScrollView::AlwaysOff);

    m_parent = dynamic_cast<MetadataWidget *>(parent);

    connect(this, TQ_SIGNAL(selectionChanged(TQListViewItem*)),
            this, TQ_SLOT(slotSelectionChanged(TQListViewItem*)));
}

MetadataListView::~MetadataListView()
{
}

TQString MetadataListView::getCurrentItemKey()
{
    if (currentItem())
    {
        if (currentItem()->isSelectable())
        {
            MetadataListViewItem *item = static_cast<MetadataListViewItem *>(currentItem());
            return item->getKey();
        }
    }

    return TQString();
}

void MetadataListView::setCurrentItemByKey(TQString itemKey)
{
    if (itemKey.isNull())
        return;

    TQListViewItemIterator it(this);
    while ( it.current() )
    {
        if ( it.current()->isSelectable() )
        {
            MetadataListViewItem *item = dynamic_cast<MetadataListViewItem *>(it.current());

            if (item->getKey() == itemKey)
            {
                setSelected(item, true);
                ensureItemVisible(item);
                m_selectedItemKey = itemKey;
                return;
            }
        }

        ++it;
    }
}

void MetadataListView::slotSelectionChanged(TQListViewItem *item)
{
    if (!item)
        return;

    MetadataListViewItem* viewItem = static_cast<MetadataListViewItem *>(item);
    m_selectedItemKey = viewItem->getKey();
    TQString tagValue  = viewItem->getValue().simplifyWhiteSpace();
    TQString tagTitle  = m_parent->getTagTitle(m_selectedItemKey);
    TQString tagDesc   = m_parent->getTagDescription(m_selectedItemKey);
    if (tagValue.length() > 128)
    {
        tagValue.truncate(128);
        tagValue.append("...");
    }

    TQWhatsThis::add(this, i18n("<b>Title: </b><p>%1<p>"
                               "<b>Value: </b><p>%2<p>"
                               "<b>Description: </b><p>%3")
                          .arg(tagTitle)
                          .arg(tagValue)
                          .arg(tagDesc));
}

void MetadataListView::setIfdList(const DMetadata::MetaDataMap& ifds, const TQStringList& tagsfilter)
{
    clear();

    uint               subItems = 0;
    TQString            ifDItemName;
    MdKeyListViewItem *parentifDItem = 0;

    for (DMetadata::MetaDataMap::const_iterator it = ifds.begin(); it != ifds.end(); ++it)
    {
        // We checking if we have changed of ifDName
        TQString currentIfDName = it.key().section('.', 1, 1);

        if ( currentIfDName != ifDItemName )
        {
            ifDItemName = currentIfDName;

            // Check if the current IfD have any items. If no remove it before to toggle to the next IfD.
            if ( subItems == 0 && parentifDItem)
                delete parentifDItem;

            parentifDItem = new MdKeyListViewItem(this, currentIfDName);
            subItems = 0;
        }

        // We ignore all unknown tags if necessary.
        if (!it.key().section('.', 2, 2).startsWith("0x"))
        {
            if (!tagsfilter.isEmpty())
            {
                // We using the filter to make a more user friendly output (Simple Mode)

                if (tagsfilter.contains(it.key().section('.', 2, 2)))
                {
                    TQString tagTitle = m_parent->getTagTitle(it.key());
                    new MetadataListViewItem(parentifDItem, it.key(), tagTitle, it.data());
                    subItems++;
                }
            }
            else
            {
                // We don't filter the output (Complete Mode)

                TQString tagTitle = m_parent->getTagTitle(it.key());
                new MetadataListViewItem(parentifDItem, it.key(), tagTitle, it.data());
                subItems++;
            }
        }
    }

    // To check if the last IfD have any items...
    if ( subItems == 0 && parentifDItem)
        delete parentifDItem;

    setCurrentItemByKey(m_selectedItemKey);
    TQTimer::singleShot( 0, this, TQ_SLOT( triggerUpdate() ) );
}

void MetadataListView::setIfdList(const DMetadata::MetaDataMap& ifds, const TQStringList& keysFilter,
                                  const TQStringList& tagsFilter)
{
    clear();

    uint               subItems = 0;
    MdKeyListViewItem *parentifDItem = 0;

    for (TQStringList::const_iterator itKeysFilter = keysFilter.begin();
         itKeysFilter != keysFilter.end();
         ++itKeysFilter)
    {
        subItems = 0;
        parentifDItem = new MdKeyListViewItem(this, *itKeysFilter);

        DMetadata::MetaDataMap::const_iterator it = ifds.end();

        while(1)
        {
            if ( *itKeysFilter == it.key().section('.', 1, 1) )
            {
                // We ignore all unknown tags if necessary.
                if (!it.key().section('.', 2, 2).startsWith("0x"))
                {
                    if (!tagsFilter.isEmpty())
                    {
                        // We using the filter to make a more user friendly output (Simple Mode)

                        if (tagsFilter.contains(it.key().section('.', 2, 2)))
                        {
                            TQString tagTitle = m_parent->getTagTitle(it.key());
                            new MetadataListViewItem(parentifDItem, it.key(), tagTitle, it.data());
                            subItems++;
                        }
                    }
                    else
                    {
                        // We don't filter the output (Complete Mode)

                        TQString tagTitle = m_parent->getTagTitle(it.key());
                        new MetadataListViewItem(parentifDItem, it.key(), tagTitle, it.data());
                        subItems++;
                    }
                }
            }

            if (it == ifds.begin()) break;
            --it;
        }

        // We checking if the last IfD have any items. If no, we remove it.
        if ( subItems == 0 && parentifDItem)
            delete parentifDItem;
    }

    setCurrentItemByKey(m_selectedItemKey);
    TQTimer::singleShot( 0, this, TQ_SLOT( triggerUpdate() ) );
}

void MetadataListView::viewportResizeEvent(TQResizeEvent* e)
{
    TQListView::viewportResizeEvent(e);
    TQTimer::singleShot( 0, this, TQ_SLOT( triggerUpdate() ) );
}

void MetadataListView::slotSearchTextChanged(const TQString& filter)
{
    bool query     = false;
    TQString search = filter.lower();

    TQListViewItemIterator it(this);
    for ( ; it.current(); ++it )
    {
        MetadataListViewItem *item = dynamic_cast<MetadataListViewItem*>(it.current());
        if (item)
       {
            if (item->text(0).lower().contains(search) ||
                item->text(1).lower().contains(search))
            {
                query = true;
                item->setVisible(true);
            }
            else
            {
                item->setVisible(false);
            }
        }
    }

    emit signalTextFilterMatch(query);
}

}  // namespace Digikam
