Index: src/ctl/ctlSQLResult.cpp =================================================================== --- src/ctl/ctlSQLResult.cpp (revision 4990) +++ src/ctl/ctlSQLResult.cpp (working copy) @@ -11,6 +11,7 @@ // wxWindows headers #include +#include #include "pgConn.h" #include "ctl/ctlSQLResult.h" @@ -20,10 +21,17 @@ ctlSQLResult::ctlSQLResult(wxWindow *parent, pgConn *_conn, wxWindowID id, const wxPoint& pos, const wxSize& size) -: wxListView(parent, id, pos, size, wxLC_REPORT | wxSUNKEN_BORDER) +: wxGrid(parent, id, pos, size, wxWANTS_CHARS|wxVSCROLL|wxHSCROLL) { conn=_conn; thread=0; + CreateGrid(0, 0); + EnableEditing(false); + SetSizer(new wxBoxSizer(wxVERTICAL)); + + wxFont fntLabel(settings->GetSystemFont()); + fntLabel.SetWeight(wxBOLD); + SetLabelFont(fntLabel); } @@ -40,12 +48,6 @@ } -void ctlSQLResult::SelectAll() -{ - for (int i = 0; i < GetItemCount(); i++) - Select(i); -} - bool ctlSQLResult::Export() { if (rowsRetrieved>0 || (thread && thread->DataSet()->NumRows() > 0)) @@ -66,23 +68,46 @@ wxString ctlSQLResult::GetExportLine(int row) { - if (GetColumnCount() <= 1) + return GetExportLine(row, 0, GetNumberCols() - 1); +} + +wxString ctlSQLResult::GetExportLine(int row, int col1, int col2) +{ + wxArrayInt cols; + wxString str; + int i; + + if (col2 < col1) + return str; + + cols.Alloc(col2 - col1 + 1); + for (i = col1; i <= col2; i++) { + cols.Add(i); + } + + return GetExportLine(row, cols); +} + + +wxString ctlSQLResult::GetExportLine(int row, wxArrayInt cols) +{ + if (GetNumberCols() <= 1) return GetItemText(row); wxString str; - int col; - for (col=1 ; col < GetColumnCount() ; col++) + unsigned int col; + for (col=0 ; col < cols.Count() ; col++) { - if (col > 1) + if (col > 0) str.Append(settings->GetCopyColSeparator()); - wxString text=GetItemText(row, col); + wxString text = GetCellValue(row, cols[col]); bool needQuote = false; if (settings->GetCopyQuoting() == 1) { /* Quote strings only */ - switch (colTypClasses.Item(col)) + switch (colTypClasses.Item(cols[col])) { case PGTYPCLASS_NUMERIC: case PGTYPCLASS_BOOL: @@ -112,20 +137,27 @@ colSizes.Empty(); colHeaders.Empty(); + int num; + +#if 0 + /* Seems pointless to me... */ int i; - wxListItem item; - item.SetMask(wxLIST_MASK_TEXT|wxLIST_MASK_WIDTH); - - for (i=0 ; i < GetColumnCount() ; i++) + for (i=0 ; i < GetNumberCols() ; i++) { - GetColumn(i, item); - colHeaders.Add(item.GetText()); - colSizes.Add(item.GetWidth()); + colHeaders.Add(GetColLabelValue(i)); + colSizes.Add(GetColSize(i)); } +#endif - ClearAll(); + num = GetNumberRows(); + if (num) + DeleteRows(0, num); + num = GetNumberCols(); + if (num) + DeleteCols(0, num); rowsRetrieved=0; + maxRows = 0; colNames.Empty(); colTypes.Empty(); colTypClasses.Empty(); @@ -165,22 +197,17 @@ if (!rowsRetrieved) { - int w, h; - if (colSizes.GetCount() == 1) - w = colSizes.Item(0); - else - GetSize(&w, &h); - colNames.Add(thread->DataSet()->ColName(0)); colTypes.Add(wxT("")); colTypClasses.Add(0L); - InsertColumn(0, thread->DataSet()->ColName(0), wxLIST_FORMAT_LEFT, w); + SetColLabelValue(0, thread->DataSet()->ColName(0)); + SetColLabelAlignment(wxALIGN_LEFT, wxALIGN_TOP); while (!thread->DataSet()->Eof()) { - InsertItem(rowsRetrieved, thread->DataSet()->GetVal(0)); + SetCellValue(rowsRetrieved, 0, thread->DataSet()->GetVal(0)); rowsRetrieved++; thread->DataSet()->MoveNext(); } @@ -207,8 +234,16 @@ colTypClasses.Add(0L); Freeze(); - InsertColumn(0, _("Row"), wxLIST_FORMAT_RIGHT, 30); - colNames.Add(wxT("Row")); + + if (!GetTable()) { + SetTable(new sqlResultTable(), true); + } + GetTable()->AppendCols(nCols); + SetColLabelAlignment(wxALIGN_LEFT, wxALIGN_TOP); + if (maxRows) + GetTable()->AppendRows(maxRows); + else + GetTable()->AppendRows(NumRows()); size_t hdrIndex=0; @@ -220,7 +255,7 @@ colTypes.Add(colType); colTypClasses.Add(thread->DataSet()->ColTypClass(col)); - wxString colHeader=colName +wxT(" (")+ colType +wxT(")"); + wxString colHeader = colName + wxT("\n") + colType; int w; if (hdrIndex < colHeaders.GetCount() && colHeaders.Item(hdrIndex) == colHeader) @@ -236,8 +271,10 @@ w=-1; } - InsertColumn(col+1, colHeader, wxLIST_FORMAT_LEFT, w); + SetColLabelValue(col, colHeader); + SetColSize(col, w); } + SetColLabelSize(GetColLabelSize() + 6); Thaw(); } @@ -246,8 +283,6 @@ while (chunk-- && !thread->DataSet()->Eof()) { - InsertItem(rowsRetrieved, NumToStr(rowsRetrieved+1L)); - for (col=0 ; col < nCols ; col++) { wxString value = thread->DataSet()->GetVal(col); @@ -256,7 +291,7 @@ if ((int)value.Length() > maxColSize) value = value.Left(maxColSize) + wxT(" (..)"); } - SetItem(rowsRetrieved, col+1, value); + GetTable()->SetValue(rowsRetrieved, col, value); } thread->DataSet()->MoveNext(); @@ -272,14 +307,9 @@ wxString ctlSQLResult::GetItemText(int row, int col) { if (col < 0) - return wxListCtrl::GetItemText(row); - - wxListItem item; - item.m_mask=wxLIST_MASK_TEXT; - item.m_itemId=row; - item.m_col=col; - GetItem(item); - return item.GetText(); + return GetExportLine(row); + else + return GetCellValue(row, col); } @@ -334,3 +364,168 @@ } +void ctlSQLResult::Copy() +{ + wxString str; + int copied = 0; + size_t i; + + if (GetSelectedRows().GetCount()) { + wxArrayInt rows = GetSelectedRows(); + + for (i=0 ; i < rows.GetCount() ; i++) + { + str.Append(GetExportLine(rows.Item(i))); + + if (rows.GetCount() > 1) + str.Append(END_OF_LINE); + } + + copied = rows.GetCount(); + } + else if (GetSelectedCols().GetCount()) { + wxArrayInt cols = GetSelectedCols(); + size_t numRows = GetNumberRows(); + + for (i=0 ; i < numRows ; i++) + { + str.Append(GetExportLine(i, cols)); + + if (numRows > 1) + str.Append(END_OF_LINE); + } + + copied = numRows; + } + else if (GetSelectionBlockTopLeft().GetCount() > 0 && + GetSelectionBlockBottomRight().GetCount() > 0) { + unsigned int x1, x2, y1, y2; + + x1 = GetSelectionBlockTopLeft()[0].GetCol(); + x2 = GetSelectionBlockBottomRight()[0].GetCol(); + y1 = GetSelectionBlockTopLeft()[0].GetRow(); + y2 = GetSelectionBlockBottomRight()[0].GetRow(); + + for (i = y1; i <= y2; i++) { + str.Append(GetExportLine(i, x1, x2)); + + if (y2 > y1) + str.Append(END_OF_LINE); + } + + copied = y2 - y1 + 1; + } + else { + int row, col; + + row = GetGridCursorRow(); + col = GetGridCursorCol(); + + str.Append(GetExportLine(row, col, col)); + copied = 1; + } + + if (copied && wxTheClipboard->Open()) + { + wxTheClipboard->SetData(new wxTextDataObject(str)); + wxTheClipboard->Close(); + } +} + +void ctlSQLResult::SetMaxRows(int rows) +{ + maxRows = rows; +} + +void ctlSQLResult::ResultsFinished() +{ + int rows = GetTable()->GetNumberRows(); + + if (rowsRetrieved < rows) { + GetTable()->DeleteRows(rowsRetrieved, rows - rowsRetrieved); + } +} + +sqlResultTable::sqlResultTable() +{ + nRows = nCols = 0; + values = 0; +} + +sqlResultTable::~sqlResultTable() +{ + values.Clear(); +} + +int sqlResultTable::GetNumberRows() +{ + return nRows; +} + +int sqlResultTable::GetNumberCols() +{ + return nCols; +} + +bool sqlResultTable::AppendCols(size_t numCols) +{ + if (values.Count()) { + values.Clear(); + nRows = 0; + } + + nCols = numCols; + return true; +} + +bool sqlResultTable::AppendRows(size_t numRows) +{ + if (numRows <= 0) + return false; + + values.Add(wxT(""), nCols * numRows); + nRows += numRows; + return true; +} + +void sqlResultTable::SetValue(int row, int col, const wxString& s) +{ + if (row < 0 || row >= nRows) + return; + + if (col < 0 || col >= nCols) + return; + + values[row * nCols + col] = s; +} + +wxString sqlResultTable::GetValue(int row, int col) +{ + if (row < 0 || row >= nRows) + return wxT(""); + + if (col < 0 || col >= nCols) + return wxT(""); + + return values[row * nCols + col]; +} + +bool sqlResultTable::IsEmptyCell(int row, int col) +{ + return false; +} + +bool sqlResultTable::DeleteRows(size_t pos, size_t numRows) +{ + if (pos >= (size_t)nRows) + return false; + + values.RemoveAt(pos, numRows); + + if (pos + numRows > (size_t)nRows) + nRows = pos; + else + nRows -= numRows; + + return true; +} Index: src/frm/frmExport.cpp =================================================================== --- src/frm/frmExport.cpp (revision 4990) +++ src/frm/frmExport.cpp (working copy) @@ -156,8 +156,8 @@ } else { - colCount = data->GetColumnCount(); - rowCount = data->GetItemCount(); + colCount = data->GetNumberCols(); + rowCount = data->GetNumberRows(); if (colCount > 1) // first col contains row count startCol=1; } Index: src/frm/frmQuery.cpp =================================================================== --- src/frm/frmQuery.cpp (revision 4990) +++ src/frm/frmQuery.cpp (working copy) @@ -590,27 +590,16 @@ msgResult->Copy(); else if (wnd == msgHistory) msgHistory->Copy(); - else if (wnd == sqlResult && sqlResult->GetSelectedItemCount() > 0) - { - wxString str; - int row=-1; - while (true) - { - row = sqlResult->GetNextItem(row, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - if (row < 0) + else { + wxWindow *obj = wnd; + + while (obj != NULL) { + if (obj == sqlResult) { + sqlResult->Copy(); break; - - str.Append(sqlResult->GetExportLine(row)); - if (sqlResult->GetSelectedItemCount() > 1) - str.Append(END_OF_LINE); + } + obj = obj->GetParent(); } - - if (wxTheClipboard->Open()) - { - wxTheClipboard->SetData(new wxTextDataObject(str)); - wxTheClipboard->Close(); - } - } updateMenu(); } @@ -1205,6 +1194,7 @@ break; } } + sqlResult->SetMaxRows(maxRows); wxLongLong startTimeRetrieve=wxGetLocalTimeMillis(); wxLongLong elapsed; elapsedRetrieve=0; @@ -1245,6 +1235,7 @@ wxYield(); } } + sqlResult->ResultsFinished(); if (resultFreezed) sqlResult->Thaw(); Index: src/include/ctl/ctlSQLResult.h =================================================================== --- src/include/ctl/ctlSQLResult.h (revision 4990) +++ src/include/ctl/ctlSQLResult.h (working copy) @@ -13,7 +13,7 @@ #define CTLSQLRESULT_H // wxWindows headers -#include +#include #include #include "pgSet.h" @@ -24,7 +24,7 @@ #define CTLSQL_RUNNING 100 // must be greater than ExecStatusType PGRES_xxx values -class ctlSQLResult : public wxListView +class ctlSQLResult : public wxGrid { public: ctlSQLResult(wxWindow *parent, pgConn *conn, wxWindowID id, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize); @@ -41,18 +41,22 @@ int RetrieveOne(); int Abort(); - void SelectAll(); - bool Export(); bool CanExport() { return rowsRetrieved>0 && colNames.GetCount() > 0; } wxString GetItemText(int row, int col=-1); wxString GetExportLine(int row); + wxString GetExportLine(int row, wxArrayInt cols); + wxString GetExportLine(int row, int col1, int col2); + void Copy(); int RunStatus(); wxString GetMessagesAndClear(); wxString GetErrorMessage(); + void SetMaxRows(int rows); + void ResultsFinished(); + wxArrayString colNames; wxArrayString colTypes; wxArrayLong colTypClasses; @@ -64,6 +68,27 @@ pgQueryThread *thread; pgConn *conn; long rowsRetrieved; + int maxRows; }; +class sqlResultTable : public wxGridTableBase +{ +public: + sqlResultTable(); + ~sqlResultTable(); + int GetNumberRows(); + int GetNumberCols(); + bool AppendCols(size_t numCols); // NOTE: Replaces cols rather than appends + bool AppendRows(size_t numRows); + void SetValue(int row, int col, const wxString& s); + wxString GetValue(int row, int col); + bool IsEmptyCell(int row, int col); + bool DeleteRows(size_t pos = 0, size_t numRows = 1); + +private: + int nRows; + int nCols; + wxArrayString values; +}; + #endif