Skip to content

Commit 53937cf

Browse files
committed
0.10.0.35: Multi-row select in grid view, multi-row selection delete in table editor. Supports discontiguous selection with Ctrl+Tap.
1 parent f6907f3 commit 53937cf

2 files changed

Lines changed: 78 additions & 39 deletions

File tree

src/sqlite-ce-edit/globals.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ BOOL WINAPI GetSaveFileNameW(CE_OPENFILENAME*);
8787
** Version
8888
**============================================================================*/
8989

90-
#define SQLITECEDIT_VERSION L"0.10.0.33"
90+
#define SQLITECEDIT_VERSION L"0.10.0.35"
9191

9292
/*============================================================================
9393
** Menu IDs

src/sqlite-ce-edit/grid.c

Lines changed: 77 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void CreateGridView(HWND hwndParent, int x, int y, int cx, int cy) {
3333
HIMAGELIST hIml;
3434

3535
g_hwndGrid = CreateWindowExW(0, WC_LISTVIEWW, NULL,
36-
WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_OWNERDATA,
36+
WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_OWNERDATA,
3737
x, y, cx, cy, hwndParent, (HMENU)IDC_GRID, g_hInst, NULL);
3838

3939
/* Enable full row select and grid lines */
@@ -181,12 +181,9 @@ LRESULT CALLBACK GridProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
181181
}
182182
return 0;
183183
}
184-
/* Delete - Delete selected row (only in edit mode, not placeholder) */
184+
/* Delete - Delete selected rows (only in edit mode) */
185185
if (wParam == VK_DELETE && g_editMode) {
186-
int sel = ListView_GetNextItem(g_hwndGrid, -1, LVNI_SELECTED);
187-
if (sel >= 0 && sel < g_lastResultRows) {
188-
DeleteSelectedRow();
189-
}
186+
DeleteSelectedRow();
190187
return 0;
191188
}
192189
/* Escape - Cancel insert mode if active (when not in cell edit) */
@@ -794,17 +791,24 @@ static void CancelCellEdit(void) {
794791
}
795792

