kplato

kptpart.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999, 2000 Torben Weis <weis@kde.org>
00003    Copyright (C) 2004, 2005 Dag Andersen <danders@get2net.dk>
00004    Copyright (C) 2006 Raphael Langerhorst <raphael.langerhorst@kdemail.net>
00005    Copyright (C) 2006 Dag Andersen <danders@get2net.dk>
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License as published by the Free Software Foundation; either
00010    version 2 of the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Library General Public License for more details.
00016 
00017    You should have received a copy of the GNU Library General Public License
00018    along with this library; see the file COPYING.LIB.  If not, write to
00019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "kptpart.h"
00024 #include "kptview.h"
00025 #include "kptfactory.h"
00026 #include "kptproject.h"
00027 #include "kptprojectdialog.h"
00028 #include "kptresource.h"
00029 #include "kptcontext.h"
00030 #include "kptganttview.h"
00031 #include "KDGanttViewTaskLink.h"
00032 
00033 #include <qpainter.h>
00034 #include <qfileinfo.h>
00035 
00036 #include <kdebug.h>
00037 #include <kconfig.h>
00038 #include <klocale.h>
00039 #include <kmessagebox.h>
00040 #include <kstandarddirs.h>
00041 #include <kcommand.h>
00042 #include <KoTemplateChooseDia.h>
00043 #include <KoCommandHistory.h>
00044 #include <KoGlobal.h>
00045 
00046 #define CURRENT_SYNTAX_VERSION "0.5"
00047 
00048 namespace KPlato
00049 {
00050 
00051 Part::Part(QWidget *parentWidget, const char *widgetName,
00052          QObject *parent, const char *name, bool singleViewMode)
00053     : KoDocument(parentWidget, widgetName, parent, name, singleViewMode),
00054       m_project(0), m_projectDialog(0), m_parentWidget(parentWidget), m_view(0),
00055       m_embeddedGanttView(new GanttView(parentWidget)),
00056       m_embeddedContext(new Context()), m_embeddedContextInitialized(false),
00057       m_context(0), m_xmlLoader()
00058 {
00059     m_update = m_calculate = false;
00060     m_commandHistory = new KoCommandHistory(actionCollection());
00061 
00062     setInstance(Factory::global());
00063     setTemplateType("kplato_template");
00064     m_config.setReadWrite(isReadWrite()|| !isEmbedded());
00065     m_config.load();
00066 
00067     delete m_project;
00068     m_project = new Project(); // after config is loaded
00069 
00070     connect(m_commandHistory, SIGNAL(commandExecuted()), SLOT(slotCommandExecuted()));
00071     connect(m_commandHistory, SIGNAL(documentRestored()), SLOT(slotDocumentRestored()));
00072 
00073     //FIXME the following is really dirty, we should make KPlato::Context a real class
00074     //      with getter and setter and signals when content changes, thus we can keep track
00075     QTimer* timer = new QTimer(this,"context update timer");
00076     connect(timer,SIGNAL(timeout()),this,SLOT(slotCopyContextFromView()));
00077     timer->start(500);
00078 }
00079 
00080 
00081 Part::~Part() {
00082     m_config.save();
00083     delete m_commandHistory; // before project, in case of dependencies...
00084     delete m_project;
00085     delete m_projectDialog;
00086     if (m_embeddedGanttView)
00087       delete m_embeddedGanttView;
00088     if (m_embeddedContext)
00089       delete m_embeddedContext;
00090 }
00091 
00092 
00093 bool Part::initDoc(InitDocFlags flags, QWidget* parentWidget) {
00094     bool result = true;
00095 
00096     if (flags==KoDocument::InitDocEmpty)
00097     {
00098         delete m_project;
00099         m_project = new Project();
00100         setAutoSave(0); // disable
00101         setModified(false);
00102         return true;
00103     }
00104 
00105     QString templateDoc;
00106     KoTemplateChooseDia::ReturnType ret;
00107     KoTemplateChooseDia::DialogType dlgtype;
00108     if (flags != KoDocument::InitDocFileNew )
00109         dlgtype = KoTemplateChooseDia::Everything;
00110     else
00111         dlgtype = KoTemplateChooseDia::OnlyTemplates;
00112 
00113     ret = KoTemplateChooseDia::choose(Factory::global(), templateDoc,
00114                                       dlgtype,
00115                                       "kplato_template",
00116                                       parentWidget);
00117     if (ret == KoTemplateChooseDia::Template) {
00118         resetURL();
00119         result = loadNativeFormat(templateDoc);
00120         if ( !result )
00121             showLoadingErrorDialog();
00122     } else if (ret == KoTemplateChooseDia::File) {
00123         KURL url(templateDoc);
00124         kdDebug() << "Part::initDoc opening URL " << url.prettyURL() <<endl;
00125         result = openURL(url);
00126     } else if (ret == KoTemplateChooseDia::Empty) {
00127         // Make a fresh project and let the user enter some info
00128         delete m_project;
00129         m_project = new Project();
00130        // an emty project should be empty
00131         // m_projectDialog = new ProjectDialog(*m_project, m_view);
00132         // m_projectDialog->exec();
00133 
00134         result = true;
00135     } else {
00136         result = false;
00137     }
00138     setAutoSave(0); // disable
00139     setModified(false);
00140     return result;
00141 }
00142 
00143 
00144 KoView *Part::createViewInstance(QWidget *parent, const char *name) {
00145     m_view = new View(this, parent, name);
00146     connect(m_view,SIGNAL(destroyed()),this,SLOT(slotViewDestroyed()));
00147 
00148     // If there is a project dialog this should be deleted so it will
00149     // use the m_view as parent. If the dialog will be needed again,
00150     // it will be made at that point
00151     if (m_projectDialog != 0) {
00152     kdDebug() << "Deleting m_projectDialog because of new ViewInstance\n";
00153     delete m_projectDialog;
00154     m_projectDialog = 0;
00155     }
00156     if (m_context)
00157         m_view->setContext( *m_context );
00158     else if (m_embeddedContext && m_embeddedContextInitialized)
00159         m_view->setContext( *m_embeddedContext );
00160     else {
00161         // Activate menu actions. Assumes ganttview, we don't get any 
00162         // 'aboutToShow' signal. Need to redo action control.
00163         m_view->setTaskActionsEnabled(true);
00164     }
00165     //m_view->setBaselineMode(getProject().isBaselined()); FIXME: Removed for this release  
00166     return m_view;
00167 }
00168 
00169 
00170 void Part::editProject() {
00171 
00172     QWidget* parent = m_parentWidget;
00173     if (m_view)
00174       parent = m_view;
00175       
00176     if (m_projectDialog == 0)
00177     // Make the dialog
00178     m_projectDialog = new ProjectDialog(*m_project, parent);
00179 
00180     m_projectDialog->exec();
00181 }
00182 
00183 
00184 bool Part::loadXML(QIODevice *, const QDomDocument &document) {
00185     QTime dt;
00186     dt.start();
00187     emit sigProgress( 0 );
00188 
00189     QString value;
00190     QDomElement plan = document.documentElement();
00191 
00192     // Check if this is the right app
00193     value = plan.attribute("mime", QString::null);
00194     if (value.isEmpty()) {
00195         kdError() << "No mime type specified!" << endl;
00196         setErrorMessage(i18n("Invalid document. No mimetype specified."));
00197         return false;
00198     }
00199     else if (value != "application/x-vnd.kde.kplato") {
00200         kdError() << "Unknown mime type " << value << endl;
00201         setErrorMessage(i18n("Invalid document. Expected mimetype application/x-vnd.kde.kplato, got %1").arg(value));
00202         return false;
00203     }
00204     QString m_syntaxVersion = plan.attribute("version", CURRENT_SYNTAX_VERSION);
00205     if (m_syntaxVersion > CURRENT_SYNTAX_VERSION) {
00206         int ret = KMessageBox::warningContinueCancel(
00207             0, i18n("This document was created with a newer version of KPlato (syntax version: %1)\n"
00208                     "Opening it in this version of KPlato will lose some information.").arg(m_syntaxVersion),
00209             i18n("File-Format Mismatch"), i18n("Continue") );
00210         if (ret == KMessageBox::Cancel)
00211         {
00212             setErrorMessage("USER_CANCELED");
00213             return false;
00214         }
00215     }
00216     emit sigProgress(5);
00217 
00218     QDomNodeList list = plan.childNodes();
00219     if (list.count() > 2) {
00220         // TODO: Make a proper bitching about this
00221         kdDebug() << "*** Error ***\n";
00222         kdDebug() << "  Children count should be 1 but is " << list.count()
00223                 << "\n";
00224         return false;
00225     }
00226     m_xmlLoader.startLoad();
00227     for (unsigned int i = 0; i < list.count(); ++i) {
00228         if (list.item(i).isElement()) {
00229             QDomElement e = list.item(i).toElement();
00230 
00231             if (e.tagName() == "context") {
00232                 delete m_context;
00233                 m_context = new Context();
00234                 m_context->load(e);
00235             } else if (e.tagName() == "project") {
00236                 Project *newProject = new Project();
00237                 if (newProject->load(e)) {
00238                     // The load went fine. Throw out the old project
00239                     delete m_project;
00240                     m_project = newProject;
00241                     delete m_projectDialog;
00242                     m_projectDialog = 0;
00243                 }
00244                 else {
00245                     delete newProject;
00246                     m_xmlLoader.addMsg(XMLLoaderObject::Errors, "Loading of project failed");
00247                     //TODO add some ui here
00248                 }
00249             }
00250         }
00251     }
00252     m_xmlLoader.stopLoad();
00253     emit sigProgress(100); // the rest is only processing, not loading
00254 
00255     kdDebug() << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
00256 
00257     // do some sanity checking on document.
00258     emit sigProgress(-1);
00259 
00260     m_commandHistory->clear();
00261     m_commandHistory->documentSaved();
00262     setModified( false );
00263     if (m_view)
00264         m_view->slotUpdate(false);
00265     return true;
00266 }
00267 
00268 QDomDocument Part::saveXML() {
00269     QDomDocument document("kplato");
00270 
00271     document.appendChild(document.createProcessingInstruction(
00272             "xml",
00273             "version=\"1.0\" encoding=\"UTF-8\""));
00274 
00275     QDomElement doc = document.createElement("kplato");
00276     doc.setAttribute("editor", "KPlato");
00277     doc.setAttribute("mime", "application/x-vnd.kde.kplato");
00278     doc.setAttribute("version", CURRENT_SYNTAX_VERSION);
00279     document.appendChild(doc);
00280 
00281     delete m_context;
00282     m_context = 0;
00283     if (m_view) {
00284         m_context = new Context();
00285         m_view->getContext(*m_context);
00286     }
00287     if (m_context) {
00288         m_context->save(doc);
00289     }
00290     // Save the project
00291     m_project->save(doc);
00292 
00293     m_commandHistory->documentSaved();
00294     return document;
00295 }
00296 
00297 
00298 void Part::slotDocumentRestored() {
00299     //kdDebug()<<k_funcinfo<<endl;
00300     setModified(false);
00301 }
00302 
00303 
00304 void Part::paintContent(QPainter &painter, const QRect &rect,
00305                bool /*transparent*/,
00306                double zoomX, double /*zoomY*/)
00307 {
00308     kdDebug() << "----------- KPlato: Part::paintContent ------------" << endl;
00309     if (isEmbedded() && m_embeddedGanttView && m_project)
00310     {
00311         if (m_embeddedContext)
00312         {
00313             int ganttsize = m_embeddedContext->ganttview.ganttviewsize;
00314             int tasksize = m_embeddedContext->ganttview.taskviewsize;
00315             bool showtaskname = m_embeddedContext->ganttview.showTaskName;
00316             
00317 //            m_embeddedContext->ganttview.ganttviewsize += m_embeddedContext->ganttview.taskviewsize;
00318 //            m_embeddedContext->ganttview.taskviewsize = 0;  //TODO this doesn't have any effect?! (bug?)
00319             m_embeddedContext->ganttview.showTaskName = true;  //since task view is not shown(?), show name in the gantt itself
00320             
00321             m_embeddedGanttView->setContext( m_embeddedContext->ganttview, *m_project );
00322             
00323             m_embeddedContext->ganttview.ganttviewsize = ganttsize;
00324             m_embeddedContext->ganttview.taskviewsize = tasksize;
00325             m_embeddedContext->ganttview.showTaskName = showtaskname;
00326         }
00327         else
00328         {
00329             kdWarning() << "Don't have any context to set!" << endl;
00330         }
00331         painter.setClipRect(rect, QPainter::CoordPainter);
00332         // We don't support zoom yet, so use the painters scaling
00333         double d_zoom = 1.0;
00334         setZoomAndResolution(100, KoGlobal::dpiX(), KoGlobal::dpiY());
00335         if ( m_zoomedResolutionX != zoomX ) {
00336             d_zoom *= ( zoomX / m_zoomedResolutionX );
00337             painter.scale(d_zoom, d_zoom);
00338         }
00339         
00340         m_embeddedGanttView->clear();
00341         m_embeddedGanttView->draw(*m_project);
00342         m_embeddedGanttView->drawOnPainter(&painter,rect);
00343     }
00344     // ####### handle transparency
00345 
00346     // Need to draw only the document rectangle described in the parameter rect.
00347 //     int left = rect.left() / 20;
00348 //     int right = rect.right() / 20 + 1;
00349 //     int top = rect.top() / 20;
00350 //     int bottom = rect.bottom() / 20 + 1;
00351 
00352 //     for( int x = left; x < right; ++x )
00353 //         painter.drawLine( x * 40, top * 20, 40 * 20, bottom * 20 );
00354 //     for( int y = left; y < right; ++y )
00355 //         painter.drawLine( left * 20, y * 20, right * 20, y * 20 );
00356 }
00357 
00358 
00359 void Part::addCommand(KCommand * cmd, bool execute)
00360 {
00361     m_commandHistory->addCommand(cmd, execute);
00362 }
00363 
00364 void Part::slotCommandExecuted() {
00365     //kdDebug()<<k_funcinfo<<endl;
00366     setModified(true);
00367     kdDebug() << "------- KPlato, is embedded: " << isEmbedded() << endl;
00368     if (m_view == NULL)
00369       return;
00370       
00371     if (m_calculate)
00372         m_view->slotUpdate(false/*config().behavior().calculationMode == Behavior::OnChange*/);
00373     else if (m_update)
00374         m_view->slotUpdate(false);
00375 
00376     if (m_baseline)
00377         m_view->setBaselineMode(getProject().isBaselined());
00378 
00379     m_update = m_calculate = m_baseline = false;
00380 }
00381 
00382 void Part::slotCopyContextFromView()
00383 {
00384     if (m_view)
00385     {
00386 //         kdDebug() << "Updating embedded context from view context." << endl;
00387         this->m_view->getContext( *m_embeddedContext );
00388         this->m_embeddedContextInitialized = true;
00389     }
00390 //     else
00391 //     {
00392 //         kdDebug() << "Not updating the context." << endl;
00393 //         if (m_context)
00394 //           kdDebug() << "Current View: " << m_context->currentView << endl;
00395 //     }
00396 }
00397 
00398 void Part::slotViewDestroyed()
00399 {
00400     m_view = NULL;
00401 }
00402 
00403 void Part::setCommandType(int type) {
00404     //kdDebug()<<k_funcinfo<<"type="<<type<<endl;
00405     if (type == 0)
00406         m_update = true;
00407     else if (type == 1)
00408         m_calculate = true;
00409     else if (type == 2)
00410         m_baseline = true;
00411 }
00412 
00413 void Part::generateWBS() {
00414     m_project->generateWBS(1, m_wbsDefinition);
00415 }
00416 
00417 }  //KPlato namespace
00418 
00419 #include "kptpart.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys