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.
koffice/kspread/dialogs/kspread_dlg_subtotal.cc

322 lines
8.2 KiB

/* This file is part of the KDE project
Copyright (C) 2002-2003 Norbert Andres <nandres@web.de>
(C) 2002 Philipp Mueller <philipp.mueller@gmx.de>
(C) 2002 Laurent Montel <montel@kde.org>
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 <klocale.h>
#include <kmessagebox.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"