796793
static void DeleteSelectedRow(void) {
797-
int sel, dataRow, rowidIdx;
794+
int sel, count, dataRow, rowidIdx, deleted, i;
798795
char *rowid;
799796
char sql[256];
800797
char tableName[128];
801798
char *p;
802799
const char *s;
803800
char *errmsg = NULL;
804801
int rc;
805-
806-
sel = ListView_GetNextItem(g_hwndGrid, -1, LVNI_SELECTED);
807-
if (sel < 0) return;
802+
wchar_t msg[64];
803+
char **rowids;
804+
805+
/* Count selected rows (excluding placeholder) */
806+
count = 0;
807+
sel = -1;
808+
while ((sel = ListView_GetNextItem(g_hwndGrid, sel, LVNI_SELECTED)) >= 0) {
809+
if (sel < g_lastResultRows) count++;
810+
}
811+
if (count < 1) return;
808812

809813
/* Save table name before it gets cleared */
810814
s = g_editTableName;
@@ -813,43 +817,78 @@ static void DeleteSelectedRow(void) {
813817
*p = '\0';
814818

815819
/* Confirm deletion */
816-
if (MessageBoxW(g_hwndMain, L"Delete this row?", L"Confirm Delete",
820+
if (count == 1)
821+
lstrcpyW(msg, L"Delete this row?");
822+
else
823+
wsprintfW(msg, L"Delete %d rows?", count);
824+
if (MessageBoxW(g_hwndMain, msg, L"Confirm Delete",
817825
MB_YESNO | MB_ICONQUESTION) != IDYES)
818826
return;
819827

820-
/* Get rowid */
821-
dataRow = g_sortIndex ? g_sortIndex[sel] : sel;
822-
rowidIdx = (dataRow + 1) * g_lastResultCols;
823-
rowid = g_lastResult[rowidIdx];
824-
825-
if (!rowid) return;
826-
827-
/* Build DELETE statement */
828-
p = sql;
829-
s = "DELETE FROM \"";
830-
while (*s) *p++ = *s++;
831-
s = tableName;
832-
while (*s) *p++ = *s++;
833-
s = "\" WHERE rowid = ";
834-
while (*s) *p++ = *s++;
835-
s = rowid;
836-
while (*s) *p++ = *s++;
837-
*p++ = ';';
838-
*p = '\0';
828+
/* Collect rowids first (data will be freed on re-query) */
829+
rowids = (char **)LocalAlloc(LMEM_FIXED, count * sizeof(char *));
830+
if (!rowids) return;
831+
832+
i = 0;
833+
sel = -1;
834+
while ((sel = ListView_GetNextItem(g_hwndGrid, sel, LVNI_SELECTED)) >= 0) {
835+
int j, len;
836+
if (sel >= g_lastResultRows) continue;
837+
dataRow = g_sortIndex ? g_sortIndex[sel] : sel;
838+
rowidIdx = (dataRow + 1) * g_lastResultCols;
839+
rowid = g_lastResult[rowidIdx];
840+
if (rowid && i < count) {
841+
len = 0;
842+
while (rowid[len]) len++;
843+
rowids[i] = (char *)LocalAlloc(LMEM_FIXED, len + 1);
844+
if (rowids[i]) {
845+
for (j = 0; j <= len; j++) rowids[i][j] = rowid[j];
846+
i++;
847+
}
848+
}
849+
}
850+
count = i; /* Actual count collected */
839851

840-
/* Execute DELETE */
841-
rc = sqlite_exec(g_db, sql, NULL, NULL, &errmsg);
852+
/* Delete by rowid */
853+
deleted = 0;
854+
for (i = 0; i < count; i++) {
855+
p = sql;
856+
s = "DELETE FROM \"";
857+
while (*s) *p++ = *s++;
858+
s = tableName;
859+
while (*s) *p++ = *s++;
860+
s = "\" WHERE rowid = ";
861+
while (*s) *p++ = *s++;
862+
s = rowids[i];
863+
while (*s) *p++ = *s++;
864+
*p++ = ';';
865+
*p = '\0';
866+
867+
rc = sqlite_exec(g_db, sql, NULL, NULL, &errmsg);
868+
if (rc != SQLITE_OK) {
869+
wchar_t wmsg[256];
870+
MultiByteToWideChar(CP_ACP, 0, errmsg ? errmsg : "Unknown error", -1, wmsg, 256);
871+
MessageBoxW(g_hwndMain, wmsg, L"Delete Failed", MB_OK | MB_ICONERROR);
872+
if (errmsg) sqlite_freemem(errmsg);
873+
break;
874+
}
875+
deleted++;
876+
}
842877

843-
if (rc != SQLITE_OK) {
844-
wchar_t wmsg[256];
845-
MultiByteToWideChar(CP_ACP, 0, errmsg ? errmsg : "Unknown error", -1, wmsg, 256);
846-
MessageBoxW(g_hwndMain, wmsg, L"Delete Failed", MB_OK | MB_ICONERROR);
847-
if (errmsg) sqlite_freemem(errmsg);
848-
return;
878+
/* Free rowid copies */
879+
for (i = 0; i < count; i++) {
880+
if (rowids[i]) LocalFree(rowids[i]);
849881
}
882+
LocalFree(rowids);
850883

851884
/* Re-query to refresh grid */
852885
OpenTableForEditing(tableName);
886+
887+
/* Status feedback */
888+
if (deleted > 0) {
889+
wsprintfW(msg, L"%d row%s deleted", deleted, deleted == 1 ? L"" : L"s");
890+
SendMessageW(g_hwndStatus, SB_SETTEXTW, 1, (LPARAM)msg);
891+
}
853892
}
854893

855894
/*============================================================================

0 commit comments

Comments
 (0)