feat(linux): add result grid context menu with Copy as and Export Results dialog - #1
Open
Seha16 wants to merge 5 commits into
Open
feat(linux): add result grid context menu with Copy as and Export Results dialog#1Seha16 wants to merge 5 commits into
Seha16 wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
There are confirmed correctness and performance issues in the new export and grid-edit flows that should be addressed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adds a Linux result-grid context menu and a new Export Results dialog, and moves export rendering into tablepro_core so exports are not truncated by grid display formatting.
Changes:
- Added shared result-grid context menus across browse tables and SQL editor results, including Copy variants, row JSON, and Export Results.
- Implemented an Export Results dialog (CSV and JSON) with persisted CSV options in
preferences.json. - Introduced pure export renderers in
linux/crates/core(CSV, TSV, JSON, Markdown, IN clause) with unit tests, and enabled ordered JSON output viaserde_jsonpreserve_order.
File summaries
| File | Description |
|---|---|
| linux/ROADMAP.md | Updates roadmap to mark context menu and export items as complete and list follow-ups. |
| linux/po/POTFILES.in | Adds the new export dialog source file to translation inputs. |
| linux/crates/core/src/lib.rs | Exposes the new export module publicly. |
| linux/crates/core/src/export.rs | Adds core export renderers and unit tests for CSV, TSV, JSON, Markdown, and IN-clause output. |
| linux/crates/app/src/ui/preferences.rs | Plumbs csv_export into preferences saving from the Preferences dialog. |
| linux/crates/app/src/ui/mod.rs | Registers the new export_dialog UI module. |
| linux/crates/app/src/ui/grid.rs | Implements shared grid context menus and adds actions for Copy-as variants, row JSON, set value, and export. |
| linux/crates/app/src/ui/export_dialog.rs | Adds the Export Results dialog UI and file-save flow. |
| linux/crates/app/src/ui/editor.rs | Enables grid context-menu routing from SQL editor result grids via a GridMsg channel. |
| linux/crates/app/src/ui/browse_tab.rs | Wires new grid messages (set value, export) and adds paginator export button behavior. |
| linux/crates/app/src/ui/app/workspace_tabs.rs | Forwards editor and browse export/copy outputs into app-level messages. |
| linux/crates/app/src/ui/app/mod.rs | Replaces old export actions with a unified ExportResults message and presents the new dialog. |
| linux/crates/app/src/ui/app/browse.rs | Removes the old export implementation that built bytes directly in the app layer. |
| linux/crates/app/src/services/preferences.rs | Adds csv_export to the persisted Preferences model with defaults. |
| linux/Cargo.toml | Enables serde_json preserve_order to keep JSON column order stable. |
| linux/Cargo.lock | Updates lockfile for serde_json feature changes and new dependencies. |
Review details
- Files reviewed: 15/16 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+2150
to
+2154
| if let Some(row_obj) = self.row_object_at(row_position) | ||
| && let Some(draft_id) = row_obj.draft_id() | ||
| { | ||
| crate::services::change_tracker::with_tab(self.tab_id, |t| { | ||
| t.track_draft_cell_edit(draft_id, col_index, value.clone()); |
Comment on lines
164
to
178
| let save_all: std::rc::Rc<dyn Fn()> = { | ||
| let page_size = page_size_row.clone(); | ||
| let confirm = confirm_row.clone(); | ||
| let font = font_size_row.clone(); | ||
| let retention = retention_row.clone(); | ||
| let timeout = timeout_row.clone(); | ||
| std::rc::Rc::new(move || { | ||
| preferences::save(&Preferences { | ||
| default_page_size: page_size.value() as u64, | ||
| confirm_destructive: confirm.is_active(), | ||
| editor_font_size: font.value() as u32, | ||
| history_retention_days: retention.value() as u32, | ||
| query_timeout_secs: timeout.value() as u32, | ||
| csv_export: preferences::load().csv_export, | ||
| }); |
Comment on lines
+188
to
+192
| if opts.header_row { | ||
| let header: Vec<String> = columns.iter().map(|c| escape_field(&c.name, opts, false)).collect(); | ||
| out.push_str(&header.join(delim)); | ||
| out.push_str(line_break); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
adw::Dialog) with a format picker (CSV, JSON) and CSV options that match the macOS app: convert NULL to empty, convert line breaks to spaces, field names in first row, sanitize formula-like values, delimiter, quote mode, line break, decimal separator. Reset to Defaults. Options persist inpreferences.json.tablepro_core::exportwith unit tests. The oldrender_csvin the app went through the grid's display formatter, so it truncated text at 10k chars and wrote theNULLsentinel into files; the new path renders full values.serde_jsongetspreserve_orderso JSON output keeps column order.Deferred to follow-up PRs: Paste rows, Set Value > NOW() / CURRENT_TIMESTAMP (needs a raw SQL expression marker in the change tracker), SQL / Markdown / HTML / XML / XLSX file export.
Test plan
./scripts/ci-local.sh(fmt, clippy-D warnings, build, 338 unit tests; 21 new for the renderers)"and a=SUM(A1)value. Right-clicking on the editor result grid shows the read-only menu; on a table tab, it shows the full menu.preferences.jsonon change, Reset to Defaults restores defaults, Export writes the file and shows the toast. Output with semicolon + line breaks to spaces:2;has,comma;'-2.25;"line1 line2";falseand3;'=SUM(A1);10;"say ""hi""";false.