~ubuntu-branches/debian/squeeze/pgadmin3/squeeze

« back to all changes in this revision

Viewing changes to src/frm/frmEditGrid.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Lionel Porcheron
  • Date: 2008-02-07 00:56:22 UTC
  • mto: (2.1.6 hardy) (6.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080207005622-c2ail8p4d0sk3dnw
Tags: upstream-1.8.2
ImportĀ upstreamĀ versionĀ 1.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//////////////////////////////////////////////////////////////////////////
2
 
//
3
 
// pgAdmin III - PostgreSQL Tools
4
 
// RCS-ID:      $Id: frmEditGrid.cpp 5108 2006-05-02 07:19:22Z dpage $
5
 
// Copyright (C) 2002 - 2006, The pgAdmin Development Team
6
 
// This software is released under the Artistic Licence
7
 
//
8
 
// frmEditGrid.cpp - Edit Grid Box
9
 
//
10
 
//////////////////////////////////////////////////////////////////////////
11
 
 
12
 
// wxWindows headers
13
 
#include <wx/wx.h>
14
 
#include <wx/grid.h>
15
 
 
16
 
#ifdef __WX_FULLSOURCE
17
 
#include "wx/generic/gridsel.h"
18
 
#else
19
 
#include "wxgridsel.h"
20
 
#endif
21
 
 
22
 
// App headers
23
 
#include "pgAdmin3.h"
24
 
#include "pgDefs.h"
25
 
#include "frmMain.h"
26
 
#include "menu.h"
27
 
 
28
 
#include <wx/generic/gridctrl.h>
29
 
#include <wx/clipbrd.h>
30
 
 
31
 
#include "frmEditGrid.h"
32
 
#include "dlgEditGridOptions.h"
33
 
#include "frmHint.h"
34
 
#include "pgTable.h"
35
 
#include "pgView.h"
36
 
 
37
 
 
38
 
// Icons
39
 
#include "images/viewdata.xpm"
40
 
#include "images/storedata.xpm"
41
 
#include "images/readdata.xpm"
42
 
#include "images/delete.xpm"
43
 
#include "images/edit_undo.xpm"
44
 
#include "images/sortfilter.xpm"
45
 
#include "images/help.xpm"
46
 
#include "images/clip_copy.xpm"
47
 
 
48
 
 
49
 
 
50
 
BEGIN_EVENT_TABLE(frmEditGrid, pgFrame)
51
 
    EVT_MENU(MNU_REFRESH,   frmEditGrid::OnRefresh)
52
 
    EVT_MENU(MNU_DELETE,    frmEditGrid::OnDelete)
53
 
    EVT_MENU(MNU_SAVE,      frmEditGrid::OnSave)
54
 
    EVT_MENU(MNU_UNDO,      frmEditGrid::OnUndo)
55
 
    EVT_MENU(MNU_OPTIONS,   frmEditGrid::OnOptions)
56
 
    EVT_MENU(MNU_HELP,      frmEditGrid::OnHelp)
57
 
    EVT_MENU(MNU_COPY,      frmEditGrid::OnCopy)
58
 
    EVT_CLOSE(              frmEditGrid::OnClose)
59
 
    EVT_KEY_DOWN(           frmEditGrid::OnKey)
60
 
    EVT_GRID_RANGE_SELECT(frmEditGrid::OnGridSelectCells)
61
 
    EVT_GRID_SELECT_CELL(frmEditGrid::OnCellChange)
62
 
    EVT_GRID_EDITOR_SHOWN(frmEditGrid::OnEditorShown)
63
 
    EVT_GRID_LABEL_LEFT_DCLICK(frmEditGrid::OnLabelDoubleClick)
64
 
    EVT_GRID_LABEL_RIGHT_CLICK(frmEditGrid::OnLabelRightClick)
65
 
END_EVENT_TABLE()
66
 
 
67
 
 
68
 
frmEditGrid::frmEditGrid(frmMain *form, const wxString& _title, pgConn *_conn, pgSchemaObject *obj)
69
 
: pgFrame(NULL, _title)
70
 
{
71
 
    wxLogInfo(wxT("Creating EditGrid"));
72
 
    SetIcon(wxIcon(viewdata_xpm));
73
 
    wxWindowBase::SetFont(settings->GetSystemFont());
74
 
    dlgName = wxT("frmEditGrid");
75
 
    RestorePosition(-1, -1, 600, 500, 200, 150);
76
 
    connection=_conn;
77
 
    mainForm=form;
78
 
    thread=0;
79
 
    relkind=0;
80
 
    relid=(Oid)obj->GetOid();
81
 
 
82
 
 
83
 
    CreateStatusBar();
84
 
    SetStatusBarPane(-1);
85
 
 
86
 
    sqlGrid = new ctlSQLGrid(this, CTL_EDITGRID, wxDefaultPosition, wxDefaultSize);
87
 
    sqlGrid->SetSizer(new wxBoxSizer(wxVERTICAL));
88
 
 
89
 
    wxFont fntLabel(settings->GetSystemFont());
90
 
    fntLabel.SetWeight(wxBOLD);
91
 
    sqlGrid->SetLabelFont(fntLabel);
92
 
 
93
 
   
94
 
    toolBar = CreateToolBar();
95
 
 
96
 
    // Set up toolbar
97
 
    toolBar->SetToolBitmapSize(wxSize(16, 16));
98
 
 
99
 
    toolBar->AddTool(MNU_SAVE, _("Save"), wxBitmap(storedata_xpm), _("Saved the changed row."), wxITEM_NORMAL);
100
 
    toolBar->AddSeparator();
101
 
    toolBar->AddTool(MNU_REFRESH, _("Refresh"), wxBitmap(readdata_xpm), _("Refresh"), wxITEM_NORMAL);
102
 
    toolBar->AddTool(MNU_UNDO, _("Undo"), wxBitmap(edit_undo_xpm), _("Undo change of data."), wxITEM_NORMAL);
103
 
    toolBar->AddSeparator();
104
 
    toolBar->AddTool(MNU_COPY, _("Copy"), wxBitmap(clip_copy_xpm), _("Copy selected lines to clipboard"), wxITEM_NORMAL);
105
 
    toolBar->AddSeparator();
106
 
    toolBar->AddTool(MNU_DELETE, _("Delete"), wxBitmap(delete_xpm), _("Delete selected lines."), wxITEM_NORMAL);
107
 
    toolBar->AddSeparator();
108
 
    toolBar->AddTool(MNU_OPTIONS, _("Options"), wxBitmap(sortfilter_xpm), _("Sort/filter options."), wxITEM_NORMAL);
109
 
    toolBar->AddSeparator();
110
 
    toolBar->AddTool(MNU_HELP, _("Help"), wxBitmap(help_xpm), _("Display help on SQL commands."));
111
 
 
112
 
    toolBar->Realize();
113
 
    toolBar->EnableTool(MNU_SAVE, false);
114
 
    toolBar->EnableTool(MNU_UNDO, false);
115
 
    toolBar->EnableTool(MNU_COPY, false);
116
 
    toolBar->EnableTool(MNU_DELETE, false);
117
 
 
118
 
 
119
 
    wxAcceleratorEntry entries[6];
120
 
 
121
 
    entries[0].Set(wxACCEL_CTRL,                (int)'S',      MNU_SAVE);
122
 
    entries[1].Set(wxACCEL_NORMAL,              WXK_F5,        MNU_REFRESH);
123
 
    entries[2].Set(wxACCEL_CTRL,                (int)'Z',      MNU_UNDO);
124
 
    entries[3].Set(wxACCEL_NORMAL,              WXK_F1,        MNU_HELP);
125
 
    entries[4].Set(wxACCEL_CTRL,                (int)'C',      MNU_COPY);
126
 
    entries[5].Set(wxACCEL_NORMAL,              WXK_DELETE,    MNU_DELETE);
127
 
 
128
 
    wxAcceleratorTable accel(6, entries);
129
 
    SetAcceleratorTable(accel);
130
 
 
131
 
 
132
 
    if (obj->GetMetaType() == PGM_TABLE)
133
 
    {
134
 
        pgTable *table = (pgTable*)obj;
135
 
 
136
 
        relkind = 'r';
137
 
        hasOids = table->GetHasOids();
138
 
        tableName = table->GetQuotedFullIdentifier();
139
 
        primaryKeyColNumbers = table->GetPrimaryKeyColNumbers();
140
 
        orderBy = table->GetQuotedPrimaryKey();
141
 
        if (orderBy.IsEmpty() && hasOids)
142
 
            orderBy=wxT("oid");
143
 
        if (!orderBy.IsEmpty())
144
 
            orderBy += wxT(" ASC");
145
 
    }
146
 
    else if (obj->IsCreatedBy(viewFactory))
147
 
    {
148
 
        pgView *view=(pgView*)obj;
149
 
 
150
 
        relkind = 'v';
151
 
        hasOids=false;
152
 
        tableName=view->GetQuotedFullIdentifier();
153
 
    }
154
 
}
155
 
 
156
 
void frmEditGrid::SetSortCols(const wxString &cols) 
157
 
158
 
        if (orderBy != cols) { 
159
 
                orderBy = cols; 
160
 
                optionsChanged = true;
161
 
        } 
162
 
}
163
 
 
164
 
void frmEditGrid::SetFilter(const wxString &filter) 
165
 
166
 
        if (rowFilter != filter) { 
167
 
                rowFilter = filter; 
168
 
                optionsChanged = true;
169
 
        } 
170
 
}
171
 
 
172
 
void frmEditGrid::OnLabelRightClick(wxGridEvent& event)
173
 
{
174
 
    wxArrayInt rows=sqlGrid->GetSelectedRows();
175
 
    if (rows.GetCount())
176
 
    {
177
 
    }
178
 
}
179
 
 
180
 
#define EXTRAEXTENT_HEIGHT 6
181
 
#define EXTRAEXTENT_WIDTH  6
182
 
 
183
 
void frmEditGrid::OnLabelDoubleClick(wxGridEvent& event)
184
 
