kspread

CalendarTool.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright 2008 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 // Local
00021 #include "CalendarTool.h"
00022 
00023 #include "CalendarToolWidget.h"
00024 
00025 #include <Sheet.h>
00026 #include <commands/DataManipulators.h>
00027 #include <part/Doc.h>
00028 
00029 #include <KCalendarSystem>
00030 #include <KGenericFactory>
00031 #include <KMessageBox>
00032 
00033 using namespace KSpread;
00034 
00035 class CalendarTool::Private
00036 {
00037 public:
00038 };
00039 
00040 
00041 CalendarTool::CalendarTool(KoCanvasBase* canvas)
00042     : CellTool(canvas)
00043     , d(new Private)
00044 {
00045     setObjectName("CalendarTool");
00046 /*
00047     KAction* importAction = new KAction(KIcon("document-import"), i18n("Import OpenDocument Spreadsheet File"), this);
00048     importAction->setIconText(i18n("Import"));
00049     addAction("import", importAction);
00050     connect(importAction, SIGNAL(triggered()), this, SLOT(importDocument()));*/
00051 }
00052 
00053 CalendarTool::~CalendarTool()
00054 {
00055     delete d;
00056 }
00057 
00058 void CalendarTool::activate(bool temporary)
00059 {
00060     CellTool::activate(temporary);
00061 }
00062 
00063 void CalendarTool::deactivate()
00064 {
00065     CellTool::deactivate();
00066 }
00067 
00068 void CalendarTool::insertCalendar(const QDate &start, const QDate &end)
00069 {
00070     if (end < start) {
00071         KMessageBox::error(0,i18n("End date is before start date! Please make sure that end date comes after start date."),i18n("Error"));
00072         return;
00073     }
00074 
00075     if (start.daysTo(end) > 3652) {
00076         KMessageBox::error(0,i18n("Calendars should not be longer than 10 years. If you really need such long periods you need to split them up."),i18n("Error"));
00077         return;
00078     }
00079 
00080     if (start == end) {
00081         if (KMessageBox::No == KMessageBox::warningYesNo(0,i18n("Start and end dates are equal! Only one day will be inserted, do you want to continue?"),i18n("Warning")))
00082             return;
00083     }
00084 
00085     if (start.daysTo(end)> 366) {
00086         if (KMessageBox::No == KMessageBox::warningYesNo(0,i18n("Creating a calendar for a longer period than a year can take up a lot of space, do you want to continue?"),i18n("Warning")))
00087             return;
00088     }
00089 
00090     const QPoint marker = this->selection()->lastRange().topLeft();
00091     Sheet* const sheet = this->selection()->activeSheet();
00092 
00093     //now let's check if the area is really empty...
00094     //we use two columns per day and one column for the week number
00095     int sizeX = 15;
00096     //we use two rows per week, some additional space between months...
00097     //so that should be ok, but can be improved of course
00098     //@todo improve calendar size prediction!
00099     int sizeY = 4 + (int)(0.5*(float)(start.daysTo(end)));
00100 
00101     if (!sheet->areaIsEmpty(Region(QRect(marker,QSize(sizeX,sizeY))))) {
00102         if (KMessageBox::No == KMessageBox::warningYesNo(0,i18n("The area where the calendar is inserted is NOT empty, are you sure you want to continue, overwriting existing data? If you choose No the area that would be required for the desired calendar will be selected so you can see what data would be overwritten."),i18n("Warning"))) {
00103             //select the area so the user knows what's in the way
00104             selection()->initialize(QRect(marker.x(),marker.y(),sizeX,sizeY));//,sheet);
00105             return;
00106         }
00107     }
00108 
00109     KCalendarSystem* cs = KCalendarSystem::create();
00110 
00111     Q_ASSERT(cs);
00112 
00113     sheet->doc()->beginMacro(i18n("Insert Calendar"));
00114 
00115     int row = marker.y();
00116     int col = marker.x();
00117     int colstart = col; //this is where we get back after each week
00118     setText(sheet, row, colstart, i18n("Calendar from %1 to %2", start.toString(), end.toString()));
00119 
00120     QDate current(start);
00121 //   QDate previous(current);
00122     bool yearheader = true;
00123     bool monthheader = true;
00124     bool weekheader = true;
00125 
00126     //this loop creates the actual calendar
00127     //@todo formatting of cells - each day occupies QRect(row,col,row,col+1)
00128     while (current <= end) {
00129         //let's see if any header is required
00130         if (cs->dayOfWeek(current)==1) {
00131             col=colstart;
00132             row++;
00133             weekheader=true;
00134         }
00135         if (cs->day(current)==1) {
00136             row+=2;
00137             col=colstart + (cs->dayOfWeek(current)-1)*2;
00138             monthheader=true;
00139             weekheader=true;
00140             if (cs->month(current)==1) {
00141                 row++;
00142                 yearheader=true;
00143             }
00144         }
00145 
00146         if (yearheader) {
00147             kDebug() <<"inserting year" + QString::number(current.year());
00148             setText(sheet,row, colstart + 6, cs->yearString(current, KCalendarSystem::LongFormat));
00149 
00150             row+=2;
00151             yearheader=false;
00152         }
00153         if (monthheader) {
00154             kDebug() <<"inserting month" + QString::number(current.month());
00155             setText(sheet, row, colstart + 6, cs->monthName(current, KCalendarSystem::LongName));
00156             row+=2;
00157             //we always have the week number in the first column
00158             setText(sheet, row, colstart, i18n("week"));
00159             for (int i=1; i<8; i++) {
00160                 setText(sheet, row, colstart + (i-1) * 2 + 1, cs->weekDayName(i));
00161             }
00162             row++;
00163             monthheader=false;
00164         }
00165         if (weekheader) {
00166             setText(sheet, row, colstart, QString::number(cs->weekNumber(current)));
00167             col++;
00168             weekheader=false;
00169 
00170             //if we are at the beginning of the month we might need an offset
00171             if (cs->day(current)==1) {
00172                 col=colstart + (cs->dayOfWeek(current)-1)*2 + 1;
00173             }
00174         }
00175 
00176         setText(sheet, row, col, QString::number(cs->day(current)));
00177         //go to the next date
00178         //@todo isn't there a better way, like current++ or something??
00179         QDate next = current.addDays(1);
00180         current.setYMD(next.year(),next.month(),next.day());
00181         col+=2;
00182     }
00183     sheet->doc()->endMacro();
00184     kDebug() <<"inserting calendar completed";
00185 }
00186 
00187 QWidget* CalendarTool::createOptionWidget()
00188 {
00189     // Create the main cell tool widget. It is not visible, but the CellTool makes heavy use
00190     // of it, and it refuses to work correctly if it does not exist
00191     CellTool::createOptionWidget ();
00192 
00193     CalendarToolWidget* widget =  new CalendarToolWidget(m_canvas->canvasWidget());
00194     connect(widget, SIGNAL(insertCalendar(const QDate&, const QDate&)),
00195             this, SLOT(insertCalendar(const QDate&, const QDate&)));
00196     return widget;
00197 }
00198 
00199 void CalendarTool::setText(Sheet* sheet, int _row, int _column, const QString& _text, bool asString)
00200 {
00201     DataManipulator* const command = new DataManipulator();
00202     command->setSheet(sheet);
00203     command->setValue(Value(_text));
00204     command->setParsing(!asString);
00205     command->add(QPoint(_column, _row));
00206     command->execute();
00207 
00208     //refresh anchor
00209     if ((!_text.isEmpty()) && (_text.at(0)=='!')) {
00210         sheet->updateView(Region(_column, _row, sheet));
00211     }
00212 }
00213 
00214 #include "CalendarTool.moc"