# -*- coding: utf-8 -*-
#
# Author: Ingelrest François (Athropos@gmail.com)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

import cgi, consts, gtk, os, dlgChooseFiles

from gettext import gettext as _

# The strings stored in the ListStore object
(
    LIST_FILE_PATH,
    LIST_FILE,
    LIST_DIRECTORY,
) = range(3)

#==========================================================
#
# Functions
#
#==========================================================

def set(parentWindow, tree, label) :
    """
        Set the treeview managed by this module
        This function should be called only once
    """
    global parent, treeview, treeLabel, wTree, storage

    if treeview is not None :
        raise Exception

    wTree     = gtk.glade.XML(os.path.join(consts.dirRes, 'creationpopupmenus.glade'))
    parent    = parentWindow
    treeview  = tree
    treeLabel = label
    # Connect signal handlers
    wTree.signal_connect('onAddDirectoryContent', onAddDirectoryContent)
    wTree.signal_connect('onAddFiles',            onAddFiles)
    wTree.signal_connect('onRemoveAll',           onRemoveAll)
    wTree.signal_connect('onRemoveSelected',      onRemoveSelected)
    # (Displayed string, Complete filename)
    storage  = gtk.ListStore(str, str, str)
    renderer = gtk.CellRendererText()
    treeview.set_model(storage)
    treeview.insert_column_with_attributes(-1, '', renderer, markup=LIST_FILE)
    treeview.insert_column_with_attributes(-1, '', renderer, markup=LIST_DIRECTORY)
    treeview.get_column(0).set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
    treeview.get_column(1).set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
    storage.set_sort_column_id(LIST_FILE, gtk.SORT_ASCENDING)
    # Drag and drop support
    treeview.enable_model_drag_dest([('STRING', 0, 0)], gtk.gdk.ACTION_COPY)
    updateLabel()


def updateLabel() :
    """
        Update the label using the number of currently selected files
    """
    lblFiles = ''
    if len(storage) != 0 :
        lblFiles = ' (' + str(len(storage)) + ')'
    treeLabel.set_markup('<b>' + _('Files to protect:') + '</b>' + lblFiles)


def hasSelection() :
    """
        Return True if something is selected, False otherwise
    """
    model, iter = treeview.get_selection().get_selected()
    return iter != None


def setFocusAtXY(x, y) :
    """
        Select the entry located at the given location
    """
    treeview.grab_focus()
    pthinfo = treeview.get_path_at_pos(x, y)
    # Select the row if any, clear selection otherwise
    if pthinfo is not None :
        path, col, cellx, celly = pthinfo
        treeview.set_cursor(path)
    elif hasSelection() :
        path, col = treeview.get_cursor()
        treeview.get_selection().unselect_path(path)


def addDirectoryContent(directory) :
    """
        Add all the files located in the given directory
    """
    # Kids, don't do that at home: pretty cool piece of code, isn't it? :-D
    map(addFile, filter(os.path.isfile, map(lambda filename : os.path.join(directory, filename), os.listdir(directory))))


def addFile(file) :
    """
        Add a file to the tree
    """
    (directory, filename) = os.path.split(file)
    if directory.startswith(consts.dirUsr) :
        directory = directory.replace(consts.dirUsr, '~', 1)
    # cgi.escape() is used to protect special characters against the Pango markup
    storage.append([file, '<b>' + cgi.escape(filename) + '</b>', '  <i>' + cgi.escape(directory) + '/</i>'])


def getAllFilenames() :
    """
        Return a list with all the entries
    """
    return [file[LIST_FILE_PATH] for file in storage]

#==========================================================
#
# Events handlers
#
#==========================================================

def onDragDrop(tree, context, x, y, selection, info, etime) :
    """
        Something has been dropped onto the treeview
    """
    for path in selection.data.split() :
        path = path.replace('file://', '', 1)
        path = path.replace('%20', ' ')
        if os.path.isfile(path) :
            addFile(path)
        elif os.path.isdir(path) :
            addDirectoryContent(path)

    updateLabel()
    context.finish(True, False, etime)


def onMouseButton(tree, event) :
    """
        A mouse button has been pressed
    """
    # Single right click ?
    if event.button == 3 and event.type == gtk.gdk.BUTTON_PRESS :
        setFocusAtXY(int(event.x), int(event.y))
        if hasSelection() :
            wTree.get_widget('menuAll').popup(None, None, None, event.button, event.time)
        elif len(storage) is not 0 :
            wTree.get_widget('menuAddClear').popup(None, None, None, event.button, event.time)
        else :
            wTree.get_widget('menuAdd').popup(None, None, None, event.button, event.time)


def onKey(tree, event) :
    """
        A key has been pressed
    """
    if gtk.gdk.keyval_name(event.keyval) == 'Delete' :
        onRemoveSelected(treeview)


def onAddDirectoryContent(widget) :
    """
        Let the user choose a directory, and then add all its content to the tree
    """
    directories = dlgChooseFiles.show(parent, dlgChooseFiles.MODE_DIRECTORY)
    if directories is not None :
        treeview.freeze_child_notify()
        map(addDirectoryContent, directories)
        treeview.thaw_child_notify()
        updateLabel()


def onAddFiles(widget) :
    """
        Let the user choose some files, and then add them to the tree
    """
    files = dlgChooseFiles.show(parent, dlgChooseFiles.MODE_FILES)
    if files is not None :
        treeview.freeze_child_notify()
        map(addFile, files)
        treeview.thaw_child_notify()
        updateLabel()


def onRemoveSelected(widget) :
    """
        Remove the currently selected entry
    """
    model, iter = treeview.get_selection().get_selected()
    if iter is not None :
        model.remove(iter)
        updateLabel()


def onRemoveAll(widget) :
    """
        Clear the tree
    """    
    storage.clear()
    updateLabel()

#==========================================================
#
# Entry point
#
#==========================================================

parent    = None
treeview  = None
treeLabel = None