{
185
 
#if wxCHECK_VERSION(2, 5, 0)
186
 
    // at the moment, not implemented for 2.4
187
 
    int maxHeight, maxWidth;
188
 
    sqlGrid->GetClientSize(&maxWidth, &maxHeight);
189
 
    int row=event.GetRow();
190
 
    int col=event.GetCol();
191
 
 
192
 
    int extent, extentWant=0;
193
 
 
194
 
    if (row >= 0)
195
 
    {
196
 
        for (col=0 ; col < sqlGrid->GetNumberCols() ; col++)
197
 
        {
198
 
            extent = sqlGrid->GetBestSize(row, col).GetHeight();
199
 
            if (extent > extentWant)
200
 
                extentWant=extent;
201
 
        }
202
 
 
203
 
        extentWant += EXTRAEXTENT_HEIGHT;
204
 
        extentWant = wxMax(extentWant, sqlGrid->GetRowMinimalAcceptableHeight());
205
 
        extentWant = wxMin(extentWant, maxHeight*3/4);
206
 
        int currentHeight=sqlGrid->GetRowHeight(row);
207
 
            
208
 
        if (currentHeight >= maxHeight*3/4 || currentHeight == extentWant)
209
 
            extentWant = sqlGrid->GetRowMinimalAcceptableHeight();
210
 
        else if (currentHeight < maxHeight/4)
211
 
            extentWant = wxMin(maxHeight/4, extentWant);
212
 
        else if (currentHeight < maxHeight/2)
213
 
            extentWant = wxMin(maxHeight/2, extentWant);
214
 
        else if (currentHeight < maxHeight*3/4)
215
 
            extentWant = wxMin(maxHeight*3/4, extentWant);
216
 
 
217
 
        if (extentWant != currentHeight)
218
 
        {
219
 
            sqlGrid->BeginBatch();
220
 
            if(sqlGrid->IsCellEditControlShown())
221
 
            {
222
 
                sqlGrid->HideCellEditControl();
223
 
                sqlGrid->SaveEditControlValue();
224
 
            }
225
 
 
226
 
            sqlGrid->SetRowHeight(row, extentWant);
227
 
            sqlGrid->EndBatch();
228
 
        }
229
 
    }
230
 
    else if (col >= 0)
231
 
    {
232
 
        for (row=0 ; row < sqlGrid->GetNumberRows() ; row++)
233
 
        {
234
 
            if (sqlGrid->GetTable()->CheckInCache(row))
235
 
            {
236
 
                extent = sqlGrid->GetBestSize(row, col).GetWidth();
237
 
                if (extent > extentWant)
238
 
                    extentWant=extent;
239
 
            }
240
 
        }
241
 
 
242
 
        extentWant += EXTRAEXTENT_WIDTH;
243
 
        extentWant = wxMax(extentWant, sqlGrid->GetColMinimalAcceptableWidth());
244
 
        extentWant = wxMin(extentWant, maxWidth*3/4);
245
 
        int currentWidth=sqlGrid->GetColumnWidth(col);
246
 
            
247
 
        if (currentWidth >= maxWidth*3/4 || currentWidth == extentWant)
248
 
            extentWant = sqlGrid->GetColMinimalAcceptableWidth();
249
 
        else if (currentWidth < maxWidth/4)
250
 
            extentWant = wxMin(maxWidth/4, extentWant);
251
 
        else if (currentWidth < maxWidth/2)
252
 
            extentWant = wxMin(maxWidth/2, extentWant);
253
 
        else if (currentWidth < maxWidth*3/4)
254
 
            extentWant = wxMin(maxWidth*3/4, extentWant);
255
 
 
256
 
        if (extentWant != currentWidth)
257
 
        {
258
 
            sqlGrid->BeginBatch();
259
 
            if(sqlGrid->IsCellEditControlShown())
260
 
            {
261
 
                sqlGrid->HideCellEditControl();
262
 
                sqlGrid->SaveEditControlValue();
263
 
            }
264
 
            sqlGrid->SetColumnWidth(col, extentWant);
265
 
            sqlGrid->EndBatch();
266
 
        }
267
 
    }
268
 
#endif
269
 
}
270
 
 
271
 
 
272
 
 
273
 
void frmEditGrid::OnCellChange(wxGridEvent& event)
274
 
{
275
 
    sqlTable *table=sqlGrid->GetTable();
276
 
    if (table)
277
 
    {
278
 
        if (table->LastRow() >= 0)
279
 
        {
280
 
            if (table->LastRow() != event.GetRow())
281
 
            {
282
 
                wxCommandEvent ev;
283
 
                OnSave(ev);
284
 
            }
285
 
        }
286
 
        else
287
 
        {
288
 
            toolBar->EnableTool(MNU_SAVE, false);
289
 
            toolBar->EnableTool(MNU_UNDO, false);
290
 
        }
291
 
    }
292
 
 
293
 
    event.Skip();
294
 
}
295
 
 
296
 
 
297
 
void frmEditGrid::OnCopy(wxCommandEvent &ev)
298
 
{
299
 
    wxArrayInt rows=sqlGrid->GetSelectedRows();
300
 
    size_t i;
301
 
    if (rows.GetCount())
302
 
    {
303
 
        wxString str;
304
 
        for (i=0 ; i < rows.GetCount() ; i++)
305
 
        {
306
 
            str.Append(sqlGrid->GetTable()->GetExportLine(rows.Item(i)));
307
 
    
308
 
            if (rows.GetCount() > 1)
309
 
                str.Append(END_OF_LINE);
310
 
        }
311
 
        if (wxTheClipboard->Open())
312
 
        {
313
 
            wxTheClipboard->SetData(new wxTextDataObject(str));
314
 
            wxTheClipboard->Close();
315
 
        }
316
 
    }
317
 
    SetStatusText(wxString::Format(_("%d rows copied to clipboard."), rows.GetCount()));
318
 
}
319
 
 
320
 
 
321
 
void frmEditGrid::OnHelp(wxCommandEvent &ev)
322
 
{
323
 
    DisplayHelp(this, wxT("editgrid"), viewdata_xpm);
324
 
}
325
 
 
326
 
 
327
 
void frmEditGrid::OnKey(wxKeyEvent &event)
328
 
{
329
 
    int curcol=sqlGrid->GetGridCursorCol();
330
 
    int currow=sqlGrid->GetGridCursorRow();
331
 
    int keycode=event.GetKeyCode();
332
 
    wxCommandEvent ev;
333
 
 
334
 
    switch (keycode)
335
 
    {
336
 
#if 0
337
 
        // the control will catch these :-(
338
 
        case WXK_UP:
339
 
            OnSave(ev);
340
 
            if (currow)
341
 
                sqlGrid->SetGridCursor(currow-1, curcol);
342
 
            return;
343
 
        case WXK_DOWN:
344
 
            OnSave(ev);
345
 
            sqlGrid->SetGridCursor(currow+1, curcol);
346
 
            return;
347
 
#endif
348
 
        case WXK_DELETE:
349
 
        {
350
 
            if (!sqlGrid->IsCurrentCellReadOnly())
351
 
            {
352
 
                sqlGrid->EnableCellEditControl();
353
 
                sqlGrid->ShowCellEditControl();
354
 
 
355
 
                wxGridCellEditor *edit=sqlGrid->GetCellEditor(currow, curcol);
356
 
                if (edit)
357
 
                {
358
 
                    wxControl *ctl=edit->GetControl();
359
 
                    if (ctl)
360
 
                    {
361
 
                        wxTextCtrl *txt=wxDynamicCast(ctl, wxTextCtrl);
362
 
                        if (txt)
363
 
                            txt->SetValue(wxEmptyString);
364
 
                    }
365
 
                    edit->DecRef();
366
 
                }
367
 
            }
368
 
            return;
369
 
        }
370
 
        case WXK_RETURN:
371
 
            // check for shift etc.
372
 
            if (event.ControlDown() || event.ShiftDown())
373
 
            {
374
 
                // Inject a RETURN into the control
375
 
                wxGridCellEditor *edit=sqlGrid->GetCellEditor(currow, curcol);
376
 
                if (edit)
377
 
                {
378
 
                    wxControl *ctl=edit->GetControl();
379
 
                    if (ctl)
380
 
                    {
381
 
                        wxTextCtrl *txt=wxDynamicCast(ctl, wxTextCtrl);
382
 
//                        if (txt && txt->IsMultiLine())
383
 
                        if (txt) // && txt->IsMultiLine())
384
 
                        {
385
 
                            long from, to;
386
 
                            txt->GetSelection(&from, &to);
387
 
                            txt->Replace(from, to, END_OF_LINE);
388
 
                        }
389
 
                    }
390
 
                    edit->DecRef();
391
 
                }
392
 
                return;
393
 
            }
394
 
            else
395
 
            {
396
 
                if (curcol == sqlGrid->GetNumberCols()-1)
397
 
                {
398
 
                    curcol=0;
399
 
                    currow++;
400
 
                    // locate first editable column
401
 
                    while (sqlGrid->IsReadOnly(currow, curcol) && curcol < sqlGrid->GetNumberCols())
402
 
                        curcol++;
403
 
                    // next line is completely read-only
404
 
                    if (curcol == sqlGrid->GetNumberCols())
405
 
                        return;
406
 
 
407
 
                }
408
 
                else
409
 
                    curcol++;
410
 
 
411
 
                OnSave(ev);
412
 
                sqlGrid->SetGridCursor(currow, curcol);
413
 
    
414
 
                return;
415
 
            }
416
 
        default:
417
 
            if (sqlGrid->IsEditable() && keycode >= WXK_SPACE && keycode < WXK_START)
418
 
            {
419
 
                if (sqlGrid->IsCurrentCellReadOnly())
420
 
                    return;
421
 
 
422
 
                toolBar->EnableTool(MNU_SAVE, true);
423
 
                toolBar->EnableTool(MNU_UNDO, true);
424
 
            }
425
 
            break;
426
 
    }
427
 
    event.Skip();
428
 
}
429
 
 
430
 
 
431
 
void frmEditGrid::OnClose(wxCloseEvent& event)
432
 
{
433
 
    if (toolBar->GetToolEnabled(MNU_SAVE))
434
 
    {
435
 
        int flag=wxYES_NO | wxICON_QUESTION;
436
 
        if (event.CanVeto())
437
 
            flag |= wxCANCEL;
438
 
 
439
 
        wxMessageDialog msg(this, _("There is unsaved data in a row.\nDo you want to store to the database?"), _("Unsaved data"),
440
 
            flag);
441
 
        switch (msg.ShowModal())
442
 
        {
443
 
            case wxID_YES:
444
 
            {
445
 
                wxCommandEvent ev;
446
 
                OnSave(ev);
447
 
                break;
448
 
            }
449
 
            case wxID_CANCEL:
450
 
                event.Veto();
451
 
                return;
452
 
        }
453
 
    }
454
 
    Abort();
455
 
    Destroy();
456
 
}
457
 
 
458
 
 
459
 
