DumontEXE 0.0.1
cmcObject.h
00001 /* ***************************************************************************
00002 **
00003 ** Copyright (C) 2007, 2008 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/exe/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/exe/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 #ifndef CDA_OBJECT_H_422FD07F_0597_4cbb_A034_9AE85166472E
00026 #define CDA_OBJECT_H_422FD07F_0597_4cbb_A034_9AE85166472E
00027 
00028 #include "rpc.h"
00029 
00030 #include <QObject>
00031 #include <QPointer>
00032 #include <QString>
00033 #include <QHash>
00034 #include <QDomElement>
00035 #include <QVariant>
00036 #include <QDate>
00037 #include <QTime>
00038 #include <QDateTime>
00039 #include <QUuid>
00040 
00041 /*!
00042 ** \brief Show the function information
00043 **
00044 ** This macro can be used inside a function to cause a debug window to open
00045 **  with the function definition information.  It's a trace function.  It
00046 **  prints the following:
00047 **
00048 ** [file]:[line]:[function signature]("[object name]")
00049 **
00050 */
00051 #define TRACE_FUNCTION   qDebug( "func: %s:%d:%s(\"%s\")", __FILE__, __LINE__, Q_FUNC_INFO, qPrintable(objectName()) );
00052 #define TRACE_MESSAGE(x) qDebug( "mesg: %s:%d:%s", __FILE__, __LINE__, x );
00053 
00054 
00055 /*
00056 ** This should be provided by the main window manager
00057 **
00058 */
00059 void statusBar( const QString & message );
00060 
00061 #include "cmcError.h"
00062 #include "cmcStringList.h"
00063 //#include "cmcActiveViewInfo.h"
00064 
00065 /*!
00066 ** \brief Commence Database API Namespace
00067 **
00068 ** This namespace contains all the objects that are used to interface
00069 **  to and manage the application through the COM interface
00070 **  API.
00071 **
00072 ** \par cmc Database Api Parent/Child Relationships
00073 ** \dot
00074 ** digraph cmcDatabaseApiNamespace
00075 ** {
00076 **   node [shape=ellipse, fontsize=10];
00077 **
00078 **   DumontEXE     [ URL="\ref DumontEXE"        ];
00079 **   Applications  [ URL="\ref cmcApplications"  ];
00080 **   winDumont     [ URL="\ref winDumontEXE"     ];
00081 **   Application   [ URL="\ref cmcApplication"   ];
00082 **   Database      [ URL="\ref cmcDatabase"      ];
00083 **   DesktopDef    [ URL="\ref cmcDesktopDef"    ];
00084 **   AgentDef      [ URL="\ref cmcAgentDef"      ];
00085 **   CategoryDef   [ URL="\ref cmcCategoryDef"   ];
00086 **   Form          [ URL="\ref cmcForm"          ];
00087 **   Cursor        [ URL="\ref cmcCursor"        ];
00088 **   Cursors       [ URL="\ref cmcCursors"       ];
00089 **   RowSet        [ URL="\ref cmcRowSet"        ];
00090 **   Conversation  [ URL="\ref cmcConversation"  ];
00091 **   Forms         [ URL="\ref cmcForms"         ];
00092 **   FieldDef      [ URL="\ref cmcFieldDef"      ];
00093 **   ConnectionDef [ URL="\ref cmcConnectionDef" ];
00094 **   FormDef       [ URL="\ref cmcFormDef"       ];
00095 **   ViewDef       [ URL="\ref cmcViewDef"       ];
00096 **   Field         [ URL="\ref cmcField"         ];
00097 **   Connection    [ URL="\ref cmcConnection"    ];
00098 **   Control       [ URL="\ref cmcControl"       ];
00099 **   Runtime       [ URL="\ref cmcRuntime"       ];
00100 **
00101 **   DumontEXE    -> Applications    ;
00102 **   DumontEXE    -> winDumont       ;
00103 **   Applications -> Application     ;
00104 **   Application  -> Database        ;
00105 **   Application  -> CategoryDef     ;
00106 **   Application  -> DesktopDef      ;
00107 **   Application  -> AgentDef        ;
00108 **   Database     -> Conversation    ;
00109 **   Database     -> Forms           ;
00110 **   Database     -> Cursors         ;
00111 **
00112 **   Forms        -> Form         [style=dashed];
00113 **   Cursors      -> Cursor       [style=dashed];
00114 **   Cursor       -> RowSet         ;
00115 **
00116 **   CategoryDef  -> FieldDef        ;
00117 **   CategoryDef  -> ConnectionDef   ;
00118 **   CategoryDef  -> FormDef         ;
00119 **   CategoryDef  -> ViewDef         ;
00120 **
00121 **   Form         -> Field           ;
00122 **   Form         -> Connection      ;
00123 **   Form         -> Control         ;
00124 **   Form         -> Runtime         ;
00125 **
00126 ** }
00127 ** \enddot
00128 **
00129 ** <b>As you are perusing</b> through these files, you will come across
00130 **  objects that look remarkably like regular Commence objects.  This
00131 **  was an intentional part of the Dumont design - to create a bunch of
00132 **  objects that look just like regular Commence objects, but that also
00133 **  have additional (aka; extended) features.  The regular Commence
00134 **  look-alike functions have no special notation on them.  However, the
00135 **  extended functions do.  And, while there are several extended functions,
00136 **  some of them are preferred.  The alias functions simply replicate
00137 **  the same functionality as another function, but with a slightly 
00138 **  different syntax.  See the following for more explanation:
00139 **
00140 ** \par extended:
00141 ** Some functions are marked as <b>"extended"</b> functions.  Extended
00142 **  functions are new functions that do not exist in the current Commence
00143 **  cursor object, but are provide by the Dumont program.  These functions
00144 **  extend the normal capabilities of the Commence API, usually resulting
00145 **  in an improvement.
00146 **
00147 ** \par preferred:
00148 ** Some functions are marked as <b>"preferred"</b> functions.  Preferred
00149 **  functions are functions that have many similar versions, but one or
00150 **  two of them are the preferred-use functions, and should be used when
00151 **  trying to decide which function to call.  Take, for instance, the
00152 **  setColumn functions.  There is a handful of various versions of these
00153 **  functions.  Some are provided as aliases of existing functions, and
00154 **  others are truly new implementations that greatly simplify the 
00155 **  application script.  These preferred functions should be considered
00156 **  first when choosing a design implementation.
00157 **
00158 ** \par alias:
00159 ** Some functions are marked as <b>"alias"</b> functions.  Alias functions
00160 **  are functions that are completely identical to some other function, but
00161 **  are provided for program API consistency.  A good example is the 
00162 **  colCount() alias function.  This function is identical in every way to
00163 **  its columnCount() counterpart, and is only provided to help with script
00164 **  readability because colCount() has a tendancy to line up nicely with
00165 **  rowCount() when they're used together.  Other alias functions are 
00166 **  simply easier to look at since they are less wordy.
00167 **
00168 ** \par General Improvements
00169 ** Let me just give a brief example of what some of the improvements to the
00170 **  Commence API that we're talking about here.  Below is a chunk of code
00171 **  that was implemented to assemble a formatted address for a client.
00172 **  The format for the address depended on the "Address Type" selected
00173 **  by the user, and the address type came from a client->Address list, 
00174 **  meaning that a single client could have many addresses associated with
00175 **  his profile.  The trick is to decide what addresses are available, and
00176 **  format something that looks like an address lable properly.  Dumont
00177 **  made this procedure really really simple:
00178 **
00179 ** \code
00180 ** ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' 
00181 ** '
00182 ** ' This function takes a client name and formats an address for him.
00183 ** '  It employs an AddressType specifier that can determine which address
00184 ** '  to choose from by priority.  The 'AddressType' is based upon the 
00185 ** '  category 'Address Type'.
00186 ** '
00187 ** ' If just the client name is given, then the address is taken from
00188 ** '  the primary address fields on the 'Contacts' item.  If an AddressType
00189 ** '  is included, then this procedure will parse through the address list
00190 ** '  of extended addresses from the 'Address' category.
00191 ** ' 
00192 ** ' The Flags field determines what content is returned by the query.
00193 ** '  .T. ~ turns on the AddressType designation.  This is prepended to
00194 ** '         the top of the address field to aid in address identification
00195 ** '
00196 ** '  .F. ~ turns on the field names.  Each field name is prepended to each
00197 ** '         address line (not working yet).
00198 ** '
00199 ** Function FormatContactAddress( ByVal ContactName, ByVal AddressType, ByVal Flags )
00200 ** 
00201 **   '
00202 **   ' Default to a blank address
00203 **   '
00204 **   FormatContactAddress = "~no address on file~"
00205 ** 
00206 **   '
00207 **   ' Get a contact item that matches the name
00208 **   '
00209 **   dim ContactItem
00210 **   set ContactItem = dapp.db.getItem( "Contacts", ContactName )
00211 ** 
00212 **   '
00213 **   ' Check the result of the query.  We should never call this routine
00214 **   '  with a bad contact name, but just in case...
00215 **   '
00216 **   if( not ContactItem.Cursor.RowCount = 1 ) then _
00217 **     MsgBox "Bad Row Count " & ContactItem.Cursor.RowCount & " for " & ContactName
00218 ** 
00219 **   '
00220 **   ' Get a string list for formatting the resulting
00221 **   '  address field.
00222 **   '
00223 **   dim addressInfo
00224 **   set addressInfo = dapp.getStringList
00225 ** 
00226 **   '
00227 **   ' If the address type was specified then assume he's referring to
00228 **   '  one of the sub-addresses and try to find a match for that.  You can
00229 **   '  find a list of address sub-types in the "Address Type" category.
00230 **   '
00231 **   if( AddressType <> "" ) then
00232 ** 
00233 **     '
00234 **     ' Get the address items for this contact
00235 **     '
00236 **     dim addressItems
00237 **     set addressItems = ContactItem.con("has","Address","for")
00238 ** 
00239 **     '
00240 **     ' Filter for the particular address type we're looking for
00241 **     '
00242 **     addressItems.cursor.filter "2,CTI,,is an,Address Type," & AddressType
00243 ** 
00244 **     '
00245 **     ' If we found one address item, then we can pull all the
00246 **     '  field data from it.
00247 **     '
00248 **     if( addressItems.count = 1 ) then
00249 ** 
00250 **       dim addressItem
00251 **       set addressItem = addressItems.item(0)
00252 ** 
00253 **       if( instr(Flags,"T") ) then _
00254 **         addressInfo.append "(" & AddressType & ")"
00255 ** 
00256 **       if( ContactItem.extField("FileAs").value = "Person" ) then
00257 **         addressInfo.append ContactItem.field("Employed by Contacts").value
00258 **       end if
00259 ** 
00260 **       addressInfo.append addressItem.field("Street").value
00261 **       addressInfo.append addressItem.field("City").value  & ", " & _
00262 **                          addressItem.field("State").value & "  " & _
00263 **                          addressItem.field("ZipPostal").value
00264 ** 
00265 **       if( addressItem.field("Note").value <> "" ) then
00266 **         addressInfo.append "Note: " & _
00267 **         addressItem.field("Note").value
00268 **       end if
00269 ** 
00270 **     end if
00271 ** 
00272 **   end if
00273 ** 
00274 **   '
00275 **   ' If the address info has no lines in it, then we were not able to
00276 **   '  find a match in the sub-address.  Assume then we are going to the
00277 **   '  primary address.
00278 **   '
00279 **   if( addressInfo.count = 0 ) then
00280 ** 
00281 **     if( instr(Flags,"T") ) then _
00282 **       addressInfo.append "(Primary)"
00283 ** 
00284 **     if( ContactItem.extField("FileAs").value = "Person" ) then
00285 **       addressInfo.append ContactItem.field("Employed by Contacts").value
00286 **     end if
00287 ** 
00288 **     addressInfo.append ContactItem.field("Street Address").value
00289 **     addressInfo.append ContactItem.field("City").value  & ", " & _
00290 **                        ContactItem.field("State").value & "  " & _
00291 **                        ContactItem.field("Zip").value
00292 ** 
00293 **   end if
00294 ** 
00295 **   '
00296 **   ' Add the other fields to the address format
00297 **   '
00298 **   addressInfo.append ContactItem.field("Phone List").value
00299 **   addressInfo.append ContactItem.field("Business Email").value
00300 **   addressInfo.append ContactItem.field("License").value
00301 ** 
00302 **   '
00303 **   ' If this address is being designated as a "bill-to" address,
00304 **   '  then make some extra effort to highlight that.
00305 **   '
00306 **   if( dfrm.field("Bill to").value = "1" ) then
00307 **     addressInfo.prepend "<< Bill to Address >>"
00308 **   end if
00309 ** 
00310 **   '
00311 **   ' Format the whole address field into a single, crlf
00312 **   '  delimited string.
00313 **   '
00314 **   if( addressInfo.count > 0 ) then _
00315 **     FormatContactAddress = addressInfo.join
00316 ** 
00317 ** End Function
00318 ** '
00319 ** ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' 
00320 ** \endcode
00321 **
00322 ** It may seem bulky at first glance, but this code worked out really well,
00323 **  and when in the middle of writing it, all I had to do was focus on the
00324 **  goal of what I was after, and not on the API interface to Commence, which
00325 **  can be somewhat distracting.  This documentation makes working with and
00326 **  learning the Dumont API a breeze.
00327 **
00328 ** Give it a try!
00329 **
00330 **
00331 
00332 */
00333 namespace cmcDatabaseApi {
00334 
00335 #define CONCAT_DELIMITER " -> "
00336 
00337 extern const QString vbCr;
00338 extern const QString vbLf;
00339 extern const QString vbCrLf;
00340 extern const QString vbLfCr;
00341 extern const QString vbCrCr;
00342 extern const QString vbLfLf;
00343 extern const QString vbCrCrLf;
00344 
00345 // QString YesNo(bool i_bool);
00346 // bool isTrue(const QString & yesNo);
00347 // bool isFalse(const QString & yesNo);
00348 
00349 #define TRIN(v_msg) dumont::Trin( __FILE__, __LINE__, v_msg );
00350 #define TRAC(v_msg) dumont::Trac( __FILE__, __LINE__, v_msg );
00351 #define TROT(v_msg) dumont::Trot( __FILE__, __LINE__, v_msg );
00352 
00353 QString prependZero   ( QString   i_string, int i_count                     );
00354 //QString dq            ( QString   v_string                                  );
00355 QString var           ( QString   v_var, QString v_fld                      );
00356 QString var           ( QString   v_var, QString v_fld, QString v_val       );
00357 QString delVar        ( QString   v_var, QString v_fld                      );
00358 QString packDate      ( QDate     i_date = QDate::currentDate()             );
00359 QString packTime      ( QTime     i_time = QTime::currentTime()             );
00360 QString packDateTime  ( QDateTime dateTimeIn = QDateTime::currentDateTime() );
00361 QString packDateTime  ( QDate     i_date, QTime i_time                      );
00362 QString unpackDateTime( QString   i_packedDateTime                          );
00363 QString guid          ( void                                                );
00364 QString formatOLtext  ( QString i_text                                      );
00365 QString formatOLdate  ( QDateTime dateTimeIn                                );
00366 QString formatOLdate  ( QDate dateIn                                        );
00367 QString formatOLurl   ( QString i_filePath                                  );
00368 QString formatOLics
00369 ( 
00370   QString   i_organizerEmail,
00371   QString   i_summary, 
00372   QDateTime i_dateStart, 
00373   QDateTime i_dateEnd, 
00374   QString   i_location, 
00375   QString   i_uid, 
00376   QString   i_desc
00377 );
00378 
00379 QString fixCase( QString i_value );
00380 QString fixPhone( QString i_value );
00381 bool phoneTooShort(void);
00382 QString vbString(QString i_string);
00383 void dumpString( QString i_string );
00384 
00385 void Trout( QString v_leader, QString v_file, QString v_line, QString v_msg );
00386 void Trout( QString v_leader, QString v_file, int     v_line, QString v_msg );
00387 
00388 void Trin( QString v_file, int     v_line, QString v_msg = "" );
00389 void Trac( QString v_file, int     v_line, QString v_msg = "" );
00390 void Trac( QString v_file, QString v_line, QString v_msg = "" );
00391 void Trot( QString v_file, int     v_line, QString v_msg = "" );
00392 
00393 void ErrorMessage(HRESULT hr);
00394 
00395 QString dateTimeStamp(const QDateTime & dateTime = QDateTime::currentDateTime(), long length=14);
00396 QString dateTimeStamp(long length);
00397 QString dateTimeStamp( const QString & delimiter );
00398 
00399 class cmcApplication;
00400 class cmcApplications;
00401 class cmcDatabase;
00402 class cmcConversation;
00403 class cmcCdaItem;
00404 class cmcActiveViewInfo;
00405 
00406 /*!
00407 ** \brief Class Name without the namespace
00408 **
00409 ** This is a global support function that strips off the namespace identifier
00410 **  from the class name.  For instance, all of the CDA objects exist in the
00411 **  cmcDatabaseApi name space.  This means that the class name for any
00412 **  of these objects in this system is going to be:
00413 **
00414 ** \par namespace examples
00415 ** \code
00416 ** cmcDatabaseApi::cmcObject      becomes cmcObject
00417 ** cmcDatabaseApi::cmcApplication becomes cmcApplication
00418 ** cmcDatabaseApi::cmcField       becomes cmcField
00419 ** \endcode
00420 **
00421 ** The purpose for this function is to extract the actual class name of the
00422 **  object for storage in the database definition extension xml file.
00423 **
00424 ** \par xml file example
00425 ** \code
00426 ** <cmcApplication name="KES.mwp" >
00427 **   <objectName type="static" >KES.mwp</objectName>
00428 **   <comment type="static" >KES Main Database</comment>
00429 **   <description type="static" ></description>
00430 **   <cmcCategoryDefs name="Categories" >
00431 **     <objectName type="static" >Categories</objectName>
00432 **     <comment type="static" ></comment>
00433 **     <description type="static" ></description>
00434 **     <documentation type="static" ></documentation>
00435 **     <cmcCategoryDef name="Activity" >
00436 ** \endcode
00437 **
00438 */
00439 QString className( QObject * object );
00440 
00441 //const char * cn( const char * );
00442 
00443 /*!
00444 ** \brief Commence Base Object
00445 **
00446 ** This is the object upon which all Commence objects are derived.  This object provides
00447 **  for the basic object functionality such as an integrated logger and reference to
00448 **  the application object from which this object sprang.
00449 **
00450 ** Reference to the application object is required so that any Commence object rooted here
00451 **  can access the Commence Application API that created it.  This reference to the API also
00452 **  allows for multiple Commence API's to run concurrently through the DumontEXE framework, 
00453 **  thus providing vbScript access to multiple Commence databases concurrently - something
00454 **  that's not possible given the Commence API.
00455 **
00456 */
00457 class cmcObject:
00458   public QObject
00459 {
00460   Q_OBJECT
00461 
00462   enum
00463   {
00464     TRACE_LEVEL   = 7,
00465     OBJECT_CREATE = 8
00466   };
00467 
00468   /*!
00469   ** \brief Object Alias Name \n
00470   **
00471   ** This property holds the aliasName property.
00472   **
00473   */
00474   Q_PROPERTY( QString aliasName     READ aliasName    WRITE setAliasName      DESIGNABLE true  SCRIPTABLE true  STORED true  )
00475 
00476   /*!
00477   ** \brief Comment Property \n
00478   **
00479   ** This property holds the comment property.
00480   **
00481   */
00482   Q_PROPERTY( QString comment       READ comment       WRITE setComment       DESIGNABLE true  SCRIPTABLE true  STORED true  )
00483 
00484   /*!
00485   ** \brief Description Property \n
00486   **
00487   */
00488   Q_PROPERTY( QString description   READ description   WRITE setDescription   DESIGNABLE true  SCRIPTABLE true  STORED true  )
00489 
00490   /*!
00491   ** \brief Documentation Property \n
00492   **
00493   */
00494   Q_PROPERTY( QString documentation READ documentation WRITE setDocumentation DESIGNABLE true  SCRIPTABLE true  STORED true  )
00495 
00496   /*!
00497   ** \brief GUID property \n
00498   **
00499   */
00500   Q_PROPERTY( QString guid          READ guid          WRITE setGuid          DESIGNABLE true  SCRIPTABLE true  STORED true  )
00501 
00502   /*!
00503   ** \brief Index property \n
00504   **
00505   */
00506   Q_PROPERTY( long index            READ index                                DESIGNABLE true  SCRIPTABLE true  STORED true  )
00507 
00508   public:
00509 
00510     /*!
00511     ** \brief Copy Constructor \n
00512     **
00513     */
00514     cmcObject( const cmcObject & copy );
00515 
00516     /*!
00517     ** \brief Simple Constructor \n
00518     **
00519     */
00520     cmcObject( QObject * parent = NULL );
00521 
00522     /*!
00523     ** \brief Standard Constructor \n
00524     **
00525     ** This constructor is used by default for nearly all createObject operations.
00526     **
00527     */
00528     cmcObject
00529     ( 
00530       /*!
00531       ** Object Name \n\n
00532       **
00533       ** All \ref cmcObject "cmcObjects" in the system should be named.  This can be any 
00534       **  string of characters but really should be limited to good variable name 
00535       **  characters (in other words, 
00536       **  no punctuation or other silly characters).  The object name will probably tolerate
00537       **  various punctuation characters, but care should be taken when creating these kinds
00538       **  of category names, field names, connection names and so on.  Consider that these
00539       **  categories and fields and connections may be exported to other systems, and other
00540       **  system can be rather intolerant of strange punctuation marks within category and
00541       **  field names.  Care should be taken when naming objects in your system.
00542       **  \n\n\n
00543       **
00544       */
00545       const QString & objectName,
00546 
00547       /*!
00548       ** Application Reference \n\n
00549       **
00550       ** All \ref cmcObject "cmcObjects" require a reference to the application object that 
00551       **  created it.  This
00552       **  is an internal reference and is mostly provided for convenience, but also to insure
00553       **  that objects that are created within the application also get properly destroyed
00554       **  by the application when the application itself is destroyed.  In the case of
00555       **  detail forms and cursors and rowsets, the objects are not directly parented by the
00556       **  application object, but, rather, indirectly spawned from the application object.
00557       **  These objects can quickly be lost within the system (think memory leak) causing
00558       **  problems shutting down Commence (Commence won't shut down when there are references
00559       **  to Commence still open - something that happens when a vbs file crashes midstream).
00560       **  In the CDA, when an application is closed, all objects that were created by that
00561       **  application are properly released.  This means that even if your vbScript file 
00562       **  crashes, and leave a component open, once your Commence database application is
00563       **  shut down, and removed from the Dumont.ROT, all left-over objects will be
00564       **  properly destroyed, allowing Commence to also shut down properly.
00565       **  \n\n\n
00566       **
00567       */
00568       cmcApplication * application, 
00569 
00570       /*!
00571       ** Direct Parent Reference \n\n
00572       **
00573       ** Not all objects within the system are directly parented by the app() object.  These
00574       **  objects include the detail forms and cursors and rowsets.  These aforementioned
00575       **  objects get parented by the vbScript program that requested them.  This allows the
00576       **  vbScript program that created them to also take care of destroying them.  In these cases
00577       **  these objects (forms and rowsets) receive no parent, and get parented by the vbScript
00578       **  program.
00579       **  \n\n\n
00580       **
00581       */
00582       QObject * parent =  NULL 
00583 
00584     ); // endcmcObject
00585 
00586     /*!
00587     ** \brief Default Destructor \n
00588     **
00589     **
00590     */
00591     virtual ~cmcObject();
00592 
00593     /*!
00594     ** \brief Return the cmcObject parent pointer \n
00595     **
00596     ** This function overrides the base-class QObject::parent() function 
00597     **
00598     */
00599     cmcObject * parent();
00600 
00601     /*!
00602     ** \brief Set the application pointer \n
00603     **
00604     ** This method turns a dispatch pointer into a cmcApplication object and stores it
00605     **  along with the object.  This is necessary when wrapping a regular Commence form
00606     **  dispatch pointer, because, normally, we don't get a reference to the application
00607     **  object that the form is running from.
00608     **
00609     */
00610     virtual void setApp( void * dispatch, const QString & dumontCategory = "Dumont" );
00611 
00612     /*!
00613     ** \brief Set the application object \n
00614     **
00615     ** When a form is instantiated directly from a form script, it does not
00616     **  include information about the active applicaiton.  During that form
00617     **  registration process the form wrapper will query the system for its
00618     **  application object, and if it finds one that is registered, it will
00619     **  set the application object using that registered object.
00620     **
00621     */
00622     virtual void setApp( cmcApplication * application );
00623 
00624   public slots:
00625 
00626     /*!
00627     ** \brief Return pointer to Application \ref ROT \n
00628     **
00629     ** The application R.O.T. (running object table) is a static table of all the
00630     **  registered running applications.
00631     **
00632     */
00633     static cmcApplications * apps() { return( &s_applications ); }
00634 
00635     /*!
00636     ** \brief Return the Commence application object \n
00637     **
00638     ** Every object references a single application object.  The application object provides
00639     **  access to the database object, conversation object, cursors and rowsets and so
00640     **  on.
00641     **
00642     */
00643     virtual cmcApplication * app();
00644 
00645     /*!
00646     ** \brief Return the Commence application object \n
00647     **
00648     ** Every object references a single application object.  The application object provides
00649     **  access to the database object, conversation object, cursors and rowsets and so
00650     **  on.
00651     **
00652     */
00653     virtual cmcApplication * application();
00654 
00655     /*!
00656     ** \brief Return the Commence database object \n
00657     **
00658     ** This is a convenience function to reference the database object of the application.
00659     **  It is the same as referencing the database object from the Application object
00660     **  such as Form.Application.Database... and so on.
00661     **
00662     */
00663     virtual cmcDatabase * db();
00664 
00665     /*!
00666     ** \brief Return the Commence DDE Conversation object \n
00667     **
00668     ** This is a convenience function to reference the DDE conversation object of the 
00669     **  application.  It is the same as referencing the conversation object from the 
00670     **  database object such as in 
00671     **  Form.Application.Database.getConversation("GetData", "Commence")
00672     **
00673     */
00674     virtual cmcConversation * cv();
00675 
00676     /*!
00677     ** \brief Object Instance ID \n
00678     **
00679     ** Every object created within the Dumont system represents an 'object instance'.
00680     **  This is true of all detail forms registered in Dumont, cursors, rowsets,
00681     **  fields and connections.  When an object is destroyed (or closed), the 
00682     **  instance memory it occupies is freed back into the system.
00683     **
00684     ** Sometimes referring to an object by name can be problemmatic, if there is a
00685     **  second or third object in the system with the same name.  Take, for instance,
00686     **  detail forms.  When two detail forms are opened on the same category
00687     **  both detail forms will be registered in the form ROT with the same name 
00688     **  since the form name is provided by Commence.
00689     **
00690     ** If you wish to run an external script and give it reference to a specific
00691     **  form instance you can do so by passing to that program this instanceID
00692     **  value.  This value is unique for every object instance.  If the form is
00693     **  closed and reopened, then it will receive a new instance ID.
00694     **
00695     ** Therefore, this reference object instance ID is a temporary value.
00696     **
00697     ** \par vbScript Example ~ Referring to a form by Instance
00698     ** \code
00699     ** dim dexe: set dexe = createObject("Dumont.EXE")
00700     ** dim dfrm: set dfrm = dexe.form(form)
00701     ** dexe.launch "C:\Commence\Scripts\FixMyFile.vbs " & dfrm.instanceID
00702     ** \endcode
00703     **
00704     ** \return string ~ unique instance identifier
00705     */
00706     virtual QString instanceID();
00707 
00708     /*!
00709     ** \brief CDA Item \n
00710     **
00711     **
00712     */
00713     virtual cmcCdaItem * cdaItem();
00714 
00715     /*!
00716     ** \brief object index number \n
00717     **
00718     ** This returns the index of the object within the list of objects.
00719     **
00720     */
00721     virtual long index();
00722 
00723     /*!
00724     ** \brief Object Name \n
00725     **
00726     ** Calling this method is identical to calling the objectName() method.  It is provided 
00727     **  simply for convenience, and the fact that myObject.name is much easier to remember,
00728     **  and more intuitive, than myObject.objectName().
00729     **
00730     */
00731     QString name();
00732 
00733     /*!
00734     ** \brief Return the object Alias Name \n
00735     **
00736     ** \sa setAliasName, \ref aliasNames
00737     **
00738     */
00739     QString aliasName();
00740 
00741     /*!
00742     ** \brief Set the object Alias Name \n
00743     **
00744     ** \sa aliasName, \ref aliasNames
00745     **
00746     */
00747     void setAliasName( const QString & value );
00748 
00749     /*!
00750     ** \brief Read the One-line Comment \n
00751     **
00752     ** The comment field is designed to provide for a quick, one-line comment reminder of
00753     **  the purpose of this object.  It is used primarily for the documentation package and
00754     **  doesn't have any functional impact over the system.
00755     **
00756     ** \image html cmcObjectComment.png
00757     **
00758     ** \par xml example of Description and Comment and Documentation
00759     ** \code
00760     ** <cmcCategoryDef name="Address" >
00761     **   <objectName type="static" >Address</objectName>
00762     **   <comment type="static" >Contact Multiple Address</comment>
00763     **   <description type="static" >This category is used to catalog multiple addresses
00764     ** for a single contact.  Each address can be given 
00765     ** designations such as 'home', 'work', 'shipping',
00766     ** 'mailing', 'primary', 'secondary' and so on.</description>
00767     **   <documentation type="static" ></documentation>
00768     ** \endcode
00769     **
00770     ** \sa ObjectExtensions, setComment, description, setDescription, documentation, setDocumentation
00771     **
00772     */
00773     virtual QString comment();
00774 
00775     /*!
00776     ** \brief Set then One-line Comment \n
00777     **
00778     ** This sets the comment value for this object.  Note that after setting the comment field
00779     **  in order for the comment to be remembered permanently, the scripting program must
00780     **  call cmcApplication.saveDefs in order for the comment to be permanently committed to
00781     **  the database definition.
00782     **
00783     ** \sa ObjectExtensions, comment, description, setDescription, documentation, setDocumentation
00784     */
00785     virtual void setComment( const QString & value );
00786 
00787     /*!
00788     ** \brief Read the Multi-line Description \n
00789     **
00790     ** The description field is used to provide a little bit more documentation about the
00791     **  object in question.  In the case of the dumont user interface, the description field
00792     **  is provided as a hint pop-up.  When the user flys his mouse over any of the designated
00793     **  objects, the description field is used to further illustrate the purpose of the 
00794     **  object definition within the system.
00795     **
00796     ** \image html cmcObjectDescription.png
00797     **
00798     ** \par Object Extensions example of Description and Comment and Documentation
00799     ** \code
00800     ** <cmcCategoryDef name="Address" >
00801     **   <objectName type="static" >Address</objectName>
00802     **   <comment type="static" >Contact Multiple Address</comment>
00803     **   <description type="static" >This category is used to catalog multiple addresses
00804     ** for a single contact.  Each address can be given 
00805     ** designations such as 'home', 'work', 'shipping',
00806     ** 'mailing', 'primary', 'secondary' and so on.</description>
00807     **   <documentation type="static" ></documentation>
00808     ** \endcode
00809     **
00810     ** \sa ObjectExtensions, setDescription, comment, setComment, documentation, setDocumentation
00811     */
00812     virtual QString description();
00813 
00814     /*!
00815     ** \brief Set the Multi-line Description \n
00816     **
00817     ** When setting the description, you should set the value to something slightly more meaningful
00818     **  than a single one-liner comment, but less then an entire documentation package.  Since
00819     **  this field is used in the 'hint' text of the dumont explorer, it should be kept reasonably
00820     **  short.
00821     **
00822     ** \sa ObjectExtensions, description, comment, setComment, documentation, setDocumentation
00823     */
00824     virtual void setDescription( const QString & value );
00825 
00826     /*!
00827     ** \brief Read the Full Documentation \n
00828     **
00829     ** The documentation field is designed to provide a full text document for this object.  The
00830     **  document
00831     **
00832     ** \sa ObjectExtensions, comment, setComment, description, setDescription, setDocumentation
00833     */
00834     virtual QString documentation();
00835 
00836     /*!
00837     ** \brief Set the One-line Comment \n
00838     **
00839     ** \sa ObjectExtensions, comment, setComment, description, setDescription, documentation
00840     */
00841     virtual void setDocumentation( const QString & value );
00842 
00843     /*!
00844     ** \brief Read a GUID \n
00845     **
00846     **
00847     */
00848     virtual QString guid();
00849 
00850     /*!
00851     ** \brief Set a GUID \n
00852     **
00853     **
00854     */
00855     virtual void setGuid( const QString & newGuid );
00856 
00857 
00858     /*
00859     ** The following is part of the persistent object store \n
00860     **
00861     */
00862 
00863     virtual QVariant property( const QString & key, const QVariant & defaultValue = "" );
00864     virtual QVariant property( const char * key,    const char     * defaultValue = "" );
00865 
00866     virtual bool setProperty( const QString & key, const QVariant & value );
00867     virtual bool setProperty( const QString & key, const QString  & value );
00868 
00869     virtual long propertyCount();
00870 
00871     virtual QString propertyKey( const long index );
00872 
00873     virtual QVariant propertyValue( const long index );
00874 
00875 
00876 
00877 
00878     /*!
00879     ** \brief Read a Property \n
00880     **
00881     */
00882     virtual QString temp( const QString & key );
00883 
00884     /*!
00885     ** \brief Write to a Property \n
00886     **
00887     */
00888     virtual void setTemp( const QString & key, const QString & value );
00889 
00890     /*!
00891     ** \brief Return the property Count \n
00892     **
00893     */
00894     virtual long tempCount();
00895 
00896     /*!
00897     ** \brief Return a property key at index \n
00898     **
00899     */
00900     virtual QString tempKey( const long index );
00901 
00902     /*!
00903     ** \brief Return a property value at index \n
00904     **
00905     */
00906     virtual QString tempValue( const long index );
00907 
00908 
00909     static QString YesNo(bool i_bool);
00910 
00911     static bool isTrue(const QString & yesNo);
00912 
00913     static bool isFalse(const QString & yesNo);
00914 
00915     /*!
00916     ** \brief Double Quote \n
00917     **
00918     ** This is a convenience function for adding double quotes to strings.
00919     **  This is generally done before parameters are passed along to various dde 
00920     **  commands and filter functions.  This function is provided as part of the
00921     **  root Commence Database Api object library so that it is available to both
00922     **  the vbScripting environment and any object in the system.
00923     **
00924     ** \par dq example
00925     ** \code
00926     ** filter = "[GetFieldDefinition(" + dq(categoryName()) + "," + dq(fieldName()) + ")]";
00927     ** // filter == "[GetFieldDefinition("Person","Last,First")]"
00928     ** \endcode
00929     **
00930     ** One thing to note is, if the string already contains quotes, this can screw
00931     **  up a formatted parameter.  Therefore, this function double-quotes existing
00932     **  quote characters before quoting the entire string.  Therefore:
00933     **
00934     ** \par dq example with quoted string: itemName = "Jones, Bubba ("Jim") Alan"
00935     ** \code
00936     ** filter = "[GetField(" + dq(categoryName()) + "," + dq(itemName) + "," + dq(fieldName()) + ")]";
00937     ** // filter == "[GetField("Person","Jones, Bubba (""Jim"") Alan","Position")]"
00938     ** \endcode
00939     **
00940     */
00941     static QString dq
00942     (
00943       /*! string ~ input \n\n */
00944       const QString & string
00945 
00946     );
00947 
00948     /*!
00949     ** \brief Calculate a CRC
00950     **
00951     ** This takes a string of characters and calculates a
00952     **  CRC value for it.
00953     **
00954     */
00955     static QString crc8String
00956     (
00957       /*! string ~ input string \n\n */
00958       const QString & string
00959     );
00960 
00961     /*!
00962     ** \brief Pad a string \n
00963     **
00964     ** This will pad a string with another string until
00965     **  the result string is the desired length.
00966     **
00967     */
00968     static QString pad
00969     (
00970       /*! string ~ the input string \n\n */
00971       const QString & string,
00972 
00973       /*! string ~ the string to pad with \n\n */
00974       const QString & padString,
00975 
00976       /*! long ~ the overall desired length \n\n */
00977       long length
00978     );
00979 
00980     /*!
00981     ** \brief Prepend a string to a string \n
00982     **
00983     **
00984     */
00985     static QString prepend
00986     (
00987       /*! string to prepend (this is usually a single character) */
00988       const QString & prep,
00989 
00990       /*! input string */
00991       const QString string,
00992 
00993       /*! overall desired length of the return string */
00994       long count
00995 
00996     );
00997 
00998 
00999     /*!
01000     ** \brief Append a String using a Delimiter \n
01001     **
01002     ** Sometimes you will want to append a string to another string
01003     **  and you want to include a delimiter between the two strings.
01004     **  This means that you must first initialize the string to the
01005     **  first value, and then append any number of additional values
01006     **  so that you end up with, say, a comma delimited string, for
01007     **  instance.  This is a bit of a tricky exercise in vbScript
01008     **  when you're filling a string via a for/next loop.  To format
01009     **  the string properly you have to first test your existing string
01010     **  and if there is text in it already, then you need to include
01011     **  a separator.  If there is not text in it already then you can
01012     **  just apply your string... it gets confusing.
01013     **
01014     ** This function should make all that a breeze.
01015     **
01016     ** \par vbScript Example ~ Building a delimited string list
01017     ** \code
01018     ** dim retVal
01019     ** dim i: for i = 1 to Attendees.connectedItemCount
01020     **   Attendees.CurrentSelection = i
01021     **   retVal = dapp.appendString( retVal, Attendees.fieldValue("FirstName") )
01022     ** next
01023     ** '
01024     ** ' result: "Tom, Dick, Harry"
01025     ** '
01026     ** \endcode
01027     **
01028     ** \return Newly formatted String, containing the initial value, a delimiter,
01029     **          followed by the append value.
01030     */
01031     static QString appendString
01032     (
01033       /*! string ~ this is the initial string.  It can be blank, or
01034       **   it can already contain some data \n\n */
01035       const QString & initial,
01036 
01037       /*! string ~ this is the value you want appended.  It can be
01038       **   blank. \n\n */
01039       const QString & appendValue,
01040 
01041       /*! string ~ (default to ", " [comma space])  This is the
01042       **   delimiter.  It is an optional value.  If left off from
01043       **   the function call it will default to a comma followed by
01044       **   a space character. \n\n */
01045       const QString & separator = ", "
01046     );
01047 
01048     /*!
01049     ** \brief Add zeros to the beginning of a string \n
01050     **
01051     **
01052     */
01053     static QString prependZero
01054     (
01055       /*! input string \n\n */
01056       const QString & string,
01057 
01058       /*! number of zeros to prepend \n\n */
01059       long count
01060 
01061     );
01062 
01063     /*!
01064     ** \brief Access a Var field \n
01065     **
01066     **
01067     */
01068     static QString var( const QString & v_var, const QString & v_fld );
01069 
01070     /*!
01071     ** \brief Set a Var field \n
01072     **
01073     **
01074     */
01075     static QString var( const QString & v_var, const QString & v_fld, const QString & v_val );
01076 
01077     /*!
01078     ** \brief Delete a Variable \n
01079     **
01080     ** This deletes a variable from a Var field.
01081     **
01082     */
01083     static QString delVar( const QString & v_var, const QString & v_fld );
01084 
01085     /*!
01086     ** \brief Pack a Date \n
01087     **
01088     **
01089     */
01090     static QString packDate
01091     (
01092       /*! date ~ defaults to currentDate */
01093       const QDate & date = QDate::currentDate()
01094 
01095     );
01096 
01097     /*!
01098     ** \brief Pack a Time \n
01099     **
01100     **
01101     */
01102     static QString packTime( const QTime & i_time = QTime::currentTime() );
01103 
01104     /*!
01105     ** \brief Pack a Date Time \n
01106     **
01107     **
01108     */
01109     static QString packDateTime( const QDateTime & dateTimeIn = QDateTime::currentDateTime() );
01110 
01111     /*!
01112     ** \brief Pack a Date Time \n
01113     **
01114     **
01115     */
01116     static QString packDateTime( const QDate & i_date, const QTime & i_time );
01117 
01118     /*!
01119     ** \brief Unpack a Date Time \n
01120     **
01121     **
01122     */
01123     static QString unpackDateTime( const QString & i_packedDateTime );
01124 
01125     /*!
01126     ** \brief Format some text \n
01127     **
01128     **
01129     */
01130     static QString formatText( const QString & i_preText, const QString & i_text, const QString & i_postText );
01131 
01132     /*!
01133     ** \brief Fix the case of a string \n
01134     **
01135     **
01136     */
01137     static QString fixCase( const QString & i_value );
01138 
01139     /*!
01140     ** \brief Fix a Phone Number \n
01141     **
01142     **
01143     */
01144     static QString fixPhone( const QString & i_value );
01145 
01146     /*!
01147     ** \brief Tell if the phone was too short \n
01148     **
01149     **
01150     */
01151     static bool phoneTooShort();
01152 
01153     /*!
01154     ** \brief Make a vbString \n
01155     **
01156     **
01157     */
01158     static QString vbString( const QString & i_string);
01159 
01160     /*!
01161     ** \brief Dump a string binary to debug \n
01162     **
01163     ** This takes an input string and dumps it to the debug window in a ascii/binary
01164     **  form that makes it possible to examine the internals of the string.  This is
01165     **  useful for doing things like determining the contents of a string, including
01166     **  non-printable imbedded characters like vbCrLf.
01167     **
01168     ** \par Example Output
01169     ** \code
01170     **   dumDLL.dumpString dumFRM.toXml("*")
01171     **
01172     ** 0000: 3c 21 44 4f 43 54 59 50 45 20 51 43 6f 6d 6d 65  <!DOCTYPE QComme
01173     ** 0010: 6e 63 65 46 6f 72 6d 3e 0d 0a 3c 69 74 65 6d 20  nceForm>..<item 
01174     ** 0020: 66 6f 72 6d 4e 61 6d 65 3d 22 44 75 6d 6f 6e 74  formName="Dumont
01175     ** 0030: 22 20 63 61 74 65 67 6f 72 79 4e 61 6d 65 3d 22  " categoryName="
01176     ** 0040: 44 75 6d 6f 6e 74 22 20 69 74 65 6d 4e 61 6d 65  Dumont" itemName
01177     ** 0050: 3d 22 74 65 73 74 22 20 69 74 65 6d 43 6c 61 72  ="test" itemClar
01178     ** 0060: 69 66 79 3d 22 22 20 3e 0d 0a 20 20 20 3c 66 69  ify="" >..   <fi
01179     ** 0070: 65 6c 64 30 20 6e 61 6d 65 3d 22 4e 61 6d 65 22  eld0 name="Name"
01180     ** 0080: 20 3e 74 65 73 74 3c 2f 66 69 65 6c 64 30 3e 0d   >test</field0>.
01181     ** 0090: 0a 20 20 20 3c 66 69 65 6c 64 31 20 6e 61 6d 65  .   <field1 name
01182     ** \endcode
01183     **
01184     */
01185     static void dumpString( const QString & i_string );
01186 
01187     bool showWarnings();
01188     void showWarnings(bool set);
01189 
01190     /*!
01191     ** \brief Return Error Object \n
01192     **
01193     ** This returns a pointer to the error element of this object.
01194     **
01195     */
01196     cmcError * error();
01197 
01198     /*!
01199     ** \brief TimeDate code stamp \n
01200     **
01201     ** \return String of Date/Time stamp
01202     */
01203     QString dateTimeStamp( long length );
01204 
01205     /*!
01206     ** \brief Time Date code stamp \n
01207     **
01208     */
01209     QString dateTimeStamp( const QDateTime & dateTime = QDateTime::currentDateTime(), long length = 14 );
01210 
01211     /*!
01212     ** \brief Set the trace level \n
01213     **
01214     */
01215     void trace( long flags );
01216 
01217     /*!
01218     ** \brief Get the trace level \n
01219     **
01220     **
01221     */
01222     long trace();
01223 
01224     /*!
01225     ** \brief Return a copy of the form's Active View Info \n
01226     **
01227     ** This method returns a copy of the Active View Info that was true when this
01228     **  request was made.  This allows the user to determine the AVI that caused
01229     **
01230     */
01231     cmcActiveViewInfo * avi();
01232 
01233     /*!
01234     ** \brief Get the String List object \n
01235     **
01236     ** This will create a new String List object and return it to the caller.
01237     **
01238     */
01239     cmcStringList * getStringList
01240     (
01241       /*! long ~ Flags for creating the object
01242       **
01243       ** \li 0 ~ no flags (default)
01244       ** \li 1 ~ allow duplicates
01245       */
01246       long flags = 0
01247     );
01248 
01249   signals:
01250 
01251   protected:
01252 
01253     /*!
01254     ** \brief Error Element \n
01255     **
01256     ** Maintain a local reference to the error element for this object.
01257     **
01258     */
01259     cmcError err;
01260 
01261     /*!
01262     ** \brief Active View Info \n
01263     **
01264     **
01265     */
01266     cmcActiveViewInfo * m_avi;
01267 
01268     /*!
01269     ** \brief Reference a CDA item for this object \n
01270     **
01271     */
01272     QPointer<cmcCdaItem> m_cdaItem;
01273 
01274   private:
01275 
01276     /*!
01277     ** \brief Global Flag to Indicate Warnings
01278     **
01279     **
01280     */
01281     static bool s_showWarnings;
01282 
01283     /*
01284     ** This is an instance ID for this object instance.  It can be
01285     **  used to obtain a reference to this object by string value.
01286     **
01287     */
01288     QUuid m_instanceID;
01289 
01290     /*!
01291     ** \brief Trace Flags \n
01292     **
01293     */
01294     long m_traceFlags;
01295 
01296     /*!
01297     ** \brief Local Property Store \n
01298     **
01299     */
01300     QHash<QString,QVariant> m_props;
01301 
01302     /*!
01303     ** \brief Static Applications Pointer \n
01304     **
01305     ** Every Commence object has access to the global running
01306     **  object table.
01307     **
01308     */
01309     static cmcApplications s_applications;
01310 
01311     /*!
01312     ** \brief Reference the Application object \n
01313     **
01314     */
01315     QPointer<cmcApplication> m_application;
01316 
01317     /*!
01318     ** \brief Extended Properties store \n
01319     **
01320     */
01321     QHash<QString,QString> m_temp;
01322 
01323 }; // endclass cmcObject:
01324 
01325 } // namespace cmcDatabaseApi
01326 
01327 Q_DECLARE_METATYPE(cmcDatabaseApi::cmcObject) 
01328 
01329 #endif // #ifndef CDA_OBJECT_H
01330 
 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