/* This file is part of the KDE project Copyright (C) 2002-2003 Norbert Andres (C) 2002 Philipp Mueller (C) 2002 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include "kspreadsubtotal.h" #include "kspread_sheet.h" #include "kspread_view.h" #include "kspread_doc.h" #include "kspread_util.h" #include "kspread_dlg_subtotal.h" using namespace KSpread; SubtotalDialog::SubtotalDialog( View * parent, TQRect const & selection, const char * name ) : KDialogBase(parent, name, true, i18n( "Subtotals" ), Ok | Cancel | User1, Ok, true, KGuiItem(i18n( "Remove All" )) ), m_pView( parent ), m_pSheet( m_pView->activeSheet() ), m_selection( selection ), m_dialog( new Subtotal( this ) ) { setButtonBoxOrientation( Qt::Vertical ); setMainWidget( m_dialog ); fillColumnBoxes(); fillFunctionBox(); } SubtotalDialog::~SubtotalDialog() { } void SubtotalDialog::slotOk() { int numOfCols = m_selection.width(); TQMemArray columns( numOfCols ); int n = 0; bool empty = true; int left = m_selection.left(); for ( TQListViewItem * item = m_dialog->m_columnList->firstChild(); item; item = item->nextSibling() ) { if ( ((TQCheckListItem * ) item)->isOn() ) { columns[n] = left + n; empty = false; } else columns[n] = -1; ++n; } if ( empty ) { KMessageBox::sorry( this, i18n("You need to select at least one column for adding subtotals.") ); return; } if ( m_dialog->m_replaceSubtotals->isChecked() ) removeSubtotalLines(); int mainCol = left + m_dialog->m_columnBox->currentItem(); int bottom = m_selection.bottom(); int top = m_selection.top(); left = m_selection.left(); TQString oldText = m_pSheet->cellAt( mainCol, top )->strOutText(); TQString newText; TQString result( " " + i18n("Result") ); int lastChangedRow = top; m_pView->doc()->emitBeginOperation( false ); bool ignoreEmptyCells = m_dialog->m_IgnoreBox->isChecked(); bool addRow; if ( !m_dialog->m_summaryOnly->isChecked() ) { int y = top + 1; kdDebug() << "Starting in row " << y << endl; while ( y <= bottom ) { addRow = true; newText = m_pSheet->cellAt( mainCol, y )->strOutText(); if ( ignoreEmptyCells && (newText.length() == 0) ) { ++y; kdDebug() << "Still the same -> " << y << endl; continue; } if (newText != oldText) { int saveY = y; for (int x = 0; x < numOfCols; ++x) { kdDebug() << "Column: " << x << ", " << columns[x] << endl; if (columns[x] != -1) { if (!addSubtotal( mainCol, columns[x], y - 1, lastChangedRow, addRow, oldText + result)) reject(); if ( addRow ) { ++saveY; ++bottom; } addRow = false; } } y = saveY; lastChangedRow = y; } oldText = newText; ++y; } addRow = true; for ( int x = 0; x < numOfCols; ++x ) { if ( columns[x] != -1 ) { if ( !addSubtotal( mainCol, columns[x], y - 1, lastChangedRow, addRow, oldText + result ) ) reject(); addRow = false; } } ++y; } if ( m_dialog->m_summaryBelow->isChecked() ) { addRow = true; int bottom = m_selection.bottom(); for (int x = 0; x < numOfCols; ++x) { if (columns[x] != -1) { addSubtotal( mainCol, columns[x], bottom, top, addRow, i18n("Grand Total") ); addRow = false; } } } m_pView->slotUpdateView( m_pView->activeSheet() ); accept(); } void SubtotalDialog::slotCancel() { reject(); } void SubtotalDialog::slotUser1() { m_pView->doc()->emitBeginOperation( false ); removeSubtotalLines(); m_pView->slotUpdateView( m_pView->activeSheet() ); accept(); } void SubtotalDialog::removeSubtotalLines() { kdDebug() << "Removing subtotal lines" << endl; int r = m_selection.right(); int l = m_selection.left(); int t = m_selection.top(); Cell * cell; TQString text; for ( int y = m_selection.bottom(); y >= t; --y ) { kdDebug() << "Checking row: " << y << endl; bool containsSubtotal = false; for (int x = l; x <= r; ++x ) { cell = m_pSheet->cellAt( x, y ); if ( cell->isDefault() || !cell->isFormula() ) continue; text = cell->text(); if ( text.find( "SUBTOTAL" ) != -1 ) { containsSubtotal = true; break; } } if ( containsSubtotal ) { kdDebug() << "Line " << y << " contains a subtotal " << endl; TQRect rect( l, y, m_selection.width(), 1 ); m_pSheet->unshiftColumn( rect ); m_selection.setHeight( m_selection.height() - 1 ); } } kdDebug() << "Done removing subtotals" << endl; } void SubtotalDialog::fillColumnBoxes() { int r = m_selection.right(); int row = m_selection.top(); Cell * cell; TQCheckListItem * item; TQString text; TQString col( i18n( "Column '%1' ") ); for ( int i = m_selection.left(); i <= r; ++i ) { cell = m_pSheet->cellAt( i, row ); text = cell->strOutText(); if ( text.length() > 0 ) { text = col.arg( Cell::columnName( i ) ); } m_dialog->m_columnBox->insertItem( text ); item = new TQCheckListItem( m_dialog->m_columnList, text, TQCheckListItem::CheckBox ); item->setOn(false); m_dialog->m_columnList->insertItem( item ); } } void SubtotalDialog::fillFunctionBox() { TQStringList lst; lst << i18n( "Average" ); lst << i18n( "Count" ); lst << i18n( "CountA" ); lst << i18n( "Max" ); lst << i18n( "Min" ); lst << i18n( "Product" ); lst << i18n( "StDev" ); lst << i18n( "StDevP" ); lst << i18n( "Sum" ); lst << i18n( "Var" ); lst << i18n( "VarP" ); m_dialog->m_functionBox->insertStringList(lst); } bool SubtotalDialog::addSubtotal( int mainCol, int column, int row, int topRow, bool addRow, TQString const & text ) { kdDebug() << "Adding subtotal: " << mainCol << ", " << column << ", Rows: " << row << ", " << topRow << ": addRow: " << addRow << ", Text: " << text << endl; if ( addRow ) { TQRect rect(m_selection.left(), row + 1, m_selection.width(), 1); if ( !m_pSheet->shiftColumn( rect ) ) return false; m_selection.setHeight( m_selection.height() + 1 ); Cell * cell = m_pSheet->nonDefaultCell( mainCol, row + 1 ); cell->setCellText( text ); cell->format()->setTextFontBold( true ); cell->format()->setTextFontItalic( true ); cell->format()->setTextFontUnderline( true ); } TQString colName = Cell::columnName( column ); TQString formula("=SUBTOTAL("); formula += TQString::number( m_dialog->m_functionBox->currentItem() + 1 ); formula += "; "; formula += colName; formula += TQString::number( topRow ); // if ( topRow != row ) { formula += ":"; formula += colName; formula += TQString::number( row ); } formula += ")"; Cell * cell = m_pSheet->nonDefaultCell( column, row + 1 ); cell->setCellText( formula ); cell->format()->setTextFontBold( true ); cell->format()->setTextFontItalic( true ); cell->format()->setTextFontUnderline( true ); return true; } #include "kspread_dlg_subtotal.moc"