~ubuntu-branches/ubuntu/maverick/datakiosk/maverick

« back to all changes in this revision

Viewing changes to src/datakiosk/src/datatablesearch.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2005-06-27 22:48:06 UTC
  • Revision ID: james.westby@ubuntu.com-20050627224806-8farkci1dc2onhbs
Tags: upstream-0.7
ImportĀ upstreamĀ versionĀ 0.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
*   Copyright (C) 2005 by Adam Treat                                      *
 
3
*   treat@kde.org                                                         *
 
4
*                                                                         *
 
5
*   Copyright (C) 2004 by Scott Wheeler                                   *
 
6
*   wheeler@kde.org                                                       *
 
7
*                                                                         *
 
8
*   This program is free software; you can redistribute it and/or modify  *
 
9
*   it under the terms of the GNU General Public License as published by  *
 
10
*   the Free Software Foundation; either version 2 of the License, or     *
 
11
*   (at your option) any later version.                                   *
 
12
*                                                                         *
 
13
***************************************************************************/
 
14
 
 
15
#include <kapplication.h>
 
16
#include <kdatastream.h>
 
17
#include <kdebug.h>
 
18
 
 
19
#include <qcursor.h>
 
20
 
 
21
#include "datatablesearch.h"
 
22
#include "datasearchpopup.h"
 
23
#include "datatable.h"
 
24
#include "datakiosk.h"
 
25
 
 
26
#define widget (kapp->mainWidget())
 
27
 
 
28
DataTableSearch::DataTableSearch( SearchMode mode,
 
29
                                  SearchLevel level ) :
 
30
        m_mode( mode ),
 
31
        m_level( level )
 
32
{}
 
33
 
 
34
DataTableSearch::DataTableSearch( const DataTableList &dataTables,
 
35
                                  const ComponentList &components,
 
36
                                  const QString &name,
 
37
                                  SearchMode mode,
 
38
                                  SearchLevel level ) :
 
39
        m_name( name ),
 
40
        m_dataTables( dataTables ),
 
41
        m_originals( components ),
 
42
        m_mode( mode ),
 
43
        m_level( level )
 
44
{
 
45
    if ( m_level == Simple )
 
46
        search();
 
47
}
 
48
 
 
49
void DataTableSearch::search()
 
50
{
 
51
    switch ( m_level )
 
52
    {
 
53
    case Simple:
 
54
        simpleSearchDataTable();
 
55
        return;
 
56
    case Advanced:
 
57
        advancedSearchDataTable();
 
58
        return;
 
59
    case Custom:
 
60
        customSearchDataTable();
 
61
        return;
 
62
    default:
 
63
        return;
 
64
    }
 
65
}
 
66
 
 
67
void DataTableSearch::dataSearchPopup()
 
68
{
 
69
    DataSearchPopup::Result r =
 
70
        DataSearchPopup( m_originals, m_level, widget, name().latin1() ).exec();
 
71
 
 
72
    if ( !r.components.empty() )
 
73
        m_updates = r.components;
 
74
}
 
75
 
 
76
void DataTableSearch::simpleSearchDataTable()
 
