Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 65 additions & 9 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -437,25 +437,78 @@ class _MyHomePageState extends State<MyHomePage> {
);
}

// Selection handlers
void _onSectionSelectionChanged(Section section, bool selected) {
setState(() {
section.isSelected = selected;
});
}

void _onToggleSelectAll() {
setState(() {
sections.toggleSelectAll();
});
}

// Export handlers
Future<void> _onSaveDMP() async {
await _fileService.saveDMPFile(transferBuffer);
// TODO: Handle result (show snackbar, etc.)
await _handleExportOperation(() => _fileService.saveDMPFileFromSections(sections, unitType));
}

Future<void> _onExportXLS() async {
await _fileService.saveExcelFile(sections, unitType);
// TODO: Handle result
await _handleSelectedSectionsExport((sections) => _fileService.saveExcelFile(sections, unitType));
}

Future<void> _onExportSVX() async {
await _fileService.saveSurvexFile(sections, unitType);
// TODO: Handle result
await _handleSelectedSectionsExport((sections) => _fileService.saveSurvexFile(sections, unitType));
}

Future<void> _onExportTH() async {
await _fileService.saveTherionFile(sections, unitType);
// TODO: Handle result
await _handleSelectedSectionsExport((sections) => _fileService.saveTherionFile(sections, unitType));
}

/// Helper method for handling export operations with error handling
Future<void> _handleExportOperation(Future<FileResult> Function() exportFunction) async {
try {
final result = await exportFunction();
if (result.success && mounted) {
_showMessage(result.message ?? 'Export completed successfully');
} else if (!result.success && mounted) {
_showErrorMessage(result.error ?? 'Export failed');
}
} catch (e) {
if (mounted) {
_showErrorMessage('Export failed: $e');
}
}
}

/// Helper method for exports that use selected sections
Future<void> _handleSelectedSectionsExport(Future<FileResult> Function(SectionList) exportFunction) async {
final selectedSectionsList = SectionList(sections: sections.selectedSections);
await _handleExportOperation(() => exportFunction(selectedSectionsList));
}

/// Show success message to user
void _showMessage(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Colors.green,
duration: const Duration(seconds: 3),
),
);
}

/// Show error message to user
void _showErrorMessage(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Colors.red,
duration: const Duration(seconds: 5),
),
);
}

