korganizer

searchdialog.cpp
1 /*
2  This file is part of KOrganizer.
3 
4  Copyright (c) 1998 Preston Brown <pbrown@kde.org>
5  Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
6  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 
22  As a special exception, permission is given to link this program
23  with any edition of TQt, and distribute the resulting executable,
24  without including the source code for TQt in the source distribution.
25 */
26 
27 #include <tqlayout.h>
28 #include <tqcheckbox.h>
29 #include <tqgroupbox.h>
30 #include <tqhbuttongroup.h>
31 #include <tqlabel.h>
32 #include <tqlineedit.h>
33 
34 #include <tdelocale.h>
35 #include <tdemessagebox.h>
36 
37 #include <libkcal/calendar.h>
38 
39 #include <libtdepim/kdateedit.h>
40 
41 #include "koglobals.h"
42 #include "koprefs.h"
43 #include "kolistview.h"
44 
45 #include "searchdialog.h"
46 #include "searchdialog.moc"
47 
48 SearchDialog::SearchDialog(Calendar *calendar,TQWidget *parent)
49  : KDialogBase(Plain,i18n("Find Events"),User1|Close,User1,parent,0,false,false,
50  KGuiItem( i18n("&Find"), "edit-find") )
51 {
52  mCalendar = calendar;
53 
54  TQFrame *topFrame = plainPage();
55  TQVBoxLayout *layout = new TQVBoxLayout(topFrame,0,spacingHint());
56 
57  // Search expression
58  TQHBoxLayout *subLayout = new TQHBoxLayout();
59  layout->addLayout(subLayout);
60 
61  searchEdit = new TQLineEdit( "*", topFrame ); // Find all events by default
62  searchLabel = new TQLabel( searchEdit, i18n("&Search for:"), topFrame );
63  subLayout->addWidget( searchLabel );
64  subLayout->addWidget( searchEdit );
65  searchEdit->setFocus();
66  connect( searchEdit, TQ_SIGNAL( textChanged( const TQString & ) ),
67  this, TQ_SLOT( searchTextChanged( const TQString & ) ) );
68 
69 
70  TQHButtonGroup *itemsGroup = new TQHButtonGroup( i18n("Search For"), topFrame );
71  layout->addWidget( itemsGroup );
72  mEventsCheck = new TQCheckBox( i18n("&Events"), itemsGroup );
73  mTodosCheck = new TQCheckBox( i18n("To-&dos"), itemsGroup );
74  mJournalsCheck = new TQCheckBox( i18n("&Journal entries"), itemsGroup );
75  mEventsCheck->setChecked( true );
76  mTodosCheck->setChecked( true );
77 
78  // Date range
79  TQGroupBox *rangeGroup = new TQGroupBox( 1, TQt::Horizontal, i18n( "Date Range" ),
80  topFrame );
81  layout->addWidget( rangeGroup );
82 
83  TQWidget *rangeWidget = new TQWidget( rangeGroup );
84  TQHBoxLayout *rangeLayout = new TQHBoxLayout( rangeWidget, 0, spacingHint() );
85 
86  mStartDate = new KDateEdit( rangeWidget );
87  rangeLayout->addWidget( new TQLabel( mStartDate, i18n("Fr&om:"), rangeWidget ) );
88  rangeLayout->addWidget( mStartDate );
89 
90  mEndDate = new KDateEdit( rangeWidget );
91  rangeLayout->addWidget( new TQLabel( mEndDate, i18n("&To:"), rangeWidget ) );
92  mEndDate->setDate( TQDate::currentDate().addDays( 365 ) );
93  rangeLayout->addWidget( mEndDate );
94 
95  mInclusiveCheck = new TQCheckBox( i18n("E&vents have to be completely included"),
96  rangeGroup );
97  mInclusiveCheck->setChecked( false );
98  mIncludeUndatedTodos = new TQCheckBox( i18n("Include to-dos &without due date"), rangeGroup );
99  mIncludeUndatedTodos->setChecked( true );
100 
101  // Subjects to search
102  TQHButtonGroup *subjectGroup = new TQHButtonGroup( i18n("Search In"), topFrame );
103  layout->addWidget(subjectGroup);
104 
105  mSummaryCheck = new TQCheckBox( i18n("Su&mmaries"), subjectGroup );
106  mSummaryCheck->setChecked( true );
107  mDescriptionCheck = new TQCheckBox( i18n("Desc&riptions"), subjectGroup );
108  mCategoryCheck = new TQCheckBox( i18n("Cate&gories"), subjectGroup );
109 
110 
111  // Results list view
112  listView = new KOListView( mCalendar, topFrame );
113  listView->showDates();
114  layout->addWidget( listView );
115 
116  if ( KOPrefs::instance()->mCompactDialogs ) {
117  KOGlobals::fitDialogToScreen( this, true );
118  }
119 
120  connect( this,TQ_SIGNAL(user1Clicked()),TQ_SLOT(doSearch()));
121 
122  // Propagate edit and delete event signals from event list view
123  connect( listView, TQ_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)),
124  TQ_SIGNAL(showIncidenceSignal(Incidence *,const TQDate &)) );
125  connect( listView, TQ_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)),
126  TQ_SIGNAL(editIncidenceSignal(Incidence *,const TQDate &)) );
127  connect( listView, TQ_SIGNAL(deleteIncidenceSignal(Incidence *)),
128  TQ_SIGNAL(deleteIncidenceSignal(Incidence *)) );
129 }
130 
131 SearchDialog::~SearchDialog()
132 {
133 }
134 
135 void SearchDialog::searchTextChanged( const TQString &_text )
136 {
137  enableButton( KDialogBase::User1, !_text.isEmpty() );
138 }
139 
140 void SearchDialog::doSearch()
141 {
142  TQRegExp re;
143 
144  re.setWildcard( true ); // most people understand these better.
145  re.setCaseSensitive( false );
146  re.setPattern( searchEdit->text() );
147  if ( !re.isValid() ) {
148  KMessageBox::sorry( this,
149  i18n("Invalid search expression, cannot perform "
150  "the search. Please enter a search expression "
151  "using the wildcard characters '*' and '?' "
152  "where needed." ) );
153  return;
154  }
155 
156  search( re );
157 
158  listView->showIncidences( mMatchedEvents, TQDate() );
159 
160  if ( mMatchedEvents.count() == 0 ) {
161  KMessageBox::information( this,
162  i18n("No events were found matching your search expression."),
163  "NoSearchResults" );
164  }
165 }
166 
167 void SearchDialog::updateView()
168 {
169  TQRegExp re;
170  re.setWildcard( true ); // most people understand these better.
171  re.setCaseSensitive( false );
172  re.setPattern( searchEdit->text() );
173  if ( re.isValid() ) {
174  search( re );
175  } else {
176  mMatchedEvents.clear();
177  }
178 
179  listView->showIncidences( mMatchedEvents, TQDate() );
180 }
181 
182 void SearchDialog::search( const TQRegExp &re )
183 {
184  TQDate startDt = mStartDate->date();
185  TQDate endDt = mEndDate->date();
186 
187  Event::List events;
188  if (mEventsCheck->isChecked()) {
189  events = mCalendar->events( startDt, endDt, mInclusiveCheck->isChecked() );
190  }
191  Todo::List todos;
192  if (mTodosCheck->isChecked()) {
193  if ( mIncludeUndatedTodos->isChecked() ) {
194  Todo::List alltodos = mCalendar->todos();
195  Todo::List::iterator it;
196  Todo *todo;
197  for (it=alltodos.begin(); it!=alltodos.end(); ++it) {
198  todo = *it;
199  if ( (!todo->hasStartDate() && !todo->hasDueDate() ) || // undated
200  ( todo->hasStartDate() && (todo->dtStart()>=TQDateTime(startDt)) && (todo->dtStart()<=TQDateTime(endDt)) ) || // start dt in range
201  ( todo->hasDueDate() && (todo->dtDue().date()>=startDt) && (todo->dtDue()<=TQDateTime(endDt)) ) || // due dt in range
202  ( todo->hasCompletedDate() && (todo->completed().date()>=startDt) && (todo->completed()<=TQDateTime(endDt)) ) ) { // completed dt in range
203  todos.append( todo );
204  }
205  }
206  } else {
207  TQDate dt = startDt;
208  while ( dt <= endDt ) {
209  todos += mCalendar->todos( dt );
210  dt = dt.addDays( 1 );
211  }
212  }
213  }
214 
215  Journal::List journals;
216  if (mJournalsCheck->isChecked()) {
217  TQDate dt = startDt;
218  while ( dt <= endDt ) {
219  journals += mCalendar->journals( dt );
220  dt = dt.addDays( 1 );
221  }
222  }
223 
224  Incidence::List allIncidences = Calendar::mergeIncidenceList( events, todos, journals );
225 
226  mMatchedEvents.clear();
227  Incidence::List::ConstIterator it;
228  for( it = allIncidences.begin(); it != allIncidences.end(); ++it ) {
229  Incidence *ev = *it;
230  if ( mSummaryCheck->isChecked() ) {
231  if ( re.search( ev->summary() ) != -1 ) {
232  mMatchedEvents.append( ev );
233  continue;
234  }
235  }
236  if ( mDescriptionCheck->isChecked() ) {
237  if ( re.search( ev->description() ) != -1 ) {
238  mMatchedEvents.append( ev );
239  continue;
240  }
241  }
242  if ( mCategoryCheck->isChecked() ) {
243  if ( re.search( ev->categoriesStr() ) != -1 ) {
244  mMatchedEvents.append( ev );
245  continue;
246  }
247  }
248  }
249 }
TQString description() const
TQString categoriesStr() const
TQString summary() const
bool hasDueDate() const
bool hasStartDate() const
TQDateTime dtStart(bool first=false) const
TQDateTime completed() const
bool hasCompletedDate() const
TQDateTime dtDue(bool first=false) const
This class provides a multi-column list view of events.
Definition: kolistview.h:69