You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tellico/src/gui/tablefieldwidget.cpp

331 lines
10 KiB

/***************************************************************************
copyright : (C) 2003-2006 by Robby Stephenson
email : robby@periapsis.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of version 2 of the GNU General Public License as *
* published by the Free Software Foundation; *
* *
***************************************************************************/
#include "tablefieldwidget.h"
#include "../field.h"
#include "../tellico_utils.h"
#include "../tellico_kernel.h"
#include <klocale.h>
#include <kpopupmenu.h>
#include <kiconloader.h>
#include <kinputdialog.h>
#include <tqtable.h>
namespace {
static const int MIN_TABLE_ROWS = 5;
static const int MAX_TABLE_COLS = 10;
}
using Tellico::GUI::TableFieldWidget;
TableFieldWidget::TableFieldWidget(Data::FieldPtr field_, TQWidget* parent_, const char* name_/*=0*/)
: FieldWidget(field_, parent_, name_), m_field(field_), m_row(-1), m_col(-1) {
bool ok;
m_columns = Tellico::toUInt(field_->property(TQString::fromLatin1("columns")), &ok);
if(!ok) {
m_columns = 1;
} else {
m_columns = TQMIN(m_columns, MAX_TABLE_COLS); // max of 5 columns
}
m_table = new TQTable(MIN_TABLE_ROWS, m_columns, this);
labelColumns(m_field);
// allow renaming of column titles
m_table->horizontalHeader()->setClickEnabled(true);
m_table->horizontalHeader()->installEventFilter(this);
m_table->verticalHeader()->setClickEnabled(true);
m_table->verticalHeader()->installEventFilter(this);
connect(m_table->verticalHeader(), TQT_SIGNAL(indexChange(int, int, int)), TQT_SIGNAL(modified()));
m_table->setDragEnabled(false);
m_table->setFocusStyle(TQTable::FollowStyle);
m_table->setRowMovingEnabled(true); // rows can be moved
m_table->setColumnMovingEnabled(false); // columns remain fixed
m_table->setColumnStretchable(m_columns-1, true);
m_table->adjustColumn(m_columns-1);
m_table->setSelectionMode(TQTable::NoSelection);
m_table->setHScrollBarMode(TQScrollView::AlwaysOff);
connect(m_table, TQT_SIGNAL(valueChanged(int, int)), TQT_SIGNAL(modified()));
connect(m_table, TQT_SIGNAL(currentChanged(int, int)), TQT_SLOT(slotCheckRows(int, int)));
connect(m_table, TQT_SIGNAL(valueChanged(int, int)), TQT_SLOT(slotResizeColumn(int, int)));
connect(m_table, TQT_SIGNAL(contextMenuRequested(int, int, const TQPoint&)), TQT_SLOT(contextMenu(int, int, const TQPoint&)));
registerWidget();
}
TQString TableFieldWidget::text() const {
TQString text, str, rstack, cstack, rowStr;
for(int row = 0; row < m_table->numRows(); ++row) {
rowStr.truncate(0);
cstack.truncate(0);
for(int col = 0; col < m_table->numCols(); ++col) {
str = m_table->text(row, col).simplifyWhiteSpace();
if(str.isEmpty()) {
cstack += TQString::fromLatin1("::");
} else {
rowStr += cstack + str + TQString::fromLatin1("::");
cstack.truncate(0);
}
}
if(rowStr.isEmpty()) {
rstack += TQString::fromLatin1("; ");
} else {
rowStr.truncate(rowStr.length()-2); // remove last semi-colon and space
text += rstack + rowStr + TQString::fromLatin1("; ");
rstack.truncate(0);
}
}
if(!text.isEmpty()) {
text.truncate(text.length()-2); // remove last semi-colon and space
}
// now reduce number of rows if necessary
bool loop = true;
for(int row = m_table->numRows()-1; loop && row > MIN_TABLE_ROWS; --row) {
bool empty = true;
for(int col = 0; col < m_table->numCols(); ++col) {
if(!m_table->text(row, col).isEmpty()) {
empty = false;
break;
}
}
if(empty) {
m_table->removeRow(row);
} else {
loop = false;
}
}
return text;
}
void TableFieldWidget::setText(const TQString& text_) {
TQStringList list = Data::Field::split(text_, true);
// add additional rows if needed
if(static_cast<int>(list.count()) > m_table->numRows()) {
m_table->insertRows(m_table->numRows(), list.count()-m_table->numRows());
}
int row;
for(row = 0; row < static_cast<int>(list.count()); ++row) {
for(int col = 0; col < m_table->numCols(); ++col) {
m_table->setText(row, col, list[row].section(TQString::fromLatin1("::"), col, col));
}
m_table->showRow(row);
}
// remove any un-needed rows
int minRow = TQMAX(row, MIN_TABLE_ROWS);
for(row = m_table->numRows()-1; row >= minRow; --row) {
m_table->removeRow(row);
}
// adjust all columns
for(int col = 0; col < m_table->numCols()-1; ++col) {
m_table->adjustColumn(col);
}
}
void TableFieldWidget::clear() {
bool wasEmpty = true;
for(int row = 0; row < m_table->numRows(); ++row) {
if(!emptyRow(row)) {
wasEmpty = false;
}
for(int col = 0; col < m_table->numCols(); ++col) {
m_table->setText(row, col, TQString());
}
if(row >= MIN_TABLE_ROWS) {
m_table->removeRow(row);
--row;
}
}
editMultiple(false);
if(!wasEmpty) {
emit modified();
}
}
TQWidget* TableFieldWidget::widget() {
return m_table;
}
void TableFieldWidget::slotCheckRows(int row_, int) {
if(row_ == m_table->numRows()-1 && !emptyRow(row_)) { // if is last row and row above is not empty
m_table->insertRows(m_table->numRows());
}
}
void TableFieldWidget::slotResizeColumn(int, int col_) {
m_table->adjustColumn(col_);
}
void TableFieldWidget::slotRenameColumn() {
if(m_col < 0 || m_col >= m_columns) {
return;
}
TQString name = m_table->horizontalHeader()->label(m_col);
bool ok;
TQString newName = KInputDialog::getText(i18n("Rename Column"), i18n("New column name:"),
name, &ok, this);
if(ok && !newName.isEmpty()) {
Data::FieldPtr newField = new Data::Field(*m_field);
newField->setProperty(TQString::fromLatin1("column%1").arg(m_col+1), newName);
if(Kernel::self()->modifyField(newField)) {
m_field = newField;
labelColumns(m_field);
}
}
}
bool TableFieldWidget::emptyRow(int row_) const {
for(int col = 0; col < m_table->numCols(); ++col) {
if(!m_table->text(row_, col).isEmpty()) {
return false;
}
}
return true;
}
void TableFieldWidget::labelColumns(Data::FieldPtr field_) {
for(int i = 0; i < m_columns; ++i) {
TQString s = field_->property(TQString::fromLatin1("column%1").arg(i+1));
if(s.isEmpty()) {
s = i18n("Column %1").arg(i+1);
}
m_table->horizontalHeader()->setLabel(i, s);
}
}
void TableFieldWidget::updateFieldHook(Data::FieldPtr, Data::FieldPtr newField_) {
bool ok;
m_columns = Tellico::toUInt(newField_->property(TQString::fromLatin1("columns")), &ok);
if(!ok) {
m_columns = 1;
} else {
m_columns = TQMIN(m_columns, MAX_TABLE_COLS); // max of 5 columns
}
if(m_columns != m_table->numCols()) {
m_table->setNumCols(m_columns);
}
m_table->horizontalHeader()->adjustHeaderSize();
labelColumns(newField_);
}
bool TableFieldWidget::eventFilter(TQObject* obj_, TQEvent* ev_) {
if(ev_->type() == TQEvent::MouseButtonPress
&& TQT_TQMOUSEEVENT(ev_)->button() == Qt::RightButton) {
if(TQT_BASE_OBJECT(obj_) == TQT_BASE_OBJECT(m_table->horizontalHeader())) {
TQMouseEvent* ev = TQT_TQMOUSEEVENT(ev_);
// might be scrolled
int pos = ev->x() + m_table->horizontalHeader()->offset();
int col = m_table->horizontalHeader()->sectionAt(pos);
if(col >= m_columns) {
return false;
}
m_row = -1;
m_col = col;
KPopupMenu menu(this);
menu.insertItem(SmallIconSet(TQString::fromLatin1("edit")), i18n("Rename Column..."),
this, TQT_SLOT(slotRenameColumn()));
menu.exec(ev->globalPos());
return true;
} else if(TQT_BASE_OBJECT(obj_) == TQT_BASE_OBJECT(m_table->verticalHeader())) {
TQMouseEvent* ev = TQT_TQMOUSEEVENT(ev_);
// might be scrolled
int pos = ev->y() + m_table->verticalHeader()->offset();
int row = m_table->verticalHeader()->sectionAt(pos);
if(row < 0 || row > m_table->numRows()-1) {
return false;
}
m_row = row;
m_col = -1;
// show regular right-click menu
contextMenu(m_row, m_col, ev->globalPos());
return true;
}
}
return FieldWidget::eventFilter(obj_, ev_);
}
void TableFieldWidget::contextMenu(int row_, int col_, const TQPoint& p_) {
// might get called with col == -1 for clicking on vertical header
// but a negative row means clicking outside bounds of table
if(row_ < 0) {
return;
}
m_row = row_;
m_col = col_;
int id;
KPopupMenu menu(this);
menu.insertItem(SmallIconSet(TQString::fromLatin1("insrow")), i18n("Insert Row"),
this, TQT_SLOT(slotInsertRow()));
menu.insertItem(SmallIconSet(TQString::fromLatin1("remrow")), i18n("Remove Row"),
this, TQT_SLOT(slotRemoveRow()));
id = menu.insertItem(SmallIconSet(TQString::fromLatin1("1uparrow")), i18n("Move Row Up"),
this, TQT_SLOT(slotMoveRowUp()));
if(m_row == 0) {
menu.setItemEnabled(id, false);
}
id = menu.insertItem(SmallIconSet(TQString::fromLatin1("1downarrow")), i18n("Move Row Down"),
this, TQT_SLOT(slotMoveRowDown()));
if(m_row == m_table->numRows()-1) {
menu.setItemEnabled(id, false);
}
menu.insertSeparator();
id = menu.insertItem(SmallIconSet(TQString::fromLatin1("edit")), i18n("Rename Column..."),
this, TQT_SLOT(slotRenameColumn()));
if(m_col < 0 || m_col > m_columns-1) {
menu.setItemEnabled(id, false);
}
menu.insertSeparator();
menu.insertItem(SmallIconSet(TQString::fromLatin1("locationbar_erase")), i18n("Clear Table"),
this, TQT_SLOT(clear()));
menu.exec(p_);
}
void TableFieldWidget::slotInsertRow() {
if(m_row > -1) {
m_table->insertRows(m_row);
emit modified();
}
}
void TableFieldWidget::slotRemoveRow() {
if(m_row > -1) {
m_table->removeRow(m_row);
emit modified();
}
}
void TableFieldWidget::slotMoveRowUp() {
if(m_row > 0) {
m_table->swapRows(m_row, m_row-1, true);
m_table->updateContents();
emit modified();
}
}
void TableFieldWidget::slotMoveRowDown() {
if(m_row < m_table->numRows()-1) {
m_table->swapRows(m_row, m_row+1, true);
m_table->updateContents();
emit modified();
}
}
#include "tablefieldwidget.moc"