DumontEXE 0.0.1
cmcForm.cpp
00001 /* ***************************************************************************
00002 **
00003 ** Copyright (C) 2007 Lorimark Solutions, LLC. All rights reserved.
00004 **
00005 ** This file is part of the DumontEXE Scripting Extension Kit
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://dumont.showoff-db.org/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://dumont.showoff-db.org/licensing.html 
00017 ** or contact the sales department at sales@lorimarksolutions.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ** author: Mark Petryk ~ Lorimark Solutions, LLC
00023 ** **************************************************************************/
00024 
00025 #include <QUuid>
00026 #include <QDebug>
00027 
00028 #include "cmcForm.h"
00029 #include "cmcApplication.h"
00030 #include "cmcApplications.h"
00031 #include "cmcFormField.h"
00032 #include "cmcFieldDefs.h"
00033 #include "cmcFieldDef.h"
00034 #include "cmcConnection.h"
00035 #include "cmcConnectionDefs.h"
00036 #include "cmcConnectionDef.h"
00037 #include "cmcFormScript.h"
00038 
00039 namespace cmcDatabaseApi {
00040 
00041 cmcForm::cmcForm( const cmcForm & copy ):
00042   cmcApi( copy )
00043 {
00044 }
00045 
00046 cmcForm::cmcForm
00047 (
00048   IDispatch * dispatch,
00049   cmcApplication * application,
00050   QObject * parent
00051 ):
00052   cmcApi( "", dispatch, application, parent )
00053 {
00054   /*
00055   ** Call name() so that the object name gets set properly.
00056   **
00057   */
00058   name();
00059 
00060   /*
00061   ** If the application object is not set then set it.
00062   **
00063   */
00064   if( !app() )
00065   {
00066     /*
00067     ** Get a dispatch pointer to the application object
00068     **  relative to the form.
00069     **
00070     */
00071     IDispatch * disp = GetServerObject("Application");
00072 
00073     /*
00074     ** Since we weren't provided with an application object,
00075     **  create one and see if it's already registered.
00076     **
00077     */
00078     cmcApplication * tempApp = new cmcApplication( disp );
00079 
00080     cmcApplication * regApp = cmcObject::apps()-> application( tempApp-> databaseName() );
00081 
00082     if( regApp )
00083     {
00084       setApp( regApp );
00085     }
00086     else
00087     {
00088       setApp( disp );
00089     }
00090 
00091     delete tempApp;
00092 
00093     /*
00094     ** Release the original dispatch pointer we got.
00095     **
00096     */
00097     disp-> Release();
00098   }
00099 
00100   /*
00101   ** See if this application is running in Dumont already.  If so
00102   **  then we can add this form to the forms collection.
00103   **
00104   */
00105   if( cmcApplication * thisApp = apps()-> application( app()-> databaseName() ) )
00106   {
00107     thisApp-> db()-> forms()-> add( this );
00108   }
00109 
00110   setDirty(false);
00111   setDelete(false);
00112 
00113 //  TRACE_FUNCTION
00114 //  TRACE_MESSAGE( qPrintable(instanceID()) );
00115 
00116 //  qDebug( "form app %p", app() );
00117 
00118 }
00119 
00120 cmcForm::~cmcForm()
00121 {
00122 //  TRACE_FUNCTION
00123 //  TRACE_MESSAGE( qPrintable(instanceID()) );
00124 }
00125 
00126 QString cmcForm::name()
00127 {
00128   if( objectName() == "" )
00129     setObjectName( GetServerString("Name") );
00130 
00131   return( objectName() );
00132 }
00133 
00134 QString cmcForm::categoryName()
00135 {
00136   if( m_categoryName == "" )
00137       m_categoryName = GetServerString("CategoryName");
00138 
00139   return( m_categoryName );
00140 }
00141 
00142 
00143 cmcDateDialog * cmcForm::multiDateDialog( const QString defaultDate )
00144 {
00145   TRACE_MESSAGE( "not implemented" );
00146   return( NULL );
00147 }
00148 
00149 void cmcForm::resetFields()
00150 {
00151 }
00152 
00153 void cmcForm::prevNext()
00154 {
00155 }
00156 
00157 QString cmcForm::itemName()
00158 {
00159   if( m_itemName == "" )
00160       m_itemName = GetServerString( "ItemName" );
00161 
00162   return( m_itemName );
00163 }
00164 
00165 QString cmcForm::clarifiedItemName()
00166 {
00167   QString retVal = itemName();
00168 
00169   if( cfyField() )
00170   {
00171     retVal += 
00172       categoryDef()-> cfySeparator() +
00173       itemClarify();
00174   }
00175 
00176   return( retVal );
00177 }
00178 
00179 
00180 QString cmcForm::itemClarify()
00181 {
00182   QString retVal;
00183 
00184   if( cfyField() )
00185     retVal = cfyField()-> value().left(40);
00186 
00187   return( retVal );
00188 }
00189 
00190 QString cmcForm::tabName()
00191 {
00192   return( GetServerString( "TabName" ) );
00193 }
00194 
00195 QString cmcForm::fieldName()
00196 {
00197   return( GetServerString( "FieldName" ) );
00198 }
00199 
00200 cmcFormField * cmcForm::keyField()
00201 {
00202   return( field( QString( categoryDef()-> keyFieldName() ) ) );
00203 }
00204 
00205 cmcFormField * cmcForm::cfyField()
00206 {
00207   return( field( categoryDef()-> cfyFieldName() ) );
00208 }
00209 
00210 cmcFormField * cmcForm::varField()
00211 {
00212   return( field( categoryDef()-> varFieldName() ) );
00213 }
00214 
00215 cmcFormField * cmcForm::guidField()
00216 {
00217   return( field( categoryDef()-> guidFieldName() ) );
00218 }
00219 
00220 cmcFormField * cmcForm::thidField()
00221 {
00222   return( field( categoryDef()-> thidFieldName() ) );
00223 }
00224 
00225 QString cmcForm::toXml( QString fieldList )
00226 {
00227 
00228   QDomDocument doc( "QCommenceForm" );
00229 
00230   QDomElement root = doc.createElement("item");
00231   doc.appendChild(root);
00232 
00233   root.setAttribute( "categoryName",  categoryName()       );
00234   root.setAttribute( "formName",      name()               );
00235   root.setAttribute( "itemName",      this-> itemName()    );
00236   root.setAttribute( "itemClarify",   this-> itemClarify() );
00237 
00238   /*! \todo finish
00239   for( int i=0; i<categoryDef()-> fieldDefs()-> count()-1; i++ )
00240   {
00241     cmcFieldDef * fieldDef = categoryDef()-> fieldDefs()-> get(i);
00242     field(fieldDef-> name())-> deValue( doc, root );
00243   }
00244 
00245   for( int i=0; i<categoryDef()-> connectionDefs()-> count(); i++ )
00246   {
00247     cmcConnectionDef * connectionDef = categoryDef()-> connectionDefs()-> get(i);
00248     cmcConnection * conn = connection(connectionDef-> name());
00249 
00250     conn-> domElement( doc, root );
00251   }
00252   */
00253 
00254   return( doc.toString(3) );
00255 
00256 }
00257 
00258 QString cmcForm::itemThid()
00259 {
00260   QString retVal = "unknown";
00261 
00262   if( categoryDef()-> hasThidField() )
00263   {
00264     retVal = thidField()-> value();
00265 
00266     if( retVal == "" || isAdd() )
00267     {
00268       thidField()-> value( "nothing" );
00269     }
00270   }
00271   else if( categoryDef()-> hasVarField() )
00272   {
00273     retVal = varField()-> var("thid");
00274 
00275     if( retVal == "" || isAdd() )
00276     {
00277       varField()-> var("thid","nothing");
00278     }
00279   }
00280   else
00281   {
00282     qDebug( "on %s, no field to store THID", categoryName().toAscii().data()  );
00283   }
00284 
00285   return( retVal );
00286 }
00287 
00288 /*
00289 ** The logic behind this assignment of the guid is as
00290 **  as follows.  
00291 **
00292 ** 1. we need a place to store the guid.  If not, we generate an error message
00293 **
00294 ** 2. if there presently is no guid then one will be generated
00295 **
00296 ** 3. if the form is in 'add' mode, and we haven't generated a new guid yet
00297 **     then a new one will be generated.
00298 **
00299 ** A static boolean is used to remember if we've generated a new guid yet or
00300 **  not.  That allows this function to generate a new guid only once if this
00301 **  is a new item.  If we switch to a new form then this whole code module
00302 **  will be reset anyway, causing the flag to go true again and a new guid
00303 **  will be generated then, again, if needed.  The logic here is suppose to
00304 **  accomodate the situation of a person copying an existing item.  In this
00305 **  instance, the old guid from the other item will be copied, and we don't
00306 **  want that.  So the test for isAdd() is suppose to generate a new guid if
00307 **  this form is a copy item, and it's suppose to do that only once.
00308 **
00309 */
00310 QString cmcForm::itemGuid()
00311 {
00312   static bool newGuidNeeded = true;
00313   static QString retVal;
00314 
00315   if( categoryDef()-> hasGuidField() )
00316   {
00317     retVal = guidField()-> value();
00318     if( retVal == "" || ( isAdd() && newGuidNeeded ) )
00319     {
00320       retVal = QUuid().createUuid().toString();
00321       guidField()-> value( retVal );
00322       newGuidNeeded = false;
00323     }
00324   }
00325   else if( categoryDef()-> hasVarField() )
00326   {
00327     retVal = varField()-> var("guid");
00328     if( retVal == "" || ( isAdd() && newGuidNeeded ) )
00329     {
00330       retVal = QUuid().createUuid().toString();
00331       varField()-> var("guid", retVal );
00332       newGuidNeeded = false;
00333     }
00334   }
00335   else
00336   {
00337     qDebug( "on %s, no field to store guid", categoryName().toAscii().data()  );
00338   }
00339 
00340   if( retVal == "" || ( isAdd() && newGuidNeeded ) )
00341   {
00342     retVal = QUuid().createUuid().toString();
00343   }
00344 
00345   return( retVal );
00346 
00347 }
00348 
00349 bool cmcForm::isAdd()
00350 {
00351   return( GetServerBool( "IsAdd" ) );
00352 }
00353 
00354 bool cmcForm::isDelete()
00355 {
00356   return( m_isDelete );
00357 }
00358 
00359 void cmcForm::setDelete( bool state )
00360 {
00361   m_isDelete = state;
00362 }
00363 
00364 bool cmcForm::isPrevNext()
00365 {
00366   return( m_prevNext );
00367 }
00368 
00369 QString cmcForm::fieldValue()
00370 {
00371   return( GetServerString( "FieldValue" ) );
00372 }
00373 
00374 bool cmcForm::isShared()
00375 {
00376   return( GetServerBool( "IsShared" ) );
00377 }
00378 
00379 long cmcForm::backColor()
00380 {
00381   return( GetServerLong( "BackColor" ) );
00382 }
00383 
00384 void cmcForm::backColor( long color )
00385 {
00386 }
00387 
00388 QString cmcForm::caption()
00389 {
00390   return( GetServerString( "Caption" ) );
00391 }
00392 
00393 void cmcForm::caption( QString cap )
00394 {
00395   SetServerString( "Caption", cap );
00396 }
00397 
00398 void cmcForm::setShared( bool state )
00399 {
00400 //  qDebug( "rs_commit(%lx)", i_dispid );
00401 
00402   VARIANTARG varg[1];
00403   ::VariantInit(&varg[0]);     // Initialize the VARIANT.
00404 
00405   // load the variant
00406   varg[0].vt = VT_I4; varg[0].lVal = state;
00407 
00408   // Fill in the DISPPARAMS structure.
00409   DISPPARAMS param;
00410   param.cArgs             = 1;     // Number of arguments
00411   param.rgvarg            = varg;  // Arguments
00412   param.cNamedArgs        = 0;     // Number of named args
00413   param.rgdispidNamedArgs = NULL;  // Named arguments
00414 
00415   // Allocate a variant for the returned parameter.
00416   VARIANT varResult;
00417   ::VariantInit(&varResult);
00418 
00419   // Invoke the function.
00420   HRESULT hr = Invoke
00421   (
00422     "SetShared",
00423     IID_NULL,
00424     GetUserDefaultLCID(),
00425     DISPATCH_METHOD,
00426     &param,
00427     &varResult,
00428     NULL,
00429     NULL
00430   );
00431 
00432   if( FAILED(hr) )
00433   {
00434     qDebug( "setShared failed hr=%lx", hr );
00435   }
00436 
00437   return;
00438 
00439 }
00440 
00441 void cmcForm::setValue( QString value )
00442 {
00443 }
00444 
00445 bool cmcForm::deleteItem()
00446 {
00447   if( !categoryDef()-> hasVarField() ) return( false );
00448 
00449   varField()-> var("deletedOn", packDateTime(QDateTime::currentDateTime()) );
00450   varField()-> var("deletedBy", db()-> meInfo()-> id() );
00451 
00452   return( true );
00453 }
00454 
00455 bool cmcForm::applyWorkgroupPermissions()
00456 {
00457   /*
00458   ** If the Workgroup Sharing fields don't exist, then
00459   **  there's nothing to do.
00460   **
00461   */
00462   if( !isField("Item Shared")                             ) return false;
00463   if( !isConnection("pR -> " + meInfo()-> categoryName()) ) return false;
00464   if( !isConnection("pW -> " + meInfo()-> categoryName()) ) return false;
00465 
00466   /*
00467   ** Get the share values.
00468   **
00469   */
00470   QString itemShared = field("Item Shared")-> value();
00471 
00472   /*
00473   ** If there is no item sharing, then there's nothing to
00474   **  do.  But, it's also not an error, so return that
00475   **  we completed successfully.
00476   **
00477   */
00478   if( itemShared == "None" )
00479   {
00480     return( true );
00481   }
00482 
00483   /*
00484   ** If this is a Public Share, then ALL active users in the database
00485   **  need to be assigned to this item.
00486   **
00487   */
00488   if( itemShared == "Public" )
00489   {
00490 //    qDebug( "Item Shared is Public" );
00491   }
00492 
00493   if( itemShared == "Protected" )
00494   {
00495 //    qDebug( "Item Shared is Protected" );
00496   }
00497 
00498   if( itemShared == "Private" )
00499   {
00500 //    qDebug( "Item Shared is Private" );
00501   }
00502 
00503   if( itemShared == "Group" )
00504   {
00505 //    qDebug( "Item Shared is By Group" );
00506   }
00507 
00508   return( true );
00509 }
00510 
00511 
00512 bool cmcForm::save()
00513 {
00514 //  if( eventTrace() )
00515 //    qDebug( "Form(%s)::save", name().toAscii().data()  );
00516 
00517   // Fill in the DISPPARAMS structure.
00518   DISPPARAMS param;
00519   param.cArgs             = 0;     // Number of arguments
00520   param.rgvarg            = NULL;  // Arguments
00521   param.cNamedArgs        = 0;     // Number of named args
00522   param.rgdispidNamedArgs = NULL;  // Named arguments
00523 
00524   // Allocate a variant for the returned parameter.
00525   VARIANT varResult;
00526   ::VariantInit(&varResult);
00527 
00528   // Invoke the function.
00529   HRESULT hr = Invoke
00530   (
00531     GetIDofName("Save"),
00532     IID_NULL,
00533     GetUserDefaultLCID(),
00534     DISPATCH_METHOD,
00535     &param,
00536     &varResult,
00537     NULL,
00538     NULL
00539   );
00540 
00541   if( FAILED(hr) )
00542   {
00543     qDebug( "Form.save failed hr=%lx", hr );
00544     return( false );
00545   }
00546 
00547   return( true );
00548 }
00549 
00550 bool cmcForm::cancel()
00551 {
00552 //  if( eventTrace() )
00553 //    qDebug( "Form(%s)::cancel", name().toAscii().data()  );
00554 
00555   // Fill in the DISPPARAMS structure.
00556   DISPPARAMS param;
00557   param.cArgs             = 0;     // Number of arguments
00558   param.rgvarg            = NULL;  // Arguments
00559   param.cNamedArgs        = 0;     // Number of named args
00560   param.rgdispidNamedArgs = NULL;  // Named arguments
00561 
00562   // Allocate a variant for the returned parameter.
00563   VARIANT varResult;
00564   ::VariantInit(&varResult);
00565 
00566   // Invoke the function.
00567   HRESULT hr = Invoke
00568   (
00569     GetIDofName("Cancel"),
00570     IID_NULL,
00571     GetUserDefaultLCID(),
00572     DISPATCH_METHOD,
00573     &param,
00574     &varResult,
00575     NULL,
00576     NULL
00577   );
00578 
00579   if( FAILED(hr) )
00580   {
00581     qDebug( "Form.cancel failed hr=%lx", hr );
00582     return( false );
00583   }
00584 
00585   return( true );
00586 
00587 }
00588 
00589 bool cmcForm::abort()
00590 {
00591 //  if( eventTrace() )
00592 //    qDebug( "Form(%s)::abort", name().toAscii().data()  );
00593 
00594   // Fill in the DISPPARAMS structure.
00595   DISPPARAMS param;
00596   param.cArgs             = 0;     // Number of arguments
00597   param.rgvarg            = NULL;  // Arguments
00598   param.cNamedArgs        = 0;     // Number of named args
00599   param.rgdispidNamedArgs = NULL;  // Named arguments
00600 
00601   // Allocate a variant for the returned parameter.
00602   VARIANT varResult;
00603   ::VariantInit(&varResult);
00604 
00605   // Invoke the function.
00606   HRESULT hr = Invoke
00607   (
00608     GetIDofName("Abort"),
00609     IID_NULL,
00610     GetUserDefaultLCID(),
00611     DISPATCH_METHOD,
00612     &param,
00613     &varResult,
00614     NULL,
00615     NULL
00616   );
00617 
00618   if( FAILED(hr) )
00619   {
00620     qDebug( "Form.abort failed hr=%lx", hr );
00621     return( false );
00622   }
00623 
00624   return( true );
00625 }
00626 
00627 void cmcForm::moveToTab( QString tabName )
00628 {
00629 }
00630 
00631 void cmcForm::moveToField( QString fieldName )
00632 {
00633 }
00634 
00635 bool cmcForm::isDirty()
00636 {
00637   return( m_isDirty );
00638 }
00639 
00640 void cmcForm::setDirty( bool state )
00641 {
00642   m_isDirty = state;
00643 }
00644 
00645 void cmcForm::undo()
00646 {
00647 }
00648 
00649 cmcCategoryDef * cmcForm::categoryDef()
00650 {
00651   if( !m_categoryDef )
00652        m_categoryDef = app()-> categoryDef( categoryName() );
00653 
00654   return( m_categoryDef );
00655 }
00656 
00657 cmcFormField * cmcForm::field( QString fieldName )
00658 {
00659 
00660   if( fieldName == "" )
00661   {
00662     return( NULL );
00663   }
00664 
00665   /*
00666   ** Fields have the unique quality that if a single field is created
00667   **  then that same field pointer is handed out to any other request
00668   **  for the same field.
00669   **
00670   ** However, this is troublesome since if someone else acquires a handle
00671   **  to a field and then destroys it, it will go out of existance for
00672   **  the first handle.  It seems we need some sort of reference counting
00673   **  in order to be able to handle multiple clients of a Qt object.  It is
00674   **  potentially a problem to have a field object deleted before its time
00675   **  since the field object, itself, carries undo and change info.
00676   **
00677   */
00678   cmcFormField * retVal = findChild<cmcFormField *>(fieldName);
00679 
00680   /*
00681   ** If the field is not already created then we need to create one.
00682   **
00683   */
00684   if( !retVal )
00685   {
00686     /*
00687     ** Before the field is created, make sure it exists in the list of 
00688     **  field definitions.  If it doesn't, then we'll just return a NULL
00689     **  pointer, the caller will have to deal with that.  But, at least
00690     **  we won't generate an error here.
00691     **
00692     */
00693     if( categoryDef()-> fieldDefs()-> contains(fieldName) )
00694     {
00695 
00696       VARIANTARG varg[1];
00697       ::VariantInit(&varg[0]);     // Initialize the VARIANT.
00698 
00699       // Convert the wide-character string to a BSTR.
00700       BSTR bstrIn = ::SysAllocString((OLECHAR*)fieldName.utf16());
00701 
00702       // load the variant
00703       varg[0].vt = VT_BSTR; varg[0].bstrVal = bstrIn;
00704 
00705       // Fill in the DISPPARAMS structure.
00706       DISPPARAMS param;
00707       param.cArgs             = 1;     // Number of arguments
00708       param.rgvarg            = varg;  // Arguments
00709       param.cNamedArgs        = 0;     // Number of named args
00710       param.rgdispidNamedArgs = NULL;  // Named arguments
00711   
00712       // Allocate a variant for the returned parameter.
00713       VARIANT varResult;
00714       ::VariantInit(&varResult);
00715 
00716       // Invoke the function.
00717       HRESULT hr = Invoke
00718       (
00719         "Field",
00720         IID_NULL,
00721         GetUserDefaultLCID(),
00722         DISPATCH_METHOD,
00723         &param,
00724         &varResult,
00725         NULL,
00726         NULL
00727       );
00728 
00729       ::SysFreeString(bstrIn);
00730 
00731       if( FAILED(hr) )
00732       {
00733         qDebug( "cmcForm::field '%s' hr=%lx", fieldName.toAscii().data(), hr );
00734         return( NULL );
00735       }
00736 
00737       // Display the returned string.
00738       if( varResult.vt == VT_DISPATCH )
00739       {
00740         retVal = new cmcFormField( fieldName, (IDispatch*) varResult.punkVal, app(), this );
00741         retVal-> api()-> Release(); // release here because we AddRef() when we Invoked
00742 
00743         /*
00744         ** Connect some signals from this field back to this form so that this form gets notified
00745         **  on any changes.
00746         **
00747         */
00748         connect( retVal, SIGNAL(change(QString,QString)), this, SLOT(changeField(QString,QString)) );
00749 
00750       }
00751     }
00752     else
00753     {
00754       /*! \todo Log Field Access Errors */
00755 //      DB()-> log( "form.field(" + i_field + ") not found" );
00756     }
00757   }
00758 
00759   return( retVal );
00760 
00761 }
00762 
00763 cmcFormField * cmcForm::fld( QString fieldName )
00764 {
00765   return( field(fieldName) );
00766 }
00767 
00768 cmcFormField * cmcForm::field
00769 (
00770   long index
00771 )
00772 {
00773   return( field( categoryDef()-> fieldDef(index)-> name() ) );
00774 }
00775 
00776 
00777 
00778 
00779 cmcConnection * cmcForm::connection( QString conName, QString catName )
00780 {
00781   QString conCatName = conName + CONCAT_DELIMITER + catName;
00782 
00783   cmcConnection * retVal = findChild<cmcConnection *>( conCatName );
00784 
00785   if( !retVal )
00786   {
00787     if( categoryDef()-> connectionDefs()-> contains( conCatName ) )
00788     {
00789       VARIANTARG varg[2];
00790       ::VariantInit(&varg[0]);     // Initialize the VARIANT.
00791 
00792       // Convert the wide-character string to a BSTR.
00793       BSTR con = ::SysAllocString((OLECHAR*)conName.utf16());
00794       BSTR cat = ::SysAllocString((OLECHAR*)catName.utf16());
00795 
00796       // load the variant
00797       varg[1].vt = VT_BSTR; varg[1].bstrVal = con;
00798       varg[0].vt = VT_BSTR; varg[0].bstrVal = cat;
00799 
00800       // Fill in the DISPPARAMS structure.
00801       DISPPARAMS param;
00802       param.cArgs             = 2;     // Number of arguments
00803       param.rgvarg            = varg;  // Arguments
00804       param.cNamedArgs        = 0;     // Number of named args
00805       param.rgdispidNamedArgs = NULL;  // Named arguments
00806   
00807       // Allocate a variant for the returned parameter.
00808       VARIANT varResult;
00809       ::VariantInit(&varResult);
00810 
00811       // Invoke the function.
00812       HRESULT hr = Invoke
00813       (
00814         "Connection",
00815         IID_NULL,
00816         GetUserDefaultLCID(),
00817         DISPATCH_PROPERTYGET,
00818         &param,
00819         &varResult,
00820         NULL,
00821         NULL
00822       );
00823 
00824       ::SysFreeString(con);
00825       ::SysFreeString(cat);
00826 
00827       if( FAILED(hr) )
00828       {
00829         qDebug( "connection( <%s>, <%s> )", 
00830           qPrintable(conName),
00831           qPrintable(catName)
00832         );
00833         qDebug( "QCommenceForm::connection hr=%lx", hr );
00834         return( NULL );
00835       }
00836 
00837       // Display the returned string.
00838       if( varResult.vt == VT_DISPATCH )
00839       {
00840         retVal = new cmcConnection( conName, (IDispatch*) varResult.punkVal, this );
00841         retVal-> Release(); // release here because we AddRef() when we Invoked
00842 
00843         /*
00844         ** Connect some signals from this connection back to this form so that this form gets notified
00845         **  on any changes.
00846         **
00847         */
00848         connect( retVal, SIGNAL(change(QString,QString,QString)), this, SLOT(changeConnection(QString,QString,QString)) );
00849       }
00850     }
00851     else
00852     {
00853 //      db()-> log( "form.connection(" + conCatName + ") not found" );
00854     }
00855   }
00856 
00857   return( retVal );
00858 
00859 }
00860 
00861 cmcConnection * cmcForm::connection( QString conCatName )
00862 {
00863   cmcConnection * retVal = NULL;
00864 
00865   /*
00866   ** Get a copy of the connection definition
00867   **
00868   */
00869   cmcConnectionDef * conDef = 
00870     categoryDef()-> 
00871       connectionDef( conCatName );
00872 
00873   /*
00874   ** If there is no conDef then we have an error condition.
00875   **
00876   */
00877   if( conDef )
00878   {
00879     /*
00880     ** See if this connection has already been created and if not, create it.
00881     **
00882     */
00883     retVal = findChild<cmcConnection*>( conDef-> name() );
00884 
00885     /*
00886     ** No field already exists, go ahead and create one.
00887     **
00888     */
00889     if( !retVal )
00890          retVal = connection( conDef-> conName(), conDef-> toCategory() );
00891   }
00892 
00893   return( retVal );
00894 
00895 }
00896 
00897 cmcConnection * cmcForm::con
00898 (
00899   QString conName,
00900   QString catName
00901 )
00902 {
00903   return( connection( conName, catName ) ); 
00904 }
00905 
00906 
00907 cmcConnection * cmcForm::con( QString conCatName )
00908 {
00909   return( connection( conCatName ) ); 
00910 }
00911 
00912 cmcConnection * cmcForm::connection( long index )
00913 {
00914   return( connection( categoryDef()-> connectionDef(index)-> name() ) );
00915 }
00916 
00917 bool cmcForm::isConnection( QString fieldName )
00918 {
00919   return( categoryDef()-> isConnection(fieldName) );
00920 }
00921 
00922 bool cmcForm::isField( QString fieldName )
00923 {
00924   return( categoryDef()-> isField(fieldName) );
00925 }
00926 
00927 cmcFormControl * cmcForm::control( QString controlName )
00928 {
00929   return( NULL );
00930 }
00931 
00932 cmcRuntime * cmcForm::runtime()
00933 {
00934   return( NULL );
00935 }
00936 
00937 cmcRuntime * cmcForm::RT()
00938 {
00939   return( NULL );
00940 }
00941 
00942 void cmcForm::multiDateDialogExec( const QString defaultDate )
00943 {
00944 }
00945 
00946 QString cmcForm::changeLog()
00947 {
00948   return( "" );
00949 }
00950 
00951 bool cmcForm::onLoad()
00952 {
00953   return( false );
00954 }
00955 
00956 bool cmcForm::onSave()
00957 {
00958   if( trace() )
00959     qDebug( "Form(%s)::onSave", name().toAscii().data() );
00960 
00961   /*
00962   ** Status flag to indicate that on-save was called.
00963   **
00964   */
00965   m_prevNext = true;
00966 
00967 #ifdef NEVER
00968 
00969   /*
00970   ** We are to logItemChanges when the global 'logItemChanges' flag is set to 'Yes' .and.
00971   **  the category we are currently in is a category that has been selected as a logging
00972   **  category.  In order to do logging properly, this category *should* contain a var
00973   **  field, and that var field *should* have a cmcID or guid field set in it BEFORE
00974   **  the log is generated.  This doesn't really work for new items, though, since the
00975   **  cmcID value isn't yet available.  That's why we've gone through all the effort with
00976   **  the guid.
00977   **
00978   */
00979   bool logItemChanges  = (db()-> dumVar("changeLogEnabled") == "Yes") &&
00980                          (db()-> dumVar("changeLogCategories").contains( categoryName() ));
00981 
00982   /*
00983   ** We are to stampItemChanges when the global 'stampItemChanges' flag is set to 'Yes'
00984   **  .and. the category we are currently in is a category that has been selected as a 
00985   **  stamping category.
00986   **
00987   */
00988   bool stampItemChanges = (db()-> dumVar("stampItemEnabled") == "Yes") &&
00989                           (db()-> dumVar("stampItemCategories").contains( categoryName() ));
00990 
00991   if( trace() )
00992     qDebug( "log %s, stamp %s", logItemChanges? "True":"False", stampItemChanges? "True":"False" );
00993 
00994 #endif
00995 
00996   /*
00997   ** bugbug: this is temporary
00998   **
00999   */
01000   bool stampItemChanges = false;
01001   if( categoryDef()-> hasVarField() )
01002     stampItemChanges = true;
01003 
01004   /*
01005   ** By calling itemGuid(), we *cause* a guid to be generated for this item if one did not
01006   **  already exist.  We also cause that generated guid to be stamped on to the varField
01007   **  if a varField is present for this category.  If a guid does get generated then we
01008   **  effectively cause this item to become dirty causing all this stamping code below
01009   **  to get busy and do its work.
01010   **
01011   */
01012   itemGuid();
01013 
01014 #ifdef NEVER
01015 
01016   /*
01017   ** If we are logging changes then perform the logging.
01018   **
01019   ** BUGBUG: this code is terribly tied to a specific ChangeLog category.
01020   **  Dumont needs some method of making its category dependencies a little
01021   **  looser.
01022   */
01023   if( logItemChanges && isDirty() )
01024   {
01025     if( trace() )
01026       qDebug( "setting up to log" );
01027 
01028     /*
01029     ** Get a handle on the Change Log Category Definition.  If the change log
01030     **  category isn't defined then the call will return a null pointer and
01031     **  we can just ignore the whole change log thingie.
01032     **
01033     */
01034     if( QCommenceAddRowSet * ars = getChangeLogAddRowSet() )
01035     {
01036       if( trace() )
01037         qDebug( "logging" );
01038 
01039       /*
01040       ** Plug this item with all the change log information.
01041       **
01042       */
01043       ars-> modifyRow( 0, 0, dumont::packDateTime() + db()-> meInfo()-> abbreviation() ); // changeLogKey
01044       ars-> modifyRow( 0, 1, guid() );                                                    // guid
01045       ars-> modifyRow( 0, 2, QDate::currentDate().toString("MM/dd/yyyy") );               // Date
01046       ars-> modifyRow( 0, 3, QTime::currentTime().toString("HH:mm:ss AP") );              // Time
01047       ars-> modifyRow( 0, 4, changeLog() );                                               // xml
01048 
01049       /*
01050       ** The next two columns should be for storing the category
01051       **  name and the item name.  This is for sorting purposes
01052       **  in the reports.
01053       **
01054       */
01055       if( ars-> columnCount() > 6 ) 
01056       {
01057         ars-> modifyRow( 0, 5, categoryName() ); // Category
01058         ars-> modifyRow( 0, 6, itemName()     ); // Item Name
01059       }
01060 
01061       /*
01062       ** If this is a shared category then set this item to be shared also.
01063       **
01064       */
01065       if( ars-> cursor()-> shared() )
01066           ars-> setShared( 0 );
01067 
01068       /*
01069       ** Commit the item.  If it fails then post an error message
01070       **
01071       */
01072       if( !ars-> commit()== -2 ) 
01073         qDebug( "commit failed %s %d", __FILE__, __LINE__ );
01074 
01075       /*
01076       ** We have to delete this cursor manually because it's tied to the
01077       **  DB object and the DB object doesn't get destroyed when this form
01078       **  closes like one might expect.
01079       **
01080       */
01081       delete ars-> cursor();
01082 
01083     } // endif( ..category def exists.. )
01084 
01085   } // endif( ..log changes.. )
01086 
01087 #endif
01088 
01089   /*
01090   ** If the category contains a catnameVar field and he has requested change stamps
01091   **  then stamp the var field with the change information.
01092   **
01093   ** It helps when executing this function to pre-load the catnameVar field with the
01094   **  cmcID, createdOn, createdBy, changedOn, changedBy fields so that they are there
01095   **  already for us when we apply these values.  That makes looking at the catnameVar
01096   **  field a little bit easier when it is in reports since all the field values will
01097   **  be in the same location on every item.
01098   **
01099   */
01100   if( stampItemChanges )
01101   {
01102     /*
01103     ** If the item is being added then we need to set the created info.
01104     **
01105     */
01106     if( isAdd() || varField()-> var("createdBy") == "" )
01107     {
01108 //      varField()-> var("itemThid",  itemThid() );
01109       varField()-> var("itemGuid",  itemGuid() );
01110       varField()-> var("createdOn", packDateTime(QDateTime::currentDateTime()) );
01111       varField()-> var("createdBy", db()-> meInfo()-> id() );
01112       setDirty(true);
01113     }
01114 
01115     /*
01116     ** Also, if the var field does not contain a valid cmcID string then set that
01117     **  up now.
01118     **
01119     */
01120 //    if( itemThid() == "nothing" || itemThid() == "" )
01121 //    {
01122 //      QString missionName = "assignTHID:" + categoryName();
01123 //      dumDLL()-> addAgentMission( missionName );
01124 //    }
01125 
01126     /*
01127     ** We will follow through with the changed info.
01128     **
01129     ** BUGBUG: need to implement the field change logging before
01130     **          isDirty is going to work properly.
01131     */
01132 //    if( isDirty() || varField()-> var("changedBy") == "" )
01133     {
01134       varField()-> var("changedOn", packDateTime(QDateTime::currentDateTime()) );
01135       varField()-> var("changedBy", db()-> meInfo()-> id() );
01136     }
01137 
01138   } // endif( ..stamp var field changes.. )
01139 
01140   resetFields();
01141 
01142   /*
01143   ** True in this case means everything worked out ok.  If something
01144   **  failed above, then we say onSave didn't work.  This is sort of
01145   **  consistent with the other boolean return values that indicate
01146   **  'true' when something happens, and false when nothing happens...
01147   **  like the onEnterField and onLeaveField functions.
01148   **
01149   */
01150   return( true );
01151 
01152 }
01153 
01154 bool cmcForm::onCancel()
01155 {
01156   return( false );
01157 }
01158 
01159 bool cmcForm::onEnterTab( QString tabName )
01160 {
01161   return( false );
01162 }
01163 
01164 bool cmcForm::onLeaveTab( QString tabName )
01165 {
01166   return( false );
01167 }
01168 
01169 bool cmcForm::onEnterField( QString fieldName )
01170 {
01171   return( false );
01172 }
01173 
01174 bool cmcForm::onLeaveField( QString fieldName )
01175 {
01176   return( false );
01177 }
01178 
01179 bool cmcForm::onEnterControl( QString controlID )
01180 {
01181   return( false );
01182 }
01183 
01184 bool cmcForm::onLeaveControl( QString controlID )
01185 {
01186   return( false );
01187 }
01188 
01189 bool cmcForm::onActiveXControlEvent( QString controlID, QString eventName, QString parameterArray )
01190 {
01191   return( false );
01192 }
01193 
01194 bool cmcForm::onClick( QString controlID )
01195 {
01196   return( false );
01197 }
01198 
01199 bool cmcForm::onChange( QString controlID )
01200 {
01201   return( false );
01202 }
01203 
01204 bool cmcForm::onKeyPress( QString controlID, long keyAscii )
01205 {
01206   return( false );
01207 }
01208 
01209 void cmcForm::changeField( QString fieldName, QString fieldValue )
01210 {
01211   qDebug() << fieldName << fieldValue;
01212 
01213   setDirty( true );
01214 }
01215 
01216 void cmcForm::changeConnection( QString connName, QString toCategory, QString value )
01217 {
01218 }
01219 
01220 void cmcForm::setReopen( bool state )
01221 {
01222 }
01223 
01224 void cmcForm::reopen()
01225 {
01226 }
01227 
01228 
01229 cmcMeInfo * cmcForm::meInfo()
01230 {
01231   return( db()-> meInfo() );
01232 }
01233 
01234 cmcRowSet * cmcForm::getChangeLogAddRowSet()
01235 {
01236   return( NULL );
01237 }
01238 
01239 } // endnamespace cmcDatabaseApi
01240 
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties




~ ~ ~ ~ ~ ~
Source Code without Comments is like a Cranberry Garland
without the berries. Comment your Code!
 
Commence Database User Support Group Forum
http://newsgroup.showoff-db.org/
~ ~ ~ ~ ~ ~
Author: Mark Petryk
Lorimark Solutions, LLC
mark@lorimarksolutions.com