
/*
 *  infokcmmodel.h
 *
 *  Copyright (C) 2010 David Hubner <hubnerd@ntlworld.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 of the License, 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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

//Local
#include "infokcmmodel.h"
#include "kcmcategoryitem.h"

//KDE
#include <KServiceTypeTrader>
#include <QDebug>
#include <KLocalizedString>

InfoKcmModel::InfoKcmModel(QObject *parent)
    : QAbstractItemModel(parent),
      m_root(new KcmCategoryItem(i18n("Information Modules")))
{
    createTreeItems();
}

InfoKcmModel::~InfoKcmModel()
{
    delete m_root;
}

void InfoKcmModel::createTreeItems()
{
    const KService::List categoryList = KServiceTypeTrader::self()->query(QStringLiteral("KInfoCenterCategory"));

    for(const KService::Ptr &categoryModule : categoryList) {
        m_root->addChild(new KcmCategoryItem(categoryModule,m_root));
    }

    const KService::List moduleList = KServiceTypeTrader::self()->query(QStringLiteral("KCModule"), QStringLiteral("[X-KDE-ParentApp] == 'kinfocenter'"));

    for (const KService::Ptr &kcmModule : moduleList) {
        if (kcmModule->isType(KST_KService) == true) {

            QString category = kcmModule->property(QStringLiteral("X-KDE-KInfoCenter-Category")).toString().trimmed();

            if(!category.isEmpty() || !category.isNull()) {
                KcmTreeItem *item = m_root->containsCategory(category);
                if(item != nullptr) {
                    item->addChild(new KcmTreeItem(kcmModule,item));
                } else {
                    KcmTreeItem *lost = m_root->containsCategory(QStringLiteral("lost_and_found"));
                    if(lost != nullptr) {
                        lost->addChild(new KcmTreeItem(kcmModule,lost));
                    } else {
                        qWarning() << "Lost and found category not found, unable to display lost Kcontrol modules";
                    }
                }
            } else {
                m_root->addChild(new KcmTreeItem(kcmModule,m_root));
            }
        }
    }
}

QModelIndex InfoKcmModel::index(int row, int column, const QModelIndex &parent) const
{
    KcmTreeItem *parentItem;

    if (!parent.isValid()) {
        parentItem = m_root;
    } else {
        parentItem = static_cast<KcmTreeItem*>(parent.internalPointer());
    }

    KcmTreeItem *childItem = parentItem->child(row);

    if (childItem) {
        return createIndex(row, column, childItem);
    }
    return QModelIndex();
}

QModelIndex InfoKcmModel::index(int row, int column, KcmTreeItem *parent) const
{
    KcmTreeItem *childItem = parent->child(row);

    if (childItem) {
        return createIndex(row, column, childItem);
    }
    return QModelIndex();
}

QModelIndex InfoKcmModel::parent(const QModelIndex &index) const
{
    if (!index.isValid()) {
        return QModelIndex();
    }

    KcmTreeItem *child = static_cast<KcmTreeItem*>(index.internalPointer());
    KcmTreeItem *parent = child->parent();

    if (parent == m_root) {
        return QModelIndex();
    }

    return createIndex(parent->row(), 0, parent);
}

QModelIndex InfoKcmModel::indexOf(KcmTreeItem *item)
{
    QModelIndex tmpIndex = createIndex(item->row(), 0, item);

    if(!tmpIndex.isValid()) {
        return QModelIndex();
    }
    return tmpIndex;
}

int InfoKcmModel::rowCount(const QModelIndex &parent) const
{
    KcmTreeItem *parentItem;

    if (!parent.isValid()) {
        parentItem = m_root;
    } else {
        parentItem = static_cast<KcmTreeItem*>(parent.internalPointer());
    }

    return parentItem->childCount();
}

int InfoKcmModel::columnCount(const QModelIndex &parent) const
{
    // Hard coded, menu should never have more than one column

    Q_UNUSED(parent);
    return 1;
}

QVariant InfoKcmModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    KcmTreeItem *item = static_cast<KcmTreeItem*>(index.internalPointer());

    switch(role) {
    case Qt::DisplayRole:
        return item->data();
    case Qt::UserRole:
        return item->weight();
    case Qt::DecorationRole:
        return QIcon::fromTheme(item->iconName());
    default:
        return QVariant();
    }
}

QVariant InfoKcmModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(section);

    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
        return m_root->data();
    }

    return QVariant();
}

Qt::ItemFlags InfoKcmModel::flags(const QModelIndex &index) const
{
    if (!index.isValid()) {
        return Qt::ItemIsEnabled;
    }

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QModelIndex InfoKcmModel::firstValid() const
{
    int rows = m_root->childCount();

    // Massive large number to max compare
    unsigned int winner = 0; winner--;

    QModelIndex winnerIndex = QModelIndex();

    for(int i=0;i<rows;i++) {
        KcmTreeItem *item = m_root->child(i);
        if(item->type() == KcmTreeItem::KCM) {
            if(winner >= (unsigned int)item->weight()) {
                winner = item->weight();
                winnerIndex = index(item->row(),0,item->parent());
            }
        }
    }
    return winnerIndex;
}

QStringList InfoKcmModel::allChildrenKeywords()
{
    return childrenKeywords(m_root);
}

QStringList InfoKcmModel::childrenKeywords(KcmTreeItem *kcmItem)
{
    QStringList childKeywords;

    int rows = kcmItem->childCount();
    for(int i=0;i<rows;i++) {
        KcmTreeItem *item = kcmItem->child(i);
        if(item->type() == KcmTreeItem::CATEGORY) {
            childKeywords = childKeywords + childrenKeywords(item);
        } else {
            childKeywords = childKeywords + item->keywords();
        }
    }
    return childKeywords;
}
