as_table.cpp

Fri, 05 Dec 2008 23:15:28 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 05 Dec 2008 23:15:28 +0100
changeset 4
c920180c879a
parent 1
d64aaa7d146f
child 12
ceb4ba3d2d00
permissions
-rw-r--r--

Correct version number and date in documentation.

     1 //
     2 //  OSSP asgui - Accounting system graphical user interface
     3 //  Copyright (c) 2002-2008 The OSSP Project (http://www.ossp.org/)
     4 //  Copyright (c) 2002-2008 Ralf S. Engelschall <rse@engelschall.com>
     5 //  Copyright (c) 2002-2008 Michael Schloh von Bennewitz <michael@schloh.com>
     6 //  Copyright (c) 2002-2008 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_table.cpp: ISO C++ implementation
    30 //
    32 #define QT3_SUPPORT
    34 #include <q3header.h>
    36 //Added by qt3to4:
    37 #include <QEvent>
    38 #include <QMouseEvent>
    39 #include <QKeyEvent>
    41 #include "as_const.h"
    42 #include "as_table.h"
    45 // Implements an event filter for catching header double click events
    46 bool TiTable::eventFilter(QObject *pObject, QEvent *pEvent)
    47 {
    48     if (pObject == horizontalHeader() && pEvent->type() == QEvent::MouseButtonDblClick)
    49         return true;
    50     if (pEvent->type() == QEvent::MouseButtonPress &&   // Ignore mid, right clicks
    51         ((QMouseEvent *)pEvent)->button() == Qt::RightButton ||
    52         ((QMouseEvent *)pEvent)->button() == Qt::MidButton)
    53         return true;
    54     else if (pEvent->type() == QEvent::KeyPress) {
    55         if (((QKeyEvent *)pEvent)->key() == Qt::Key_Tab) { // Handle tab key
    56             if (this->getEdition() >= 0) {
    57                 int nIter = 1; // Logic to skip invisible or read only columns
    58                 while (columnWidth((currentColumn() + nIter) % TITRAQ_IDXTAIL) <= 0
    59                     || isColumnReadOnly((currentColumn() + nIter) % TITRAQ_IDXTAIL))
    60                     nIter++;
    62                 // Advance the column or both row and column possibly
    63                 int nColadvance = ((currentColumn() + nIter) % TITRAQ_IDXTAIL);
    64                 if ((currentColumn() + nIter) >= TITRAQ_IDXTAIL) {
    65                     this->clearSelection(true);
    66                     this->setCurrentCell(currentRow() + 1, nColadvance);
    67 //                    this->repaint(false);   // Really necessary?
    68                 }
    69                 else
    70                     this->setCurrentCell(currentRow(), nColadvance);
    71                 this->setReadOnly(false);
    72                 this->editCell(currentRow(), currentColumn());
    73                 this->setEdition(currentColumn());
    74             }
    75             return true; // Handle the tab key event and cancel its progress
    76         }
    77         else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Backtab) { // Handle shift tab key
    78             if (this->getEdition() >= 0) {
    79                 int nIter = 1; // Logic to skip invisible or read only columns
    80                 while (columnWidth((currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL) <= 0
    81                     || isColumnReadOnly((currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL))
    82                     nIter++;
    84                 // Advance the column or both row and column possibly
    85                 int nColadvance = (currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL;
    86                 if ((currentColumn() - nIter) < 0) {
    87                     this->clearSelection(true);
    88                     this->setCurrentCell(currentRow() - 1, nColadvance);
    89 //                    this->repaint(false);   // Really necessary?
    90                 }
    91                 else
    92                     this->setCurrentCell(currentRow(), nColadvance);
    93                 this->setReadOnly(false);
    94                 this->editCell(currentRow(), currentColumn());
    95                 this->setEdition(currentColumn());
    96             }
    97             return true; // Handle the shift tab key event and cancel its progress
    98         }
    99         else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Return && this->getEdition() >= 0) { // Return key
   100             this->endEdit(currEditRow(), currEditCol(), true, false);
   101             this->setEdition();                             // Reset edition
   102             return true;                                    // Cancel progress
   103         }
   104         else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Enter && this->getEdition() >= 0) { // Enter key
   105             this->endEdit(currEditRow(), currEditCol(), true, false);
   106             this->setEdition();                             // Reset edition
   107             return true;                                    // Cancel progress
   108         }
   109         else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Return) { // Return key without edition
   110             this->setReadOnly(false);                       // Allow edition
   111             this->editCell(currentRow(), currentColumn());  // Begin edition
   112             this->setEdition(currentColumn());              // Store edition state
   113             return true;                                    // Cancel further progress
   114         }
   115         else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Enter) { // Enter key without edition
   116             this->setReadOnly(false);                       // Allow edition
   117             this->editCell(currentRow(), currentColumn());  // Begin edition
   118             this->setEdition(currentColumn());              // Store edition state
   119             return true;                                    // Cancel further progress
   120         }
   121         else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Escape)    // Handle escape key
   122             this->setEdition();
   123         else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Up && this->getEdition() >= 0) // Handle up key
   124             return true;                                            // Capture
   125         else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Down && this->getEdition() >= 0) // Handle down key
   126             return true;                                            // Capture
   128         // Forward incompletely handled key events
   129         return Q3Table::eventFilter(pObject, pEvent);
   130     }
   131     else // Default behaviour is to pass the event onwards
   132         return Q3Table::eventFilter(pObject, pEvent);
   133 }
   135 // Overridden member hack to allow externally connected control
   136 // widgets to influence dirty or clean state of table data
   137 void TiTable::setText(int nRow, int nCol, const QString &nText)
   138 {
   139     if (this->numRows() > 0) {
   140         // If a cell was edited, emit a signal indicating so
   141         // We can't rely on valueChanged for unknown reasons
   142         if (nText != this->text(nRow, nCol) && nCol != TITRAQ_IDXLINE)
   143             emit textEdited(nRow, nCol);
   145         Q3Table::setText(nRow, nCol, nText);
   146     }
   147 }
   149 // Overridden member hack to allow externally connected control
   150 // widgets to influence dirty or clean state of table data
   151 void TiTable::sortColumn(int nCol, bool bAscend, bool bWhole)
   152 {
   153     // Guard against a repeat sort behaviour
   154     if (nCol == this->getSortcol() && bAscend == this->getSortdir())
   155         this->setSortdir(!bAscend);
   156     else
   157         this->setSortdir(bAscend);
   159     this->setSortcol(nCol);
   160     Q3Table::sortColumn(nCol, this->getSortdir(), true);
   162 //    // Announce sorting policy with multiple selections
   163 //    QTableSelection Testsel = this->selection(this->currentSelection());
   164 //    if (Testsel.topRow() != Testsel.bottomRow())
   165 //        m_pStatbar->message(trUtf8("Multiple selections dropped when sorting"), 4000);
   167     // Move and display the selection highlight
   168     this->removeSelection(this->currentSelection());
   169     this->selectRow(this->currentRow());
   170     this->ensureCellVisible(this->currentRow(), 0);
   172     // Write nonsaving line numbers for all rows
   173     for (int nIter = this->numRows() - 1; nIter >= 0; nIter--)
   174         this->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter).rightJustify(4, QChar('0')));
   175 }
   177 // Overriden member to render edge rows differently according to a sort key
   178 void TiTable::paintCell(QPainter *pPainter, int nRow, int nCol, const QRect &Recto, bool bSelect, const QColorGroup &Colgroup)
   179 {
   180     QColorGroup Cgroup(Colgroup);
   181     int nRed, nGreen, nBlue;
   183     nRed = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTRED, TITRAQ_DEFLIGHTRED);
   184     nGreen = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTGREEN, TITRAQ_DEFLIGHTGREEN);
   185     nBlue = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTBLUE, TITRAQ_DEFLIGHTBLUE);
   186     QColor Bright = QColor(nRed, nGreen, nBlue);
   187     nRed = m_pTiprefs->getNumber(TITRAQ_PREFDARKRED, TITRAQ_DEFDARKRED);
   188     nGreen = m_pTiprefs->getNumber(TITRAQ_PREFDARKGREEN, TITRAQ_DEFDARKGREEN);
   189     nBlue = m_pTiprefs->getNumber(TITRAQ_PREFDARKBLUE, TITRAQ_DEFDARKBLUE);
   190     QColor Dark = QColor(nRed, nGreen, nBlue);
   192     // Alternate color for nonmatching sort keys
   193     QString Cur = this->text(nRow, this->getSortcol());
   194     QString Las = this->text(nRow - 1, this->getSortcol());
   196     // A nice cascade of conditions providing a linewise base color test and set
   197     // The algorythm:
   198     //   1  Determine if the current row's index key differs from the former one
   199     //   2a If they are the same, then current row should have the same color
   200     //   2b If they are different, then current row should have an alt color
   201     //   3  Store information about which color we chose for the current row
   202     if (!Cur.isNull() && !Las.isNull() && Cur == Las) { // Set the base color conditionally
   203         if (this->text(nRow - 1, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) == QChar(TITRAQ_BRIGHT)) {
   204             Cgroup.setColor(QColorGroup::Base, Bright); // Bright
   205             if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_BRIGHT))
   206                 this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_BRIGHT)));
   207         }
   208         else {
   209             Cgroup.setColor(QColorGroup::Base, Dark);   // Dark
   210             if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_DARK))
   211                 this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_DARK)));
   212         }
   213     }
   214     else {
   215         if (this->text(nRow - 1, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) == QChar(TITRAQ_BRIGHT)) {
   216             Cgroup.setColor(QColorGroup::Base, Dark);   // Dark
   217             if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_DARK))
   218                 this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_DARK)));
   219         }
   220         else {
   221             Cgroup.setColor(QColorGroup::Base, Bright); // Bright
   222             if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_BRIGHT))
   223                 this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_BRIGHT)));
   224         }
   225     }
   227     Q3Table::paintCell(pPainter, nRow, nCol, Recto, bSelect, Cgroup);
   228 };
   230 // Blah
   231 void TiTable::activateNextCell(void)
   232 {
   233     int nIter = 1; // Logic to skip invisible or read only columns
   234     while (columnWidth((currentColumn() + nIter) % TITRAQ_IDXTAIL) <= 0
   235         || isColumnReadOnly((currentColumn() + nIter) % TITRAQ_IDXTAIL))
   236         nIter++;
   238     // Advance the column or both row and column possibly
   239     int nColadvance = ((currentColumn() + nIter) % TITRAQ_IDXTAIL);
   240     if ((currentColumn() + nIter) >= TITRAQ_IDXTAIL)
   241         this->setCurrentCell(currentRow() + 1, nColadvance);
   242     else
   243         this->setCurrentCell(currentRow(), nColadvance);
   244     this->setReadOnly(false);
   245     this->editCell(currentRow(), currentColumn());
   246     this->setEdition(currentColumn());
   247 }
   249 // Overriden member to properly handle read only attribute after edition
   250 void TiTable::endEdit(int nRow, int nCol, bool bAccept, bool bReplace)
   251 {
   252     Q3Table::endEdit(nRow, nCol, bAccept, bReplace);
   254     // Table read only attribute must be set to return to the normal
   255     // row highlight and selection behaviour of AS. The reason it was
   256     // reset in inplaceEdit() was to allow editing in the first place.
   257     this->setReadOnly(true);
   258 }

mercurial