diff --git a/.gitignore b/.gitignore index fa1d510..02a8b6b 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ doc/api/ web/ ios/ android/ +windows/ +list.csv \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 0d0b3e1..9527970 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -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> loadOperatingSystems(bool showUbuntus) async { + var file = File('list.csv'); + var fileExists = file.existsSync(); + if (fileExists) { + Stream 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>((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 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; + }); + } +} diff --git a/lib/src/pages/main_page.dart b/lib/src/pages/main_page.dart index 059206a..8820709 100644 --- a/lib/src/pages/main_page.dart +++ b/lib/src/pages/main_page.dart @@ -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 createState() => _MainPageState(); -} - -class _MainPageState extends State { - OperatingSystem? _selectedOperatingSystem; - Version? _selectedVersion; - @override Widget build(BuildContext context) { return Scaffold( @@ -45,62 +33,32 @@ class _MainPageState extends State { 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(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(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 { ), ); } - - 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), - ), - ), - ), - ], - ), - ), - ), - ), - ); - } } diff --git a/lib/src/pages/operating_system_page.dart b/lib/src/pages/operating_system_page.dart deleted file mode 100644 index a3cb2e6..0000000 --- a/lib/src/pages/operating_system_page.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'package:flutter/material.dart'; - -class OperatingSystemMetadata { - final String name; - final String description; - final List? children; - - OperatingSystemMetadata({ - required this.name, - required this.description, - this.children, - }); -} - -final Map 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 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), - ), - ); - } -} diff --git a/lib/src/pages/operating_system_selection.dart b/lib/src/pages/operating_system_selection.dart index 05420d7..5811a39 100644 --- a/lib/src/pages/operating_system_selection.dart +++ b/lib/src/pages/operating_system_selection.dart @@ -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 createState() => _OperatingSystemSelectionState(); + State createState() => + _OperatingSystemSelectionState(); } class _OperatingSystemSelectionState extends State { @@ -18,7 +20,6 @@ class _OperatingSystemSelectionState extends State { @override void initState() { - _future = loadOperatingSystems(widget.showUbuntus); super.initState(); } @@ -43,7 +44,9 @@ class _OperatingSystemSelectionState extends State { 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 { 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 { ), ); } - - Future> loadOperatingSystems(bool showUbuntus) async { - return Process.run('quickget', []).then>((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 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; - }); - } } diff --git a/lib/src/widgets/home_page_buttons.dart b/lib/src/widgets/home_page_buttons.dart new file mode 100644 index 0000000..803e457 --- /dev/null +++ b/lib/src/widgets/home_page_buttons.dart @@ -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 createState() => _HomePageButtonsState(); +} + +class _HomePageButtonsState extends State { + @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(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(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), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +}