OSSP CVS Repository

ossp - ossp-pkg/as/as-gui/as_table.cpp
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/as/as-gui/as_table.cpp
//
//  OSSP asgui - Accounting system graphical user interface
//  Copyright (c) 2002-2004 The OSSP Project (http://www.ossp.org/)
//  Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>
//  Copyright (c) 2002-2004 Michael Schloh von Bennewitz <michael@schloh.com>
//  Copyright (c) 2002-2004 Cable & Wireless Telecommunications Services GmbH
//
//  This file is part of OSSP asgui, an accounting system graphical user
//  interface which can be found at http://www.ossp.org/pkg/tool/asgui/.
//
//  Permission to use, copy, modify, and distribute this software for
//  any purpose with or without fee is hereby granted, provided that
//  the above copyright notice and this permission notice appear in all
//  copies.
//
//  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
//  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
//  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
//  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
//  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
//  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//  SUCH DAMAGE.
//
//  as_table.cpp: ISO C++ implementation
//

#include <qheader.h>

#include "as_const.h"
#include "as_table.h"


// Implements an event filter for catching header double click events
bool TiTable::eventFilter(QObject *pObject, QEvent *pEvent)
{
    if (pObject == horizontalHeader() && pEvent->type() == QEvent::MouseButtonDblClick)
        return true;
    if (pEvent->type() == QEvent::MouseButtonPress &&   // Ignore mid, right clicks
        ((QMouseEvent *)pEvent)->button() == QMouseEvent::RightButton ||
        ((QMouseEvent *)pEvent)->button() == QMouseEvent::MidButton)
        return true;
    else if (pEvent->type() == QEvent::KeyPress) {
        if (((QKeyEvent *)pEvent)->key() == Qt::Key_Tab) { // Handle tab key
            if (this->getEdition() >= 0) {
                int nIter = 1; // Logic to skip invisible or read only columns
                while (columnWidth((currentColumn() + nIter) % TITRAQ_IDXTAIL) <= 0
                    || isColumnReadOnly((currentColumn() + nIter) % TITRAQ_IDXTAIL))
                    nIter++;

                // Advance the column or both row and column possibly
                int nColadvance = ((currentColumn() + nIter) % TITRAQ_IDXTAIL);
                if ((currentColumn() + nIter) >= TITRAQ_IDXTAIL) {
                    this->clearSelection(true);
                    this->setCurrentCell(currentRow() + 1, nColadvance);
//                    this->repaint(false);   // Really necessary?
                }
                else
                    this->setCurrentCell(currentRow(), nColadvance);
                this->setReadOnly(false);
                this->editCell(currentRow(), currentColumn());
                this->setEdition(currentColumn());
            }
            return true; // Handle the tab key event and cancel its progress
        }
        else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Backtab) { // Handle shift tab key
            if (this->getEdition() >= 0) {
                int nIter = 1; // Logic to skip invisible or read only columns
                while (columnWidth((currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL) <= 0
                    || isColumnReadOnly((currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL))
                    nIter++;

                // Advance the column or both row and column possibly
                int nColadvance = (currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL;
                if ((currentColumn() - nIter) < 0) {
                    this->clearSelection(true);
                    this->setCurrentCell(currentRow() - 1, nColadvance);
//                    this->repaint(false);   // Really necessary?
                }
                else
                    this->setCurrentCell(currentRow(), nColadvance);
                this->setReadOnly(false);
                this->editCell(currentRow(), currentColumn());
                this->setEdition(currentColumn());
            }
            return true; // Handle the shift tab key event and cancel its progress
        }
        else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Return && this->getEdition() >= 0) { // Return key
            this->endEdit(currEditRow(), currEditCol(), true, false);
            this->setEdition();                             // Reset edition
            return true;                                    // Cancel progress
        }
        else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Enter && this->getEdition() >= 0) { // Enter key
            this->endEdit(currEditRow(), currEditCol(), true, false);
            this->setEdition();                             // Reset edition
            return true;                                    // Cancel progress
        }
        else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Return) { // Return key without edition
            this->setReadOnly(false);                       // Allow edition
            this->editCell(currentRow(), currentColumn());  // Begin edition
            this->setEdition(currentColumn());              // Store edition state
            return true;                                    // Cancel further progress
        }
        else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Enter) { // Enter key without edition
            this->setReadOnly(false);                       // Allow edition
            this->editCell(currentRow(), currentColumn());  // Begin edition
            this->setEdition(currentColumn());              // Store edition state
            return true;                                    // Cancel further progress
        }
        else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Escape)    // Handle escape key
            this->setEdition();
        else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Up && this->getEdition() >= 0) // Handle up key
            return true;                                            // Capture
        else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Down && this->getEdition() >= 0) // Handle down key
            return true;                                            // Capture

        // Forward incompletely handled key events
        return QTable::eventFilter(pObject, pEvent);
    }
    else // Default behaviour is to pass the event onwards
        return QTable::eventFilter(pObject, pEvent);
}

