simplified the custom dialog constructing -- still not too happy with it + some preliminary work on exporting...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2016-04-15 23:32:33 +03:00
parent de0136c614
commit 4063cc4898
4 changed files with 209 additions and 73 deletions

View File

@ -33,6 +33,15 @@ var browseWalk = require('lib/widget/browse-walk')
/*********************************************************************/
if(typeof(process) != 'undefined'){
var copy = file.denodeify(fse.copy)
var ensureDir = file.denodeify(fse.ensureDir)
}
/*********************************************************************/
// fs reader/loader...
@ -758,17 +767,21 @@ var FileSystemWriterActions = actions.Actions({
exportView: ['File/Export current view',
function(){
}],
// XXX not done yet...
// needs:
// ensureDir(..)
// copy(..)
// ...both denodeify(..)'ed
// XXX export current state as a full loadable index
// Export current state as a full loadable index
//
// XXX might be interesting to unify this and .exportView(..)
// XXX should this return a promise??? ...a clean promise???
// XXX add preview selection...
// XXX handle .image.path and other stack files...
// XXX local collections???
// XXX add a ui...
// - select path
// - select preview size
exportCollection: ['File/Export as collection',
function(path, logger){
logger = logger || this.logger
var json = this.json()
// get all loaded gids...
@ -785,6 +798,7 @@ var FileSystemWriterActions = actions.Actions({
var img = json.images[gid]
if(img){
images[gid] = json.images[gid]
// remove un-needed previews...
// XXX
}
@ -794,27 +808,28 @@ var FileSystemWriterActions = actions.Actions({
json.data.order = gids
json.images = images
// XXX should we check if index dir is present in path???
path = path +'/'+ this.config['index-dir']
var index_path = path +'/'+ this.config['index-dir']
// NOTE: if we are to use .saveIndex(..) here, do not forget
// to reset .changes
file.writeIndex(
this.prepareIndexForWrite(json).prepared,
path,
this.config['index-filename-template'],
logger || this.logger)
// copy previews for the loaded images...
// XXX should also optionally populate the base dir and nested favs...
var base_dir = this.base_dir
var base_dir = this.location.path
gids.forEach(function(gid){
var img = json.images[gid]
var img_base = img.base_path
img.base_path = path
var previews = img.preview
for(var res in previews){
var from = (img_base || base_dir) +'/'+ preview_path
// NOTE: we are copying everything to one place so no
// need for a base path...
delete img.base_path
// XXX copy img.path -- the main image, especially when no previews present....
// XXX
Object.keys(previews).forEach(function(res){
var preview_path = decodeURI(previews[res])
var from = (img_base || base_dir) +'/'+ preview_path
var to = path +'/'+ preview_path
// XXX do we queue these or let the OS handle it???
@ -823,7 +838,7 @@ var FileSystemWriterActions = actions.Actions({
// XXX
ensureDir(pathlib.dirname(to))
.catch(function(err){
// XXX
logger && logger.emit('error', err)
})
.then(function(){
return copy(from, to)
@ -832,12 +847,99 @@ var FileSystemWriterActions = actions.Actions({
// we just use the one above (after
// .then(..))
.catch(function(err){
// XXX
logger && logger.emit('error', err)
})
.then(function(){
logger && logger.emit('done', to)
})
})
}
})
})
// NOTE: if we are to use .saveIndex(..) here, do not forget
// to reset .changes
file.writeIndex(
this.prepareIndexForWrite(json, true).prepared,
index_path,
this.config['index-filename-template'],
logger || this.logger)
}],
// XXX use options:
// - level dir name
// - size
// - filename pattern
// XXX might also be good to save/load the export state to .ImageGrid-export.json
// XXX make custom previews...
// ...should this be a function of .images.getBestPreview(..)???
exportDirs: ['File/Export as nested directories',
function(path, pattern, level_dir, size, logger){
logger = logger || this.logger
var that = this
var base_dir = this.location.path
var to_dir = path
// get/set the config data...
// XXX should this store the last set???
level_dir = level_dir || this.config['export-level-directory-name'] || 'fav'
size = size || this.config['export-preview-size'] || 1000
pattern = pattern || this.config['export-preview-name-pattern'] || '%f'
this.data.ribbon_order
.slice()
.reverse()
.forEach(function(ribbon){
// NOTE: this is here to keep the specific path local to
// this scope...
var img_dir = to_dir
ensureDir(pathlib.dirname(img_dir))
.catch(function(err){
logger && logger.emit('error', err)
})
.then(function(){
that.data.ribbons[ribbon].forEach(function(gid){
var img = that.images[gid]
// get best preview...
var from = (img.base_path || base_dir) +'/'+ that.images.getBestPreview(gid, size).url
// XXX see if we need to make a preview (sharp)
// XXX
// XXX get/form image name...
// XXX might be a good idea to connect this to the info framework...
var ext = pathlib.extname(img.name)
var name = pattern
.replace(/%f/, img.name)
.replace(/%n/, img.name.replace(ext, ''))
.replace(/%e/, ext)
.replace(/%gid/, gid)
// XXX get the correct length...
.replace(/%g/, gid.slice(-7, -1))
// XXX %()m marked...
// XXX
// XXX %()b bookmarked...
// XXX
// XXX EXIF...
var to = img_dir +'/'+ name
copy(from, to)
.catch(function(err){
logger && logger.emit('error', err)
})
.then(function(){
logger && logger.emit('done', to)
})
})
})
to_dir += '/'+level_dir
})
}]
})

View File

@ -57,33 +57,25 @@ var SlideshowActions = actions.Actions({
this.suspendSlideshowTimer()
// XXX might be a good idea to make this generic...
var _makeTogglHandler = function(toggler){
return function(){
var txt = $(this).find('.text').first().text()
that[toggler]()
o.client.update()
.then(function(){ o.client.select(txt) })
that.toggleSlideshow('?') == 'on'
&& o.close()
}
}
var o = overlay.Overlay(this.ribbons.viewer,
browse.makeList(
null,
[
// XXX make this editable...
['Interval: ',
function(){ return that.config['slideshow-interval'] }],
['Direction: ',
function(){ return that.config['slideshow-direction'] }],
['Looping: ',
function(){ return that.config['slideshow-looping'] }],
browse.makeLister(null, function(path, make){
make(['Interval: ',
function(){ return that.config['slideshow-interval'] }])
.on('open', function(){
var txt = $(this).find('.text').first().text()
//'---',
[function(){
return that.toggleSlideshow('?') == 'on' ? 'Stop' : 'Start' }],
])
.open(function(evt, path){
// start/stop...
if(path == 'Start' || path == 'Stop'){
that.toggleSlideshow()
o.close()
return
}
// interval...
if(/interval/i.test(path)){
var to_remove = []
var oo = widgets.makeConfigListEditor(that, 'slideshow-intervals', {
new_button: 'New...',
length_limit: that.config['slideshow-interval-max-count'],
@ -107,9 +99,8 @@ var SlideshowActions = actions.Actions({
// XXX this is ugly...
o.focus()
if(that.toggleSlideshow('?') == 'on'){
o.close()
}
that.toggleSlideshow('?') == 'on'
&& o.close()
})
oo.client
@ -122,42 +113,36 @@ var SlideshowActions = actions.Actions({
// XXX this is ugly...
oo.close()
o.client.update()
o.client.select(path.split(':')[0])
o.client.select(txt)
}
})
oo.client.dom.addClass('tail-action')
oo.client.select(that.config['slideshow-interval'])
})
return
}
make(['Direction: ',
function(){ return that.config['slideshow-direction'] }])
.on('open', _makeTogglHandler('toggleSlideshowDirection'))
make(['Looping: ',
function(){ return that.config['slideshow-looping'] }])
.on('open', _makeTogglHandler('toggleSlideshowLooping'))
// direction...
if(/direction/i.test(path)){
that.toggleSlideshowDirection()
o.client.update()
// Looping...
} else if(/looping/i.test(path)){
that.toggleSlideshowLooping()
o.client.update()
}
// XXX this is ugly...
o.client.select(path.split(':')[0])
// do not keep the dialog open during the slideshow...
if(that.toggleSlideshow('?') == 'on'){
// Start/stop...
make([function(){
return that.toggleSlideshow('?') == 'on' ? 'Stop' : 'Start' }])
.on('open', function(){
that.toggleSlideshow()
o.close()
}
}))
})
}))
.close(function(){
that.resetSlideshowTimer()
})
o.client.dom.addClass('metadata-view tail-action')
o.client.select(-1)
return o

View File

@ -94,8 +94,15 @@ function listJSON(path, pattern){
return gGlob(path +'/'+ pattern +'.json')
}
// wrap a node style callback function into a Promise...
//
// NOTE: this is inspired by the promise module for node this stopped
// working, and porting one method was simpler that trying to get
// to the bottom of the issue, especially with native promises...
// XXX move to someplace generic...
var denodeify = function(func){
var denodeify =
module.denodeify =
function(func){
return function(){
// XXX for some reason this does not see args2array...
// XXX and for some reason the error is not reported...

View File

@ -2189,6 +2189,48 @@ Browser.prototype.__proto__ = widget.Widget.prototype
/*********************************************************************/
var ListerPrototype = Object.create(BrowserPrototype)
ListerPrototype.options = {
pathPrefix: '',
fullPathEdit: false,
traversable: false,
flat: true,
// XXX not sure if we need these...
skipDisabledItems: false,
// NOTE: to disable this set it to false or null
disableItemPattern: '^- ',
elementSeparatorText: '---',
}
// XXX should we inherit or copy options???
// ...inheriting might pose problems with deleting values reverting
// them to default instead of nulling them and mutable options might
// get overwritten...
ListerPrototype.options.__proto__ = BrowserPrototype.options
var Lister =
module.Lister =
object.makeConstructor('Lister',
BrowserClassPrototype,
ListerPrototype)
// This is a shorthand for: new List(<elem>, { data: <list> })
var makeLister =
module.makeLister = function(elem, lister, options){
var opts = {}
for(var k in options){
opts[k] = rest[k]
}
opts.list = lister
return Lister(elem, opts)
}
/*********************************************************************/
// Flat list...