void frmEditGrid::OnUndo(wxCommandEvent& event)
460
 
{
461
 
    sqlGrid->DisableCellEditControl();
462
 
    sqlGrid->GetTable()->UndoLine(sqlGrid->GetGridCursorRow());
463
 
    sqlGrid->ForceRefresh();
464
 
}
465
 
 
466
 
 
467
 
void frmEditGrid::OnRefresh(wxCommandEvent& event)
468
 
{
469
 
    sqlGrid->DisableCellEditControl();
470
 
    Go();
471
 
}
472
 
 
473
 
 
474
 
void frmEditGrid::OnSave(wxCommandEvent& event)
475
 
{
476
 
    sqlGrid->HideCellEditControl();
477
 
    sqlGrid->SaveEditControlValue();
478
 
    sqlGrid->DisableCellEditControl();
479
 
    sqlGrid->GetTable()->StoreLine();
480
 
 
481
 
    toolBar->EnableTool(MNU_SAVE, false);
482
 
    toolBar->EnableTool(MNU_UNDO, false);
483
 
}
484
 
 
485
 
void frmEditGrid::OnOptions(wxCommandEvent& event)
486
 
{
487
 
        optionsChanged = false;
488
 
    dlgEditGridOptions *winOptions = new dlgEditGridOptions(this, connection, tableName, sqlGrid);
489
 
    winOptions->ShowModal();
490
 
 
491
 
        if (optionsChanged) Go();
492
 
}
493
 
 
494
 
template < class T >
495
 
int ArrayCmp(T *a, T *b)
496
 
{
497
 
        if (*a == *b)
498
 
                return 0;
499
 
 
500
 
        if (*a > *b)
501
 
                return 1;
502
 
        else
503
 
                return -1;
504
 
}
505
 
 
506
 
void frmEditGrid::OnDelete(wxCommandEvent& event)
507
 
{
508
 
        wxMessageDialog msg(this, _("Are you sure you wish to delete the selected row(s)?"), _("Delete rows?"), wxYES_NO | wxICON_QUESTION);
509
 
    if (msg.ShowModal() != wxID_YES)
510
 
        return;
511
 
 
512
 
    sqlGrid->BeginBatch();
513
 
    wxArrayInt delrows=sqlGrid->GetSelectedRows();
514
 
    int i=delrows.GetCount();
515
 
 
516
 
        // Sort the grid so we always delete last->first, otherwise we 
517
 
        // could end up deleting anything because the array returned by 
518
 
        // GetSelectedRows is in the order that rows were selected by
519
 
        // the user.
520
 
        delrows.Sort(ArrayCmp);
521
 
 
522
 
    // don't care a lot about optimizing here; doing it line by line
523
 
    // just as sqlTable::DeleteRows does
524
 
        while (i--)
525
 
                sqlGrid->DeleteRows(delrows.Item(i), 1);
526
 
 
527
 
 
528
 
    sqlGrid->EndBatch();
529
 
 
530
 
    SetStatusText(wxString::Format(_("%d rows."), sqlGrid->GetTable()->GetNumberStoredRows()), 0);
531
 
}
532
 
 
533
 
 
534
 
void frmEditGrid::OnEditorShown(wxGridEvent& event)
535
 
{
536
 
    toolBar->EnableTool(MNU_SAVE, true);
537
 
    toolBar->EnableTool(MNU_UNDO, true);
538
 
 
539
 
    event.Skip();
540
 
}
541
 
 
542
 
 
543
 
void frmEditGrid::OnGridSelectCells(wxGridRangeSelectEvent& event)
544
 
{
545
 
    if (sqlGrid->GetEditable())
546
 
    {
547
 
        wxArrayInt rows=sqlGrid->GetSelectedRows();
548
 
 
549
 
        bool enable=rows.GetCount() > 0;
550
 
        if (enable)
551
 
        {
552
 
            wxCommandEvent nullEvent;
553
 
            OnSave(event);
554
 
 
555
 
            // check if a readonly line is selected
556
 
            int row, col;
557
 
            size_t i;
558
 
 
559
 
            for (i=0 ; i < rows.GetCount() ; i++)
560
 
            {
561
 
                row = rows.Item(i);
562
 
                bool lineEnabled=false;
563
 
 
564
 
                if (row == sqlGrid->GetNumberRows()-1)
565
 
                {
566
 
                    // the (*) line may not be deleted/copied
567
 
                    enable=false;
568
 
                    break;
569
 
                }
570
 
                for (col = 0 ; col < sqlGrid->GetNumberCols() ; col++)
571
 
                {
572
 
                    if (!sqlGrid->IsReadOnly(row, col))
573
 
                    {
574
 
                        lineEnabled=true;
575
 
                        break;
576
 
                    }
577
 
                }
578
 
 
579
 
                if (!lineEnabled)
580
 
                {
581
 
                    enable=false;
582
 
                    break;
583
 
                }
584
 
            }
585
 
        }
586
 
        toolBar->EnableTool(MNU_DELETE, enable);
587
 
        toolBar->EnableTool(MNU_COPY,  enable);
588
 
    }
589
 
    event.Skip();
590
 
}
591
 
 
592
 
 
593
 
void frmEditGrid::ShowForm(bool filter)
594
 
{
595
 
        bool abort = false;
596
 
 
597
 
    if (relkind == 'r' || relkind == 'v')
598
 
        {
599
 
                if (filter) 
600
 
                {
601
 
                        dlgEditGridOptions *winOptions = new dlgEditGridOptions(this, connection, tableName, sqlGrid);
602
 
                        abort = !(winOptions->ShowModal());
603
 
                }
604
 
                if (abort) {
605
 
                        Close();
606
 
                        Destroy();
607
 
                } else {
608
 
            Show(true);
609
 
                    Go();
610
 
                }
611
 
        }
612
 
    else
613
 
    {
614
 
        wxLogError(__("No Table or view."));
615
 
        Close();
616
 
        Destroy();
617
 
    }
618
 
}
619
 
 
620
 
void frmEditGrid::Go()
621
 
{
622
 
    SetStatusText(_("Refreshing data, please wait."), 0);
623
 
 
624
 
    wxString qry=wxT("SELECT ");
625
 
    if (hasOids)
626
 
        qry += wxT("oid, ");
627
 
    qry += wxT("* FROM ") + tableName;
628
 
    if (!rowFilter.IsEmpty())
629
 
    {
630
 
        qry += wxT(" WHERE ") + rowFilter;
631
 
    }
632
 
    if (!orderBy.IsEmpty())
633
 
    {
634
 
        qry += wxT(" ORDER BY ") + orderBy;
635
 
    }
636
 
 
637
 
    thread=new pgQueryThread(connection, qry);
638
 
    if (thread->Create() != wxTHREAD_NO_ERROR)
639
 
    {
640
 
        Abort();
641
 
        return;
642
 
    }
643
 
 
644
 
    thread->Run();
645
 
 
646
 
    while (thread && thread->IsRunning())
647
 
    {
648
 
        wxYield();
649
 
        wxMilliSleep(10);
650
 
    }
651
 
    if (!thread)
652
 
        return;
653
 
 
654
 
    if (!thread->DataValid())
655
 
    {
656
 
        Abort();
657
 
        return;
658
 
    }
659
 
    SetStatusText(wxString::Format(_("%d rows."), thread->DataSet()->NumRows()), 0);
660
 
 
661
 
    sqlGrid->BeginBatch();
662
 
 
663
 
    // to force the grid to create scrollbars, we make sure the size  so small that scrollbars are needed 
664
 
    // later, we will resize the grid's parent to force the correct size (now including scrollbars, even if
665
 
    // they are suppressed initially. Win32 won't need this.
666
 
    sqlGrid->SetSize(10,10);
667
 
 
668
 
    sqlGrid->SetTable(new sqlTable(connection, thread, tableName, relid, hasOids, primaryKeyColNumbers, relkind), true);
669
 
    sqlGrid->EndBatch();
670
 
 
671
 
    wxSizeEvent event;
672
 
    event.m_size = GetSize();
673
 
    OnSize(event);
674
 
 
675
 
    if (!hasOids && primaryKeyColNumbers.IsEmpty() && relkind == 'r')
676
 
        frmHint::ShowHint(this, HINT_READONLY_NOPK, tableName);
677
 
}
678
 
 
679
 
 
680
 
frmEditGrid::~frmEditGrid()
681
 
{
682
 
    wxLogInfo(wxT("Destroying SQL EditGrid"));
683
 
    mainForm->RemoveFrame(this);
684
 
 
685
 
    if (connection)
686
 
        delete connection;
687
 
}
688
 
 
689
 
 
690
 
void frmEditGrid::Abort()
691
 
{
692
 
    if (sqlGrid->GetTable())
693
 
    {
694
 
        sqlGrid->HideCellEditControl();
695
 
        // thread is owned by table und will be destroyed there
696
 
        sqlGrid->SetTable(0);
697
 
    }
698
 
    else if (thread)
699
 
    {
700
 
        SetStatusText(_("aborting."), 0);
701
 
        if (thread->IsRunning())
702
 
            thread->Delete();
703
 
        delete thread;
704
 
        thread=0;
705
 
    }
706
 
}
707
 
 
708
 
 
709
 
ctlSQLGrid::ctlSQLGrid(wxFrame *parent, wxWindowID id, const wxPoint& pos, const wxSize& size)
710
 
: wxGrid(parent, id, pos, size, wxWANTS_CHARS|wxVSCROLL|wxHSCROLL)
711
 
{
712
 
}
713
 
 
714
 
 
715
 
 
716
 
 
717
 
void ctlSQLGrid::ResizeEditor(int row, int col)
718
 
