src/qt3support/sql/q3databrowser.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt3Support module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "q3databrowser.h"
       
    43 
       
    44 #ifndef QT_NO_SQL_VIEW_WIDGETS
       
    45 
       
    46 #include "q3sqlform.h"
       
    47 #include "private/q3sqlmanager_p.h"
       
    48 #include "qsqlresult.h"
       
    49 
       
    50 QT_BEGIN_NAMESPACE
       
    51 
       
    52 class Q3DataBrowserPrivate
       
    53 {
       
    54 public:
       
    55     Q3DataBrowserPrivate() : boundaryCheck(true), readOnly(false) {}
       
    56     Q3SqlCursorManager cur;
       
    57     Q3SqlFormManager frm;
       
    58     Q3DataManager dat;
       
    59     bool boundaryCheck;
       
    60     bool readOnly;
       
    61 };
       
    62 
       
    63 /*!
       
    64     \class Q3DataBrowser
       
    65     \brief The Q3DataBrowser class provides data manipulation and
       
    66     navigation for data entry forms.
       
    67 
       
    68     \compat
       
    69 
       
    70     A high-level API is provided for navigating through data records
       
    71     in a cursor, for inserting, updating and deleting records, and for
       
    72     refreshing data in the display.
       
    73 
       
    74     If you want a read-only form to present database data use
       
    75     Q3DataView; if you want a table-based presentation of your data use
       
    76     Q3DataTable.
       
    77 
       
    78     A Q3DataBrowser is used to associate a dataset with a form in much
       
    79     the same way as a Q3DataTable associates a dataset with a table.
       
    80     Once the data browser has been constructed it can be associated
       
    81     with a dataset with setSqlCursor(), and with a form with
       
    82     setForm(). Boundary checking, sorting and filtering can be set
       
    83     with setBoundaryChecking(), setSort() and setFilter(),
       
    84     respectively.
       
    85 
       
    86     The insertCurrent() function reads the fields from the default
       
    87     form into the default cursor and performs the insert. The
       
    88     updateCurrent() and deleteCurrent() functions perform similarly to
       
    89     update and delete the current record respectively.
       
    90 
       
    91     The user can be asked to confirm all edits with setConfirmEdits().
       
    92     For more precise control use setConfirmInsert(),
       
    93     setConfirmUpdate(), setConfirmDelete() and setConfirmCancels().
       
    94     Use setAutoEdit() to control the behavior of the form when the
       
    95     user edits a record and then navigates.
       
    96 
       
    97     The record set is navigated using first(), next(), prev(), last()
       
    98     and seek(). The form's display is updated with refresh(). When
       
    99     navigation takes place the firstRecordAvailable(),
       
   100     lastRecordAvailable(), nextRecordAvailable() and
       
   101     prevRecordAvailable() signals are emitted. When the cursor record
       
   102     is changed due to navigation the cursorChanged() signal is
       
   103     emitted.
       
   104 
       
   105     If you want finer control of the insert, update and delete
       
   106     processes then you can use the lower level functions to perform
       
   107     these operations as described below.
       
   108 
       
   109     The form is populated with data from the database with
       
   110     readFields(). If the user is allowed to edit, (see setReadOnly()),
       
   111     write the form's data back to the cursor's edit buffer with
       
   112     writeFields(). You can clear the values in the form with
       
   113     clearValues(). Editing is performed as follows:
       
   114     \list
       
   115     \i \e insert When the data browser enters insertion mode it emits the
       
   116     primeInsert() signal which you can connect to, for example to
       
   117     pre-populate fields. Call writeFields() to write the user's edits to
       
   118     the cursor's edit buffer then call insert() to insert the record
       
   119     into the database. The beforeInsert() signal is emitted just before
       
   120     the cursor's edit buffer is inserted into the database; connect to
       
   121     this for example, to populate fields such as an auto-generated
       
   122     primary key.
       
   123     \i \e update For updates the primeUpdate() signal is emitted when
       
   124     the data browser enters update mode. After calling writeFields()
       
   125     call update() to update the record and connect to the beforeUpdate()
       
   126     signal to manipulate the user's data before the update takes place.
       
   127     \i \e delete For deletion the primeDelete() signal is emitted when
       
   128     the data browser enters deletion mode. After calling writeFields()
       
   129     call del() to delete the record and connect to the beforeDelete()
       
   130     signal, for example to record an audit of the deleted record.
       
   131     \endlist
       
   132 
       
   133 */
       
   134 
       
   135 /*!
       
   136     \enum Q3DataBrowser::Boundary
       
   137 
       
   138     This enum describes where the data browser is positioned.
       
   139 
       
   140     \value Unknown  the boundary cannot be determined (usually because
       
   141     there is no default cursor, or the default cursor is not active).
       
   142 
       
   143     \value None  the browser is not positioned on a boundary, but it is
       
   144     positioned on a record somewhere in the middle.
       
   145 
       
   146     \value BeforeBeginning  the browser is positioned before the
       
   147     first available record.
       
   148 
       
   149     \value Beginning  the browser is positioned at the first record.
       
   150 
       
   151     \value End  the browser is positioned at the last
       
   152     record.
       
   153 
       
   154     \value AfterEnd  the browser is positioned after the last
       
   155     available record.
       
   156 */
       
   157 
       
   158 /*!
       
   159     Constructs a data browser which is a child of \a parent, with the
       
   160     name \a name and widget flags set to \a fl.
       
   161 */
       
   162 
       
   163 Q3DataBrowser::Q3DataBrowser(QWidget *parent, const char *name, Qt::WindowFlags fl)
       
   164     : QWidget(parent, name, fl)
       
   165 {
       
   166     d = new Q3DataBrowserPrivate();
       
   167     d->dat.setMode(QSql::Update);
       
   168 }
       
   169 
       
   170 /*!
       
   171     Destroys the object and frees any allocated resources.
       
   172 */
       
   173 
       
   174 Q3DataBrowser::~Q3DataBrowser()
       
   175 {
       
   176     delete d;
       
   177 }
       
   178 
       
   179 
       
   180 /*!
       
   181     Returns an enum indicating the boundary status of the browser.
       
   182 
       
   183     This is achieved by moving the default cursor and checking the
       
   184     position, however the current default form values will not be
       
   185     altered. After checking for the boundary, the cursor is moved back
       
   186     to its former position. See \l Q3DataBrowser::Boundary.
       
   187 
       
   188     \sa Boundary
       
   189 */
       
   190 
       
   191 Q3DataBrowser::Boundary Q3DataBrowser::boundary()
       
   192 {
       
   193     Q3SqlCursor* cur = d->cur.cursor();
       
   194     if (!cur || !cur->isActive())
       
   195         return Unknown;
       
   196     if (!cur->isValid()) {
       
   197         if (cur->at() == QSql::BeforeFirst)
       
   198             return BeforeBeginning;
       
   199         if (cur->at() == QSql::AfterLast)
       
   200             return AfterEnd;
       
   201         return Unknown;
       
   202     }
       
   203     if (cur->at() == 0)
       
   204         return Beginning;
       
   205     int currentAt = cur->at();
       
   206 
       
   207     Boundary b = None;
       
   208     if (!cur->previous())
       
   209         b = Beginning;
       
   210     else
       
   211         cur->seek(currentAt);
       
   212     if (b == None && !cur->next())
       
   213         b = End;
       
   214     cur->seek(currentAt);
       
   215     return b;
       
   216 }
       
   217 
       
   218 
       
   219 /*!
       
   220     \property Q3DataBrowser::boundaryChecking
       
   221     \brief whether boundary checking is active
       
   222 
       
   223     When boundary checking is active (the default), signals are
       
   224     emitted indicating the current position of the default cursor.
       
   225 
       
   226     \sa boundary()
       
   227 */
       
   228 
       
   229 void Q3DataBrowser::setBoundaryChecking(bool active)
       
   230 {
       
   231     d->boundaryCheck = active;
       
   232 }
       
   233 
       
   234 bool Q3DataBrowser::boundaryChecking() const
       
   235 {
       
   236     return d->boundaryCheck;
       
   237 }
       
   238 
       
   239 /*!
       
   240     \property Q3DataBrowser::sort
       
   241     \brief the data browser's sort
       
   242 
       
   243     The data browser's sort affects the order in which records are
       
   244     viewed in the browser. Call refresh() to apply the new sort.
       
   245 
       
   246     When retrieving the sort property, a string list is returned in
       
   247     the form 'fieldname order', e.g. 'id ASC', 'surname DESC'.
       
   248 
       
   249     There is no default sort.
       
   250 
       
   251     Note that if you want to iterate over the list, you should iterate
       
   252     over a copy, e.g.
       
   253     \snippet doc/src/snippets/code/src_qt3support_sql_q3databrowser.cpp 0
       
   254 */
       
   255 
       
   256 void Q3DataBrowser::setSort(const QStringList& sort)
       
   257 {
       
   258     d->cur.setSort(sort);
       
   259 }
       
   260 
       
   261 /*!
       
   262     \overload
       
   263 
       
   264     Sets the data browser's sort to the QSqlIndex \a sort. To apply
       
   265     the new sort, use refresh().
       
   266 
       
   267 */
       
   268 void Q3DataBrowser::setSort(const QSqlIndex& sort)
       
   269 {
       
   270     d->cur.setSort(sort);
       
   271 }
       
   272 
       
   273 QStringList Q3DataBrowser::sort() const
       
   274 {
       
   275     return d->cur.sort();
       
   276 }
       
   277 
       
   278 
       
   279 /*!
       
   280     \property Q3DataBrowser::filter
       
   281     \brief the data browser's filter
       
   282 
       
   283     The filter applies to the data shown in the browser. Call
       
   284     refresh() to apply the new filter. A filter is a string containing
       
   285     a SQL WHERE clause without the WHERE keyword, e.g. "id>1000",
       
   286     "name LIKE 'A%'", etc.
       
   287 
       
   288     There is no default filter.
       
   289 
       
   290     \sa sort()
       
   291 */
       
   292 
       
   293 void Q3DataBrowser::setFilter(const QString& filter)
       
   294 {
       
   295     d->cur.setFilter(filter);
       
   296 }
       
   297 
       
   298 
       
   299 QString Q3DataBrowser::filter() const
       
   300 {
       
   301     return d->cur.filter();
       
   302 }
       
   303 
       
   304 
       
   305 /*!
       
   306     Sets the default cursor used by the data browser to \a cursor. If
       
   307     \a autoDelete is true (the default is false), the data browser
       
   308     takes ownership of the \a cursor pointer, which will be deleted
       
   309     when the browser is destroyed, or when setSqlCursor() is called
       
   310     again. To activate the \a cursor use refresh(). The cursor's edit
       
   311     buffer is used in the default form to browse and edit records.
       
   312 
       
   313     \sa sqlCursor() form() setForm()
       
   314 */
       
   315 
       
   316 void Q3DataBrowser::setSqlCursor(Q3SqlCursor* cursor, bool autoDelete)
       
   317 {
       
   318     if (!cursor)
       
   319         return;
       
   320     d->cur.setCursor(cursor, autoDelete);
       
   321     d->frm.setRecord(cursor->editBuffer());
       
   322     if (cursor->isReadOnly())
       
   323         setReadOnly(true);
       
   324 }
       
   325 
       
   326 
       
   327 /*!
       
   328     Returns the default cursor used for navigation, or 0 if there is
       
   329     no default cursor.
       
   330 
       
   331     \sa setSqlCursor()
       
   332 */
       
   333 
       
   334 Q3SqlCursor* Q3DataBrowser::sqlCursor() const
       
   335 {
       
   336     return d->cur.cursor();
       
   337 }
       
   338 
       
   339 
       
   340 /*!
       
   341     Sets the browser's default form to \a form. The cursor and all
       
   342     navigation and data manipulation functions that the browser
       
   343     provides become available to the \a form.
       
   344 */
       
   345 
       
   346 void Q3DataBrowser::setForm(Q3SqlForm* form)
       
   347 {
       
   348     d->frm.setForm(form);
       
   349 }
       
   350 
       
   351 
       
   352 /*!
       
   353     Returns the data browser's default form or 0 if no form has been
       
   354     set.
       
   355 */
       
   356 
       
   357 Q3SqlForm* Q3DataBrowser::form()
       
   358 {
       
   359     return d->frm.form();
       
   360 }
       
   361 
       
   362 /*!
       
   363     \property Q3DataBrowser::readOnly
       
   364     \brief whether the browser is read-only
       
   365 
       
   366     The default is false, i.e. data can be edited. If the data browser
       
   367     is read-only, no database edits will be allowed.
       
   368 */
       
   369 
       
   370 void Q3DataBrowser::setReadOnly(bool active)
       
   371 {
       
   372     d->readOnly = active;
       
   373 }
       
   374 
       
   375 bool Q3DataBrowser::isReadOnly() const
       
   376 {
       
   377     return d->readOnly;
       
   378 }
       
   379 
       
   380 void Q3DataBrowser::setConfirmEdits(bool confirm)
       
   381 {
       
   382     d->dat.setConfirmEdits(confirm);
       
   383 }
       
   384 
       
   385 /*!
       
   386     \property Q3DataBrowser::confirmInsert
       
   387     \brief whether the data browser confirms insertions
       
   388 
       
   389     If this property is true, the browser confirms insertions,
       
   390     otherwise insertions happen immediately.
       
   391 
       
   392     \sa confirmCancels() confirmEdits() confirmUpdate() confirmDelete() confirmEdit()
       
   393 */
       
   394 
       
   395 void Q3DataBrowser::setConfirmInsert(bool confirm)
       
   396 {
       
   397     d->dat.setConfirmInsert(confirm);
       
   398 }
       
   399 
       
   400 /*!
       
   401     \property Q3DataBrowser::confirmUpdate
       
   402     \brief whether the browser confirms updates
       
   403 
       
   404     If this property is true, the browser confirms updates, otherwise
       
   405     updates happen immediately.
       
   406 
       
   407     \sa confirmCancels() confirmEdits() confirmInsert() confirmDelete() confirmEdit()
       
   408 */
       
   409 
       
   410 void Q3DataBrowser::setConfirmUpdate(bool confirm)
       
   411 {
       
   412     d->dat.setConfirmUpdate(confirm);
       
   413 }
       
   414 
       
   415 /*!
       
   416     \property Q3DataBrowser::confirmDelete
       
   417     \brief whether the browser confirms deletions
       
   418 
       
   419     If this property is true, the browser confirms deletions,
       
   420     otherwise deletions happen immediately.
       
   421 
       
   422     \sa confirmCancels() confirmEdits() confirmUpdate() confirmInsert() confirmEdit()
       
   423 */
       
   424 
       
   425 void Q3DataBrowser::setConfirmDelete(bool confirm)
       
   426 {
       
   427     d->dat.setConfirmDelete(confirm);
       
   428 }
       
   429 
       
   430 /*!
       
   431     \property Q3DataBrowser::confirmEdits
       
   432     \brief whether the browser confirms edits
       
   433 
       
   434     If this property is true, the browser confirms all edit operations
       
   435     (insertions, updates and deletions), otherwise all edit operations
       
   436     happen immediately. Confirmation is achieved by presenting the
       
   437     user with a message box -- this behavior can be changed by
       
   438     reimplementing the confirmEdit() function,
       
   439 
       
   440     \sa confirmEdit() confirmCancels() confirmInsert() confirmUpdate() confirmDelete()
       
   441 */
       
   442 
       
   443 bool Q3DataBrowser::confirmEdits() const
       
   444 {
       
   445     return (d->dat.confirmEdits());
       
   446 }
       
   447 
       
   448 bool Q3DataBrowser::confirmInsert() const
       
   449 {
       
   450     return (d->dat.confirmInsert());
       
   451 }
       
   452 
       
   453 bool Q3DataBrowser::confirmUpdate() const
       
   454 {
       
   455     return (d->dat.confirmUpdate());
       
   456 }
       
   457 
       
   458 bool Q3DataBrowser::confirmDelete() const
       
   459 {
       
   460     return (d->dat.confirmDelete());
       
   461 }
       
   462 
       
   463 /*!
       
   464     \property Q3DataBrowser::confirmCancels
       
   465     \brief whether the browser confirms cancel operations
       
   466 
       
   467     If this property is true, all cancels must be confirmed by the
       
   468     user through a message box (this behavior can be changed by
       
   469     overriding the confirmCancel() function), otherwise all cancels
       
   470     occur immediately. The default is false.
       
   471 
       
   472     \sa confirmEdits() confirmCancel()
       
   473 */
       
   474 
       
   475 void Q3DataBrowser::setConfirmCancels(bool confirm)
       
   476 {
       
   477     d->dat.setConfirmCancels(confirm);
       
   478 }
       
   479 
       
   480 bool Q3DataBrowser::confirmCancels() const
       
   481 {
       
   482     return d->dat.confirmCancels();
       
   483 }
       
   484 
       
   485 /*!
       
   486     \property Q3DataBrowser::autoEdit
       
   487     \brief whether the browser automatically applies edits
       
   488 
       
   489     The default value for this property is true. When the user begins
       
   490     an insertion or an update on a form there are two possible
       
   491     outcomes when they navigate to another record:
       
   492 
       
   493     \list
       
   494     \i the insert or update is is performed -- this occurs if autoEdit is true
       
   495     \i the insert or update is discarded -- this occurs if autoEdit is false
       
   496     \endlist
       
   497 */
       
   498 
       
   499 void Q3DataBrowser::setAutoEdit(bool autoEdit)
       
   500 {
       
   501     d->dat.setAutoEdit(autoEdit);
       
   502 }
       
   503 
       
   504 bool Q3DataBrowser::autoEdit() const
       
   505 {
       
   506     return d->dat.autoEdit();
       
   507 }
       
   508 
       
   509 /*!
       
   510     \fn void Q3DataBrowser::firstRecordAvailable(bool available)
       
   511 
       
   512     This signal is emitted whenever the position of the cursor
       
   513     changes. The \a available parameter indicates whether or not the
       
   514     first record in the default cursor is available.
       
   515 */
       
   516 
       
   517 /*!
       
   518     \fn void Q3DataBrowser::lastRecordAvailable(bool available)
       
   519 
       
   520     This signal is emitted whenever the position of the cursor
       
   521     changes. The \a available parameter indicates whether or not the
       
   522     last record in the default cursor is available.
       
   523 */
       
   524 
       
   525 /*!
       
   526     \fn void Q3DataBrowser::nextRecordAvailable(bool available)
       
   527 
       
   528     This signal is emitted whenever the position of the cursor
       
   529     changes. The \a available parameter indicates whether or not the
       
   530     next record in the default cursor is available.
       
   531 */
       
   532 
       
   533 
       
   534 /*!
       
   535     \fn void Q3DataBrowser::prevRecordAvailable(bool available)
       
   536 
       
   537     This signal is emitted whenever the position of the cursor
       
   538     changes. The \a available parameter indicates whether or not the
       
   539     previous record in the default cursor is available.
       
   540 */
       
   541 
       
   542 
       
   543 /*!
       
   544     \fn void Q3DataBrowser::currentChanged(const QSqlRecord* record)
       
   545 
       
   546     This signal is emitted whenever the current cursor position
       
   547     changes. The \a record parameter points to the contents of the
       
   548     current cursor's record.
       
   549 */
       
   550 
       
   551 
       
   552 /*!
       
   553     \fn void Q3DataBrowser::primeInsert(QSqlRecord* buf)
       
   554 
       
   555     This signal is emitted when the data browser enters insertion
       
   556     mode. The \a buf parameter points to the record buffer that is to
       
   557     be inserted. Connect to this signal to, for example, prime the
       
   558     record buffer with default data values, auto-numbered fields etc.
       
   559     (Note that Q3SqlCursor::primeInsert() is \e not called on the
       
   560     default cursor, as this would corrupt values in the form.)
       
   561 
       
   562     \sa insert()
       
   563 */
       
   564 
       
   565 
       
   566 /*!
       
   567     \fn void Q3DataBrowser::primeUpdate(QSqlRecord* buf)
       
   568 
       
   569     This signal is emitted when the data browser enters update mode.
       
   570     Note that during navigation (first(), last(), next(), prev()),
       
   571     each record that is shown in the default form is primed for
       
   572     update. The \a buf parameter points to the record buffer being
       
   573     updated. (Note that Q3SqlCursor::primeUpdate() is \e not called on
       
   574     the default cursor, as this would corrupt values in the form.)
       
   575     Connect to this signal in order to, for example, keep track of
       
   576     which records have been updated, perhaps for auditing purposes.
       
   577 
       
   578     \sa update()
       
   579 */
       
   580 
       
   581 /*!
       
   582     \fn void Q3DataBrowser::primeDelete(QSqlRecord* buf)
       
   583 
       
   584     This signal is emitted when the data browser enters deletion mode.
       
   585     The \a buf parameter points to the record buffer being deleted.
       
   586     (Note that Q3SqlCursor::primeDelete() is \e not called on the
       
   587     default cursor, as this would corrupt values in the form.)
       
   588     Connect to this signal in order to, for example, save a copy of
       
   589     the deleted record for auditing purposes.
       
   590 
       
   591     \sa del()
       
   592 */
       
   593 
       
   594 
       
   595 /*!
       
   596     \fn void Q3DataBrowser::cursorChanged(Q3SqlCursor::Mode mode)
       
   597 
       
   598     This signal is emitted whenever the cursor record was changed due
       
   599     to navigation. The \a mode parameter is the edit that just took
       
   600     place, e.g. Insert, Update or Delete. See \l Q3SqlCursor::Mode.
       
   601 */
       
   602 
       
   603 
       
   604 /*!
       
   605     Refreshes the data browser's data using the default cursor. The
       
   606     browser's current filter and sort are applied if they have been
       
   607     set.
       
   608 
       
   609     \sa setFilter() setSort()
       
   610 */
       
   611 
       
   612 void Q3DataBrowser::refresh()
       
   613 {
       
   614     d->cur.refresh();
       
   615 }
       
   616 
       
   617 
       
   618 /*!
       
   619     Performs an insert operation on the data browser's cursor. If
       
   620     there is no default cursor or no default form, nothing happens.
       
   621 
       
   622     If auto-editing is on (see setAutoEdit()), the following happens:
       
   623 
       
   624     \list
       
   625     \i If the browser is already actively inserting a record,
       
   626     the current form's data is inserted into the database.
       
   627     \i If the browser is not inserting a record, but the current record
       
   628     was changed by the user, the record is updated in the database with
       
   629     the current form's data (i.e. with the changes).
       
   630     \endlist
       
   631 
       
   632     If there is an error handling any of the above auto-edit actions,
       
   633     handleError() is called and no insert or update is performed.
       
   634 
       
   635     If no error occurred, or auto-editing is not enabled, the data browser
       
   636     begins actively inserting a record into the database by performing the
       
   637     following actions:
       
   638 
       
   639     \list
       
   640     \i The default cursor is primed for insert using Q3SqlCursor::primeInsert().
       
   641     \i The primeInsert() signal is emitted.
       
   642     \i The form is updated with the values in the default cursor's.
       
   643     edit buffer so that the user can fill in the values to be inserted.
       
   644     \endlist
       
   645 
       
   646 */
       
   647 
       
   648 void Q3DataBrowser::insert()
       
   649 {
       
   650     QSqlRecord* buf = d->frm.record();
       
   651     Q3SqlCursor* cur = d->cur.cursor();
       
   652     if (!buf || !cur)
       
   653         return;
       
   654     bool doIns = true;
       
   655     QSql::Confirm conf = QSql::Yes;
       
   656     switch (d->dat.mode()) {
       
   657     case QSql::Insert:
       
   658         if (autoEdit()) {
       
   659             if (confirmInsert())
       
   660                 conf = confirmEdit(QSql::Insert);
       
   661             switch (conf) {
       
   662             case QSql::Yes:
       
   663                 insertCurrent();
       
   664                 break;
       
   665             case QSql::No:
       
   666                 break;
       
   667             case QSql::Cancel:
       
   668                 doIns = false;
       
   669                 break;
       
   670             }
       
   671         }
       
   672         break;
       
   673     default:
       
   674         if (autoEdit() && currentEdited()) {
       
   675             if (confirmUpdate())
       
   676                 conf = confirmEdit(QSql::Update);
       
   677             switch (conf) {
       
   678             case QSql::Yes:
       
   679                 updateCurrent();
       
   680                 break;
       
   681             case QSql::No:
       
   682                 break;
       
   683             case QSql::Cancel:
       
   684                 doIns = false;
       
   685                 break;
       
   686             }
       
   687         }
       
   688         break;
       
   689     }
       
   690     if (doIns) {
       
   691         d->dat.setMode(QSql::Insert);
       
   692         sqlCursor()->primeInsert();
       
   693         emit primeInsert(d->frm.record());
       
   694         readFields();
       
   695     }
       
   696 }
       
   697 
       
   698 
       
   699 /*!
       
   700     Performs an update operation on the data browser's cursor.
       
   701 
       
   702     If there is no default cursor or no default form, nothing happens.
       
   703     Otherwise, the following happens:
       
   704 
       
   705     If the data browser is actively inserting a record (see insert()),
       
   706     that record is inserted into the database using insertCurrent().
       
   707     Otherwise, the database is updated with the current form's data
       
   708     using updateCurrent(). If there is an error handling either
       
   709     action, handleError() is called.
       
   710 */
       
   711 
       
   712 void Q3DataBrowser::update()
       
   713 {
       
   714     QSqlRecord* buf = d->frm.record();
       
   715     Q3SqlCursor* cur = d->cur.cursor();
       
   716     if (!buf || !cur)
       
   717         return;
       
   718     QSql::Confirm conf = QSql::Yes;
       
   719     switch (d->dat.mode()){
       
   720     case QSql::Insert:
       
   721         if (confirmInsert())
       
   722             conf = confirmEdit(QSql::Insert);
       
   723         switch (conf) {
       
   724             case QSql::Yes:
       
   725                 if (insertCurrent())
       
   726                     d->dat.setMode(QSql::Update);
       
   727             break;
       
   728             case QSql::No:
       
   729                 d->dat.setMode(QSql::Update);
       
   730             cur->editBuffer(true);
       
   731             readFields();
       
   732             break;
       
   733             case QSql::Cancel:
       
   734             break;
       
   735         }
       
   736     break;
       
   737     default:
       
   738         d->dat.setMode(QSql::Update);
       
   739         if (confirmUpdate())
       
   740             conf = confirmEdit(QSql::Update);
       
   741         switch (conf) {
       
   742         case QSql::Yes:
       
   743             updateCurrent();
       
   744             break;
       
   745         case QSql::No:
       
   746         case QSql::Cancel:
       
   747             break;
       
   748         }
       
   749         break;
       
   750     }
       
   751 }
       
   752 
       
   753 
       
   754 /*!
       
   755     Performs a delete operation on the data browser's cursor. If there
       
   756     is no default cursor or no default form, nothing happens.
       
   757 
       
   758     Otherwise, the following happens:
       
   759 
       
   760     The current form's record is deleted from the database, providing
       
   761     that the data browser is not in insert mode. If the data browser
       
   762     is actively inserting a record (see insert()), the insert action
       
   763     is canceled, and the browser navigates to the last valid record
       
   764     that was current. If there is an error, handleError() is called.
       
   765 */
       
   766 
       
   767 void Q3DataBrowser::del()
       
   768 {
       
   769     QSqlRecord* buf = d->frm.record();
       
   770     Q3SqlCursor* cur = d->cur.cursor();
       
   771     if (!buf || !cur)
       
   772         return;
       
   773     QSql::Confirm conf = QSql::Yes;
       
   774     switch (d->dat.mode()){
       
   775     case QSql::Insert:
       
   776         if (confirmCancels())
       
   777             conf = confirmCancel(QSql::Insert);
       
   778         if (conf == QSql::Yes) {
       
   779             cur->editBuffer(true); /* restore from cursor */
       
   780             readFields();
       
   781             d->dat.setMode(QSql::Update);
       
   782         } else
       
   783             d->dat.setMode(QSql::Insert);
       
   784         break;
       
   785     default:
       
   786         if (confirmDelete())
       
   787             conf = confirmEdit(QSql::Delete);
       
   788         switch (conf) {
       
   789         case QSql::Yes:
       
   790             emit primeDelete(buf);
       
   791             deleteCurrent();
       
   792             break;
       
   793         case QSql::No:
       
   794         case QSql::Cancel:
       
   795             break;
       
   796         }
       
   797         d->dat.setMode(QSql::Update);
       
   798         break;
       
   799     }
       
   800 }
       
   801 
       
   802 /*!
       
   803   Moves the default cursor to the record specified by index \a i
       
   804   and refreshes the default form to display that record. If there is
       
   805   no default form or no default cursor, nothing happens. If
       
   806   \a relative is true (the default is false), the cursor is moved
       
   807   relative to its current position. If the data browser successfully
       
   808   navigated to the desired record, the default cursor is primed for
       
   809   update and the primeUpdate() signal is emitted.
       
   810   
       
   811   If the browser is already positioned on the desired record nothing
       
   812   happens. Returns false if there is no cursor. Otherwise returns
       
   813   true.
       
   814 */
       
   815 
       
   816 bool Q3DataBrowser::seek(int i, bool relative)
       
   817 {
       
   818     int b = 0;
       
   819     Q3SqlCursor* cur = d->cur.cursor();
       
   820     if (!cur)
       
   821         return false;
       
   822     if (preNav())
       
   823         b = cur->seek(i, relative);
       
   824     postNav(b);
       
   825     return b;
       
   826 }
       
   827 
       
   828 /*!
       
   829     Moves the default cursor to the first record and refreshes the
       
   830     default form to display this record. If there is no default form
       
   831     or no default cursor, nothing happens. If the data browser
       
   832     successfully navigated to the first record, the default cursor is
       
   833     primed for update and the primeUpdate() signal is emitted.
       
   834 
       
   835     If the browser is already positioned on the first record nothing
       
   836     happens.
       
   837 
       
   838 */
       
   839 
       
   840 void Q3DataBrowser::first()
       
   841 {
       
   842     nav(&Q3SqlCursor::first);
       
   843 }
       
   844 
       
   845 
       
   846 /*!
       
   847     Moves the default cursor to the last record and refreshes the
       
   848     default form to display this record. If there is no default form
       
   849     or no default cursor, nothing happens. If the data browser
       
   850     successfully navigated to the last record, the default cursor is
       
   851     primed for update and the primeUpdate() signal is emitted.
       
   852 
       
   853     If the browser is already positioned on the last record nothing
       
   854     happens.
       
   855 */
       
   856 
       
   857 void Q3DataBrowser::last()
       
   858 {
       
   859     nav(&Q3SqlCursor::last);
       
   860 }
       
   861 
       
   862 
       
   863 /*!
       
   864     Moves the default cursor to the next record and refreshes the
       
   865     default form to display this record. If there is no default form
       
   866     or no default cursor, nothing happens. If the data browser
       
   867     successfully navigated to the next record, the default cursor is
       
   868     primed for update and the primeUpdate() signal is emitted.
       
   869 
       
   870     If the browser is positioned on the last record nothing happens.
       
   871 */
       
   872 
       
   873 void Q3DataBrowser::next()
       
   874 {
       
   875     nav(&Q3SqlCursor::next);
       
   876 }
       
   877 
       
   878 
       
   879 /*!
       
   880     Moves the default cursor to the previous record and refreshes the
       
   881     default form to display this record. If there is no default form
       
   882     or no default cursor, nothing happens. If the data browser
       
   883     successfully navigated to the previous record, the default cursor
       
   884     is primed for update and the primeUpdate() signal is emitted.
       
   885 
       
   886     If the browser is positioned on the first record nothing happens.
       
   887 */
       
   888 
       
   889 void Q3DataBrowser::prev()
       
   890 {
       
   891     nav(&Q3SqlCursor::previous);
       
   892 }
       
   893 
       
   894 /*!
       
   895     Reads the fields from the default cursor's edit buffer and
       
   896     displays them in the form. If there is no default cursor or no
       
   897     default form, nothing happens.
       
   898 */
       
   899 
       
   900 void Q3DataBrowser::readFields()
       
   901 {
       
   902     d->frm.readFields();
       
   903 }
       
   904 
       
   905 
       
   906 /*!
       
   907     Writes the form's data to the default cursor's edit buffer. If
       
   908     there is no default cursor or no default form, nothing happens.
       
   909 */
       
   910 
       
   911 void Q3DataBrowser::writeFields()
       
   912 {
       
   913     d->frm.writeFields();
       
   914 }
       
   915 
       
   916 
       
   917 /*!
       
   918     Clears all the values in the form.
       
   919 
       
   920     All the edit buffer field values are set to their 'zero state',
       
   921     e.g. 0 for numeric fields and "" for string fields. Then the
       
   922     widgets are updated using the property map. For example, a
       
   923     combobox that is property-mapped to integers would scroll to the
       
   924     first item. See the \l Q3SqlPropertyMap constructor for the default
       
   925     mappings of widgets to properties.
       
   926 */
       
   927 
       
   928 void Q3DataBrowser::clearValues()
       
   929 {
       
   930     d->frm.clearValues();
       
   931 }
       
   932 
       
   933 /*!
       
   934     Reads the fields from the default form into the default cursor and
       
   935     performs an insert on the default cursor. If there is no default
       
   936     form or no default cursor, nothing happens. If an error occurred
       
   937     during the insert into the database, handleError() is called and
       
   938     false is returned. If the insert was successful, the cursor is
       
   939     refreshed and relocated to the newly inserted record, the
       
   940     cursorChanged() signal is emitted, and true is returned.
       
   941 
       
   942     \sa cursorChanged() sqlCursor() form() handleError()
       
   943 */
       
   944 
       
   945 bool Q3DataBrowser::insertCurrent()
       
   946 {
       
   947     if (isReadOnly())
       
   948         return false;
       
   949     QSqlRecord* buf = d->frm.record();
       
   950     Q3SqlCursor* cur = d->cur.cursor();
       
   951     if (!buf || !cur)
       
   952         return false;
       
   953     writeFields();
       
   954     emit beforeInsert(buf);
       
   955     int ar = cur->insert();
       
   956     if (!ar || !cur->isActive()) {
       
   957         handleError(cur->lastError());
       
   958         refresh();
       
   959         updateBoundary();
       
   960     } else {
       
   961         refresh();
       
   962         d->cur.findBuffer(cur->primaryIndex());
       
   963         updateBoundary();
       
   964         cursorChanged(Q3SqlCursor::Insert);
       
   965         return true;
       
   966     }
       
   967     return false;
       
   968 }
       
   969 
       
   970 
       
   971 /*!
       
   972     Reads the fields from the default form into the default cursor and
       
   973     performs an update on the default cursor. If there is no default
       
   974     form or no default cursor, nothing happens. If an error occurred
       
   975     during the update on the database, handleError() is called and
       
   976     false is returned. If the update was successful, the cursor is
       
   977     refreshed and relocated to the updated record, the cursorChanged()
       
   978     signal is emitted, and true is returned.
       
   979 
       
   980     \sa cursor() form() handleError()
       
   981 */
       
   982 
       
   983 bool Q3DataBrowser::updateCurrent()
       
   984 {
       
   985     if (isReadOnly())
       
   986         return false;
       
   987     QSqlRecord* buf = d->frm.record();
       
   988     Q3SqlCursor* cur = d->cur.cursor();
       
   989     if (!buf || !cur)
       
   990         return false;
       
   991     writeFields();
       
   992     emit beforeUpdate(buf);
       
   993     int ar = cur->update();
       
   994     if (!ar || !cur->isActive()) {
       
   995         handleError(cur->lastError());
       
   996         refresh();
       
   997         updateBoundary();
       
   998     } else {
       
   999         refresh();
       
  1000         d->cur.findBuffer(cur->primaryIndex());
       
  1001         updateBoundary();
       
  1002         cur->editBuffer(true);
       
  1003         cursorChanged(Q3SqlCursor::Update);
       
  1004         readFields();
       
  1005         return true;
       
  1006     }
       
  1007     return false;
       
  1008 }
       
  1009 
       
  1010 
       
  1011 /*!
       
  1012     Performs a delete on the default cursor using the values from the
       
  1013     default form and updates the default form. If there is no default
       
  1014     form or no default cursor, nothing happens. If the deletion was
       
  1015     successful, the cursor is repositioned to the nearest record and
       
  1016     true is returned. The nearest record is the next record if there
       
  1017     is one otherwise the previous record if there is one. If an error
       
  1018     occurred during the deletion from the database, handleError() is
       
  1019     called and false is returned.
       
  1020 
       
  1021     \sa cursor() form() handleError()
       
  1022 */
       
  1023 
       
  1024 bool Q3DataBrowser::deleteCurrent()
       
  1025 {
       
  1026     if (isReadOnly())
       
  1027         return false;
       
  1028     QSqlRecord* buf = d->frm.record();
       
  1029     Q3SqlCursor* cur = d->cur.cursor();
       
  1030     if (!buf || !cur)
       
  1031         return false;
       
  1032     writeFields();
       
  1033     int n = cur->at();
       
  1034     emit beforeDelete(buf);
       
  1035     int ar = cur->del();
       
  1036     if (ar) {
       
  1037         refresh();
       
  1038         updateBoundary();
       
  1039         cursorChanged(Q3SqlCursor::Delete);
       
  1040         if (!cur->seek(n))
       
  1041             last();
       
  1042         if (cur->isValid()) {
       
  1043             cur->editBuffer(true);
       
  1044             readFields();
       
  1045         } else {
       
  1046             clearValues();
       
  1047         }
       
  1048         return true;
       
  1049     } else {
       
  1050         if (!cur->isActive()) {
       
  1051             handleError(cur->lastError());
       
  1052             refresh();
       
  1053             updateBoundary();
       
  1054         }
       
  1055     }
       
  1056     return false;
       
  1057 }
       
  1058 
       
  1059 
       
  1060 /*!
       
  1061     Returns true if the form's edit buffer differs from the current
       
  1062     cursor buffer; otherwise returns false.
       
  1063 */
       
  1064 
       
  1065 bool Q3DataBrowser::currentEdited()
       
  1066 {
       
  1067     QSqlRecord* buf = d->frm.record();
       
  1068     Q3SqlCursor* cur = d->cur.cursor();
       
  1069     if (!buf || !cur)
       
  1070         return false;
       
  1071     if (!cur->isActive() || !cur->isValid())
       
  1072         return false;
       
  1073     writeFields();
       
  1074     for (int i = 0; i < cur->count(); ++i) {
       
  1075         if (cur->value(i) != buf->value(i))
       
  1076             return true;
       
  1077     }
       
  1078     return false;
       
  1079 }
       
  1080 
       
  1081 /*! \internal
       
  1082 
       
  1083   Pre-navigation checking.
       
  1084 */
       
  1085 
       
  1086 bool Q3DataBrowser::preNav()
       
  1087 {
       
  1088     QSqlRecord* buf = d->frm.record();
       
  1089     Q3SqlCursor* cur = d->cur.cursor();
       
  1090     if (!buf || !cur)
       
  1091         return false;
       
  1092 
       
  1093     if (!isReadOnly() && autoEdit() && currentEdited()) {
       
  1094         bool ok = true;
       
  1095         QSql::Confirm conf = QSql::Yes;
       
  1096         switch (d->dat.mode()){
       
  1097         case QSql::Insert:
       
  1098             if (confirmInsert())
       
  1099                 conf = confirmEdit(QSql::Insert);
       
  1100             switch (conf) {
       
  1101             case QSql::Yes:
       
  1102                 ok = insertCurrent();
       
  1103                 d->dat.setMode(QSql::Update);
       
  1104                 break;
       
  1105             case QSql::No:
       
  1106                 d->dat.setMode(QSql::Update);
       
  1107                 break;
       
  1108             case QSql::Cancel:
       
  1109                 return false;
       
  1110             }
       
  1111             break;
       
  1112         default:
       
  1113             if (confirmUpdate())
       
  1114                 conf = confirmEdit(QSql::Update);
       
  1115             switch (conf) {
       
  1116             case QSql::Yes:
       
  1117                 ok = updateCurrent();
       
  1118                 break;
       
  1119             case QSql::No:
       
  1120                 break;
       
  1121             case QSql::Cancel:
       
  1122                 return false;
       
  1123             }
       
  1124         }
       
  1125         return ok;
       
  1126     }
       
  1127     return true;
       
  1128 }
       
  1129 
       
  1130 /*! \internal
       
  1131 
       
  1132   Handles post-navigation according to \a primeUpd.
       
  1133 */
       
  1134 
       
  1135 void Q3DataBrowser::postNav(bool primeUpd)
       
  1136 {
       
  1137     if (primeUpd) {
       
  1138         QSqlRecord* buf = d->frm.record();
       
  1139         Q3SqlCursor* cur = d->cur.cursor();
       
  1140         if (!buf || !cur)
       
  1141             return;
       
  1142         currentChanged(cur);
       
  1143         cur->primeUpdate();
       
  1144         emit primeUpdate(buf);
       
  1145         readFields();
       
  1146     }
       
  1147     updateBoundary();
       
  1148 }
       
  1149 
       
  1150 /*! \internal
       
  1151 
       
  1152   Navigate default cursor according to \a nav. Handles autoEdit.
       
  1153 
       
  1154 */
       
  1155 void Q3DataBrowser::nav(Nav nav)
       
  1156 {
       
  1157     int b = 0;
       
  1158     Q3SqlCursor* cur = d->cur.cursor();
       
  1159     if (!cur)
       
  1160         return;
       
  1161     if (preNav())
       
  1162         b = (cur->*nav)();
       
  1163     postNav(b);
       
  1164 }
       
  1165 
       
  1166 /*!
       
  1167     If boundaryChecking() is true, checks the boundary of the current
       
  1168     default cursor and emits signals which indicate the position of
       
  1169     the cursor.
       
  1170 */
       
  1171 
       
  1172 void Q3DataBrowser::updateBoundary()
       
  1173 {
       
  1174     if (d->boundaryCheck) {
       
  1175         Boundary bound = boundary();
       
  1176         switch (bound) {
       
  1177         case Unknown:
       
  1178         case None:
       
  1179             emit firstRecordAvailable(true);
       
  1180             emit prevRecordAvailable(true);
       
  1181             emit nextRecordAvailable(true);
       
  1182             emit lastRecordAvailable(true);
       
  1183             break;
       
  1184 
       
  1185         case BeforeBeginning:
       
  1186             emit firstRecordAvailable(false);
       
  1187             emit prevRecordAvailable(false);
       
  1188             emit nextRecordAvailable(true);
       
  1189             emit lastRecordAvailable(true);
       
  1190             break;
       
  1191 
       
  1192         case Beginning:
       
  1193             emit firstRecordAvailable(false);
       
  1194             emit prevRecordAvailable(false);
       
  1195             emit nextRecordAvailable(true);
       
  1196             emit lastRecordAvailable(true);
       
  1197             break;
       
  1198 
       
  1199         case End:
       
  1200             emit firstRecordAvailable(true);
       
  1201             emit prevRecordAvailable(true);
       
  1202             emit nextRecordAvailable(false);
       
  1203             emit lastRecordAvailable(false);
       
  1204             break;
       
  1205 
       
  1206         case AfterEnd:
       
  1207             emit firstRecordAvailable(true);
       
  1208             emit prevRecordAvailable(true);
       
  1209             emit nextRecordAvailable(false);
       
  1210             emit lastRecordAvailable(false);
       
  1211             break;
       
  1212         }
       
  1213     }
       
  1214 }
       
  1215 
       
  1216 /*!
       
  1217     Virtual function which handles the error \a error. The default
       
  1218     implementation warns the user with a message box.
       
  1219 */
       
  1220 
       
  1221 void Q3DataBrowser::handleError(const QSqlError& error)
       
  1222 {
       
  1223     d->dat.handleError(this, error);
       
  1224 }
       
  1225 
       
  1226 /*!
       
  1227     Protected virtual function which returns a confirmation for an
       
  1228     edit of mode \a m. Derived classes can reimplement this function
       
  1229     and provide their own confirmation dialog. The default
       
  1230     implementation uses a message box which prompts the user to
       
  1231     confirm the edit action.
       
  1232 */
       
  1233 
       
  1234 QSql::Confirm Q3DataBrowser::confirmEdit(QSql::Op m)
       
  1235 {
       
  1236     return d->dat.confirmEdit(this, m);
       
  1237 }
       
  1238 
       
  1239 /*!
       
  1240     Protected virtual function which returns a confirmation for
       
  1241     canceling an edit mode \a m. Derived classes can reimplement this
       
  1242     function and provide their own confirmation dialog. The default
       
  1243     implementation uses a message box which prompts the user to
       
  1244     confirm the edit action.
       
  1245 */
       
  1246 
       
  1247 QSql::Confirm  Q3DataBrowser::confirmCancel(QSql::Op m)
       
  1248 {
       
  1249     return d->dat.confirmCancel(this, m);
       
  1250 }
       
  1251 
       
  1252 /*!
       
  1253     \fn void Q3DataBrowser::beforeInsert(QSqlRecord* buf)
       
  1254 
       
  1255     This signal is emitted just before the cursor's edit buffer is
       
  1256     inserted into the database. The \a buf parameter points to the
       
  1257     edit buffer being inserted. You might connect to this signal to
       
  1258     populate a generated primary key for example.
       
  1259 */
       
  1260 
       
  1261 /*!
       
  1262     \fn void Q3DataBrowser::beforeUpdate(QSqlRecord* buf)
       
  1263 
       
  1264     This signal is emitted just before the cursor's edit buffer is
       
  1265     updated in the database. The \a buf parameter points to the edit
       
  1266     buffer being updated. You might connect to this signal to capture
       
  1267     some auditing information about the update.
       
  1268 */
       
  1269 
       
  1270 /*!
       
  1271     \fn void Q3DataBrowser::beforeDelete(QSqlRecord* buf)
       
  1272 
       
  1273     This signal is emitted just before the cursor's edit buffer  is
       
  1274     deleted from the database. The \a buf parameter points to the edit
       
  1275     buffer being deleted. You might connect to this signal to capture
       
  1276     some auditing information about the deletion.
       
  1277 */
       
  1278 
       
  1279 QT_END_NAMESPACE
       
  1280 
       
  1281 #endif