OOFILE  1.9
oofgui.cpp
Go to the documentation of this file.
1 // COPYRIGHT 1999 A.D. Software, All rights reserved
2 
3 // Platform-independent GUI Integration layer of OOFILE database
4 
5 #include "oofpch_m.h" // for precompilation of MFC GUI files
6 
7 #ifndef H_OOFGUI
8  #include "oofgui.h"
9 #endif
10 #ifndef H_OOFIOS
11  #include "oofios.h"
12 #endif
13 #ifndef H_OOF2
14  #include "oof2.h"
15 #endif
16 #ifndef H_OOF4
17  #include "oof4.h"
18 #endif
19 #ifndef H_OOFQUERY
20  #include "oofquery.h"
21 #endif
22 #ifndef H_OOFVIEW
23  #include "oofview.h"
24 #endif
25 #ifndef H_OOFREL
26  #include "oofrel.h"
27 #endif
28 #ifndef H_OOFEXCEP
29  #include "oofexcep.h"
30 #endif
31 #ifndef OOFYNC_H
32  #include "oofync.h"
33 #endif
34 
35 #ifdef OOF_MEM_DEBUG_LAST_INCLUDE
36  #include OOF_MEM_DEBUG_LAST_INCLUDE
37 #endif
38 
39 #ifndef OOF_NO_STDLIB
40  #ifndef std
41  using namespace std;
42  #endif
43 #endif
44 
45 const unsigned long kRecordLockedByOtherUser = 'Lock';
46 
47 // -------------------------------------------------------
48 // d b G U I
49 // -------------------------------------------------------
50 dbGUI::dbGUI(dbTable* inTable) :
51  mClosing(false),
52  mTable(inTable),
53  mLastDisplayTable(0),
54  mLastBrowser(0),
55  mDontCareIfLocked(true) // until they link something editable, or explicitly change
56 {
57 }
58 
59 
60 bool
61 dbGUI::ConfirmDelete(const char* confirmMessage)
62 {
63  bool ret = false;
64  if (!confirmMessage)
65  confirmMessage = "Are you sure you want to delete this record?";
66  oofYNC theMsg(confirmMessage, "Delete", "Cancel");
67  theMsg.setDefaultButton(1); // cancel
68  retTypeT buttonClicked = theMsg.msgBox();
69  if (buttonClicked==IDYES)
70  ret = true;
71  return ret;
72 }
73 
74 
75 bool
77 {
78  bool ret = false;
79  oofYNC theMsg("Are you sure you want to Revert this record, losing all your changes?", "Revert", "Cancel");
80  theMsg.setDefaultButton(1); // cancel
81  retTypeT buttonClicked = theMsg.msgBox();
82  if (buttonClicked==IDYES)
83  ret = true;
84  return ret;
85 }
86 
87 
88 void
90 {
91  if (leaveRecord()) {
92  mTable->beginTransaction();
93  mTable->newRecord();
95  }
96 }
97 
98 
99 void
101 {
102  bool canSave = (askAllStoppingAtFirst(false, OOFmsg_AttemptSaveRecord) == 0);
103  if (canSave) {
104  mTable->saveRecord();
106  }
107 }
108 
109 
110 void
112 {
113 // don't need to confirm we can leave it - it's being deleted !!!!
114  mTable->deleteRecord();
116 }
117 
118 
119 void
121 {
122  if (ConfirmRevert()) {
123  mTable->revertRecord();
125  }
126 }
127 
128 
129 void
131 {
132  assert(mTable);
133  if (leaveRecord()) {
134  mTable->cloneRecord();
136  }
137 }
138 
139 
142 {
143  dbAbstractBrowseHelper* ret = 0;
144  /*if (mLastDisplayTable == ioParam)
145  ret = mLastBrowser;
146  else*/ {
147  ret = (dbAbstractBrowseHelper*) askAllStoppingAtFirst(true, OOFmsg_GetDisplayTableHandler, (unsigned long)ioParam); // safe downcast
148  if (ret) {
149  mLastBrowser = ret;
150  mLastDisplayTable = ioParam;
151  }
152  }
153  return ret;
154 }
155 
156 
157 void
159 {
160  assert(mTable);
161  if (mTable->atFirst())
163  else
164  {
165  if(leaveRecord()) {
166  mTable->first();
168  }
169  }
170 }
171 
172 
173 void
175 {
176  assert(mTable);
177  if (mTable->atLast())
179  else
180  {
181  if(leaveRecord()) {
182  mTable->next();
184  }
185  }
186 }
187 
188 
189 void
191 {
192  assert(mTable);
193  if (mTable->atFirst())
195  else
196  {
197  if(leaveRecord()) {
198  mTable->prev();
200  }
201  }
202 }
203 
204 
205 void
207 {
208  assert(mTable);
209  if (mTable->atLast())
211  else
212  {
213  if(leaveRecord()) {
214  mTable->last();
216  }
217  }
218 }
219 
220 
224 void
226 {
227 // called before data loaded
228  if (mTable->isEmpty())
229  mTable->newRecord();
230  else
231  if (!mTable->isRecordLoaded())
232  mTable->start();
234 }
235 
236 
244 bool
246 {
247  bool canLeave = (askAllStoppingAtFirst(false, OOFmsg_AttemptLeaveRecord)==0);
248  if (canLeave) {
249  if (mTable->isDirty()) {
250  mTable->saveRecord();
252  }
253  if(mTable->transactionDirty())
254  mTable->commitTransaction();
255  else
256  mTable->abortTransaction();// releases all locks
257  mTable->unlockRecord();
258  }
259  return canLeave;
260 }
261 
262 
263 // -------------------------------------------------------
264 // d b H e l p e r
265 // -------------------------------------------------------
267  oofSingleListener(tbl ? tbl->getGUI() : 0)
268 {
269 }
270 
271 
273 {
274 }
275 
276 
277 void
279 {
280 // null method so subclasses not forced to override
281 }
282 
283 
284 void
286 {
287 // null method so subclasses not forced to override
288 }
289 
290 
291 dbTable*
293 {
294  return NULL;
295 }
296 
297 
298 // -------------------------------------------------------
299 // d b A b s t r a c t B r o w s e H e l p e r
300 // -------------------------------------------------------
301 
303 : dbHelper(inTable)
304 {}
305 
306 
307 dbTable*
309 {
310  dbView* theView = view();
311  if (theView)
312  return theView->table();
313  else
314  return NULL;
315 }
316 
317 
318 void
320 {
321  dbTable* table = view()->table();
322  // current selection in the main table
323  dbSelection curSel = table->currentSelection();
324 
325  // this must be done before the deleteSelection takes place
326  if (!curSel.isAllRecs())
327  curSel.difference_with(inSel);
328 
329  table->setSelection(inSel);
330  table->deleteSelection();
331 
332  // handle the situation when all records were deleted from the table, which has
333  // "allRecs" flag set on; it would be actually OK to restore the curSel, which has
334  // the "allRecs" flag set on, to an empty table, but it's better to be consistent,
335  // because if the table items are deleted one by one, the state of the table
336  // selection will be "empty"
337  if (curSel.isAllRecs()) {
338  table->selectAll();
339  if (table->isEmpty())
340  table->selectNone();
341  }
342  else
343  table->setSelection(curSel);
344 }
345 
346 
347 bool
348 dbAbstractBrowseHelper::receiveMsg(OOFmsgT msg, unsigned long senderDefined)
349 {
350  bool ret = true;
351  dbTable* ourTable = view()->table();
352  assert(ourTable);
353 
354  switch (msg) {
355  case OOFmsg_NewRecord : // avoid highlighting another record
356  refreshBrowser(); // will pick up added record if any
358  break;
359 
360  case OOFmsg_SaveRecord : // senderDefined is the OID
361  refreshBrowser(); // will pick up added record if any
362  break;
363 
364  case OOFmsg_ChangeSelection : {
365 // later use new message ChangeRecord and pass new rec no
366  refreshBrowser(); // will recalc storage size
367  dbTable* realTable = ourTable->getGUI()->mainTable();
368  highlightRecNo(realTable->recordNumber());
369  break;
370  }
371 
374  break; // later might allow for editable cells with validation, just default to true now
375 
376  case OOFmsg_RevertRecord:
377  refreshBrowser();
378  break;
379 
380  default :
381  ret = false; // ignore unknown messages
382  };
383  return ret;
384 }
385 
386 
387 // -------------------------------------------------------
388 // d b A b s t r a c t E d i t H e l p e r
389 // -------------------------------------------------------
390 
392  dbHelper(tbl),
393  mChangingPages(false),
394  mAutoSaveOnMoving(tbl ? tbl->tableCachesDirtyRecords() : false),
395  mMainTable(tbl),
396  mReadOnly(false),
397  mCurrentLink(0),
398  mMsgEnteringAboutToLoad(OOFmsg_None),
399  mMsgEnteringAfterLoad(OOFmsg_None),
400  mMsgCanSaveRecord(OOFmsg_None),
401  mMsgConfirmSave(OOFmsg_None),
402  mMsgChangedCurrentField(OOFmsg_None)
403 {
404 }
405 
406 
408 {
409  mLinks.deleteAll();
410 // delete mMainTable;
411 }
412 
413 
414 
415 void
417 {
418  mLinks.append(adoptedLink);
419  adoptedLink->owner(this);
420 }
421 
422 
423 
424 bool
425 dbAbstractEditHelper::receiveMsg(OOFmsgT msg, unsigned long senderDefined)
426 {
427  bool ret = true;
428  switch (msg) {
430  ret = LeaveRecord();
431  break;
432 
434  if (mCurrentLink)
435  ret = mCurrentLink->leaveLink();
436  if (ret)
437  ret = CanSaveRecord();
438  break;
439 
440  case OOFmsg_NewRecord :
441  LoadData();
442  break;
443 
445  if (senderDefined == kRecordLockedByOtherUser)
446  readOnly(true);
447  LoadData();
448  break;
449 
450  case OOFmsg_SaveRecord :
451  ResetDirtyLinks();
452  break;
453 
454  case OOFmsg_RevertRecord :
455  mMainTable->unloadRecord(); // flush any modified fields
457  LoadData();
458  break;
459 
460  default :
461  ret = false; // ignore unknown messages
462  };
463  return ret;
464 }
465 
466 
476 YNCancelT
478 {
479  YNCancelT ret = Yes;
482  else {
483  oofYNC theMsg("Do you want to save your changes?", "Save", "Don't Save", "Cancel");
484  retTypeT buttonClicked = theMsg.msgBox();
485  switch (buttonClicked) {
486  case IDYES:
487  ret = Yes;
488  break;
489  case IDNO:
490  ret = No;
491  break;
492  case IDCANCEL:
493  ret = Cancel;
494  break;
495  }
496  }
497  return ret;
498 }
499 
500 
501 void
503 {
506 }
507 
508 
509 void
511 {
514 
515 }
516 
517 
518 bool
520 {
521  bool ret = ValidateLinks();
522  if (ret) {
525  }
526  return ret;
527 }
528 
529 
530 void
532 {
535 }
536 
537 
547 void
549 {
550  if (mCurrentLink != newLink) {
551 // NOT YET IMPLEMENTED - option of field-departure validate triggered here
552  if (!mCurrentLink) { // on first field in screen?
553  void* maybeTarget = currentGUItarget();
554  mCurrentLink = getLink(maybeTarget);
555  }
556  bool changedField = true;
557  if (mCurrentLink)
558  changedField = mCurrentLink->leaveLink(); // update DB so calc fields etc. work
559 
560  mCurrentLink = newLink;
561  if (changedField) {
562  ChangedCurrentField(); // user hook or message broadcast
563 
564 // update displays after user hook in case they change some other value
565  updateDerivedFieldDisplays(); // masked formats, calculated fields, default calculated fields etc.
566  }
567  }
568 }
569 
570 
571 void
573 {
574 // if (mCurrentLink) {
575 // assert(mCurrentLink == inLink);
576 // worked out sometimes mCurrentLink may point to a caption, in which case typing in the first
577 // field will cause the above assertion to fail.
578 // }
579 // else
580  mCurrentLink = inLink;
581 // NOT YET IMPLEMENTED - locking check - bring up warning if locked
582 }
583 
584 
585 dbTable*
587 {
588  return mMainTable;
589 }
590 
591 
592 dbFieldLink*
594 {
595  dbFieldLink* ret = 0; // default is return nil pointer
596  int numLinks = mLinks.count();
597  for (int i=0; i<numLinks; i++) {
598  dbFieldLink* fl = (dbFieldLink*) (mLinks[i]); // safe downcast
599  dbGUIAdapter* fa = fl->adapter();
600  if (fa && fa->adaptsControl(targetPane)) {
601  ret = fl;
602  break;
603  }
604  }
605  return ret;
606 }
607 
608 
614 bool
616 {
617  bool willLeave = true;
618  if (mCurrentLink) {
620  }
621 
622  if (isDirty()) {
624  willLeave = CanSaveRecord();
625  }
626  else {
627  YNCancelT reply = ConfirmSave();
628  if (reply==No)
630  else {
631  if (reply==Cancel)
632  willLeave = false;
633  else
634  willLeave = CanSaveRecord();
635  } // cancelled
636  } // auto-save
637  } // dirty, otherwise don't care to check further
638 
639  if (willLeave)
640  mCurrentLink = 0; // so we don't think we've stayed in the same edit control
641  return willLeave;
642 }
643 
644 
645 void
647 {
648  assert(mMainTable); // should be setup by now!
649  EnteringAboutToLoad(); // user hook
652  EnteringAfterLoad(); // user hook
653 }
654 
655 
656 void
658 {
659 #ifdef _Windows
660  OOF_String s(os);
661  ::MessageBox(0, s, "Warning", MB_ICONEXCLAMATION);
662 #else
663  dbConnect::raise(os, false);
664 #endif
665 }
666 
667 
668 void
669 dbAbstractEditHelper::readOnly(bool becomeReadOnly)
670 {
671  if (mReadOnly == becomeReadOnly)
672  return; // same setting - trivial exit
673 
674  if (becomeReadOnly || mMainTable->lockedCurrentRecord()) {
675  mReadOnly = becomeReadOnly;
676  const int numLinks = mLinks.count();
677  for (int i=0; i<numLinks; i++) {
678  dbFieldLink* fl = (dbFieldLink*) (mLinks[i]); // safe downcast
679  fl->PreApprovedReadOnly(becomeReadOnly);
680  mLinks.next();
681  }
682  }
683 }
684 
685 
686 void
688 {
689  const int numLinks = mLinks.count();
690  for (int i=0; i<numLinks; i++) {
691  dbFieldLink* fl = (dbFieldLink*) (mLinks[i]); // safe downcast
692  fl->markClean();
693  }
694 }
695 
696 
702 void
704 {
705  const int numLinks = mLinks.count();
706  for (int i=0; i<numLinks; i++) {
707  dbFieldLink* fl = (dbFieldLink*) (mLinks[i]); // safe downcast
708  fl->copyLinkToField();
709  }
710 }
711 
712 
716 bool
718 {
719  bool ret = true;
720  const int numLinks = mLinks.count();
721  for (int i=0; i<numLinks; i++) {
722  dbFieldLink* fl = (dbFieldLink*) (mLinks[i]); // safe downcast
723  if (!fl->validToLeaveForm()) {
724  ret = false;
725  fl->highlightLink();
726  break;
727  }
728  } // loop all links
729  return ret;
730 }
731 
732 
733 void
735 {
736  const int numLinks = mLinks.count();
737  for (int i=0; i<numLinks; i++) {
738  dbFieldLink* fl = (dbFieldLink*) (mLinks[i]); // safe downcast
739  fl->copyFieldToLink();
740  fl->markClean();
741  }
742 }
743 
744 
745 void
747 {
748  int numLinks = mLinks.count();
749  bool isNew = table()->isNewRecord();
750  for (int i=0; i<numLinks; i++) {
751  dbFieldLink* fl = (dbFieldLink*) (mLinks[i]); // safe downcast
752  fl->updateDerivedFieldDisplay(isNew);
753  }
754 }
755 
756 
762 bool
764 {
765  bool ret = mMainTable->isDirty();
766  return ret; // assume dirtied by copying link to field, or by other user action
767 }
768 
769 
777 bool
779 {
780  return SendFrameworkMessage(inMsg, ioParam);
781 }
782 
783 
786 void
787 dbAbstractEditHelper::linkAdapter(dbField* fld, dbGUIAdapter* adoptedAdapter, bool becomeReadOnly)
788 {
789  dbFieldLink* newLink;
790  assert(fld);
791  switch (fld->fieldType()) {
792  case (boolField):
793  newLink = new dbBoolLink(fld, adoptedAdapter, becomeReadOnly);
794  break;
795 
796  case (dateField):
797  newLink = new dbDateLink2Editor(fld, adoptedAdapter, becomeReadOnly);
798  break;
799 
800  case (dateTimeField):
801  newLink = new dbDateTimeLink2Editor(fld, adoptedAdapter, becomeReadOnly);
802  break;
803 
804  default:
805  newLink = new dbFieldLink(fld, adoptedAdapter, becomeReadOnly);
806  }
807  adoptLink(newLink);
808 }
809 
810 
828 void
830  bool becomeReadOnly, dbRelRef* pickVia)
831 {
832  assert(!fld->fieldIsStandalone());
833  dbTable* rightmostTable = fld->fieldTable();
834  assert(rightmostTable->isRelatedClone());
835  if (pickVia) {
836  assert(pickVia->fieldTable()->baseTableOfRelationChain() == rightmostTable->baseTableOfRelationChain());
837  // confirms pickVia is in the chain
838  assert(!pickVia->isRelBackToParent()); // we must be pointing right, ie: toward lookup table.
839  }
840  else {
841  dbRelRefBase* fldRel = rightmostTable->controllingRelationship()->inverse();
842  assert(fldRel && (fldRel->isManyToOne() || fldRel->isOneToOne()));
843  pickVia = (dbRelRef*) fldRel; // safe downcast due test above
844  }
845 
846 
847  dbFieldLink* newLink = new dbFieldPickLink(fld, adoptedAdapter, becomeReadOnly, pickVia);
848  adoptLink(newLink);
849 }
850 
851 // -------------------------------------------------------
852 // d b T a b l e D i s p l a y
853 // -------------------------------------------------------
854 dbTableDisplay::dbTableDisplay(unsigned short headingRows) :
855  mHeadingRows(headingRows)
856 {}
857 
858 
859 
860 // -------------------------------------------------------
861 // d b G U I A d a p t o r
862 // -------------------------------------------------------
863 void
865 {
866  mFieldLink = inLink;
867 }
868 
869 
870 bool
871 dbGUIAdapter::equalsString(const oofString& inString) const
872 {
873 // by avoiding copying the getString return value to a local var we hopefully avoid a
874 // copy of the contents as oofString::operator==(const oofString&) will
875 // use the temp return value directly
876  const bool ret = (inString==getString());
877  return ret;
878 }
879 
880 
881 int
883 {
884  long ret = getString().asLong(); // should use temporary ret value - avoid extra copy
885  return ret;
886 }
887 
888 
889 void
891 {
892  char buf[20];
893  sprintf(buf, "%i", inValue);
894  setString(buf);
895 }
896 
897 
898 bool
899 dbGUIAdapter::equalsValue(int inValue) const
900 {
901  const long theValue = getValue();
902  const bool ret = (theValue==inValue);
903  return ret;
904 }
905 
906 
907 bool
909 {
910  return false;
911 }
912 
913 
917 void
919 {
920 }
921 
922 
923 
924 // -------------------------------------------------------
925 // d b G U I A d a p t C o n t r o l
926 // -------------------------------------------------------
927 oofString
929 {
930  const int theValue = getValue();
931  oofString ret;
932  ret.convertNumber(theValue);
933  return ret;
934 }
935 
936 
937 void
939 {
940  const long theValue = inString.asLong();
941  setValue(theValue);
942 }
943 
944 
945 bool
947 {
948  const long theValue = getValue();
949  const long inValue = inString.asLong();
950  const bool ret = (theValue==inValue);
951  return ret;
952 }
953 
954 
955 
956 // -------------------------------------------------------
957 // d b G U I A d a p t E d i t o r
958 // -------------------------------------------------------
959 void
961 {
963 }
964 
965 
966 void
968 {
969 // empty virtual to avoid having to implement where not possible/needed
970 }
971 
972 
973 
974 
975 // -------------------------------------------------------
976 // d b F i e l d L i n k
977 // -------------------------------------------------------
982 dbFieldLink::dbFieldLink(dbField* fld, dbGUIAdapter* adoptedAdapter, bool becomeReadOnly) :
983  mField(fld),
984  mAdapter(adoptedAdapter),
985  mOwner(0),
986  mMaybeDirty(false),
987  mReadOnly(becomeReadOnly),
988  mAlwaysReadOnly(becomeReadOnly)
989 {
990  if (mAdapter)
991  mAdapter->setFieldLink(this);
992 }
993 
994 
996  mMaybeDirty(rhs.mMaybeDirty),
997  mOwner(rhs.mOwner),
998  mReadOnly(rhs.mReadOnly),
999  mAlwaysReadOnly(rhs.mAlwaysReadOnly)
1000 {
1001  if (rhs.mAdapter) {
1002  mAdapter = rhs.mAdapter->clone();
1003  mAdapter->setFieldLink(this);
1004  }
1005  else
1006  mAdapter = 0;
1007 }
1008 
1009 
1011 {
1012  delete mAdapter;
1013 }
1014 
1015 void
1017 {
1018  assert(field() && mAdapter);
1019  if (!field()->fieldIsStandalone())
1020  field()->fieldTable()->ensureRecordLoaded(true /* autoCreateRelated */);
1021 
1022  const oofString fldContents = field()->copyString();
1023  mAdapter->setString(fldContents);
1024 }
1025 
1026 
1027 void
1029 {
1030  assert(field() && mAdapter);
1031  const oofString guiContents = mAdapter->getString();
1032  const oofString fldContents = mField->copyString();
1033  if (fldContents!=guiContents)
1034  mField->setString(guiContents);
1035 }
1036 
1037 
1043 void
1045 {
1046  assert(mAdapter);
1048 }
1049 
1050 
1051 void
1053 {
1054  if (!mField)
1055  return;
1056 
1057  if (!mField->fieldIsStandalone()) {
1058  dbGUI* fieldGUI = mField->fieldTable()->getGUI();
1059  assert(fieldGUI);
1060  fieldGUI->careIfLocked();
1061  }
1062 }
1063 
1064 
1065 bool
1067 {
1068  bool ret = false; // assume fails
1069  if (mMaybeDirty) { // state set by editing the linked control onscreen
1070  if (validToLeaveLink()) {
1071  if (field()->fieldIsUniqueIndexed() && linkIsEmpty())
1072  copyFieldToLink(); // don't allow user to leave a unique key empty
1073  // usually used in conjunction with a default calculator on that key
1074  // so a calculated value would be displayed for an empty new field
1075  else {
1076  if (!linkEqualsField()) { // link has been updated so keep dbField in synch
1077  copyLinkToField();
1078  } // not equal field
1079  ret = true;
1080  } // not unique key
1081  } // valid to leave
1082  } // dirty
1083  else
1084  ret = true; // if not dirty assume still valid
1085  // NOT YET IMPLEMENTED - think about this in future, it doesn't cope well if we have a field
1086  // that is valid when entered but becomes invalid due to other changes
1087  // however form-level validation should catch those cases
1088  return ret;
1089 }
1090 
1091 
1098 bool
1100 {
1101  return true;
1102 }
1103 
1104 
1109 bool
1111 {
1112  bool ret = validToLeaveLink();
1113 
1114 // check unique indexed fields
1115  if (ret && mField->fieldIsUniqueIndexed()) {
1116  if (mField->valueIsDuplicate()) { // could allow dups in just leaveField, but not for final exit
1117  OOF_String fldStr = mField->copyString();
1118  oofYNC(
1119  stringstream() << flush << mField->fieldName() << '\'' << fldStr << "' is not unique, please change it and try saving again"
1120  );
1121  ret = false;
1122  } // BAD FIELD - DUPLICATE KEY
1123  } // test unique field
1124  return ret;
1125 }
1126 
1127 
1132 void
1133 dbFieldLink::readOnly(bool becomeReadOnly)
1134 {
1135  if (!mAlwaysReadOnly && (becomeReadOnly!=mReadOnly)) {
1136  // only change if able to change and not already in state
1137  if (!becomeReadOnly) {
1138  dbTable* tbl = mOwner->table();
1139  // the table we want locked is that being edited
1140  // this field may be a standalone field, NOT one linked to database
1141  if (tbl) {
1142  const bool isLockedByOther = !tbl->getGUI()->recordAvailable();
1143  if (isLockedByOther)
1144  return; // programmer can't make individual field writable if record locked
1145  }
1146  }
1147  PreApprovedReadOnly(becomeReadOnly);
1148  }
1149 }
1150 
1151 
1156 void
1157 dbFieldLink::PreApprovedReadOnly(bool becomeReadOnly)
1158 {
1159  // repeat test in readOnly() because we may be called directly
1160  if (!mAlwaysReadOnly && (becomeReadOnly!=mReadOnly)) {
1161  mReadOnly = becomeReadOnly;
1162  mAdapter->readOnly(becomeReadOnly);
1163  }
1164 }
1165 
1166 
1167 bool
1169 {
1170  assert(mAdapter);
1171  assert(mField);
1172  const oofString fldContents = mField->copyString();
1173  const bool ret = mAdapter->equalsString(fldContents);
1174  return ret;
1175 }
1176 
1177 
1178 bool
1180 {
1181  const oofString theStr = mAdapter->getString();
1182  const bool ret = theStr.isEmpty();
1183  return ret;
1184 }
1185 
1186 
1187 void
1189 {
1190  if (mField->fieldIsVirtual() || (isNew && mField->hasDefaultCalculator()) )
1191  copyFieldToLink();
1192 }
1193 
1194 
1195 // -------------------------------------------------------
1196 // d b F i e l d P i c k L i n k
1197 // -------------------------------------------------------
1198 
1203  bool becomeReadOnly, dbRelRef* pickVia) :
1204  dbFieldLink(fld, adoptedAdapter, becomeReadOnly) ,
1205  mAllowsNullRelationship(false),
1206  mPickVia(pickVia),
1207  mLookupTable(0),
1208  mCachedRecordNumber(ULONG_MAX),
1209  mDefaultPick(1)
1210 {
1211  assert(!pickVia->isRelBackToParent());
1212 }
1213 
1214 
1216  dbFieldLink(rhs),
1217  mAllowsNullRelationship(rhs.mAllowsNullRelationship),
1218  mPickVia(rhs.mPickVia),
1219  mLookupTable(0),
1220  mCachedRecordNumber(rhs.mCachedRecordNumber),
1221  mDefaultPick(rhs.mDefaultPick)
1222 {
1223 }
1224 
1226 {
1227  delete mLookupTable;
1228 }
1229 
1230 
1237 void
1239 {
1240  const bool firstCall = mLookupTable==0;
1241  if (firstCall)
1242  InitLookup();
1243 
1244  assert(mAdapter);
1245  assert(mLookupTable);
1246  if (mAdapter->isValuePicker()) {
1247  if (firstCall) {
1248  dbView valueView(mLookupTable);
1249  valueView << mField;
1250  mAdapter->setValueList(valueView);
1251  }
1252  dbTable* currentLookup = mPickVia->relatedTable();
1253  int pickIndex;
1254  if (currentLookup->count()==0) {
1255  pickIndex = mDefaultPick;
1257  mCachedRecordNumber = ULONG_MAX; // invalid
1258  else {
1262  }
1263  }
1264  else {
1265  assert(!mPickVia->isJoin()); // see comment above method
1267  pickIndex = 1 + mCachedRecordNumber;
1268  }
1269  mAdapter->setValue(pickIndex);
1270  }
1271  else {
1273  }
1274 }
1275 
1276 
1281 void
1283 {
1284  assert(!mLookupTable);
1285  assert(mField && !mField->fieldIsStandalone() );
1286  mLookupTable = mField->fieldTable()->cloneTableWithoutSelection(); // we will selectAll
1287  mLookupTable->selectAll();
1288 }
1289 
1290 
1297 void
1299 {
1300  assert(mAdapter);
1301  assert(mLookupTable);
1302  if (mAdapter->isValuePicker()) {
1303  const int pickIndex = mAdapter->getValue() - 1; // pickIndex should be a valid record number
1304  assert((pickIndex >= 0) && pickIndex < mLookupTable->count());
1305  mLookupTable->gotoRecord(pickIndex);
1306  mCachedRecordNumber = pickIndex;
1308  }
1309  else {
1310  // something like;
1311  // search the mLookupTable by the target field value
1312  // maybe do a setRelatedRecord(search expr)
1313  assert(!"dbFieldPickLink::copyLinkToField doesn't yet support picking via edit fields"); //lint !e506 constant Boolean
1314  }
1315 }
1316 
1317 
1321 bool
1323 {
1324  assert(mAdapter);
1325  assert(mLookupTable);
1326  if (mAdapter->isValuePicker()) {
1327  const int pickIndex = mAdapter->getValue() - 1; // pickIndex should be a valid record number
1328  return pickIndex==mCachedRecordNumber;
1329  }
1330  else {
1332  }
1333 }
1334 
1335 
1342 bool
1344 {
1345  bool ret = false; // assume fails
1346 // currently we are not reliably marked dirty so assume always dirty
1347 // if (mMaybeDirty) { // state set by editing the linked control onscreen
1348  if (validToLeaveLink()) {
1349  if (!linkEqualsField()) { // link has been updated so keep dbField in synch
1350  copyLinkToField();
1351  } // not equal field
1352  ret = true;
1353  } // valid to leave
1354 // } // dirty
1355 // else
1356 // ret = true; // if not dirty assume still valid
1357  return ret;
1358 }
1359 
1360 
1361 bool
1363 {
1364  const bool pickerIsValid = mAllowsNullRelationship || (mPickVia->relatedTable()->count()>0);
1365  return pickerIsValid;
1366 }
1367 
1368 
1369 
1370 
1371 
1372 // -------------------------------------------------------
1373 // d b N u m e r i c F i e l d L i n k
1374 // -------------------------------------------------------
1375 dbNumericFieldLink::dbNumericFieldLink(dbField* fld, dbGUIAdapter* inAdapter, bool becomeReadOnly) :
1376  dbFieldLink(fld, inAdapter, becomeReadOnly)
1377 {}
1378 
1379 
1380 void
1382 {
1383  const dbNumericField* numField = (const dbNumericField*)mField; // safe downcast
1384  if (isDirty()) {
1385 // we have a format mask, so update the display
1386  if (numField->formatMask().length()) {
1387  copyFieldToLink();
1388  }
1389  }
1390  else {
1391  if (numField->fieldIsVirtual() || (isNew && numField->hasDefaultCalculator()) )
1392  copyFieldToLink();
1393  }
1394 }
1395 
1396 
1397 // -------------------------------------------------------
1398 // d b B o o l L i n k
1399 // -------------------------------------------------------
1400 dbBoolLink::dbBoolLink(dbField* fld, dbGUIAdapter* inAdapter, bool becomeReadOnly) :
1401  dbNumericFieldLink(fld, inAdapter, becomeReadOnly)
1402 {}
1403 
1404 void
1406 {
1407  if (!field()->fieldIsStandalone())
1408  field()->fieldTable()->ensureRecordLoaded(true /* autoCreateRelated */);
1409 
1410  assert(field() && field()->fieldType()==boolField);
1411  const dbBool* asBool = (dbBool*) field(); // safe downcast
1412  if (asBool->value())
1413  mAdapter->setValue(1);
1414  else
1415  mAdapter->setValue(0);
1416 }
1417 
1418 
1419 void
1421 {
1422  assert(field() && field()->fieldType()==boolField);
1423  dbBool* asBool = (dbBool*) field(); // safe downcast
1424 
1425  const bool guiContents = mAdapter->getValue();
1426  const bool fldContents = asBool->value();
1427  if (fldContents!=guiContents)
1428  *asBool = guiContents;
1429 }
1430 
1431 
1432 bool
1434 {
1435  assert(field() && field()->fieldType()==boolField);
1436  const dbBool* asBool = (dbBool*) field(); // safe downcast
1437 
1438  const bool guiContents = mAdapter->getValue();
1439  const bool fldContents = asBool->value();
1440  const bool ret = (fldContents==guiContents);
1441  return ret;
1442 }
1443 
1444 
1445 
1446 // -------------------------------------------------------
1447 // d b D a t e L i n k 2 E d i t o r
1448 // -------------------------------------------------------
1449 dbDateLink2Editor::dbDateLink2Editor(dbField* fld, dbGUIAdapter* inAdapter, bool becomeReadOnly) :
1450  dbNumericFieldLink(fld, inAdapter, becomeReadOnly)
1451 {}
1452 
1453 
1454 void
1456 {
1457  const dbDate* dateField = (const dbDate*)mField; // safe downcast
1458  if (isDirty() && dateField->isValid()) {
1459  if (dateField->formatMask().length()) { // we have a format mask, so update the display
1460  copyFieldToLink();
1461  }
1462  }
1463  else {
1464  if (dateField->fieldIsVirtual() || (isNew && dateField->hasDefaultCalculator()) )
1465  copyFieldToLink();
1466  }
1467 }
1468 
1469 
1470 bool
1472 {
1473  assert(mAdapter);
1474  bool ret = dbDate::checkDate(mAdapter->getString());
1475  if (!ret) {
1476  oofYNC("Invalid date");
1477  }
1478  return true;
1479 }
1480 
1481 
1482 
1483 // -------------------------------------------------------
1484 // d b D a t e T i m e L i n k 2 E d i t o r
1485 // -------------------------------------------------------
1487  dbNumericFieldLink(fld, inAdapter, becomeReadOnly)
1488 {}
1489 
1490 
1491 void
1493 {
1494  const dbDateTime* dateField = (const dbDateTime*)mField; // safe downcast
1495  if (isDirty() && dateField->isValid()) {
1496  if (dateField->formatMask().length()) { // we have a format mask, so update the display
1497  copyFieldToLink();
1498  }
1499  }
1500  else {
1501  if (dateField->fieldIsVirtual() || (isNew && dateField->hasDefaultCalculator()) )
1502  copyFieldToLink();
1503  }
1504 }
1505 
1506 
1507 bool
1509 {
1510  assert(mAdapter);
1511  bool ret = dbDateTime::checkTime(mAdapter->getString());
1512  if (!ret) {
1513  oofYNC("Invalid date");
1514  }
1515  return true;
1516 }
bool value() const
Definition: oof4.h:1529
bool reloadRecord()
Definition: oof1.cpp:2075
retTypeT
Definition: oofync.h:31
Definition: oofgui.h:41
OOFmsgT mMsgConfirmSave
Definition: oofgui.h:486
const OOFmsgT OOFmsg_RevertRecord
Definition: oofmsg.h:39
virtual void ChangedCurrentField()
Definition: oofgui.cpp:531
void linkPickAdapter(dbField &, dbGUIAdapter *adoptedAdapter, bool becomeReadOnly=false, dbRelRef *pickVia=0)
Definition: oofgui.h:699
virtual void readOnly(bool)
Definition: oofgui.h:95
virtual void highlightRecNo(unsigned long inRecNo, bool bSelect=true) const =0
void revertRecord()
Definition: oofgui.cpp:120
void changedSelection(oofReceiver *dontNeedToTell=0)
Definition: oofpp.cpp:256
bool valueIsDuplicate() const
Definition: oof3.cpp:291
static void raise(std::ostream &, bool terminateAfterMsg=true)
YNCancelT
Definition: oofgui.h:41
unsigned long count()
Count records in current selection.
Definition: oof1.h:2017
virtual void maybeChangeTargetLink(dbFieldLink *)
Definition: oofgui.cpp:278
dbFieldLink for dbDate that knows how to translate and validate.
Definition: oofgui.h:525
Abstract manager coordinating dbHelper objects that manage interaction on a window.
Definition: oofgui.h:301
virtual const oofString & fieldName() const
Definition: oof3.h:769
unsigned long recordNumber() const
Ordinal record number of current record in selection.
Definition: oof1.h:2041
dbDateTimeLink2Editor(dbField *, dbGUIAdapter *, bool becomeReadOnly=false)
Definition: oofgui.cpp:1486
Definition: oof3.h:26
Tries to hide the different platforms and version issues with standard IO.
bool ValidateLinks()
Check all links to see if they are validToLeaveForm, stopping at first failure.
Definition: oofgui.cpp:717
virtual bool fieldIsUniqueIndexed() const
Definition: oof3.cpp:422
virtual void EnteringAfterLoad()
Definition: oofgui.cpp:510
OOFmsgT mMsgCanSaveRecord
Definition: oofgui.h:485
bool hasDefaultCalculator() const
Definition: oof3.h:792
const OOFmsgT OOFmsg_ChangeSelection
Definition: oofmsg.h:33
dbFieldLink * mFieldLink
reference, maybe null
Definition: oofgui.h:112
Definition: oofync.h:36
dbRelRefBase * inverse() const
Definition: oofrel.h:242
Envelope class to contain an abstract selection apart from its dbTable.
Definition: oof1.h:316
virtual bool equalsValue(int) const
Definition: oofgui.cpp:899
virtual void setValueList(dbView &)
Null virtual method for subclasses to override, eg dbGUIAdaptLPopupButton.
Definition: oofgui.cpp:918
bool fieldIsStandalone() const
Definition: oof3.h:733
bool isDirty()
Check if helper is dirty, implied by mMainTable being dirty.
Definition: oofgui.cpp:763
const OOFmsgT OOFmsg_AttemptSaveRecord
Definition: oofmsg.h:42
virtual void setFieldLink(dbFieldLink *)
Definition: oofgui.cpp:864
bool recordAvailable() const
Editing-aware check if record available.
Definition: oofgui.h:589
virtual bool adaptsControl(void *) const
Definition: oofgui.cpp:908
virtual void revertRecord()
Definition: oof1.cpp:2524
const OOFmsgT OOFmsg_GetDisplayTableHandler
Definition: oofmsg.h:64
dbTable * relatedTable()
Definition: oofrel.cpp:1074
dbFieldLink for dbDateTimeLink that knows how to translate and validate.
Definition: oofgui.h:538
void start()
Definition: oof1.cpp:2057
dbTableDisplay(unsigned short headingRows=0)
Definition: oofgui.cpp:854
void deleteAll()
Definition: oof2.cpp:433
Persistent base for fields which can be represented as numbers.
Definition: oof4.h:166
bool ConfirmRevert()
Definition: oofgui.cpp:76
Special limited oofReceiver which will only ever listen to one oofBroadcaster at a time...
Definition: oofmsg.h:133
OOFmsgT mMsgEnteringAfterLoad
Definition: oofgui.h:484
void deleteRecord()
Definition: oofgui.cpp:111
virtual bool receiveMsg(OOFmsgT msg, unsigned long senderDefined)
The default receiveMsg behaviour is to delete yourself when the broadcaster closes.
Definition: oofgui.cpp:425
virtual void newRecord()
Definition: oof1.cpp:2090
const unsigned long kRecordLockedByOtherUser
Definition: oofgui.cpp:45
void append(OOF_bitPointer)
Definition: oof1.h:1551
static bool checkDate(unsigned short year, unsigned short month, unsigned short day)
Definition: oof5.cpp:1353
virtual void refreshBrowser()=0
Platform-independent GUI Integration layer of OOFILE database.
bool setRelatedRecord(oidT)
Set our link to a single record to the specified OID.
Definition: oofrel.cpp:1147
virtual dbGUIAdapter * clone() const =0
bool isJoin() const
If we don't have mJoinField then we are a pointer relationship.
Definition: oofrel.h:304
virtual bool validToLeaveLink()
Validate field contents, overridden if can check just contents.
Definition: oofgui.cpp:1471
virtual oofString getString() const =0
virtual void setTextEntryLimit(unsigned long)
Definition: oofgui.cpp:967
void adoptLink(dbFieldLink *adoptedLink)
Definition: oofgui.cpp:416
void copyFieldsToLinks()
Definition: oofgui.cpp:734
bool isEmpty()
Definition: oof1.cpp:2107
const OOFmsgT OOFmsg_None
Definition: oofmsg.h:32
Links a dbField to a known control type or I/O mechanism.
Definition: oofgui.h:74
void beginTransaction(short tMode=0)
Start a transaction if not already in one.
Definition: oof1.cpp:2238
OOFmsgT mMsgEnteringAboutToLoad
Definition: oofgui.h:483
virtual dbTable * table() const
Definition: oofgui.cpp:586
void selectAll()
Change the current selection to all records.
Definition: oof1.h:2304
virtual void maybeChangeTargetLink(dbFieldLink *)
React to possibly leaving a field, calling validation and update methods.
Definition: oofgui.cpp:548
bool mAutoSaveOnMoving
Definition: oofgui.h:471
bool lockedCurrentRecord() const
Definition: oof1.h:2470
dbHelper for managing lists of records.
Definition: oofgui.h:372
virtual void deleteSelection(const dbSelection &inSel)
Definition: oofgui.cpp:319
void goNextRecord()
Definition: oofgui.cpp:174
void convertNumber(int, const char *printfMask=0, bool appendIt=false)
Definition: oofstr.cpp:882
Parent for any field that is a relationship to another table.
Definition: oofrel.h:19
static bool checkTime(unsigned short year, unsigned short month, unsigned short day, unsigned short hour, unsigned short minute, unsigned short second)
Definition: oof5.cpp:2846
Provide an iterable set of fields.
Definition: oofview.h:26
bool isDirty() const
Definition: oof1.h:2334
dbTable * mainTable() const
Definition: oofgui.h:577
const OOFmsgT OOFmsg_AttemptLeaveRecord
Definition: oofmsg.h:41
virtual void setString(const oofString &)=0
virtual void setString(const char *)
Definition: oof3.h:132
bool isValid() const
Definition: oof4.h:1709
virtual void editingOccurred()
signals changes to anyone who needs to know
Definition: oofgui.cpp:960
static void beep()
Definition: oof1.cpp:3362
void goPrevRecord()
Definition: oofgui.cpp:190
dbDateLink2Editor(dbField *, dbGUIAdapter *, bool becomeReadOnly=false)
Definition: oofgui.cpp:1449
virtual void setValue(int)
Definition: oofgui.cpp:890
virtual bool SendFrameworkMessage(OOFmsgT, void *ioParam=0)=0
dbTable * baseTableOfRelationChain()
Definition: oof1.cpp:1984
void readOnly(bool isReadOnly=true)
Definition: oofgui.cpp:669
void deleteSelection()
Definition: oof1.cpp:1765
bool atFirst() const
Definition: oof1.h:1913
virtual void updateDerivedFieldDisplays()
Definition: oofgui.cpp:746
bool isEmpty() const
Test based on either length or null pointer.
Definition: oofstr.h:413
unsigned long length() const
Primary test: oofStringTest::emptyStringByNullInitIsLenZero()
Definition: oofstr.h:447
virtual oofString getString() const
Definition: oofgui.cpp:928
virtual dbTable * table() const
Definition: oofgui.cpp:292
virtual void * currentGUItarget() const =0
void selectNone()
Change the current selection to no records.
Definition: oof1.h:2321
void prev()
Previous record in the selection becomes current.
Definition: oof1.h:1997
virtual void setDefaultButton(int)
Definition: oofync.h:122
void copyLinksToFields()
Definition: oofgui.cpp:703
Persistent field used to store a date and time.
Definition: oof4.h:929
OOFmsgT mMsgChangedCurrentField
Definition: oofgui.h:487
dbSelection currentSelection()
Definition: oof1.cpp:2674
Definition: oofgui.h:41
void setSelection(const dbSelection &)
Definition: oof1.cpp:2725
virtual bool equalsString(const oofString &) const
Definition: oofgui.cpp:871
virtual void highlightNothing() const =0
dbAbstractBrowseHelper * GetDisplayTableHandler(void *ioParam)
Definition: oofgui.cpp:141
virtual void maybeDirty(dbFieldLink *)
Definition: oofgui.cpp:285
dbFieldLink * mCurrentLink
Definition: oofgui.h:480
virtual bool LeaveRecord()
Leave record, asking user to OK changes if necessary.
Definition: oofgui.cpp:615
bool isRelBackToParent() const
Do we point left or right? ie: in Patients->Visits is this relationship field pointing back from Visi...
Definition: oofrel.h:321
dbFieldLink * getLink(void *)
Definition: oofgui.cpp:593
virtual bool receiveMsg(OOFmsgT msg, unsigned long senderDefined)
The default receiveMsg behaviour is to delete yourself when the broadcaster closes.
Definition: oofgui.cpp:348
virtual ~dbHelper()
Definition: oofgui.cpp:272
virtual void highlightContents()
Definition: oofgui.h:94
void first()
First record in the selection becomes current.
Definition: oof1.h:1986
virtual void maybeDirty(dbFieldLink *)
Definition: oofgui.cpp:572
void gotoCurrentOrNewRec()
Provide a current record for the form to edit.
Definition: oofgui.cpp:225
Persistent field used to store a boolean.
Definition: oof4.h:367
void difference_with(const dbSelection &)
Definition: oof2.cpp:718
virtual dbTable * cloneTableWithoutSelection() const
Definition: oof1.cpp:1423
virtual dbView * view() const =0
Declare query classes.
bool gotoRecord(unsigned long)
Definition: oof1.cpp:2213
unsigned int count() const
Definition: oof1.h:1498
bool isOneToOne() const
Definition: oofrel.h:284
const OOFmsgT OOFmsg_NewRecord
Definition: oofmsg.h:36
Base class for persistent tables.
Definition: oof1.h:452
virtual YNCancelT ConfirmSave()
Ask user to confirm if should save or not, allowing cancel.
Definition: oofgui.cpp:477
Definition: oof3.h:26
dbTable * fieldTable() const
Definition: oof3.cpp:308
Persistent field used to store a date.
Definition: oof4.h:577
void next()
Next record in the selection becomes current.
Definition: oof1.h:1970
Portable highly capable string class.
Definition: oofstr.h:101
virtual int getValue() const
Definition: oofgui.cpp:882
virtual retTypeT msgBox(bool playBeep=true)
Definition: oofppyn.cpp:429
Definition: oofgui.h:41
virtual bool CanSaveRecord()
Definition: oofgui.cpp:519
long asLong() const
Attempt to return integer value of string.
Definition: oofstr.cpp:2217
dbAbstractBrowseHelper(dbTable *)
Definition: oofgui.cpp:302
dbGUI * getGUI()
Definition: oof1.cpp:2557
void commitTransaction(short rMode=0)
Definition: oof1.cpp:2249
saveOptionsT tableSaveOption() const
Definition: oof1.h:2394
virtual void updateDerivedFieldDisplay(bool isNew)
Definition: oofgui.cpp:1492
oofReceiver * askAllStoppingAtFirst(bool stopOn, OOFmsgT msg, unsigned long senderDefined=0, const oofReceiver *skipping=0)
Definition: oofmsg.cpp:114
const oofString & formatMask() const
Definition: oof4.h:1381
void linkAdapter(dbField &, dbGUIAdapter *adoptedAdapter, bool becomeReadOnly=false)
Definition: oofgui.h:692
virtual dbTable * table() const
Definition: oofgui.cpp:308
virtual bool fieldIsVirtual() const
Definition: oof3.cpp:400
virtual void saveRecord()
Definition: oof1.cpp:1689
virtual void EnteringAboutToLoad()
Definition: oofgui.cpp:502
void last()
Last record in the selection becomes current.
Definition: oof1.cpp:2199
unsigned long recordNumberOfOID(oidT inOID)
Find ordinal position in ordered selection of record by OID.
Definition: oof1.h:2056
static void warnUser(std::ostream &os)
Definition: oofgui.cpp:657
bool isAllRecs() const
Definition: oof2.cpp:746
virtual ~dbAbstractEditHelper()
Definition: oofgui.cpp:407
void goFirstRecord()
Definition: oofgui.cpp:158
virtual oofString copyString() const
Definition: oof3.cpp:472
virtual OOF_fieldTypes fieldType() const =0
void next()
Definition: oof1.h:1519
unsigned long OOFmsgT
Definition: oofmsg.h:31
bool transactionDirty()
Definition: oof1.h:2456
void cloneRecord()
Definition: oofgui.cpp:130
virtual void setString(const oofString &)
Definition: oofgui.cpp:938
void goLastRecord()
Definition: oofgui.cpp:206
Definition: oofync.h:37
void unlockRecord()
Definition: oof1.h:2447
Cross-platform class providing MessageBox functionality.
Definition: oofync.h:57
bool isValid() const
Definition: oof4.h:2149
bool isNewRecord() const
Definition: oof1.h:2341
void saveRecord()
Definition: oofgui.cpp:100
void careIfLocked()
Definition: oofgui.h:604
bool isValuePicker() const
Definition: oofgui.h:730
OOF_Dictionary mLinks
Definition: oofgui.h:473
virtual void updateDerivedFieldDisplay(bool isNew)
Definition: oofgui.cpp:1455
Abstract base Controller class managing database to GUI mapping.
Definition: oofgui.h:355
const OOFmsgT OOFmsg_SaveRecord
Definition: oofmsg.h:38
oidT currentOID()
Absolute record address of current record.
Definition: oof1.h:1938
dbAbstractEditHelper(dbTable *)
Definition: oofgui.cpp:391
bool leaveRecord()
Get permission to leave record and unlock including commmit/abort transactions.
Definition: oofgui.cpp:245
virtual void LoadData()
Definition: oofgui.cpp:646
virtual bool validToLeaveLink()
Validate field contents, overridden if can check just contents.
Definition: oofgui.cpp:1508
dbGUI(dbTable *)
Definition: oofgui.cpp:50
dbTable * mMainTable
Definition: oofgui.h:472
virtual bool equalsString(const oofString &) const
Definition: oofgui.cpp:946
virtual void deleteRecord()
Definition: oof1.cpp:1749
dbTable * table() const
Definition: oofview.h:109
void unloadRecord()
Definition: oof1.cpp:2536
bool isManyToOne() const
Definition: oofrel.h:276
void broadcast(OOFmsgT msg, unsigned long senderDefined=0, const oofReceiver *skipping=0)
Broadcast a message to all anonymous subscribers.
Definition: oofmsg.cpp:82
Base class for persistent fields in dbTable's.
Definition: oof3.h:63
bool isRecordLoaded() const
Definition: oof1.h:1823
void newRecord()
Definition: oofgui.cpp:89
virtual void cloneRecord()
Definition: oof1.cpp:1657
bool ensureRecordLoaded(bool autoCreateRelated=false, bool failureAborts=true)
Definition: oof1.cpp:1228
Relationship field to 1 or 0 instances.
Definition: oofrel.h:113
void ResetDirtyLinks()
Definition: oofgui.cpp:687
dbHelper(dbTable *)
Definition: oofgui.cpp:266
bool ConfirmDelete(const char *confirmMessage=0)
Definition: oofgui.cpp:61
void abortTransaction(short rMode=0)
Forward request to backend to abort transaction, if mInTransaction.
Definition: oof1.cpp:2264
bool atLast() const
Definition: oof1.h:1920
virtual bool SendImmediateFrameworkMessage(OOFmsgT, void *ioParam=0)
Send a message so any listeners can approve an action.
Definition: oofgui.cpp:778