77
{
 
78
    DataTable* dataTable = m_dataTables[0];
 
79
    ComponentList::Iterator componentIt = m_originals.begin();
 
80
    for ( ; componentIt != m_originals.end(); ++componentIt )
 
81
    {
 
82
        QString query = ( *componentIt ).query();
 
83
 
 
84
        if ( query.isEmpty() )
 
85
        {
 
86
            dataTable->setSearchFilter( QString::null );
 
87
            execQuery( dataTable, dataTable->defaultFilter() );
 
88
            return ;
 
89
        }
 
90
 
 
91
        QStringList list;
 
92
        QStringList queries = QStringList::split( ' ', query );
 
93
 
 
94
        uint j = 0;
 
95
        for ( QStringList::Iterator it = queries.begin(); it != queries.end(); ++it )
 
96
        {
 
97
            ++j;
 
98
 
 
99
            list.append( "(" );
 
100
            for ( int i = 0; i < dataTable->dataTableView() ->numCols(); ++i )
 
101
            {
 
102
                if ( dataTable->dataField( i ) ->relation() )
 
103
                {
 
104
                    list.append(
 
105
                        relationSnippet(
 
106
                            *it,
 
107
                            dataTable->dataField( i ) ->fullName(),
 
108
                            dataTable->dataField( i ) ->relation() ->fullKey(),
 
109
                            dataTable->dataField( i ) ->relation() ->table(),
 
110
                            dataTable->dataField( i ) ->relation() ->fullField()
 
111
                        )
 
112
                    );
 
113
 
 
114
                    if ( i != dataTable->dataTableView() ->numCols() - 1 )
 
115
                        list.append( " OR " );
 
116
                    continue;
 
117
                }
 
118
 
 
119
                list.append( operatorSnippet( *it, dataTable->dataField( i ) ->fullName() ) );
 
120
 
 
121
                if ( i != dataTable->dataTableView() ->numCols() - 1 )
 
122
                    list.append( " OR " );
 
123
            }
 
124
            list.append( ")" );
 
125
 
 
126
            if ( j != queries.count() )
 
127
                list.append( " AND " );
 
128
        }
 
129
 
 
130
        if ( dataTable->defaultFilter() != QString::null )         //parent relation
 
131
        {
 
132
            list.prepend( " AND (" );
 
133
            list.append( ")" );
 
134
        }
 
135
 
 
136
        dataTable->setSearchFilter( list.join( "" ) );
 
137
        execQuery( dataTable, dataTable->defaultFilter().append( dataTable->searchFilter() ) );
 
138
    }
 
139
}
 
140
 
 
141
void DataTableSearch::advancedSearchDataTable()
 
142
{
 
143
    dataSearchPopup();
 
144
    QString sql = constructSQLForList( m_dataTables[ 0 ], true );
 
145
    m_dataTables[ 0 ] ->setSearchFilter( sql );
 
146
    execQuery( m_dataTables[ 0 ], sql );
 
147
}
 
148
 
 
149
void DataTableSearch::customSearchDataTable()
 
150
{
 
151
    dataSearchPopup();
 
152
    ComponentList components = m_updates.empty() ? m_originals : m_updates;
 
153
    ComponentList::Iterator componentIt = components.begin();
 
154
    for ( ; componentIt != components.end(); ++componentIt )
 
155
    {
 
156
        DataTable *dataTable = ( *componentIt ).dataTable();
 
157
        if ( !dataTable )
 
158
            continue;
 
159
        QString sql = ( *componentIt ).query();
 
160
        if ( dataTable != m_dataTables[0] )
 
161
            sql.prepend( " AND " );
 
162
        dataTable->setSearchFilter( sql );
 
163
        execQuery( dataTable, dataTable->defaultFilter().append( dataTable->searchFilter() ) );
 
164
    }
 
165
    return;
 
166
}
 
167
 
 
168
void DataTableSearch::execQuery( DataTable* dataTable, const QString &query )
 
169
{
 
170
    if ( !dataTable )
 
171
        return;
 
172
 
 
173
    dataTable->dataTableView() ->setFilter( query );
 
174
    dataTable->dataTableEdit() ->setFilter( dataTable->dataTableView() ->filter() );
 
175
 
 
176
    static_cast<DataKiosk*>( widget ) ->setStatusLeft( query );
 
177
    if ( query != QString::null )
 
178
        kdDebug() << query << endl;
 
179
 
 
180
    QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
 
181
    QTime t;
 
182
    t.start();
 
183
    dataTable->tableRefresh();
 
184
    dataTable->slotSelectFirstRow();
 
185
    static_cast<DataKiosk*>( widget ) ->setStatusRight( QString::number( t.elapsed() ) );
 
186
    QApplication::restoreOverrideCursor();
 
187
}
 