{
719
 
 
720
 
    if (GetTable()->needsResizing(col))
721
 
    {
722
 
        wxGridCellAttr* attr = GetCellAttr(row, col);
723
 
        wxGridCellRenderer* renderer = attr->GetRenderer(this, row, col);
724
 
        if ( renderer )
725
 
        {
726
 
            wxClientDC dc(GetGridWindow());
727
 
            wxSize size = renderer->GetBestSize(*this, *attr, dc, row, col);
728
 
            renderer->DecRef();
729
 
 
730
 
            int w=wxMax(size.GetWidth(), 15)+20;
731
 
            int h=wxMax(size.GetHeight(), 15)+20;
732
 
 
733
 
 
734
 
            wxGridCellEditor *editor=attr->GetEditor(this, row, col);
735
 
            if (editor)
736
 
            {
737
 
                wxRect cellRect = CellToRect(m_currentCellCoords);
738
 
                wxRect rect = cellRect;
739
 
                rect.SetWidth(w);
740
 
                rect.SetHeight(h);
741
 
 
742
 
                // we might have scrolled
743
 
                CalcUnscrolledPosition(0, 0, &w, &h);
744
 
                rect.SetLeft(rect.GetLeft() - w);
745
 
                rect.SetTop(rect.GetTop() - h);
746
 
 
747
 
                // Clip rect to client size
748
 
                GetClientSize(&w, &h);
749
 
                rect.SetRight(wxMin(rect.GetRight(), w));
750
 
                rect.SetBottom(wxMin(rect.GetBottom(), h));
751
 
 
752
 
                // but not smaller than original cell
753
 
                rect.SetWidth(wxMax(cellRect.GetWidth(), rect.GetWidth()));
754
 
                rect.SetHeight(wxMax(cellRect.GetHeight(), rect.GetHeight()));
755
 
 
756
 
                editor->SetSize(rect);
757
 
                editor->DecRef();
758
 
            }
759
 
        }
760
 
 
761
 
        attr->DecRef();
762
 
    }
763
 
}
764
 
 
765
 
 
766
 
wxSize ctlSQLGrid::GetBestSize(int row, int col)
767
 
{
768
 
    wxSize size;
769
 
 
770
 
    wxGridCellAttr* attr = GetCellAttr(row, col);
771
 
    wxGridCellRenderer* renderer = attr->GetRenderer(this, row, col);
772
 
    if ( renderer )
773
 
    {
774
 
        wxClientDC dc(GetGridWindow());
775
 
        size = renderer->GetBestSize(*this, *attr, dc, row, col);
776
 
        renderer->DecRef();
777
 
    }
778
 
 
779
 
    attr->DecRef();
780
 
 
781
 
    return size;
782
 
}
783
 
 
784
 
 
785
 
 
786
 
#if wxCHECK_VERSION(2,5,0)
787
 
    // problems are fixed
788
 
#else
789
 
 
790
 
bool ctlSQLGrid::SetTable(wxGridTableBase *table, bool takeOwnership)
791
 
{
792
 
    bool done=false;
793
 
    if (m_created)
794
 
    {
795
 
        m_created = false;
796
 
        if (m_ownTable)
797
 
            delete m_table;
798
 
 
799
 
        delete m_selection;
800
 
 
801
 
        // stop all processing
802
 
        m_table=0;
803
 
        m_selection=0;
804
 
        m_numRows=0;
805
 
        m_numCols=0;
806
 
    }
807
 
    if (table)
808
 
    {
809
 
 
810
 
 
811
 
        int col;
812
 
        wxCoord w, h, wmax;
813
 
 
814
 
        done= wxGrid::SetTable(table, takeOwnership);
815
 
 
816
 
        wxClientDC dc(this);
817
 
        dc.SetFont(GetLabelFont());
818
 
 
819
 
        for (col=0 ; col < m_numCols ; col++)
820
 
        {
821
 
            wxString str=GetColLabelValue(col);
822
 
            dc.GetTextExtent(str.BeforeFirst('\n'), &wmax, &h);
823
 
            int crPos=str.Find('\n');
824
 
            if (crPos)
825
 
            {
826
 
                dc.GetTextExtent(str.Mid(crPos+1), &w, &h);
827
 
                if (w>wmax)
828
 
                    wmax=w;
829
 
            }
830
 
            wmax += 4;      // looks better
831
 
            if (wmax < 40)
832
 
                wmax = 40;
833
 
 
834
 
            SetColSize(col, wmax);
835
 
        }
836
 
    }
837
 
    return done;
838
 
}
839
 
#endif
840
 
 
841
 
 
842
 
 
843
 
wxArrayInt ctlSQLGrid::GetSelectedRows() const
844
 
{
845
 
    wxArrayInt rows, rows2;
846
 
 
847
 
    wxGridCellCoordsArray tl=GetSelectionBlockTopLeft(), br=GetSelectionBlockBottomRight();
848
 
 
849
 
    int maxCol=((ctlSQLGrid*)this)->GetNumberCols() -1;
850
 
    size_t i;
851
 
    for (i=0 ; i < tl.GetCount() ; i++)
852
 
    {
853
 
        wxGridCellCoords c1=tl.Item(i), c2=br.Item(i);
854
 
        if (c1.GetCol() != 0 || c2.GetCol() != maxCol)
855
 
            return rows2;
856
 
 
857
 
        int j;
858
 
        for (j=c1.GetRow() ; j <= c2.GetRow() ; j++)
859
 
            rows.Add(j);
860
 
    }
861
 
 
862
 
    rows2=wxGrid::GetSelectedRows();
863
 
 
864
 
    rows.Sort(ArrayCmp);
865
 
    rows2.Sort(ArrayCmp);
866
 
 
867
 
    size_t i2=0, cellRowMax=rows.GetCount();
868
 
 
869
 
    for (i=0 ; i < rows2.GetCount() ; i++)
870
 
    {
871
 
        int row=rows2.Item(i);
872
 
        while (i2 < cellRowMax && rows.Item(i2) < row)
873
 
            i2++;
874
 
        if (i2 == cellRowMax || row != rows.Item(i2))
875
 
            rows.Add(row);
876
 
    }
877
 
 
878
 
    return rows;
879
 
}
880
 
 
881
 
 
882
 
class sqlGridTextEditor : public wxGridCellTextEditor
883
 
{
884
 
public:
885
 
    sqlGridTextEditor(bool multiLine=false, int len=0) { isMultiLine=multiLine; textlen=len;  }
886
 
    virtual wxGridCellEditor *Clone() const { return new sqlGridTextEditor(isMultiLine, textlen); }
887
 
    void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);
888
 
    void BeginEdit(int row, int col, wxGrid* grid);
889
 
    bool EndEdit(int row, int col, wxGrid* grid);
890
 
 
891
 
 
892
 
protected:
893
 
    int textlen;
894
 
    bool isMultiLine;
895
 
};
896
 
 
897
 
 
898
 
 
899
 
 
900
 
void sqlGridTextEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler)
901
 
{
902
 
    int flags=0;
903
 
    if (isMultiLine)
904
 
        flags = wxTE_RICH|wxTE_MULTILINE|wxTE_DONTWRAP;
905
 
 
906
 
    m_control = new wxTextCtrl(parent, id, wxEmptyString,
907
 
                               wxDefaultPosition, wxDefaultSize, flags
908
 
                              );
909
 
 
910
 
    if (textlen > 0)
911
 
        Text()->SetMaxLength(textlen);
912
 
 
913
 
    wxGridCellEditor::Create(parent, id, evtHandler);
914
 
}
915
 
 
916
 
 
917
 
void sqlGridTextEditor::BeginEdit(int row, int col, wxGrid *grid)
918
 
{
919
 
    wxGridCellTextEditor::BeginEdit(row, col, grid);
920
 
    ((ctlSQLGrid*)grid)->ResizeEditor(row, col);
921
 
}
922
 
 
923
 
 
924
 
bool sqlGridTextEditor::EndEdit(int row, int col, wxGrid *grid)
925
 
{
926
 
    bool changed = false;
927
 
    wxString value = Text()->GetValue();
928
 
    changed = true;
929
 
 
930
 
    if (changed)
931
 
        grid->GetTable()->SetValue(row, col, value);
932
 
 
933
 
//    Text()->SetValue(wxEmptyString);
934
 
 
935
 
    return changed;
936
 
 
937
 
#if 0
938
 
    bool rc=wxGridCellTextEditor::EndEdit(row, col, grid);
939
 
#ifdef __WXMSW__
940
 
    if (Text()->IsRich())
941
 
    {
942
 
        m_control->wxWindowBase::Show(true);
943
 
        m_control->Show(false);
944
 
    }
945
 
#endif
946
 
    return rc;
947
 
#endif
948
 
}
949
 
 
950
 
    
951
 
class sqlGridNumericEditor : public wxGridCellTextEditor
952
 
{
953
 
public:
954
 
    sqlGridNumericEditor(int len=-1, int prec=-1) {numlen=len; numprec=prec; }
955
 
    virtual wxGridCellEditor *Clone() const { return new sqlGridNumericEditor(numlen, numprec); }
956
 
    virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);
957
 
 
958
 
    virtual bool IsAcceptedKey(wxKeyEvent& event);
959
 
    virtual void BeginEdit(int row, int col, wxGrid* grid);
960
 
    virtual bool EndEdit(int row, int col, wxGrid* grid);
961
 
 
962
 
    virtual void Reset() {DoReset(m_startValue); }
963
 
    virtual void StartingKey(wxKeyEvent& event);
964
 
    virtual void SetParameters(const wxString& params);
965
 
 
966
 
protected:
967
 
    int numlen, numprec;
968
 
    wxString m_startValue;
969
 
 
970
 
};
971
 
 
972
 
 
973
 
 
974
 
void sqlGridNumericEditor::StartingKey(wxKeyEvent& event)
975
 
{
976
 
    int keycode = event.GetKeyCode();
977
 
    bool allowed=false;
978
 
 
979
 
    switch (keycode)
980
 
    {
981
 
        case WXK_DECIMAL:
982
 
        case WXK_NUMPAD_DECIMAL:
983
 
        case '.':
984
 
            if (numprec)
985
 
                allowed=true;
986
 
            break;
987
 
        case '+':
988
 
        case WXK_ADD:
989
 
        case WXK_NUMPAD_ADD:
990
 
        case '-':
991
 
        case WXK_SUBTRACT:
992
 
        case WXK_NUMPAD_SUBTRACT:
993
 
 
994
 
        case WXK_NUMPAD0:
995
 
        case WXK_NUMPAD1:
996
 
        case WXK_NUMPAD2:
997
 
        case WXK_NUMPAD3:
998
 
        case WXK_NUMPAD4:
999
 
        case WXK_NUMPAD5:
1000
 
        case WXK_NUMPAD6:
1001
 
        case WXK_NUMPAD7:
1002
 
        case WXK_NUMPAD8:
1003
 
        case WXK_NUMPAD9:
1004
 
            allowed=true;
1005
 
            break;
1006
 
        default:
1007
 
            if (wxIsdigit(keycode))
1008
 
                allowed =true;
1009
 
            break;
1010
 
    
1011
 
    }
1012
 
    if (allowed)
1013
 
        wxGridCellTextEditor::StartingKey(event);
1014
 
    else
1015
 
        event.Skip();
1016
 
}
1017
 
 
1018
 
 
1019
 
 
1020
 
bool sqlGridNumericEditor::IsAcceptedKey(wxKeyEvent& event)
1021
 
{
1022
 
    if ( wxGridCellEditor::IsAcceptedKey(event) )
1023
 
    {
1024
 
        int keycode = event.GetKeyCode();
1025
 
        switch ( keycode )
1026
 
        {
1027
 
            case WXK_DECIMAL:
1028
 
            case WXK_NUMPAD_DECIMAL:
1029
 
                return (numprec != 0);
1030
 
 
1031
 
            case '+':
1032
 
            case WXK_ADD:
1033
 
            case WXK_NUMPAD_ADD:
1034
 
            case '-':
1035
 
            case WXK_SUBTRACT:
1036
 
            case WXK_NUMPAD_SUBTRACT:
1037
 
 
1038
 
            case WXK_NUMPAD0:
1039
 
            case WXK_NUMPAD1:
1040
 
            case WXK_NUMPAD2:
1041
 
            case WXK_NUMPAD3:
1042
 
            case WXK_NUMPAD4:
1043
 
            case WXK_NUMPAD5:
1044
 
            case WXK_NUMPAD6:
1045
 
            case WXK_NUMPAD7:
1046
 
            case WXK_NUMPAD8:
1047
 
            case WXK_NUMPAD9:
1048
 
                return true;
1049
 
            default:
1050
 
                return wxIsdigit(keycode) != 0;
1051
 
        }
1052
 
    }
1053
 
 
1054
 
    return false;
1055
 
}
1056
 
 
1057
 
 
1058
 
 
1059
 
void sqlGridNumericEditor::BeginEdit(int row, int col, wxGrid* grid)
1060
 
{
1061
 
    m_startValue = grid->GetTable()->GetValue(row, col);
1062
 
 
1063
 
 
1064
 
    wxString value = m_startValue;
1065
 
    // localize value here
1066
 
 
1067
 
    DoBeginEdit(value);
1068
 
}
1069
 
 
1070
 
 
1071
 
 
1072
 
bool sqlGridNumericEditor::EndEdit(int row, int col, wxGrid* grid)
1073
 
{
1074
 
    wxASSERT_MSG(m_control,
1075
 
                 wxT("The sqlGridNumericEditor must be Created first!"));
1076
 
 
1077
 
    bool changed = false;
1078
 
    wxString value = Text()->GetValue();
1079
 
 
1080
 
    // de-localize value here
1081
 
 
1082
 
    if (value != m_startValue)
1083
 
        changed = true;
1084
 
 
1085
 
    if (changed)
1086
 
        grid->GetTable()->SetValue(row, col, value);
1087
 
 
1088
 
    m_startValue = wxEmptyString;
1089
 
    Text()->SetValue(m_startValue);
1090
 
 
1091
 
    return changed;
1092
 
}
1093
 
 
1094
 
 
1095
 
void sqlGridNumericEditor::SetParameters(const wxString& params)
1096
 
{
1097
 
    if ( !params )
1098
 
    {
1099
 
        // reset to default
1100
 
        numlen=-1;
1101
 
        numprec=-1;
1102
 
    }
1103
 
    else
1104
 
    {
1105
 
        long tmp;
1106
 
        if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )
1107
 
        {
1108
 
            numlen = (int)tmp;
1109
 
 
1110
 
            if ( params.AfterFirst(_T(',')).ToLong(&tmp) )
1111
 
            {
1112
 
                numprec = (int)tmp;
1113
 
 
1114
 
                // skip the error message below
1115
 
                return;
1116
 
            }
1117
 
        }
1118
 
    }
1119
 
}
1120
 
 
1121
 
 
1122
 
void sqlGridNumericEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler)
1123
 
{
1124
 
    m_control = new wxTextCtrl(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize);
1125
 
 
1126
 
    wxGridCellEditor::Create(parent, id, evtHandler);
1127
 
    Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
1128
 
}
1129
 
 
1130
 
 
1131
 
 
1132
 
 
1133
 
sqlTable::sqlTable(pgConn *conn, pgQueryThread *_thread, const wxString& tabName, const OID _relid, bool _hasOid, const wxString& _pkCols, char _relkind)
1134
 
{
1135
 
    connection=conn;
1136
 
    primaryKeyColNumbers = _pkCols;
1137
 
    relid=_relid;
1138
 
    relkind=_relkind;
1139
 
    tableName=tabName;
1140
 
    hasOids=_hasOid;
1141
 
    thread=_thread;
1142
 
 
1143
 
    rowsCached=0;
1144
 
    rowsAdded=0;
1145
 
    rowsStored=0;
1146
 
    rowsDeleted=0;
1147
 
 
1148
 
    dataPool=0;
1149
 
    addPool = new cacheLinePool(100);       // arbitrary initial size
1150
 
    lastRow=-1;
1151
 
    int i;
1152
 
 
1153
 
    nRows = thread->DataSet()->NumRows();
1154
 
    nCols=thread->DataSet()->NumCols();
1155
 
 
1156
 
    columns = new sqlCellAttr[nCols];
1157
 
    savedLine.cols = new wxString[nCols];
1158
 
 
1159
 
 
1160
 
    pgSet *colSet=connection->ExecuteSet(
1161
 
        wxT("SELECT n.nspname AS nspname, relname, t.typname, nt.nspname AS typnspname, ")
1162
 
               wxT("attname, attnum, COALESCE(b.oid, t.oid) AS basetype, atthasdef, adsrc,\n")
1163
 
        wxT("       CASE WHEN t.typbasetype::oid=0 THEN att.atttypmod else t.typtypmod END AS typmod,\n")
1164
 
        wxT("       CASE WHEN t.typbasetype::oid=0 THEN att.attlen else t.typlen END AS typlen\n")
1165
 
        wxT("  FROM pg_attribute att\n")
1166
 
        wxT("  JOIN pg_type t ON t.oid=att.atttypid\n")
1167
 
        wxT("  JOIN pg_namespace nt ON nt.oid=t.typnamespace\n")
1168
 
        wxT("  JOIN pg_class c ON c.oid=attrelid\n")
1169
 
        wxT("  JOIN pg_namespace n ON n.oid=relnamespace\n")
1170
 
        wxT("  LEFT OUTER JOIN pg_type b ON b.oid=t.typbasetype\n")
1171
 
        wxT("  LEFT OUTER JOIN pg_attrdef def ON adrelid=attrelid AND adnum=attnum\n")
1172
 
        wxT(" WHERE attnum > 0 AND NOT attisdropped AND attrelid=") + NumToStr(relid) + wxT("::oid\n")
1173
 
        wxT(" ORDER BY attnum"));
1174
 
 
1175
 
 
1176
 
 
1177
 
    bool canInsert=false;
1178
 
    if (colSet)
1179
 
    {
1180
 
        if (hasOids)
1181
 
        {
1182
 
            columns[0].name = wxT("oid");
1183
 
            columns[0].numeric = true;
1184
 
            columns[0].attr->SetReadOnly(true);
1185
 
            columns[0].type = PGTYPCLASS_NUMERIC;
1186
 
        }
1187
 
 
1188
 
        for (i=(hasOids ? 1 : 0) ; i < nCols ; i++)
1189
 
        {
1190
 
            wxGridCellEditor *editor=0;
1191
 
 
1192
 
            columns[i].name = colSet->GetVal(wxT("attname"));
1193
 
            columns[i].typeName = colSet->GetVal(wxT("typname"));
1194
 
            columns[i].typeNspName = colSet->GetVal(wxT("typnspname"));
1195
 
 
1196
 
            columns[i].type = (Oid)colSet->GetOid(wxT("basetype"));
1197
 
            if ((columns[i].type == PGOID_TYPE_INT4 || columns[i].type == PGOID_TYPE_INT8)
1198
 
                && colSet->GetBool(wxT("atthasdef")))
1199
 
            {
1200
 
                if (colSet->GetVal(wxT("adsrc")) ==  wxT("nextval('") 
1201
 
                        + colSet->GetVal(wxT("nspname")) + wxT(".") + colSet->GetVal(wxT("relname"))
1202
 
                        + wxT("_") + columns[i].name + wxT("_seq'::text)"))
1203
 
                {
1204
 
                    if (columns[i].type == PGOID_TYPE_INT4)
1205
 
                        columns[i].type = (Oid)PGOID_TYPE_SERIAL;
1206
 
                    else
1207
 
                        columns[i].type = (Oid)PGOID_TYPE_SERIAL8;
1208
 
                }
1209
 
            }
1210
 
            columns[i].typlen=colSet->GetLong(wxT("typlen"));
1211
 
            columns[i].typmod=colSet->GetLong(wxT("typmod"));
1212
 
 
1213
 
            switch (columns[i].type)
1214
 
            {
1215
 
                case PGOID_TYPE_BOOL:
1216
 
                    columns[i].numeric = false;
1217
 
                    columns[i].attr->SetReadOnly(false);
1218
 
                    editor = new wxGridCellBoolEditor();
1219
 
                    break;
1220
 
                case PGOID_TYPE_INT8:
1221
 
                case PGOID_TYPE_SERIAL8:
1222
 
                    SetNumberEditor(i, 20);
1223
 
                    break;
1224
 
                case PGOID_TYPE_INT2:
1225
 
                    SetNumberEditor(i, 5);
1226
 
                    break;
1227
 
                case PGOID_TYPE_INT4:
1228
 
                case PGOID_TYPE_SERIAL:
1229
 
                    SetNumberEditor(i, 10);
1230
 
                    break;
1231
 
                case PGOID_TYPE_OID:
1232
 
                case PGOID_TYPE_TID:
1233
 
                case PGOID_TYPE_XID:
1234
 
                case PGOID_TYPE_CID:
1235
 
                    SetNumberEditor(i, 10);
1236
 
                    break;
1237
 
                case PGOID_TYPE_FLOAT4:
1238
 
                case PGOID_TYPE_FLOAT8:
1239
 
                    columns[i].numeric = true;
1240
 
                    columns[i].attr->SetReadOnly(false);
1241
 
                    editor = new sqlGridNumericEditor();
1242
 
                    break;
1243
 
                case PGOID_TYPE_MONEY:
1244
 
                case PGOID_TYPE_NUMERIC:
1245
 
                {
1246
 
                    columns[i].numeric = true;
1247
 
                    columns[i].attr->SetReadOnly(false);
1248
 
                    int len=columns[i].size();
1249
 
                    int prec=columns[i].precision();
1250
 
                    if (prec>0)
1251
 
                        len -= (prec);
1252
 
                    editor = new sqlGridNumericEditor(len, prec);
1253
 
                    break;
1254
 
                }
1255
 
                case PGOID_TYPE_BYTEA:
1256
 
                case PGOID_TYPE_CHAR:
1257
 
                case PGOID_TYPE_NAME:
1258
 
                case PGOID_TYPE_TEXT:
1259
 
                default:
1260
 
                    columns[i].numeric = false;
1261
 
                    columns[i].attr->SetReadOnly(false);
1262
 
                    columns[i].needResize = true;
1263
 
// Temorary fix for 1.4.0 - FIXME properly!!
1264
 
#ifdef __WXMAC__
1265
 
                    editor = new wxGridCellAutoWrapStringEditor();
1266
 
#else
1267
 
                    editor = new sqlGridTextEditor(true);
1268
 
#endif
1269
 
                    break;
1270
 
            }
1271
 
            if (editor)
1272
 
                columns[i].attr->SetEditor(editor);
1273
 
 
1274
 
            if (relkind != 'r' || (!hasOids && primaryKeyColNumbers.IsNull()))
1275
 
            {
1276
 
                // for security reasons, we need oid or pk to enable updates. If none is available,
1277
 
                // the table definition can be considered faulty.
1278
 
                columns[i].attr->SetReadOnly(true);
1279
 
            }
1280
 
            if (!columns[i].attr->IsReadOnly())
1281
 
                canInsert=true;
1282
 
 
1283
 
            wxStringTokenizer collist(primaryKeyColNumbers, wxT(","));
1284
 
            long cn=0;
1285
 
            long attnum=colSet->GetLong(wxT("attnum"));
1286
 
 
1287
 
            while (cn < attnum && collist.HasMoreTokens())
1288
 
            {
1289
 
                cn=StrToLong(collist.GetNextToken());
1290
 
                if (cn == attnum)
1291
 
                    columns[i].isPrimaryKey = true;
1292
 
            }
1293
 
 
1294
 
            colSet->MoveNext();
1295
 
        }
1296
 
        delete colSet;
1297
 
    }
1298
 
    else
1299
 
    {
1300
 
        // um, we never should reach here because this would mean 
1301
 
        // that datatypes are unreadable.
1302
 
        // *if* we reach here, namespace info is missing.
1303
 
        for (i=0 ; i < nCols ; i++)
1304
 
        {
1305
 
            columns[i].typeName = thread->DataSet()->ColType(i);
1306
 
            columns[i].name = thread->DataSet()->ColName(i);
1307
 
        }
1308
 
    }
1309
 
 
1310
 
    if (nRows)
1311
 
    {
1312
 
        dataPool=new cacheLinePool(nRows);
1313
 
        lineIndex = new int[nRows];
1314
 
        for (i=0 ; i < nRows ; i++)
1315
 
            lineIndex[i] = i;
1316
 
    }
1317
 
 
1318
 
    if (canInsert)
1319
 
    {
1320
 
        // an empty line waiting for inserts
1321
 
        rowsAdded=1;
1322
 
    }
1323
 
}
1324
 
 
1325
 
 
1326
 
