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.
1299 lines
41 KiB
1299 lines
41 KiB
15 years ago
|
/***************************************************************************
|
||
|
tableeditor.cpp - table editor dialog
|
||
|
begin : Thu 15 Apr 2004
|
||
|
copyright : (C) 2004 by Andras Mantia <amantia@kde.org>
|
||
|
***************************************************************************/
|
||
|
|
||
|
/***************************************************************************
|
||
|
*
|
||
|
* 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; version 2 of the License.
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
//kde includes
|
||
|
#include <kapplication.h>
|
||
|
#include <kdebug.h>
|
||
|
#include <kiconloader.h>
|
||
|
#include <klocale.h>
|
||
|
#include <kmessagebox.h>
|
||
|
#include <kparts/componentfactory.h>
|
||
|
#include <kpopupmenu.h>
|
||
|
#include <kpushbutton.h>
|
||
|
#include <ktexteditor/document.h>
|
||
|
#include <ktexteditor/editinterface.h>
|
||
|
|
||
|
//qt includes
|
||
|
#include <qcheckbox.h>
|
||
|
#include <qiconset.h>
|
||
|
#include <qlineedit.h>
|
||
|
#include <qobject.h>
|
||
|
#include <qpoint.h>
|
||
|
#include <qrect.h>
|
||
|
#include <qspinbox.h>
|
||
|
#include <qstring.h>
|
||
|
#include <qtabwidget.h>
|
||
|
#include <qvaluevector.h>
|
||
|
|
||
|
//own includes
|
||
|
#include "tagdialog.h"
|
||
|
#include "parser.h"
|
||
|
#include "node.h"
|
||
|
#include "tag.h"
|
||
|
|
||
|
#include "quantacommon.h"
|
||
|
#include "tableitem.h"
|
||
|
#include "tableeditor.h"
|
||
|
|
||
|
int newNum;
|
||
|
|
||
|
TableEditor::TableEditor(QWidget* parent, const char* name)
|
||
|
: TableEditorS(parent, name)
|
||
|
{
|
||
|
m_popup = new KPopupMenu();
|
||
|
m_cellEditId = m_popup->insertItem(i18n("&Edit Cell Properties"), this ,SLOT(slotEditCell()));
|
||
|
m_rowEditId = m_popup->insertItem(i18n("Edit &Row Properties"), this ,SLOT(slotEditRow()));
|
||
|
// m_colEditId = m_popup->insertItem(i18n("Edit &Column Properties"), this ,SLOT(slotEditCol()));
|
||
|
m_mergeSeparatorId = m_popup->insertSeparator();
|
||
|
m_mergeCellsId = m_popup->insertItem(i18n("Merge Cells"), this, SLOT(slotMergeCells()));
|
||
|
m_unmergeCellsId = m_popup->insertItem(i18n("Break Merging"), this, SLOT(slotUnmergeCells()));
|
||
|
|
||
|
m_popup->insertSeparator();
|
||
|
m_popup->insertItem(i18n("&Insert Row"), this, SLOT(slotInsertRow()));
|
||
|
m_popup->insertItem(i18n("Insert Co&lumn"), this, SLOT(slotInsertCol()));
|
||
|
m_popup->insertItem(i18n("Remove Row"), this, SLOT(slotRemoveRow()));
|
||
|
m_popup->insertItem(i18n("Remove Column"), this, SLOT(slotRemoveCol()));
|
||
|
m_popup->insertSeparator();
|
||
|
m_popup->insertItem(i18n("Edit &Table Properties"), this, SLOT(slotEditTable()));
|
||
|
m_editChildId = m_popup->insertItem(i18n("Edit Child Table"), this, SLOT(slotEditChildTable()));
|
||
|
|
||
|
buttonOk->setIconSet(SmallIconSet("button_ok"));
|
||
|
buttonCancel->setIconSet(SmallIconSet("button_cancel"));
|
||
|
buttonHelp->setIconSet(SmallIconSet("help"));
|
||
|
|
||
|
m_row = m_col = -1;
|
||
|
m_tbody = 0L;
|
||
|
m_thead = 0L;
|
||
|
m_tfoot = 0L;
|
||
|
m_table = 0L;
|
||
|
m_dtd = 0L;
|
||
|
m_write = 0L;
|
||
|
m_tableDataTags = new QValueList<QValueList<TableNode> >;
|
||
|
m_tableHeaderTags = new QValueList<QValueList<TableNode> >;
|
||
|
m_tableFooterTags = new QValueList<QValueList<TableNode> >;
|
||
|
m_tableTags = 0L;
|
||
|
m_tableDataRows = new QValueList<TableNode>;
|
||
|
m_tableHeaderRows = new QValueList<TableNode>;
|
||
|
m_tableFooterRows = new QValueList<TableNode>;
|
||
|
m_tableRows = 0L;
|
||
|
m_createNodes = true;
|
||
|
newNum += 7;
|
||
|
|
||
|
connect(headerColSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveCol(int)));
|
||
|
connect(headerRowSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveRow(int)));
|
||
|
connect(rowSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveRow(int)));
|
||
|
connect(colSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveCol(int)));
|
||
|
connect(footerRowSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveRow(int)));
|
||
|
connect(footerColSpinBox, SIGNAL(valueChanged(int)), SLOT(slotAddRemoveCol(int)));
|
||
|
connect(tableData, SIGNAL(contextMenuRequested(int,int,const QPoint&)),
|
||
|
SLOT(slotContextMenuRequested(int,int,const QPoint&)));
|
||
|
connect(pushButton7, SIGNAL(clicked()), SLOT(slotEditTable()));
|
||
|
connect(pushButton7_2, SIGNAL(clicked()), SLOT(slotEditTableBody()));
|
||
|
connect(pushButton7_3, SIGNAL(clicked()), SLOT(slotEditTableHeader()));
|
||
|
connect(pushButton7_4, SIGNAL(clicked()), SLOT(slotEditTableFooter()));
|
||
|
connect(headerTableData, SIGNAL(contextMenuRequested(int,int,const QPoint&)),
|
||
|
SLOT(slotContextMenuRequested(int,int,const QPoint&)));
|
||
|
connect(footerTableData, SIGNAL(contextMenuRequested(int,int,const QPoint&)),
|
||
|
SLOT(slotContextMenuRequested(int,int,const QPoint&)));
|
||
|
connect(tabWidget, SIGNAL(currentChanged(QWidget*)), SLOT(slotTabChanged(QWidget*)));
|
||
|
connect(buttonHelp, SIGNAL(clicked()), SLOT(slotHelpInvoked()));
|
||
|
connect(tableData, SIGNAL(valueChanged(int,int)), SLOT(slotEditCellText(int,int)));
|
||
|
connect(headerTableData, SIGNAL(valueChanged(int,int)), SLOT(slotEditCellText(int,int)));
|
||
|
connect(footerTableData, SIGNAL(valueChanged(int,int)), SLOT(slotEditCellText(int,int)));
|
||
|
}
|
||
|
|
||
|
TableEditor::~TableEditor()
|
||
|
{
|
||
|
delete m_popup;
|
||
|
delete m_tbody;
|
||
|
delete m_thead;
|
||
|
delete m_tfoot;
|
||
|
delete m_table;
|
||
|
newNum -=5;
|
||
|
deleteMatrix(m_tableDataTags);
|
||
|
deleteMatrix(m_tableHeaderTags);
|
||
|
deleteMatrix(m_tableFooterTags);
|
||
|
deleteList(m_tableDataRows);
|
||
|
deleteList(m_tableHeaderRows);
|
||
|
deleteList(m_tableFooterRows);
|
||
|
kdDebug(24000) << "Undeleted new: " << newNum << endl;
|
||
|
}
|
||
|
|
||
|
void TableEditor::slotContextMenuRequested( int row, int col, const QPoint & pos )
|
||
|
{
|
||
|
m_row = row;
|
||
|
m_col = col;
|
||
|
m_popup->setItemEnabled(m_cellEditId, (row >=0 && col >=0));
|
||
|
m_popup->setItemEnabled(m_rowEditId, (row >=0));
|
||
|
m_popup->setItemEnabled(m_colEditId, (col >=0));
|
||
|
m_popup->setItemVisible(m_mergeSeparatorId, false);
|
||
|
m_popup->setItemVisible(m_mergeCellsId, false);
|
||
|
m_popup->setItemVisible(m_unmergeCellsId, false);
|
||
|
if (row >=0 && col >=0) {
|
||
|
TableNode tableNode = (*m_tableTags)[m_row][m_col];
|
||
|
m_popup->setItemVisible(m_mergeSeparatorId, false);
|
||
|
m_popup->setItemVisible(m_mergeCellsId, false);
|
||
|
m_popup->setItemVisible(m_editChildId, false);
|
||
|
if (tableNode.merged) {
|
||
|
m_popup->setItemVisible(m_unmergeCellsId, true);
|
||
|
m_popup->setItemVisible(m_mergeSeparatorId, true);
|
||
|
}
|
||
|
QTableSelection selection = m_dataTable->selection(m_dataTable->currentSelection());
|
||
|
QRect rect(QPoint(selection.topRow(), selection.leftCol()) ,
|
||
|
QPoint(selection.bottomRow(), selection.rightCol()));
|
||
|
if (rect.isValid() && (rect.width() > 1 || rect.height() > 1) && rect.contains(m_row, m_col)) {
|
||
|
m_popup->setItemVisible(m_mergeCellsId, true);
|
||
|
m_popup->setItemVisible(m_mergeSeparatorId, true);
|
||
|
}
|
||
|
if (m_dataTable->item(m_row, m_col) && !m_dataTable->item(m_row, m_col)->pixmap().isNull()) {
|
||
|
m_popup->setItemVisible(m_editChildId, true);
|
||
|
}
|
||
|
}
|
||
|
m_popup->popup(pos);
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotEditCell()
|
||
|
{
|
||
|
Tag *tag = (*m_tableTags)[m_row][m_col].node->tag;
|
||
|
TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd, "td"), tag, m_baseURL);
|
||
|
int many = 0;
|
||
|
if (dlg.exec()) {
|
||
|
for (int row = 0; row < m_dataTable->numRows(); row++)
|
||
|
for (int col = 0; col < m_dataTable->numCols(); col++) {
|
||
|
many++;
|
||
|
if (m_dataTable->isSelected(row, col)) {
|
||
|
(*m_tableTags)[row][col].node->tag->modifyAttributes(dlg.getAttributes());
|
||
|
configureCell(row, col, (*m_tableTags)[row][col].node);
|
||
|
}
|
||
|
}
|
||
|
if (!many) {
|
||
|
(*m_tableTags)[m_row][m_col].node->tag->modifyAttributes(dlg.getAttributes());
|
||
|
configureCell(m_row, m_col, (*m_tableTags)[m_row][m_col].node);
|
||
|
}
|
||
|
//TODO: add/remove columns/rows if the colspan/rowspan attribute is changed
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TableEditor::slotEditCellText( int r, int )
|
||
|
{
|
||
|
m_dataTable->adjustRow(r);
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotEditRow()
|
||
|
{
|
||
|
Tag *tag = (*m_tableRows)[m_row].node->tag;
|
||
|
TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"tr"), tag, m_baseURL);
|
||
|
if (dlg.exec()) {
|
||
|
tag->modifyAttributes(dlg.getAttributes());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotEditCol()
|
||
|
{
|
||
|
KMessageBox::information(this, i18n("Edit col: %1").arg(m_col + 1));
|
||
|
TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"col"));
|
||
|
dlg.exec();
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotEditTable()
|
||
|
{
|
||
|
TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"table"), m_table, m_baseURL);
|
||
|
if (dlg.exec()) {
|
||
|
m_table->modifyAttributes(dlg.getAttributes());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotEditTableBody()
|
||
|
{
|
||
|
TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"tbody"), m_tbody, m_baseURL);
|
||
|
if (dlg.exec()) {
|
||
|
m_tbody->modifyAttributes(dlg.getAttributes());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
bool TableEditor::setTableArea( int bLine, int bCol, int eLine, int eCol, Parser *docParser )
|
||
|
{
|
||
|
const uint pInitialTableSize = 20;
|
||
|
|
||
|
m_bLine = bLine;
|
||
|
m_bCol = bCol;
|
||
|
m_eLine = eLine;
|
||
|
m_eCol = eCol;
|
||
|
m_createNodes = false; //don't create the cell and row content when adding a new cell/row
|
||
|
Node *node = docParser->nodeAt(bLine, bCol + 1);
|
||
|
Node *lastNode = docParser->nodeAt(eLine, eCol);
|
||
|
if (node)
|
||
|
kdDebug(24000) << "node = " << node->tag->name << endl;
|
||
|
if (lastNode)
|
||
|
kdDebug(24000) << "lastnode = " << lastNode->tag->name << endl;
|
||
|
if (!node || !lastNode)
|
||
|
return false;
|
||
|
m_write = node->tag->write();
|
||
|
m_dtd = node->tag->dtd();
|
||
|
if ( !QuantaCommon::closesTag(node->tag, lastNode->tag) ) {
|
||
|
return false;
|
||
|
}
|
||
|
int nCol, nRow, maxCol;
|
||
|
nCol = nRow = maxCol = 0;
|
||
|
bool countRows = false;
|
||
|
bool missingBody = false;
|
||
|
m_rowSpin = 0L;
|
||
|
m_colSpin = 0L;
|
||
|
m_dataTable = 0L;
|
||
|
QValueList<TableNode> tableRowTags;
|
||
|
QValueVector< QValueVector<TableNode> > mergeMatrix;
|
||
|
mergeMatrix.resize(pInitialTableSize);
|
||
|
for (uint i = 0; i < pInitialTableSize; i++)
|
||
|
mergeMatrix[i].resize(pInitialTableSize);
|
||
|
TableNode tableNode;
|
||
|
Node *n = node;
|
||
|
while (n != lastNode->nextSibling())
|
||
|
{
|
||
|
QString tagName = n->tag->name.lower();
|
||
|
if (tagName == "table")
|
||
|
{
|
||
|
if (m_table && m_dataTable && nRow > 0 && nCol > 0) //nested table!
|
||
|
{
|
||
|
int line, col;
|
||
|
n->tag->beginPos(line, col);
|
||
|
NestedTable table;
|
||
|
table.row = nRow -1;
|
||
|
table.col = nCol - 1;
|
||
|
table.bLine = line;
|
||
|
table.bCol = col;
|
||
|
if (n->next && QuantaCommon::closesTag(n->tag, n->next->tag)) {
|
||
|
n->next->tag->endPos(table.eLine, table.eCol);
|
||
|
table.node = n;
|
||
|
table.nestedData = m_write->text(table.bLine, table.bCol, table.eLine, table.eCol);
|
||
|
m_nestedTables.append(table);
|
||
|
m_dataTable->item(nRow -1, nCol -1)->setPixmap(QIconSet(UserIcon("quick_table")).pixmap());
|
||
|
m_dataTable->updateCell(nRow - 1, nCol - 1);
|
||
|
}
|
||
|
n = n->next;
|
||
|
} else
|
||
|
{
|
||
|
m_table = new Tag(*(n->tag));
|
||
|
newNum++;
|
||
|
}
|
||
|
}
|
||
|
else if (tagName == "thead")
|
||
|
{
|
||
|
headerCheckBox->setChecked(true);
|
||
|
countRows = true;
|
||
|
m_rowSpin = headerRowSpinBox;
|
||
|
m_colSpin = headerColSpinBox;
|
||
|
m_dataTable= headerTableData;
|
||
|
m_tableTags = m_tableHeaderTags;
|
||
|
m_tableRows = m_tableHeaderRows;
|
||
|
if (m_thead) { //there was already a <thead> tag in the area
|
||
|
nRow = m_dataTable->numRows();
|
||
|
} else {
|
||
|
m_thead = new Tag(*(n->tag));
|
||
|
newNum++;
|
||
|
}
|
||
|
}
|
||
|
else if (tagName == "/thead")
|
||
|
{
|
||
|
headerRowSpinBox->setValue(nRow);
|
||
|
headerColSpinBox->setValue(maxCol);
|
||
|
countRows = false;
|
||
|
nCol = nRow = maxCol = 0;
|
||
|
m_rowSpin = 0L;
|
||
|
m_colSpin = 0L;
|
||
|
m_dataTable = 0L;
|
||
|
}
|
||
|
else if (tagName == "tfoot")
|
||
|
{
|
||
|
footerCheckBox->setChecked(true);
|
||
|
m_rowSpin = footerRowSpinBox;
|
||
|
m_colSpin = footerColSpinBox;
|
||
|
m_tableTags = m_tableFooterTags;
|
||
|
m_tableRows = m_tableFooterRows;
|
||
|
m_dataTable = footerTableData;
|
||
|
countRows = true;
|
||
|
if (m_tfoot) { //there was already a <tfoot> tag in the area
|
||
|
nRow = m_dataTable->numRows();
|
||
|
} else {
|
||
|
m_tfoot = new Tag(*(n->tag));
|
||
|
newNum++;
|
||
|
}
|
||
|
}
|
||
|
else if (tagName == "/tfoot")
|
||
|
{
|
||
|
footerRowSpinBox->setValue(nRow);
|
||
|
footerColSpinBox->setValue(maxCol);
|
||
|
countRows = false;
|
||
|
nCol = nRow = maxCol = 0;
|
||
|
m_rowSpin = 0L;
|
||
|
m_colSpin = 0L;
|
||
|
m_dataTable = 0L;
|
||
|
}
|
||
|
else if (tagName == "tbody")
|
||
|
{
|
||
|
m_rowSpin = rowSpinBox;
|
||
|
m_colSpin = colSpinBox;
|
||
|
m_tableTags = m_tableDataTags;
|
||
|
m_tableRows = m_tableDataRows;
|
||
|
m_dataTable = tableData;
|
||
|
countRows = true;
|
||
|
m_tbody = new Tag(*(n->tag));
|
||
|
newNum++;
|
||
|
}
|
||
|
else if (tagName == "/tbody")
|
||
|
{
|
||
|
rowSpinBox->setValue(nRow);
|
||
|
colSpinBox->setValue(maxCol);
|
||
|
countRows = false;
|
||
|
nCol = nRow = maxCol = 0;
|
||
|
m_tableTags = 0L;
|
||
|
m_tableRows = 0L;
|
||
|
m_rowSpin = 0L;
|
||
|
m_colSpin = 0L;
|
||
|
m_dataTable = 0L;
|
||
|
}
|
||
|
else if (tagName == "tr")
|
||
|
{
|
||
|
if (!countRows)
|
||
|
{
|
||
|
missingBody = true;
|
||
|
m_rowSpin = rowSpinBox;
|
||
|
m_colSpin = colSpinBox;
|
||
|
m_tableTags = m_tableDataTags;
|
||
|
m_tableRows = m_tableDataRows;
|
||
|
m_dataTable = tableData;
|
||
|
countRows = true;
|
||
|
m_tbody = new Tag();
|
||
|
newNum++;
|
||
|
m_tbody->parse("<tbody>", m_write);
|
||
|
}
|
||
|
nRow++;
|
||
|
if ((uint)nRow >= mergeMatrix.size()) { // Check if there are enough rows in mergeMatriz
|
||
|
mergeMatrix.resize(2 * mergeMatrix.size());
|
||
|
for (uint i = mergeMatrix.size() / 2; i < mergeMatrix.size(); i++)
|
||
|
mergeMatrix[i].resize(mergeMatrix[0].size());
|
||
|
}
|
||
|
|
||
|
m_rowSpin->setValue(nRow);
|
||
|
nCol = 0;
|
||
|
tableNode.node = new Node(0L);
|
||
|
tableNode.node->tag = new Tag(*(n->tag));
|
||
|
newNum++;
|
||
|
tableNode.merged = false;
|
||
|
m_tableRows->append(tableNode);
|
||
|
}
|
||
|
else if (tagName == "/tr")
|
||
|
{
|
||
|
if (countRows)
|
||
|
{
|
||
|
maxCol = (nCol > maxCol) ? nCol : maxCol;
|
||
|
maxCol = (maxCol == 0) ? 1 : maxCol;
|
||
|
for (int col = nCol; col < maxCol; col++)
|
||
|
{
|
||
|
if (mergeMatrix[nRow - 1][col].node != 0L) {
|
||
|
if (m_colSpin->value() < col)
|
||
|
m_colSpin->setValue(col);
|
||
|
TableNode tableN = mergeMatrix[nRow - 1][col];
|
||
|
Node *n = tableN.node;
|
||
|
setCellText(m_dataTable, nRow - 1, col, i18n("Merged with (%1, %2).").arg(tableN.mergedRow + 1).arg(tableN.mergedCol + 1));
|
||
|
m_dataTable->item(nRow-1, col)->setEnabled(false);
|
||
|
tableNode.node = new Node(0L);
|
||
|
tableNode.node->tag = new Tag(*(n->tag));
|
||
|
configureCell(nRow-1, col, tableNode.node);
|
||
|
newNum++;
|
||
|
tableNode.merged = true;
|
||
|
tableNode.mergedRow = tableN.mergedRow;
|
||
|
tableNode.mergedCol = tableN.mergedCol;
|
||
|
tableRowTags.append(tableNode);
|
||
|
if ((uint)nCol >= mergeMatrix[0].size()) // Check if there are enough cols
|
||
|
for (uint i=0; i<mergeMatrix.size(); i++)
|
||
|
mergeMatrix[i].resize(2 * mergeMatrix[i].size());
|
||
|
|
||
|
} else
|
||
|
{
|
||
|
tableNode.node = new Node(0L);
|
||
|
newNum++;
|
||
|
tableNode.node->tag = new Tag();
|
||
|
tableNode.node->tag->setDtd(m_dtd);
|
||
|
tableNode.node->tag->parse("<td>", m_write);
|
||
|
tableNode.merged = false;
|
||
|
tableRowTags.append(tableNode);
|
||
|
}
|
||
|
}
|
||
|
if (!tableRowTags.isEmpty())
|
||
|
m_tableTags->append(tableRowTags);
|
||
|
tableRowTags.clear();
|
||
|
}
|
||
|
}
|
||
|
else if (tagName == "th" || tagName == "td")
|
||
|
{
|
||
|
if (countRows)
|
||
|
{
|
||
|
int col = nCol;
|
||
|
while (mergeMatrix[nRow - 1][col].node != 0L) {
|
||
|
if (m_colSpin->value() < col)
|
||
|
m_colSpin->setValue(col);
|
||
|
TableNode tableN = mergeMatrix[nRow - 1][col];
|
||
|
Node *n = tableN.node;
|
||
|
setCellText(m_dataTable, nRow - 1, col, i18n("Merged with (%1, %2).").arg(tableN.mergedRow + 1).arg(tableN.mergedCol + 1));
|
||
|
m_dataTable->item(nRow-1, col)->setEnabled(false);
|
||
|
tableNode.node = new Node(0L);
|
||
|
tableNode.node->tag = new Tag(*(n->tag));
|
||
|
configureCell(nRow-1, col, tableNode.node);
|
||
|
newNum++;
|
||
|
tableNode.merged = true;
|
||
|
tableNode.mergedRow = tableN.mergedRow;
|
||
|
tableNode.mergedCol = tableN.mergedCol;
|
||
|
tableRowTags.append(tableNode);
|
||
|
col++;
|
||
|
nCol++;
|
||
|
if ((uint)nCol >= mergeMatrix[0].size()) // Check if there are enough cols
|
||
|
for (uint i = 0; i < mergeMatrix.size(); i++)
|
||
|
mergeMatrix[i].resize(2 * mergeMatrix[i].size());
|
||
|
|
||
|
}
|
||
|
nCol++;
|
||
|
if (m_rowSpin && m_colSpin && m_dataTable)
|
||
|
{
|
||
|
m_rowSpin->setValue(nRow);
|
||
|
if (m_colSpin->value() < nCol)
|
||
|
m_colSpin->setValue(nCol);
|
||
|
setCellText(m_dataTable, nRow - 1, nCol - 1, tagContent(n));
|
||
|
tableNode.node = new Node(0L);
|
||
|
tableNode.node->tag = new Tag(*(n->tag));
|
||
|
configureCell(nRow-1, col, tableNode.node);
|
||
|
newNum++;
|
||
|
tableNode.merged = false;
|
||
|
tableRowTags.append(tableNode);
|
||
|
}
|
||
|
QString colspanValue = n->tag->attributeValue("colspan", true);
|
||
|
int colValue = 1;
|
||
|
int lastCol = nCol;
|
||
|
if (!colspanValue.isEmpty())
|
||
|
{
|
||
|
bool ok;
|
||
|
colValue = colspanValue.toInt(&ok, 10);
|
||
|
if (ok && colValue > 1)
|
||
|
{
|
||
|
nCol += (colValue - 1);
|
||
|
if (m_colSpin->value() < nCol)
|
||
|
m_colSpin->setValue(nCol);
|
||
|
for (int i = 0; i < colValue - 1; i++)
|
||
|
{
|
||
|
setCellText(m_dataTable, nRow - 1, lastCol + i, i18n("Merged with (%1, %2).").arg(nRow).arg(lastCol));
|
||
|
m_dataTable->item(nRow-1, lastCol + i)->setEnabled(false);
|
||
|
tableNode.node = new Node(0L);
|
||
|
tableNode.node->tag = new Tag(*(n->tag));
|
||
|
configureCell(nRow-1, col, tableNode.node);
|
||
|
newNum++;
|
||
|
tableNode.merged = true;
|
||
|
tableNode.mergedRow = nRow - 1;
|
||
|
tableNode.mergedCol = lastCol - 1;
|
||
|
tableRowTags.append(tableNode);
|
||
|
}
|
||
|
} else
|
||
|
colValue = 1;
|
||
|
}
|
||
|
QString rowspanValue = n->tag->attributeValue("rowspan", true);
|
||
|
if (!rowspanValue.isEmpty())
|
||
|
{
|
||
|
bool ok;
|
||
|
int rowValue = rowspanValue.toInt(&ok, 10);
|
||
|
if (ok && rowValue > 1)
|
||
|
{
|
||
|
lastCol--;
|
||
|
// Check if there are enough columns in mergeMatriz
|
||
|
if ((uint)(lastCol + colValue) >= mergeMatrix[0].size())
|
||
|
for (uint i = 0; i < mergeMatrix.size(); i++)
|
||
|
mergeMatrix[i].resize(2 * mergeMatrix[i].size());
|
||
|
// Check if there are enough rows in mergeMatriz
|
||
|
if ((uint)(nRow + rowValue) >= mergeMatrix.size()) {
|
||
|
mergeMatrix.resize(2 * mergeMatrix.size());
|
||
|
for (uint i = mergeMatrix.size() / 2; i < mergeMatrix.size(); i++)
|
||
|
mergeMatrix[i].resize(mergeMatrix[0].size());
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < rowValue - 1; i++)
|
||
|
for (int j = 0; j < colValue; j++) {
|
||
|
mergeMatrix[nRow + i][lastCol + j].mergedRow = nRow - 1;
|
||
|
mergeMatrix[nRow + i][lastCol + j].mergedCol = lastCol;
|
||
|
mergeMatrix[nRow + i][lastCol + j].node = n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (tagName == "caption")
|
||
|
{
|
||
|
captionText->setText(tagContent(n));
|
||
|
} else if (tagName == "col" || tagName == "colgroup") {
|
||
|
m_colTags.append(n->tag);
|
||
|
}
|
||
|
n = n->nextSibling();
|
||
|
}
|
||
|
/* if (missingBody) { //Hm, why do we need it? I don't remember now. ;-)
|
||
|
rowSpinBox->setValue(nRow);
|
||
|
colSpinBox->setValue(maxCol);
|
||
|
} */
|
||
|
//by default the current page is the data handling page
|
||
|
m_tableTags = m_tableDataTags;
|
||
|
m_tableRows = m_tableDataRows;
|
||
|
m_dataTable = tableData;
|
||
|
m_rowSpin = rowSpinBox;
|
||
|
m_colSpin = colSpinBox;
|
||
|
|
||
|
//create the thead, tbody, tfoot tags if they were not present in the parsed area
|
||
|
if (!m_thead) {
|
||
|
m_thead = new Tag();
|
||
|
newNum++;
|
||
|
m_thead->parse("<thead>", m_write);
|
||
|
}
|
||
|
if (!m_tfoot) {
|
||
|
m_tfoot = new Tag();
|
||
|
newNum++;
|
||
|
m_tfoot->parse("<tfoot>", m_write);
|
||
|
}
|
||
|
m_createNodes = true; //enable cell/row creation
|
||
|
|
||
|
configureTable(tableData);
|
||
|
configureTable(headerTableData);
|
||
|
configureTable(footerTableData);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::setBaseURL( const KURL & url )
|
||
|
{
|
||
|
m_baseURL = url;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotEditTableHeader()
|
||
|
{
|
||
|
TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd, "thead"), m_thead, m_baseURL);
|
||
|
if (dlg.exec()) {
|
||
|
m_thead->modifyAttributes(dlg.getAttributes());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotEditTableFooter()
|
||
|
{
|
||
|
TagDialog dlg(QuantaCommon::tagFromDTD(m_dtd,"tfoot"), m_tfoot, m_baseURL);
|
||
|
if (dlg.exec()) {
|
||
|
m_tfoot->modifyAttributes(dlg.getAttributes());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotTabChanged( QWidget *w)
|
||
|
{
|
||
|
int i = tabWidget->indexOf(w);
|
||
|
switch (i)
|
||
|
{
|
||
|
case 0: {
|
||
|
m_tableTags = m_tableDataTags;
|
||
|
m_tableRows = m_tableDataRows;
|
||
|
m_dataTable = tableData;
|
||
|
m_colSpin = colSpinBox;
|
||
|
m_rowSpin = rowSpinBox;
|
||
|
break;
|
||
|
}
|
||
|
case 1: {
|
||
|
m_tableTags = m_tableHeaderTags;
|
||
|
m_tableRows = m_tableHeaderRows;
|
||
|
m_dataTable = headerTableData;
|
||
|
m_colSpin = headerColSpinBox;
|
||
|
m_rowSpin = headerRowSpinBox;
|
||
|
break;
|
||
|
}
|
||
|
case 2: {
|
||
|
m_tableTags = m_tableFooterTags;
|
||
|
m_tableRows = m_tableFooterRows;
|
||
|
m_dataTable = footerTableData;
|
||
|
m_colSpin = footerColSpinBox;
|
||
|
m_rowSpin = footerRowSpinBox;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
configureTable(m_dataTable);
|
||
|
}
|
||
|
|
||
|
|
||
|
QString TableEditor::readModifiedTable()
|
||
|
{
|
||
|
QString tableString;
|
||
|
tableString = m_table->toString();
|
||
|
if (!captionText->text().isEmpty()) {
|
||
|
tableString += indent(2);
|
||
|
tableString += "<" + QuantaCommon::tagCase("caption") + ">";
|
||
|
tableString += captionText->text();
|
||
|
tableString += "</" + QuantaCommon::tagCase("caption") + ">";
|
||
|
}
|
||
|
for (QValueList<Tag*>::Iterator it = m_colTags.begin(); it != m_colTags.end(); ++it) {
|
||
|
tableString += indent(2);
|
||
|
tableString += (*it)->toString();
|
||
|
}
|
||
|
if (headerCheckBox->isChecked() && headerTableData->numRows() > 0) {
|
||
|
//insert the <thead> tag
|
||
|
tableString += indent(2);
|
||
|
tableString += m_thead->toString();
|
||
|
|
||
|
kdDebug(24000) << "thead" << endl;
|
||
|
m_tableTags = m_tableHeaderTags;
|
||
|
m_tableRows = m_tableHeaderRows;
|
||
|
m_dataTable = headerTableData;
|
||
|
tableString += tableToString();
|
||
|
tableString += indent(2);
|
||
|
tableString += "</" + QuantaCommon::tagCase(m_thead->name) +">";
|
||
|
}
|
||
|
if (footerCheckBox->isChecked() && footerTableData->numRows() > 0) {
|
||
|
//insert the <tfoot> tag
|
||
|
tableString += indent(2);
|
||
|
tableString += m_tfoot->toString();
|
||
|
|
||
|
kdDebug(24000) << "tfoot" << endl;
|
||
|
m_tableTags = m_tableFooterTags;
|
||
|
m_tableRows = m_tableFooterRows;
|
||
|
m_dataTable = footerTableData;
|
||
|
tableString += tableToString();
|
||
|
tableString += indent(2);
|
||
|
tableString += "</" + QuantaCommon::tagCase(m_tfoot->name) +">";
|
||
|
}
|
||
|
//insert the <tbody> tag
|
||
|
if (!m_tbody)
|
||
|
{
|
||
|
m_tbody = new Tag();
|
||
|
newNum++;
|
||
|
m_tbody->parse("<tbody>", m_write);
|
||
|
}
|
||
|
tableString += indent(2);
|
||
|
tableString += m_tbody->toString();
|
||
|
kdDebug(24000) << "tbody" << endl;
|
||
|
m_tableTags = m_tableDataTags;
|
||
|
m_tableRows = m_tableDataRows;
|
||
|
m_dataTable = tableData;
|
||
|
tableString += tableToString();
|
||
|
//close the <tbody> and <table> tags
|
||
|
tableString += indent(2);
|
||
|
tableString += "</" + QuantaCommon::tagCase(m_tbody->name) +">";
|
||
|
tableString += "\n";
|
||
|
tableString += "</" + QuantaCommon::tagCase(m_table->name) + ">";
|
||
|
|
||
|
//kdDebug(24000) << tableString << endl;
|
||
|
return tableString;
|
||
|
}
|
||
|
|
||
|
|
||
|
QString TableEditor::indent( int n )
|
||
|
{
|
||
|
QString str;
|
||
|
str.fill(' ', n);
|
||
|
str.prepend('\n');
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
|
||
|
QString TableEditor::cellValue( int row, int col )
|
||
|
{
|
||
|
if (!m_dataTable)
|
||
|
return QString::null;
|
||
|
QString str;
|
||
|
Node *node = (*m_tableTags)[row][col].node;
|
||
|
if (!node)
|
||
|
return QString::null;
|
||
|
str = node->tag->toString();
|
||
|
str += m_dataTable->text(row, col);
|
||
|
str += "</" + QuantaCommon::tagCase(node->tag->name) + ">";
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
|
||
|
QString TableEditor::tableToString()
|
||
|
{
|
||
|
QString tableStr;
|
||
|
for (int i = 0; i < m_dataTable->numRows(); i++) {
|
||
|
tableStr += indent(4);
|
||
|
Node *node = (*m_tableRows)[i].node;
|
||
|
Tag *tag = 0L;
|
||
|
if (node)
|
||
|
tag = node->tag;
|
||
|
if (tag)
|
||
|
tableStr += tag->toString();
|
||
|
else
|
||
|
tableStr += QuantaCommon::tagCase("<tr>");
|
||
|
for (int j = 0; j < m_dataTable->numCols(); j++) {
|
||
|
if ((*m_tableTags)[i][j].node && !(*m_tableTags)[i][j].merged)
|
||
|
{
|
||
|
tableStr += indent(6);
|
||
|
tableStr += cellValue(i, j);
|
||
|
}
|
||
|
}
|
||
|
tableStr += indent(4);
|
||
|
if (tag)
|
||
|
tableStr += "</" + QuantaCommon::tagCase(tag->name) +">";
|
||
|
else
|
||
|
tableStr += QuantaCommon::tagCase("</tr>");
|
||
|
}
|
||
|
return tableStr;
|
||
|
}
|
||
|
|
||
|
|
||
|
QString TableEditor::tagContent(Node *node)
|
||
|
{
|
||
|
if (!node)
|
||
|
return QString::null;
|
||
|
QString content;
|
||
|
int bl, bc, el, ec;
|
||
|
node->tag->endPos(bl, bc);
|
||
|
bc++;
|
||
|
if (node->next)
|
||
|
{
|
||
|
node->next->tag->beginPos(el, ec);
|
||
|
ec--;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Node *n = node->nextSibling();
|
||
|
if (n) {
|
||
|
n->tag->beginPos(el, ec);
|
||
|
ec--;
|
||
|
} else {
|
||
|
return QString::null;
|
||
|
}
|
||
|
}
|
||
|
content = m_write->text(bl, bc, el, ec);
|
||
|
return content;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotInsertRow()
|
||
|
{
|
||
|
int num = m_dataTable->numRows();
|
||
|
if (m_row >= 0)
|
||
|
num = m_row;
|
||
|
m_dataTable->insertRows(num);
|
||
|
m_dataTable->setRowHeight(num, 50);
|
||
|
if (m_createNodes) {
|
||
|
TableNode tableNode;
|
||
|
tableNode.merged = false;
|
||
|
tableNode.node = new Node(0L);
|
||
|
newNum++;
|
||
|
tableNode.node->tag = new Tag();
|
||
|
tableNode.node->tag->setDtd(m_dtd);
|
||
|
tableNode.node->tag->parse("<tr>", m_write);
|
||
|
QValueList<TableNode>::Iterator rowIt = m_tableRows->at(num);
|
||
|
if (rowIt != m_tableRows->end())
|
||
|
m_tableRows->insert(rowIt, tableNode);
|
||
|
else
|
||
|
m_tableRows->append(tableNode);
|
||
|
QValueList<TableNode> tableRowTags;
|
||
|
for (int i = 0; i < m_dataTable->numCols(); i++) {
|
||
|
tableNode.merged = false;
|
||
|
tableNode.node = new Node(0L);
|
||
|
newNum++;
|
||
|
tableNode.node->tag = new Tag();
|
||
|
tableNode.node->tag->setDtd(m_dtd);
|
||
|
if (m_tableTags == m_tableHeaderTags) {
|
||
|
tableNode.node->tag->parse("<th>", m_write);
|
||
|
} else {
|
||
|
tableNode.node->tag->parse("<td>", m_write);
|
||
|
}
|
||
|
tableRowTags.append(tableNode);
|
||
|
setCellText(m_dataTable, num, i, "");
|
||
|
}
|
||
|
QValueList<QValueList<TableNode> >::Iterator it = m_tableTags->at(num);
|
||
|
if (it != m_tableTags->end())
|
||
|
m_tableTags->insert(it, tableRowTags);
|
||
|
else
|
||
|
m_tableTags->append(tableRowTags);
|
||
|
}
|
||
|
m_rowSpin->setValue(m_dataTable->numRows());
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotInsertCol()
|
||
|
{
|
||
|
int num = m_dataTable->numCols();
|
||
|
if (m_col >= 0)
|
||
|
num = m_col;
|
||
|
m_dataTable->insertColumns(num);
|
||
|
m_dataTable->setColumnWidth(num, 150);
|
||
|
if (m_createNodes) {
|
||
|
TableNode tableNode;
|
||
|
int i = 0;
|
||
|
for (QValueList<QValueList<TableNode> >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) {
|
||
|
tableNode.merged = false;
|
||
|
tableNode.node = new Node(0L);
|
||
|
newNum++;
|
||
|
tableNode.node->tag = new Tag();
|
||
|
tableNode.node->tag->setDtd(m_dtd);
|
||
|
if (m_tableTags == m_tableHeaderTags) {
|
||
|
tableNode.node->tag->parse("<th>", m_write);
|
||
|
} else {
|
||
|
tableNode.node->tag->parse("<td>", m_write);
|
||
|
}
|
||
|
(*it).append(tableNode);
|
||
|
setCellText(m_dataTable, i, num, "");
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
m_colSpin->setValue(m_dataTable->numCols());
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotAddRemoveRow( int num )
|
||
|
{
|
||
|
m_row = -1;
|
||
|
int numRows = m_dataTable->numRows();
|
||
|
if (num > numRows) {
|
||
|
for (int i = numRows; i < num; i++) {
|
||
|
slotInsertRow();
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
for (int i = num; i < numRows; i++) {
|
||
|
slotRemoveRow();
|
||
|
}
|
||
|
}
|
||
|
//TODO: change the main tag's rowspan if necessary
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotAddRemoveCol( int num )
|
||
|
{
|
||
|
m_col = -1;
|
||
|
int numCols = m_dataTable->numCols();
|
||
|
if (num > numCols) {
|
||
|
for (int i = numCols; i < num; i++) {
|
||
|
slotInsertCol();
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
for (int i = num; i < numCols; i++) {
|
||
|
slotRemoveCol();
|
||
|
}
|
||
|
}
|
||
|
//TODO: change the main tag's colspan if necessary}
|
||
|
}
|
||
|
|
||
|
void TableEditor::slotRemoveRow()
|
||
|
{
|
||
|
if (m_row == -1)
|
||
|
m_row = m_dataTable->numRows() - 1;
|
||
|
int i = 0;
|
||
|
int j = 0;
|
||
|
for (QValueList<QValueList<TableNode> >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) {
|
||
|
j = 0;
|
||
|
for (QValueList<TableNode>::Iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) {
|
||
|
if ((*it2).merged && (*it2).mergedRow == m_row) {
|
||
|
(*it2).merged = false;
|
||
|
setCellText(m_dataTable, i, j, tagContent((*it2).node));
|
||
|
m_dataTable->item(i, j)->setEnabled(true);
|
||
|
(*it2).node->tag->deleteAttribute("colspan");
|
||
|
(*it2).node->tag->deleteAttribute("rowspan");
|
||
|
}
|
||
|
j++;
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
QValueList<TableNode*> updatedMainNodes;
|
||
|
QValueList<QValueList<TableNode> >::Iterator it2 = m_tableTags->at(m_row);
|
||
|
for (QValueList<TableNode>::Iterator it3 = (*it2).begin(); it3 != (*it2).end(); ++it3) {
|
||
|
if ((*it3).merged)
|
||
|
{
|
||
|
TableNode *mainTableNode = &((*m_tableTags)[(*it3).mergedRow][(*it3).mergedCol]);
|
||
|
if (mainTableNode->node && !updatedMainNodes.contains(mainTableNode))
|
||
|
{
|
||
|
int rowspan = mainTableNode->node->tag->attributeValue("rowspan", true).toInt();
|
||
|
rowspan--;
|
||
|
if (rowspan > 1)
|
||
|
mainTableNode->node->tag->editAttribute("rowspan", QString("%1").arg(rowspan));
|
||
|
else
|
||
|
mainTableNode->node->tag->deleteAttribute("rowspan");
|
||
|
updatedMainNodes.append(mainTableNode);
|
||
|
}
|
||
|
}
|
||
|
Node::deleteNode((*it3).node);
|
||
|
(*it3).node = 0L;
|
||
|
newNum--;
|
||
|
}
|
||
|
m_tableTags->erase(it2);
|
||
|
m_dataTable->removeRow(m_row);
|
||
|
QValueList<TableNode>::Iterator it = m_tableRows->at(m_row);
|
||
|
Node::deleteNode((*it).node);
|
||
|
newNum--;
|
||
|
m_tableRows->erase(it);
|
||
|
m_rowSpin->setValue(m_dataTable->numRows());
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotRemoveCol()
|
||
|
{
|
||
|
int i = 0;
|
||
|
int j = 0;
|
||
|
for (QValueList<QValueList<TableNode> >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) {
|
||
|
j = 0;
|
||
|
for (QValueList<TableNode>::Iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) {
|
||
|
if ((*it2).merged && (*it2).mergedCol == m_col) {
|
||
|
(*it2).merged = false;
|
||
|
setCellText(m_dataTable, i, j, tagContent((*it2).node));
|
||
|
m_dataTable->item(i, j)->setEnabled(true);
|
||
|
(*it2).node->tag->deleteAttribute("colspan");
|
||
|
(*it2).node->tag->deleteAttribute("rowspan");
|
||
|
}
|
||
|
j++;
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
if (m_col == -1)
|
||
|
m_col = m_dataTable->numCols() - 1;
|
||
|
QValueList<TableNode*> updatedMainNodes;
|
||
|
for (QValueList<QValueList<TableNode> >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) {
|
||
|
QValueList<TableNode>::Iterator it2 = (*it).at(m_col);
|
||
|
if ((*it2).merged)
|
||
|
{
|
||
|
TableNode *mainTableNode = &((*m_tableTags)[(*it2).mergedRow][(*it2).mergedCol]);
|
||
|
if (mainTableNode->node && !updatedMainNodes.contains(mainTableNode))
|
||
|
{
|
||
|
int colspan = mainTableNode->node->tag->attributeValue("colspan", true).toInt();
|
||
|
colspan--;
|
||
|
if (colspan > 1)
|
||
|
mainTableNode->node->tag->editAttribute("colspan", QString("%1").arg(colspan));
|
||
|
else
|
||
|
mainTableNode->node->tag->deleteAttribute("colspan");
|
||
|
updatedMainNodes.append(mainTableNode);
|
||
|
}
|
||
|
}
|
||
|
Node::deleteNode((*it2).node);
|
||
|
newNum--;
|
||
|
(*it).erase(it2);
|
||
|
}
|
||
|
m_dataTable->removeColumn(m_col);
|
||
|
m_colSpin->setValue(m_dataTable->numCols());
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::createNewTable(Document *write, const DTDStruct *dtd)
|
||
|
{
|
||
|
m_write = write;
|
||
|
m_dtd = dtd;
|
||
|
m_table = new Tag();
|
||
|
m_table->setDtd(m_dtd);
|
||
|
newNum++;
|
||
|
m_table->parse("<table>", m_write);
|
||
|
m_thead = new Tag();
|
||
|
m_thead->setDtd(m_dtd);
|
||
|
newNum++;
|
||
|
m_thead->parse("<thead>", m_write);
|
||
|
m_tfoot = new Tag();
|
||
|
m_tfoot->setDtd(m_dtd);
|
||
|
newNum++;
|
||
|
m_tfoot->parse("<tfoot>", m_write);
|
||
|
m_tbody = new Tag();
|
||
|
m_tbody->setDtd(m_dtd);
|
||
|
newNum++;
|
||
|
m_tbody->parse("<tbody>", m_write);
|
||
|
//by default the current page is the data handling page
|
||
|
m_tableTags = m_tableDataTags;
|
||
|
m_tableRows = m_tableDataRows;
|
||
|
m_dataTable = tableData;
|
||
|
m_bLine = m_bCol = m_eLine = m_eCol = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::deleteList( QValueList<TableNode> *table )
|
||
|
{
|
||
|
for (QValueList<TableNode>::Iterator it = table->begin(); it != table->end(); ++it) {
|
||
|
Node::deleteNode((*it).node);
|
||
|
newNum--;
|
||
|
}
|
||
|
delete table;
|
||
|
newNum--;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::deleteMatrix( QValueList<QValueList<TableNode> > *matrix )
|
||
|
{
|
||
|
for (QValueList<QValueList<TableNode> >::Iterator it = matrix->begin(); it != matrix->end(); ++it) {
|
||
|
for (QValueList<TableNode>::Iterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) {
|
||
|
Node::deleteNode((*it2).node);
|
||
|
newNum--;
|
||
|
}
|
||
|
}
|
||
|
delete matrix;
|
||
|
newNum--;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotMergeCells()
|
||
|
{
|
||
|
slotUnmergeCells(); //first unmerge all cells from the selection
|
||
|
|
||
|
QTableSelection selection = m_dataTable->selection(m_dataTable->currentSelection());
|
||
|
int tRow, bRow, lCol, rCol;
|
||
|
tRow = selection.topRow();
|
||
|
bRow = selection.bottomRow();
|
||
|
lCol = selection.leftCol();
|
||
|
rCol = selection.rightCol();
|
||
|
TableNode *mainTableNode = &((*m_tableTags)[tRow][lCol]);
|
||
|
if (rCol - lCol > 0)
|
||
|
mainTableNode->node->tag->editAttribute("colspan", QString("%1").arg(rCol - lCol + 1));
|
||
|
if (bRow - tRow > 0)
|
||
|
mainTableNode->node->tag->editAttribute("rowspan", QString("%1").arg(bRow - tRow + 1));
|
||
|
for (int i = 0; i < bRow - tRow + 1; i++)
|
||
|
for (int j = 0; j < rCol - lCol + 1; j++) {
|
||
|
if (i != 0 || j != 0) {
|
||
|
setCellText(m_dataTable, tRow + i, lCol + j, i18n("Merged with (%1, %2).").arg(tRow + 1).arg(lCol + 1));
|
||
|
m_dataTable->item(tRow + i, lCol + j)->setEnabled(false);
|
||
|
TableNode *tableNode = &((*m_tableTags)[tRow + i][lCol + j]);
|
||
|
Node::deleteNode(tableNode->node);
|
||
|
tableNode->node = new Node(0L);
|
||
|
newNum++;
|
||
|
tableNode->node->tag = new Tag(*(mainTableNode->node->tag));
|
||
|
tableNode->merged = true;
|
||
|
tableNode->mergedRow = tRow;
|
||
|
tableNode->mergedCol = lCol;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotUnmergeCells()
|
||
|
{
|
||
|
int tRow, bRow, lCol, rCol;
|
||
|
int selectionNum = m_dataTable->currentSelection();
|
||
|
if (selectionNum != -1) {
|
||
|
QTableSelection selection = m_dataTable->selection(selectionNum);
|
||
|
tRow = selection.topRow();
|
||
|
bRow = selection.bottomRow();
|
||
|
lCol = selection.leftCol();
|
||
|
rCol = selection.rightCol();
|
||
|
} else {
|
||
|
tRow = m_row;
|
||
|
bRow = m_row;
|
||
|
lCol = m_col;
|
||
|
rCol = m_col;
|
||
|
}
|
||
|
for (int row = tRow; row <= bRow; ++row)
|
||
|
for (int col = lCol; col <= rCol; ++col) {
|
||
|
TableNode tableNode = (*m_tableTags)[row][col];
|
||
|
if (!tableNode.merged)
|
||
|
continue;
|
||
|
TableNode newTableNode;
|
||
|
int i = 0;
|
||
|
int j = 0;
|
||
|
for (QValueList<QValueList<TableNode> >::Iterator it = m_tableTags->begin(); it != m_tableTags->end(); ++it) {
|
||
|
j = 0;
|
||
|
QValueList<TableNode>::Iterator it2 = (*it).begin();
|
||
|
while (it2 != (*it).end()) {
|
||
|
if ((*it2).merged &&
|
||
|
tableNode.mergedRow == (*it2).mergedRow &&
|
||
|
tableNode.mergedCol == (*it2).mergedCol) {
|
||
|
|
||
|
Node::deleteNode((*it2).node);
|
||
|
newNum--;
|
||
|
it2 = (*it).erase(it2);
|
||
|
newTableNode.merged = false;
|
||
|
newTableNode.node = new Node(0L);
|
||
|
newNum++;
|
||
|
newTableNode.node->tag = new Tag();
|
||
|
newTableNode.node->tag->setDtd(m_dtd);
|
||
|
if (m_tableTags == m_tableHeaderTags) {
|
||
|
newTableNode.node->tag->parse("<th>", m_write);
|
||
|
} else {
|
||
|
newTableNode.node->tag->parse("<td>", m_write);
|
||
|
}
|
||
|
(*it).insert(it2, newTableNode);
|
||
|
setCellText(m_dataTable, i, j, tagContent(newTableNode.node));
|
||
|
m_dataTable->item(i, j)->setEnabled(true);
|
||
|
} else {
|
||
|
++it2;
|
||
|
}
|
||
|
j++;
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
newTableNode = (*m_tableTags)[tableNode.mergedRow][tableNode.mergedCol];
|
||
|
newTableNode.node->tag->deleteAttribute("colspan");
|
||
|
newTableNode.node->tag->deleteAttribute("rowspan");
|
||
|
//change the main node
|
||
|
TableNode tmpNode = newTableNode;
|
||
|
newTableNode.node = new Node(0L);
|
||
|
newNum++;
|
||
|
newTableNode.node->tag = new Tag(*(tmpNode.node->tag));
|
||
|
QValueList<QValueList<TableNode> >::Iterator iter1 = m_tableTags->at(tableNode.mergedRow);
|
||
|
QValueList<TableNode>::Iterator iter2 = (*iter1).at(tableNode.mergedCol);
|
||
|
iter2 = (*iter1).erase(iter2);
|
||
|
(*iter1).insert(iter2, newTableNode);
|
||
|
Node::deleteNode(tmpNode.node);
|
||
|
newNum--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void TableEditor::slotEditChildTable()
|
||
|
{
|
||
|
bool tempDocCreated = false;
|
||
|
bool error = false;
|
||
|
QValueList<NestedTable>::Iterator errorIt;
|
||
|
Parser *localParser = 0L;
|
||
|
Document *w = 0L;
|
||
|
Node *savedBaseNode = 0L;
|
||
|
NestedTable table;
|
||
|
|
||
|
for (QValueList<NestedTable>::Iterator it = m_nestedTables.begin(); it != m_nestedTables.end(); ++it) {
|
||
|
table = *it;
|
||
|
if (table.row == m_row && table.col == m_col) {
|
||
|
QString cellData = m_dataTable->text(table.row, table.col);
|
||
|
int pos = cellData.find(table.nestedData);
|
||
|
if (pos == -1) {
|
||
|
KMessageBox::error(this, i18n("Cannot edit the child table; you probably modified the cell containing the table manually."), i18n("Cannot Read Table"));
|
||
|
error = true;
|
||
|
errorIt = it;
|
||
|
break;
|
||
|
}
|
||
|
//create a new editor object and save the current state of the table there
|
||
|
KTextEditor::Document *doc =
|
||
|
KTextEditor::createDocument ("libkatepart", 0L, "KTextEditor::Document");
|
||
|
w = new Document(doc, 0L);
|
||
|
QString tableData = readModifiedTable();
|
||
|
w->editIf->insertText(0, 0, tableData);
|
||
|
localParser = new Parser();
|
||
|
savedBaseNode = baseNode; //we must save it as it's deleted in the localParser->parse();
|
||
|
baseNode = 0L;
|
||
|
baseNode = localParser->parse(w);
|
||
|
tempDocCreated = true;
|
||
|
//try to find the child table position
|
||
|
int pos2 = tableData.find(cellData);
|
||
|
if (pos2 != -1)
|
||
|
pos2 = tableData.find(table.nestedData, pos2);
|
||
|
else {
|
||
|
KMessageBox::error(this, i18n("Cannot edit the child table; you probably modified the cell containing the table manually."), i18n("Cannot Read Table"));
|
||
|
error = true;
|
||
|
errorIt = it;
|
||
|
break;
|
||
|
}
|
||
|
tableData = tableData.left(pos2);
|
||
|
table.bLine = tableData.contains('\n');
|
||
|
pos2 = tableData.findRev('\n');
|
||
|
if (pos2 != -1) {
|
||
|
table.bCol = tableData.length() - pos2;
|
||
|
} else {
|
||
|
table.bCol = tableData.length();
|
||
|
}
|
||
|
Node *childTableNode = localParser->nodeAt(table.bLine, table.bCol);
|
||
|
if (!childTableNode->next || !QuantaCommon::closesTag(childTableNode->tag, childTableNode->next->tag)) {
|
||
|
KMessageBox::error(this, i18n("Cannot find the closing tag of the child table; you have probably introduced unclosed tags in the table and have broken its consistency."), i18n("Cannot Read Table"));
|
||
|
error = true;
|
||
|
errorIt = it;
|
||
|
break;
|
||
|
}
|
||
|
childTableNode->next->tag->endPos(table.eLine, table.eCol);
|
||
|
TableEditor editor;
|
||
|
editor.setCaption("Child Table Editor");
|
||
|
editor.setBaseURL(m_baseURL);
|
||
|
editor.setTableArea(table.bLine, table.bCol, table.eLine, table.eCol, localParser);
|
||
|
if (editor.exec()) {
|
||
|
int length = table.nestedData.length();
|
||
|
(*it).nestedData = editor.readModifiedTable();
|
||
|
cellData.replace(pos, length, (*it).nestedData);
|
||
|
setCellText(m_dataTable, table.row, table.col, cellData);
|
||
|
}
|
||
|
//cleanup on success
|
||
|
Node::deleteNode(baseNode);
|
||
|
baseNode = savedBaseNode;
|
||
|
delete localParser;
|
||
|
delete w;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
//cleanup on error
|
||
|
if (error) {
|
||
|
m_nestedTables.erase(errorIt);
|
||
|
m_dataTable->item(table.row, table.col)->setPixmap(QPixmap());
|
||
|
m_dataTable->updateCell(table.row, table.col);
|
||
|
if (tempDocCreated) {
|
||
|
Node::deleteNode(baseNode);
|
||
|
baseNode = savedBaseNode;
|
||
|
delete localParser;
|
||
|
delete w;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void TableEditor::slotHelpInvoked()
|
||
|
{
|
||
|
kapp->invokeHelp("table-editor","quanta");
|
||
|
}
|
||
|
|
||
|
void TableEditor::configureTable( QTable * table )
|
||
|
{
|
||
|
if (!table)
|
||
|
return;
|
||
|
for (int r=0; r<table->numRows(); r++) {
|
||
|
table->adjustRow(r);
|
||
|
for (int c=0; c<table->numCols(); c++)
|
||
|
if (table->item(r, c))
|
||
|
table->item(r, c)->setWordWrap(true);
|
||
|
}
|
||
|
table->setColumnMovingEnabled(true);
|
||
|
table->setRowMovingEnabled(true);
|
||
|
}
|
||
|
|
||
|
void TableEditor::setCellText( QTable * table, int row, int col, const QString & text )
|
||
|
{
|
||
|
table->setItem(row, col, new TableItem(table, QTableItem::OnTyping, text));
|
||
|
}
|
||
|
|
||
|
void TableEditor::configureCell(int row, int col, Node * node)
|
||
|
{
|
||
|
TableItem* item = (TableItem*) m_dataTable->item(row, col);
|
||
|
if (!item)
|
||
|
return;
|
||
|
// Header (TH) or standard cell?
|
||
|
item->setHeader(node->tag->name.lower() == "th");
|
||
|
// Horizontal alignment
|
||
|
Qt::AlignmentFlags flags;
|
||
|
QString align = node->tag->attributeValue("align", true);
|
||
|
if (align == "right")
|
||
|
flags = Qt::AlignRight;
|
||
|
else if (align == "center")
|
||
|
flags = Qt::AlignHCenter;
|
||
|
else if (align == "justify")
|
||
|
flags = Qt::AlignJustify;
|
||
|
else if (align.isEmpty() && item->header())
|
||
|
flags = Qt::AlignHCenter; // TH is centered by default
|
||
|
else
|
||
|
flags = Qt::AlignLeft;
|
||
|
item->setAlignment(flags);
|
||
|
// Vertical alignment
|
||
|
QString valign = node->tag->attributeValue("valign", true);
|
||
|
if (valign == "top")
|
||
|
flags = Qt::AlignTop;
|
||
|
else if (valign == "bottom")
|
||
|
flags = Qt::AlignBottom;
|
||
|
else flags = Qt::AlignVCenter;
|
||
|
item->setVAlignment(flags);
|
||
|
}
|
||
|
|
||
|
#include "tableeditor.moc"
|