This commit is contained in:
Yannick Mauray 2021-10-19 15:13:50 +02:00
parent 852d73ebc9
commit 0e082ac402
No known key found for this signature in database
GPG Key ID: C98AB53D9773539F
6 changed files with 267 additions and 239 deletions

2
.gitignore vendored
View File

@ -26,3 +26,5 @@ doc/api/
web/
ios/
android/
windows/
list.csv

View File

@ -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;
});
}
}

View File

@ -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),
),
),
),
],
),
),
),
),
);
}
}

View File

@ -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),
),
);
}
}

View File

@ -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;
});
}
}

View File

@ -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),
),
),
),
],
),
),
),
),
);
}
}