Thu, 06 Aug 2009 13:21:30 +0200
Remove seemingly declarations unnecessary according to Qt 4.5.2 headers.
1 //
2 // OSSP asgui - Accounting system graphical user interface
3 // Copyright (c) 2002-2009 The OSSP Project (http://www.ossp.org/)
4 // Copyright (c) 2002-2009 Ralf S. Engelschall <rse@engelschall.com>
5 // Copyright (c) 2002-2009 Michael Schloh von Bennewitz <michael@schloh.com>
6 // Copyright (c) 2002-2009 Cable & Wireless Telecommunications Services GmbH
7 //
8 // This file is part of OSSP asgui, an accounting system graphical user
9 // interface which can be found at http://asgui.europalab.com/.
10 //
11 // Permission to use, copy, modify, and distribute this software for
12 // any purpose with or without fee is hereby granted, provided that
13 // the above copyright notice and this permission notice appear in all
14 // copies.
15 //
16 // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
17 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 // IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
20 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 // SUCH DAMAGE.
28 //
29 // as_dataops.cpp: ISO C++ implementation
30 //
32 // System headers
33 #include <map>
34 #include <string>
36 // Qt general headers
37 #include <qregexp.h> // Portable regular expressions
38 #include <qdatetime.h>
39 #include <qmessagebox.h>
40 #include <q3textstream.h>
41 #include <q3popupmenu.h>
42 #include <qfile.h>
43 //Added by qt3to4:
44 #include <QPixmap>
46 // User interface
47 #include "as_const.h" // Application constants
48 #include "as_tableitem.h" // For class RtTableItem
49 #include "as_crc.h" // For quality strings
50 #include "as_uuid.h" // UUID classes
51 #include "as_table.h" // TiTable class
53 // Icon pixel maps
54 #include "as_gfx/statok.xpm" // static const char *s_kpcStatokay_xpm[]
55 #include "as_gfx/staterr.xpm" // static const char *s_kpcStaterror_xpm[]
56 #include "as_gfx/statwrn.xpm" // static const char *s_kpcStatwarn_xpm[]
59 //
60 // Convenience method to load accounts from a file
61 //
62 void Titraqform::loadAccounts(QFile &Fileobj)
63 {
64 if (Fileobj.isOpen()) { // Check state of file
65 Fileobj.flush(); // Begin processing file cleanly
66 Q3TextStream Account(&Fileobj); // Convert data to stream
67 this->loadAccounts(Account); // Pass off to do the real work
68 }
69 else {
70 if (!Fileobj.open(QIODevice::ReadOnly)) { // Try to open file
71 QString Readerrstr;
72 Readerrstr = trUtf8(TITRAQ_READAFILFAIL).arg(Fileobj.name());
73 throw Genexcept(Readerrstr.ascii());
74 }
75 else
76 Fileobj.flush(); // Begin processing file cleanly
77 Q3TextStream Account(&Fileobj); // Convert data to stream
78 this->loadAccounts(Account); // Pass off to do the real work
79 Fileobj.close(); // Finish fileop by closing
80 }
81 }
83 //
84 // Load accounts themselves data from a stream
85 //
86 void Titraqform::loadAccounts(Q3TextStream &Tstream)
87 {
88 using namespace std; // Needed for hash tables with hmap
89 map<string, int> Hashnames; // Hashtable for storing names
90 map<int, string> Hashnums; // Hashtable for storing repetitions
91 map<string, int>::iterator Nameiter; // The hashtable name iterator
92 map<int, string>::iterator Numiter; // The hashtable number iterator
94 QString Line; // Used for linewise editing and whitespace eating
96 // Eat lines until reading the start accounts token
97 while (!Line.startsWith(trUtf8("%!AS-ACCOUNTS")) && !Tstream.atEnd()) {
98 Line = QString(""); // Empty line for later inspection
99 Line = Tstream.readLine(); // Get a new line to examine
100 }
102 // Strip out extra line feeds in stream
103 while (Line.isEmpty() && !Tstream.atEnd()) {
104 Tstream.skipWhiteSpace(); // Strip and get
105 Line = Tstream.readLine(); // the new line
106 if (Line.at(0) == QChar('#')) // Remove comments
107 Line = QString("");
108 }
110 // Set the accounts choices by linewise reading from the input
111 // stream and parsing the corresponding account fields out of it
112 while (!Line.isEmpty()) {
113 QString Temp; // For reading from stream
114 Q3TextStream Asline(&Line, QIODevice::ReadOnly); // Convert a single line
116 Asline.skipWhiteSpace(); // Remove whitespaces
117 Asline >> Temp; // Copy revision indicator
119 if (Temp == QString(QChar('R'))) { // Copy the account field
120 Asline >> Temp; // to temporary for transfer
121 string Convstring = Temp.toStdString(); // Convert to string (can't cast?)
122 Hashnames[Convstring] += Hashnames[Convstring];
123 }
125 Line = QString(""); // Clear line for next round
126 while (Line.isEmpty() && !Tstream.atEnd()) {
127 Tstream.skipWhiteSpace(); // Strip and get
128 Line = Tstream.readLine(); // the new line
129 if (Line.at(0) == QChar('#')) // Remove comments
130 Line = QString("");
131 }
132 }
134 // Hashnames.insert(map<string, int>::value_type((string)QString, int));
135 for (Nameiter = Hashnames.begin(); Nameiter != Hashnames.end(); Nameiter++)
136 Hashnums[Nameiter->second] += Nameiter->first + '\n';
138 // FIXME: Put this in loadData, to load custom and most used task names before
139 // FIXME: default listings are sorted and inserted
140 for (Numiter = Hashnums.begin(); Numiter != Hashnums.end(); Numiter++) {
142 // Count the number of lines of sorted task names
143 int nNumlines = QString::fromStdString(Numiter->second).count('\n');
145 // Iterate through the lines of task names, feeding them into the menu
146 for (int nIter = 0; nIter < nNumlines; nIter++)
147 *m_pTaskentries << QString::fromStdString(Numiter->second).section('\n', nIter, nIter);
148 }
149 }
151 //
152 // Convenience method to load personal data from a file
153 //
154 void Titraqform::loadData(QFile &Fileobj)
155 {
156 if (Fileobj.isOpen()) { // Check state of file
157 Fileobj.flush(); // Begin processing file cleanly
158 Q3TextStream Asentry(&Fileobj); // Convert data to stream
159 this->loadData(Asentry); // Pass off to do the real work
160 }
161 else {
162 if (!Fileobj.open(QIODevice::ReadOnly)) // Try to open file
163 throw Genexcept(trUtf8(TITRAQ_READPFILFAIL));
164 else
165 Fileobj.flush(); // Begin processing file cleanly
166 Q3TextStream Asentry(&Fileobj); // Convert data to stream
167 this->loadData(Asentry); // Pass off to do the real work
168 Fileobj.close(); // Finish fileop by closing
169 }
170 }
172 //
173 // Load personal data from a stream
174 //
175 void Titraqform::loadData(Q3TextStream &Tstream)
176 {
177 bool bValid = true; // Used to warn on globally invalid accounting data
178 int nIter = 0; // Iterator used in loop and also as a count
179 QString Line; // Used for linewise editing and whitespace eating
180 QString Bitbucket; // Used for null device until we find a better way
182 QPixmap Statokay(s_kpcStatokay_xpm);
183 QPixmap Statwarn(s_kpcStatwarn_xpm);
184 QPixmap Staterror(s_kpcStaterror_xpm);
186 // Strip out extra line feeds at stream start
187 while (Line.isEmpty() && !Tstream.atEnd()) {
188 Tstream.skipWhiteSpace(); // Strip and get
189 Line = Tstream.readLine(); // the new line
190 if (Line.at(0) == QChar('#')) // Remove comments
191 Line = QString("");
192 }
194 // Strip out extra line feeds after reading the data symbol
195 Line = QString(""); // Reset our line
196 while (Line.isEmpty() && !Tstream.atEnd()) {
197 Tstream.skipWhiteSpace(); // Strip and get
198 Line = Tstream.readLine(); // the new line
199 if (Line.at(0) == QChar('#')) // Remove comments
200 Line = QString("");
201 }
203 // // Going into data churning, so prepare date and time parsing and conversion
204 // Converdate.setSeparator(trUtf8("."));
205 // Convertime.setSeparator(trUtf8(":"));
207 // Optimize viewing by repainting cells only once after processing
208 m_pMaintable->setUpdatesEnabled(false);
210 // Set the table text by linewise reading from the input stream
211 // and parsing date, time, account, and other columns out of it
212 while (!Line.isEmpty()) {
213 bool bValid = true; // Warns on linewise invalid accounting data
214 QString User, Guid, Crc, Rev; // Valid admin fields
215 QString Date, Start, Finish, Account, Amount, Remark; // Valid user fields
216 Q3TextStream Asline(&Line, QIODevice::ReadOnly); // Convert a single line now
218 if (nIter % g_knBlocks == 0) // Add blocks of rows to optimize loading
219 m_pMaintable->setNumRows(m_pMaintable->numRows() + g_knBlocks);
221 Asline.skipWhiteSpace(); // Remove whitespaces
222 Asline >> User; // Copy the user field
223 if (!User.isEmpty())
224 m_pMaintable->setText(nIter, TITRAQ_IDXUSER, User);
225 else
226 bValid = false;
228 Asline.skipWhiteSpace(); // Remove whitespaces
229 Asline >> Guid; // Copy the GUID field
230 // Postpone actual text delivery, to autoinsert GUIDs!
232 Asline.skipWhiteSpace(); // Remove whitespaces
233 Asline >> Crc; // Copy the CRC field
234 // Postpone actual text delivery, to autoinsert CRCs!
236 Asline.skipWhiteSpace(); // Remove whitespaces
237 Asline >> Rev; // Copy the rev field
238 if (!Rev.isEmpty())
239 m_pMaintable->setText(nIter, TITRAQ_IDXREV, Rev);
240 else
241 bValid = false;
243 Asline.skipWhiteSpace(); // Remove whitespaces
244 Asline >> Date; // Copy the date field
245 if (!Date.isEmpty())
246 m_pMaintable->setText(nIter, TITRAQ_IDXDATE, Date);
247 else
248 bValid = false;
250 Asline.skipWhiteSpace(); // Remove whitespaces
251 Asline >> Start; // Copy the start field
252 if (!Start.isEmpty())
253 m_pMaintable->setText(nIter, TITRAQ_IDXSTART, Start);
254 else
255 bValid = false;
257 Asline.skipWhiteSpace(); // Remove whitespaces
258 Asline >> Finish; // Copy the finish field
259 if (!Finish.isEmpty())
260 m_pMaintable->setText(nIter, TITRAQ_IDXFINISH, Finish);
261 else
262 bValid = false;
264 Asline.skipWhiteSpace(); // Remove whitespaces
265 Asline >> Amount; // Copy the amount field
266 if (!Amount.isEmpty())
267 m_pMaintable->setText(nIter, TITRAQ_IDXAMOUNT, Amount);
268 else
269 bValid = false;
271 Asline.skipWhiteSpace(); // Remove whitespaces
272 Asline >> Account; // Copy the account field
273 if (!Account.isEmpty()) {
274 Q3TableItem *pOld = m_pMaintable->item(nIter, TITRAQ_IDXTASK);
275 delete(pOld); // Get rid of the old before going with the new
276 RtTableItem *pSwapitem = new RtTableItem(m_pMaintable, Q3TableItem::WhenCurrent, Account);
277 pSwapitem->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
278 m_pMaintable->setItem(nIter, TITRAQ_IDXTASK, pSwapitem);
279 }
280 else
281 bValid = false;
283 Asline.skipWhiteSpace(); // Remove whitespaces
284 Remark = Asline.read(); // Copy the remark field
286 QRegExp Quoted("\"(.*[^\\\\])\""); // Get rid of
287 Quoted.search(Remark); // surrounding double
288 Remark = Quoted.cap(Quoted.numCaptures()); // quotes, and
289 Remark.replace(QRegExp("\\\\(.)"), QString("\\1")); // escape backslashes
291 if (!Remark.isEmpty())
292 m_pMaintable->setText(nIter, TITRAQ_IDXREMARK, Remark);
294 if (bValid) { // Show a bitmap to signal valid or error state
295 m_pMaintable->setText(nIter, TITRAQ_IDXSTATUS, QString(QChar('O')));
296 m_pMaintable->setPixmap(nIter, TITRAQ_IDXSTATUS, Statokay);
297 }
298 else {
299 m_pMaintable->setText(nIter, TITRAQ_IDXSTATUS, QString(QChar('E')));
300 m_pMaintable->setPixmap(nIter, TITRAQ_IDXSTATUS, Staterror);
301 }
303 // Set the GUID text here, in case we need to generate a fresh value
304 if (!Guid.isEmpty()) {
305 if (Guid != ".") // This means, generate a fresh GUID value
306 m_pMaintable->setText(nIter, TITRAQ_IDXGUID, Guid);
307 else {
308 AS::Uuid Guidi; // For GUID production
309 Guidi.genId();
310 m_pMaintable->setText(nIter, TITRAQ_IDXGUID, QString::fromStdString(Guidi.getString()));
311 }
312 }
313 else // if isEmpty()
314 bValid = false;
316 // Set the CRC text here, in case we need to generate a fresh value
317 if (!Crc.isEmpty()) {
318 if (Crc != ".") // This means, generate a fresh CRC value
319 m_pMaintable->setText(nIter, TITRAQ_IDXCRC, "0x" + Crc);
320 else {
321 // Make our long tuple to run through the CRC32 generator
322 Qualistring Testuple = User + Guid + Rev + Date + Start;
323 Testuple += Finish + Amount + Account + Remark;
324 U32 Valcrc = Testuple.getCrc(); // Finally set the checksum to its new value
325 QString Crcstr = QString::number(Valcrc, 16).rightJustify(8, '0');
326 m_pMaintable->setText(nIter, TITRAQ_IDXCRC, "0x" + Crcstr);
327 }
328 }
329 else // if isEmpty()
330 bValid = false;
332 nIter++; // The big increment
333 Line = QString(""); // Clear line for next round
335 while (Line.isEmpty() && !Tstream.atEnd()) { // Strip and get
336 Tstream.skipWhiteSpace(); // Remove white
337 Line = Tstream.readLine(); // the new line
338 if (Line.at(0) == QChar('#')) // Remove comments
339 Line = QString("");
340 }
341 }
343 // // Start sorting order and direction correctly according to user preferences
344 // int nSortcol = (int)m_pPrefs->getNumber(TITRAQ_PREFSORTCOL, TITRAQ_DEFSORTCOL);
345 // bool bSortdir = m_pPrefs->getBool(TITRAQ_PREFSORTDIR, TITRAQ_DEFSORTDIR);
346 // m_pMaintable->setSortdir(!bSortdir); // Hack! Fake sortdir so we start right
347 // m_pMaintable->sortColumn(nSortcol, bSortdir);
349 // Write nonsaving line numbers for all rows
350 for (int nIter = m_pMaintable->numRows() - 1; nIter >= 0; nIter--)
351 m_pMaintable->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter).rightJustify(4, QChar('0')));
353 m_pMaintable->setUpdatesEnabled(true); // Update and repaint
354 m_pMaintable->setNumRows(nIter); // No excess rows
355 m_pMaintable->setCurrentCell(nIter - 1, 0); // Move focus to last row
356 m_pMaintable->ensureCellVisible(nIter - 1, 0); // Scroll please
358 if (!bValid)
359 throw Genexcept("Warning: invalid accounting data.");
360 }
362 //
363 // Convenience method to save accounting data to a file
364 //
365 void Titraqform::saveData(QFile &Fileobj)
366 {
367 if (Fileobj.isOpen()) { // Check state of file
368 Fileobj.flush(); // Begin processing file cleanly
369 Q3TextStream Asentry(&Fileobj); // Convert data to stream
370 this->saveData(Asentry); // Pass off to do the real work
371 }
372 else {
373 if (!Fileobj.open(QIODevice::WriteOnly)) // Try to open file
374 throw Genexcept(trUtf8(TITRAQ_READPFILFAIL));
375 Q3TextStream Asentry(&Fileobj); // Convert data to stream
376 this->saveData(Asentry); // Pass off to do the real work
377 Fileobj.close(); // Finish fileop by closing
378 }
379 }
381 //
382 // Save accounting data to a stream
383 //
384 void Titraqform::saveData(Q3TextStream &Tstream)
385 {
386 const int nRows = m_pMaintable->numRows(); // Max rows used in loop
387 QString Tempfield; // Current field string
388 QString Strsearch; // String to strip search
389 QRegExp Stripper("\\s*$"); // Pattern to strip off
391 // Start by prepending the AS data format version symbol
392 Tstream << TITRAQ_DATAPATTERN << TITRAQ_DATAVERSIONMAJ
393 << QChar('.') << TITRAQ_DATAVERSIONMIN << endl;
395 // Linewise save from the main table date, time, account, and others
396 for (int nIter = 0; nIter < nRows; nIter++) {
397 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXUSER); // Load user field text
398 if (!Tempfield.isNull())
399 Tstream << Tempfield; // Save user field text
401 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXGUID); // Load GUID field text
402 if (!Tempfield.isNull())
403 Tstream << trUtf8(" ") << Tempfield; // Save GUID field text
405 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXCRC); // Load CRC field text
406 Tempfield.remove("0x");
407 if (!Tempfield.isNull())
408 Tstream << trUtf8(" ") << Tempfield; // Save CRC field text
410 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXREV); // Load rev field text
411 if (!Tempfield.isNull())
412 Tstream << trUtf8(" ") << Tempfield; // Save rev field text
414 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXDATE); // Load date field text
415 if (!Tempfield.isNull())
416 Tstream << trUtf8(" ") << Tempfield; // Save date field text
418 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXSTART); // Load start field text
419 if (!Tempfield.isNull())
420 Tstream << trUtf8(" ") << Tempfield; // Save start field text
422 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXFINISH); // Load end field text
423 if (!Tempfield.isNull())
424 Tstream << trUtf8(" ") << Tempfield; // Save end field text
426 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXAMOUNT); // Load amount field text
427 if (!Tempfield.isNull())
428 Tstream << trUtf8(" ") << Tempfield; // Save amount
430 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXTASK); // Load acct field text
431 if (!Tempfield.isNull())
432 Tstream << trUtf8(" ") << Tempfield; // Save acct field text
434 Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXREMARK); // Load remark field text
435 Tstream << trUtf8(" \""); // Save beginning double quote
436 if (!Tempfield.isNull()) {
437 Strsearch = QRegExp::escape(Tempfield); // Incoming string escaped
438 Stripper.search(Strsearch);
439 Tempfield.truncate(Stripper.pos()); // Cut off whitespace
440 Tempfield.replace(QChar('\\'), QString("\\\\")); // Escape back slashes
441 Tempfield.replace(QChar('\"'), QString("\\\"")); // Escape double quotes
442 Tstream << Tempfield; // Save remark field text
443 }
444 Tstream << trUtf8("\""); // Save ending double quote
446 Tstream << endl; // Append a newline
447 }
448 }
450 //
451 // Convenience method to validate AS data in a file
452 //
453 const bool Titraqform::validateData(QFile &Filin) const
454 {
455 QString Firstline; // Will contain the first line of text
456 char szReadline[QString(TITRAQ_DATAPATTERN).length() + 4L]; // File line
457 bool bRet = false; // Set the initial return value
459 if (Filin.isOpen()) { // Check open state of file
460 Filin.flush(); // Not sure if this is needed
461 Filin.reset(); // Set the file index position to 0
462 Filin.readLine(szReadline, QString(TITRAQ_DATAPATTERN).length() + 2L);
463 }
464 else {
465 if (!Filin.open(QIODevice::ReadOnly)) // Try to open file
466 throw Genexcept(trUtf8(TITRAQ_READPFILFAIL));
467 else { // File is now open
468 Filin.readLine(szReadline, QString(TITRAQ_DATAPATTERN).length() + 2L);
469 Filin.close(); // Remember to close
470 }
471 }
473 try { // Pass off to worker method
474 Firstline = QString::fromAscii(szReadline);
475 bRet = this->validateData(Firstline);
476 }
477 catch (Genexcept &) {
478 throw; // Rethrow onwards
479 }
480 return bRet;
481 }
483 //
484 // Validate the AS data pattern in a line
485 //
486 const bool Titraqform::validateData(QString &Linin) const
487 {
488 bool bRet = false; // Initial return value
490 // Ensure that the right data version pattern precedes the data
491 QString Datapattern = QString(TITRAQ_DATAPATTERN);
492 if (!Linin.startsWith(Datapattern)) { // Incompatible data format
493 QMessageBox Problema(QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short,
494 TITRAQ_NOPATTERNFOUND + QString(TITRAQ_DATAPATTERN) + TITRAQ_WASNOTFOUNDIN,
495 QMessageBox::Critical, QMessageBox::Ok | QMessageBox::Escape,
496 Qt::NoButton, Qt::NoButton);
497 Problema.exec(); // Give the user the bad news
498 throw Genexcept(TITRAQ_INVALIDDATA);
499 }
500 else if (Linin.section(Datapattern, 1).section('.', 0, 0).toInt() != TITRAQ_DATAVERSIONMAJ) {
501 QMessageBox Problema(QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short,
502 TITRAQ_BADVERSIONMAJ, QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Escape,
503 Qt::NoButton, Qt::NoButton);
504 Problema.exec(); // Give the user the bad news
505 throw Genexcept(TITRAQ_INCOMPATDATA);
506 }
507 else if (Linin.section(Datapattern, 1).section('.', 1, 1).toInt() > TITRAQ_DATAVERSIONMIN) {
508 QMessageBox Problema(QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short,
509 TITRAQ_BADVERSIONMIN, QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Escape,
510 Qt::NoButton, Qt::NoButton);
511 Problema.exec(); // Give the user the bad news
512 throw Genexcept(TITRAQ_INCOMPATDATA);
513 }
514 else
515 bRet = true;
517 return bRet; // Not reached in case of failure
518 }
520 //
521 // Get a whole row of data
522 //
523 const QString Titraqform::getRowdata(void) const
524 {
525 QString Rowdata, Tempstring; // For output string
526 Q3TableSelection Select = m_pMaintable->selection(0); // Highlighted text
527 int nTotal = Select.bottomRow() - Select.topRow() + 1; // Total row select
529 // Calculate rows to delete from selection highlight
530 for (int nIter = 0; nIter < nTotal; ++nIter) {
531 // Build the row data string one field at a time, adding seps inbetween
532 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXLINE);
533 if (!Tempstring.isEmpty())
534 Rowdata += Tempstring;
535 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXUSER);
536 if (!Tempstring.isEmpty())
537 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
538 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXGUID);
539 if (!Tempstring.isEmpty())
540 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
541 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXCRC);
542 if (!Tempstring.isEmpty())
543 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
544 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXREV);
545 if (!Tempstring.isEmpty())
546 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
547 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXDATE);
548 if (!Tempstring.isEmpty())
549 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
550 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXSTART);
551 if (!Tempstring.isEmpty())
552 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
553 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXFINISH);
554 if (!Tempstring.isEmpty())
555 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
556 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXAMOUNT);
557 if (!Tempstring.isEmpty())
558 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
559 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXTASK);
560 if (!Tempstring.isEmpty())
561 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
562 Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXREMARK);
563 if (!Tempstring.isEmpty())
564 Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
565 Rowdata += trUtf8("\n"); // Finish off line
566 }
568 return Rowdata;
569 }
571 //
572 // Set a whole row of data
573 //
574 void Titraqform::setRowdata(QString &Rowdata) const
575 {
576 int nRows = Rowdata.count(QChar('\n')); // Set so many rows
577 int nCurrentrow = m_pMaintable->currentRow(); // Current table row
578 Q3TableItem *pItem = NULL; // Old item to change out
579 QString Line, User, Guid, Crc, Rev; // Admin fields in table
580 QString Date, Start, Finish, Amount, Task, Remark; // Viewable fields in table
581 Q3TextStream Datastream(&Rowdata, QIODevice::ReadOnly); // Convert data to stream
583 for (int nIter = 0; nIter < nRows; ++nIter) {
584 QString Singlerow = Datastream.readLine(); // For linewise operation
585 Q3TextStream Rowstream(&Singlerow, QIODevice::ReadOnly); // Convert row to stream
587 Rowstream >> Line >> User >> Guid >> Crc >> Rev; // Stream data fields
588 Rowstream >> Date >> Start >> Finish >> Amount >> Task; // to corresponding vars
589 Remark = Rowstream.readLine(); // Remark is a whole line
591 // Set the table row data one field at a time, skipping seps inbetween
592 // Importantly, do not copy over the GUID, which must be unique each row
593 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXLINE, Line);
594 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXUSER, User);
595 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXCRC, Crc);
596 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXREV, Rev);
597 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXDATE, Date);
598 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXSTART, Start);
599 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXFINISH, Finish);
600 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXAMOUNT, Amount);
602 // // FIXME: Why doesn't this code change the RtTableItem text in place?
603 // RtTableItem *pTask = NULL; // Derived and special
604 // pItem = m_pMaintable->item(nCurrentrow + nIter, TITRAQ_IDXTASK);
605 // pTask = static_cast<RtTableItem *>(pItem);
606 // pTask->setText(Task);
608 // Change out old item and replace with new task data
609 pItem = m_pMaintable->item(nCurrentrow + nIter, TITRAQ_IDXTASK);
610 delete(pItem); // Get rid of the old before going with the new
611 RtTableItem *pSwapitem = new RtTableItem(m_pMaintable, Q3TableItem::WhenCurrent, Task);
612 pSwapitem->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
613 m_pMaintable->setItem(nCurrentrow + nIter, TITRAQ_IDXTASK, pSwapitem);
615 // Continue with field processing business as usual
616 m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXREMARK, Remark.simplifyWhiteSpace());
617 }
618 }
620 //
621 // Discover which column is the first in view
622 //
623 const int Titraqform::getFirstcol(void) const
624 {
625 int nIter = 0; // Is both iterator in loop and column number returned
627 // Use column selector menu popup as sole key to determining column state
628 while (nIter < TITRAQ_IDXTAIL && !m_pColspopup->isItemChecked(m_pColspopup->idAt(++nIter)))
629 TITRAQ_NOP;
631 return nIter - 1; // Return one less to account for start of item offset
632 }