Thu, 06 Aug 2009 13:21:30 +0200
Remove seemingly declarations unnecessary according to Qt 4.5.2 headers.
michael@1 | 1 | // |
michael@1 | 2 | // OSSP asgui - Accounting system graphical user interface |
michael@12 | 3 | // Copyright (c) 2002-2009 The OSSP Project (http://www.ossp.org/) |
michael@12 | 4 | // Copyright (c) 2002-2009 Ralf S. Engelschall <rse@engelschall.com> |
michael@12 | 5 | // Copyright (c) 2002-2009 Michael Schloh von Bennewitz <michael@schloh.com> |
michael@12 | 6 | // Copyright (c) 2002-2009 Cable & Wireless Telecommunications Services GmbH |
michael@1 | 7 | // |
michael@1 | 8 | // This file is part of OSSP asgui, an accounting system graphical user |
michael@3 | 9 | // interface which can be found at http://asgui.europalab.com/. |
michael@1 | 10 | // |
michael@1 | 11 | // Permission to use, copy, modify, and distribute this software for |
michael@1 | 12 | // any purpose with or without fee is hereby granted, provided that |
michael@1 | 13 | // the above copyright notice and this permission notice appear in all |
michael@1 | 14 | // copies. |
michael@1 | 15 | // |
michael@1 | 16 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
michael@1 | 17 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
michael@1 | 18 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
michael@1 | 19 | // IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR |
michael@1 | 20 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@1 | 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@1 | 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
michael@1 | 23 | // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
michael@1 | 24 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
michael@1 | 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
michael@1 | 26 | // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
michael@1 | 27 | // SUCH DAMAGE. |
michael@1 | 28 | // |
michael@1 | 29 | // as_table.cpp: ISO C++ implementation |
michael@1 | 30 | // |
michael@1 | 31 | |
michael@3 | 32 | #include <q3header.h> |
michael@3 | 33 | |
michael@3 | 34 | //Added by qt3to4: |
michael@3 | 35 | #include <QEvent> |
michael@3 | 36 | #include <QMouseEvent> |
michael@3 | 37 | #include <QKeyEvent> |
michael@1 | 38 | |
michael@1 | 39 | #include "as_const.h" |
michael@1 | 40 | #include "as_table.h" |
michael@1 | 41 | |
michael@1 | 42 | |
michael@1 | 43 | // Implements an event filter for catching header double click events |
michael@1 | 44 | bool TiTable::eventFilter(QObject *pObject, QEvent *pEvent) |
michael@1 | 45 | { |
michael@1 | 46 | if (pObject == horizontalHeader() && pEvent->type() == QEvent::MouseButtonDblClick) |
michael@1 | 47 | return true; |
michael@1 | 48 | if (pEvent->type() == QEvent::MouseButtonPress && // Ignore mid, right clicks |
michael@3 | 49 | ((QMouseEvent *)pEvent)->button() == Qt::RightButton || |
michael@3 | 50 | ((QMouseEvent *)pEvent)->button() == Qt::MidButton) |
michael@1 | 51 | return true; |
michael@1 | 52 | else if (pEvent->type() == QEvent::KeyPress) { |
michael@1 | 53 | if (((QKeyEvent *)pEvent)->key() == Qt::Key_Tab) { // Handle tab key |
michael@1 | 54 | if (this->getEdition() >= 0) { |
michael@1 | 55 | int nIter = 1; // Logic to skip invisible or read only columns |
michael@1 | 56 | while (columnWidth((currentColumn() + nIter) % TITRAQ_IDXTAIL) <= 0 |
michael@1 | 57 | || isColumnReadOnly((currentColumn() + nIter) % TITRAQ_IDXTAIL)) |
michael@1 | 58 | nIter++; |
michael@1 | 59 | |
michael@1 | 60 | // Advance the column or both row and column possibly |
michael@1 | 61 | int nColadvance = ((currentColumn() + nIter) % TITRAQ_IDXTAIL); |
michael@1 | 62 | if ((currentColumn() + nIter) >= TITRAQ_IDXTAIL) { |
michael@1 | 63 | this->clearSelection(true); |
michael@1 | 64 | this->setCurrentCell(currentRow() + 1, nColadvance); |
michael@1 | 65 | // this->repaint(false); // Really necessary? |
michael@1 | 66 | } |
michael@1 | 67 | else |
michael@1 | 68 | this->setCurrentCell(currentRow(), nColadvance); |
michael@1 | 69 | this->setReadOnly(false); |
michael@1 | 70 | this->editCell(currentRow(), currentColumn()); |
michael@1 | 71 | this->setEdition(currentColumn()); |
michael@1 | 72 | } |
michael@1 | 73 | return true; // Handle the tab key event and cancel its progress |
michael@1 | 74 | } |
michael@1 | 75 | else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Backtab) { // Handle shift tab key |
michael@1 | 76 | if (this->getEdition() >= 0) { |
michael@1 | 77 | int nIter = 1; // Logic to skip invisible or read only columns |
michael@1 | 78 | while (columnWidth((currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL) <= 0 |
michael@1 | 79 | || isColumnReadOnly((currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL)) |
michael@1 | 80 | nIter++; |
michael@1 | 81 | |
michael@1 | 82 | // Advance the column or both row and column possibly |
michael@1 | 83 | int nColadvance = (currentColumn() - nIter + TITRAQ_IDXTAIL) % TITRAQ_IDXTAIL; |
michael@1 | 84 | if ((currentColumn() - nIter) < 0) { |
michael@1 | 85 | this->clearSelection(true); |
michael@1 | 86 | this->setCurrentCell(currentRow() - 1, nColadvance); |
michael@1 | 87 | // this->repaint(false); // Really necessary? |
michael@1 | 88 | } |
michael@1 | 89 | else |
michael@1 | 90 | this->setCurrentCell(currentRow(), nColadvance); |
michael@1 | 91 | this->setReadOnly(false); |
michael@1 | 92 | this->editCell(currentRow(), currentColumn()); |
michael@1 | 93 | this->setEdition(currentColumn()); |
michael@1 | 94 | } |
michael@1 | 95 | return true; // Handle the shift tab key event and cancel its progress |
michael@1 | 96 | } |
michael@1 | 97 | else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Return && this->getEdition() >= 0) { // Return key |
michael@1 | 98 | this->endEdit(currEditRow(), currEditCol(), true, false); |
michael@1 | 99 | this->setEdition(); // Reset edition |
michael@1 | 100 | return true; // Cancel progress |
michael@1 | 101 | } |
michael@1 | 102 | else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Enter && this->getEdition() >= 0) { // Enter key |
michael@1 | 103 | this->endEdit(currEditRow(), currEditCol(), true, false); |
michael@1 | 104 | this->setEdition(); // Reset edition |
michael@1 | 105 | return true; // Cancel progress |
michael@1 | 106 | } |
michael@1 | 107 | else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Return) { // Return key without edition |
michael@1 | 108 | this->setReadOnly(false); // Allow edition |
michael@1 | 109 | this->editCell(currentRow(), currentColumn()); // Begin edition |
michael@1 | 110 | this->setEdition(currentColumn()); // Store edition state |
michael@1 | 111 | return true; // Cancel further progress |
michael@1 | 112 | } |
michael@1 | 113 | else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Enter) { // Enter key without edition |
michael@1 | 114 | this->setReadOnly(false); // Allow edition |
michael@1 | 115 | this->editCell(currentRow(), currentColumn()); // Begin edition |
michael@1 | 116 | this->setEdition(currentColumn()); // Store edition state |
michael@1 | 117 | return true; // Cancel further progress |
michael@1 | 118 | } |
michael@1 | 119 | else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Escape) // Handle escape key |
michael@1 | 120 | this->setEdition(); |
michael@1 | 121 | else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Up && this->getEdition() >= 0) // Handle up key |
michael@1 | 122 | return true; // Capture |
michael@1 | 123 | else if (((QKeyEvent *)pEvent)->key() == Qt::Key_Down && this->getEdition() >= 0) // Handle down key |
michael@1 | 124 | return true; // Capture |
michael@1 | 125 | |
michael@1 | 126 | // Forward incompletely handled key events |
michael@3 | 127 | return Q3Table::eventFilter(pObject, pEvent); |
michael@1 | 128 | } |
michael@1 | 129 | else // Default behaviour is to pass the event onwards |
michael@3 | 130 | return Q3Table::eventFilter(pObject, pEvent); |
michael@1 | 131 | } |
michael@1 | 132 | |
michael@1 | 133 | // Overridden member hack to allow externally connected control |
michael@1 | 134 | // widgets to influence dirty or clean state of table data |
michael@1 | 135 | void TiTable::setText(int nRow, int nCol, const QString &nText) |
michael@1 | 136 | { |
michael@1 | 137 | if (this->numRows() > 0) { |
michael@1 | 138 | // If a cell was edited, emit a signal indicating so |
michael@1 | 139 | // We can't rely on valueChanged for unknown reasons |
michael@1 | 140 | if (nText != this->text(nRow, nCol) && nCol != TITRAQ_IDXLINE) |
michael@1 | 141 | emit textEdited(nRow, nCol); |
michael@1 | 142 | |
michael@3 | 143 | Q3Table::setText(nRow, nCol, nText); |
michael@1 | 144 | } |
michael@1 | 145 | } |
michael@1 | 146 | |
michael@1 | 147 | // Overridden member hack to allow externally connected control |
michael@1 | 148 | // widgets to influence dirty or clean state of table data |
michael@1 | 149 | void TiTable::sortColumn(int nCol, bool bAscend, bool bWhole) |
michael@1 | 150 | { |
michael@1 | 151 | // Guard against a repeat sort behaviour |
michael@1 | 152 | if (nCol == this->getSortcol() && bAscend == this->getSortdir()) |
michael@1 | 153 | this->setSortdir(!bAscend); |
michael@1 | 154 | else |
michael@1 | 155 | this->setSortdir(bAscend); |
michael@1 | 156 | |
michael@1 | 157 | this->setSortcol(nCol); |
michael@3 | 158 | Q3Table::sortColumn(nCol, this->getSortdir(), true); |
michael@1 | 159 | |
michael@1 | 160 | // // Announce sorting policy with multiple selections |
michael@1 | 161 | // QTableSelection Testsel = this->selection(this->currentSelection()); |
michael@1 | 162 | // if (Testsel.topRow() != Testsel.bottomRow()) |
michael@1 | 163 | // m_pStatbar->message(trUtf8("Multiple selections dropped when sorting"), 4000); |
michael@1 | 164 | |
michael@1 | 165 | // Move and display the selection highlight |
michael@1 | 166 | this->removeSelection(this->currentSelection()); |
michael@1 | 167 | this->selectRow(this->currentRow()); |
michael@1 | 168 | this->ensureCellVisible(this->currentRow(), 0); |
michael@1 | 169 | |
michael@1 | 170 | // Write nonsaving line numbers for all rows |
michael@1 | 171 | for (int nIter = this->numRows() - 1; nIter >= 0; nIter--) |
michael@1 | 172 | this->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter).rightJustify(4, QChar('0'))); |
michael@1 | 173 | } |
michael@1 | 174 | |
michael@1 | 175 | // Overriden member to render edge rows differently according to a sort key |
michael@1 | 176 | void TiTable::paintCell(QPainter *pPainter, int nRow, int nCol, const QRect &Recto, bool bSelect, const QColorGroup &Colgroup) |
michael@1 | 177 | { |
michael@1 | 178 | QColorGroup Cgroup(Colgroup); |
michael@1 | 179 | int nRed, nGreen, nBlue; |
michael@1 | 180 | |
michael@1 | 181 | nRed = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTRED, TITRAQ_DEFLIGHTRED); |
michael@1 | 182 | nGreen = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTGREEN, TITRAQ_DEFLIGHTGREEN); |
michael@1 | 183 | nBlue = m_pTiprefs->getNumber(TITRAQ_PREFLIGHTBLUE, TITRAQ_DEFLIGHTBLUE); |
michael@1 | 184 | QColor Bright = QColor(nRed, nGreen, nBlue); |
michael@1 | 185 | nRed = m_pTiprefs->getNumber(TITRAQ_PREFDARKRED, TITRAQ_DEFDARKRED); |
michael@1 | 186 | nGreen = m_pTiprefs->getNumber(TITRAQ_PREFDARKGREEN, TITRAQ_DEFDARKGREEN); |
michael@1 | 187 | nBlue = m_pTiprefs->getNumber(TITRAQ_PREFDARKBLUE, TITRAQ_DEFDARKBLUE); |
michael@1 | 188 | QColor Dark = QColor(nRed, nGreen, nBlue); |
michael@1 | 189 | |
michael@1 | 190 | // Alternate color for nonmatching sort keys |
michael@1 | 191 | QString Cur = this->text(nRow, this->getSortcol()); |
michael@1 | 192 | QString Las = this->text(nRow - 1, this->getSortcol()); |
michael@1 | 193 | |
michael@1 | 194 | // A nice cascade of conditions providing a linewise base color test and set |
michael@1 | 195 | // The algorythm: |
michael@1 | 196 | // 1 Determine if the current row's index key differs from the former one |
michael@1 | 197 | // 2a If they are the same, then current row should have the same color |
michael@1 | 198 | // 2b If they are different, then current row should have an alt color |
michael@1 | 199 | // 3 Store information about which color we chose for the current row |
michael@1 | 200 | if (!Cur.isNull() && !Las.isNull() && Cur == Las) { // Set the base color conditionally |
michael@1 | 201 | if (this->text(nRow - 1, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) == QChar(TITRAQ_BRIGHT)) { |
michael@1 | 202 | Cgroup.setColor(QColorGroup::Base, Bright); // Bright |
michael@1 | 203 | if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_BRIGHT)) |
michael@1 | 204 | this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_BRIGHT))); |
michael@1 | 205 | } |
michael@1 | 206 | else { |
michael@1 | 207 | Cgroup.setColor(QColorGroup::Base, Dark); // Dark |
michael@1 | 208 | if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_DARK)) |
michael@1 | 209 | this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_DARK))); |
michael@1 | 210 | } |
michael@1 | 211 | } |
michael@1 | 212 | else { |
michael@1 | 213 | if (this->text(nRow - 1, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) == QChar(TITRAQ_BRIGHT)) { |
michael@1 | 214 | Cgroup.setColor(QColorGroup::Base, Dark); // Dark |
michael@1 | 215 | if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_DARK)) |
michael@1 | 216 | this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_DARK))); |
michael@1 | 217 | } |
michael@1 | 218 | else { |
michael@1 | 219 | Cgroup.setColor(QColorGroup::Base, Bright); // Bright |
michael@1 | 220 | if (this->text(nRow, TITRAQ_IDXSTATUS).at(TITRAQ_IDXSTATCOLOR) != QChar(TITRAQ_BRIGHT)) |
michael@1 | 221 | this->setText(nRow, TITRAQ_IDXSTATUS, this->text(nRow, TITRAQ_IDXSTATUS).replace(TITRAQ_IDXSTATCOLOR, sizeof(char), QChar(TITRAQ_BRIGHT))); |
michael@1 | 222 | } |
michael@1 | 223 | } |
michael@1 | 224 | |
michael@3 | 225 | Q3Table::paintCell(pPainter, nRow, nCol, Recto, bSelect, Cgroup); |
michael@1 | 226 | }; |
michael@1 | 227 | |
michael@1 | 228 | // Blah |
michael@1 | 229 | void TiTable::activateNextCell(void) |
michael@1 | 230 | { |
michael@1 | 231 | int nIter = 1; // Logic to skip invisible or read only columns |
michael@1 | 232 | while (columnWidth((currentColumn() + nIter) % TITRAQ_IDXTAIL) <= 0 |
michael@1 | 233 | || isColumnReadOnly((currentColumn() + nIter) % TITRAQ_IDXTAIL)) |
michael@1 | 234 | nIter++; |
michael@1 | 235 | |
michael@1 | 236 | // Advance the column or both row and column possibly |
michael@1 | 237 | int nColadvance = ((currentColumn() + nIter) % TITRAQ_IDXTAIL); |
michael@1 | 238 | if ((currentColumn() + nIter) >= TITRAQ_IDXTAIL) |
michael@1 | 239 | this->setCurrentCell(currentRow() + 1, nColadvance); |
michael@1 | 240 | else |
michael@1 | 241 | this->setCurrentCell(currentRow(), nColadvance); |
michael@1 | 242 | this->setReadOnly(false); |
michael@1 | 243 | this->editCell(currentRow(), currentColumn()); |
michael@1 | 244 | this->setEdition(currentColumn()); |
michael@1 | 245 | } |
michael@1 | 246 | |
michael@1 | 247 | // Overriden member to properly handle read only attribute after edition |
michael@1 | 248 | void TiTable::endEdit(int nRow, int nCol, bool bAccept, bool bReplace) |
michael@1 | 249 | { |
michael@3 | 250 | Q3Table::endEdit(nRow, nCol, bAccept, bReplace); |
michael@1 | 251 | |
michael@1 | 252 | // Table read only attribute must be set to return to the normal |
michael@1 | 253 | // row highlight and selection behaviour of AS. The reason it was |
michael@1 | 254 | // reset in inplaceEdit() was to allow editing in the first place. |
michael@1 | 255 | this->setReadOnly(true); |
michael@1 | 256 | } |