as_dataop.cpp

Fri, 28 Nov 2008 14:20:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 28 Nov 2008 14:20:00 +0100
changeset 2
e8292658d5b3
child 3
c1941114ca88
permissions
-rw-r--r--

Added tag ASGUI_0.7.7 for changeset d64aaa7d146f

     1 //
     2 //  OSSP asgui - Accounting system graphical user interface
     3 //  Copyright (c) 2002-2004 The OSSP Project (http://www.ossp.org/)
     4 //  Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>
     5 //  Copyright (c) 2002-2004 Michael Schloh von Bennewitz <michael@schloh.com>
     6 //  Copyright (c) 2002-2004 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://www.ossp.org/pkg/tool/asgui/.
    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 <qtextstream.h>
    41 #include <qpopupmenu.h>
    42 #include <qfile.h>
    44 // User interface
    45 #include "as_const.h"           // Application constants
    46 #include "as_tableitem.h"       // For class RtTableItem
    47 #include "as_crc.h"             // For quality strings
    48 #include "as_uuid.h"            // UUID classes
    49 #include "as_table.h"           // TiTable class
    51 // Icon pixel maps
    52 #include "as_gfx/statok.xpm"    // static const char *s_kpcStatokay_xpm[]
    53 #include "as_gfx/staterr.xpm"   // static const char *s_kpcStaterror_xpm[]
    54 #include "as_gfx/statwrn.xpm"   // static const char *s_kpcStatwarn_xpm[]
    57 //
    58 // Convenience method to load accounts from a file
    59 //
    60 void Titraqform::loadAccounts(QFile &Fileobj)
    61 {
    62     if (Fileobj.isOpen()) {             // Check state of file
    63         Fileobj.flush();                // Begin processing file cleanly
    64         QTextStream Account(&Fileobj);  // Convert data to stream
    65         this->loadAccounts(Account);    // Pass off to do the real work
    66     }
    67     else {
    68         if (!Fileobj.open(IO_ReadOnly)) {   // Try to open file
    69             QString Readerrstr;
    70             Readerrstr = trUtf8(TITRAQ_READAFILFAIL).arg(Fileobj.name());
    71             throw Genexcept(Readerrstr.ascii());
    72         }
    73         else
    74             Fileobj.flush();                // Begin processing file cleanly
    75             QTextStream Account(&Fileobj);  // Convert data to stream
    76             this->loadAccounts(Account);    // Pass off to do the real work
    77             Fileobj.close();                // Finish fileop by closing
    78     }
    79 }
    81 //
    82 // Load accounts themselves data from a stream
    83 //
    84 void Titraqform::loadAccounts(QTextStream &Tstream)
    85 {
    86     using namespace std;                // Needed for hash tables with hmap
    87     map<string, int> Hashnames;         // Hashtable for storing names
    88     map<int, string> Hashnums;          // Hashtable for storing repetitions
    89     map<string, int>::iterator Nameiter; // The hashtable name iterator
    90     map<int, string>::iterator Numiter;  // The hashtable number iterator
    92     QString Line;           // Used for linewise editing and whitespace eating
    94     // Eat lines until reading the start accounts token
    95     while (!Line.startsWith(trUtf8("%!AS-ACCOUNTS")) && !Tstream.atEnd()) {
    96         Line = QString("");         // Empty line for later inspection
    97         Line = Tstream.readLine();  // Get a new line to examine
    98     }
   100     // Strip out extra line feeds in stream
   101     while (Line.isEmpty() && !Tstream.atEnd()) {
   102         Tstream.skipWhiteSpace();       // Strip and get
   103         Line = Tstream.readLine();      // the new line
   104         if (Line.at(0) == QChar('#'))   // Remove comments
   105             Line = QString("");
   106     }
   108     // Set the accounts choices by linewise reading from the input
   109     // stream and parsing the corresponding account fields out of it
   110     while (!Line.isEmpty()) {
   111         QString Temp;                           // For reading from stream
   112         QTextStream Asline(&Line, IO_ReadOnly); // Convert a single line
   114         Asline.skipWhiteSpace();            // Remove whitespaces
   115         Asline >> Temp;                     // Copy revision indicator
   117         if (Temp == QString(QChar('R'))) {  // Copy the account field
   118             Asline >> Temp;                 // to temporary for transfer
   119             string Convstring = Temp;       // Convert to string (can't cast?)
   120             Hashnames[Convstring] += Hashnames[Convstring];
   121         }
   123         Line = QString(""); // Clear line for next round
   124         while (Line.isEmpty() && !Tstream.atEnd()) {
   125             Tstream.skipWhiteSpace();       // Strip and get
   126             Line = Tstream.readLine();      // the new line
   127             if (Line.at(0) == QChar('#'))   // Remove comments
   128                 Line = QString("");
   129         }
   130     }
   132 //    Hashnames.insert(map<string, int>::value_type((string)QString, int));
   133     for (Nameiter = Hashnames.begin(); Nameiter != Hashnames.end(); Nameiter++)
   134         Hashnums[Nameiter->second] += Nameiter->first + '\n';
   136 // FIXME: Put this in loadData, to load custom and most used task names before
   137 // FIXME: default listings are sorted and inserted
   138     for (Numiter = Hashnums.begin(); Numiter != Hashnums.end(); Numiter++) {
   140         // Count the number of lines of sorted task names
   141         int nNumlines = QString(Numiter->second).contains('\n');
   143         // Iterate through the lines of task names, feeding them into the menu
   144         for (int nIter = 0; nIter < nNumlines; nIter++)
   145             *m_pTaskentries << QString(Numiter->second).section('\n', nIter, nIter);
   146     }
   147 }
   149 //
   150 // Convenience method to load personal data from a file
   151 //
   152 void Titraqform::loadData(QFile &Fileobj)
   153 {
   154     if (Fileobj.isOpen()) {             // Check state of file
   155         Fileobj.flush();                // Begin processing file cleanly
   156         QTextStream Asentry(&Fileobj);  // Convert data to stream
   157         this->loadData(Asentry);        // Pass off to do the real work
   158     }
   159     else {
   160         if (!Fileobj.open(IO_ReadOnly)) // Try to open file
   161             throw Genexcept(trUtf8(TITRAQ_READPFILFAIL));
   162         else
   163             Fileobj.flush();                // Begin processing file cleanly
   164             QTextStream Asentry(&Fileobj);  // Convert data to stream
   165             this->loadData(Asentry);        // Pass off to do the real work
   166             Fileobj.close();                // Finish fileop by closing
   167     }
   168 }
   170 //
   171 // Load personal data from a stream
   172 //
   173 void Titraqform::loadData(QTextStream &Tstream)
   174 {
   175     bool bValid = true; // Used to warn on globally invalid accounting data
   176     int nIter = 0;      // Iterator used in loop and also as a count
   177     QString Line;       // Used for linewise editing and whitespace eating
   178     QString Bitbucket;  // Used for null device until we find a better way
   180     QPixmap Statokay(s_kpcStatokay_xpm);
   181     QPixmap Statwarn(s_kpcStatwarn_xpm);
   182     QPixmap Staterror(s_kpcStaterror_xpm);
   184     // Strip out extra line feeds at stream start
   185     while (Line.isEmpty() && !Tstream.atEnd()) {
   186         Tstream.skipWhiteSpace();       // Strip and get
   187         Line = Tstream.readLine();      // the new line
   188         if (Line.at(0) == QChar('#'))   // Remove comments
   189             Line = QString("");
   190     }
   192     // Strip out extra line feeds after reading the data symbol
   193     Line = QString("");                 // Reset our line
   194     while (Line.isEmpty() && !Tstream.atEnd()) {
   195         Tstream.skipWhiteSpace();       // Strip and get
   196         Line = Tstream.readLine();      // the new line
   197         if (Line.at(0) == QChar('#'))   // Remove comments
   198             Line = QString("");
   199     }
   201 //    // Going into data churning, so prepare date and time parsing and conversion
   202 //    Converdate.setSeparator(trUtf8("."));
   203 //    Convertime.setSeparator(trUtf8(":"));
   205     // Optimize viewing by repainting cells only once after processing
   206     m_pMaintable->setUpdatesEnabled(false);
   208     // Set the table text by linewise reading from the input stream
   209     // and parsing date, time, account, and other columns out of it
   210     while (!Line.isEmpty()) {
   211         bool bValid = true; // Warns on linewise invalid accounting data
   212         QString User, Guid, Crc, Rev;                           // Valid admin fields
   213         QString Date, Start, Finish, Account, Amount, Remark;   // Valid user fields
   214         QTextStream Asline(&Line, IO_ReadOnly); // Convert a single line now
   216         if (nIter % g_knBlocks == 0) // Add blocks of rows to optimize loading
   217             m_pMaintable->setNumRows(m_pMaintable->numRows() + g_knBlocks);
   219         Asline.skipWhiteSpace();    // Remove whitespaces
   220         Asline >> User;             // Copy the user field
   221         if (!User.isEmpty())
   222             m_pMaintable->setText(nIter, TITRAQ_IDXUSER, User);
   223         else
   224             bValid = false;
   226         Asline.skipWhiteSpace();    // Remove whitespaces
   227         Asline >> Guid;             // Copy the GUID field
   228         // Postpone actual text delivery, to autoinsert GUIDs!
   230         Asline.skipWhiteSpace();    // Remove whitespaces
   231         Asline >> Crc;              // Copy the CRC field
   232         // Postpone actual text delivery, to autoinsert CRCs!
   234         Asline.skipWhiteSpace();    // Remove whitespaces
   235         Asline >> Rev;              // Copy the rev field
   236         if (!Rev.isEmpty())
   237             m_pMaintable->setText(nIter, TITRAQ_IDXREV, Rev);
   238         else
   239             bValid = false;
   241         Asline.skipWhiteSpace();    // Remove whitespaces
   242         Asline >> Date;             // Copy the date field
   243         if (!Date.isEmpty())
   244             m_pMaintable->setText(nIter, TITRAQ_IDXDATE, Date);
   245         else
   246             bValid = false;
   248         Asline.skipWhiteSpace();    // Remove whitespaces
   249         Asline >> Start;            // Copy the start field
   250         if (!Start.isEmpty())
   251             m_pMaintable->setText(nIter, TITRAQ_IDXSTART, Start);
   252         else
   253             bValid = false;
   255         Asline.skipWhiteSpace();    // Remove whitespaces
   256         Asline >> Finish;           // Copy the finish field
   257         if (!Finish.isEmpty())
   258             m_pMaintable->setText(nIter, TITRAQ_IDXFINISH, Finish);
   259         else
   260             bValid = false;
   262         Asline.skipWhiteSpace();    // Remove whitespaces
   263         Asline >> Amount;           // Copy the amount field
   264         if (!Amount.isEmpty())
   265             m_pMaintable->setText(nIter, TITRAQ_IDXAMOUNT, Amount);
   266         else
   267             bValid = false;
   269         Asline.skipWhiteSpace();    // Remove whitespaces
   270         Asline >> Account;          // Copy the account field
   271         if (!Account.isEmpty()) {
   272             QTableItem *pOld = m_pMaintable->item(nIter, TITRAQ_IDXTASK);
   273             delete(pOld);   // Get rid of the old before going with the new
   274             RtTableItem *pSwapitem = new RtTableItem(m_pMaintable, QTableItem::WhenCurrent, Account);
   275             pSwapitem->setAlignment(AlignLeft | AlignVCenter);
   276             m_pMaintable->setItem(nIter, TITRAQ_IDXTASK, pSwapitem);
   277         }
   278         else
   279             bValid = false;
   281         Asline.skipWhiteSpace();    // Remove whitespaces
   282         Remark = Asline.read();     // Copy the remark field
   284         QRegExp Quoted("\"(.*[^\\\\])\"");                  // Get rid of
   285         Quoted.search(Remark);                              // surrounding double
   286         Remark = Quoted.cap(Quoted.numCaptures());          // quotes, and
   287         Remark.replace(QRegExp("\\\\(.)"), QString("\\1")); // escape backslashes
   289         if (!Remark.isEmpty())
   290             m_pMaintable->setText(nIter, TITRAQ_IDXREMARK, Remark);
   292         if (bValid) { // Show a bitmap to signal valid or error state
   293             m_pMaintable->setText(nIter, TITRAQ_IDXSTATUS, QString(QChar('O')));
   294             m_pMaintable->setPixmap(nIter, TITRAQ_IDXSTATUS, Statokay);
   295         }
   296         else {
   297             m_pMaintable->setText(nIter, TITRAQ_IDXSTATUS, QString(QChar('E')));
   298             m_pMaintable->setPixmap(nIter, TITRAQ_IDXSTATUS, Staterror);
   299         }
   301         // Set the GUID text here, in case we need to generate a fresh value
   302         if (!Guid.isEmpty()) {
   303             if (Guid != ".")    // This means, generate a fresh GUID value
   304                 m_pMaintable->setText(nIter, TITRAQ_IDXGUID, Guid);
   305             else {
   306                 AS::Uuid Guidi; // For GUID production
   307                 Guidi.genId();
   308                 m_pMaintable->setText(nIter, TITRAQ_IDXGUID, Guidi.getString());
   309             }
   310         }
   311         else // if isEmpty()
   312             bValid = false;
   314         // Set the CRC text here, in case we need to generate a fresh value
   315         if (!Crc.isEmpty()) {
   316             if (Crc != ".") // This means, generate a fresh CRC value
   317                 m_pMaintable->setText(nIter, TITRAQ_IDXCRC, "0x" + Crc);
   318             else {
   319                 // Make our long tuple to run through the CRC32 generator
   320                 Qualistring Testuple = User + Guid + Rev + Date + Start;
   321                             Testuple += Finish + Amount + Account + Remark;
   322                 U32 Valcrc = Testuple.getCrc(); // Finally set the checksum to its new value
   323                 QString Crcstr = QString::number(Valcrc, 16).rightJustify(8, '0');
   324                 m_pMaintable->setText(nIter, TITRAQ_IDXCRC, "0x" + Crcstr);
   325             }
   326         }
   327         else // if isEmpty()
   328             bValid = false;
   330         nIter++;            // The big increment
   331         Line = QString(""); // Clear line for next round
   333         while (Line.isEmpty() && !Tstream.atEnd()) {    // Strip and get
   334             Tstream.skipWhiteSpace();                   // Remove white
   335             Line = Tstream.readLine();                  // the new line
   336             if (Line.at(0) == QChar('#'))               // Remove comments
   337                 Line = QString("");
   338         }
   339     }
   341 //    // Start sorting order and direction correctly according to user preferences
   342 //    int nSortcol = (int)m_pPrefs->getNumber(TITRAQ_PREFSORTCOL, TITRAQ_DEFSORTCOL);
   343 //    bool bSortdir = m_pPrefs->getBool(TITRAQ_PREFSORTDIR, TITRAQ_DEFSORTDIR);
   344 //    m_pMaintable->setSortdir(!bSortdir); // Hack! Fake sortdir so we start right
   345 //    m_pMaintable->sortColumn(nSortcol, bSortdir);
   347     // Write nonsaving line numbers for all rows
   348     for (int nIter = m_pMaintable->numRows() - 1; nIter >= 0; nIter--)
   349         m_pMaintable->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter).rightJustify(4, QChar('0')));
   351     m_pMaintable->setUpdatesEnabled(true);      // Update and repaint
   352     m_pMaintable->setNumRows(nIter);            // No excess rows
   353     m_pMaintable->setCurrentCell(nIter - 1, 0); // Move focus to last row
   354     m_pMaintable->ensureCellVisible(nIter - 1, 0); // Scroll please
   356     if (!bValid)
   357         throw Genexcept("Warning: invalid accounting data.");
   358 }
   360 //
   361 // Convenience method to save accounting data to a file
   362 //
   363 void Titraqform::saveData(QFile &Fileobj)
   364 {
   365     if (Fileobj.isOpen()) {             // Check state of file
   366         Fileobj.flush();                // Begin processing file cleanly
   367         QTextStream Asentry(&Fileobj);  // Convert data to stream
   368         this->saveData(Asentry);        // Pass off to do the real work
   369     }
   370     else {
   371         if (!Fileobj.open(IO_WriteOnly)) // Try to open file
   372             throw Genexcept(trUtf8(TITRAQ_READPFILFAIL));
   373         QTextStream Asentry(&Fileobj);  // Convert data to stream
   374         this->saveData(Asentry);        // Pass off to do the real work
   375         Fileobj.close();                // Finish fileop by closing
   376     }
   377 }
   379 //
   380 // Save accounting data to a stream
   381 //
   382 void Titraqform::saveData(QTextStream &Tstream)
   383 {
   384     const int nRows = m_pMaintable->numRows();      // Max rows used in loop
   385     QString Tempfield;                              // Current field string
   386     QString Strsearch;                              // String to strip search
   387     QRegExp Stripper("\\s*$");                      // Pattern to strip off
   389     // Start by prepending the AS data format version symbol
   390     Tstream << TITRAQ_DATAPATTERN << TITRAQ_DATAVERSIONMAJ
   391             << QChar('.') << TITRAQ_DATAVERSIONMIN << endl;
   393     // Linewise save from the main table date, time, account, and others
   394     for (int nIter = 0; nIter < nRows; nIter++) {
   395         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXUSER);      // Load user field text
   396         if (Tempfield != NULL)
   397             Tstream << Tempfield;                                   // Save user field text
   399         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXGUID);      // Load GUID field text
   400         if (Tempfield != NULL)
   401             Tstream << trUtf8(" ") << Tempfield;                    // Save GUID field text
   403         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXCRC);       // Load CRC field text
   404         Tempfield.remove("0x");
   405         if (Tempfield != NULL)
   406             Tstream << trUtf8(" ") << Tempfield;                    // Save CRC field text
   408         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXREV);       // Load rev field text
   409         if (Tempfield != NULL)
   410             Tstream << trUtf8(" ") << Tempfield;                    // Save rev field text
   412         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXDATE);      // Load date field text
   413         if (Tempfield != NULL)
   414             Tstream << trUtf8(" ") << Tempfield;                    // Save date field text
   416         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXSTART);     // Load start field text
   417         if (Tempfield != NULL)
   418             Tstream << trUtf8(" ") << Tempfield;                    // Save start field text
   420         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXFINISH);    // Load end field text
   421         if (Tempfield != NULL)
   422             Tstream << trUtf8(" ") << Tempfield;                    // Save end field text
   424         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXAMOUNT);    // Load amount field text
   425         if (Tempfield != NULL)
   426             Tstream << trUtf8(" ") << Tempfield;                    // Save amount
   428         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXTASK);      // Load acct field text
   429         if (Tempfield != NULL)
   430             Tstream << trUtf8(" ") << Tempfield;                    // Save acct field text
   432         Tempfield = m_pMaintable->text(nIter, TITRAQ_IDXREMARK);    // Load remark field text
   433         Tstream << trUtf8(" \"");                                   // Save beginning double quote
   434         if (Tempfield != NULL) {
   435             Strsearch = QRegExp::escape(Tempfield);                 // Incoming string escaped
   436             Stripper.search(Strsearch);
   437             Tempfield.truncate(Stripper.pos());                     // Cut off whitespace
   438             Tempfield.replace(QChar('\\'), QString("\\\\"));        // Escape back slashes
   439             Tempfield.replace(QChar('\"'), QString("\\\""));        // Escape double quotes
   440             Tstream << Tempfield;                                   // Save remark field text
   441         }
   442         Tstream << trUtf8("\"");                                    // Save ending double quote
   444         Tstream << endl;                                            // Append a newline
   445     }
   446 }
   448 //
   449 // Convenience method to validate AS data in a file
   450 //
   451 const bool Titraqform::validateData(QFile &Filin) const
   452 {
   453     QString Firstline;      // Will contain the first line of text
   454     bool bRet = false;      // Set the initial return value
   456     if (Filin.isOpen()) {   // Check open state of file
   457         Filin.flush();      // Not sure if this is needed
   458         Filin.reset();      // Set the file index position to 0
   459         Filin.readLine(Firstline, QString(TITRAQ_DATAPATTERN).length() + 2L);
   460     }
   461     else {
   462         if (!Filin.open(IO_ReadOnly))   // Try to open file
   463             throw Genexcept(trUtf8(TITRAQ_READPFILFAIL));
   464         else {                          // File is now open
   465             Filin.readLine(Firstline, QString(TITRAQ_DATAPATTERN).length() + 2L);
   466             Filin.close();              // Remember to close
   467         }
   468     }
   470     try {   // Pass off to worker method
   471         bRet = this->validateData(Firstline);
   472     }
   473     catch (Genexcept &) {
   474         throw;  // Rethrow onwards
   475     }
   476     return bRet;
   477 }
   479 //
   480 // Validate the AS data pattern in a line
   481 //
   482 const bool Titraqform::validateData(QString &Linin) const
   483 {
   484     bool bRet = false;  // Initial return value
   486     // Ensure that the right data version pattern precedes the data
   487     QString Datapattern = QString(TITRAQ_DATAPATTERN);
   488     if (!Linin.startsWith(Datapattern)) { // Incompatible data format
   489         QMessageBox Problema(QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short,
   490             TITRAQ_NOPATTERNFOUND + QString(TITRAQ_DATAPATTERN) + TITRAQ_WASNOTFOUNDIN,
   491             QMessageBox::Critical, QMessageBox::Ok | QMessageBox::Escape,
   492             QMessageBox::NoButton, QMessageBox::NoButton);
   493         Problema.exec(); // Give the user the bad news
   494         throw Genexcept(TITRAQ_INVALIDDATA);
   495     }
   496     else if (Linin.section(Datapattern, 1).section('.', 0, 0).toInt() != TITRAQ_DATAVERSIONMAJ) {
   497         QMessageBox Problema(QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short,
   498             TITRAQ_BADVERSIONMAJ, QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Escape,
   499             QMessageBox::NoButton, QMessageBox::NoButton);
   500         Problema.exec(); // Give the user the bad news
   501         throw Genexcept(TITRAQ_INCOMPATDATA);
   502     }
   503     else if (Linin.section(Datapattern, 1).section('.', 1, 1).toInt() > TITRAQ_DATAVERSIONMIN) {
   504         QMessageBox Problema(QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short,
   505             TITRAQ_BADVERSIONMIN, QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Escape,
   506             QMessageBox::NoButton, QMessageBox::NoButton);
   507         Problema.exec(); // Give the user the bad news
   508         throw Genexcept(TITRAQ_INCOMPATDATA);
   509     }
   510     else
   511         bRet = true;
   513     return bRet;    // Not reached in case of failure
   514 }
   516 //
   517 // Get a whole row of data
   518 //
   519 const QString Titraqform::getRowdata(void) const
   520 {
   521     QString Rowdata, Tempstring;                            // For output string
   522     QTableSelection Select = m_pMaintable->selection(0);    // Highlighted text
   523     int nTotal = Select.bottomRow() - Select.topRow() + 1;  // Total row select
   525     // Calculate rows to delete from selection highlight
   526     for (int nIter = 0; nIter < nTotal; ++nIter) {
   527         // Build the row data string one field at a time, adding seps inbetween
   528         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXLINE);
   529         if (!Tempstring.isEmpty())
   530             Rowdata += Tempstring;
   531         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXUSER);
   532         if (!Tempstring.isEmpty())
   533             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   534         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXGUID);
   535         if (!Tempstring.isEmpty())
   536             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   537         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXCRC);
   538         if (!Tempstring.isEmpty())
   539             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   540         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXREV);
   541         if (!Tempstring.isEmpty())
   542             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   543         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXDATE);
   544         if (!Tempstring.isEmpty())
   545             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   546         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXSTART);
   547         if (!Tempstring.isEmpty())
   548             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   549         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXFINISH);
   550         if (!Tempstring.isEmpty())
   551             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   552         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXAMOUNT);
   553         if (!Tempstring.isEmpty())
   554             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   555         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXTASK);
   556         if (!Tempstring.isEmpty())
   557             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   558         Tempstring = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXREMARK);
   559         if (!Tempstring.isEmpty())
   560             Rowdata += TITRAQ_SEPARATORTOK + Tempstring;
   561         Rowdata += trUtf8("\n");    // Finish off line
   562     }
   564     return Rowdata;
   565 }
   567 //
   568 // Set a whole row of data
   569 //
   570 void Titraqform::setRowdata(QString &Rowdata) const
   571 {
   572     int nRows = Rowdata.contains(QChar('\n'));          // Set so many rows
   573     int nCurrentrow = m_pMaintable->currentRow();       // Current table row
   574     QTableItem *pItem = NULL;                           // Old item to change out
   575     QString Line, User, Guid, Crc, Rev;                 // Admin fields in table
   576     QString Date, Start, Finish, Amount, Task, Remark;  // Viewable fields in table
   577     QTextStream Datastream(&Rowdata, IO_ReadOnly);      // Convert data to stream
   579     for (int nIter = 0; nIter < nRows; ++nIter) {
   580         QString Singlerow = Datastream.readLine();              // For linewise operation
   581         QTextStream Rowstream(&Singlerow, IO_ReadOnly);         // Convert row to stream
   583         Rowstream >> Line >> User >> Guid >> Crc >> Rev;        // Stream data fields
   584         Rowstream >> Date >> Start >> Finish >> Amount >> Task; // to corresponding vars
   585         Remark = Rowstream.readLine();                          // Remark is a whole line
   587         // Set the table row data one field at a time, skipping seps inbetween
   588         // Importantly, do not copy over the GUID, which must be unique each row
   589         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXLINE, Line);
   590         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXUSER, User);
   591         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXCRC, Crc);
   592         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXREV, Rev);
   593         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXDATE, Date);
   594         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXSTART, Start);
   595         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXFINISH, Finish);
   596         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXAMOUNT, Amount);
   598 //        // FIXME: Why doesn't this code change the RtTableItem text in place?
   599 //        RtTableItem *pTask = NULL;                      // Derived and special
   600 //        pItem = m_pMaintable->item(nCurrentrow + nIter, TITRAQ_IDXTASK);
   601 //        pTask = static_cast<RtTableItem *>(pItem);
   602 //        pTask->setText(Task);
   604         // Change out old item and replace with new task data
   605         pItem = m_pMaintable->item(nCurrentrow + nIter, TITRAQ_IDXTASK);
   606         delete(pItem);  // Get rid of the old before going with the new
   607         RtTableItem *pSwapitem = new RtTableItem(m_pMaintable, QTableItem::WhenCurrent, Task);
   608         pSwapitem->setAlignment(AlignLeft | AlignVCenter);
   609         m_pMaintable->setItem(nCurrentrow + nIter, TITRAQ_IDXTASK, pSwapitem);
   611         // Continue with field processing business as usual
   612         m_pMaintable->setText(nCurrentrow + nIter, TITRAQ_IDXREMARK, Remark.simplifyWhiteSpace());
   613     }
   614 }
   616 //
   617 // Discover which column is the first in view
   618 //
   619 const int Titraqform::getFirstcol(void) const
   620 {
   621     int nIter = 0;  // Is both iterator in loop and column number returned
   623     // Use column selector menu popup as sole key to determining column state
   624     while (nIter < TITRAQ_IDXTAIL && !m_pColspopup->isItemChecked(m_pColspopup->idAt(++nIter)))
   625         TITRAQ_NOP;
   627     return nIter - 1; // Return one less to account for start of item offset
   628 }

mercurial