344 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			344 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			V
		
	
	
/**********************************************************************
 | 
						|
*
 | 
						|
* File scanner
 | 
						|
*
 | 
						|
* Copyright (c) 2021 Dario Deledda. All rights reserved.
 | 
						|
* Use of this source code is governed by an MIT license
 | 
						|
* that can be found in the LICENSE file.
 | 
						|
*
 | 
						|
* TODO:
 | 
						|
**********************************************************************/
 | 
						|
import os
 | 
						|
 | 
						|
// STBI supported format
 | 
						|
//        STBI_NO_JPEG *
 | 
						|
//        STBI_NO_PNG  *
 | 
						|
//        STBI_NO_BMP  *
 | 
						|
//        STBI_NO_PSD
 | 
						|
//        STBI_NO_TGA  *
 | 
						|
//        STBI_NO_GIF  *
 | 
						|
//        STBI_NO_HDR  *
 | 
						|
//        STBI_NO_PIC  *
 | 
						|
//        STBI_NO_PNM  *
 | 
						|
 | 
						|
/******************************************************************************
 | 
						|
*
 | 
						|
* Struct and Enums
 | 
						|
*
 | 
						|
******************************************************************************/
 | 
						|
enum Item_type {
 | 
						|
	file = 0
 | 
						|
	folder
 | 
						|
	// archive format
 | 
						|
	zip = 16
 | 
						|
	archive_file
 | 
						|
	// graphic format, MUST stay after the other types!!
 | 
						|
	bmp = 32
 | 
						|
	jpg
 | 
						|
	png
 | 
						|
	gif
 | 
						|
	tga
 | 
						|
	ppm
 | 
						|
	pgm
 | 
						|
	pic
 | 
						|
	hdr
 | 
						|
}
 | 
						|
 | 
						|
pub struct Item {
 | 
						|
pub mut:
 | 
						|
	path                 string
 | 
						|
	name                 string
 | 
						|
	size                 u64
 | 
						|
	i_type               Item_type = .file
 | 
						|
	container_index      int  // used if the item is in a container (.zip, .rar, etc)
 | 
						|
	container_item_index int  // index in the container if the item is contained
 | 
						|
	need_extract         bool // if true need to extraction from the container
 | 
						|
	drawable             bool // if true the image can be showed
 | 
						|
	n_item               int  //
 | 
						|
	rotation             int  // number of rotation of PI/2
 | 
						|
}
 | 
						|
 | 
						|
