Index: ossp-pkg/as/as-gui/TODO RCS File: /v/ossp/cvs/ossp-pkg/as/as-gui/TODO,v rcsdiff -q -kk '-r1.51' '-r1.52' -u '/v/ossp/cvs/ossp-pkg/as/as-gui/TODO,v' 2>/dev/null --- TODO 2002/12/18 10:36:09 1.51 +++ TODO 2002/12/18 14:50:58 1.52 @@ -33,9 +33,11 @@ IDs in as_const.h much better choosing, so they make sense Make edit control window optional through preferences Add customizable column ordering by click and drag -Method refreshDisplay is too expensive to process Soll mehr intuitive, mit sekondaer/dritte Keycolumn Be consistent with szQString vs QString var names +After every result write a status bar message +Overidden paintCell() might not work when called asynchronously +Dirty member should be part of table class, not titraq class Preferences ----------- Index: ossp-pkg/as/as-gui/as_assist.cpp RCS File: /v/ossp/cvs/ossp-pkg/as/as-gui/as_assist.cpp,v rcsdiff -q -kk '-r1.74' '-r1.75' -u '/v/ossp/cvs/ossp-pkg/as/as-gui/as_assist.cpp,v' 2>/dev/null --- as_assist.cpp 2002/12/16 17:13:17 1.74 +++ as_assist.cpp 2002/12/18 14:50:58 1.75 @@ -576,9 +576,9 @@ connect(m_pMaintable, SIGNAL(currentChanged(int, int)), this, SLOT(validateData(int, int))); connect(m_pMaintable, SIGNAL(doubleClicked(int, int, int, const QPoint&)), this, SLOT(inplaceEdit(int, int, int, const QPoint&))); connect(m_pTablehead, SIGNAL(sizeChange(int, int, int)), this, SLOT(updSizes(int, int, int))); - connect(m_pMaintable, SIGNAL(valueChanged(int, int)), this, SLOT(dataChanged(void))); + connect(m_pMaintable, SIGNAL(valueChanged(int, int)), this, SLOT(dataChanged(int, int))); connect(m_pMaintable, SIGNAL(valueChanged(int, int)), this, SLOT(validateData(int, int))); - connect(m_pMaintable, SIGNAL(textEdited(void)), this, SLOT(dataChanged(void))); + connect(m_pMaintable, SIGNAL(textEdited(int, int)), this, SLOT(dataChanged(int, int))); } // Index: ossp-pkg/as/as-gui/as_const.h RCS File: /v/ossp/cvs/ossp-pkg/as/as-gui/as_const.h,v rcsdiff -q -kk '-r1.31' '-r1.32' -u '/v/ossp/cvs/ossp-pkg/as/as-gui/as_const.h,v' 2>/dev/null --- as_const.h 2002/12/17 16:47:30 1.31 +++ as_const.h 2002/12/18 14:50:58 1.32 @@ -170,6 +170,10 @@ #define TITRAQ_IDXVIEWBAR 3 #define TITRAQ_IDXWHATBAR 4 +// Indexes of character tokens in strings +#define TITRAQ_IDXSTATERROR 0 +#define TITRAQ_IDXSTATCOLOR 1 + // Values #define TITRAQ_MARGIN 10 // Default layout margin #define TITRAQ_SPACING 6 // Default layout spacing @@ -178,5 +182,7 @@ #define TITRAQ_MINAMOUNT 0 // Minimum valid amount #define TITRAQ_STEPAMOUNT 15 // Line step interval #define TITRAQ_MINSINHOUR 60 // Only idiots don't know this +#define TITRAQ_BRIGHT 'H' // For coloring rows +#define TITRAQ_DARK 'D' // For coloring rows #endif // TITCONST_H Index: ossp-pkg/as/as-gui/as_gui.cpp RCS File: /v/ossp/cvs/ossp-pkg/as/as-gui/as_gui.cpp,v rcsdiff -q -kk '-r1.31' '-r1.32' -u '/v/ossp/cvs/ossp-pkg/as/as-gui/as_gui.cpp,v' 2>/dev/null --- as_gui.cpp 2002/12/12 21:24:07 1.31 +++ as_gui.cpp 2002/12/18 14:50:58 1.32 @@ -41,10 +41,6 @@ Titraqform::Titraqform(QWidget *pParent, const char *kszName, WFlags Flags) : QMainWindow(pParent, kszName, Flags) { - // Early member initialization - this->setDirty(false); - m_szFilename = new QString(); - try { setupPrefs(); // Load general preferences setupActions(); // Create and initialize actions @@ -61,7 +57,9 @@ exit(1); } - // Initial widget manipulations + // Early initializations and manipulations + m_szFilename = new QString(); + m_pMaintable->setDirty(false); if (!kszName) setName(trUtf8("Titraqform")); resize(m_pPrefs->getNumber(TITRAQ_PREFFRAMEWIDTH, TITRAQ_DEFFRAMEWIDTH), Index: ossp-pkg/as/as-gui/as_gui.h RCS File: /v/ossp/cvs/ossp-pkg/as/as-gui/as_gui.h,v rcsdiff -q -kk '-r1.56' '-r1.57' -u '/v/ossp/cvs/ossp-pkg/as/as-gui/as_gui.h,v' 2>/dev/null --- as_gui.h 2002/12/16 16:05:57 1.56 +++ as_gui.h 2002/12/18 14:50:58 1.57 @@ -81,8 +81,6 @@ ~Titraqform(void); // Accessor methods - const bool isDirty(void) {return m_bDirt;}; // Check for changed state danger - void setDirty(bool bDirty = true) {m_bDirt = bDirty;}; // Clean or dirty const QString getRowdata(void) const; // Get a whole row of data void setRowdata(QString &) const; // Set a whole row of data const int getFirstcol(void) const; // Learn which col is first @@ -139,7 +137,7 @@ void updEdit(int, int); // Update edit controls void validateData(int, int); // Validate one row of matrix data void updSizes(int, int, int); // Update edit sizes - void dataChanged(void); // Timesheet data changed + void dataChanged(int, int); // Timesheet data changed void updateLine(const QString &); // Update line number column void updateUser(const QString &); // Update user column void updateGuid(const QString &); // Update GUID column @@ -199,9 +197,6 @@ QToolBar *m_pWhatstools; QString *m_szFilename; - // Standard members - bool m_bDirt; // To track dirty and clean states - // Constructor helpers void setupPrefs(void); // Preferences void setupActions(void); // Actions Index: ossp-pkg/as/as-gui/as_slot.cpp RCS File: /v/ossp/cvs/ossp-pkg/as/as-gui/as_slot.cpp,v rcsdiff -q -kk '-r1.68' '-r1.69' -u '/v/ossp/cvs/ossp-pkg/as/as-gui/as_slot.cpp,v' 2>/dev/null --- as_slot.cpp 2002/12/18 12:36:16 1.68 +++ as_slot.cpp 2002/12/18 14:50:58 1.69 @@ -127,7 +127,7 @@ // Add a row after selection and focus to the new row if (Select.bottomRow() + 1 != m_pMaintable->numRows()) { // Add upwards m_pMaintable->insertRows(Select.topRow(), nTotal); - this->setDirty(); // Set data to dirty state + m_pMaintable->setDirty(); // Set data to dirty state m_pMaintable->setCurrentCell(Select.topRow(), m_pMaintable->currentColumn()); // Update relevant data fields for all new rows @@ -147,7 +147,7 @@ } else { // Special case on last row add downwards m_pMaintable->insertRows(Select.bottomRow() + 1, nTotal); - this->setDirty(); // Set data to dirty state + m_pMaintable->setDirty(); // Set data to dirty state m_pMaintable->setCurrentCell(Select.bottomRow() + 1, m_pMaintable->currentColumn()); m_pMaintable->ensureCellVisible(m_pMaintable->numRows() - 1, 0); // Scroll please @@ -199,11 +199,11 @@ if (m_pMaintable->currentRow() + 1 != m_pMaintable->numRows()) { m_pMaintable->setCurrentCell(Select.bottomRow() + 1, m_pMaintable->currentColumn()); m_pMaintable->removeRows(Rowselect); - this->setDirty(); // Set data to dirty state + m_pMaintable->setDirty(); // Set data to dirty state } else { // Special case to handle removing of only row or last row m_pMaintable->removeRows(Rowselect); - this->setDirty(); // Set data to dirty state + m_pMaintable->setDirty(); // Set data to dirty state } // Update line numbers for this new row and all subsequent rows @@ -227,7 +227,8 @@ nIter++; } - this->repaint(); // Do a general repaint of viewable area + m_pMaintable->repaintContents(true); // Do a general repaint of table + m_pStatbar->message(trUtf8("Refreshed display"), 4000); // Announce result } // @@ -238,7 +239,7 @@ int nResult = 0; // Check modification state of current data - if (this->isDirty()) { + if (m_pMaintable->isDirty()) { nResult = QMessageBox::information(this, trUtf8(TITRAQ_APPTITLE), trUtf8(TITRAQ_SAVEFIRST), trUtf8("&Save"), trUtf8("&Discard"), trUtf8("Cancel"), 0, 2); @@ -269,7 +270,7 @@ m_pTasks->setEnabled(true); m_pRemark->setEnabled(true); this->updEdit(0, 0); // Reset edit controls - this->setDirty(false); // Reset data to clean state + m_pMaintable->setDirty(false); // Reset data to clean state break; case 1: // Second button selected, so don't save first but do new m_pMaintable->setEnabled(true); // Enable the table first @@ -286,7 +287,7 @@ m_pTasks->setEnabled(true); m_pRemark->setEnabled(true); this->updEdit(0, 0); // Reset edit controls - this->setDirty(false); // Reset data to clean state + m_pMaintable->setDirty(false); // Reset data to clean state break; case 2: // Third button selected, so don't do a new timesheet default: @@ -315,7 +316,7 @@ m_pTasks->setEnabled(true); m_pRemark->setEnabled(true); this->updEdit(0, 0); // Reset edit controls - this->setDirty(false); // Reset data to clean state + m_pMaintable->setDirty(false); // Reset data to clean state } } @@ -330,7 +331,7 @@ if (!Filestring.isEmpty()) { QFile Filetemp(Filestring); // File to load // Check modification state of current data - if (this->isDirty()) { + if (m_pMaintable->isDirty()) { nResult = QMessageBox::information(this, trUtf8(TITRAQ_APPTITLE), trUtf8(TITRAQ_SAVEFIRST), trUtf8("&Save"), trUtf8("&Discard"), trUtf8("Cancel"), 0, 2); @@ -361,7 +362,7 @@ m_pAmount->setEnabled(true); m_pTasks->setEnabled(true); m_pRemark->setEnabled(true); - this->setDirty(false); // Set the clean state + m_pMaintable->setDirty(false); // Set the clean state break; case 1: // Don't save first but do load m_szFilename->operator=(Filestring); @@ -387,7 +388,7 @@ m_pAmount->setEnabled(true); m_pTasks->setEnabled(true); m_pRemark->setEnabled(true); - this->setDirty(false); // Set the clean state + m_pMaintable->setDirty(false); // Set the clean state break; case 2: // Don't do a load timesheet default: @@ -418,7 +419,7 @@ m_pAmount->setEnabled(true); m_pTasks->setEnabled(true); m_pRemark->setEnabled(true); - this->setDirty(false); // Set the clean state + m_pMaintable->setDirty(false); // Set the clean state } } else @@ -447,7 +448,7 @@ // Reset and give output to main window this->setCaption(*m_szFilename); m_pStatbar->message(trUtf8("File %1 saved").arg(*m_szFilename), 4000); - this->setDirty(false); // Set the clean state to allow close + m_pMaintable->setDirty(false); // Set the clean state to allow close } // @@ -491,7 +492,7 @@ int nResult = 0; // Check modification state of current data - if (this->isDirty()) { + if (m_pMaintable->isDirty()) { nResult = QMessageBox::information(this, trUtf8(TITRAQ_APPTITLE), trUtf8(TITRAQ_SAVEFIRST), trUtf8("&Save"), trUtf8("&Discard"), trUtf8("Cancel"), 0, 2); @@ -499,11 +500,11 @@ switch (nResult) { case 0: // Save first this->saveFile(); // Save changes first - this->setDirty(false); // Reset data to clean state + m_pMaintable->setDirty(false); // Reset data to clean state pClosit->accept(); // then close timesheet break; case 1: // Don't save first but close - this->setDirty(false); // Reset data to clean state + m_pMaintable->setDirty(false); // Reset data to clean state pClosit->accept(); // Close timesheet break; case 2: // Don't close @@ -513,7 +514,7 @@ } } else { // Data is already up to date - this->setDirty(false); // Reset data to clean state + m_pMaintable->setDirty(false); // Reset data to clean state pClosit->accept(); } } @@ -654,9 +655,10 @@ // // What to do if a data cell is modified // -void Titraqform::dataChanged(void) +void Titraqform::dataChanged(int nRow, int nCol) { - setDirty(); // Mark this timesheet dirty, changes pending save + if (nCol != TITRAQ_IDXSTATUS && nCol != TITRAQ_IDXLINE) + m_pMaintable->setDirty(); // Mark this timesheet dirty, changes pending save } // @@ -735,17 +737,16 @@ m_pMaintable->text(nRow, TITRAQ_IDXTASK).isEmpty()) { // No K&R style to show where actual code begins if (!Statis.startsWith(QString("E"))) { // Conditionally set pixmap to avoid overhead - m_pMaintable->setText(nRow, TITRAQ_IDXSTATUS, Statis.replace(0, sizeof(char), 'E')); + m_pMaintable->setText(nRow, TITRAQ_IDXSTATUS, Statis.replace(TITRAQ_IDXSTATERROR, sizeof(char), 'E')); m_pMaintable->setPixmap(nRow, TITRAQ_IDXSTATUS, QPixmap(s_kpcStaterror_xpm)); } } else { if (!Statis.startsWith(QString("O"))) { // Conditionally set pixmap to avoid overhead - m_pMaintable->setText(nRow, TITRAQ_IDXSTATUS, Statis.replace(0, sizeof(char), 'O')); + m_pMaintable->setText(nRow, TITRAQ_IDXSTATUS, Statis.replace(TITRAQ_IDXSTATERROR, sizeof(char), 'O')); m_pMaintable->setPixmap(nRow, TITRAQ_IDXSTATUS, QPixmap(s_kpcStatokay_xpm)); } } - m_pStatbar->message(trUtf8("Refreshed display"), 4000); // Announce result } // Index: ossp-pkg/as/as-gui/as_table.cpp RCS File: /v/ossp/cvs/ossp-pkg/as/as-gui/as_table.cpp,v rcsdiff -q -kk '-r1.16' '-r1.17' -u '/v/ossp/cvs/ossp-pkg/as/as-gui/as_table.cpp,v' 2>/dev/null --- as_table.cpp 2002/12/17 16:55:08 1.16 +++ as_table.cpp 2002/12/18 14:50:58 1.17 @@ -106,7 +106,7 @@ // 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(); + emit textEdited(nRow, nCol); QTable::setText(nRow, nCol, nText); } @@ -133,11 +133,36 @@ QString Cur = this->text(nRow, this->getSortcol()); QString Las = this->text(nRow - 1, this->getSortcol()); - // Set the base color conditionally - if (!Cur.isNull() && !Las.isNull() && Cur == Las) - Cgroup.setColor(QColorGroup::Base, QColor(248, 248, 240)); - else - Cgroup.setColor(QColorGroup::Base, QColor(232, 232, 224)); + // 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, QColor(248, 248, 240)); // 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, QColor(224, 224, 216)); // 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, QColor(224, 224, 216)); // 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, QColor(248, 248, 240)); // 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); }; Index: ossp-pkg/as/as-gui/as_table.h RCS File: /v/ossp/cvs/ossp-pkg/as/as-gui/as_table.h,v rcsdiff -q -kk '-r1.12' '-r1.13' -u '/v/ossp/cvs/ossp-pkg/as/as-gui/as_table.h,v' 2>/dev/null --- as_table.h 2002/12/17 16:55:08 1.12 +++ as_table.h 2002/12/18 14:50:58 1.13 @@ -40,15 +40,17 @@ Q_OBJECT private: - int m_nSortcol; + int m_nSortcol; // To track current sort column + bool m_bDirt; // To track dirty and clean states public: // Try to match QTable's default constructor with an initializer list TiTable(QWidget *pParent = 0, const char *szName = 0) : QTable(pParent, szName) { - m_nSortcol = 0; - horizontalHeader()->installEventFilter(this); + this->setSortcol(0); + this->setDirty(false); this->setEdition(); // Reset edition state + horizontalHeader()->installEventFilter(this); }; bool eventFilter(QObject *, QEvent *); @@ -57,7 +59,9 @@ int m_nEdit; // To track edition state // Accessor methods - const int getEdition(void) {return m_nEdit;}; // Which edited column was confirmed + const bool isDirty(void) {return m_bDirt;}; // Check for changed state danger + void setDirty(bool bDirty = true) {m_bDirt = bDirty;}; // Clean or dirty + const int getEdition(void) {return m_nEdit;}; // Which edited column was confirmed void setEdition(const int nEdit = -1) {m_nEdit = nEdit;}; // Set edition status const int getSortcol(void) {return m_nSortcol;}; void setSortcol(const int nColin) {m_nSortcol = nColin;}; @@ -78,7 +82,7 @@ virtual void activateNextCell(void); signals: - void textEdited(void); // A cell was edited and data was modified + void textEdited(int, int); // A cell was edited and data was modified }; #endif // TITABLE_H