188
 
 
189
QString DataTableSearch::constructSQLForList( DataTable* dataTable, bool isRoot )
 
190
{
 
191
    QStringList list;
 
192
 
 
193
    ComponentList components = m_updates.empty() ? m_originals : m_updates;
 
194
    ComponentList::Iterator componentIt = components.begin();
 
195
    for ( ; componentIt != components.end(); ++componentIt )
 
196
    {
 
197
        DataField *field = ( *componentIt ).dataField();
 
198
        /*        kdDebug() << field->name() << endl;*/
 
199
 
 
200
        MatchMode mode = ( *componentIt ).matchMode();
 
201
        /*        kdDebug() << field->name() << endl;*/
 
202
 
 
203
        QString query = ( *componentIt ).query();
 
204
        /*        kdDebug() << query << endl;*/
 
205
 
 
206
        if ( dataTable ->dataField( field->name() ) == field )
 
207
        {
 
208
            if ( field ->relation() )
 
209
            {
 
210
                if ( !list.empty() && list[ list.count() ] != searchModeSnippet() )
 
211
                    list.append( searchModeSnippet() );
 
212
 
 
213
                list.append(
 
214
                    relationSnippet(
 
215
                        query,
 
216
                        field ->fullName(),
 
217
                        field ->relation() ->fullKey(),
 
218
                        field ->relation() ->table(),
 
219
                        field ->relation() ->fullField(),
 
220
                        mode
 
221
                    )
 
222
                );
 
223
                continue;
 
224
            }
 
225
 
 
226
            if ( !list.empty() && list[ list.count() ] != searchModeSnippet() )
 
227
                list.append( searchModeSnippet() );
 
228
 
 
229
            list.append( operatorSnippet( query, field ->fullName(), mode ) );
 
230
        }
 
231
        else
 
232
        {
 
233
            /*
 
234
            (PROPERTY_ID IN
 
235
             (SELECT PROPERTY_ID FROM IR_PROPERTY_LISTING WHERE
 
236
              (LISTING_FIRM_ID IN
 
237
               (SELECT FIRM_ID FROM IR_FIRM WHERE (FIRM_SHORT_CODE LIKE '%%')))))
 
238
               */
 
239
 
 
240
            //Get a list of dataTables affected by this field
 
241
            QStringList complex = getInheritanceTree( dataTable, field );
 
242
            if ( complex.empty() )
 
243
                continue;
 
244
 
 
245
            if ( !list.empty() && list[ list.count() ] != searchModeSnippet() )
 
246
                list.append( searchModeSnippet() );
 
247
 
 
248
            uint j = 0;
 
249
            for ( QStringList::Iterator it = complex.begin(); it != complex.end(); ++it )
 
250
            {
 
251
                ++j;
 
252
                DataTableList::Iterator it2 = m_dataTables.begin();
 
253
                for ( ; it2 != m_dataTables.end(); ++it2 )
 
254
                {
 
255
                    if ( ( *it ) == ( *it2 ) ->name() )
 
256
                    {
 
257
                        QString subselect = subselectSnippet( ( *it2 ) ->parentKey(),
 
258
                                                              ( *it2 ) ->foreignKey(),
 
259
                                                              ( *it2 ) ->tableName() );
 
260
                        list.append( subselect );
 
261
 
 
262
                        if ( j == complex.size() )
 
263
                        {
 
264
                            if ( field ->relation() )
 
265
                            {
 
266
                                QString relation = relationSnippet(
 
267
                                                       query,
 
268
                                                       field ->fullName(),
 
269
                                                       field ->relation() ->fullKey(),
 
270
                                                       field ->relation() ->table(),
 
271
                                                       field ->relation() ->fullField(),
 
272
                                                       mode
 
273
                                                   );
 
274
                                list.append( relation );
 
275
                            }
 
276
                            else
 
277
                            {
 
278
                                QString operators = operatorSnippet( query, field ->fullName(), mode );
 
279
                                list.append( operators );
 
280
                            }
 
281
 
 
282
                            for ( uint k = 0; k < j; ++k )
 
283
                                list.append( subselectEndSnippet() );
 
284
                        }
 
285
 
 
286
                        if ( isRoot )
 
287
                        {
 
288
                            QString sql = constructSQLForList( ( *it2 ) );
 
289
                            sql.prepend( " AND " );
 
290
                            ( *it2 ) ->setSearchFilter( sql );
 
291
//                             kdDebug() << ( *it2 ) ->name() << endl;
 
292
//                             kdDebug() << ( *it2 )->defaultFilter().append( ( *it2 )->searchFilter() ) << endl;
 
293
                        }
 
294
                    }
 
295
                }
 
296
            }
 
297
        }
 
298
    }
 
299
 
 
300
    return list.join( "" );
 
301
}
 