struct Item_list {
 | 
						|
pub mut:
 | 
						|
	lst        []Item
 | 
						|
	path_sep   string
 | 
						|
	item_index int = -1 // image currently shown
 | 
						|
	n_item     int  // number of images scanned
 | 
						|
	loaded     bool // flag that indicate that the list is ready to  be used
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************
 | 
						|
*
 | 
						|
* Utility functions
 | 
						|
*
 | 
						|
******************************************************************************/
 | 
						|
[inline]
 | 
						|
fn modulo(x int, n int) int {
 | 
						|
	return (x % n + n) % n
 | 
						|
}
 | 
						|
 | 
						|
[inline]
 | 
						|
fn get_extension(x string) Item_type {
 | 
						|
	// 4 char extension check
 | 
						|
	if x.len > 4 {
 | 
						|
		ext4 := x[x.len - 4..].to_lower()
 | 
						|
		match ext4 {
 | 
						|
			// containers
 | 
						|
			'.zip' { return .zip }
 | 
						|
			// graphic formats
 | 
						|
			'.jpg' { return .jpg }
 | 
						|
			'.png' { return .png }
 | 
						|
			'.bmp' { return .bmp }
 | 
						|
			'.gif' { return .gif }
 | 
						|
			'.tga' { return .tga }
 | 
						|
			'.ppm' { return .ppm }
 | 
						|
			'.pgm' { return .pgm }
 | 
						|
			'.pic' { return .pic }
 | 
						|
			'.hdr' { return .hdr }
 | 
						|
			else {}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	// 5 char extension check
 | 
						|
	if x.len > 5 {
 | 
						|
		ext5 := x[x.len - 5..].to_lower()
 | 
						|
		if ext5 == '.jpeg' {
 | 
						|
			{
 | 
						|
				return .jpg
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return .file
 | 
						|
}
 | 
						|
 | 
						|
[inline]
 | 
						|
fn is_image(x Item_type) bool {
 | 
						|
	if int(x) >= int(Item_type.bmp) {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
[inline]
 | 
						|
fn is_container(x Item_type) bool {
 | 
						|
	if x in [.zip, .folder] {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
[inline]
 | 
						|
fn (item_list Item_list) is_inside_a_container() bool {
 | 
						|
	if item_list.lst.len <= 0 || item_list.n_item <= 0 {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return item_list.lst[item_list.item_index].need_extract
 | 
						|
}
 | 
						|
 | 
						|
[inline]
 | 
						|
fn (item_list Item_list) get_file_path() string {
 | 
						|
	if item_list.lst.len <= 0 || item_list.n_item <= 0 {
 | 
						|
		return ''
 | 
						|
	}
 | 
						|
	if item_list.lst[item_list.item_index].path.len > 0 {
 | 
						|
		return '${item_list.lst[item_list.item_index].path}$item_list.path_sep${item_list.lst[item_list.item_index].name}'
 | 
						|
	}
 | 
						|
	return item_list.lst[item_list.item_index].name
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************
 | 
						|
*
 | 
						|
* Scan functions
 | 
						|
*
 | 
						|
******************************************************************************/
 | 
						|
fn (mut item_list Item_list) scan_folder(path string, in_index int) ? {
 | 
						|
	println('Scanning [$path]')
 | 
						|
	mut folder_list := []string{}
 | 
						|
	lst := os.ls(path) ?
 | 
						|
 | 
						|
	// manage the single files
 | 
						|
	for c, x in lst {
 | 
						|
		pt := '$path$item_list.path_sep$x'
 | 
						|
		mut item := Item{
 | 
						|
			path: path
 | 
						|
			name: x
 | 
						|
			container_index: in_index
 | 
						|
			container_item_index: c
 | 
						|
		}
 | 
						|
		if os.is_dir(pt) {
 | 
						|
			folder_list << x
 | 
						|
		} else {
 | 
						|
			ext := get_extension(x)
 | 
						|
			if ext == .zip {
 | 
						|
				item.i_type = .zip
 | 
						|
				item_list.lst << item
 | 
						|
				item_list.scan_zip(pt, item_list.lst.len - 1) ?
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			if is_image(ext) == true {
 | 
						|
				item_list.n_item += 1
 | 
						|
				item.n_item = item_list.n_item
 | 
						|
				item.i_type = ext
 | 
						|
				item.drawable = true
 | 
						|
				item_list.lst << item
 | 
						|
				continue
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// manage the folders
 | 
						|
	for x in folder_list {
 | 
						|
		pt := '$path$item_list.path_sep$x'
 | 
						|
		item := Item{
 | 
						|
			path: path
 | 
						|
			name: x
 | 
						|
			i_type: .folder
 | 
						|
		}
 | 
						|
		item_list.lst << item
 | 
						|
		item_list.scan_folder(pt, item_list.lst.len - 1) ?
 | 
						|
	}
 | 
						|
	// println(item_list.lst.len)
 | 
						|
	// println("==================================")
 | 
						|
}
 | 
						|
 | 
						|
fn (item_list Item_list) print_list() {
 | 
						|
	println('================================')
 | 
						|
	for x in item_list.lst {
 | 
						|
		if x.i_type == .folder {
 | 
						|
			print('[]')
 | 
						|
		}
 | 
						|
		if x.i_type == .zip {
 | 
						|
			print('[ZIP]')
 | 
						|
		}
 | 
						|
		println('$x.path => $x.container_index $x.container_item_index $x.name ne:$x.need_extract')
 | 
						|
	}
 | 
						|
	println('n_item: $item_list.n_item index: $item_list.item_index')
 | 
						|
	println('================================')
 | 
						|
}
 | 
						|
 | 
						|
fn (mut item_list Item_list) get_items_list(args []string) {
 | 
						|
	item_list.loaded = false
 | 
						|
	println('Args: $args')
 | 
						|
 | 
						|
	item_list.path_sep = $if windows { '\\' } $else { '/' }
 | 
						|
	for x in args {
 | 
						|
		// scan folder
 | 
						|
		if os.is_dir(x) {
 | 
						|
			mut item := Item{
 | 
						|
				path: x
 | 
						|
				name: x
 | 
						|
				container_index: item_list.lst.len
 | 
						|
				i_type: .folder
 | 
						|
			}
 | 
						|
			item_list.lst << item
 | 
						|
			item_list.scan_folder(x, item_list.lst.len - 1) or {
 | 
						|
				eprintln('ERROR: scanning folder [$x]!')
 | 
						|
				continue
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			mut item := Item{
 | 
						|
				path: ''
 | 
						|
				name: x
 | 
						|
				container_index: -1
 | 
						|
			}
 | 
						|
			ext := get_extension(x)
 | 
						|
			// scan .zip
 | 
						|
			if ext == .zip {
 | 
						|
				item.i_type = .zip
 | 
						|
				item_list.lst << item
 | 
						|
				item_list.scan_zip(x, item_list.lst.len - 1) or {
 | 
						|
					eprintln('ERROR: scanning zip [$x]!')
 | 
						|
					continue
 | 
						|
				}
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			// single images
 | 
						|
			if is_image(ext) == true {
 | 
						|
				item_list.n_item += 1
 | 
						|
				item.n_item = item_list.n_item
 | 
						|
				item.i_type = ext
 | 
						|
				item.drawable = true
 | 
						|
				item_list.lst << item
 | 
						|
				continue
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	// debug call for list all the loaded items
 | 
						|
	// item_list.print_list()
 | 
						|
 | 
						|
	println('Items: $item_list.n_item')
 | 
						|
	println('Scanning done.')
 | 
						|
 | 
						|
	item_list.get_next_item(1)
 | 
						|
	item_list.loaded = true
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************
 | 
						|
*
 | 
						|
* Navigation functions
 | 
						|
*
 | 
						|
******************************************************************************/
 | 
						|
fn (mut item_list Item_list) get_next_item(in_inc int) {
 | 
						|
	// if empty exit
 | 
						|
	if item_list.lst.len <= 0 || item_list.n_item <= 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	inc := if in_inc > 0 { 1 } else { -1 }
 | 
						|
	mut i := item_list.item_index + in_inc
 | 
						|
	i = modulo(i, item_list.lst.len)
 | 
						|
	start := i
 | 
						|
	for {
 | 
						|
		if item_list.lst[i].drawable == true {
 | 
						|
			item_list.item_index = i
 | 
						|
			break
 | 
						|
		}
 | 
						|
		i = i + inc
 | 
						|
		i = modulo(i, item_list.lst.len)
 | 
						|
		// if we are in a loop break it
 | 
						|
		if i == start {
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
	// println("Found: ${item_list.item_index}")
 | 
						|
}
 | 
						|
 | 
						|
fn (mut item_list Item_list) go_to_next_container(in_inc int) {
 | 
						|
	// if empty exit
 | 
						|
	if item_list.lst.len <= 0 || item_list.n_item <= 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	inc := if in_inc > 0 { 1 } else { -1 }
 | 
						|
	mut i := item_list.item_index + in_inc
 | 
						|
	i = modulo(i, item_list.lst.len)
 | 
						|
	start := i
 | 
						|
	for {
 | 
						|
		// check if we found a folder
 | 
						|
		if is_container(item_list.lst[i].i_type) == true
 | 
						|
			&& i != item_list.lst[item_list.item_index].container_index {
 | 
						|
			item_list.item_index = i
 | 
						|
			item_list.get_next_item(1)
 | 
						|
			break
 | 
						|
		}
 | 
						|
		// continue to search
 | 
						|
		i = i + inc
 | 
						|
		i = modulo(i, item_list.lst.len)
 | 
						|
		// if we are in a loop break it
 | 
						|
		if i == start {
 | 
						|
			break
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************
 | 
						|
*
 | 
						|
* Other functions
 | 
						|
*
 | 
						|
******************************************************************************/
 | 
						|
[inline]
 | 
						|
fn (mut item_list Item_list) rotate(in_inc int) {
 | 
						|
	item_list.lst[item_list.item_index].rotation += in_inc
 | 
						|
	if item_list.lst[item_list.item_index].rotation >= 4 {
 | 
						|
		item_list.lst[item_list.item_index].rotation = 0
 | 
						|
	}
 | 
						|
}
 |