sqlTable::~sqlTable()
1327
 
{
1328
 
    if (thread)
1329
 
        delete thread;
1330
 
    if (dataPool)
1331
 
        delete dataPool;
1332
 
 
1333
 
    delete addPool;
1334
 
 
1335
 
    delete[] columns;
1336
 
}
1337
 
 
1338
 
 
1339
 
int sqlTable::GetNumberCols()
1340
 
{
1341
 
    return nCols;
1342
 
}
1343
 
 
1344
 
 
1345
 
int sqlTable::GetNumberRows()
1346
 
{
1347
 
    return nRows + rowsAdded - rowsDeleted;
1348
 
}
1349
 
 
1350
 
 
1351
 
int sqlTable::GetNumberStoredRows()
1352
 
{
1353
 
    return nRows + rowsStored - rowsDeleted;
1354
 
}
1355
 
 
1356
 
 
1357
 
wxString sqlTable::GetExportLine(int row)
1358
 
{
1359
 
    wxString str;
1360
 
    cacheLine *line = GetLine(row);
1361
 
    if (line)
1362
 
    {
1363
 
        int col;
1364
 
        for (col=0 ; col < nCols ; col++)
1365
 
        {
1366
 
            if (col)
1367
 
                str.Append(settings->GetExportColSeparator());
1368
 
            bool needQuote = settings->GetExportQuoting() > 1;
1369
 
 
1370
 
            // find out if string
1371
 
            switch (columns[col].type)
1372
 
            {
1373
 
                case PGTYPCLASS_NUMERIC:
1374
 
                case PGTYPCLASS_BOOL:
1375
 
                    break;
1376
 
                default:
1377
 
                    needQuote=true;
1378
 
                    break;
1379
 
            }
1380
 
            if (needQuote)
1381
 
                str.Append(settings->GetExportQuoteChar());
1382
 
 
1383
 
            str.Append(line->cols[col]);
1384
 
        
1385
 
            if (needQuote)
1386
 
                str.Append(settings->GetExportQuoteChar());
1387
 
        }
1388
 
    }
1389
 
    return str;
1390
 
}
1391
 
 
1392
 
 
1393
 
wxString sqlTable::GetColLabelValue(int col)
1394
 
{
1395
 
    wxString label=columns[col].name + wxT("\n");
1396
 
    if (columns[col].isPrimaryKey)
1397
 
        label += wxT("[PK] ");
1398
 
 
1399
 
    switch (columns[col].type)
1400
 
    {
1401
 
        case (Oid)PGOID_TYPE_SERIAL:
1402
 
            label += wxT("serial");
1403
 
            break;
1404
 
        case (Oid)PGOID_TYPE_SERIAL8:
1405
 
            label += wxT("bigserial");
1406
 
            break;
1407
 
        default:
1408
 
            label += columns[col].typeName;
1409
 
            break;
1410
 
    }
1411
 
    return label;
1412
 
}
1413
 
 
1414
 
 
1415
 
wxString sqlTable::GetRowLabelValue(int row)
1416
 
{
1417
 
    wxString label;
1418
 
    if (row < nRows-rowsDeleted || GetLine(row)->stored)
1419
 
        label.Printf(wxT("%d"), row+1);
1420
 
    else
1421
 
        label = wxT("*");
1422
 
    return label;
1423
 
}
1424
 
 
1425
 
 
1426
 
 
1427
 
void sqlTable::SetNumberEditor(int col, int len)
1428
 
{
1429
 
    columns[col].numeric = true;
1430
 
    columns[col].attr->SetReadOnly(false);
1431
 
    columns[col].attr->SetEditor(new sqlGridNumericEditor(len, 0));
1432
 
}
1433
 
 
1434
 
 
1435
 
bool sqlTable::CheckInCache(int row)
1436
 
{
1437
 
    if (row > nRows - rowsDeleted + rowsAdded)
1438
 
        return false;
1439
 
    if (row >= nRows-rowsDeleted)
1440
 
        return true;
1441
 
 
1442
 
    return dataPool->IsFilled(row);
1443
 
}
1444
 
 
1445
 
 
1446
 
cacheLine *sqlTable::GetLine(int row)
1447
 
{
1448
 
    cacheLine *line;
1449
 
    if (row < nRows-rowsDeleted)
1450
 
        line=dataPool->Get(lineIndex[row]);
1451
 
    else
1452
 
        line=addPool->Get(row-(nRows-rowsDeleted));
1453
 
    return line;
1454
 
}
1455
 
 
1456
 
 
1457
 
 
1458
 
wxString sqlTable::MakeKey(cacheLine *line)
1459
 
{
1460
 
    wxString where;
1461
 
    if (hasOids)
1462
 
        where = wxT("OID = ") + line->cols[0];
1463
 
    else
1464
 
    {
1465
 
        wxStringTokenizer collist(primaryKeyColNumbers, wxT(","));
1466
 
        long cn;
1467
 
 
1468
 
        while (collist.HasMoreTokens())
1469
 
        {
1470
 
            cn=StrToLong(collist.GetNextToken());
1471
 
 
1472
 
            wxString colval=line->cols[cn-1];
1473
 
            if (colval.IsEmpty())
1474
 
                return wxEmptyString;
1475
 
 
1476
 
            if (!where.IsEmpty())
1477
 
                where += wxT(" AND ");
1478
 
            where += qtIdent(columns[cn-1].name) + wxT(" = ") 
1479
 
                  + qtString(colval) + wxT("::") + qtIdent(columns[cn-1].typeNspName)
1480
 
                                     + wxT(".") + qtIdent(columns[cn-1].typeName);
1481
 
        }
1482
 
    }
1483
 
    return where;
1484
 
}
1485
 
 
1486
 
 
1487
 
 
1488
 
void sqlTable::UndoLine(int row)
1489
 
{
1490
 
    if (lastRow >= 0 && row >= 0)
1491
 
    {
1492
 
        cacheLine *line=GetLine(row);
1493
 
        if (line)
1494
 
        {
1495
 
            int i;
1496
 
            for (i=0 ; i < nCols ; i++)
1497
 
                line->cols[i] = savedLine.cols[i];
1498
 
            wxToolBar *tb=((wxFrame*)GetView()->GetParent())->GetToolBar();
1499
 
            if (tb)
1500
 
            {
1501
 
                tb->EnableTool(MNU_SAVE, false);
1502
 
                tb->EnableTool(MNU_UNDO, false);
1503
 
            }
1504
 
        }
1505
 
    }
1506
 
    lastRow = -1;
1507
 
}
1508
 
 
1509
 
    
1510
 
