/*
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 "MemoryRegions.h"
#include "Debugger.h"

#include <QHeaderView>
#include <QString>
#include <QVector>
#include <QMenu>

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
DialogMemoryRegions::DialogMemoryRegions(QWidget *parent) : QDialog(parent) {
	ui.setupUi(this);
	ui.tableWidget->verticalHeader()->hide();
	ui.tableWidget->horizontalHeader()->setStretchLastSection(true);
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::showEvent(QShowEvent *) {
	updateView(ui.txtSearch->text());
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::on_txtSearch_textChanged(const QString &text) {
	updateView(text);
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::updateView(const QString &filter) {
	if(Debugger::memoryRegions != 0) {
		Debugger::memoryRegions->sync();
		QVector<MemoryRegions::Region> r = Debugger::memoryRegions->regions();

		ui.tableWidget->setSortingEnabled(false);
		ui.tableWidget->setRowCount(0);
		for(QVector<MemoryRegions::Region>::const_iterator i = r.begin(); i != r.end(); ++i) {
		
			const QString regionName = i->name;
			if(filter.isEmpty() || regionName.toLower().contains(filter.toLower())) {
				int row = ui.tableWidget->rowCount();
				ui.tableWidget->insertRow(row);
			
				ui.tableWidget->setItem(row, 0, new QTableWidgetItem(QString().sprintf("%08x", i->start)));
				ui.tableWidget->setItem(row, 1, new QTableWidgetItem(QString().sprintf("%08x", i->end)));
				ui.tableWidget->setItem(row, 2, new QTableWidgetItem(QString().sprintf("%c%c%c", i->readable() ? 'r' : '-', i->writeable() ? 'w' : '-', i->executable() ? 'x' : '-' )));
				ui.tableWidget->setItem(row, 3, new QTableWidgetItem(regionName));
			}
		}
		ui.tableWidget->setSortingEnabled(true);
		
	} else {
		ui.tableWidget->setRowCount(0);
	}
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::on_tableWidget_customContextMenuRequested(const QPoint &pos) {
	QMenu *const menu = new QMenu(this);
	
	QMenu *const accessMenu = new QMenu("Set Access", this);

	accessMenu->addAction("No Access", this, SLOT(setAccessNone()));	// ---
	accessMenu->addAction("Read Only", this, SLOT(setAccessR()));		// r--
	accessMenu->addAction("Write Only", this, SLOT(setAccessW()));		// -w-
	accessMenu->addAction("Execute Only", this, SLOT(setAccessX()));	// --x
	accessMenu->addAction("Read/Write", this, SLOT(setAccessRW()));		// rw-
	accessMenu->addAction("Read/Execute", this, SLOT(setAccessRX()));	// r-x
	accessMenu->addAction("Write/Execute", this, SLOT(setAccessWX()));	// -wx
	accessMenu->addAction("Full Access", this, SLOT(setAccessRWX()));	// rwx
	
	menu->addMenu(accessMenu);
	menu->exec(ui.tableWidget->mapToGlobal(pos));
	delete menu;
}

//------------------------------------------------------------------------------
// Name: 
// Desc: 
//------------------------------------------------------------------------------
void DialogMemoryRegions::setPermissions(bool read, bool write, bool execute) {
	QList<QTableWidgetItem *> sel = ui.tableWidget->selectedItems();
	if(sel.size() != 0) {
		const BaseTypes::address_t region_start	= sel.begin()[0]->text().toUInt(0, 16);
		MemoryRegions::Region r;
		if(Debugger::memoryRegions->findRegion(region_start, r)) {
			r.setPermissions(read, write, execute);
		}
		updateView(ui.txtSearch->text());
	}
}

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

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

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

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

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

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

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

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