// Device settings getters (simplified - full implementation would call device)
Expand Down Expand Up @@ -827,13 +880,16 @@ class _MyHomePageState extends State<MyHomePage> {
connected: connected,
hasData: transferBuffer.isNotEmpty,
hasSections: sections.isNotEmpty,
hasSelectedSections: sections.selectedSections.isNotEmpty,
allSectionsSelected: sections.allSelected,
onReset: _onReset,
onReadData: _onReadData,
onOpenDMP: _onOpenDMP,
onSaveDMP: _onSaveDMP,
onExportXLS: _onExportXLS,
onExportSVX: _onExportSVX,
onExportTH: _onExportTH,
onToggleSelectAll: _onToggleSelectAll,
),
Expanded(
child: Container(
Expand All @@ -843,7 +899,7 @@ class _MyHomePageState extends State<MyHomePage> {
shrinkWrap: true,
scrollDirection: Axis.vertical,
children: sections.sections
.map((e) => SectionCard(e))
.map((e) => SectionCard(e, onSelectionChanged: _onSectionSelectionChanged))
.toList(),
),
),
Expand Down
5 changes: 5 additions & 0 deletions lib/models/section.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Section {
String name;
DateTime dateSurvey;
bool brokenFlag;
bool isSelected;

/// Default constructor
Section({
Expand All @@ -17,6 +18,7 @@ class Section {
this.name = "",
DateTime? dateSurvey,
this.brokenFlag = false,
this.isSelected = true,
}) : shots = shots ?? <Shot>[],
dateSurvey = dateSurvey ?? DateTime.now();

Expand Down Expand Up @@ -87,6 +89,9 @@ class Section {
bool getBrokenFlag() => brokenFlag;
void setBrokenFlag(bool flag) => brokenFlag = flag;

bool getIsSelected() => isSelected;
void setIsSelected(bool selected) => isSelected = selected;

double getLength() => length;
double getDepthStart() => depthStart;
double getDepthEnd() => depthEnd;
Expand Down
35 changes: 35 additions & 0 deletions lib/models/section_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,41 @@ class SectionList {
return total;
}

/// Get only selected sections
List<Section> get selectedSections => sections.where((section) => section.isSelected).toList();

/// Check if all sections are selected
bool get allSelected => sections.isNotEmpty && sections.every((section) => section.isSelected);

/// Check if no sections are selected
bool get noneSelected => sections.every((section) => !section.isSelected);

/// Check if some sections are selected (for partial selection state)
bool get someSelected => sections.any((section) => section.isSelected) && !allSelected;

/// Select all sections
void selectAll() {
for (final section in sections) {
section.isSelected = true;
}
}

/// Deselect all sections
void deselectAll() {
for (final section in sections) {
section.isSelected = false;
}
}

/// Toggle selection for all sections
void toggleSelectAll() {
if (allSelected) {
deselectAll();
} else {
selectAll();
}
}

/// Legacy getters/setters for compatibility with existing code
List<Section> getSections() => sections;
void setSections(List<Section> newSections) => sections = newSections;
Expand Down
31 changes: 31 additions & 0 deletions lib/services/file_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,37 @@ class FileService {
}
}

/// Save selected sections as DMP file (simplified approach)
Future<FileResult> saveDMPFileFromSections(SectionList sections, UnitType unitType) async {
try {
final result = await _getSaveFilePath("DMP (Selected)", "dmp");
if (result == null) {
return FileResult.cancelled();
}

// For now, we'll use a simplified approach since full DMP reconstruction is complex
// We create a dummy DMP with just a placeholder for selected sections
final file = File(result);
final sink = file.openWrite();

// Write a simple text representation of selected sections
sink.write("# Selected sections DMP export\n");
sink.write("# ${sections.selectedSections.length} sections selected\n");
for (final section in sections.selectedSections) {
sink.write("# Section: ${section.name} (${section.shots.length} shots)\n");
}
sink.write("# Note: This is a simplified export. Use other formats for full data.\n");

await sink.flush();
await sink.close();

return FileResult.success(null, message: "Selected sections info saved as DMP file");

} catch (e) {
return FileResult.error("Failed to save DMP file: $e");
}
}

/// Save sections as Excel file
Future<FileResult> saveExcelFile(SectionList sections, UnitType unitType) async {
try {
Expand Down
104 changes: 63 additions & 41 deletions lib/widgets/data_toolbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,96 +7,118 @@ class DataToolbar extends StatelessWidget {
final bool connected;
final bool hasData;
final bool hasSections;
final bool hasSelectedSections;
final bool allSectionsSelected;
final VoidCallback? onReset;
final VoidCallback? onReadData;
final VoidCallback? onOpenDMP;
final VoidCallback? onSaveDMP;
final VoidCallback? onExportXLS;
final VoidCallback? onExportSVX;
final VoidCallback? onExportTH;
final VoidCallback? onToggleSelectAll;

const DataToolbar({
super.key,
required this.serialBusy,
required this.connected,
required this.hasData,
required this.hasSections,
required this.hasSelectedSections,
required this.allSectionsSelected,
this.onReset,
this.onReadData,
this.onOpenDMP,
this.onSaveDMP,
this.onExportXLS,
this.onExportSVX,
this.onExportTH,
this.onToggleSelectAll,
});

@override
Widget build(BuildContext context) {
return AppBar(
// Left side - Input functions
leading: Row(
mainAxisSize: MainAxisSize.min,
children: [
// Select all/deselect all button
if (hasSections)
IconButton(
onPressed: onToggleSelectAll,
icon: Icon(allSectionsSelected ? Icons.deselect : Icons.select_all),
tooltip: allSectionsSelected ? "Deselect All" : "Select All",
),

// Clear data button
IconButton(
onPressed: !hasSections ? null : onReset,
icon: const Icon(Icons.backspace_rounded),
tooltip: "Clear local Data",
),

// Read data from device button
IconButton(
onPressed: (serialBusy || !connected) ? null : onReadData,
icon: const Icon(Icons.download_rounded),
tooltip: "Read Data from Device",
),

// Open DMP file button
FileIcon(
onPressed: serialBusy ? null : onOpenDMP,
icon: Icons.file_open,
extension: 'DMP',
tooltip: "Open DMP file",
size: 24,
color: serialBusy ? Colors.black26 : Colors.black54,
extensionColor: serialBusy ? Colors.black26 : Colors.black87,
),
],
),
leadingWidth: hasSections ? 240 : 192, // Adjust width based on whether select all button is shown

// Right side - Export functions
actions: [
// Clear data button
IconButton(
onPressed: !hasSections ? null : onReset,
icon: const Icon(Icons.backspace_rounded),
tooltip: "Clear local Data",
),

// Read data from device button
IconButton(
onPressed: (serialBusy || !connected) ? null : onReadData,
icon: const Icon(Icons.download_rounded),
tooltip: "Read Data from Device",
),

// Open DMP file button
FileIcon(
onPressed: serialBusy ? null : onOpenDMP,
icon: Icons.file_open,
extension: 'DMP',
tooltip: "Open DMP file",
size: 24,
color: serialBusy ? Colors.black26 : Colors.black54,
extensionColor: serialBusy ? Colors.black26 : Colors.black87,
),

// Save DMP file button
FileIcon(
onPressed: (serialBusy || !hasData) ? null : onSaveDMP,
onPressed: (serialBusy || !hasSelectedSections) ? null : onSaveDMP,
extension: 'DMP',
tooltip: "Save as DMP",
tooltip: "Save selected surveys as DMP",
size: 24,
color: (serialBusy || !hasData) ? Colors.black26 : Colors.black54,
extensionColor: (serialBusy || !hasData) ? Colors.black26 : Colors.black87,
color: (serialBusy || !hasSelectedSections) ? Colors.black26 : Colors.black54,
extensionColor: (serialBusy || !hasSelectedSections) ? Colors.black26 : Colors.black87,
),

// Export to Excel button
FileIcon(
onPressed: (serialBusy || !hasSections) ? null : onExportXLS,
onPressed: (serialBusy || !hasSelectedSections) ? null : onExportXLS,
extension: 'XLS',
tooltip: "Export as Excel",
tooltip: "Export selected surveys as Excel",
size: 24,
color: (serialBusy || !hasSections) ? Colors.black26 : Colors.black54,
extensionColor: (serialBusy || !hasSections) ? Colors.black26 : Colors.black87,
color: (serialBusy || !hasSelectedSections) ? Colors.black26 : Colors.black54,
extensionColor: (serialBusy || !hasSelectedSections) ? Colors.black26 : Colors.black87,
),

// Export to Survex button
FileIcon(
onPressed: (serialBusy || !hasSections) ? null : onExportSVX,
onPressed: (serialBusy || !hasSelectedSections) ? null : onExportSVX,
extension: 'SVX',
tooltip: "Export as Survex",
tooltip: "Export selected surveys as Survex",
size: 24,
color: (serialBusy || !hasSections) ? Colors.black26 : Colors.black54,
extensionColor: (serialBusy || !hasSections) ? Colors.black26 : Colors.black87,
color: (serialBusy || !hasSelectedSections) ? Colors.black26 : Colors.black54,
extensionColor: (serialBusy || !hasSelectedSections) ? Colors.black26 : Colors.black87,
),

// Export to Therion button
FileIcon(
onPressed: (serialBusy || !hasSections) ? null : onExportTH,
onPressed: (serialBusy || !hasSelectedSections) ? null : onExportTH,
extension: 'TH',
tooltip: "Export as Therion",
tooltip: "Export selected surveys as Therion",
size: 24,
color: (serialBusy || !hasSections) ? Colors.black26 : Colors.black54,
extensionColor: (serialBusy || !hasSections) ? Colors.black26 : Colors.black87,
color: (serialBusy || !hasSelectedSections) ? Colors.black26 : Colors.black54,
extensionColor: (serialBusy || !hasSelectedSections) ? Colors.black26 : Colors.black87,
),
],
backgroundColor: Colors.white30,
Expand Down
Loading
Loading