/*
Copyright (C) 2006 Evan Teran
                   eteran@alum.rit.edu

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.
*/

#include "DialogMemoryRegions.h"
#include "DebuggerCoreInterface.h"
#include "Debugger.h"

#include <QHeaderView>
#include <QString>
#include <QMenu>
#include <QSortFilterProxyModel>
#include <QItemSelectionModel>

#include <boost/smart_ptr.hpp>

//------------------------------------------------------------------------------
// Name: DialogMemoryRegions(QWidget *parent)
// Desc: 
//------------------------------------------------------------------------------
DialogMemoryRegions::DialogMemoryRegions(QWidget *parent) : QDialog(parent) {
	ui.setupUi(this);

	ui.tableView->verticalHeader()->hide();
	ui.tableView->horizontalHeader()->setStretchLastSection(true);
	ui.tableView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
	
	m_FilterModel = new QSortFilterProxyModel(this);
	connect(ui.txtSearch, SIGNAL(textChanged(const QString &)), m_FilterModel, SLOT(setFilterFixedString(const QString &)));
}

//------------------------------------------------------------------------------
// Name: showEvent(QShowEvent *)
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::showEvent(QShowEvent *) {

	m_FilterModel->setFilterKeyColumn(3);
	m_FilterModel->setSourceModel(&edb::v1::memoryRegions());
	ui.tableView->setModel(m_FilterModel);
}

//------------------------------------------------------------------------------
// Name: on_tableWidget_customContextMenuRequested(const QPoint &pos)
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::on_tableView_customContextMenuRequested(const QPoint &pos) {
	
	QMenu *const accessMenu = new QMenu(tr("Set Access"), this);
	accessMenu->addAction(tr("No Access"), this, SLOT(setAccessNone()));	// ---
	accessMenu->addAction(tr("Read Only"), this, SLOT(setAccessR()));		// r--
	accessMenu->addAction(tr("Write Only"), this, SLOT(setAccessW()));		// -w-
	accessMenu->addAction(tr("Execute Only"), this, SLOT(setAccessX()));	// --x
	accessMenu->addAction(tr("Read/Write"), this, SLOT(setAccessRW()));		// rw-
	accessMenu->addAction(tr("Read/Execute"), this, SLOT(setAccessRX()));	// r-x
	accessMenu->addAction(tr("Write/Execute"), this, SLOT(setAccessWX()));	// -wx
	accessMenu->addAction(tr("Full Access"), this, SLOT(setAccessRWX()));	// rwx
	
	boost::scoped_ptr<QMenu> menu(new QMenu(this));
	menu->addMenu(accessMenu);
	menu->exec(ui.tableView->mapToGlobal(pos));
}

//------------------------------------------------------------------------------
// Name: selectedRegion() const
// Desc: 
//------------------------------------------------------------------------------
MemRegion *DialogMemoryRegions::selectedRegion() const {
	const QItemSelectionModel *const selModel = ui.tableView->selectionModel();
	const QModelIndexList sel = selModel->selectedRows();
	MemRegion *ret = 0;
	if(sel.size() == 1) {
		const QModelIndex index = m_FilterModel->mapToSource(sel[0]);
		ret = reinterpret_cast<MemRegion *>(index.internalPointer());
	}
	return ret;
}

//------------------------------------------------------------------------------
// Name: setPermissions(bool read, bool write, bool execute)
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setPermissions(bool read, bool write, bool execute) {
	MemRegion *const region = selectedRegion();

	if(region != 0) {
		region->setPermissions(edb::v1::setDebugEventHandler, edb::v1::memoryRegions(), edb::v1::debuggerBase, read, write, execute);
		edb::v1::memoryRegions().sync();
	}
}

//------------------------------------------------------------------------------
// Name: setAccessNone()
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setAccessNone() {
	setPermissions(false, false, false);
}

//------------------------------------------------------------------------------
// Name: setAccessR()
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setAccessR() {
	setPermissions(true, false, false);
}

//------------------------------------------------------------------------------
// Name: setAccessW()
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setAccessW() {
	setPermissions(false, true, false);
}

//------------------------------------------------------------------------------
// Name: setAccessX()
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setAccessX() {
	setPermissions(false, false, true);
}

//------------------------------------------------------------------------------
// Name: setAccessRW()
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setAccessRW() {
	setPermissions(true, true, false);
}

//------------------------------------------------------------------------------
// Name: setAccessRX()
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setAccessRX() {
	setPermissions(true, false, true);
}

//------------------------------------------------------------------------------
// Name: setAccessWX()
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setAccessWX() {
	setPermissions(false, true, true);
}

//------------------------------------------------------------------------------
// Name: setAccessRWX()
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setAccessRWX() {
	setPermissions(true, true, true);
}

