korganizer

datenavigatorcontainer.cpp
1 /*
2  This file is part of KOrganizer.
3 
4  Copyright (c) 2001,2002,2003 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, permission is given to link this program
22  with any edition of TQt, and distribute the resulting executable,
23  without including the source code for TQt in the source distribution.
24 */
25 
26 #include <kdebug.h>
27 #include <tdelocale.h>
28 
29 #include "koglobals.h"
30 #include "navigatorbar.h"
31 #include "kdatenavigator.h"
32 #include "kodaymatrix.h"
33 
34 #include <kcalendarsystem.h>
35 #include <kdialog.h>
36 
37 #include "datenavigatorcontainer.h"
38 
39 #include <tqwhatsthis.h>
40 #include <tqtimer.h>
41 
42 DateNavigatorContainer::DateNavigatorContainer( TQWidget *parent,
43  const char *name )
44  : TQFrame( parent, name ), mCalendar( 0 ),
45  mHorizontalCount( 1 ), mVerticalCount( 1 )
46 {
47  mExtraViews.setAutoDelete( true );
48  setFrameStyle( TQFrame::Sunken | TQFrame::StyledPanel );
49 
50  mNavigatorView = new KDateNavigator( this, name );
51  TQWhatsThis::add( mNavigatorView,
52  i18n( "<qt><p>Select the dates you want to "
53  "display in KOrganizer's main view here. Hold down the "
54  "mouse button to select more than one day.</p>"
55  "<p>Press the top buttons to browse to the next "
56  "/ previous months or years.</p>"
57  "<p>Each line shows a week. The number in the left "
58  "column is the number of the week in the year. "
59  "Press it to select the whole week.</p>"
60  "</qt>" ) );
61 
62  connectNavigatorView( mNavigatorView );
63 }
64 
65 DateNavigatorContainer::~DateNavigatorContainer()
66 {
67 }
68 
69 void DateNavigatorContainer::connectNavigatorView( KDateNavigator *v )
70 {
71  connect( v, TQ_SIGNAL( datesSelected( const KCal::DateList & ) ),
72  TQ_SIGNAL( datesSelected( const KCal::DateList & ) ) );
73  connect( v, TQ_SIGNAL( incidenceDropped( Incidence *, const TQDate & ) ),
74  TQ_SIGNAL( incidenceDropped( Incidence *, const TQDate & ) ) );
75  connect( v, TQ_SIGNAL( incidenceDroppedMove( Incidence *, const TQDate & ) ),
76  TQ_SIGNAL( incidenceDroppedMove( Incidence *, const TQDate & ) ) );
77  connect( v, TQ_SIGNAL( weekClicked( const TQDate & ) ),
78  TQ_SIGNAL( weekClicked( const TQDate & ) ) );
79 
80  connect( v, TQ_SIGNAL( goPrevious() ), TQ_SIGNAL( goPrevious() ) );
81  connect( v, TQ_SIGNAL( goNext() ), TQ_SIGNAL( goNext() ) );
82 
83  connect( v, TQ_SIGNAL( nextYearClicked() ), TQ_SIGNAL( nextYearClicked() ) );
84  connect( v, TQ_SIGNAL( prevYearClicked() ), TQ_SIGNAL( prevYearClicked() ) );
85 
86  connect( v, TQ_SIGNAL( prevMonthClicked() ), this, TQ_SLOT( goPrevMonth() ) );
87  connect( v, TQ_SIGNAL( nextMonthClicked() ), this, TQ_SLOT( goNextMonth() ) );
88 
89  connect( v, TQ_SIGNAL( monthSelected( int ) ), TQ_SIGNAL( monthSelected( int ) ) );
90  connect( v, TQ_SIGNAL( yearSelected( int ) ), TQ_SIGNAL( yearSelected( int ) ) );
91 }
92 
93 void DateNavigatorContainer::setCalendar( Calendar *cal )
94 {
95  mCalendar = cal;
96  mNavigatorView->setCalendar( cal );
97  KDateNavigator *n;
98  for( n = mExtraViews.first(); n; n = mExtraViews.next() ) {
99  n->setCalendar( cal );
100  }
101 }
102 
103 // TODO_Recurrence: let the navigators update just once, and tell them that
104 // if data has changed or just the selection (because then the list of dayss
105 // with events doesn't have to be updated if the month stayed the same
106 void DateNavigatorContainer::updateDayMatrix()
107 {
108  mNavigatorView->updateDayMatrix();
109  KDateNavigator *n;
110  for( n = mExtraViews.first(); n; n = mExtraViews.next() ) {
111  n->updateDayMatrix();
112  }
113 }
114 
115 void DateNavigatorContainer::updateToday()
116 {
117  mNavigatorView->updateToday();
118  KDateNavigator *n;
119  for( n = mExtraViews.first(); n; n = mExtraViews.next() ) {
120  n->updateToday();
121  }
122 }
123 
124 void DateNavigatorContainer::setUpdateNeeded()
125 {
126  mNavigatorView->setUpdateNeeded();
127  KDateNavigator *n;
128  for ( n = mExtraViews.first(); n; n = mExtraViews.next() ) {
129  n->setUpdateNeeded();
130  }
131 }
132 
133 void DateNavigatorContainer::updateView()
134 {
135  mNavigatorView->updateView();
136  KDateNavigator *n;
137  for ( n = mExtraViews.first(); n; n = mExtraViews.next() ) {
138  n->setUpdateNeeded();
139  }
140 }
141 
142 void DateNavigatorContainer::updateConfig()
143 {
144  mNavigatorView->updateConfig();
145  KDateNavigator *n;
146  for( n = mExtraViews.first(); n; n = mExtraViews.next() ) {
147  n->updateConfig();
148  }
149 }
150 
151 void DateNavigatorContainer::selectDates( const DateList &dateList, const TQDate &preferredMonth )
152 {
153  if ( !dateList.isEmpty() ) {
154  TQDate start( dateList.first() );
155  TQDate end( dateList.last() );
156  TQDate navfirst( mNavigatorView->startDate() );
157  TQDate navsecond; // start of the second shown month if existant
158  TQDate navlast;
159  if ( !mExtraViews.isEmpty() ) {
160  navlast = mExtraViews.last()->endDate();
161  navsecond = mExtraViews.first()->startDate();
162  } else {
163  navlast = mNavigatorView->endDate();
164  navsecond = navfirst;
165  }
166 
167  const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
168 
169  // If the datelist crosses months we won't know which month to show
170  // so we read what's in preferredMonth
171  const bool changingMonth = ( preferredMonth.isValid() &&
172  calSys->month( mNavigatorView->month() ) != calSys->month( preferredMonth ) );
173 
174  if ( start < navfirst // <- start should always be visible
175  // end is not visible and we have a spare month at the beginning:
176  || ( end > navlast && start >= navsecond )
177  || changingMonth ) {
178 
179  if ( preferredMonth.isValid() ) {
180  setBaseDates( preferredMonth );
181  } else {
182  setBaseDates( start );
183  }
184  }
185 
186  mNavigatorView->selectDates( dateList );
187  KDateNavigator *n = mExtraViews.first();
188  while ( n ) {
189  n->selectDates( dateList );
190  n = mExtraViews.next();
191  }
192  }
193 }
194 
195 void DateNavigatorContainer::setBaseDates( const TQDate &start )
196 {
197  TQDate baseDate = start;
198  mNavigatorView->setBaseDate( baseDate );
199  for( KDateNavigator *n = mExtraViews.first(); n; n = mExtraViews.next() ) {
200  baseDate = KOGlobals::self()->calendarSystem()->addMonths( baseDate, 1 );
201  n->setBaseDate( baseDate );
202  }
203 }
204 
205 void DateNavigatorContainer::resizeEvent( TQResizeEvent * )
206 {
207 #if 0
208  kdDebug(5850) << "DateNavigatorContainer::resizeEvent()" << endl;
209  kdDebug(5850) << " CURRENT SIZE: " << size() << endl;
210  kdDebug(5850) << " MINIMUM SIZEHINT: " << minimumSizeHint() << endl;
211  kdDebug(5850) << " SIZEHINT: " << sizeHint() << endl;
212  kdDebug(5850) << " MINIMUM SIZE: " << minimumSize() << endl;
213 #endif
214  TQTimer::singleShot( 0, this, TQ_SLOT( resizeAllContents() ) );
215 }
216 
217 void DateNavigatorContainer::resizeAllContents()
218 {
219  TQSize minSize = mNavigatorView->minimumSizeHint();
220 
221 // kdDebug(5850) << " NAVIGATORVIEW minimumSizeHint: " << minSize << endl;
222 
223  int margin = KDialog::spacingHint();
224  int verticalCount = ( size().height() - margin*2 ) / minSize.height();
225  int horizontalCount = ( size().width() - margin*2 ) / minSize.width();
226 
227  if ( horizontalCount != mHorizontalCount ||
228  verticalCount != mVerticalCount ) {
229  uint count = horizontalCount * verticalCount;
230  if ( count == 0 ) {
231  return;
232  }
233 
234  while ( count > ( mExtraViews.count() + 1 ) ) {
235  KDateNavigator *n = new KDateNavigator( this );
236  mExtraViews.append( n );
237  n->setCalendar( mCalendar );
238  connectNavigatorView( n );
239  }
240 
241  while ( count < ( mExtraViews.count() + 1 ) ) {
242  mExtraViews.removeLast();
243  }
244 
245  mHorizontalCount = horizontalCount;
246  mVerticalCount = verticalCount;
247  setBaseDates( mNavigatorView->selectedDates().first() );
248  selectDates( mNavigatorView->selectedDates() );
249  for( KDateNavigator *n = mExtraViews.first(); n; n = mExtraViews.next() ) {
250  n->show();
251  }
252  }
253 
254  int height = (size().height() - margin*2) / verticalCount;
255  int width = (size().width() - margin*2) / horizontalCount;
256 
257  NavigatorBar *bar = mNavigatorView->navigatorBar();
258  if ( horizontalCount > 1 ) {
259  bar->showButtons( true, false );
260  } else {
261  bar->showButtons( true, true );
262  }
263 
264  mNavigatorView->setGeometry(
265  ( ( (KOGlobals::self()->reverseLayout())?(horizontalCount-1):0) * width ) + margin,
266  margin, width, height );
267 
268  for( uint i = 0; i < mExtraViews.count(); ++i ) {
269  int x = ( i + 1 ) % horizontalCount;
270  int y = ( i + 1 ) / horizontalCount;
271 
272  KDateNavigator *view = mExtraViews.at( i );
273  bar = view->navigatorBar();
274  if ( y > 0 ) {
275  bar->showButtons( false, false );
276  } else {
277  if ( x + 1 == horizontalCount ) {
278  bar->showButtons( false, true );
279  } else {
280  bar->showButtons( false, false );
281  }
282  }
283  view->setGeometry(
284  ( ( (KOGlobals::self()->reverseLayout())?(horizontalCount-1-x):x) * width ) + margin,
285  ( y * height ) + margin, width, height );
286  }
287 }
288 
289 TQSize DateNavigatorContainer::minimumSizeHint() const
290 {
291  int margin = KDialog::spacingHint() * 2;
292  return mNavigatorView->minimumSizeHint() + TQSize( margin, margin );
293 }
294 
295 TQSize DateNavigatorContainer::sizeHint() const
296 {
297  int margin = KDialog::spacingHint() * 2;
298  return mNavigatorView->sizeHint() + TQSize( margin, margin );
299 }
300 
301 void DateNavigatorContainer::goNextMonth()
302 {
303  const TQPair<TQDate,TQDate> p = dateLimits( 1 );
304 
305  emit nextMonthClicked( mNavigatorView->month(),
306  p.first,
307  p.second);
308 }
309 
310 void DateNavigatorContainer::goPrevMonth()
311 {
312  const TQPair<TQDate,TQDate> p = dateLimits( -1 );
313 
314  emit prevMonthClicked( mNavigatorView->month(),
315  p.first,
316  p.second );
317 }
318 
319 TQPair<TQDate,TQDate> DateNavigatorContainer::dateLimits( int offset )
320 {
321  const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
322  TQDate firstMonth, lastMonth;
323  if ( mExtraViews.isEmpty() ) {
324  lastMonth = mNavigatorView->month();
325  } else {
326  lastMonth = mExtraViews.last()->month();
327  }
328 
329  firstMonth = calSys->addMonths( mNavigatorView->month(), offset );
330  lastMonth = calSys->addMonths( lastMonth, offset );
331 
332  TQPair<TQDate,TQDate> firstMonthBoundary = KODayMatrix::matrixLimits( firstMonth );
333  TQPair<TQDate,TQDate> lastMonthBoundary = KODayMatrix::matrixLimits( lastMonth );
334 
335  return qMakePair( firstMonthBoundary.first, lastMonthBoundary.second );
336 }
337 
338 #include "datenavigatorcontainer.moc"
static TQPair< TQDate, TQDate > matrixLimits(const TQDate &month)
returns the first and last date of the 6*7 matrix that displays month
bool view(TQWidget *parent, Attachment *attachment)