diff -r 27e940e8e5f3 -r d64aaa7d146f as_slot.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/as_slot.cpp Fri Nov 28 11:21:08 2008 +0100 @@ -0,0 +1,2018 @@ +// +// 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 +// Copyright (c) 2002-2004 Michael Schloh von Bennewitz +// 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_slot.cpp: ISO C++ implementation +// + +// system headers +#include +#include + +// Qt headers +#include +#include +#include +#include +#include +#include +#include +#include + +// Qt style headers +#include +#include +#include +#include +#include +#include + +// User interface +#include "as_const.h" // Application constants +#include "as_except.h" // Exception classes +#include "as_tableitem.h" // For our custom table items +#include "as_generic.h" // Generic classes +#include "as_uuid.h" // UUID classes +#include "as_datedit.h" // Derived from QDateEdit +#include "as_amount.h" // Derived from QTimeEdit +#include "as_crc.h" // Useful Qualistring class +#include "as_pref.h" // For Preferences class +#include "as_panel.h" // For Prefpanel class +#include "as_reportpanel.h" // For Reportpanel class +#include "as_helpanel.h" // For Helpanel class +#include "as_sfile.h" // For Simplefile class +#include "as_table.h" // For TiTable class + +// RPC headers +#ifdef HAVE_ESOAP +#include +#endif // HAVE_ESOAP +#ifdef HAVE_MICO +#include +#include "as_stub.h" // CORBA stubs and skeletons +#endif // HAVE_MICO + +// Icon pixel maps +#include "as_gfx/cwlogo.xpm" // static const char *s_kpcCwlogo_xpm[] +#include "as_gfx/ossplogo.xpm" // static const char *s_kpcOssplogo_xpm[] +#include "as_gfx/statok.xpm" // static const char *s_kpcStatokay_xpm[] +#include "as_gfx/staterr.xpm" // static const char *s_kpcStaterror_xpm[] +#include "as_gfx/statwrn.xpm" // static const char *s_kpcStatwarn_xpm[] +#include "as_gfx/statvoid.xpm" // static const char *s_kpcStatvoid_xpm[] + + +// +// Cut an entry +// +void Titraqform::cutEntry(void) +{ + this->copyEntry(); // Reuse slot + this->delEntry(); // Reuse slot +} + +// +// Copy an entry +// +void Titraqform::copyEntry(void) +{ + QString Selection; // Will hold the selected text + QClipboard *pClip; // Will reference the global clipboard + + // Initialize data and clipboard handle + Selection = getRowdata(); // Use accessor + pClip = QApplication::clipboard(); + + Q_ASSERT(!Selection.isNull()); + pClip->setText(Selection, QClipboard::Selection); // Doesn't work on Windows + pClip->setText(Selection, QClipboard::Clipboard); // Works on both equally +} + +// +// Paste an entry +// +void Titraqform::pasteEntry(void) +{ + int nRows = 0; // Paste so many rows as are stored + QString Selection; // Will receive the clipboard text + QClipboard *pClip = NULL; // Will reference the global clipboard + + pClip = QApplication::clipboard(); // Prime the clips + Selection = pClip->text(QClipboard::Clipboard); // Windows and Unix + nRows = Selection.contains(QChar('\n')); // How many rows + if (Selection != NULL && nRows > 0) { // Ignore empty clipboards + this->addEntry(nRows); // Reuse slot + setRowdata(Selection); // Use accessor + + // Update line numbers for this new row and all subsequent rows + for (int nIter = m_pMaintable->currentRow(); nIter < m_pMaintable->numRows(); nIter++) + m_pMaintable->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter).rightJustify(4, QChar('0'))); + + // Do basic data validation to warn against missing fields + for (int nIter = 0; nIter < nRows; nIter++) + this->validateRow(m_pMaintable->currentRow() + nIter, 0); + + m_pStatbar->message(QString::number(nRows) + trUtf8(" rows pasted"), 4000); + updEdit(m_pMaintable->currentRow()); // Reflect in the update controls + } + else // Well, I guess the user tried to paste an empty clipboard + m_pStatbar->message(trUtf8("The clipboard is empty"), 4000); +} + +// +// Append a blank row entry +// +void Titraqform::addEntry(int nRows) +{ + QTableSelection Select; // Highlighted text + int nTotal = 0; // Total row select + int nCurrent = 0; // Current row + std::auto_ptr pGuid(new AS::Uuid); // For GUID production + + // Decide how many rows to add + Select = m_pMaintable->selection(0); + if (nRows > 0) + nTotal = nRows; + else + nTotal = Select.bottomRow() - Select.topRow() + 1; + + // Optimize viewing by repainting cells only once after processing + m_pMaintable->setUpdatesEnabled(false); + + // 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); + m_pMaintable->setDirty(); // Set data to dirty state + m_pMaintable->setCurrentCell(Select.topRow(), m_pMaintable->currentColumn()); + + // According to Trolltech, insertRows() "clears the selection(s)". + // They are pretty wrong about that, so unfortunately we'll have to + // take care of the dirty work ourselves with a clearSelection(). + m_pMaintable->clearSelection(false); + m_pMaintable->selectRow(m_pMaintable->currentRow()); + + // Update relevant data fields for all new rows + for (int nIter = 0; nIter < nTotal; nIter++) { + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXSTATUS, QString(QChar('W'))); + m_pMaintable->setPixmap(Select.topRow() + nIter, TITRAQ_IDXSTATUS, QPixmap(s_kpcStatwarn_xpm)); + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXUSER, m_pPrefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER)); + pGuid->genId(); + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXGUID, pGuid->getString()); + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXCRC, "0"); // 0 = invalid entry + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXREV, "0"); // Entry not revised + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXDATE, QDate::currentDate().toString(Qt::ISODate)); + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXSTART, "00:00"); + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXFINISH, "00:00"); + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXAMOUNT, "00:00"); +// m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXTASK, "/"); +// m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXREMARK, "Remark"); + m_pMaintable->setText(Select.topRow() + nIter, TITRAQ_IDXCRC, "1"); // 0 = invalid entry + this->calcCrc(Select.topRow() + nIter, -1); + } + } + else { // Special case on last row add downwards + m_pMaintable->insertRows(Select.bottomRow() + 1, nTotal); + m_pMaintable->setDirty(); // Set data to dirty state + m_pMaintable->setCurrentCell(Select.bottomRow() + 1, m_pMaintable->currentColumn()); + + // According to Trolltech, insertRows() "clears the selection(s)". + // They are pretty wrong about that, so unfortunately we'll have to + // take care of the dirty work ourselves with a clearSelection(). + m_pMaintable->clearSelection(false); + m_pMaintable->selectRow(m_pMaintable->currentRow()); + + // Update relevant data fields for all new rows + for (int nIter = 1; nIter <= nTotal; nIter++) { + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXSTATUS, QString(QChar('W'))); + m_pMaintable->setPixmap(Select.bottomRow() + nIter, TITRAQ_IDXSTATUS, QPixmap(s_kpcStatwarn_xpm)); + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXUSER, m_pPrefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER)); + pGuid->genId(); + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXGUID, pGuid->getString()); + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXCRC, "0"); + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXREV, "0"); + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXDATE, QDate::currentDate().toString(Qt::ISODate)); + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXSTART, "00:00"); + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXFINISH, "00:00"); + m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXAMOUNT, "00:00"); +// m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXTASK, "/"); +// m_pMaintable->setText(Select.bottomRow() + nIter, TITRAQ_IDXREMARK, "Remark"); + this->calcCrc(Select.bottomRow() + nIter, -1); + } + } + + // Update line numbers for this new row and all subsequent rows + for (int nIter = m_pMaintable->currentRow(); nIter < m_pMaintable->numRows(); nIter++) + m_pMaintable->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter).rightJustify(4, QChar('0'))); + + updEdit(m_pMaintable->currentRow()); // Reflect in the update controls + m_pStatusedit->setPixmap(QPixmap(s_kpcStatwarn_xpm)); // Show pixmap + + m_pMaintable->setUpdatesEnabled(true); // Turn updates back on + m_pMaintable->repaintContents(true); // Do a general repaint of table + m_pMaintable->ensureCellVisible(m_pMaintable->currentRow() + nTotal - 1, m_pMaintable->currentColumn()); + m_pMaintable->ensureCellVisible(m_pMaintable->currentRow(), m_pMaintable->currentColumn()); + + // In case we added the first and only row entry, + // do post state adjustments like icon undimming + if (m_pMaintable->numRows() == 1) { + m_pDelrowact->setEnabled(true); + m_pRefreshact->setEnabled(true); + m_pCutact->setEnabled(true); + m_pCopyact->setEnabled(true); + + // Brighten all the edit controls also + m_pLineedit->setEnabled(true); + m_pUseredit->setEnabled(true); + m_pGuidedit->setEnabled(true); + m_pCrcedit->setEnabled(true); + m_pRevedit->setEnabled(true); + m_pDateedit->setEnabled(true); + m_pStarttime->setEnabled(true); + m_pEndtime->setEnabled(true); + m_pAmount->setEnabled(true); + m_pTasks->setEnabled(true); + m_pRemark->setEnabled(true); + + // And optionally the RPC actions, too +#if defined HAVE_MICO || defined HAVE_ESOAP + m_pSyncact->setEnabled(m_pPrefs->getBool(TITRAQ_PREFCORBON, TITRAQ_DEFCORBON) + | m_pPrefs->getBool(TITRAQ_PREFSOAPON, TITRAQ_DEFSOAPON)); +#endif // HAVE_MICO || defined HAVE_ESOAP + } +} + +// +// Delete a row entry +// +void Titraqform::delEntry(int nRows) +{ + QTableSelection Select = m_pMaintable->selection(0); // Highlighted text + int nTotal = Select.bottomRow() - Select.topRow() + 1; // Total row select + QMemArray Rowselect(nTotal); // Row array + + // Calculate rows to delete from selection highlight + for (int nIter = 0; nIter < nTotal; ++nIter) + Rowselect[nIter] = Select.topRow() + nIter; + + // Remove the row at selection and focus to the next row + if (m_pMaintable->currentRow() + 1 != m_pMaintable->numRows()) { + m_pMaintable->setCurrentCell(Select.bottomRow() + 1, m_pMaintable->currentColumn()); + m_pMaintable->removeRows(Rowselect); + m_pMaintable->setDirty(); // Set data to dirty state + } + else { // Special case to handle removing of only row or last row + m_pMaintable->removeRows(Rowselect); + m_pMaintable->setDirty(); // Set data to dirty state + } + + // Update line numbers for this new row and all subsequent rows + for (int nIter = m_pMaintable->currentRow(); nIter < m_pMaintable->numRows(); nIter++) + m_pMaintable->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter)); + + // In case we removed the last remaining row, + // do post state adjustments like icon dimming + if (m_pMaintable->numRows() <= 0) { + m_pDelrowact->setEnabled(false); + m_pRefreshact->setEnabled(false); + m_pCutact->setEnabled(false); + m_pCopyact->setEnabled(false); + + // Dim all the edit controls also + m_pStatusedit->setPixmap(s_kpcStatvoid_xpm); + m_pLineedit->setEnabled(false); + m_pUseredit->setEnabled(false); + m_pGuidedit->setEnabled(false); + m_pCrcedit->setEnabled(false); + m_pRevedit->setEnabled(false); + m_pDateedit->setEnabled(false); + m_pStarttime->setEnabled(false); + m_pEndtime->setEnabled(false); + m_pAmount->setEnabled(false); + m_pTasks->setEnabled(false); + m_pRemark->setEnabled(false); + + // And optionally dim the RPC actions +#if defined HAVE_MICO || defined HAVE_ESOAP + m_pSyncact->setEnabled(false); +#endif // HAVE_MICO || defined HAVE_ESOAP + } +} + +// +// Refresh the display of all data items +// +void Titraqform::refreshDisplay(void) +{ + int nIter = 0; // Matrix iterator + int nRows = m_pMaintable->numRows(); // Total number of rows + + // Sweep through matrix validating linewise + // data and updating line numbers for all rows + while (nIter < nRows) { + this->validateRow(nIter, 0); + m_pMaintable->setText(nIter, TITRAQ_IDXLINE, QString::number(nIter).rightJustify(4, QChar('0'))); + nIter++; + } + + m_pMaintable->repaintContents(false); // Do a general repaint of table + m_pStatbar->message(trUtf8("Display was refreshed"), 4000); // Announce result +} + +// +// Make and display a new document window +// +void Titraqform::newDoc(void) +{ + int nResult = 0; // Holds return value from save first messagebox + + // Check modification state of current data + if (m_pMaintable->isDirty()) { + nResult = QMessageBox::information(this, QString(TITRAQ_APPTITLE) + + ' ' + asgui_version.v_short, trUtf8(TITRAQ_SAVEFIRST), + trUtf8("&Save"), trUtf8("&Discard"), trUtf8("Cancel"), 0, 2); + + switch (nResult) { + case 0: // First button selected, so save first + this->saveFile(); // Save changes first + break; + case 1: // Second button selected, so don't save + break; + case 2: // Third button selected, so return sofort + default: + m_pStatbar->message(trUtf8("New aborted"), 4000); + return; + break; + } + } + + if (!m_pMaintable->isDirty() || nResult == 1) { // Check modification state + // Fall through to implicit new doc code + this->setCaption(trUtf8("No file name")); + m_pStatbar->message(trUtf8("New document"), 4000); + this->enableIface(true); // Enable the interface + m_pMaintable->setNumRows(0); // Remove all data in table + this->setFilename(""); // Signal a closed doc state + this->addEntry(1); // Default new op adds a row + m_pMaintable->setDirty(false); // Start out clean + } +} + +// +// Open and display an existing document +// +void Titraqform::openDoc(void) +{ + int nResult = 0; // Holds return value from save first messagebox + +// +// This block will guide the user to saving the contents of the timesheet +// before losing them in an open operation. The question and dialog box will +// not be raised if no open timesheet exists or if it was just serialized. +// + if (m_pMaintable->isDirty()) { // Check modification state + nResult = QMessageBox::information(this, QString(TITRAQ_APPTITLE) + + ' ' + asgui_version.v_short, trUtf8(TITRAQ_SAVEFIRST), + trUtf8("&Save"), trUtf8("&Discard"), trUtf8("Cancel"), 0, 2); + + switch (nResult) { + case 0: // Save first + this->saveFile(); // Save changes first + break; + case 1: // Don't save first but do load + break; + case 2: // Don't do a load timesheet + default: + m_pStatbar->message(trUtf8("Loading aborted"), 4000); + return; + break; + } + } + +// +// This block ensures that conditions of first block logic were met if +// applicable. If so, the user gives a file name to open or cancels the +// operation. The corresponding file will be opened, and if this is +// unsuccessful then the post state is exactly the same as the pre state. +// + if (!m_pMaintable->isDirty() || nResult == 1) { // Check modification state + // Make sure we correctly get the name of the default file to open + QString Openas = m_pPrefs->getString(TITRAQ_PREFASDIR, TITRAQ_DEFASDIR); + if (Openas.startsWith(TITRAQ_HOMEDIRTOK)) + Openas = QDir::homeDirPath() + Openas.remove(0, QString(TITRAQ_HOMEDIRTOK).length() - 1); + + // This dialog asks which file the user wants to open + QString Filestring = QFileDialog::getOpenFileName(Openas, + trUtf8("Accounting Data (*.as);;Text files (*.txt);;All Files (*)"), + this, trUtf8("ChooserDialog"), trUtf8("Choose a file to open"), NULL, false); + + // We might have a filename to work on, so do something with it + if (!Filestring.isEmpty()) { + QFile Filetemp(Filestring); // File to load + try { + if (Filetemp.exists() && validateData(Filetemp)) { // Be extra sure + setFilename(Filestring); // Set the new file name + m_pMaintable->setNumRows(0); // Clear out old data + m_pMaintable->setDirty(false); // Reset dirty flag + loadData(Filetemp); // Pass to helper method + this->setCaption(Filestring); // Caption in the titlebar + m_pStatbar->message(trUtf8("Loaded document ") + Filestring, 4000); + this->enableIface(true); // Turn on the lights + this->setOpen(true); // Indicate doc is open + } + } + catch (Genexcept& Genex) { // Crap, we failed + m_pStatbar->message(trUtf8("Loading failed"), 4000); + Genex.reportErr(); + return; + } + } + else // An empty filename returning from the file dialog means cancel + m_pStatbar->message(trUtf8("Loading aborted"), 4000); + } +} + +// +// Serialize current state to the current file +// +void Titraqform::saveFile(void) +{ + QString Fname; + Simplefile Filevents; + + try { + Fname = *this->getFilename(); + + // First time saves are really just saveName in disguise + if (Fname.isEmpty()) { + try { + this->saveName(); // Try to 'save as' + return; // and short circuit + } + catch (Genexcept& Genex) { +// Genex.reportErr(); // Report the error + return; // and short circuit + } + } + + Filevents.setName(Fname); // Construct a file to write + if (m_pPrefs->getBool(TITRAQ_PREFBAKON, TITRAQ_DEFBAKON)) + Filevents.makeBackup(); // Back up to filename.bak + this->saveData(Filevents); // Pass to helper method + } + catch (Genexcept& Genex) { + Genex.reportErr(); + } + // Reset and give output to main window + this->setCaption(Fname); + m_pStatbar->message(trUtf8("File %1 saved").arg(Fname), 4000); + m_pMaintable->setDirty(false); // Set the clean state to allow close +} + +// +// Serialize current state to a selected file +// +void Titraqform::saveAs(void) +{ + int nResult = 0; // For checking user's answer + + // Make sure we correctly get the name of the default file to open + QString Openas = m_pPrefs->getString(TITRAQ_PREFASDIR, TITRAQ_DEFASDIR); + if (Openas.startsWith(TITRAQ_HOMEDIRTOK)) + Openas = QDir::homeDirPath() + Openas.remove(0, QString(TITRAQ_HOMEDIRTOK).length() - 1); + + // And then get the name of the selected file to save to + QString Filestring = QFileDialog::getSaveFileName(Openas, trUtf8("Accounting Data (*.as);;Text files (*.txt);;All Files (*)"), this, trUtf8("ChooserDialog"), trUtf8("Choose a file to save"), NULL, false); + if (!Filestring.isEmpty()) { + if (QFile::exists(Filestring)) { + nResult = QMessageBox::warning(this, QString(TITRAQ_APPTITLE) + + ' ' + asgui_version.v_short, trUtf8(TITRAQ_OVERWRITE), + trUtf8("&Yes"), trUtf8("&No"), NULL, 1, 1); + switch (nResult) { + case 0: // Overwrite contents + this->setFilename(Filestring); + this->saveFile(); + break; + case 1: // Don't overwrite + default: + break; + } + } + else { + // Conditionally use a unique extension like '.as' if user prefers + if (m_pPrefs->getBool(TITRAQ_PREFEXTENDON, TITRAQ_DEFEXTENDON)) { + QString Extension = TITRAQ_FEXTENSION; // Logic to handle + if (!Filestring.endsWith(Extension)) // AS file extension + Filestring += Extension; // insertion + } + this->setFilename(Filestring); // Set filename of object first + this->saveFile(); // Finish by calling the save action + } + } + else + // User did not select a valid file and push okay button + m_pStatbar->message(trUtf8("Saving aborted"), 4000); +} + +// +// Implicitly serialize current state to a selected file +// The main difference with saveAs is that this uses exceptions +// +void Titraqform::saveName(void) +{ + int nResult = 0; // For checking user's answer + + // Make sure we correctly get the name of the default file to open + QString Openas = m_pPrefs->getString(TITRAQ_PREFASDIR, TITRAQ_DEFASDIR); + if (Openas.startsWith(TITRAQ_HOMEDIRTOK)) + Openas = QDir::homeDirPath() + Openas.remove(0, QString(TITRAQ_HOMEDIRTOK).length() - 1); + + nResult = 1; // We loop on this dialog only if an indecisive user + while (nResult > 0) { // is hesitant to overwrite a file over and over again + QString Filestring = QFileDialog::getSaveFileName(Openas, trUtf8("Accounting Data (*.as);;Text files (*.txt);;All Files (*)"), this, trUtf8("ChooserDialog"), trUtf8("Choose a file to save"), NULL, false); + if (!Filestring.isEmpty()) { + if (QFile::exists(Filestring)) { + nResult = QMessageBox::warning(this, QString(TITRAQ_APPTITLE) + + ' ' + asgui_version.v_short, trUtf8(TITRAQ_OVERWRITE), + trUtf8("&Yes"), trUtf8("&No"), NULL, 1, 1); + switch (nResult) { + case 0: // Overwrite contents + this->setFilename(Filestring); + this->saveFile(); + break; + case 1: // Don't overwrite + default: + break; + } + } + else { + + // Conditionally use a unique extension like '.as' if user prefers + if (m_pPrefs->getBool(TITRAQ_PREFEXTENDON, TITRAQ_DEFEXTENDON)) { + QString Extension = TITRAQ_FEXTENSION; // Logic to handle + if (!Filestring.endsWith(Extension)) // AS file extension + Filestring += Extension; // insertion + } + this->setFilename(Filestring); // Set filename of object first + nResult = 0; // Reset our loop control + this->saveFile(); // Finish by calling the save action + } + } + else { + // User did not select a valid file and push okay button + m_pStatbar->message(trUtf8("Saving aborted"), 4000); + throw Genexcept(TITRAQ_SAVECANCELLED); + } + } +} + +// +// Close current document, and then quit the application +// +void Titraqform::quitApp(void) +{ + int nResult = 0; + + if (m_pMaintable->isDirty()) { + nResult = QMessageBox::information(this, QString(TITRAQ_APPTITLE) + + ' ' + asgui_version.v_short, trUtf8(TITRAQ_SAVEFIRST), + trUtf8("&Save"), trUtf8("&Discard"), trUtf8("Cancel"), 0, 2); + + switch (nResult) { // Maybe save before closing + case 0: // Save first + this->saveFile(); // Save changes first + break; + case 1: // Don't save first + m_pMaintable->setDirty(false); + break; + case 2: // Do nothing + default: + return; // Go away without closing + break; + } + } + + // We should be clean now, but double check just in case + if (!m_pMaintable->isDirty()) + qApp->quit(); +} + +// +// Close current document, displaying in main window +// +void Titraqform::closeEvent(QCloseEvent *pClosit) +{ + int nResult = 0; + + if (!this->isOpen()) // Short circuit if user + qApp->quit(); // selects close twice + + // Check modification state of current data + if (m_pMaintable->isDirty()) { + nResult = QMessageBox::information(this, QString(TITRAQ_APPTITLE) + + ' ' + asgui_version.v_short, trUtf8(TITRAQ_SAVEFIRST), + trUtf8("&Save"), trUtf8("&Discard"), trUtf8("Cancel"), 0, 2); + + switch (nResult) { // Maybe save before closing + case 0: // Save first + this->saveFile(); // Save changes first + break; + case 1: // Don't save first + m_pMaintable->setDirty(false); + break; + case 2: // Do nothing + default: + pClosit->ignore(); + return; // Go away without closing + break; + } + } + + if (!m_pMaintable->isDirty()) { // Check again + // Fall through to implicit close code + this->setCaption(QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short); + try { // There might be problems, so wrap these last ops with error handling + QString Lightsout; // It's late, go to bed + if (this->isOpen()) + Lightsout = trUtf8("Closed document ") + *this->getFilename(); + this->setOpen(false); // Set doc state to closed + this->enableIface(false); // Turn off the lights + m_pStatbar->message(Lightsout, 4000); + } + catch (Genexcept& Genex) { + Genex.reportErr(); + } + } + pClosit->ignore(); // Finish off by not closing +} + +// +// Edit menu select all entries +// +void Titraqform::selAll(void) +{ + Prototype Unimp; + Unimp.doMbox(); +} + +// +// Edit a table entry in place, without the usual edit controls +// +void Titraqform::inplaceEdit(int nRow, int nCol, int nButton, const QPoint &Mousepos) +{ + // Table read only attribute must be reset here, so that editing can take + // place. Otherwise calls to editCell are ignored (for obvious reasons). + m_pMaintable->setReadOnly(false); + + // After editCell() is called, beginEdit() and endEdit() execute. The read + // only attribute is reset in endEdit() to return everything to normal. + m_pMaintable->editCell(nRow, nCol); + + m_pMaintable->setEdition(nCol); +} + +// +// Update the edit controls widget sizes +// +void Titraqform::updSizes(int nSection, int nOldsize, int nNewsize) +{ + switch (nSection) { + case TITRAQ_IDXALLCTRLS: + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXSTATUS) > 0) + m_pStatusedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXSTATUS) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXLINE) > 0) + m_pLineedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXLINE) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXUSER) > 0) + m_pUseredit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXUSER) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXGUID) > 0) + m_pGuidedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXGUID) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXCRC) > 0) + m_pCrcedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXCRC) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXREV) > 0) + m_pRevedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXREV) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXDATE) > 0) + m_pDateedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXDATE) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXSTART) > 0) + m_pStarttime->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXSTART) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXFINISH) > 0) + m_pEndtime->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXFINISH) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXAMOUNT) > 0) + m_pAmount->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXAMOUNT) - TITRAQ_SPACING); + if (m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXTASK) > 0) + m_pTasks->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXTASK) - TITRAQ_SPACING); +// if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXRCOL))) +// m_pRemark->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXREMARK) - TITRAQ_SPACING); + break; + case TITRAQ_IDXSTATUS: + m_pStatusedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXSTATUS) - TITRAQ_SPACING); + break; + case TITRAQ_IDXLINE: + m_pLineedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXLINE) - TITRAQ_SPACING); + break; + case TITRAQ_IDXUSER: + m_pUseredit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXUSER) - TITRAQ_SPACING); + break; + case TITRAQ_IDXGUID: + m_pGuidedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXGUID) - TITRAQ_SPACING); + break; + case TITRAQ_IDXCRC: + m_pCrcedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXCRC) - TITRAQ_SPACING); + break; + case TITRAQ_IDXREV: + m_pRevedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXREV) - TITRAQ_SPACING); + break; + case TITRAQ_IDXDATE: + m_pDateedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXDATE) - TITRAQ_SPACING); + break; + case TITRAQ_IDXSTART: + m_pStarttime->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXSTART) - TITRAQ_SPACING); + break; + case TITRAQ_IDXFINISH: + m_pEndtime->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXFINISH) - TITRAQ_SPACING); + break; + case TITRAQ_IDXAMOUNT: + m_pAmount->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXAMOUNT) - TITRAQ_SPACING); + break; + case TITRAQ_IDXTASK: + m_pTasks->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXTASK) - TITRAQ_SPACING); + break; + case TITRAQ_IDXREMARK: +// m_pRemark->setFixedWidth(nNewsize); + break; + default: + throw Genexcept("Unrecognized main window column header."); + break; + } + + // As a last and redundant step, adjust size of first visible control + switch(this->getFirstcol()) { + case TITRAQ_IDXSTATUS: + m_pStatusedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXSTATUS) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXLINE: + m_pLineedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXLINE) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXUSER: + m_pUseredit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXUSER) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXGUID: + m_pGuidedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXGUID) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXCRC: + m_pCrcedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXCRC) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXREV: + m_pRevedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXREV) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXDATE: + m_pDateedit->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXDATE) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXSTART: + m_pStarttime->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXSTART) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXFINISH: + m_pEndtime->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXFINISH) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXAMOUNT: + m_pAmount->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXAMOUNT) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + case TITRAQ_IDXTASK: + m_pTasks->setFixedWidth(m_pMaintable->horizontalHeader()->sectionSize(TITRAQ_IDXTASK) - TITRAQ_SPACING + TITRAQ_SPACING / 2); + break; + default: // Probably no columns are visible? + break; + } +} + +// +// What to do if a data cell is modified +// +void Titraqform::dataChanged(int nRow, int nCol) +{ + if (nCol != TITRAQ_IDXSTATUS && nCol != TITRAQ_IDXLINE) + m_pMaintable->setDirty(); // Mark this timesheet dirty, changes pending save +} + +// +// Convenience member calculates CRC for current row +// +void Titraqform::calcCrc(void) +{ + this->calcCrc(-1, -1); +} + +// +// Calculates CRC for the specified row, fires when data is changed +// +void Titraqform::calcCrc(int nRow, int nCol) +{ + if (nCol != TITRAQ_IDXSTATUS && nCol != TITRAQ_IDXLINE \ + && m_pMaintable->numRows() > 0) { + U32 Testcrc, Valcrc; + QString Crcstr; + std::auto_ptrpWholerow(new Qualistring); + int nRealrow = -1; + + // Build the data that will be used in testing CRC calculation + nRealrow = (nRow >= 0) ? nRow : m_pMaintable->currentRow(); + *pWholerow = m_pMaintable->text(nRealrow, TITRAQ_IDXUSER); + for (int nIter = TITRAQ_IDXUSER + 1; nIter < TITRAQ_IDXTAIL; nIter++) + if (nIter != TITRAQ_IDXCRC) // Don't checksum the checksum! + *pWholerow += m_pMaintable->text(nRealrow, nIter); + + // Update the checksum and revision only if necessary + Testcrc = pWholerow->getCrc(); + + // FIXME: This thing is not very unportable, because toUInt != U32 + if (Testcrc != m_pMaintable->text(nRealrow, TITRAQ_IDXCRC).toUInt()) { + +// // Bump the revision number of our entry to control conflicts +// nNewrev = m_pMaintable->text(nRealrow, TITRAQ_IDXREV).toInt() + 1; +// m_pMaintable->setText(nRealrow, TITRAQ_IDXREV, QString::number(nNewrev)); + + // Build the data that will be used in setting CRC calculation + *pWholerow = m_pMaintable->text(nRealrow, TITRAQ_IDXUSER); + for (int nIter = TITRAQ_IDXUSER + 1; nIter < TITRAQ_IDXTAIL; nIter++) + if (nIter != TITRAQ_IDXCRC) // Don't checksum the checksum! + *pWholerow += m_pMaintable->text(nRealrow, nIter); + + Valcrc = pWholerow->getCrc(); // Finally set the checksum to its new value + Crcstr = QString::number(Valcrc, 16).rightJustify(8, '0'); + m_pMaintable->setText(nRealrow, TITRAQ_IDXCRC, "0x" + Crcstr); + m_pCrcedit->setText("0x" + Crcstr); + } + } +} + +// +// Gets a hit on every table click +// +void Titraqform::onClick(int nRow, int nCol, int nButton, const QPoint &Mousepos) +{ + // Give the clueless user some hints when clicking an empty timesheet + if (m_pMaintable->numRows() <= 0) + m_pStatbar->message(trUtf8("Empty timesheet, add entries first please"), 2000); +} + +// +// Update the edit controls contents +// +void Titraqform::updEdit(int nRow, int nCol) +{ + // Why is the app sending negative row signal? I don't know yet, + // so add in this nasty hack to fend off the debug spew on stderr + if (m_pMaintable->numRows() > 0 && nRow >= 0) { + // Field strings to check for validity and process + QString Textline(m_pMaintable->text(nRow, TITRAQ_IDXLINE)); + QString Textuser(m_pMaintable->text(nRow, TITRAQ_IDXUSER)); + QString Textguid(m_pMaintable->text(nRow, TITRAQ_IDXGUID)); + QString Textcrc(m_pMaintable->text(nRow, TITRAQ_IDXCRC)); + QString Textrev(m_pMaintable->text(nRow, TITRAQ_IDXREV)); + QString Textdate(m_pMaintable->text(nRow, TITRAQ_IDXDATE)); + QString Textstart(m_pMaintable->text(nRow, TITRAQ_IDXSTART)); + QString Textfinish(m_pMaintable->text(nRow, TITRAQ_IDXFINISH)); + QString Textamount(m_pMaintable->text(nRow, TITRAQ_IDXAMOUNT)); + QString Texttask(m_pMaintable->text(nRow, TITRAQ_IDXTASK)); + QString Textremark(m_pMaintable->text(nRow, TITRAQ_IDXREMARK)); + + // Reset the edition state member + m_pMaintable->setEdition(); + + // Set text of member edit controls + if (m_pMaintable->text(nRow, TITRAQ_IDXSTATUS).isEmpty()) // If row is empty + m_pStatusedit->setPixmap(s_kpcStatvoid_xpm); // add a placeholder + else + m_pStatusedit->setPixmap(m_pMaintable->pixmap(nRow, TITRAQ_IDXSTATUS)); + m_pLineedit->setText(Textline); + m_pUseredit->setText(Textuser); + m_pGuidedit->setText(Textguid); + m_pCrcedit->setText(Textcrc); + m_pRevedit->setText(Textrev); + +// QRegExp Shorten("/(\\w+)$"); // For stripping prefix off the current task +// Texttask.remove(0, Shorten.search(Texttask) + 1); // Strip leading slash + + m_pRemark->setText(Textremark); + m_pTasks->setCurrentText(Texttask); + + // Date field not suitable for empty string text + if (Textdate == ".") + m_pDateedit->setDate(QDate::currentDate()); + else if (Textdate.isEmpty()) + m_pDateedit->setDate(QDate::fromString("0000-00-00", Qt::ISODate)); + else + m_pDateedit->setDate(QDate::fromString(Textdate, Qt::ISODate)); + + // Start time not suitable for empty string text + if (Textstart == ".") + m_pStarttime->setTime(QTime::currentTime()); + else if (Textstart.isEmpty()) + m_pStarttime->setTime(QTime::QTime(0, 0)); + else + m_pStarttime->setTime(QTime::fromString(Textstart, Qt::ISODate)); + + // Finish time not suitable for empty string text + if (Textfinish == ".") + m_pEndtime->setTime(QTime::currentTime()); + else if (Textfinish.isEmpty()) + m_pEndtime->setTime(QTime::QTime(0, 0)); + else + m_pEndtime->setTime(QTime::fromString(Textfinish, Qt::ISODate)); + + // Amount time not suitable for empty string text + if (Textamount == ".") { + int nDifference = m_pStarttime->time().secsTo(m_pEndtime->time()); + m_pAmount->setTime(QTime(0, 0).addSecs(nDifference)); + } + else if (Textamount.isEmpty()) + m_pAmount->setTime(QTime::QTime(0, 0)); + else + m_pAmount->setTime(QTime::fromString(Textamount, Qt::ISODate)); + } +} + +// +// Validate current row of the matrix +// +void Titraqform::validateRow(void) +{ + this->validateRow(-1, -1); +} + +// +// Validate specified row of the matrix +// +void Titraqform::validateRow(int nRow, int nCol) +{ + int nRealrow = -1; + + if (!this->isOpen()) { // If no data is loaded then short circuit + m_pStatbar->message(trUtf8("Timesheet contains no data"), 4000); + return; + } + + nRealrow = (nRow >= 0) ? nRow : m_pMaintable->currentRow(); + QString Statis = m_pMaintable->text(nRealrow, TITRAQ_IDXSTATUS); // Get text + + // Review whole data validity, and set pixmap accordingly + if (m_pMaintable->text(nRealrow, TITRAQ_IDXUSER).isEmpty() || + m_pMaintable->text(nRealrow, TITRAQ_IDXGUID).isEmpty() || + m_pMaintable->text(nRealrow, TITRAQ_IDXCRC).isEmpty() || + m_pMaintable->text(nRealrow, TITRAQ_IDXREV).isEmpty() || + m_pMaintable->text(nRealrow, TITRAQ_IDXDATE).isEmpty() || + m_pMaintable->text(nRealrow, TITRAQ_IDXSTART).isEmpty() || + m_pMaintable->text(nRealrow, TITRAQ_IDXFINISH).isEmpty() || + m_pMaintable->text(nRealrow, TITRAQ_IDXAMOUNT).isEmpty() || + m_pMaintable->text(nRealrow, TITRAQ_IDXTASK).isEmpty()) + { // No K&R style to show where actual code begins + if (Statis.startsWith(QString("W"))) { // Conditionally set pixmap to avoid overhead +// FIXME: Next line commented out, and I see that this algorythm needs help +// m_pStatusedit->setPixmap(m_pMaintable->pixmap(nRealrow, TITRAQ_IDXSTATUS)); + } + else if (!Statis.startsWith(QString("E"))) { // Conditionally set pixmap to avoid overhead + m_pMaintable->setText(nRealrow, TITRAQ_IDXSTATUS, Statis.replace(TITRAQ_IDXSTATERROR, sizeof(char), 'E')); + m_pMaintable->setPixmap(nRealrow, TITRAQ_IDXSTATUS, QPixmap(s_kpcStaterror_xpm)); + m_pStatusedit->setPixmap(m_pMaintable->pixmap(nRealrow, TITRAQ_IDXSTATUS)); + } + } + else { + if (!Statis.startsWith(QString("O"))) { // Conditionally set pixmap to avoid overhead + m_pMaintable->setText(nRealrow, TITRAQ_IDXSTATUS, Statis.replace(TITRAQ_IDXSTATERROR, sizeof(char), 'O')); + m_pMaintable->setPixmap(nRealrow, TITRAQ_IDXSTATUS, QPixmap(s_kpcStatokay_xpm)); + m_pStatusedit->setPixmap(m_pMaintable->pixmap(nRealrow, TITRAQ_IDXSTATUS)); + } + } + + // Test for blank user field, and set to default if so + if (m_pMaintable->text(nRealrow, TITRAQ_IDXUSER).isEmpty()) + m_pMaintable->setText(nRealrow, TITRAQ_IDXUSER, m_pPrefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER)); + + // Test for blank date field, and set to default if so + if (m_pMaintable->text(nRealrow, TITRAQ_IDXDATE) == ".") + m_pMaintable->setText(nRealrow, TITRAQ_IDXDATE, QDate::currentDate().toString(Qt::ISODate)); + + // Test for blank start field, and set to default if so + if (m_pMaintable->text(nRealrow, TITRAQ_IDXSTART) == ".") + m_pMaintable->setText(nRealrow, TITRAQ_IDXSTART, QTime::currentTime().toString("hh:mm")); + + // Test for blank finish field, and set to default if so + if (m_pMaintable->text(nRealrow, TITRAQ_IDXFINISH) == ".") + m_pMaintable->setText(nRealrow, TITRAQ_IDXFINISH, QTime::currentTime().toString("hh:mm")); + + // Test for blank amount field, and set to default if so + if (m_pMaintable->text(nRealrow, TITRAQ_IDXAMOUNT) == ".") { + QTime Begin = QTime::fromString(m_pMaintable->text(nRealrow, TITRAQ_IDXSTART), Qt::ISODate); + QTime End = QTime::fromString(m_pMaintable->text(nRealrow, TITRAQ_IDXFINISH), Qt::ISODate); + QString Diff = QTime(0, 0).addSecs(Begin.secsTo(End)).toString("hh:mm"); + m_pMaintable->setText(nRealrow, TITRAQ_IDXAMOUNT, Diff); + } +} + +// +// Update the current line number column item +// +void Titraqform::updateLine(const QString &Instring) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXLINE, Instring); +} + +// +// Update the current user column item +// +void Titraqform::updateUser(const QString &Instring) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXUSER, Instring); +} + +// +// Update the current GUID column item +// +void Titraqform::updateGuid(const QString &Instring) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXGUID, Instring); +} + +// +// Update the current CRC column item +// +void Titraqform::updateCrc(const QString &Instring) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXCRC, Instring); +} + +// +// Update the current rev column item +// +void Titraqform::updateRev(const QString &Instring) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXREV, Instring); +} + +// +// Update the current date column item +// +void Titraqform::updateDate(const QDate &Dateup) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXDATE, Dateup.toString(Qt::ISODate)); +} + +// +// Update the current start column item +// +void Titraqform::updateStart(const QTime &Startup) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXSTART, Startup.toString("hh:mm")); +} + +// +// Update the current finish column item +// +void Titraqform::updateFinish(const QTime &Finishup) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXFINISH, Finishup.toString("hh:mm")); +} + +// +// Update the current amount column item +// +void Titraqform::updateAmount(const QTime &Amountup) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXAMOUNT, Amountup.toString("hh:mm")); +} + +// +// Update the current task column item +// +void Titraqform::updateTask(const QString &Taskup) +{ +// // FIXME: Broken +// RtTableItem *pTask = NULL; +// pTask = static_cast(m_pMaintable->item(m_pMaintable->currentRow(), TITRAQ_IDXTASK)); +// pTask->setText(Taskup); + + // Don't try to use the Taskup string, because it ignores autocompletion + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXTASK, m_pTasks->currentText()); +} + +// +// Update the current remark column item +// +void Titraqform::updateRemark(const QString &Remarkup) +{ + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXREMARK, Remarkup); +} + +// +// Confirm any recent editions on a whole row +// +void Titraqform::confirmEdit(void) +{ + RtTableItem *pTask = NULL; // Task item is a derived class + + // Conversions from edit control data formats to native tabular format + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXDATE, m_pDateedit->date().toString(Qt::ISODate)); + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXSTART, m_pStarttime->time().toString(Qt::ISODate)); + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXFINISH, m_pEndtime->time().toString(Qt::ISODate)); + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXAMOUNT, m_pAmount->time().toString(Qt::ISODate)); + + // Specially handle task fields + pTask = static_cast(m_pMaintable->item(m_pMaintable->currentRow(), TITRAQ_IDXTASK)); + pTask->setText(m_pTasks->currentText()); + + m_pMaintable->setText(m_pMaintable->currentRow(), TITRAQ_IDXREMARK, m_pRemark->text()); +} + +// +// Edit menu configure preferences +// +void Titraqform::configPrefs(void) +{ + QString Templine; // Used for preferences resetting + Prefpanel *pUserpanel = NULL; // The user preferences panel itself + + // Create a new preferences panel window + pUserpanel = new Prefpanel(this, "Userprefpanel"); + connect(pUserpanel, SIGNAL(applied(void)), SLOT(applyPrefs(void))); + + // Set default values to appear in initialized panel widgets + pUserpanel->setAccounts(m_pPrefs->getString(TITRAQ_PREFACCOUNTS, TITRAQ_DEFACCOUNTS)); + pUserpanel->setEvents(m_pPrefs->getString(TITRAQ_PREFASDIR, TITRAQ_DEFASDIR)); + pUserpanel->setUser(m_pPrefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER)); + pUserpanel->setHome(m_pPrefs->getString(TITRAQ_PREFHOME, TITRAQ_DEFHOME)); + pUserpanel->setCorbahost(m_pPrefs->getString(TITRAQ_PREFCORBHOST, TITRAQ_DEFCORBHOST)); + pUserpanel->setSoaphost(m_pPrefs->getString(TITRAQ_PREFSOAPHOST, TITRAQ_DEFSOAPHOST)); +#ifdef HAVE_MICO + pUserpanel->setCorbaon(m_pPrefs->getBool(TITRAQ_PREFCORBON, TITRAQ_DEFCORBON)); +#else + pUserpanel->setCorbaon(false); + pUserpanel->lockCorba(); +#endif +#ifdef HAVE_ESOAP + pUserpanel->setSoapon(m_pPrefs->getBool(TITRAQ_PREFSOAPON, TITRAQ_DEFSOAPON)); +#else + pUserpanel->setSoapon(false); + pUserpanel->lockSoap(); +#endif + pUserpanel->setBackon(m_pPrefs->getBool(TITRAQ_PREFBAKON, TITRAQ_DEFBAKON)); + pUserpanel->setExtendon(m_pPrefs->getBool(TITRAQ_PREFEXTENDON, TITRAQ_DEFEXTENDON)); + pUserpanel->setDetailon(m_pPrefs->getBool(TITRAQ_PREFDETAILON, TITRAQ_DEFDETAILON)); + pUserpanel->setSignaton(m_pPrefs->getBool(TITRAQ_PREFSIGNATON, TITRAQ_DEFSIGNATON)); + + // Set default style which can be more complicated due to mapping... + switch (m_pPrefs->getNumber(TITRAQ_PREFSTYLE, TITRAQ_STYLECDE)) { + case TITRAQ_STYLECDE: + pUserpanel->setStyle(TITRAQ_STRCDE); + break; + case TITRAQ_STYLESGI: + pUserpanel->setStyle(TITRAQ_STRSGI); + break; + case TITRAQ_STYLEMOTIF: + pUserpanel->setStyle(TITRAQ_STRMOTIF); + break; + case TITRAQ_STYLEMPLUS: + pUserpanel->setStyle(TITRAQ_STRMPLUS); + break; + case TITRAQ_STYLEPLAT: + pUserpanel->setStyle(TITRAQ_STRPLAT); + break; + case TITRAQ_STYLEMSOFT: + pUserpanel->setStyle(TITRAQ_STRMSOFT); + break; + default: + pUserpanel->setStyle(TITRAQ_STRCDE); // My personal favourite ;-) + break; + } + + // Colour preferences + int nRed, nGreen, nBlue; + QColorGroup Origcolour, Altcolour; + const QColor Origlight = QColor(TITRAQ_DEFLIGHTRED, TITRAQ_DEFLIGHTGREEN, TITRAQ_DEFLIGHTBLUE); + const QColor Origdark = QColor(TITRAQ_DEFDARKRED, TITRAQ_DEFDARKGREEN, TITRAQ_DEFDARKBLUE); + const QColor Altlight = QColor(TITRAQ_DEFLTALTRED, TITRAQ_DEFLTALTGREEN, TITRAQ_DEFLTALTBLUE); + const QColor Altdark = QColor(TITRAQ_DEFDKALTRED, TITRAQ_DEFDKALTGREEN, TITRAQ_DEFDKALTBLUE); + + // Set colours to revert to if user screws up and wants out + Origcolour.setColor(QColorGroup::Foreground, Origlight); + Origcolour.setColor(QColorGroup::Background, Origdark); + pUserpanel->setOrigcolour(&Origcolour); + Altcolour.setColor(QColorGroup::Foreground, Altlight); + Altcolour.setColor(QColorGroup::Background, Altdark); + pUserpanel->setAltcolour(&Altcolour); + + // Set colour preferences saved from last session + nRed = m_pPrefs->getNumber(TITRAQ_PREFLIGHTRED, TITRAQ_DEFLIGHTRED); + nGreen = m_pPrefs->getNumber(TITRAQ_PREFLIGHTGREEN, TITRAQ_DEFLIGHTGREEN); + nBlue = m_pPrefs->getNumber(TITRAQ_PREFLIGHTBLUE, TITRAQ_DEFLIGHTBLUE); + const QColor Lightshade = QColor(nRed, nGreen, nBlue); + pUserpanel->setLight(&Lightshade); + nRed = m_pPrefs->getNumber(TITRAQ_PREFDARKRED, TITRAQ_DEFDARKRED); + nGreen = m_pPrefs->getNumber(TITRAQ_PREFDARKGREEN, TITRAQ_DEFDARKGREEN); + nBlue = m_pPrefs->getNumber(TITRAQ_PREFDARKBLUE, TITRAQ_DEFDARKBLUE); + const QColor Darkshade = QColor(nRed, nGreen, nBlue); + pUserpanel->setDark(&Darkshade); + + // Modal panel handler + if (pUserpanel->exec() == QDialog::Accepted) + this->applyPrefs(pUserpanel); + + // Dispose Panel object + delete pUserpanel; +} + +// +// View menu normal +// +void Titraqform::normalView(void) +{ + // All view types except normal are disabled until implemention, so + // this body can remain empty, causing nothing to happen on selection. +} + +// +// View menu editing +// +void Titraqform::editingView(void) +{ + // All view types except normal are disabled until implemention, so + // this body can remain empty, causing nothing to happen on selection. +} + +// +// View menu timing +// +void Titraqform::timingView(void) +{ + // All view types except normal are disabled until implemention, so + // this body can remain empty, causing nothing to happen on selection. +} + +// +// View menu show file toolbar +// +void Titraqform::showFilebar(void) +{ + if (m_pFiletools->isVisible()) { + m_pFiletools->hide(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXFILEBAR), false); + } + else { + m_pFiletools->show(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXFILEBAR), true); + } +} + +// +// View menu show edit toolbar +// +void Titraqform::showEditbar(void) +{ + if (m_pEdittools->isVisible()) { + m_pEdittools->hide(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXEDITBAR), false); + } + else { + m_pEdittools->show(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXEDITBAR), true); + } +} + +// +// View menu show view toolbar +// +void Titraqform::showViewbar(void) +{ + if (m_pViewtools->isVisible()) { + m_pViewtools->hide(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXVIEWBAR), false); + } + else { + m_pViewtools->show(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXVIEWBAR), true); + } +} + +// +// View menu show prefs toolbar +// +void Titraqform::showPrefsbar(void) +{ + if (m_pPrefstools->isVisible()) { + m_pPrefstools->hide(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXPREFBAR), false); + } + else { + m_pPrefstools->show(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXPREFBAR), true); + } +} + +// +// View menu show whats this toolbar +// +void Titraqform::showWhatsbar(void) +{ + if (m_pWhatstools->isVisible()) { + m_pWhatstools->hide(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXWHATBAR), false); + } + else { + m_pWhatstools->show(); + m_pTbarspopup->setItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXWHATBAR), true); + } +} + +// +// View menu show status column +// +void Titraqform::showStatcol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXSTATCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXSTATUS); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXSTATCOL), false); + m_pStatusedit->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXSTATUS); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXSTATCOL), true); + m_pStatusedit->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXSTATCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show line numbers column +// +void Titraqform::showLinecol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXLCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXLINE); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXLCOL), false); + m_pLineedit->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXLINE); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXLCOL), true); + m_pLineedit->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXLCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show users column +// +void Titraqform::showUsercol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXUCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXUSER); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXUCOL), false); + m_pUseredit->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXUSER); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXUCOL), true); + m_pUseredit->show(); + } + + // Make sure switch take place right away and sizes are handled + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXUCOL)); +} + +// +// View menu show GUIDs column +// +void Titraqform::showGuidcol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXGCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXGUID); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXGCOL), false); + m_pGuidedit->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXGUID); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXGCOL), true); + m_pGuidedit->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXGCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show CRC column +// +void Titraqform::showCrccol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXCCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXCRC); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXCCOL), false); + m_pCrcedit->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXCRC); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXCCOL), true); + m_pCrcedit->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXCCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show Rev column +// +void Titraqform::showRevcol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXREVCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXREV); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXREVCOL), false); + m_pRevedit->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXREV); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXREVCOL), true); + m_pRevedit->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXREVCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show dates column +// +void Titraqform::showDatecol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXDCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXDATE); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXDCOL), false); + m_pDateedit->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXDATE); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXDCOL), true); + m_pDateedit->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXDCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show start time column +// +void Titraqform::showStartcol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXSTARTCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXSTART); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXSTARTCOL), false); + m_pStarttime->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXSTART); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXSTARTCOL), true); + m_pStarttime->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXSTARTCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show finish time column +// +void Titraqform::showFinishcol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXFCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXFINISH); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXFCOL), false); + m_pEndtime->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXFINISH); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXFCOL), true); + m_pEndtime->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXFCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show Amounts column +// +void Titraqform::showAmountcol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXACOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXAMOUNT); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXACOL), false); + m_pAmount->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXAMOUNT); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXACOL), true); + m_pAmount->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXACOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show tasks column +// +void Titraqform::showTaskcol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXTCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXTASK); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXTCOL), false); + m_pTasks->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXTASK); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXTCOL), true); + m_pTasks->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXTCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// View menu show Remarks column +// +void Titraqform::showRemarkcol(void) +{ + // Test if column is currently shown, conditionally show or hide it + if (m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXREMCOL))) { + m_pMaintable->hideColumn(TITRAQ_IDXREMARK); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXREMCOL), false); + m_pRemark->hide(); + } + else { + m_pMaintable->showColumn(TITRAQ_IDXREMARK); + m_pColspopup->setItemChecked(m_pColspopup->idAt(TITRAQ_IDXREMCOL), true); + m_pRemark->show(); + } + + // Make sure switch take place right away and sizes are handled + m_pColspopup->updateItem(m_pColspopup->idAt(TITRAQ_IDXREMCOL)); + this->updSizes(TITRAQ_IDXALLCTRLS, 0, 0); // Update size of this and next +} + +// +// Generate a local formatted report +// +void Titraqform::genReport(void) +{ + try { // Create and execute a new local report window + std::auto_ptr pReport(new AS::Reportpanel + (m_pMaintable, m_pPrefs, this, "Locreportpanel")); + pReport->exec(); + delete pReport.release(); // Technically unnecessary, smart pointer + } + catch (Genexcept& Genex) { + Genex.reportErr(); + return; + } +} + +// +// Syncronize data with server using IIOP +// +void Titraqform::syncIiop(void) +{ +#ifdef HAVE_MICO + // Short circuit if user has disabled CORBA transmission in prefs + if (!m_pPrefs->getBool(TITRAQ_PREFCORBON, TITRAQ_DEFCORBON)) + return; + + char **ppcInargv = NULL; // Parameters to the ORB + CORBA::ORB_var Orb; // The ORB iself + + CORBA::Object_var Nameobj; // Name service reference + CosNaming::NamingContext_var Namectx; // COSS ns context + CosNaming::Name Cosname; // Our requested obj name + + CORBA::Object_var Objcaster; // Generic CORBA object + Asdatabase_var Asdbase; // Casted object to ASDB + Astuple Singlerow; // A single row of AS data + + QString *pOrbargv = new QString(TITRAQ_ORBINIT); + int nCount = pOrbargv->contains(' '); + int nNamesize = 0; + + // Build a false incoming argv with which we initialize the ORB + ppcInargv = new char *[nCount + 3]; // 3 = arg0 + last section + COSS host + *ppcInargv = new char[strlen(*qApp->argv() + 2)]; // For cmd name + strcpy(ppcInargv[0], *qApp->argv()); // Copy cmd name + for (int nIter = 0; nIter <= nCount; nIter++) { + QString Section = pOrbargv->section(' ', nIter, nIter); + ppcInargv[nIter + 1] = new char[strlen(Section.ascii() + 2)]; + strcpy(ppcInargv[nIter + 1], Section.ascii()); + } + + // Build the single string COSS naming host name with associated port number + *pOrbargv = TITRAQ_COSSPART1 + + m_pPrefs->getString(TITRAQ_PREFCORBHOST, TITRAQ_DEFCORBHOST) + + TITRAQ_COSSPART2; + nNamesize = strlen(pOrbargv->ascii()); + ppcInargv[nCount + 2] = new char[nNamesize]; + strcpy(ppcInargv[nCount + 2], pOrbargv->ascii()); + + try { + // Initialization of the ORB and COSS naming service + nCount = nCount + 3; // Raise the count to include app, last sec, COSS + Orb = CORBA::ORB_init(nCount, ppcInargv, "mico-local-orb"); + Nameobj = Orb->resolve_initial_references("NameService"); + Namectx = CosNaming::NamingContext::_narrow(Nameobj); + if (CORBA::is_nil(Namectx)) { // Verify sanity + m_pStatbar->message(trUtf8("Could not find the COSS naming service")); + qWarning("Could not find the COSS naming service\n"); + } + + // Clean up our dynamically allocated array + for (int nIter = 0; nIter < nCount; nIter++) + delete ppcInargv[nIter]; + delete ppcInargv; // Free the array itself + delete pOrbargv; // Free the intermediate string + + // Prepare the COSS name request + Cosname.length(1); + Cosname[0].id = CORBA::string_dup("Asdatabase"); + Cosname[0].kind = CORBA::string_dup(""); + + try { // Resolve to a CORBA object + Objcaster = Namectx->resolve(Cosname); + } + catch (CosNaming::NamingContext::NotFound &Cossex) { + m_pStatbar->message(trUtf8("NotFound exception thrown")); + qWarning("NotFound exception thrown\n"); + return; + } + catch (CosNaming::NamingContext::CannotProceed &Cossex) { + m_pStatbar->message(trUtf8("CannotProceed exception thrown")); + qWarning("CannotProceed exception thrown\n"); + return; + } + catch (CosNaming::NamingContext::InvalidName &Cossex) { + m_pStatbar->message(trUtf8("InvalidName exception thrown")); + qWarning("InvalidName exception thrown\n"); + return; + } + + // Cast the generic CORBA object to a AS database type + Asdbase = Asdatabase::_narrow(Objcaster); + if (CORBA::is_nil(Asdbase)) { // Verify sanity + m_pStatbar->message(trUtf8("Could not find the AS database")); + qWarning("Could not find the AS database\n"); + return; + } + + // Open an account object on the remote server + Account_var Account = Asdbase->Open("/tmp/events.as"); + if (CORBA::is_nil(Account)) { // Verify sanity + m_pStatbar->message(trUtf8("Could not create an account object on the server")); + qWarning("Could not create an account object on the server\n"); + return; + } + + // Fill account log object(s) to marshall and transmit + int nRow = m_pMaintable->currentRow(); + QTableSelection Select = m_pMaintable->selection(0); // Capture selected rows + int nTotal = Select.bottomRow() - Select.topRow() + 1; // Total rows selected + + // Remember, CORBA::stri_dup creates smart pointers + for (int nIter = 0; nIter < nTotal; nIter++) { + Singlerow.szUser = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXUSER)); + Singlerow.szGuid = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXGUID)); + Singlerow.szCrc = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXCRC).remove("0x")); + Singlerow.szRev = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXREV)); + Singlerow.szDate = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXDATE)); + Singlerow.szStart = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXSTART)); + Singlerow.szFinish = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXFINISH)); + Singlerow.szAmount = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXAMOUNT)); +// Singlerow.nRev = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXREV).toUInt(); +// Singlerow.nDate = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXDATE).toUInt(); +// Singlerow.nStart = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXSTART).toUInt(); +// Singlerow.nFinish = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXFINISH).toUInt(); +// Singlerow.nAmount = m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXAMOUNT).toUInt(); + Singlerow.szTask = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXTASK)); + Singlerow.szRemark = CORBA::string_dup(m_pMaintable->text(Select.topRow() + nIter, TITRAQ_IDXREMARK)); + Account->Log(Singlerow); // Finally transmit to server + } + + m_pStatbar->message(trUtf8("Successful transmission of accounting data")); + } + catch (const CORBA::Exception &Corbex) { + m_pStatbar->message(trUtf8("Caught CORBA exception: %1").arg(Corbex._repoid())); + qWarning("Caught CORBA exception: %s", Corbex._repoid()); + } + catch (...) { + qWarning("Caught unknown exception\n"); + } +#endif // HAVE_MICO +} + +// +// Syncronize data with server using SOAP +// +void Titraqform::syncSoap(void) +{ +#ifdef HAVE_ESOAP + // Short circuit if user has disabled SOAP transmission in prefs + if (!m_pPrefs->getBool(TITRAQ_PREFSOAPON, TITRAQ_DEFSOAPON)) + return; + + USING_EASYSOAP_NAMESPACE + + try { + SOAPMethod Logmeth("Log", TITRAQ_SOAPSPACE); // SOAP namespace + SOAPString Clistr; // Outgoing parameter to marshall + int nCrc; // SOAP unmarshalled return value + + // Build the single string SOAP end point which look like this: + // "http://www.europalab.com/cgi-bin/asdbserv" + QString Endpoint; + Endpoint = TITRAQ_PREFIXHTTP + m_pPrefs->getString(TITRAQ_PREFSOAPHOST, TITRAQ_DEFSOAPHOST); + SOAPProxy Proxy(Endpoint.ascii()); + + // Fill account log object(s) to marshall and transmit + QTableSelection Select = m_pMaintable->selection(0); // Capture selected rows + int nTotal = Select.bottomRow() - Select.topRow() + 1; // Total rows selected + + // Iterate through the selection of row entries to transmit + for (int nRowiter = 0; nRowiter < nTotal; nRowiter++) { + QString Syncthis = m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXUSER); + Syncthis += ' ' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXGUID); + Syncthis += ' ' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXCRC).remove("0x"); + Syncthis += ' ' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXREV); + Syncthis += ' ' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXDATE); + Syncthis += ' ' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXSTART); + Syncthis += ' ' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXFINISH); + Syncthis += ' ' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXAMOUNT); + Syncthis += ' ' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXTASK); + Syncthis += ' ' + ('"' + m_pMaintable->text(Select.topRow() + nRowiter, TITRAQ_IDXREMARK)) + '"'; + Clistr = Syncthis; // Build RPC parameter + Logmeth.AddParameter("Tuple") << Clistr; // Prepare for marshalling + const SOAPResponse &Logresp = Proxy.Execute(Logmeth); + Logresp.GetReturnValue() >> nCrc; + } + m_pStatbar->message(trUtf8("Successful transmission, CRC returned %1").arg(nCrc)); + } + catch (SOAPException& Soapex) { // Announce the exception we received + m_pStatbar->message(trUtf8("Caught SOAP exception: %1").arg(Soapex.What().Str())); + qDebug("Caught SOAP exception: %s", Soapex.What().Str()); + } + catch (...) { + qDebug("Caught unknown exception\n"); + } +#endif // HAVE_ESOAP +} + +// +// Save user preferences +// +void Titraqform::savePrefs(void) +{ + // Get check status from column menu and pass it to prefs handler + m_pPrefs->setBool(TITRAQ_PREFSTATCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXSTATCOL))); + m_pPrefs->setBool(TITRAQ_PREFLCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXLCOL))); + m_pPrefs->setBool(TITRAQ_PREFUCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXUCOL))); + m_pPrefs->setBool(TITRAQ_PREFGCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXGCOL))); + m_pPrefs->setBool(TITRAQ_PREFCCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXCCOL))); + m_pPrefs->setBool(TITRAQ_PREFREVCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXREVCOL))); + m_pPrefs->setBool(TITRAQ_PREFDCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXDCOL))); + m_pPrefs->setBool(TITRAQ_PREFSTARTCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXSTARTCOL))); + m_pPrefs->setBool(TITRAQ_PREFFCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXFCOL))); + m_pPrefs->setBool(TITRAQ_PREFACOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXACOL))); + m_pPrefs->setBool(TITRAQ_PREFFCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXFCOL))); + m_pPrefs->setBool(TITRAQ_PREFREMCOLON, m_pColspopup->isItemChecked(m_pColspopup->idAt(TITRAQ_IDXREMCOL))); + + // Get check status from toolbar menu and pass it to prefs handler + m_pPrefs->setBool(TITRAQ_PREFFILEBAR, m_pTbarspopup->isItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXFILEBAR))); + m_pPrefs->setBool(TITRAQ_PREFEDITBAR, m_pTbarspopup->isItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXEDITBAR))); + m_pPrefs->setBool(TITRAQ_PREFVIEWBAR, m_pTbarspopup->isItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXVIEWBAR))); + m_pPrefs->setBool(TITRAQ_PREFPREFBAR, m_pTbarspopup->isItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXPREFBAR))); + m_pPrefs->setBool(TITRAQ_PREFWHATBAR, m_pTbarspopup->isItemChecked(m_pTbarspopup->idAt(TITRAQ_IDXWHATBAR))); + + // Get column widths from main table and pass it to prefs handler + if (m_pMaintable->columnWidth(TITRAQ_IDXSTATUS) > 0) + m_pPrefs->setNumber(TITRAQ_PREFSTATCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXSTATUS)); + if (m_pMaintable->columnWidth(TITRAQ_IDXLINE) > 0) + m_pPrefs->setNumber(TITRAQ_PREFLCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXLINE)); + if (m_pMaintable->columnWidth(TITRAQ_IDXUSER) > 0) + m_pPrefs->setNumber(TITRAQ_PREFUCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXUSER)); + if (m_pMaintable->columnWidth(TITRAQ_IDXGUID) > 0) + m_pPrefs->setNumber(TITRAQ_PREFGCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXGUID)); + if (m_pMaintable->columnWidth(TITRAQ_IDXCRC) > 0) + m_pPrefs->setNumber(TITRAQ_PREFCCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXCRC)); + if (m_pMaintable->columnWidth(TITRAQ_IDXREV) > 0) + m_pPrefs->setNumber(TITRAQ_PREFREVCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXREV)); + if (m_pMaintable->columnWidth(TITRAQ_IDXDATE) > 0) + m_pPrefs->setNumber(TITRAQ_PREFDCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXDATE)); + if (m_pMaintable->columnWidth(TITRAQ_IDXSTART) > 0) + m_pPrefs->setNumber(TITRAQ_PREFSTARTCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXSTART)); + if (m_pMaintable->columnWidth(TITRAQ_IDXFINISH) > 0) + m_pPrefs->setNumber(TITRAQ_PREFFCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXFINISH)); + if (m_pMaintable->columnWidth(TITRAQ_IDXAMOUNT) > 0) + m_pPrefs->setNumber(TITRAQ_PREFACOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXAMOUNT)); + if (m_pMaintable->columnWidth(TITRAQ_IDXTASK) > 0) + m_pPrefs->setNumber(TITRAQ_PREFTCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXTASK)); + if (m_pMaintable->columnWidth(TITRAQ_IDXREMARK) > 0) + m_pPrefs->setNumber(TITRAQ_PREFREMCOLWIDTH, (long)m_pMaintable->columnWidth(TITRAQ_IDXREMARK)); + + // Get sorting order and direction from table and pass it to prefs handler + m_pPrefs->setNumber(TITRAQ_PREFSORTCOL, (long)m_pMaintable->getSortcol()); + m_pPrefs->setBool(TITRAQ_PREFSORTDIR, (long)m_pMaintable->getSortdir()); + + // Set frame geometry preferences + m_pPrefs->setNumber(TITRAQ_PREFFRAMEWIDTH, (long)this->width()); + m_pPrefs->setNumber(TITRAQ_PREFFRAMEHEIGHT, (long)this->height()); + + // Remember main window layout and doc positions + QString Laystring; + QTextStream Laystream(&Laystring, IO_WriteOnly); + Laystream << *this; // Persist the main window + m_pPrefs->setString(TITRAQ_PREFFRAMELAY, Laystring); +} + +// +// Get help on Titraq functionality +// +void Titraqform::helpContents(void) +{ + try { // Create and execute a new help contents window + std::auto_ptr pHelpcont(new AS::Helpanel(TITRAQ_REFHELP, this, "Helpanel")); + pHelpcont->exec(); + delete pHelpcont.release(); // Technically unnecessary, smart pointer + } + catch (Genexcept& Genex) { + Genex.reportErr(); + return; + } +} + +// +// Learn more about this program itself +// +void Titraqform::aboutTitraq(void) +{ + QString Namever = QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short; + QMessageBox *pCwmsg = new QMessageBox(Namever, + QObject::trUtf8("The as-gui is a time and task-based accounting\n" + "system that acts as both a work-like punch card and\n" + "time tracker. Development of as-gui is sponsored by\n" + "Cable & Wireless Telecommunications Services GmbH."), + QMessageBox::NoIcon, QMessageBox::Ok | QMessageBox::Default, + QMessageBox::NoButton, QMessageBox::NoButton, + NULL, "Titraqmessage", true, Qt::WStyle_NormalBorder); + + pCwmsg->setIconPixmap(QPixmap(s_kpcCwlogo_xpm)); + pCwmsg->exec(); +} + +// +// Learn more about the OSSP +// +void Titraqform::aboutOSSP(void) +{ + QString Namever = QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short; + QMessageBox *pOsspmsg = new QMessageBox(Namever, + QObject::trUtf8("The open source software project (OSSP) is\n" + "a collective effort aimed at implementing\n" + "high-quality Unix software components,\n" + "ranging from networking, multi-threading\n" + "and algorithmic libraries to networking\n" + "servers and development tools."), + QMessageBox::NoIcon, QMessageBox::Ok | QMessageBox::Default, + QMessageBox::NoButton, QMessageBox::NoButton, + NULL, "Osspmessage", true, Qt::WStyle_NormalBorder); + + pOsspmsg->setIconPixmap(QPixmap(s_kpcOssplogo_xpm)); + pOsspmsg->exec(); +} + +// +// Learn more about this program and Qt +// +void Titraqform::aboutQt(void) +{ + QMessageBox::aboutQt(this, QString(TITRAQ_APPTITLE) + ' ' + asgui_version.v_short); +} + +// +// Apply preference values from a signal emitting object +// +void Titraqform::applyPrefs(void) +{ + Prefpanel *pPan = (Prefpanel *)QObject::sender(); + this->applyPrefs(pPan); +} + +// +// Accept preference values from a inbound Panel object +// +void Titraqform::applyPrefs(Prefpanel *pPrefpanel) +{ + m_pPrefs->setString(TITRAQ_PREFACCOUNTS, pPrefpanel->getAccounts()); + m_pPrefs->setString(TITRAQ_PREFASDIR, pPrefpanel->getEvents()); + m_pPrefs->setString(TITRAQ_PREFUSER, pPrefpanel->getUser()); + m_pPrefs->setString(TITRAQ_PREFHOME, pPrefpanel->getHome()); + m_pPrefs->setString(TITRAQ_PREFCORBHOST, pPrefpanel->getCorbahost()); + m_pPrefs->setString(TITRAQ_PREFSOAPHOST, pPrefpanel->getSoaphost()); + m_pPrefs->setBool(TITRAQ_PREFCORBON, pPrefpanel->getCorbaon()); + m_pPrefs->setBool(TITRAQ_PREFSOAPON, pPrefpanel->getSoapon()); + m_pPrefs->setBool(TITRAQ_PREFBAKON, pPrefpanel->getBackon()); + m_pPrefs->setBool(TITRAQ_PREFEXTENDON, pPrefpanel->getExtendon()); + m_pPrefs->setBool(TITRAQ_PREFDETAILON, pPrefpanel->getDetailon()); + m_pPrefs->setBool(TITRAQ_PREFSIGNATON, pPrefpanel->getSignaton()); + m_pPrefs->setNumber(TITRAQ_PREFLIGHTRED, pPrefpanel->getLight()->red()); + m_pPrefs->setNumber(TITRAQ_PREFLIGHTGREEN, pPrefpanel->getLight()->green()); + m_pPrefs->setNumber(TITRAQ_PREFLIGHTBLUE, pPrefpanel->getLight()->blue()); + m_pPrefs->setNumber(TITRAQ_PREFDARKRED, pPrefpanel->getDark()->red()); + m_pPrefs->setNumber(TITRAQ_PREFDARKGREEN, pPrefpanel->getDark()->green()); + m_pPrefs->setNumber(TITRAQ_PREFDARKBLUE, pPrefpanel->getDark()->blue()); + + // Dim the lights if no RPC transports are available + if (this->isOpen()) + m_pSyncact->setEnabled(m_pPrefs->getBool(TITRAQ_PREFCORBON, TITRAQ_DEFCORBON) + | m_pPrefs->getBool(TITRAQ_PREFSOAPON, TITRAQ_DEFSOAPON)); + else + m_pSyncact->setEnabled(false); + + // Get the selected style which can be more complicated due to mapping... + if (pPrefpanel->getStyle() == TITRAQ_STRCDE) { + m_pPrefs->setNumber(TITRAQ_PREFSTYLE, TITRAQ_STYLECDE); + qApp->setStyle(new QCDEStyle); + } + else if (pPrefpanel->getStyle() == TITRAQ_STRSGI) { + m_pPrefs->setNumber(TITRAQ_PREFSTYLE, TITRAQ_STYLESGI); + qApp->setStyle(new QSGIStyle); + } + else if (pPrefpanel->getStyle() == TITRAQ_STRMOTIF) { + m_pPrefs->setNumber(TITRAQ_PREFSTYLE, TITRAQ_STYLEMOTIF); + qApp->setStyle(new QMotifStyle); + } + else if (pPrefpanel->getStyle() == TITRAQ_STRMPLUS) { + m_pPrefs->setNumber(TITRAQ_PREFSTYLE, TITRAQ_STYLEMPLUS); + qApp->setStyle(new QMotifPlusStyle); + } + else if (pPrefpanel->getStyle() == TITRAQ_STRPLAT) { + m_pPrefs->setNumber(TITRAQ_PREFSTYLE, TITRAQ_STYLEPLAT); + qApp->setStyle(new QPlatinumStyle); + } + else if (pPrefpanel->getStyle() == TITRAQ_STRMSOFT) { + m_pPrefs->setNumber(TITRAQ_PREFSTYLE, TITRAQ_STYLEMSOFT); + qApp->setStyle(new QWindowsStyle); + } + else // My personal favourite ;-) + m_pPrefs->setNumber(TITRAQ_PREFSTYLE, TITRAQ_STYLECDE); +}