kspread

kspread_dlg_subtotal.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002-2003 Norbert Andres <nandres@web.de>
3 (C) 2002 Philipp Mueller <philipp.mueller@gmx.de>
4 (C) 2002 Laurent Montel <montel@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include <tqcheckbox.h>
23#include <tqcombobox.h>
24#include <tqlistview.h>
25#include <tqmemarray.h>
26
27#include <kdebug.h>
28#include <tdelocale.h>
29#include <tdemessagebox.h>
30
31#include "kspreadsubtotal.h"
32#include "kspread_sheet.h"
33#include "kspread_view.h"
34#include "kspread_doc.h"
35#include "kspread_util.h"
36
37#include "kspread_dlg_subtotal.h"
38
39using namespace KSpread;
40
41SubtotalDialog::SubtotalDialog( View * parent, TQRect const & selection, const char * name )
42 : KDialogBase(parent, name, true, i18n( "Subtotals" ), Ok | Cancel | User1, Ok, true, KGuiItem(i18n( "Remove All" )) ),
43 m_pView( parent ),
44 m_pSheet( m_pView->activeSheet() ),
45 m_selection( selection ),
46 m_dialog( new Subtotal( this ) )
47{
48 setButtonBoxOrientation( TQt::Vertical );
49 setMainWidget( m_dialog );
50
51 fillColumnBoxes();
52 fillFunctionBox();
53}
54
55SubtotalDialog::~SubtotalDialog()
56{
57}
58
59void SubtotalDialog::slotOk()
60{
61 int numOfCols = m_selection.width();
62 TQMemArray<int> columns( numOfCols );
63
64 int n = 0;
65 bool empty = true;
66 int left = m_selection.left();
67 for ( TQListViewItem * item = m_dialog->m_columnList->firstChild(); item; item = item->nextSibling() )
68 {
69 if ( ((TQCheckListItem * ) item)->isOn() )
70 {
71 columns[n] = left + n;
72 empty = false;
73 }
74 else
75 columns[n] = -1;
76 ++n;
77 }
78
79 if ( empty )
80 {
81 KMessageBox::sorry( this, i18n("You need to select at least one column for adding subtotals.") );
82 return;
83 }
84
85 if ( m_dialog->m_replaceSubtotals->isChecked() )
86 removeSubtotalLines();
87
88 int mainCol = left + m_dialog->m_columnBox->currentItem();
89 int bottom = m_selection.bottom();
90 int top = m_selection.top();
91 left = m_selection.left();
92 TQString oldText = m_pSheet->cellAt( mainCol, top )->strOutText();
93 TQString newText;
94 TQString result( " " + i18n("Result") );
95 int lastChangedRow = top;
96
97 m_pView->doc()->emitBeginOperation( false );
98 bool ignoreEmptyCells = m_dialog->m_IgnoreBox->isChecked();
99 bool addRow;
100 if ( !m_dialog->m_summaryOnly->isChecked() )
101 {
102 int y = top + 1;
103 kdDebug() << "Starting in row " << y << endl;
104 while ( y <= bottom )
105 {
106 addRow = true;
107 newText = m_pSheet->cellAt( mainCol, y )->strOutText();
108
109 if ( ignoreEmptyCells && (newText.length() == 0) )
110 {
111 ++y;
112 kdDebug() << "Still the same -> " << y << endl;
113 continue;
114 }
115
116 if (newText != oldText)
117 {
118 int saveY = y;
119 for (int x = 0; x < numOfCols; ++x)
120 {
121 kdDebug() << "Column: " << x << ", " << columns[x] << endl;
122 if (columns[x] != -1)
123 {
124 if (!addSubtotal( mainCol, columns[x], y - 1, lastChangedRow, addRow, oldText + result))
125 reject();
126
127 if ( addRow )
128 {
129 ++saveY;
130 ++bottom;
131 }
132
133 addRow = false;
134 }
135 }
136 y = saveY;
137 lastChangedRow = y;
138 }
139 oldText = newText;
140 ++y;
141 }
142
143 addRow = true;
144 for ( int x = 0; x < numOfCols; ++x )
145 {
146 if ( columns[x] != -1 )
147 {
148 if ( !addSubtotal( mainCol, columns[x], y - 1, lastChangedRow, addRow, oldText + result ) )
149 reject();
150 addRow = false;
151 }
152 }
153 ++y;
154 }
155
156 if ( m_dialog->m_summaryBelow->isChecked() )
157 {
158 addRow = true;
159 int bottom = m_selection.bottom();
160 for (int x = 0; x < numOfCols; ++x)
161 {
162 if (columns[x] != -1)
163 {
164 addSubtotal( mainCol, columns[x], bottom, top, addRow, i18n("Grand Total") );
165 addRow = false;
166 }
167 }
168 }
169
170 m_pView->slotUpdateView( m_pView->activeSheet() );
171 accept();
172}
173
174void SubtotalDialog::slotCancel()
175{
176 reject();
177}
178
179void SubtotalDialog::slotUser1()
180{
181 m_pView->doc()->emitBeginOperation( false );
182 removeSubtotalLines();
183 m_pView->slotUpdateView( m_pView->activeSheet() );
184 accept();
185}
186
187void SubtotalDialog::removeSubtotalLines()
188{
189 kdDebug() << "Removing subtotal lines" << endl;
190
191 int r = m_selection.right();
192 int l = m_selection.left();
193 int t = m_selection.top();
194
195 Cell * cell;
196 TQString text;
197
198 for ( int y = m_selection.bottom(); y >= t; --y )
199 {
200 kdDebug() << "Checking row: " << y << endl;
201 bool containsSubtotal = false;
202 for (int x = l; x <= r; ++x )
203 {
204 cell = m_pSheet->cellAt( x, y );
205 if ( cell->isDefault() || !cell->isFormula() )
206 continue;
207
208 text = cell->text();
209 if ( text.find( "SUBTOTAL" ) != -1 )
210 {
211 containsSubtotal = true;
212 break;
213 }
214 }
215
216 if ( containsSubtotal )
217 {
218 kdDebug() << "Line " << y << " contains a subtotal " << endl;
219 TQRect rect( l, y, m_selection.width(), 1 );
220
221 m_pSheet->unshiftColumn( rect );
222 m_selection.setHeight( m_selection.height() - 1 );
223 }
224 }
225 kdDebug() << "Done removing subtotals" << endl;
226}
227
228void SubtotalDialog::fillColumnBoxes()
229{
230 int r = m_selection.right();
231 int row = m_selection.top();
232
233 Cell * cell;
234 TQCheckListItem * item;
235
236 TQString text;
237 TQString col( i18n( "Column '%1' ") );
238
239 for ( int i = m_selection.left(); i <= r; ++i )
240 {
241 cell = m_pSheet->cellAt( i, row );
242 text = cell->strOutText();
243
244 if ( text.length() > 0 )
245 {
246 text = col.arg( Cell::columnName( i ) );
247 }
248
249 m_dialog->m_columnBox->insertItem( text );
250
251 item = new TQCheckListItem( m_dialog->m_columnList,
252 text,
253 TQCheckListItem::CheckBox );
254 item->setOn(false);
255 m_dialog->m_columnList->insertItem( item );
256 }
257}
258
259void SubtotalDialog::fillFunctionBox()
260{
261 TQStringList lst;
262 lst << i18n( "Average" );
263 lst << i18n( "Count" );
264 lst << i18n( "CountA" );
265 lst << i18n( "Max" );
266 lst << i18n( "Min" );
267 lst << i18n( "Product" );
268 lst << i18n( "StDev" );
269 lst << i18n( "StDevP" );
270 lst << i18n( "Sum" );
271 lst << i18n( "Var" );
272 lst << i18n( "VarP" );
273 m_dialog->m_functionBox->insertStringList(lst);
274}
275
276bool SubtotalDialog::addSubtotal( int mainCol, int column, int row, int topRow,
277 bool addRow, TQString const & text )
278{
279 kdDebug() << "Adding subtotal: " << mainCol << ", " << column << ", Rows: " << row << ", " << topRow
280 << ": addRow: " << addRow << ", Text: " << text << endl;
281 if ( addRow )
282 {
283 TQRect rect(m_selection.left(), row + 1, m_selection.width(), 1);
284 if ( !m_pSheet->shiftColumn( rect ) )
285 return false;
286
287 m_selection.setHeight( m_selection.height() + 1 );
288
289 Cell * cell = m_pSheet->nonDefaultCell( mainCol, row + 1 );
290 cell->setCellText( text );
291 cell->format()->setTextFontBold( true );
292 cell->format()->setTextFontItalic( true );
293 cell->format()->setTextFontUnderline( true );
294 }
295
296 TQString colName = Cell::columnName( column );
297
298 TQString formula("=SUBTOTAL(");
299 formula += TQString::number( m_dialog->m_functionBox->currentItem() + 1 );
300 formula += "; ";
301 formula += colName;
302 formula += TQString::number( topRow );
303 // if ( topRow != row )
304 {
305 formula += ":";
306 formula += colName;
307 formula += TQString::number( row );
308 }
309 formula += ")";
310
311 Cell * cell = m_pSheet->nonDefaultCell( column, row + 1 );
312 cell->setCellText( formula );
313 cell->format()->setTextFontBold( true );
314 cell->format()->setTextFontItalic( true );
315 cell->format()->setTextFontUnderline( true );
316
317 return true;
318}
319
320#include "kspread_dlg_subtotal.moc"
321
For every cell in the spread sheet there is a Cell object.
TQString text() const
Return the text the user entered.
bool isFormula() const
Returns true if this cell holds a formula.
void setCellText(const TQString &_text, bool asString=false)
The high-level method for setting text, when the user inputs it.
Format * format() const
Returns the format object of this cell.
TQString columnName() const
Returns the column name of the cell.
bool isDefault() const
Returns true if this is a default cell (with row and column equal to zero).
The View class displays a KSpread document.
The KSpread namespace.
Definition commands.h:39