###
# Application: pyFind
# File:        appMain.py
# Description: Main window callbacks
# Copyright (c) 2001-2002   Andy Balcombe <kinematics _at_ ntlworld.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#standard python modules
import os

#project modules
from LoadGlade import *
import dlgPreferences
import dlgSaveAs
import config
import match_files

class appMain(LoadGlade):
    """
    The main pyfind gui class
    """
    def init_appMain(self, p_sPath=""):
        #init config db
        self.confPrefs = config.GnomeConfig("pyFind")
        
        #signal connect
        self.appMain.connect("destroy", gtk.mainquit)

        #set inital values
        self.apbMain.set_status("Started")
        self.cmdStop.set_sensitive(gtk.FALSE)
        self.set_file_buttons()
        
        #drag and drop stuff
        self.targets = [('STRING', 0, 0), ('text/plain', 0,1), ('text/uri-list', 0, 2) ]
        self.clstFiles.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.targets, gtk.GDK.ACTION_COPY | gtk.GDK.ACTION_MOVE)
        self.clstFiles.drag_source_set(gtk.GDK.SHIFT_MASK | gtk.GDK.BUTTON1_MASK, self.targets, gtk.GDK.ACTION_COPY | gtk.GDK.ACTION_MOVE )
        #self.clstFiles.connect("drag_data_get",self.on_clstFiles_drag_data_get)

        #load histories
        self.entFileSpec.load_history()
        self.entContaining.load_history()
        self.fentSearchIn.gnome_entry().load_history()

        #see if --last has been used to run pyfind...
        if p_sPath == "":
            #...yes, start with previous settings
            sLastFileSpec = self.confPrefs.get_value( "History: entFileSpec", "0", "*" )
            sLastSearchItem = self.confPrefs.get_value( "History: entContaining", "0", "" )
            sLastSearchPath = self.confPrefs.get_value( "History: fentSearchIn", "0", "/" )
            self.txeFileSpec.set_text(sLastFileSpec) 
            self.txeContaining.set_text(sLastSearchItem) 
            self.txeSearchIn.set_text( sLastSearchPath )
        else:
            #...no, start with default settings and specified path
            self.txeFileSpec.set_text("*") 
            self.txeContaining.set_text("") 
            self.txeSearchIn.set_text( p_sPath )

        #init toolbars and result cols, etc
        self.set_config_preferences()
        
        #flags, etc
        self.bStopPressed = 0

    #process gtk / gnome events
    def process_gtk_events(self):
        while gtk.events_pending():
            gtk.mainiteration()

    def set_config_preferences(self):
        #init toolbars
        self.tbrMain.set_style( int(self.confPrefs.get_value( "config", "tbrMain", str(gtk.TOOLBAR_BOTH))))
        #self.tbrFile.set_style( int(self.confPrefs.get_value( "config", "tbrFile", str(gtk.TOOLBAR_BOTH))))

        #set columns
        sCols = self.confPrefs.get_value( "config", "ResultCols", "011100101" )
        iColNum = -1
        for sColVisible in sCols:
            iColNum = iColNum + 1
            self.clstFiles.set_column_visibility( iColNum, (sColVisible=="1") )

        #sync config file
        self.confPrefs.sync()

    def set_file_buttons(self):
        #get selected rows
        lSelected = self.clstFiles.selection
        if len(lSelected) > 0:
            self.cmdFOpen.set_sensitive(gtk.TRUE)
            self.cmdFDelete.set_sensitive(gtk.TRUE)
        else:
            self.cmdFOpen.set_sensitive(gtk.FALSE)
            self.cmdFDelete.set_sensitive(gtk.FALSE)

    ### Main Toolbar
    # Find
    def on_cmdFind_clicked(self, *args):
        #sanity checking
        if self.txeFileSpec.get_text() == "" or \
           self.fentSearchIn.get_full_path(1) == None:
            #stop here
            self.apbMain.set_status( "Enter a path and file spec" )
            return
            
        #search for files!
        self.entFileSpec.prepend_history(1,self.txeFileSpec.get_text())
        self.entContaining.prepend_history(1,self.txeContaining.get_text())
        self.fentSearchIn.gnome_entry().prepend_history(1,self.fentSearchIn.get_full_path(1))

        #set progress bar to 0 and clear list
        self.cmdStop.set_sensitive(gtk.TRUE)
        self.apbMain.set_progress(0.0)
        self.clstFiles.clear()
        self.process_gtk_events()

        #reset flags
        self.bStopPressed = 0

        #build parameter list
        if self.txeFileSize.get_text() == "At Least":
            sSizeType = ">"
        else:
            sSizeType = "<"

        #call search module
        lFiles = []
        lFiles, sFindCmd = match_files.find_matching_files(
            self,
            self.fentSearchIn.get_full_path(1),        #search path
            not(self.chkSubDirectories.get_active()),  #search sub-directories
            self.chkSearchMountedVols.get_active(),    #search mounted volumes
            self.txeFileSpec.get_text(),               #file spec 
            self.chkFileCase.get_active(),             #case sensitive filenames
            self.chkPreviousDays.get_active(),         #search previous 
            self.txeMDays.get_text(),                  #num previous type (weeks, days, etc)
            self.spnPreviousDays.get_value_as_int(),   #num previous val
            self.txeContaining.get_text() != "",       #search contents
            self.chkContCase.get_active(),             #case sensitive contents
            self.txeContaining.get_text(),             #search contents val
            self.chkFileSize.get_active(),             #search by size
            sSizeType,                                 #size type (< or >)
            self.spnFileSize.get_value_as_int() * 1024,#size in kb
            self.chkBetween.get_active(),              #search on mod date
            self.dteBetweenStart.get_date(),           #start date
            self.dteBetweenEnd.get_date() + 86400,     #end date +1 day (to make date inclusive) 
            self.chkReplace.get_active(),              #search and replace text within files
            self.txeRepSearch.get_text(),              #replace - search text
            self.txeRepReplace.get_text(),             #        - replace text
            self.chkRegExp.get_active(),               #        - use regular expressions
            self.chkRepCaseSensitive.get_active()      #        - case senstive search for regular expressions
        )

        #done search
        self.txeFindCmd.set_text(sFindCmd) #fill in find cmd line
        self.cmdStop.set_sensitive(gtk.FALSE)
        
    # Clear search parameters
    def on_cmdReset_clicked(self, *args):
        #clear all search options
        self.txeFileSpec.set_text("*")
        self.txeContaining.set_text("")
        self.txeSearchIn.set_text("/")

    #stop search
    def on_cmdStop_clicked(self, *args):
        #set flag (checked in match_files.py)
        self.bStopPressed = 1
        
    # save as
    def on_save_as_activate(self, *args):
        dlgSaveResults = dlgSaveAs.dlgSaveAs("pyfind.glade","dlgSaveAs", self.sMode)
        dlgSaveResults.init_dlgSaveAs(self)
        
    # display Preferences dialog
    def on_preferences_activate(self, *args):
        dlgPrefs = dlgPreferences.dlgPreferences("pyfind.glade","dlgPreferences", self.sMode)
        dlgPrefs.init_Preferences(self)
        
    # display About dialog 
    def on_about_activate(self, *args):
        #set glade file name
        if self.sMode == "development":
            #development version
            sPixmap = os.path.join("pixmaps", "pyFind3.png")
        else:
            #production version
            sPixmap = gnome.util.datadir_file( os.path.join("pyFind/pixmaps", "pyFind3.png")) 
        dlgAbout = gnome.ui.GnomeAbout( config.app_name, \
                       config.app_version, \
                       "GPL (c) 2001-2002 Andy Balcombe", \
                       config.authors, \
                       "pyFind - a simple Gnome file find utility", \
                       sPixmap )
        dlgAbout.show()

    # Open selected files
    def on_cmdFOpen_clicked(self, *args):
        #get the name of the Gnome editor
        confEditor = config.GnomeConfig("editor")
        #for each file in selection
        lSelected = self.clstFiles.selection
        sFilename = ""
        for iRow in lSelected:
            sFilename = sFilename + " " + \
                        self.clstFiles.get_text(iRow,2) + "/" + \
                        self.clstFiles.get_text(iRow,1) 
        #open the editor with a list of files
        sCmd = "gnome-edit %s &" % (sFilename)
        os.system( sCmd )

    # Delete selected files
    def on_cmdFDelete_clicked(self, *args):
        lSelected = self.clstFiles.selection
        self.lDelFiles=[] #empty list
        for iRow in lSelected:
            sFilename = self.clstFiles.get_text(iRow,2) + "/" + \
                        self.clstFiles.get_text(iRow,1) 
            self.lDelFiles.append([iRow,sFilename])
        if self.lDelFiles != []:
            sMsg = "Are you sure you want to delete the " + str(len(self.lDelFiles)) + " selected files?"
            ctlMsgBox = gnome.ui.GnomeQuestionDialog( sMsg, self.on_ctlMsgBox_question, self.appMain)

    # callback for delete files question box
    def on_ctlMsgBox_question(self, button, *args):
        #print "on_ctlMsgBox_question=",button
        if button == 0: #yes
            #print "self.lDelFiles=",self.lDelFiles
            i=0
            for iRow, sFile in self.lDelFiles:
                try:
                    os.remove( sFile )
                    self.clstFiles.remove( iRow-i )
                    i=i+1
                except:
                    sErrMsg = "Error - Cannot remove file:\n " + sFile
                    ctlMsgBox = GnomeErrorDialog(sErrMsg, self.appMain)
        #remove file list
        del self.lDelFiles

    # file list (column heading)
    def on_clstFiles_click_column(self, ctlCList, iCol, *args):
        #sort the results list
        self.clstFiles.set_sort_column(iCol)
        self.clstFiles.sort()

    def on_clstFiles_drag_drop(self, w, context, x, y, time):
        pass

    # called when a 'drop' occurs on a dnd target
    def on_clstFiles_drag_data_get(self,w,context,selection_data,info, time):
        sFiles="" #file list
        #for each selected file...
        lSelected = self.clstFiles.selection
        for iRow in lSelected:
            #basic filename
            sFilename = self.clstFiles.get_text(iRow,2) + "/" + \
                        self.clstFiles.get_text(iRow,1) 
            if selection_data.target == self.targets[2][0]:
                #text/uri-list
                sFilename = "file://" + sFilename + "\r\n"
            else:
                #STRING or text/plain
                sFilename = sFilename + "\n"
            #add to list
            sFiles = sFiles + sFilename
        selection_data.set(selection_data.target, 8, sFiles)

    def on_clstFiles_drag_begin(self, targets, actions):
        #start of a dnd thingy
        pass
        
    # file list (row selected)
    def on_clstFiles_select_row(self, ctlCList, iRow, iCol, iX, *args):
        self.set_file_buttons()

    # file list (row unselected)
    def on_clstFiles_unselect_row(self, ctlCList, iRow, iCol, iX, *args):
        self.set_file_buttons()

    # file filter tab
    # File Size
    def on_chkFileSize_toggled(self, *args):
        bEnabled = self.chkFileSize.get_active()
        self.cboFileSize.set_sensitive( bEnabled )
        self.spnFileSize.set_sensitive( bEnabled )
        self.lblKb.set_sensitive( bEnabled )

    # Previous
    def on_chkPreviousDays_toggled(self, *args):
        bEnabled = self.chkPreviousDays.get_active()
        self.spnPreviousDays.set_sensitive( bEnabled )
        self.cboMDays.set_sensitive( bEnabled )
        
    # Date Range
    def on_chkBetween_toggled(self, *args):
        bEnabled = self.chkBetween.get_active()
        self.dteBetweenStart.set_sensitive( bEnabled )
        self.dteBetweenEnd.set_sensitive( bEnabled )
        self.lblPrevious.set_sensitive( bEnabled )

    # Replace Tab
    # search and replace
    def on_chkReplace_toggled(self, *args):
        bEnabled = self.chkReplace.get_active()        
        self.chkRegExp.set_sensitive( bEnabled )
        self.lblRepSearch.set_sensitive( bEnabled )
        self.txeRepSearch.set_sensitive( bEnabled )
        self.lblRepReplace.set_sensitive( bEnabled )
        self.txeRepReplace.set_sensitive( bEnabled )

    # case sensitive reg exp matching
    def on_chkRegExp_toggled(self, *args):
        bEnabled = self.chkRegExp.get_active()        
        self.chkRepCaseSensitive.set_sensitive( bEnabled )

    #done, quit the application
    def on_appMain_destroy (self, *args):
        gtk.mainquit()