void sqlTable::StoreLine()
1511
 
{
1512
 
    GetView()->BeginBatch();
1513
 
    if (lastRow >= 0)
1514
 
    {
1515
 
        bool done=false;
1516
 
 
1517
 
        cacheLine *line=GetLine(lastRow);
1518
 
 
1519
 
        int i;
1520
 
        wxString colList, valList;
1521
 
 
1522
 
        if (line->stored)
1523
 
        {
1524
 
            // UPDATE
1525
 
 
1526
 
            for (i=(hasOids? 1 : 0) ; i<nCols ; i++)
1527
 
            {
1528
 
                if (columns[i].type == PGOID_TYPE_BOOL)  // bool
1529
 
                    line->cols[i] = (StrToBool(line->cols[i]) ? wxT("t") : wxT("f"));
1530
 
 
1531
 
                if (savedLine.cols[i] != line->cols[i])
1532
 
                {
1533
 
                    if (!valList.IsNull())
1534
 
                        valList += wxT(", ");
1535
 
                    valList += qtIdent(columns[i].name) + wxT("=") + columns[i].Quote(line->cols[i]);
1536
 
                }
1537
 
            }
1538
 
 
1539
 
            if (valList.IsEmpty())
1540
 
                done=true;
1541
 
            else
1542
 
            {
1543
 
                wxString key=MakeKey(&savedLine);
1544
 
                wxASSERT(!key.IsEmpty());
1545
 
                done=connection->ExecuteVoid(wxT(
1546
 
                    "UPDATE ") + tableName + wxT(
1547
 
                    " SET ") + valList + wxT(
1548
 
                    " WHERE ") + key);
1549
 
            }
1550
 
        }
1551
 
        else
1552
 
        {
1553
 
            // INSERT
1554
 
 
1555
 
            for (i=0 ; i<nCols ; i++)
1556
 
            {
1557
 
                if (!columns[i].attr->IsReadOnly() && !line->cols[i].IsEmpty())
1558
 
                {
1559
 
                    if (!colList.IsNull())
1560
 
                    {
1561
 
                        valList += wxT(", ");
1562
 
                        colList += wxT(", ");
1563
 
                    }
1564
 
                    colList += qtIdent(columns[i].name);
1565
 
                    if (columns[i].type == PGOID_TYPE_BOOL)
1566
 
                        line->cols[i] = (StrToBool(line->cols[i]) ? wxT("t") : wxT("f"));
1567
 
                    valList += columns[i].Quote(line->cols[i]);
1568
 
                }
1569
 
            }
1570
 
 
1571
 
            if (!valList.IsEmpty())
1572
 
            {
1573
 
                pgSet *set=connection->ExecuteSet(
1574
 
                    wxT("INSERT INTO ") + tableName
1575
 
                    + wxT("(") + colList 
1576
 
                    + wxT(") VALUES (") + valList
1577
 
                    + wxT(")"));
1578
 
                if (set)
1579
 
                {
1580
 
                    if (hasOids)
1581
 
                        line->cols[0] = NumToStr((long)set->GetInsertedOid());
1582
 
                    delete set;
1583
 
 
1584
 
                    done=true;
1585
 
                    rowsStored++;
1586
 
                    ((wxFrame*)GetView()->GetParent())->SetStatusText(wxString::Format(wxT("%d rows."), GetNumberStoredRows()));
1587
 
                    if (rowsAdded == rowsStored)
1588
 
                        GetView()->AppendRows();
1589
 
 
1590
 
                    // Read back what we inserted to get default vals
1591
 
                    wxString key=MakeKey(line);
1592
 
 
1593
 
                    if (key.IsEmpty())
1594
 
                    {
1595
 
                        // That's a problem: obviously, the key generated isn't present
1596
 
                        // because it's serial or default or otherwise generated in the backend
1597
 
                        // we don't get.
1598
 
                        // That's why the whole line is declared readonly.
1599
 
 
1600
 
                        line->readOnly=true;
1601
 
                    }
1602
 
                    else
1603
 
                    {
1604
 
                        set=connection->ExecuteSet(
1605
 
                            wxT("SELECT * FROM ") + tableName + 
1606
 
                            wxT(" WHERE ") + key);
1607
 
                        if (set)
1608
 
                        {
1609
 
                            for (i=(hasOids?1:0) ; i < nCols ; i++)
1610
 
                            {
1611
 
                                line->cols[i] = set->GetVal(columns[i].name);
1612
 
                            }
1613
 
                            delete set;
1614
 
                        }
1615
 
                    }
1616
 
                }
1617
 
            }
1618
 
        }
1619
 
        if (done)
1620
 
        {
1621
 
            line->stored = true;
1622
 
            lastRow = -1;
1623
 
        }
1624
 
        else
1625
 
            UndoLine(lastRow);
1626
 
    }
1627
 
 
1628
 
    GetView()->EndBatch();
1629
 
}
1630
 
 
1631
 
 
1632
 
void sqlTable::SetValue(int row, int col, const wxString &value)
1633
 
{
1634
 
    cacheLine *line=GetLine(row);
1635
 
 
1636
 
    if (!line)
1637
 
    {
1638
 
        // Bad problem, no line!
1639
 
        return;
1640
 
    }
1641
 
 
1642
 
 
1643
 
    if (row != lastRow)
1644
 
    {
1645
 
        if (lastRow >= 0)
1646
 
            StoreLine();
1647
 
 
1648
 
        if (!line->cols)
1649
 
            line->cols = new wxString[nCols];
1650
 
 
1651
 
        // remember line contents for later reference in update ... where
1652
 
        int i;
1653
 
        for (i=0 ; i < nCols ; i++)
1654
 
            savedLine.cols[i] = line->cols[i];
1655
 
        lastRow = row;
1656
 
    }
1657
 
    wxToolBar *tb=((wxFrame*)GetView()->GetParent())->GetToolBar();
1658
 
    if (tb)
1659
 
    {
1660
 
        tb->EnableTool(MNU_SAVE, true);
1661
 
        tb->EnableTool(MNU_UNDO, true);
1662
 
    }
1663
 
    line->cols[col] = value;
1664
 
}
1665
 
 
1666
 
 
1667
 
 
1668
 
wxString sqlTable::GetValue(int row, int col)
1669
 
{
1670
 
    wxString val;
1671
 
    cacheLine *line;
1672
 
    if (row < nRows-rowsDeleted)
1673
 
        line=dataPool->Get(lineIndex[row]);
1674
 
    else
1675
 
        line=addPool->Get(row-(nRows-rowsDeleted));
1676
 
 
1677
 
    if (!line)
1678
 
    {
1679
 
        // Bad problem, no line!
1680
 
        return val;
1681
 
    }
1682
 
 
1683
 
    if (!line->cols)
1684
 
    {
1685
 
        line->cols = new wxString[nCols];
1686
 
        if (row < nRows-rowsDeleted)
1687
 
        {
1688
 
            if (!thread)
1689
 
            {
1690
 
                wxLogError(__("Unexpected empty cache line: dataSet already closed."));
1691
 
                return val;
1692
 
            }
1693
 
 
1694
 
            line->stored = true;
1695
 
            if (lineIndex[row] != thread->DataSet()->CurrentPos() -1)
1696
 
                thread->DataSet()->Locate(lineIndex[row]+1);
1697
 
 
1698
 
            int i;
1699
 
            for (i=0 ; i < nCols ; i++)
1700
 
            {
1701
 
                wxString val= thread->DataSet()->GetVal(i);
1702
 
                if (val.IsEmpty())
1703
 
                {
1704
 
                    if (!thread->DataSet()->IsNull(i))
1705
 
                        val = wxT("''");
1706
 
                }
1707
 
                else if (val == wxT("''"))
1708
 
                    val = wxT("\\'\\'");
1709
 
                line->cols[i] = val;
1710
 
            }
1711
 
            rowsCached++;
1712
 
 
1713
 
            if (rowsCached == nRows)
1714
 
            {
1715
 
                delete thread;
1716
 
                thread=0;
1717
 
            }
1718
 
        }
1719
 
    }
1720
 
    if (columns[col].type == PGOID_TYPE_BOOL)
1721
 
        line->cols[col] = (StrToBool(line->cols[col]) ? wxT("TRUE") : wxT("FALSE"));
1722
 
 
1723
 
    val = line->cols[col];
1724
 
    return val;
1725
 
}
1726
 
 
1727
 
 
1728
 
 
1729
 
bool sqlTable::CanGetValueAs(int row, int col, const wxString& typeName)
1730
 
{
1731
 
    return CanSetValueAs(row, col, typeName);
1732
 
}
1733
 
 
1734
 
 
1735
 
bool sqlTable::CanSetValueAs(int row, int col, const wxString& typeName)
1736
 
{
1737
 
    if (typeName == wxGRID_VALUE_STRING)
1738
 
        return true;
1739
 
 
1740
 
    switch (columns[col].type)
1741
 
    {
1742
 
        case PGOID_TYPE_BOOL:
1743
 
            return typeName == wxGRID_VALUE_BOOL;
1744
 
        default:
1745
 
            return false;
1746
 
    }
1747
 
}
1748
 
 
1749
 
    
1750
 
bool sqlTable::GetValueAsBool(int row, int col)
1751
 
{
1752
 
    return StrToBool(GetValue(row, col));
1753
 
}
1754
 
 
1755
 
 
1756
 
void sqlTable::SetValueAsBool(int row, int col, bool b)
1757
 
{
1758
 
    SetValue(row, col, (b ? wxT("TRUE") : wxT("FALSE")));
1759
 
}
1760
 
 
1761
 
 
1762
 
bool sqlTable::AppendRows(size_t rows)
1763
 
{
1764
 
    rowsAdded += rows;
1765
 
    GetLine(nRows + rowsAdded - rowsDeleted -1);
1766
 
 
1767
 
    wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, rows);
1768
 
    GetView()->ProcessTableMessage(msg);
1769
 
 
1770
 
    return true;
1771
 
}
1772
 
 
1773
 
 
1774
 
bool sqlTable::DeleteRows(size_t pos, size_t rows)
1775
 
