# Copyright 2004,2005 Pierre Martineau <pmartino@users.sourceforge.net>
# This file is part of Bibus, a bibliographic database that can
# work together with OpenOffice.org to generate bibliographic indexes.
#
# Bibus 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.
#
# Bibus 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bibus; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
#
# generated by wxGlade 0.2 on Wed May 28 22:47:35 2003
# Then edited by hand
# DO NOT EDIT WITH wxGLADE

import wx
import BIB

class Search(wx.Dialog):
	def __init__(self,bibus_frame, *args, **kwds):
		kwds["style"] = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL
		wx.Dialog.__init__(self,*args, **kwds)
		self.SearchList = [_('Main Fields')] + [ BIB.NAME_FIELD[field] for field in BIB.BIB_FIELDS ]
		self.SearchBool = [u'AND',u'OR']
		self.SearchEquList = [u'LIKE',u'NOT LIKE',u'=',u'!=',u'>',u'>=',u'<',u'<=']
		self.parenthesisLeft = [u'',u'(']
		self.parenthesisRight = [u'',u')']
		self.bibus_frame = bibus_frame
		self.db = bibus_frame.db	# database
		self.keytree = bibus_frame.keytree	# keytree
		self.Selected = self.bibus_frame.keytree.GetSelection()
		self.key_id,self.user,self.id = self.bibus_frame.keytree.GetPyData(self.Selected)
		# Top of the Dialog
		self.Mode = wx.RadioBox(self, -1, _("Mode"), choices=[_('Normal'), _('Expert')], majorDimension=0, style=wx.RA_SPECIFY_COLS)
		self.SearchIn = wx.RadioBox(self, -1, _("Search in"), choices=[_('Current key'), _('All references')], majorDimension=0, style=wx.RA_SPECIFY_COLS)
		self.static_line_1 = wx.StaticLine(self, -1)
		#
		# TextCtrl to enter query in expert mode
		self.ExpertValue = wx.TextCtrl(self, -1, u"", style=wx.TE_MULTILINE)
		# Panel that contains the grid
		self.PanelSearch = wx.Panel(self,-1)
		# Search grid
		self.ScrollWin = wx.ScrolledWindow(self.PanelSearch,style=wx.TAB_TRAVERSAL)	# in order to be able to scroll the choices grid
		self.ScrollWin.SetScrollRate(10,10)
		self.SearchBoolKey=[]
		self.SearchChoice=[]
		self.SearchEqu = []
		self.SearchValue=[]
		self.SearchParenthesisLeft=[]
		self.SearchParenthesisRight=[]
		#
		self.SearchBoolKey.append(wx.StaticText(self.ScrollWin, -1, u" "))	# first line special since there is no bool choice
		self.SearchParenthesisLeft.append(wx.Choice(self.ScrollWin, -1, choices=self.parenthesisLeft))
		self.SearchChoice.append(wx.Choice(self.ScrollWin, -1, choices=self.SearchList))
		self.SearchEqu.append(wx.Choice(self.ScrollWin, -1, choices=self.SearchEquList))
		self.SearchValue.append(wx.TextCtrl(self.ScrollWin, -1, u"",size=(250,-1)))
		self.SearchParenthesisRight.append(wx.Choice(self.ScrollWin, -1, choices=self.parenthesisRight))
		for line in range(1,4):
			self.SearchBoolKey.append(wx.Choice(self.ScrollWin, -1, choices=self.SearchBool))
			self.SearchParenthesisLeft.append(wx.Choice(self.ScrollWin, -1, choices=self.parenthesisLeft))
			self.SearchChoice.append(wx.Choice(self.ScrollWin, -1, choices=self.SearchList))
			self.SearchEqu.append(wx.Choice(self.ScrollWin, -1, choices=self.SearchEquList))
			self.SearchValue.append(wx.TextCtrl(self.ScrollWin, -1, u""))
			self.SearchParenthesisRight.append(wx.Choice(self.ScrollWin, -1, choices=self.parenthesisRight))
		# Button to add line
		self.static_line_2 = wx.StaticLine(self.PanelSearch, -1)
		self.button_Add = wx.Button(self.PanelSearch, -1, _("Add a line"))
		self.static_line_3 = wx.StaticLine(self, -1)
		# Static text to explain 'Main Fields'
		self.explain = wx.StaticText(self.PanelSearch, -1, _("Main Fields = %s") % u'+'.join([BIB.NAME_FIELD[field] for field in BIB.BIB_SEARCH_FIELDS]))
		#
		self.button_Cancel = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
		self.button_Search = wx.Button(self, wx.ID_OK, _("Search"))
		self.button_SearchClose = wx.Button(self, -1, _("Search && Close"))

		self.__set_properties()
		self.__do_layout()
		self.__set_event()
		self.SetDimensions(BIB.SEARCH_X, BIB.SEARCH_Y, BIB.SEARCH_WIDTH, BIB.SEARCH_HEIGHT)
		#self.CenterOnParent()

	def __set_properties(self):
		self.SetTitle(_("Search"))
		self.Mode.SetSelection(0)	# Normal mode
		if self.id == BIB.ID_REF_ROOT or self.id == BIB.ID_REF:
			self.SearchIn.SetSelection(0)
		else:
			self.SearchIn.SetSelection(1)
		self.SearchChoice[0].SetSelection(0)
		self.SearchEqu[0].SetSelection(0)
		for line in range(1,4):
			self.SearchChoice[line].SetSelection(0)
			self.SearchBoolKey[line].SetSelection(0)
			self.SearchEqu[line].SetSelection(0)
		self.button_Search.SetDefault()
		self.SearchValue[0].SetFocus()	# we give focus to the first entry box

	def __do_layout(self):
		sizer_1 = wx.BoxSizer(wx.VERTICAL)	# top sizer if the dialog window
		sizer_2 = wx.BoxSizer(wx.HORIZONTAL)	# for top of the dialog
		self.grid_sizer_1 = wx.FlexGridSizer(0, 6, vgap=0, hgap=0)	# main grid
		self.sizer = wx.BoxSizer(wx.VERTICAL) # sizer enclosing scrolled window + button 'Add line' = sizer of self.PanelSearch
		sizer_3 = wx.BoxSizer(wx.HORIZONTAL)	# for buttons (bottom)
		#
		# Set top of the dialog
		sizer_2.Add(self.Mode,0,wx.ALIGN_LEFT|wx.ALL,5)
		sizer_2.Add(self.SearchIn,0,wx.ALIGN_RIGHT|wx.ALL,5)
		sizer_1.Add(sizer_2,0,wx.EXPAND,0)
		sizer_1.Add(self.static_line_1,0,wx.EXPAND,0)
		# Line explaining 'Main Fields' meaning
		self.sizer.Add(self.explain,0,wx.EXPAND|wx.ALL,5)
		self.sizer.Add(wx.StaticLine(self.PanelSearch, -1),0,wx.EXPAND,0)
		# Set grid
		for line in range(4):
			self.grid_sizer_1.Add(self.SearchBoolKey[line],0,0,0)
			self.grid_sizer_1.Add(self.SearchParenthesisLeft[line],0,0,0)
			self.grid_sizer_1.Add(self.SearchChoice[line],0,0,0)
			self.grid_sizer_1.Add(self.SearchEqu[line],0,0,0)
			self.grid_sizer_1.Add(self.SearchValue[line],0,wx.EXPAND,0)
			self.grid_sizer_1.Add(self.SearchParenthesisRight[line],0,0,0)
		self.grid_sizer_1.AddGrowableCol(4)
		self.ScrollWin.SetSizer(self.grid_sizer_1)
		self.grid_sizer_1.Fit(self.ScrollWin)
		#self.grid_sizer_1.SetSizeHints(self.ScrollWin)
		self.ScrollWin.Layout()
		self.sizer.Add(self.ScrollWin,1,wx.EXPAND,0)
		# Add line button
		self.sizer.Add(self.static_line_2,0,wx.EXPAND,0)
		self.sizer.Add(self.button_Add,0,wx.EXPAND,0)
		self.PanelSearch.SetSizerAndFit(self.sizer)
		#
		sizer_1.Add(self.PanelSearch,1,wx.EXPAND,0)
		# when expert selected
		sizer_1.Add(self.ExpertValue,1,wx.EXPAND,0)
		sizer_1.Show(self.ExpertValue,False)	# Masked at startup
		#
		sizer_1.Add(self.static_line_3,0,wx.EXPAND,0)
		#
		# Set Bottom Buttons
		sizer_3.Add(self.button_Cancel, 0, wx.ALL,5)
		sizer_3.Add(self.button_Search, 0, wx.ALL,5)
		sizer_3.Add(self.button_SearchClose, 0, wx.ALL,5)
		sizer_1.Add(sizer_3,0,wx.ALIGN_CENTER_HORIZONTAL,0)
		#
		self.SetAutoLayout(1)
		self.SetSizer(sizer_1)
		sizer_1.Fit(self)
		sizer_1.SetSizeHints(self)
		self.Layout()

	def __set_event(self):
		wx.EVT_BUTTON(self,wx.ID_OK,self.onSearch)
		wx.EVT_BUTTON(self,wx.ID_CANCEL,self.onCloseWindow)
		wx.EVT_CLOSE(self, self.onCloseWindow)
		wx.EVT_BUTTON(self,self.button_Add.GetId(),self.addLine)
		wx.EVT_BUTTON(self,self.button_SearchClose.GetId(),self.onSearchClose)
		wx.EVT_RADIOBOX(self,self.Mode.GetId(),self.onMode)

	def onMode(self,event):
		selection = self.Mode.GetStringSelection()
		if selection == _('Normal'):
			self.GetSizer().Show(self.ExpertValue,False)
			self.GetSizer().Show(self.PanelSearch,True)
		else:
			searchStr = self.__constructSearch()
			self.ExpertValue.SetValue(searchStr)
			self.GetSizer().Show(self.PanelSearch,False)
			self.GetSizer().Show(self.ExpertValue,True)
		self.Layout()

	def addLine(self,event):
		self.SearchBoolKey.append(wx.Choice(self.ScrollWin, -1, choices=self.SearchBool))
		self.SearchParenthesisLeft.append(wx.Choice(self.ScrollWin, -1, choices=self.parenthesisLeft))
		self.SearchChoice.append(wx.Choice(self.ScrollWin, -1, choices=self.SearchList))
		self.SearchEqu.append(wx.Choice(self.ScrollWin, -1, choices=self.SearchEquList))
		self.SearchValue.append(wx.TextCtrl(self.ScrollWin, -1, u""))
		self.SearchParenthesisRight.append(wx.Choice(self.ScrollWin, -1, choices=self.parenthesisRight))
		self.grid_sizer_1.Add(self.SearchBoolKey[-1],0,0,0)
		self.grid_sizer_1.Add(self.SearchParenthesisLeft[-1],0,0,0)
		self.grid_sizer_1.Add(self.SearchChoice[-1],0,0,0)
		self.grid_sizer_1.Add(self.SearchEqu[-1],0,0,0)
		self.grid_sizer_1.Add(self.SearchValue[-1],0,wx.EXPAND,0)
		self.grid_sizer_1.Add(self.SearchParenthesisRight[-1],0,0,0)
		self.grid_sizer_1.Fit(self.ScrollWin)
		self.PanelSearch.Layout()
		self.Layout()

	def onCloseWindow(self,event):
		BIB.SEARCH_WIDTH, BIB.SEARCH_HEIGHT = self.GetSizeTuple()
		BIB.SEARCH_X, BIB.SEARCH_Y = self.GetPositionTuple()
		self.Destroy()

	def onSearchClose(self,event):
		self.onSearch(event)
		self.onCloseWindow(event)

	def __anyField(self,searchStr,equ):
		ret=u''
		if equ == u'LIKE' or equ == u'=':
			link = u'OR'
		else:
			link = u'AND'
		for field in BIB.BIB_SEARCH_FIELDS:	# search in 'interesting' fields
			ret = u"""%s %s %s %s '%s'""" %(ret,link,field,equ,searchStr.replace(u"'",u"\\'"))
		ret = ret[1+len(link):]	# remove the first ' OR'
		return u'(' + ret + u')'

	def __constructSearch(self):
		line = 0
		search = u''
		try:
			while self.SearchValue[line].GetValue() == u'': line = line +1
			equ = self.SearchEqu[line].GetStringSelection()
			searchStr = self.SearchValue[line].GetValue().strip()
			if equ==u'LIKE':
				searchStr=u'%'+searchStr+u'%'
			if self.SearchChoice[line].GetSelection() == 0:	# == 'Main Fields'
				search = u"""%s%s%s""" %(self.SearchParenthesisLeft[line].GetStringSelection(),self.__anyField(searchStr,equ),self.SearchParenthesisRight[line].GetStringSelection())
			else:
				search=u"""%s%s %s '%s'%s""" %(self.SearchParenthesisLeft[line].GetStringSelection(),BIB.BIB_FIELDS[self.SearchChoice[line].GetSelection()-1],equ,searchStr.replace(u"'",u"\\'"),self.SearchParenthesisRight[line].GetStringSelection())
			line = line +1
			while True:
				equ = self.SearchEqu[line].GetStringSelection()
				searchStr = self.SearchValue[line].GetValue().strip()
				if searchStr:
					if equ==u'LIKE': searchStr=u'%'+searchStr+u'%'
					if self.SearchChoice[line].GetSelection() == 0:	# == 'Main Fields'
						search = u"""%s %s %s%s%s""" %(search,self.SearchBoolKey[line].GetStringSelection(),self.SearchParenthesisLeft[line].GetStringSelection(),self.__anyField(searchStr,equ),self.SearchParenthesisRight[line].GetStringSelection())
					else:
						search = u"""%s %s %s%s %s '%s'%s""" %(search,self.SearchBoolKey[line].GetStringSelection(),self.SearchParenthesisLeft[line].GetStringSelection(),BIB.BIB_FIELDS[self.SearchChoice[line].GetSelection()-1],equ,searchStr.replace(u"'",u"\\'"),self.SearchParenthesisRight[line].GetStringSelection())
				line = line +1
		except IndexError: pass
		return search
		#print search
		
	def __checkParenthesis(self,searchStr):
		nbopenParenthesis = searchStr.count("(")
		nbclosedParenthesis = searchStr.count(")")
		if nbopenParenthesis != nbclosedParenthesis:
			wx.LogError(_("Error in the number of parentheses: %(open)s ( and %(close)s )") %{'open':nbopenParenthesis,'close':nbclosedParenthesis})
		return

	def onSearch(self,event):
		shortSearch = self.bibus_frame.toolbar.searchtxt1.GetValue()	# keep the value of the search field (toolbar)
		if self.Mode.GetSelection() == 0:		# normal mode
			searchStr = self.__constructSearch()
		else:									# expert mode
			searchStr = self.ExpertValue.GetValue()
		self.__checkParenthesis(searchStr)
		Selected = self.bibus_frame.keytree.GetSelection()	# current key
		key_id,user,id = self.bibus_frame.keytree.GetPyData(Selected)
		if self.SearchIn.GetSelection() == 0 and (id == BIB.ID_REF_ROOT or id == BIB.ID_REF):	# current key possible
			if searchStr != u'':
				refList = self.db.getRefKeySearch(key_id,searchStr,BIB.LIST_DISPLAY,BIB.LIST_ORDER,BIB.LIST_HOW,short=True)
			else:
				refList = self.db.getRefKey(key_id,BIB.LIST_DISPLAY,BIB.LIST_ORDER,BIB.LIST_HOW,short=True)
		else:
			self.SearchIn.SetSelection(1)
			if searchStr != u'':
				refList = self.db.getAllRefSearch(user,searchStr,BIB.LIST_DISPLAY,BIB.LIST_ORDER,BIB.LIST_HOW,short=True)
			else:
				refList = self.db.getAllRef(self.user,BIB.LIST_DISPLAY,BIB.LIST_ORDER,BIB.LIST_HOW,short=True)
			self.bibus_frame.keytree.SelectItem(self.bibus_frame.keytree.keyAll)
		if self.IsShown():	# we used the dialog for the search
			self.bibus_frame.toolbar.choice1.SetStringSelection(_('Expert Search'))
			self.bibus_frame.toolbar.displaySearch(searchStr)	# display the last search in query mode
		else:			# we used the toolbar search
			self.bibus_frame.toolbar.searchtxt1.SetValue(shortSearch)	# display the last search in search mode
		#print 'Search result = ',refList
		self.bibus_frame.updateList(refList)

	def __showError(self):
		dlg=wx.MessageDialog(self, _("Error during query"), caption = _("Error"), style = wx.OK | wx.CENTRE | wx.ICON_ERROR, pos = wx.DefaultPosition)
		try:
			dlg.ShowModal()
		finally:
			dlg.Destroy()


# end of class Search

class Query(Search):
	def __init__(self,user,queryname,*args, **kwds):
		Search.__init__(self,*args, **kwds)
		self.user = user
		self.queryname = queryname
		self.SearchIn.SetSelection(1)	# 'All references' choice
		self.SearchIn.Enable(False)		# choice 'current key' not possible
		self.button_Search.SetLabel(_("Save"))	# relabel the button save
		self.button_SearchClose.Show(False)	# remove the button save & close

	def onSearch(self,event):
		self.onSave(event)
		self.onCloseWindow(event)

	def onCloseWindow(self,event):
		self.EndModal(0)

	def onSave(self,event):
		if self.Mode.GetSelection() == 0:		# normal mode
			searchStr = self._Search__constructSearch()
		else:									# expert mode
			searchStr = self.ExpertValue.GetValue()
		self.db.writeNewQuery(self.user,self.queryname,searchStr)


class EditQuery(Query):
	def __init__(self,user,queryname,queryvalue,query_id,*args, **kwds):
		Query.__init__(self,user,queryname,*args, **kwds)
		self.queryvalue = queryvalue
		self.query_id = query_id
		self.Mode.SetSelection(1)	# expert mode
		self.onMode(None)
		self.ExpertValue.SetValue(queryvalue)
		self.Mode.Enable(False)	# block to expert mode

	def onSave(self,event):
		searchStr = self.ExpertValue.GetValue()
		self.db.setQuery(self.query_id,searchStr)