// Overridden member hack to allow externally connected control
// widgets to influence dirty or clean state of table data
void TiTable::setText(int nRow, int nCol, const QString &nText)
{
    if (this->numRows() > 0) {
        // If a cell was edited, emit a signal indicating so
        // We can't rely on valueChanged for unknown reasons
        if (nText != this->text(nRow, nCol) && nCol != TITRAQ_IDXLINE)
            emit textEdited(nRow, nCol);

        QTable::setText(nRow, nCol, nText);
    }
}

// Overridden member hack to allow externally connected control
// widgets to influence dirty or clean state of table data
void TiTable::sortColumn(int nCol, bool bAscend, bool bWhole)
{
    // Guard against a repeat sort behaviour
    if (nCol == this->getSortcol() && bAscend == this->getSortdir())
        this->setSortdir(!bAscend);
    else
        this->setSortdir(bAscend);

    this->setSortcol(nCol);
    QTable::sortColumn(nCol, this->getSortdir(), true);

//    // Announce sorting policy with multiple selections
//    QTableSelection Testsel = this->selection(this->currentSelection());
//    if (Testsel.topRow() != Testsel.bottomRow())
//        m_pStatbar->message(trUtf8("Multiple selections dropped when sorting"), 4000);

    // Move and display the selection highlight
    this->removeSelection(this->currentSelection());
    this->selectRow(this->currentRow());
    this->ensureCellVisible(this->currentRow(), 0);

    // Write nonsaving line numbers for all rows
    for (int nIter = this->numRows() - 1; nIter >= 0; nIter--)
        this->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter).rightJustify(4, QChar('0')));
}

// Overriden member to render edge rows differently according to a sort key
void TiTable::paintCell(QPainter *pPainter, int nRow, int nCol, const QRect &Recto, bool bSelect, const QColorGroup &Colgroup)
{
    QColorGroup Cgroup(Colgroup);
    int nRed, nGreen, nBlue;

    nRed = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTRED, TITRAQ_DEFLIGHTRED);
    nGreen = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTGREEN, TITRAQ_DEFLIGHTGREEN);
    nBlue = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTBLUE, TITRAQ_DEFLIGHTBLUE);
    QColor Bright = QColor(nRed, nGreen, nBlue);
    nRed = m_pTiprefs->getNumber(TITRAQ_PREFDARKRED, TITRAQ_DEFDARKRED);
    nGreen = m_pTiprefs->getNumber(TITRAQ_PREFDARKGREEN, TITRAQ_DEFDARKGREEN);
    nBlue = m_pTiprefs->getNumber(TITRAQ_PREFDARKBLUE, TITRAQ_DEFDARKBLUE);
    QColor Dark = QColor(nRed, nGreen, nBlue);

    // Alternate color for nonmatching sort keys
    QString Cur = this->text(nRow, this->getSortcol());
    QString Las = this->text(nRow - 1, this->getSortcol());

    // A nice cascade of conditions providing a linewise base color test and set
    // The algorythm:
    //   1  Determine if the current row's index key differs from the former one
    //   2a If they are the same, then current row should have the same color
    //   2b If they are different, then current row should have an alt color
    //   3  Store information about which color we chose for the current row
    if (!Cur.isNull() && !Las.isNull() && Cur == Las) { // Set the base color conditionally
        if (this->text(nRow - 1, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) == QChar(TITRAQ_BRIGHT)) {
            Cgroup.setColor(QColorGroup::Base, Bright); // Bright
            if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_BRIGHT))
                this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_BRIGHT)));
        }
        else {
            Cgroup.setColor(QColorGroup::Base, Dark);   // Dark
            if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_DARK))
                this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_DARK)));
        }
    }
    else {
        if (this->text(nRow - 1, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) == QChar(TITRAQ_BRIGHT)) {
            Cgroup.setColor(QColorGroup::Base, Dark);   // Dark
            if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_DARK))
                this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_DARK)));
        }
        else {
            Cgroup.setColor(QColorGroup::Base, Bright); // Bright
            if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_BRIGHT))
                this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_BRIGHT)));
        }
    }

    QTable::paintCell(pPainter, nRow, nCol, Recto, bSelect, Cgroup);
};

// Blah
void TiTable::activateNextCell(void)
{
    int nIter = 1; // Logic to skip invisible or read only columns
    while (columnWidth((currentColumn() + nIter) % TITRAQ_IDXTAIL) <= 0
        || isColumnReadOnly((currentColumn() + nIter) % TITRAQ_IDXTAIL))
        nIter++;

    // Advance the column or both row and column possibly
    int nColadvance = ((currentColumn() + nIter) % TITRAQ_IDXTAIL);
    if ((currentColumn() + nIter) >= TITRAQ_IDXTAIL)
        this->setCurrentCell(currentRow() + 1, nColadvance);
    else
        this->setCurrentCell(currentRow(), nColadvance);
    this->setReadOnly(false);
    this->editCell(currentRow(), currentColumn());
    this->setEdition(currentColumn());
}

// Overriden member to properly handle read only attribute after edition
void TiTable::endEdit(int nRow, int nCol, bool bAccept, bool bReplace)
{
    QTable::endEdit(nRow, nCol, bAccept, bReplace);

    // Table read only attribute must be set to return to the normal
    // row highlight and selection behaviour of AS. The reason it was
    // reset in inplaceEdit() was to allow editing in the first place.
    this->setReadOnly(true);
}

CVSTrac 2.0.1