{
1776
 
    size_t i=pos;
1777
 
    size_t rowsDone=0;
1778
 
 
1779
 
    while (i < pos+rows)
1780
 
    {
1781
 
        cacheLine *line=GetLine(pos);
1782
 
        if (!line)
1783
 
            break;
1784
 
 
1785
 
        if (line->stored)
1786
 
        {
1787
 
            wxString key=MakeKey(line);
1788
 
            wxASSERT(!key.IsEmpty());
1789
 
            bool done=connection->ExecuteVoid(wxT(
1790
 
                "DELETE FROM ") + tableName + wxT(" WHERE ") + key);
1791
 
            if (!done)
1792
 
                break;
1793
 
 
1794
 
            if ((int)pos < nRows - rowsDeleted)
1795
 
            {
1796
 
                rowsDeleted++;
1797
 
                if ((int)pos < nRows - rowsDeleted)
1798
 
                    memmove(lineIndex+pos, lineIndex+pos+1, sizeof(cacheLine*)*(nRows-rowsDeleted-pos));
1799
 
            }
1800
 
            else
1801
 
            {
1802
 
                rowsAdded--;
1803
 
                if (GetLine(pos)->stored)
1804
 
                    rowsStored--;
1805
 
                addPool->Delete(pos - (nRows-rowsDeleted));
1806
 
            }
1807
 
            rowsDone++;
1808
 
        }
1809
 
        else
1810
 
        {
1811
 
            // last empty line won't be deleted, just cleared
1812
 
            int j;
1813
 
            for (j=0 ; j < nCols ; j++)
1814
 
                line->cols[j] = wxT("");
1815
 
        }
1816
 
        i++;
1817
 
    }
1818
 
 
1819
 
    if (rowsDone > 0 && GetView())
1820
 
    {
1821
 
        wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, pos, rowsDone);
1822
 
        GetView()->ProcessTableMessage(msg);
1823
 
    }
1824
 
    return (rowsDone != 0);
1825
 
}
1826
 
 
1827
 
 
1828
 
    
1829
 
 
1830
 
wxGridCellAttr* sqlTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind  kind)
1831
 
{
1832
 
    cacheLine *line=GetLine(row);
1833
 
    if (line && line->readOnly)
1834
 
    {
1835
 
        wxGridCellAttr *attr=new wxGridCellAttr(columns[col].attr);
1836
 
        attr->SetReadOnly();
1837
 
        return attr;
1838
 
    }
1839
 
    else
1840
 
    {
1841
 
        columns[col].attr->IncRef();
1842
 
        return columns[col].attr;
1843
 
    }
1844
 
}
1845
 
 
1846
 
 
1847
 
 
1848
 
wxString sqlCellAttr::Quote(const wxString& value)
1849
 
{
1850
 
    wxString str;
1851
 
    if (value.IsEmpty())
1852
 
        str=wxT("NULL");
1853
 
    else if (numeric)
1854
 
        str = value;
1855
 
    else if (value == wxT("\\'\\'"))
1856
 
        str = qtString(wxT("''"));
1857
 
    else if (value == wxT("''"))
1858
 
        str = wxT("''");
1859
 
    else
1860
 
        str=qtString(value);
1861
 
 
1862
 
    return str + wxT("::") + qtIdent(typeNspName) + wxT(".") + qtIdent(typeName);
1863
 
}
1864
 
 
1865
 
 
1866
 
 
1867
 
 
1868
 
int sqlCellAttr::size()
1869
 
{
1870
 
    if (typlen == -1 && typmod > 0)
1871
 
    {
1872
 
        return (typmod-4) >> 16;
1873
 
    }
1874
 
    else
1875
 
        return typlen;
1876
 
}
1877
 
 
1878
 
 
1879
 
int sqlCellAttr::precision()
1880
 
{
1881
 
    if (typlen == -1 && typmod > 0)
1882
 
    {
1883
 
        return (typmod-4) & 0x7fff;
1884
 
    }
1885
 
    else
1886
 
        return -1;
1887
 
}
1888
 
 
1889
 
 
1890
 
cacheLinePool::cacheLinePool(int initialLines)
1891
 
{
1892
 
    ptr=new cacheLine*[initialLines];
1893
 
    if (ptr)
1894
 
    {
1895
 
        anzLines=initialLines;
1896
 
        memset(ptr, 0, sizeof(cacheLine*)*anzLines);
1897
 
    }
1898
 
    else
1899
 
    {
1900
 
        anzLines=0;
1901
 
        wxLogError(__("Out of Memory for cacheLinePool"));
1902
 
    }
1903
 
}
1904
 
 
1905
 
 
1906
 
 
1907
 
cacheLinePool::~cacheLinePool()
1908
 
{
1909
 
    if (ptr)
1910
 
    {
1911
 
        while (anzLines--)
1912
 
        {
1913
 
            if (ptr[anzLines])
1914
 
                delete ptr[anzLines];
1915
 
        }
1916
 
        delete[] ptr;
1917
 
    }
1918
 
}
1919
 
 
1920
 
 
1921
 
 
1922
 
void cacheLinePool::Delete(int lineNo)
1923
 
{
1924
 
    if (ptr && lineNo >= 0 && lineNo < anzLines)
1925
 
    {
1926
 
#if 1
1927
 
        if (ptr[lineNo])
1928
 
            delete ptr[lineNo];
1929
 
 
1930
 
        if (lineNo < anzLines-1)
1931
 
        {
1932
 
            // beware: overlapping copy
1933
 
            memmove(ptr+lineNo, ptr+lineNo+1, sizeof(cacheLine*) * (anzLines-lineNo-1));
1934
 
        }
1935
 
#else
1936
 
        cacheLine *c;
1937
 
        c=ptr[0];
1938
 
        ptr[0]=ptr[1];
1939
 
        ptr[1]=c;
1940
 
#endif
1941
 
        ptr[anzLines-1]=0;
1942
 
    }
1943
 
}
1944
 
 
1945
 
 
1946
 
cacheLine *cacheLinePool::Get(int lineNo)
1947
 
{
1948
 
    if (lineNo < 0) return 0;
1949
 
 
1950
 
    if (lineNo >= anzLines)
1951
 
    {
1952
 
        cacheLine **old=ptr;
1953
 
        int oldAnz=anzLines;
1954
 
        anzLines=lineNo+100;
1955
 
        ptr=new cacheLine*[anzLines];
1956
 
        if (!ptr)
1957
 
        {
1958
 
            anzLines=0;
1959
 
            wxLogError(__("Out of Memory for cacheLinePool"));
1960
 
        }
1961
 
        else
1962
 
        {
1963
 
            if (oldAnz)
1964
 
            {
1965
 
                memcpy(ptr, old, sizeof(cacheLine*)*oldAnz);
1966
 
                delete[] old;
1967
 
            }
1968
 
            memset(ptr+oldAnz, 0, anzLines-oldAnz);
1969
 
        }
1970
 
    }
1971
 
 
1972
 
    if (lineNo < anzLines)
1973
 
    {
1974
 
        if (!ptr[lineNo])
1975
 
            ptr[lineNo] = new cacheLine();
1976
 
        return ptr[lineNo];
1977
 
    }
1978
 
    return 0;
1979
 
}
1980
 
 
1981
 
 
1982
 
bool cacheLinePool::IsFilled(int lineNo)
1983
 
{
1984
 
    return (lineNo < anzLines && ptr[lineNo]);
1985
 
}
1986
 
 
1987
 
 
1988
 
bool editGridFactoryBase::CheckEnable(pgObject *obj)
1989
 
{
1990
 
    if (obj)
1991
 
    {
1992
 
        pgaFactory *factory=obj->GetFactory();
1993
 
        return factory == &tableFactory || factory == &viewFactory;
1994
 
    }
1995
 
    return false;
1996
 
}
1997
 
 
1998
 
 
1999
 
wxWindow *editGridFactoryBase::ViewData(frmMain *form, pgObject *obj, bool filter)
2000
 
{
2001
 
    pgDatabase *db=((pgSchemaObject*)obj)->GetDatabase();
2002
 
 
2003
 
    pgServer *server=db->GetServer();
2004
 
    pgConn *conn= db->CreateConn();
2005
 
    if (conn)
2006
 
    {
2007
 
        wxString txt = wxT("pgAdmin III Edit Data - ")
2008
 
            + server->GetDescription() 
2009
 
            + wxT(" (") + server->GetName() 
2010
 
            + wxT(":") + NumToStr((long)server->GetPort()) 
2011
 
            + wxT(") - ") + db->GetName()
2012
 
            + wxT(" - ") + obj->GetFullIdentifier();
2013
 
 
2014
 
        frmEditGrid *eg= new frmEditGrid(form, txt, conn, (pgSchemaObject*)obj);
2015
 
        eg->ShowForm(filter);
2016
 
        return eg;
2017
 
    }
2018
 
    return 0;
2019
 
}
2020
 
 
2021
 
 
2022
 
editGridFactory::editGridFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) : editGridFactoryBase(list)
2023
 
{
2024
 
    mnu->Append(id, _("View &Data"), _("View the data in the selected object."));
2025
 
    toolbar->AddTool(id, _("View Data"), wxBitmap(viewdata_xpm), _("View the data in the selected object."), wxITEM_NORMAL);
2026
 
}
2027
 
 
2028
 
 
2029
 
wxWindow *editGridFactory::StartDialog(frmMain *form, pgObject *obj)
2030
 
{
2031
 
    return ViewData(form, obj, false);
2032
 
}
2033
 
 
2034
 
 
2035
 
#include "images/viewfiltereddata.xpm"
2036
 
editGridFilteredFactory::editGridFilteredFactory(menuFactoryList *list, wxMenu *mnu, wxToolBar *toolbar) : editGridFactoryBase(list)
2037
 
{
2038
 
    mnu->Append(id, _("View F&iltered Data"), _("Apply a filter and view the data in the selected object."));
2039
 
    toolbar->AddTool(id, _("View Filtered Data"), wxBitmap(viewfiltereddata_xpm), _("Apply a filter and view the data in the selected object."), wxITEM_NORMAL);
2040
 
}
2041
 
 
2042
 
 
2043
 
wxWindow *editGridFilteredFactory::StartDialog(frmMain *form, pgObject *obj)
2044
 
{
2045
 
    return ViewData(form, obj, true);
2046
 
}
2047