/*
 * Copyright Johannes Sixt
 * This file is licensed under the GNU General Public License Version 2.
 * See the file COPYING in the toplevel directory of the source directory.
 */

#include "threadlist.h"
#include "dbgdriver.h"
#include <tdelocale.h>
#include <kiconloader.h>
#include <tqbitmap.h>
#include <tqpainter.h>


class ThreadEntry : public TQListViewItem, public ThreadInfo
{
public:
    ThreadEntry(TQListView* parent, const ThreadInfo& thread);
    void setFunction(const TQString& func);

    bool m_delete;			/* used for updating the list */
};

ThreadEntry::ThreadEntry(TQListView* parent, const ThreadInfo& thread) :
	TQListViewItem(parent, thread.threadName, thread.function),
	ThreadInfo(thread),
	m_delete(false)
{
}

void ThreadEntry::setFunction(const TQString& func)
{
    function = func;
    setText(1, function);
}


ThreadList::ThreadList(TQWidget* parent, const char* name) :
	TQListView(parent, name)
{
    addColumn(i18n("Thread ID"), 150);
    addColumn(i18n("Location"));

    // load pixmaps
    m_focusIcon = UserIcon("pcinner");
    makeNoFocusIcon();

    connect(this, TQ_SIGNAL(currentChanged(TQListViewItem*)),
	    this, TQ_SLOT(slotCurrentChanged(TQListViewItem*)));
}

ThreadList::~ThreadList()
{
}

void ThreadList::updateThreads(const std::list<ThreadInfo>& threads)
{
    // reset flag in all items
    for (TQListViewItem* e = firstChild(); e != 0; e = e->nextSibling()) {
	static_cast<ThreadEntry*>(e)->m_delete = true;
    }

    for (std::list<ThreadInfo>::const_iterator i = threads.begin(); i != threads.end(); ++i)
    {
	// look up this thread by id
	ThreadEntry* te = threadById(i->id);
	if (te == 0) {
	    te = new ThreadEntry(this, *i);
	} else {
	    te->m_delete = false;
	    te->setFunction(i->function);
	}
	// set focus icon
	te->hasFocus = i->hasFocus;
	te->setPixmap(0, i->hasFocus  ?  m_focusIcon  :  m_noFocusIcon);
    }

    // delete all entries that have not been seen
    for (TQListViewItem* e = firstChild(); e != 0;) {
	ThreadEntry* te = static_cast<ThreadEntry*>(e);
	e = e->nextSibling();		/* step ahead before deleting it ;-) */
	if (te->m_delete) {
	    delete te;
	}
    }
}

ThreadEntry* ThreadList::threadById(int id)
{
    for (TQListViewItem* e = firstChild(); e != 0; e = e->nextSibling()) {
	ThreadEntry* te = static_cast<ThreadEntry*>(e);
	if (te->id == id) {
	    return te;
	}
    }
    return 0;
}

/*
 * Creates an icon of the same size as the m_focusIcon, but which is
 * totally transparent.
 */
void ThreadList::makeNoFocusIcon()
{
    m_noFocusIcon = m_focusIcon;
    {
	TQPainter p(&m_noFocusIcon);
	p.fillRect(0,0, m_noFocusIcon.width(),m_noFocusIcon.height(), TQColor(white));
    }
    m_noFocusIcon.setMask(m_noFocusIcon.createHeuristicMask());
}

void ThreadList::slotCurrentChanged(TQListViewItem* newItem)
{
    if (newItem == 0)
	return;

    ThreadEntry* te = static_cast<ThreadEntry*>(newItem);

    // change the focused thread
    if (te->hasFocus)
	return;

    emit setThread(te->id);
}


#include "threadlist.moc"
