Merge 4ec263414d into 74949e0861
This commit is contained in:
commit
bae053c8e9
|
|
@ -0,0 +1,21 @@
|
|||
import 'dart:io';
|
||||
|
||||
class VmConfig {
|
||||
final String name;
|
||||
final File file;
|
||||
String rawContent = '';
|
||||
|
||||
VmConfig({required this.name, required String confPath})
|
||||
: file = File(confPath);
|
||||
|
||||
Future<void> load() async {
|
||||
if (file.existsSync()) {
|
||||
rawContent = await file.readAsString();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> save(String updatedContent) async {
|
||||
rawContent = updatedContent;
|
||||
await file.writeAsString(rawContent);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import '../globals.dart';
|
|||
import '../mixins/preferences_mixin.dart';
|
||||
import '../model/osicons.dart';
|
||||
import '../model/vminfo.dart';
|
||||
import '../pages/vm_config_editor.dart';
|
||||
|
||||
/// VM manager page.
|
||||
/// Displays a list of available VMs, running state and connection info,
|
||||
|
|
@ -28,6 +29,7 @@ class Manager extends StatefulWidget {
|
|||
|
||||
class _ManagerState extends State<Manager> with PreferencesMixin {
|
||||
List<String> _currentVms = [];
|
||||
Map<String, String> _vmConfFiles = {};
|
||||
Map<String, VmInfo> _activeVms = {};
|
||||
bool _spicy = false;
|
||||
final List<String> _sshVms = [];
|
||||
|
|
@ -146,6 +148,7 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
|
|||
|
||||
void _getVms(context) async {
|
||||
List<String> currentVms = [];
|
||||
Map<String, String> vmConfFiles = {};
|
||||
Map<String, VmInfo> activeVms = {};
|
||||
|
||||
await for (var entity
|
||||
|
|
@ -153,6 +156,7 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
|
|||
if ((entity.path.endsWith('.conf')) && (_isValidConf(entity.path))) {
|
||||
String name = path.basenameWithoutExtension(entity.path);
|
||||
currentVms.add(name);
|
||||
vmConfFiles[name] = entity.path;
|
||||
File pidFile = File('$name/$name.pid');
|
||||
if (pidFile.existsSync()) {
|
||||
String pid = pidFile.readAsStringSync().trim();
|
||||
|
|
@ -172,6 +176,7 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
|
|||
currentVms.sort();
|
||||
setState(() {
|
||||
_currentVms = currentVms;
|
||||
_vmConfFiles = vmConfFiles;
|
||||
_activeVms = activeVms;
|
||||
});
|
||||
}
|
||||
|
|
@ -291,6 +296,21 @@ class _ManagerState extends State<Manager> with PreferencesMixin {
|
|||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings, semanticLabel: 'Settings'),
|
||||
tooltip: context.t('Edit configuration'),
|
||||
onPressed: active
|
||||
? null
|
||||
: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => VmConfigEditorDialog(
|
||||
vmName: currentVm,
|
||||
confPath: _vmConfFiles[currentVm]!,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
active ? Icons.play_arrow : Icons.play_arrow_outlined,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import '../model/vm_config.dart';
|
||||
|
||||
class VmConfigEditorDialog extends StatefulWidget {
|
||||
final String vmName;
|
||||
final String confPath;
|
||||
|
||||
const VmConfigEditorDialog({
|
||||
super.key,
|
||||
required this.vmName,
|
||||
required this.confPath,
|
||||
});
|
||||
|
||||
@override
|
||||
State<VmConfigEditorDialog> createState() => _VmConfigEditorDialogState();
|
||||
}
|
||||
|
||||
class _VmConfigEditorDialogState extends State<VmConfigEditorDialog> {
|
||||
late VmConfig config;
|
||||
final TextEditingController _editorController = TextEditingController();
|
||||
bool _loading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
config = VmConfig(name: widget.vmName, confPath: widget.confPath);
|
||||
config.load().then((_) {
|
||||
_editorController.text = config.rawContent;
|
||||
setState(() => _loading = false);
|
||||
});
|
||||
}
|
||||
|
||||
void _save() async {
|
||||
await config.save(_editorController.text);
|
||||
if(!mounted) return;
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
void _openDocs() async {
|
||||
const url = 'https://github.com/quickemu-project/quickemu/blob/master/docs/quickemu_conf.5.md';
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Edit VM: ${widget.vmName}'),
|
||||
content: _loading
|
||||
? const SizedBox(height: 100, child: Center(child: CircularProgressIndicator()))
|
||||
: SizedBox(
|
||||
width: double.maxFinite,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(config.file.path,
|
||||
style: const TextStyle(fontSize: 12, color: Colors.grey)),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton.icon(
|
||||
icon: const Icon(Icons.help_outline),
|
||||
label: const Text("Open config documentation"),
|
||||
onPressed: _openDocs,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
controller: _editorController,
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: const TextStyle(fontFamily: 'monospace'),
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
contentPadding: EdgeInsets.all(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: _save,
|
||||
child: const Text('Save'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue