diff options
Diffstat (limited to 'kspread/dialogs/kspread_dlg_subtotal.cpp')
-rw-r--r-- | kspread/dialogs/kspread_dlg_subtotal.cpp | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/kspread/dialogs/kspread_dlg_subtotal.cpp b/kspread/dialogs/kspread_dlg_subtotal.cpp new file mode 100644 index 00000000..054cc1f7 --- /dev/null +++ b/kspread/dialogs/kspread_dlg_subtotal.cpp @@ -0,0 +1,321 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2003 Norbert Andres <[email protected]> + (C) 2002 Philipp Mueller <[email protected]> + (C) 2002 Laurent Montel <[email protected]> + + 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 <tqcheckbox.h> +#include <tqcombobox.h> +#include <tqlistview.h> +#include <tqmemarray.h> + +#include <kdebug.h> +#include <tdelocale.h> +#include <tdemessagebox.h> + +#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<int> 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" + |