302
 
 
303
QStringList DataTableSearch::getInheritanceTree( DataTable* dataTable, DataField* dataField )
 
304
{
 
305
    DataTable * childList = 0;
 
306
    DataTableList::Iterator it = m_dataTables.begin();
 
307
    for ( ; it != m_dataTables.end(); ++it )
 
308
        if ( ( *it ) ->dataField( dataField->name() ) == dataField )
 
309
        {
 
310
            childList = ( *it );
 
311
            break;
 
312
        }
 
313
 
 
314
    QStringList complex;
 
315
    complex.prepend( childList->name() );
 
316
    QString root = childList->parentName();
 
317
    while ( dataTable ->name() != root )
 
318
    {
 
319
        if ( root.isEmpty() )
 
320
            return QStringList();
 
321
 
 
322
        complex.prepend( root );
 
323
        DataTableList::Iterator it2 = m_dataTables.begin();
 
324
        for ( ; it2 != m_dataTables.end(); ++it2 )
 
325
        {
 
326
            if ( ( *it2 ) ->name() == root )
 
327
            {
 
328
                root = ( *it2 ) ->parentName();
 
329
                break;
 
330
            }
 
331
        }
 
332
    }
 
333
 
 
334
    return complex;
 
335
}
 
336
 
 
337
QString DataTableSearch::searchModeSnippet()
 
338
{
 
339
    switch ( m_mode )
 
340
    {
 
341
    case MatchAny:
 
342
        return " OR " ;
 
343
    case MatchAll:
 
344
        return " AND ";
 
345
    default:
 
346
        return QString::null;
 
347
    }
 
348
}
 
349
 
 
350
QString DataTableSearch::relationSnippet( const QString &query, const QString &name, const QString &key,
 
351
        const QString &table, const QString &field, MatchMode mode )
 
352
{
 
353
 
 
354
    QStringList list;
 
355
    list.append( subselectSnippet( name, key, table ) );
 
356
    list.append( operatorSnippet( query, field, mode ) );
 
357
    list.append( subselectEndSnippet() );
 
358
    return list.join( "" );
 
359
}
 
360
 
 
361
QString DataTableSearch::subselectSnippet( const QString &parentKey, const QString &foreignKey,
 
362
        const QString &tableName )
 
363
{
 
364
    QStringList list;
 
365
    list.append( "(" );
 
366
    list.append( parentKey );
 
367
    list.append( " IN (SELECT " );
 
368
    list.append( foreignKey );
 
369
    list.append( " FROM " );
 
370
    list.append( tableName );
 
371
    list.append( " WHERE " );
 
372
    return list.join( "" );
 
373
}
 
374
 
 
375
QString DataTableSearch::subselectEndSnippet()
 
376
{
 
377
    return "))";
 
378
}
 
379
 
 
380
QString DataTableSearch::operatorSnippet( const QString &query, const QString &name, MatchMode mode )
 
