DumontEXE 0.0.1
DumontEXE.h
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 /*!
00026 ** \mainpage DumontEXE - Dumont Uses Multitudes Of Nifty Techniques
00027 **
00028 ** \note <b>This project has not been released yet!  This documentation is here for
00029 **        reference purposes only.  If you are interested in using this project
00030 **        in one of your Commence databases (like I am) then shoot an email to
00031 **        mark@lorimarksolutions.com </b>
00032 ** 
00033 ** Dumont: A small program designed to extend the programming capabilities 
00034 **  of the Commence Database API.
00035 **
00036 ** The DumontEXE project represents Phase-II of a scripting enhancement effort
00037 **  designed expressly for the Commence database system available from the 
00038 **  http://www.commence.com website.
00039 **
00040 ** The Dumont project started somewhere in late 2002.  It was an attempt
00041 **  to improve on the Commence API which, quite honestly, as cool as the Commence
00042 **  database tool is, the API is a mess.  All the programming interface is through
00043 **  visual basic, and as easy as that can be at times, deploying truly robust 
00044 **  applications is difficult when your only primary programming interface is 
00045 **  vbScripting.  It is for me anyhow.
00046 **
00047 ** That early Dumont application did little more than allow manipulation of memo
00048 **  fields (aka; large text fields) in an .ini file type of format, in an attempt
00049 **  to break the 100 field limit of the Commence database..  The effort
00050 **  to get even that to function reliably was excrutiating, since, at that time, I knew
00051 **  just about nothing about COM and the process of automating applications through it.
00052 **
00053 ** Late in the fall of 2006 I decided to rewite Dumont in an open-source platform
00054 **  using the Qt development library from http://qt.nokia.com/ .  My desire 
00055 **  there was to produce a truly feature-rich programming extension library for
00056 **  Commence they way I had envisioned - by subclassing cursors and rowsets and
00057 **  fields and connections and so on - and to make it open-source which would mean
00058 **  that anyone would be able to contribute.
00059 ** 
00060 ** The primary hurdle there was COM.  The Qt programming library, in its open-source
00061 **  version offers no COM support.  I had to develop this component by hand. Holy, moly,
00062 **  what a task that was!  It took me six months of hard research and testing and
00063 **  prototyping and reading and researching just to get my first COM interface to
00064 **  function.  I'm not talking about writing a COM client, something that talks to
00065 **  Outlook or Word, but a COM server - an entirely different animal.
00066 **
00067 ** Qt offers a COM extension in their purchased version, but I wanted to keep this
00068 **  an open-source product, so I have refused to bite the bullet and pay for a license,
00069 **  as tempting as it has been.  Believe me, it's been tempting.
00070 **
00071 ** In the spring of 2007 I finally had a functioning DLL that had a COM interface and
00072 **  did a pretty-darned good job of subclassing Commence objects, including cursors and
00073 **  rowsets and fields and connections, just like I had envisioned.  You can get to the
00074 **  documentation and source code for that project here: http://dumont.showoff-db.org
00075 **  I put the package
00076 **  into production and started using it immediately.  I built in to it a feature for
00077 **  quickly including script portions into other scripts, allowing me to modularize
00078 **  my code in my projects.  I added a changeLog functionality that captured in an
00079 **  xml file every change to every field and connection on every item.  It worked 
00080 **  great.
00081 **
00082 ** But, there were a few things missing.  For one, I couldn't easily produce a
00083 **  running object table for Commence.  If you are unfamiliar with this concept, 
00084 **  a running object table allows any application from any location to get a copy of
00085 **  any other application.  In the case of Commence, you acquire a 'handle' to the
00086 **  database from a form by specifying: Form.Application.Database.getCursor(...).
00087 **  This function works, and gives you a handle to a cursor in your currently open
00088 **  database.  If you are running a .vbs (external application) to Commence, and
00089 **  you want to get a cursor on a category, you do it slightly differently.  You
00090 **  would say; createObject("Commence.DB").getCursor(...) or something to that
00091 **  effect (I'm just talking here, I'm not trying to learn you how to program).
00092 **
00093 ** Well, in those two examples, if you have two databases open, how do you 'specify'
00094 **  which database you want a handle to?  In the Form.Application version, you get
00095 **  the current database you're in.  In the createObject("Commence.DB") version
00096 **  you get... who knows, the first opened database?  the last?  It doesn't matter
00097 **  if it's not the one you want, and you can't direct windows to give you specifically
00098 **  a handle to a specific database.
00099 **
00100 ** Enter the DumontEXE project.
00101 **
00102 ** What the DumontEXE allows you to do is "Register" your application
00103 **  instance with Dumont.  When you do that the registration is filed by database name.
00104 **  What the DumontEXE then makes available to you is a get() function that will
00105 **  get a specific instance of a database by name.
00106 **
00107 ** This means, then, that for every database you open, if you register it with Dumont,
00108 **  then that same database will be available to any script.  I'll save the details
00109 **  for another help page, but suffice it to say that if you are currently running
00110 **  a script on a form in one database, and you want to fetch something from another
00111 **  database, it is now a trivial matter.
00112 **
00113 ** The DumontEXE project has all the same features and functionality as the DumontDLL
00114 **  project, plus a few extras (such as the DumontROT).  Plus it has a few general 
00115 **  improvements to some of the technology since the first iteration of the DumontDLL
00116 **  suffered a little bit of design-on-the-fly implementation degredation.
00117 **
00118 ** There are several clear advantages to using the Dumont API wrapper.  For one thing,
00119 **  while the API is completely backwards compatible with the Commence API, the Dumont
00120 **  offers significantly improved API functions.  These improvements result in cleaner
00121 **  looking vbScript code.  Cleaner looking code is easier to understand code.  And
00122 **  easier to understand code is easier to maintain.  Dumont also provides additional
00123 **  features that are not easy or readily available through the Commence API without
00124 **  a lot of special vbScript coding gymnastics.  With Dumont all these gymnastics
00125 **  are trivial, natural and taken care of internally.  This translates into a more
00126 **  efficient API.  Dumont can do things in ways that are just not possible in other
00127 **  frameworks.  The result is your vbScript programs will run faster, and be more
00128 **  reliable.
00129 ** 
00130 ** None the less.  Have a look.  Play around.  Give it a try.  Comment back.  And, by
00131 **  all means, jump on in and help!  Programming in C++ is easy and fun.
00132 **
00133 ** A good place to start is the page on the cmcDatabaseApi namespace.  That page
00134 **  is more-or-less at the heart of the project.  We are also working on a series of
00135 **  videos for better understanding of the component capabilities.
00136 **
00137 ** You can find those videos here: http://www.youtube.com/watch?v=Sx4JWp5GBoA
00138 **
00139 ** \author Mark Petryk ~ Lorimark Solutions, LLC.
00140 **
00141 */
00142 
00143 #ifndef DUMONTEXE_H_422FD07F_0597_4cbb_A034_9AE85166472E
00144 #define DUMONTEXE_H_422FD07F_0597_4cbb_A034_9AE85166472E
00145 
00146 /*
00147 ** Define application globals and constants here...
00148 **
00149 */
00150 #define ORG_DOMAIN  "Lorimark Solutions"
00151 #define APP_NAME    "DumontEXE"
00152 
00153 #include "version.h"
00154 
00155 /*
00156 ** Include any stock Qt files here...
00157 **
00158 */
00159 #include <QApplication>
00160 #include <QMainWindow>
00161 #include <QPointer>
00162 #include <QHash>
00163 
00164 
00165 class QTimerEvent;
00166 class QTreeWidgetItem;
00167 class QShowEvent;
00168 
00169 /*
00170 ** Include any application specific headers here.
00171 **
00172 */
00173 #include <ui_MainWindow.h>
00174 //#include "cmcExe.h"
00175 #include "DumontObject.h"
00176 
00177 void statusBar( const QString & message );
00178 
00179 /*
00180 ** Forward-declare any required classes here.  We do not include the
00181 **  header files for these classes here because it just increases the
00182 **  compile times unnecessarily.  This method is considered more
00183 **  practical - these are typical.
00184 **
00185 */
00186 class QAction;
00187 class QAction;
00188 class QListWidget;
00189 class QMenu;
00190 class QTextEdit;
00191 class QSystemTrayIcon;
00192 
00193 class QSqlDatabase;
00194 class QSqlRelationalTableModel;
00195 class QSqlRelationalDelegate;
00196 
00197 class winDumontEXE;
00198 class QxtLogger;
00199 class QxtLoggerWindow;
00200 
00201 #include "cmcObject.h"
00202 #include "cmcApplication.h"
00203 #include "cmcApplications.h"
00204 #include "cmcForm.h"
00205 #include "cmcExe.h"
00206 
00207 #define DumontEXE_CLSID   "{C7860C20-9B6F-4f31-8293-31CB0C1799F0}"
00208 #define DumontEXE_IID     "{2EF48B5D-2A56-42c9-9BAA-2D94603FC1C5}"
00209 #define DumontEXE_EVENTID "{9BAB97F2-8E41-45cf-AFD0-D720204A8E7D}"
00210 
00211 using namespace cmcDatabaseApi;
00212 
00213 /*!
00214 ** \brief Dumont Primary Application Interface object
00215 **
00216 ** This object represents the primary interface to the Dumont application.
00217 **  It is from here that you can wrap the various Commence objects, register
00218 **  applications into the DumontROT and do lots of other things.
00219 **
00220 **
00221 ** \todo Provide an application update module to allow Dumont to check
00222 **  a central repository and bring down updates.  Be sure to include a
00223 **  mechanism whereby an update can be easily reversed.  Frankly, the
00224 **  whole cmcDatabaseApi modue should be placed into a plugin,
00225 **  where versions can be quickly and easily managed.  Also, I'd like
00226 **  to see the cmcDatabaseApi on a single code-base so that it can
00227 **  be compiled into a stand-alone dll, compiled into a stand-alone static
00228 **  executable, or compiled into a Qt plugin.
00229 */
00230 class DumontEXE:
00231   public DumontObject
00232 {
00233   Q_OBJECT
00234 
00235   /*
00236   ** Set this object up for automation through ActiveX.
00237   **
00238   */
00239   Q_CLASSINFO( "ClassHelp",      "Dumont Wrapper for Commence" )
00240   Q_CLASSINFO( "ClassID",        "{C7860C20-9B6F-4f31-8293-31CB0C1799F0}"  )
00241   Q_CLASSINFO( "InterfaceID",    "{2EF48B5D-2A56-42c9-9BAA-2D94603FC1C5}"  )
00242   Q_CLASSINFO( "EventID",        "{9BAB97F2-8E41-45cf-AFD0-D720204A8E7D}"  )
00243   Q_CLASSINFO( "RegisterObject", "yes"                         )
00244 
00245   public:
00246 
00247     /*!
00248     ** \brief Guid Output Formats \n
00249     **
00250     */
00251     enum GuidFormats
00252     {
00253       /*! \li 0 ~ "080b29a9175a4096b450b1ff11a7816c" \n\n */
00254       rawDataGuid,
00255 
00256       /*! \li 1 ~ "{080b29a9-175a-4096-b450-b1ff11a7816c}" <b>(default)</b> \n\n */
00257       registryGuid,
00258 
00259       /*! \li 2 ~ "_080b29a9_175a_4096_b450_b1ff11a7816c" \n\n */
00260       headerProtectGuid,
00261 
00262       /*! \li 3 ~ "IMPLEMENT_OLECREATE(<<class>>, <<external_name>>, 0x080b29a9, 0x175a, 0x4096, 0xb4, 0x50, 0xb1, 0xff, 0x11, 0xa7, 0x81, 0x6c);" \n\n */
00263       oleCreateGuid,
00264 
00265       /*! \li 4 ~ "DEFINE_GUID(<<name>>, 0x080b29a9, 0x175a, 0x4096, 0xb4, 0x50, 0xb1, 0xff, 0x11, 0xa7, 0x81, 0x6c);" \n\n */
00266       defGuid,
00267 
00268       /*! \li 5 ~ "static const GUID <<name>> = { 0x080b29a9, 0x175a, 0x4096, { 0xb4, 0x50, 0xb1, 0xff, 0x11, 0xa7, 0x81, 0x6c } };" \n\n */
00269       staticGuid
00270 
00271     };
00272 
00273 
00274     DumontEXE( QObject * parent = NULL );
00275 
00276     virtual ~DumontEXE();
00277 
00278     static DumontEXE * createObject( QObject * parent = NULL );
00279 
00280   public slots:
00281 
00282     /*!
00283     ** \brief Quick Test Slot \n
00284     **
00285     ** This slot is used for performing quick Qt tests without requiring
00286     **  a big API implementation or supporting objects.
00287     **
00288     */
00289     void test();
00290 
00291     /*!
00292     ** \brief Return Dumont's version number \n
00293     **
00294     **
00295     */
00296     QString version();
00297 
00298     /*!
00299     ** \brief Return a handle to the system log \n
00300     **
00301     */
00302     QxtLogger * log();
00303 
00304     /*!
00305     ** \brief Open/Fetch a logging window by name \n
00306     **
00307     ** This fetches a logging window by name.  You can have as many Logging
00308     **  windows in your system that you want - depending on memory limitations.
00309     **
00310     ** \par vbScript Example ~ Opening and Printing to a Logging Window
00311     ** \code
00312     ** dim dexe: set dexe = createObject("Dumont.EXE")
00313     ** dim dlog: set dlog = dexe.logWindow("MyLoggingWindow")
00314     ** 
00315     ** dlog.print "This message is appended to the log"
00316     ** \endcode
00317     **
00318     ** As long as the dumont application remains running, the contents of the
00319     **  logging window will remain.  You can clear and save the contents of the
00320     **  logging window, and show the logging window, and actually watch the
00321     **  logging window while information is being posted to it.
00322     **
00323     ** By specifying any of the position parameters, the window will be shown
00324     **  immediately.  By not specifying these parameters, the will will be placed
00325     **  in the last location.
00326     **
00327     ** \return Logger Window
00328     */
00329     QxtLoggerWindow * logWindow
00330     (
00331       /*! string ~ Title/Name of logging window \n\n */
00332       const QString & name = "Log Window",
00333 
00334       /*! boolean (default false) ~ show the window automatically \n\n */
00335       bool show = false,
00336 
00337       /*! boolean (default false) ~ clear the window automatically \n\n */
00338       bool clear = false,
00339 
00340       /*! integer (optional) ~ left/right position, defaults to last \n\n */
00341       long x = -1,
00342 
00343       /*! integer (optional) ~ top/bottom position, defaults to last \n\n */
00344       long y = -1,
00345 
00346       /*! integer (optional) ~ width, defaults to last \n\n */
00347       long w = -1,
00348 
00349       /*! integer (optional) ~ height, defaults to last \n\n */
00350       long h = -1
00351     );
00352 
00353     /*!
00354     ** \brief Return a handle to the main application window \n
00355     **
00356     */
00357     winDumontEXE * mainWindow();
00358 
00359     /*!
00360     ** \brief Send a debug message \n
00361     **
00362     */
00363     void debugClear();
00364     void debug( const QString & msg = "" );
00365     void debug( const long value )   { debug( QString::number(value)         ); }
00366     void debug( const double value ) { debug( QString::number(value)         ); }
00367     void debug( const bool value )   { debug( QString(value? "True":"False") ); }
00368 
00369     /*!
00370     ** \brief Send a debug message \n
00371     **
00372     */
00373     void print( const QString & msg = "" ) { debug( msg ); }
00374     void print( const long value )   { debug( QString::number(value)         ); }
00375     void print( const double value ) { debug( QString::number(value)         ); }
00376     void print( const bool value )   { debug( QString(value? "True":"False") ); }
00377 
00378     /*!
00379     ** \brief Send a warning message \n
00380     **
00381     */
00382     void warning( const QString & msg = "" );
00383     void warning( const long value )   { warning( QString::number(value) ); }
00384     void warning( const double value ) { warning( QString::number(value) ); }
00385     void warning( const bool value )   { warning( QString(value? "True":"False") ); }
00386 
00387     /*!
00388     ** \brief Send a critical message \n
00389     **
00390     */
00391     void critical( const QString & msg = "" );
00392     void critical( const long value )   { critical( QString::number(value) ); }
00393     void critical( const double value ) { critical( QString::number(value) ); }
00394     void critical( const bool value )   { critical( QString(value? "True":"False") ); }
00395 
00396     /*!
00397     ** \brief Send a fatal message \n
00398     **
00399     */
00400     void fatal( const QString & msg = "" );
00401     void fatal( const long value )   { fatal( QString::number(value) ); }
00402     void fatal( const double value ) { fatal( QString::number(value) ); }
00403     void fatal( const bool value )   { fatal( QString(value? "True":"False") ); }
00404 
00405     /*!
00406     ** \brief Return the Commence Running Applications Table \n
00407     **
00408     ** This function returns a handle to the Commence Running Applications Table.  From
00409     **  that table a user can gain access to any database that has been registered
00410     **  with the DumontEXE application.  This allows a single database Form script
00411     **  to access anything in a different database, *and* also allows extern .vbs 
00412     **  programs and other programs to access specific instances of running 
00413     **  Commence databases.
00414     **
00415     ** \par vbScript Example:
00416     ** \code
00417     ** dim dexe: set dexe = createObject("Dumont.EXE")
00418     ** dim dap1: set dap1 = dexe.applications.get("Leads Database")
00419     ** dim dap2: set dap2 = dexe.applications.get("Order Processing System")
00420     ** \endcode
00421     **
00422     ** The two handles, .dap1. and .dap2. now (probably) point to entirely two different
00423     **  Commence database application sessions.  I say 'probably' because it is entirely
00424     **  possible that one of the databases has been closed, or a different db opened
00425     **  since it was registered with Dumont.  
00426     **
00427     */
00428     cmcDatabaseApi::cmcApplications * applications();
00429 
00430     /*!
00431     ** \brief Fetch a specific application instance by name \n
00432     **
00433     **
00434     */
00435     cmcDatabaseApi::cmcApplication * application( const QString & databaseName );
00436     cmcDatabaseApi::cmcApplication * applications( const QString & databaseName )
00437     { return( application(databaseName) ); }
00438 
00439 
00440     cmcDatabaseApi::cmcApplication * application( long index );
00441     cmcDatabaseApi::cmcApplication * applications( long index )
00442     { return( application(index) ); }
00443 
00444 
00445     /*!
00446     ** \brief Return a wrapped application object \n
00447     **
00448     ** This function wraps an application object.  It is intended to be called from 
00449     **  a detail form vbScript with an existing application object handle as follows:
00450     **
00451     ** \par Form vbScript Example
00452     ** \code
00453     ** dim dexe: set dexe = createObject("Dumont.EXE")
00454     ** dim dapp: set dapp = dexe.app(Application)
00455     ** \endcode
00456     **
00457     */
00458     cmcDatabaseApi::cmcApplication * app( IDispatch * dispatch );
00459 
00460     /*!
00461     ** \brief Wrap a Form \n
00462     **
00463     ** This function wraps a regular Commence Form object with a specially enhanced
00464     **  Dumont Form object.  The Dumont Form object has significantly improved form
00465     **  handling functionalities.
00466     **
00467     ** \par vbScript Example ~ Wrapping a Commence Form
00468     ** \code
00469     ** dim dexe: set dexe = createObject("Dumont.EXE") ' Hook Dumont
00470     ** dim dfrm: set dfrm = dexe.form(Form)            ' Wrap Ourselves
00471     ** \endcode
00472     **
00473     ** Wrapping a form in this matter causes a special \ref cmcDatabaseApi::cmcForm "Form"
00474     **  object to be returned by Dumont.  It also causes this form object to be 
00475     **  registered in the Dumont Form \ref ROT list, providing access to this form 
00476     **  from other parts of the application.
00477     **
00478     */
00479     cmcDatabaseApi::cmcForm * form( IDispatch * dispatch );
00480 
00481     /*!
00482     ** \brief Return Current Date/Time Stamp \n
00483     **
00484     ** This function returns a string suitable for a date time stamp using
00485     **  the current system date/time.
00486     **
00487     ** \par vbScript Example ~ Time/Date stamp of current Date/Time
00488     ** \code
00489     ** dim dexe: set dexe = createObject("Dumont.EXE")
00490     ** msgBox "Current Date/Time Stamp: " & dexe.dateTimeStamp
00491     ** \endcode
00492     **
00493     ** \attention Do not try to use this function for producing extremely accurate
00494     **  time tracking - like tracking the running of a program, from some external
00495     **  program that runs multiple times.  For instance, you can call this function
00496     **  from a .vbs file, and you can run that .vbs file repeatedly, quickly.
00497     **  You can get in to a situation where multiple seperate instances of that
00498     **  .vbs program are hammering on this function, and even though one of
00499     **  the instances was launched first, it might not get to this function before
00500     **  another instance that was launched after... that's entirely up to windows.
00501     **  Therefore, you could have an instance that was launched before another 
00502     **  getting a time value later than the second... if that makes any sense at
00503     **  all.  Of course, all of this is only true if you are relying on the 
00504     **  millisecond return value.
00505     **
00506     ** \sa \ref dateTimeStamp(const QDateTime &,long) "dateTimeStamp( Date/Time, Length )"
00507     **
00508     ** \return String ~ Date/Time Stamp formatted to: \c yyyyMMddhhmmsszzz
00509     */
00510     QString dateTimeStamp
00511     (
00512       /*! long (optional) ~ specify number of characters to return from the
00513       **  dateTime stamp.  This parameter is optional.  You can specify this
00514       **  if you only want a portion of the date/time stamp.  It specifies the
00515       **  left-most \c length characters.
00516       */
00517       long length
00518     );
00519 
00520     /*!
00521     ** \brief Return a particular Date/Time Stamp \n
00522     **
00523     ** This function returns a string suitable for a date time stamp using
00524     **  the current system date/time.
00525     **
00526     ** \par vbScript Example ~ Time/Date stamp of current Date/Time
00527     ** \code
00528     ** dim dexe: set dexe = createObject("Dumont.EXE")
00529     ** msgBox "Current Date/Time Stamp: " & dexe.dateTimeStamp
00530     ** \endcode
00531     **
00532     ** \attention Do not try to use this function for producing extremely accurate
00533     **  time tracking - like tracking the running of a program, from some external
00534     **  program that runs multiple times.  For instance, you can call this function
00535     **  from a .vbs file, and you can run that .vbs file repeatedly, quickly.
00536     **  You can get in to a situation where multiple seperate instances of that
00537     **  .vbs program are hammering on this function, and even though one of
00538     **  the instances was launched first, it might not get to this function before
00539     **  another instance that was launched after... that's entirely up to windows.
00540     **  Therefore, you could have an instance that was launched before another 
00541     **  getting a time value later than the second... if that makes any sense at
00542     **  all.  Of course, all of this is only true if you are relying on the 
00543     **  millisecond return value.
00544     **
00545     ** \sa \ref dateTimeStamp(long) "dateTimeStamp( Current Date/Time )"
00546     **
00547     ** \return String ~ Date/Time Stamp formatted to: \c yyyyMMddhhmmsszzz
00548     */
00549     QString dateTimeStamp
00550     (
00551       /*! DateTime ~ value to be converted */
00552       const QDateTime & dateTime = QDateTime::currentDateTime(),
00553 
00554       /*! long (optional) ~ specify number of characters to return from the
00555       **  dateTime stamp.  This parameter is optional.  You can specify this
00556       **  if you only want a portion of the date/time stamp.  It specifies the
00557       **  left-most \c length characters.
00558       */
00559       long length = 14
00560     );
00561 
00562     QString dateTimeStamp
00563     (
00564       const QString & delimiter
00565     );
00566 
00567     /*!
00568     ** \brief Write some text to a file
00569     **
00570     ** File contents will be overwritten
00571     **
00572     */
00573     void textFile( const QString & fileName, const QString & data );
00574 
00575     /*!
00576     ** \brief Append some text to a file \n
00577     **
00578     ** File contents will be preserved
00579     **
00580     */
00581     void appendTextFile( const QString & fileName, const QString & data );
00582 
00583     /*!
00584     ** \brief Return a new GUID \n
00585     **
00586     ** Format a new GUID
00587     **
00588     */
00589     QString guid( long format = registryGuid, bool ucase = false );
00590 
00591     /*
00592     ** \brief Format an existing GUID \n
00593     **
00594     **
00595     */
00596     QString guid( const QUuid & id, long format = registryGuid, bool ucase = false );
00597 
00598     /*
00599     ** \brief Format an existing GUID \n
00600     **
00601     **
00602     */
00603     QString guid( const QString & id, long format = registryGuid, bool ucase = false );
00604 
00605     /*!
00606     ** \brief Quote a String \n
00607     **
00608     */
00609     QString dq( const QString & string );
00610 
00611     /*!
00612     ** \brief Run a Program \n
00613     **
00614     */
00615     bool run
00616     (
00617       const QString program,
00618       const QString argument1 = "",
00619       const QString argument2 = "",
00620       const QString argument3 = "",
00621       const QString argument4 = "",
00622       const QString argument5 = "",
00623       const QString argument6 = "",
00624       const QString argument7 = "",
00625       const QString argument8 = ""
00626     );
00627 
00628     void cliptext( const QString & value );
00629 
00630     QString cliptext( void );
00631 
00632 
00633     /*!
00634     ** \brief Present a File-Open dialog to the user \n
00635     **
00636     ** This feature has been provided in Dumont to deal with the lack of FileOpen
00637     **  in the Vista operating system.  It does not model the "UserAccounts.CommonDialog"
00638     **  interface, and probably never will, but its interface is pretty simple.  The
00639     **  Dialog Window is based upon the Qt FileOpen dialog window found on the
00640     **  http://doc.trolltech.com/4.3/qfiledialog.html website.
00641     **
00642     ** Normally, in Qt, file and folder paths are handled with "/" (forward slash)
00643     **  characters.  This is common in the Linux world.  However, this is somewhat
00644     **  incompatible with windows, since windows employs the "\" (back slash) character
00645     **  when dealing with file and folder paths.  Therefore, this routine has been
00646     **  modified to change all incoming "\" characters to "/" before employing the
00647     **  dialog, and then change all "/" characters from the dialog back into "\"
00648     **  characters for the caller.  This should simplify employing this dialog in
00649     **  windows based applications that are expecting the "\" character.
00650     **
00651     ** In its simplest form, the Dialog returns the string of the full-path
00652     **  to the selected file.  If the user presses 'cancel', an empty string
00653     **  is returned.
00654     **
00655     ** \par vbScript Example
00656     ** \code
00657     ** sub SelectTheFile()
00658     **   dim dexe: set dexe = createObject("Dumont.EXE")
00659     **   dim selectedFile
00660     **       selectedFile = dexe.fileOpenDialog( _
00661     **        "Pick a File", _
00662     **        "C:\Documents and Settings\mark\My Documents", _
00663     **        "Docs (*.doc;*.wpd)" )
00664     **   if( selectedFile = "" ) then
00665     **     msgbox "no file was selected"
00666     **   else
00667     **     msgbox "you selected the file: " & selectedFile
00668     **   end if
00669     ** end sub
00670     ** \endcode
00671     **
00672     ** \image html fileOpenDialog.jpg
00673     **
00674     ** \note This doesn't work when called from within a Commence detail 
00675     **        form - it times out.  It does, however, work when called 
00676     **        from a vbScript program.  If you want to use this routine
00677     **        from within your Commence detail forms, see the
00678     **        <a href="http://dumont.showoff-db.org/dll/doc/html" target="_blank">DumontDLL</a>
00679     **        project and the 
00680     **        <a href="http://dumont.showoff-db.org/dll/doc/html/classQDumontDLL.html" target="_blank">fileOpenDialog</a>
00681     **        command found there.
00682     **
00683     ** \note When calling this function, note that the Commence 'detail form' is 
00684     **       is *not* modal.  This could be a potential problem if the user closes
00685     **       the detail form before closing this FileOpen dialog either by 'cancel'
00686     **       or 'open'.  If the user does first close the detail form without properly
00687     **       acknowledging this dialog window, then Commence will simply crash.
00688     **
00689     */
00690     QString fileOpenDialog
00691     (
00692       const QString & caption,
00693       const QString & dir,
00694       const QString & filter = ""
00695     );
00696 
00697     /*!
00698     ** \brief Generate an MD5 hash of data
00699     **
00700     */
00701     QString md5( const QString & data );
00702 
00703     /*!
00704     ** \brief Generate a 16-bit CRC on some data
00705     **
00706     */
00707     long crc16( const QString & data );
00708 
00709     /*!
00710     ** \brief Generate a 32-bit CRC on some data
00711     **
00712     ** This does the same thing as the crc16 except it runs
00713     **  the crc on the data string twice, once in forward 
00714     **  order and once in reverse order.
00715     **
00716     */
00717     long crc32( const QString & data );
00718 
00719     /*!
00720     ** \brief Compress a String
00721     **
00722     ** Compresses the string and returns the compressed data in a new byte array.
00723     **
00724     ** The compressionLevel parameter specifies how much compression should be used. 
00725     **  Valid values are between 0 and 9, with 9 corresponding to the greatest 
00726     **  compression (i.e. smaller compressed data) at the cost of using a slower 
00727     **  algorithm. Smaller values (8, 7, ..., 1) provide successively less 
00728     **  compression at slightly faster speeds. The value 0 corresponds to no 
00729     **  compression at all. The default value is -1, which specifies zlib's 
00730     **  default compression.
00731     **
00732     */
00733     QString compress( const QString & data, int level = -1 );
00734 
00735   protected:
00736 
00737   private:
00738 
00739     QHash< QString, QPointer<QxtLoggerWindow> > m_loggerWindows;
00740 
00741 }; // endclass DumontEXE
00742 
00743 
00744 
00745 /*!
00746 ** \brief The Main Window is the main user interface screen for the
00747 **  application.  It is implemented as a MIDI type window.
00748 **
00749 */
00750 class winDumontEXE
00751 :
00752   public QMainWindow,
00753   public Ui::MainWindow
00754 {
00755   Q_OBJECT
00756 
00757   public:
00758 
00759     winDumontEXE();
00760 
00761     ~winDumontEXE();
00762 
00763     /*!
00764     ** \brief Read Registry Settings \n
00765     **
00766     ** This method is used internally upon creation of the window to restore
00767     **  settings from the system registry.  The settings include window
00768     **  size and placement on the desktop, placement of docking windows and
00769     **  so on.
00770     **
00771     ** \par See the following for the actual registry root settings:
00772     ** \code
00773     ** #define ORG_DOMAIN  "Lorimark Solutions"
00774     ** #define APP_NAME    "DumontEXE"
00775     ** \endcode
00776     **
00777     ** \sa writeSettings
00778     **
00779     */
00780     void readSettings();
00781 
00782     /*!
00783     ** \brief Write Registry Settings \n
00784     **
00785     ** This method is used internally upon destruction of the window to
00786     **  store settings into the system registry.
00787     ** 
00788     ** \sa readSettings
00789     */
00790     void writeSettings();
00791 
00792     /*!
00793     ** \brief Register the COM server \n
00794     **
00795     ** This function registers the COM server in to the Windows Registry.  The
00796     **  windows registry is what is used to hook various programs together through
00797     **  the COM subsystem.
00798     **
00799     ** When the vbScript program performs a function such as createObject("Dumont.EXE")
00800     **  it is calling upon the COM subsystem to establish a connection between the
00801     **  vbScript program and the other program.  The registry is used to establish that
00802     **  connection.
00803     ** 
00804     ** When an object is created by name using "Dumont.EXE", for instance, the COM
00805     **  system looks into the registry for an HKEY_CLASSES_ROOT/Dumont.EXE entry.  If
00806     **  it can find this entry it then it looks to a HKEY_CLASSES_ROOT/Dumont.EXE/CLSID
00807     **  entry to acquire the ClassID of the object.  Then the COM system looks for a
00808     **  HKEY_CLASSES_ROOT/CLSID/{class id of the previous call} entry.  If it can find
00809     **  that entry then it looks for LocalServer and RemoteServer and InprocServer
00810     **  values to get the name of the binary file that is to be loaded.  With that
00811     **  information, Windows is able to load the program - whatever it may be, a DLL
00812     **  or EXE, it doesn't matter.
00813     **
00814     ** Depending on a loaded DLL or EXE different things happen.  If the program is
00815     **  an EXE, then the EXE program is launched by the system.  It is up to the EXE
00816     **  program (server) to hook itself (register itself) in to the COM subsystem.
00817     **  Once the server has hooked in, then the vbScript program can call upon 
00818     **  functions contained within it.
00819     **
00820     ** The registry is set up as follows:
00821     **
00822     ** \par Windows Registry Definitions
00823     ** \code 
00824     **  HKEY_CLASSES_ROOT
00825     **    CLSID
00826     **      {00000000-0000-0000-0000-000000000000}   // description
00827     **        LocalServer                            // serverPath
00828     **        ProgID                                 // progid
00829     **    progid                                     // description
00830     **      CLSID                                    // clsid
00831     ** \endcode
00832     **
00833     **
00834     ** Here is a typical registry organization for the Dumont project:
00835     **
00836     ** \par Windows Registry Example
00837     ** \code 
00838     **  HKEY_CLASSES_ROOT
00839     **    CLSID
00840     **      {C7860C20-9B6F-4f31-8293-31CB0C1799F0}   // Dumont Commence Application Extensions
00841     **        LocalServer                            // C:/commence/Dumont/Dumont.exe
00842     **        ProgID                                 // Dumont.EXE
00843     **    Dumont.EXE                                 // Dumont Commence Application Extensions
00844     **      CLSID                                    // {C7860C20-9B6F-4f31-8293-31CB0C1799F0}
00845     ** \endcode
00846     **
00847     */
00848     void RegisterServer
00849     (
00850       /*! \b ClassID of the COM component.  This number acts as a cross-reference number
00851       **   between the Program ID and the CLSID.
00852       **  \n\n
00853       */
00854       const QUuid   & clsid,
00855 
00856       /*! \b Program \b ID ~ This is the vbScript component \b Name.
00857       ** \n\n
00858       */
00859       const QString & progid,
00860 
00861       /*! This has not real functional impact on the system, but
00862       **   is used inside the registry to help users browse the
00863       **   many registry settings.
00864       ** \n\n
00865       */
00866       const QString & description,
00867 
00868       /*! The values here can be 'LocalServer', or 'InprocServer' or
00869       **   'RemoteServer'.
00870       ** \n\n
00871       */
00872       const QString & serverType,
00873 
00874       /*! The path to the actual program
00875       ** \n\n
00876       */
00877       const QString & serverPath
00878     );
00879 
00880     bool checkError( QSettings & );
00881 
00882     /*
00883     ** Show Event Override
00884     **
00885     */
00886     void showEvent( QShowEvent * event );
00887 
00888  public slots:
00889 
00890     void on_actFileOpen_triggered();
00891     void on_actFileQuit_triggered();
00892 
00893     void on_actViewRefresh_triggered();
00894     void on_actViewTaskMonitor_triggered();
00895     void on_actViewAppMonitor_triggered();
00896     void on_actViewLogWindow_triggered();
00897 
00898     void on_actHelpAbout_triggered();
00899 
00900     void on_actDumontShow_triggered();
00901 
00902     void on_dockApplications_visibilityChanged( bool visible );
00903     void on_applicationsTree_itemExpanded( QTreeWidgetItem * item );
00904     void on_applicationsTree_itemClicked( QTreeWidgetItem * item, int column );
00905     void on_applicationsTree_itemDoubleClicked( QTreeWidgetItem * item, int column );
00906     void on_applicationsTree_customContextMenuRequested ( const QPoint & pos );
00907 
00908     void on_actCheckOutAllScripts_triggered ( bool checked = false );
00909     void on_actCheckOutFormScript_triggered( bool checked = false );
00910     void on_actCheckInFormScript_triggered( bool checked = false );
00911     void on_actShowView_triggered( bool checked = false );
00912     void on_actDeleteView_triggered( bool checked = false );
00913 
00914 //    void appRegistered( cmcApplication * application );
00915 //    void appUnregistered( cmcApplication * application );
00916 
00917   protected:
00918 
00919     void closeEvent( QCloseEvent * event );
00920     void timerEvent( QTimerEvent * event );
00921 
00922   private:
00923 
00924     void DumpCategoryFields( cmcDatabaseApi::cmcCategoryDef * categoryDef );
00925     void DumpCategoryConnections( cmcDatabaseApi::cmcCategoryDef * categoryDef );
00926 
00927     QSystemTrayIcon * sti;
00928     QMenu * stm;
00929 
00930     HWND m_cmcHwnd;
00931 
00932     cmcExe * m_cmcExe;
00933 
00934 }; // endclass winDumontEXE
00935 
00936 #endif // #ifndef DUMONTEXE_H
00937 
 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