summaryrefslogtreecommitdiffstats
path: root/src/gui/tablefieldwidget.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:17:32 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 19:17:32 +0000
commite38d2351b83fa65c66ccde443777647ef5cb6cff (patch)
tree1897fc20e9f73a81c520a5b9f76f8ed042124883 /src/gui/tablefieldwidget.cpp
downloadtellico-e38d2351b83fa65c66ccde443777647ef5cb6cff.tar.gz
tellico-e38d2351b83fa65c66ccde443777647ef5cb6cff.zip
Added KDE3 version of Tellico
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/tellico@1097620 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/gui/tablefieldwidget.cpp')
-rw-r--r--src/gui/tablefieldwidget.cpp330
1 files changed, 330 insertions, 0 deletions
diff --git a/src/gui/tablefieldwidget.cpp b/src/gui/tablefieldwidget.cpp
new file mode 100644
index 0000000..30f89b4
--- /dev/null
+++ b/src/gui/tablefieldwidget.cpp
@@ -0,0 +1,330 @@
+/***************************************************************************
+ 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 <qtable.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_, QWidget* 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(QString::fromLatin1("columns")), &ok);
+ if(!ok) {
+ m_columns = 1;
+ } else {
+ m_columns = QMIN(m_columns, MAX_TABLE_COLS); // max of 5 columns
+ }
+
+ m_table = new QTable(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(), SIGNAL(indexChange(int, int, int)), SIGNAL(modified()));
+
+ m_table->setDragEnabled(false);
+ m_table->setFocusStyle(QTable::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(QTable::NoSelection);
+ m_table->setHScrollBarMode(QScrollView::AlwaysOff);
+
+ connect(m_table, SIGNAL(valueChanged(int, int)), SIGNAL(modified()));
+ connect(m_table, SIGNAL(currentChanged(int, int)), SLOT(slotCheckRows(int, int)));
+ connect(m_table, SIGNAL(valueChanged(int, int)), SLOT(slotResizeColumn(int, int)));
+ connect(m_table, SIGNAL(contextMenuRequested(int, int, const QPoint&)), SLOT(contextMenu(int, int, const QPoint&)));
+
+ registerWidget();
+}
+
+QString TableFieldWidget::text() const {
+ QString 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 += QString::fromLatin1("::");
+ } else {
+ rowStr += cstack + str + QString::fromLatin1("::");
+ cstack.truncate(0);
+ }
+ }
+ if(rowStr.isEmpty()) {
+ rstack += QString::fromLatin1("; ");
+ } else {
+ rowStr.truncate(rowStr.length()-2); // remove last semi-colon and space
+ text += rstack + rowStr + QString::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 QString& text_) {
+ QStringList 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(QString::fromLatin1("::"), col, col));
+ }
+ m_table->showRow(row);
+ }
+ // remove any un-needed rows
+ int minRow = QMAX(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, QString::null);
+ }
+ if(row >= MIN_TABLE_ROWS) {
+ m_table->removeRow(row);
+ --row;
+ }
+ }
+ editMultiple(false);
+ if(!wasEmpty) {
+ emit modified();
+ }
+}
+
+QWidget* 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;
+ }
+ QString name = m_table->horizontalHeader()->label(m_col);
+ bool ok;
+ QString 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(QString::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) {
+ QString s = field_->property(QString::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(QString::fromLatin1("columns")), &ok);
+ if(!ok) {
+ m_columns = 1;
+ } else {
+ m_columns = QMIN(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(QObject* obj_, QEvent* ev_) {
+ if(ev_->type() == QEvent::MouseButtonPress
+ && static_cast<QMouseEvent*>(ev_)->button() == Qt::RightButton) {
+ if(obj_ == m_table->horizontalHeader()) {
+ QMouseEvent* ev = static_cast<QMouseEvent*>(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(QString::fromLatin1("edit")), i18n("Rename Column..."),
+ this, SLOT(slotRenameColumn()));
+ menu.exec(ev->globalPos());
+ return true;
+ } else if(obj_ == m_table->verticalHeader()) {
+ QMouseEvent* ev = static_cast<QMouseEvent*>(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 QPoint& 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(QString::fromLatin1("insrow")), i18n("Insert Row"),
+ this, SLOT(slotInsertRow()));
+ menu.insertItem(SmallIconSet(QString::fromLatin1("remrow")), i18n("Remove Row"),
+ this, SLOT(slotRemoveRow()));
+ id = menu.insertItem(SmallIconSet(QString::fromLatin1("1uparrow")), i18n("Move Row Up"),
+ this, SLOT(slotMoveRowUp()));
+ if(m_row == 0) {
+ menu.setItemEnabled(id, false);
+ }
+ id = menu.insertItem(SmallIconSet(QString::fromLatin1("1downarrow")), i18n("Move Row Down"),
+ this, SLOT(slotMoveRowDown()));
+ if(m_row == m_table->numRows()-1) {
+ menu.setItemEnabled(id, false);
+ }
+ menu.insertSeparator();
+ id = menu.insertItem(SmallIconSet(QString::fromLatin1("edit")), i18n("Rename Column..."),
+ this, SLOT(slotRenameColumn()));
+ if(m_col < 0 || m_col > m_columns-1) {
+ menu.setItemEnabled(id, false);
+ }
+ menu.insertSeparator();
+ menu.insertItem(SmallIconSet(QString::fromLatin1("locationbar_erase")), i18n("Clear Table"),
+ this, 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"