381
{
 
382
    QStringList list;
 
383
    list.append( "(" );
 
384
    list.append( name );
 
385
 
 
386
    switch ( mode )
 
387
    {
 
388
    case DataTableSearch::Contains:
 
389
        list.append( " LIKE '%" );
 
390
        list.append( query );
 
391
        list.append( "%'" );
 
392
        break;
 
393
    case DataTableSearch::DoesNotContain:
 
394
        list.append( " NOT LIKE '%" );
 
395
        list.append( query );
 
396
        list.append( "%'" );
 
397
        break;
 
398
    case DataTableSearch::Equals:
 
399
        list.append( " = '" );
 
400
        list.append( query );
 
401
        list.append( "'" );
 
402
        break;
 
403
    case DataTableSearch::DoesNotEqual:
 
404
        list.append( " != '" );
 
405
        list.append( query );
 
406
        list.append( "'" );
 
407
        break;
 
408
    case DataTableSearch::IsNull:
 
409
        list.append( " IS NULL" );
 
410
        break;
 
411
    case DataTableSearch::IsNotNull:
 
412
        list.append( " IS NOT NULL" );
 
413
        break;
 
414
    case DataTableSearch::Before:
 
415
        list.append( " < '" );
 
416
        list.append( query );
 
417
        list.append( "'" );
 
418
        break;
 
419
    case DataTableSearch::After:
 
420
        list.append( " > '" );
 
421
        list.append( query );
 
422
        list.append( "'" );
 
423
        break;
 
424
    case DataTableSearch::OnOrBefore:
 
425
        list.append( " <= '" );
 
426
        list.append( query );
 
427
        list.append( "'" );
 
428
        break;
 
429
    case DataTableSearch::OnOrAfter:
 
430
        list.append( " >= '" );
 
431
        list.append( query );
 
432
        list.append( "'" );
 
433
        break;
 
434
    case DataTableSearch::LessThan:
 
435
        list.append( " < '" );
 
436
        list.append( query );
 
437
        list.append( "'" );
 
438
        break;
 
439
    case DataTableSearch::GreaterThan:
 
440
        list.append( " > '" );
 
441
        list.append( query );
 
442
        list.append( "'" );
 
443
        break;
 
444
    case DataTableSearch::LessOrEquals:
 
445
        list.append( " <= '" );
 
446
        list.append( query );
 
447
        list.append( "'" );
 
448
        break;
 
449
    case DataTableSearch::GreaterOrEquals:
 
450
        list.append( " >= '" );
 
451
        list.append( query );
 
452
        list.append( "'" );
 
453
        break;
 
454
    }
 
455
 
 
456
    list.append( ")" );
 
457
    return list.join( "" );
 
458
}
 
459
 
 
460
QString DataTableSearch::parentName() const
 
461
{
 
462
    DataTableList::ConstIterator it = m_dataTables.begin();
 
463
    return ( *it ) ->name();
 
464
}
 
465
 
 
466
bool DataTableSearch::isEmpty() const
 
467
{
 
468
    if ( isNull() )
 
469
        return true;
 
470
 
 
471
    ComponentList::ConstIterator it = m_originals.begin();
 
472
    for ( ; it != m_originals.end(); ++it )
 
473
    {
 
474
        if ( !( *it ).query().isEmpty() )
 
475
            return false;
 
476
    }
 
477
 
 
478
    return true;
 
479
}
 
480
 
 
481
DataTableSearch::Component::Component() :
 
482
        m_mode( Contains )
 
483
{}
 
484
 
 
485
DataTableSearch::Component::Component( const QString &query,
 
486
                                       DataTable *dataTable,
 
487
                                       DataField *dataField,
 
488
                                       bool prompt,
 
489
                                       MatchMode mode ) :
 
490
        m_query( query ),
 
491
        m_dataTable( dataTable ),
 
492
        m_dataField( dataField ),
 
493
        m_prompt( prompt ),
 
494
        m_mode( mode )
 
495
{}
 
496
 
 
497
bool DataTableSearch::Component::operator==( const Component &v ) const
 
498
{
 
499
    return m_query == v.m_query &&
 
500
           m_mode == v.m_mode;
 
501
}
 
502
 
 
503
#ifdef widget
 
504
#undef widget
 
505
#endif
 
506