WIP
This commit is contained in:
parent
852d73ebc9
commit
0e082ac402
|
@ -26,3 +26,5 @@ doc/api/
|
|||
web/
|
||||
ios/
|
||||
android/
|
||||
windows/
|
||||
list.csv
|
|
@ -1,5 +1,10 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:quickgui/src/app.dart';
|
||||
import 'package:quickgui/src/model/operating_system.dart';
|
||||
import 'package:quiver/iterables.dart';
|
||||
import 'package:window_size/window_size.dart';
|
||||
|
||||
void main() async {
|
||||
|
@ -7,5 +12,45 @@ void main() async {
|
|||
setWindowTitle('Quickgui : a flutter frontend for Quickget and Quickemu');
|
||||
setWindowMinSize(const Size(692, 580));
|
||||
setWindowMaxSize(const Size(692, 580));
|
||||
var config = await loadOperatingSystems(false);
|
||||
|
||||
runApp(const App());
|
||||
}
|
||||
|
||||
Future<List<OperatingSystem>> loadOperatingSystems(bool showUbuntus) async {
|
||||
var file = File('list.csv');
|
||||
var fileExists = file.existsSync();
|
||||
if (fileExists) {
|
||||
Stream<String> lines = file
|
||||
.openRead()
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.skip(1);
|
||||
await for (var line in lines) {
|
||||
print(line);
|
||||
}
|
||||
return [];
|
||||
} else {
|
||||
return await Process.run('quickget', [])
|
||||
.then<List<OperatingSystem>>((process) {
|
||||
var stdout = process.stdout as String;
|
||||
var codes = stdout.split('\n')[1].split(' ').where((element) =>
|
||||
showUbuntus ? element.contains('buntu') : !element.contains('buntu'));
|
||||
var names = codes.map((code) => code
|
||||
.toLowerCase()
|
||||
.split('-')
|
||||
.map((e) => e[0].toUpperCase() + e.substring(1))
|
||||
.join(' '));
|
||||
List<OperatingSystem> items = [];
|
||||
if (!showUbuntus) {
|
||||
items.add(OperatingSystem(name: 'Ubuntu', hasMore: true));
|
||||
}
|
||||
items.addAll(zip([codes, names])
|
||||
.map((item) => OperatingSystem(code: item[0], name: item[1]))
|
||||
.toList());
|
||||
items.sort((a, b) => a.name.compareTo(b.name));
|
||||
|
||||
return items;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,13 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:quickgui/src/model/operating_system.dart';
|
||||
import 'package:quickgui/src/model/version.dart';
|
||||
import 'package:quickgui/src/pages/operating_system_selection.dart';
|
||||
import 'package:quickgui/src/pages/version_selection.dart';
|
||||
import 'package:quickgui/src/widgets/home_page_button.dart';
|
||||
import 'package:quickgui/src/widgets/home_page_buttons.dart';
|
||||
|
||||
class MainPage extends StatefulWidget {
|
||||
class MainPage extends StatelessWidget {
|
||||
const MainPage({Key? key, required this.title}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MainPage> createState() => _MainPageState();
|
||||
}
|
||||
|
||||
class _MainPageState extends State<MainPage> {
|
||||
OperatingSystem? _selectedOperatingSystem;
|
||||
Version? _selectedVersion;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
@ -45,62 +33,32 @@ class _MainPageState extends State<MainPage> {
|
|||
child: Container(
|
||||
color: Colors.pink,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
HomePageButton(
|
||||
label: "Operating system",
|
||||
text: _selectedOperatingSystem?.name ?? 'Select...',
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.push<OperatingSystem>(MaterialPageRoute(fullscreenDialog: true, builder: (context) => const OperatingSystemSelection()))
|
||||
.then((selection) {
|
||||
if (selection != null) {
|
||||
setState(() {
|
||||
_selectedOperatingSystem = selection;
|
||||
_selectedVersion = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
child: HomePageButtons(),
|
||||
)
|
||||
],
|
||||
),
|
||||
HomePageButton(
|
||||
label: "Version",
|
||||
text: _selectedVersion?.name ?? 'Select...',
|
||||
onPressed: (_selectedOperatingSystem != null)
|
||||
? () {
|
||||
Navigator.of(context)
|
||||
.push<Version>(MaterialPageRoute(
|
||||
fullscreenDialog: true,
|
||||
builder: (context) => VersionSelection(operatingSystem: _selectedOperatingSystem!),
|
||||
))
|
||||
.then((selection) {
|
||||
if (selection != null) {
|
||||
setState(() {
|
||||
_selectedVersion = selection;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
: null,
|
||||
),
|
||||
HomePageButton(
|
||||
text: 'Download',
|
||||
onPressed: (_selectedVersion == null)
|
||||
? null
|
||||
: () async {
|
||||
showLoadingIndicator(text: 'Downloading');
|
||||
await Process.run('quickget', [_selectedOperatingSystem!.code!, _selectedVersion!.code!]);
|
||||
hideLoadingIndicator();
|
||||
showDoneDialog(operatingSystem: _selectedOperatingSystem!.code!, version: _selectedVersion!.code!);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
"Working directory : ${Directory.current.absolute.path}",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.subtitle1!
|
||||
.copyWith(color: Colors.white),
|
||||
),
|
||||
)
|
||||
onPressed: () {},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -109,86 +67,4 @@ class _MainPageState extends State<MainPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showLoadingIndicator({String text = ''}) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
),
|
||||
backgroundColor: Colors.black87,
|
||||
content: SizedBox(
|
||||
height: 200,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: Text('Downloading...', style: Theme.of(context).textTheme.bodyText1?.copyWith(color: Colors.white)),
|
||||
),
|
||||
const CircularProgressIndicator(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: Text(
|
||||
'Target : ${Directory.current.absolute.path}',
|
||||
style: Theme.of(context).textTheme.bodyText1?.copyWith(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void hideLoadingIndicator() {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
void showDoneDialog({required String operatingSystem, required String version}) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
),
|
||||
backgroundColor: Colors.black87,
|
||||
content: SizedBox(
|
||||
height: 200,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: Text('Done !', style: Theme.of(context).textTheme.bodyText1?.copyWith(color: Colors.white)),
|
||||
),
|
||||
Text('Now run "quickemu --vm $operatingSystem-$version" to start the VM',
|
||||
style: Theme.of(context).textTheme.bodyText1?.copyWith(color: Colors.white)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
'Dismiss',
|
||||
style: Theme.of(context).textTheme.bodyText1?.copyWith(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class OperatingSystemMetadata {
|
||||
final String name;
|
||||
final String description;
|
||||
final List<OperatingSystemMetadata>? children;
|
||||
|
||||
OperatingSystemMetadata({
|
||||
required this.name,
|
||||
required this.description,
|
||||
this.children,
|
||||
});
|
||||
}
|
||||
|
||||
final Map<String, OperatingSystemMetadata> operatingSystems = {
|
||||
"ubuntu": OperatingSystemMetadata(name: "Ubuntu", description: "The mothership"),
|
||||
"*buntu*": OperatingSystemMetadata(name: "Ubuntu derivatives", description: "The many great derivatives", children: [
|
||||
OperatingSystemMetadata(name: "kUbuntu", description: "KDE-based version of Ubuntu"),
|
||||
OperatingSystemMetadata(name: "Lubuntu", description: "LxQt-based version of Ubuntu"),
|
||||
OperatingSystemMetadata(name: "Ubuntu Budgie", description: "Budgie-based version of Ubuntu"),
|
||||
OperatingSystemMetadata(name: "Ubuntu Kylin", description: "Kylin-based version of Ubuntu"),
|
||||
OperatingSystemMetadata(name: "Ubuntu MATE", description: "MATE-based version of Ubuntu"),
|
||||
OperatingSystemMetadata(name: "Ubuntu Studio", description: "Ubuntu for artists"),
|
||||
OperatingSystemMetadata(name: "Xubuntu", description: "Xfce-based version of Ubuntu"),
|
||||
]),
|
||||
"macOS": OperatingSystemMetadata(name: "macOS", description: "The beautiful one"),
|
||||
"windows": OperatingSystemMetadata(name: "Windows", description: "Why would you want to install this ?"),
|
||||
"freebsd": OperatingSystemMetadata(name: "FreeBSD", description: "FreeBSD"),
|
||||
};
|
||||
|
||||
class OperatingSystemPpage extends StatelessWidget {
|
||||
const OperatingSystemPpage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<OperatingSystemMetadata> names = operatingSystems.entries.map((e) => e.value).toList();
|
||||
return SingleChildScrollView(
|
||||
child: ListView.builder(
|
||||
//child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) => OperatingSystemCard(
|
||||
title: names[index].name,
|
||||
subtitle: names[index].description,
|
||||
),
|
||||
itemCount: operatingSystems.length,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class OperatingSystemCard extends StatelessWidget {
|
||||
final String title;
|
||||
final String subtitle;
|
||||
|
||||
const OperatingSystemCard({
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
shape: const ContinuousRectangleBorder(),
|
||||
margin: EdgeInsets.zero,
|
||||
child: ListTile(
|
||||
title: Text(title),
|
||||
subtitle: Text(subtitle),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -5,12 +5,14 @@ import 'package:quickgui/src/model/operating_system.dart';
|
|||
import 'package:quiver/iterables.dart';
|
||||
|
||||
class OperatingSystemSelection extends StatefulWidget {
|
||||
const OperatingSystemSelection({Key? key, this.showUbuntus = false}) : super(key: key);
|
||||
const OperatingSystemSelection({Key? key, this.showUbuntus = false})
|
||||
: super(key: key);
|
||||
|
||||
final bool showUbuntus;
|
||||
|
||||
@override
|
||||
State<OperatingSystemSelection> createState() => _OperatingSystemSelectionState();
|
||||
State<OperatingSystemSelection> createState() =>
|
||||
_OperatingSystemSelectionState();
|
||||
}
|
||||
|
||||
class _OperatingSystemSelectionState extends State<OperatingSystemSelection> {
|
||||
|
@ -18,7 +20,6 @@ class _OperatingSystemSelectionState extends State<OperatingSystemSelection> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
_future = loadOperatingSystems(widget.showUbuntus);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -43,7 +44,9 @@ class _OperatingSystemSelectionState extends State<OperatingSystemSelection> {
|
|||
return Card(
|
||||
child: ListTile(
|
||||
title: Text(item.name),
|
||||
trailing: item.hasMore ? const Icon(Icons.chevron_right) : null,
|
||||
trailing: item.hasMore
|
||||
? const Icon(Icons.chevron_right)
|
||||
: null,
|
||||
onTap: () {
|
||||
if (!item.hasMore) {
|
||||
Navigator.of(context).pop(item);
|
||||
|
@ -51,7 +54,8 @@ class _OperatingSystemSelectionState extends State<OperatingSystemSelection> {
|
|||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
fullscreenDialog: true,
|
||||
builder: (context) => const OperatingSystemSelection(
|
||||
builder: (context) =>
|
||||
const OperatingSystemSelection(
|
||||
showUbuntus: true,
|
||||
)))
|
||||
.then((selection) {
|
||||
|
@ -77,18 +81,4 @@ class _OperatingSystemSelectionState extends State<OperatingSystemSelection> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<OperatingSystem>> loadOperatingSystems(bool showUbuntus) async {
|
||||
return Process.run('quickget', []).then<List<OperatingSystem>>((process) {
|
||||
var stdout = process.stdout as String;
|
||||
var codes = stdout.split('\n')[1].split(' ').where((element) => showUbuntus ? element.contains('buntu') : !element.contains('buntu'));
|
||||
var names = codes.map((code) => code.toLowerCase().split('-').map((e) => e[0].toUpperCase() + e.substring(1)).join(' '));
|
||||
List<OperatingSystem> items = [];
|
||||
if (!showUbuntus) items.add(OperatingSystem(name: 'Ubuntu', hasMore: true));
|
||||
items.addAll(zip([codes, names]).map((item) => OperatingSystem(code: item[0], name: item[1])).toList());
|
||||
items.sort((a, b) => a.name.compareTo(b.name));
|
||||
|
||||
return items;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:quickgui/src/model/operating_system.dart';
|
||||
import 'package:quickgui/src/model/version.dart';
|
||||
import 'package:quickgui/src/pages/operating_system_selection.dart';
|
||||
import 'package:quickgui/src/pages/version_selection.dart';
|
||||
import 'package:quickgui/src/widgets/home_page_button.dart';
|
||||
|
||||
class HomePageButtons extends StatefulWidget {
|
||||
const HomePageButtons({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<HomePageButtons> createState() => _HomePageButtonsState();
|
||||
}
|
||||
|
||||
class _HomePageButtonsState extends State<HomePageButtons> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
OperatingSystem? _selectedOperatingSystem;
|
||||
Version? _selectedVersion;
|
||||
return Row(
|
||||
children: [
|
||||
HomePageButton(
|
||||
label: "Operating system",
|
||||
text: _selectedOperatingSystem?.name ?? 'Select...',
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.push<OperatingSystem>(MaterialPageRoute(
|
||||
fullscreenDialog: true,
|
||||
builder: (context) => const OperatingSystemSelection()))
|
||||
.then((selection) {
|
||||
if (selection != null) {
|
||||
setState(() {
|
||||
_selectedOperatingSystem = selection;
|
||||
_selectedVersion = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
HomePageButton(
|
||||
label: "Version",
|
||||
text: _selectedVersion?.name ?? 'Select...',
|
||||
onPressed: (_selectedOperatingSystem != null)
|
||||
? () {
|
||||
Navigator.of(context)
|
||||
.push<Version>(MaterialPageRoute(
|
||||
fullscreenDialog: true,
|
||||
builder: (context) => VersionSelection(
|
||||
operatingSystem: _selectedOperatingSystem!),
|
||||
))
|
||||
.then((selection) {
|
||||
if (selection != null) {
|
||||
setState(() {
|
||||
_selectedVersion = selection;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
: null,
|
||||
),
|
||||
HomePageButton(
|
||||
label: 'Download',
|
||||
text: 'Download',
|
||||
onPressed: (_selectedVersion == null)
|
||||
? null
|
||||
: () async {
|
||||
showLoadingIndicator(text: 'Downloading');
|
||||
await Process.run('quickget', [
|
||||
_selectedOperatingSystem!.code!,
|
||||
_selectedVersion!.code!
|
||||
]);
|
||||
hideLoadingIndicator();
|
||||
showDoneDialog(
|
||||
operatingSystem: _selectedOperatingSystem!.code!,
|
||||
version: _selectedVersion!.code!);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
;
|
||||
}
|
||||
|
||||
void showLoadingIndicator({String text = ''}) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
),
|
||||
backgroundColor: Colors.black87,
|
||||
content: SizedBox(
|
||||
height: 200,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: Text('Downloading...',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText1
|
||||
?.copyWith(color: Colors.white)),
|
||||
),
|
||||
const CircularProgressIndicator(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: Text(
|
||||
'Target : ${Directory.current.absolute.path}',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText1
|
||||
?.copyWith(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void hideLoadingIndicator() {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
void showDoneDialog(
|
||||
{required String operatingSystem, required String version}) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
child: AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
),
|
||||
backgroundColor: Colors.black87,
|
||||
content: SizedBox(
|
||||
height: 200,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: Text('Done !',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText1
|
||||
?.copyWith(color: Colors.white)),
|
||||
),
|
||||
Text(
|
||||
'Now run "quickemu --vm $operatingSystem-$version" to start the VM',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText1
|
||||
?.copyWith(color: Colors.white)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 32),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
'Dismiss',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText1
|
||||
?.copyWith(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue