|
|
|
/* 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"
|
|
|
|
|