/* This file is part of the KDE project Copyright (C) 2003 - 2005 Dag Andersen <danders@get2net.dk> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2 of the License. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptreportview.h" #include "kptview.h" #include "kptpart.h" #include "kptcontext.h" #include <mreportviewer.h> #include <mpagecollection.h> #include <KoStore.h> #include <kdebug.h> #include <tdeaction.h> #include <kstdaction.h> #include <tdetoolbar.h> #include <kstandarddirs.h> #include <kurl.h> #include <tdemessagebox.h> #include <tdeio/netaccess.h> #include <tdelocale.h> #include <tdeglobal.h> #include <kdesktopfile.h> #include <tdefiledialog.h> #include <tqfile.h> #include <tqfileinfo.h> #include <tqheader.h> #include <tqpopupmenu.h> #include <tqlayout.h> #include <tqdom.h> #include <tqstringlist.h> namespace KPlato { class ReportTagsPrivate { public: ReportTagsPrivate() : m_project(0), m_task(0), m_resourcegroup(0), m_resource(0), alltasksLevel("-1"), summarytasksLevel("-1"), tasksLevel("-1"), milestonesLevel("-1"), resourcegroupsLevel("-1"), resourcesLevel("-1") {} ~ReportTagsPrivate() {} TQString getData(TQString source, TQString tag) const { if (tag.contains(".")) return getData(tag); return getData(source + "." + tag); } TQString getData(TQString tag) const { //kdDebug()<<k_funcinfo<<"tag="<<tag<<endl; TDELocale *l = TDEGlobal::locale(); if (!tag.contains('.')) { // global tags if (tag == "currentdate") { return l->formatDate(TQDate::currentDate(), true); } return TQString(); } if (tag.section(".", 0, 0) == "project") { if (tag.section(".", 1, 1) == "name") return (m_project ? m_project->name() : TQString()); if (tag.section(".", 1, 1) == "leader") return (m_project ? m_project->leader() : TQString()); } else if (tag.section(".", 0, 0) == "task") { if (tag.section(".", 1, 1) == "name") return (m_task ? m_task->name() : TQString()); if (tag.section(".", 1, 1) == "responsible") return (m_task ? m_task->leader() : TQString()); else if (tag.section(".", 1, 1) == "wbs") return (m_task ? m_task->wbs() : TQString()); else if (tag.section(".", 1, 1) == "start") return (m_task ? l->formatDateTime(m_task->startTime()) : TQString()); else if (tag.section(".", 1, 1) == "starttime") return (m_task ? l->formatTime(m_task->startTime().time()) : TQString()); else if (tag.section(".", 1, 1) == "startdate") return (m_task ? l->formatDate(m_task->startTime().date(), true) : TQString()); else if (tag.section(".", 1, 1) == "duration") { return (m_task ? m_task->duration().toString(Duration::Format_i18nDayTime) : TQString()); } else if (tag.section(".", 1, 1) == "plannedcost") { return (m_task ? l->formatMoney(m_task->plannedCost()) : TQString()); } } else if (tag.section(".", 0, 0) == "resourcegroup") { if (tag.section(".", 1, 1) == "name") return (m_resourcegroup ? m_resourcegroup->name() : TQString()); } else if (tag.section(".", 0, 0) == "resource") { if (tag.section(".", 1, 1) == "name") return (m_resource ? m_resource->name() : TQString()); if (tag.section(".", 1, 1) == "type") return (m_resource ? m_resource->typeToString() : TQString()); if (tag.section(".", 1, 1) == "email") return (m_resource ? m_resource->email() : TQString()); if (tag.section(".", 1, 1) == "availablefrom") return (m_resource ? l->formatDate(m_resource->availableFrom().date(), true) : TQString()); if (tag.section(".", 1, 1) == "availableuntil") return (m_resource ? l->formatDate(m_resource->availableUntil().date(), true) : TQString()); if (tag.section(".", 1, 1) == "units") return (m_resource ? TQString("%1%").arg(m_resource->units()) : TQString()); if (tag.section(".", 1, 1) == "normalrate") return (m_resource ? l->formatMoney(m_resource->normalRate()) : TQString()); if (tag.section(".", 1, 1) == "overtimerate") return (m_resource ? l->formatMoney(m_resource->overtimeRate()) : TQString()); } return TQString(); } Project *m_project; Task *m_task; ResourceGroup *m_resourcegroup; Resource *m_resource; TQString alltasksLevel; TQStringList alltasksProps; TQString summarytasksLevel; TQStringList summarytasksProps; TQString tasksLevel; TQStringList tasksProps; TQString milestonesLevel; TQStringList milestonesProps; TQString resourcegroupsLevel; TQStringList resourcegroupsProps; TQString resourcesLevel; TQStringList resourcesProps; }; class KugarReportViewer : public Kugar::MReportViewer { public: KugarReportViewer(TQWidget *parent = 0, const char *name = 0) : MReportViewer(parent, name) {} int currentPage() { return report ? report->getCurrentIndex() : 0; } int pageCount() { return report ? report->pageCount() : 0; } }; ReportView::ReportView(View *view, TQWidget *parent) : TQSplitter(parent), m_mainview(view), m_reportTags(0) { //kdDebug()<<k_funcinfo<<endl; m_reportList = new TDEListView(this); #if KDE_IS_VERSION(3,3,9) m_reportList->setShadeSortColumn(false); #endif m_reportList->addColumn(i18n("Report Template")); m_reportList->header()->setStretchEnabled(true, 0); m_reportList->header()->setSortIndicator(0); m_reportview = new KugarReportViewer(this); initReportList(); connect(m_reportList, TQT_SIGNAL(clicked(TQListViewItem*)), TQT_SLOT(slotReportListClicked(TQListViewItem*))); connect(m_reportList, TQT_SIGNAL(selectionChanged(TQListViewItem*)), TQT_SLOT(slotReportListSelectionChanged(TQListViewItem*))); //setCentralWidget(m_reportview); // Create the user interface. //KStdAction::print(this,TQT_SLOT(slotPrint()),actionCollection()); //KStdAction::quit(this,TQT_SLOT(slotFileQuit()),actionCollection()); // KStdAction::showToolbar(this,TQT_SLOT(slotViewToolBar()),actionCollection()); // KStdAction::showStatusbar(this,TQT_SLOT(slotViewStatusBar()),actionCollection()); // statusBar(); // createGUI(); } ReportView::~ReportView() { //safe delete m_reportTags; } void ReportView::initReportList() { //FIXME: We need a solution that takes care project specific reports. //kdDebug()<<k_funcinfo<<endl; TQStringList list; m_reportList->clear(); TDEStandardDirs std; TQStringList reportDesktopFiles = std.findAllResources("data", "kplato/reports/*.desktop", true, true); for (TQStringList::iterator it = reportDesktopFiles.begin(); it != reportDesktopFiles.end(); ++it) { KDesktopFile file((*it), true); TQString name = file.readName(); if (!name.isNull()) { //kdDebug()<<" file: "<<*it<<" name="<<name<<endl; TQString url = file.readURL(); if (!url.isNull()) { if (url.left(1) != "/" || url.left(6) != "file:/") { TQString path = (*it).left((*it).findRev('/', -1)+1); // include '/' url = path + url; } m_reportList->insertItem(new ReportItem(m_reportList, name, url)); } } } } void ReportView::draw(const TQString &report) { //kdDebug()<<k_funcinfo<<endl; m_reportview->clearReport(); m_reportTags = new ReportTagsPrivate(); getTemplateFile(report); m_reportview->setReportTemplate(templateDoc.toString()); setReportData(); m_reportview->renderReport(); m_reportview->show(); delete m_reportTags; m_reportTags=0L; enableNavigationBtn(); } void ReportView::setup(KPrinter &printer) { //kdDebug()<<k_funcinfo<<endl; m_reportview->setupPrinter(printer); } void ReportView::print(KPrinter &printer) { //kdDebug()<<k_funcinfo<<endl; m_reportview->printReport(printer); } // Generate report data based on info from the template file void ReportView::setReportData() { TQString s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; s+="<KugarData>\n"; s += setReportDetail(); s+="</KugarData>\n"; //kdDebug()<<s<<endl; m_reportview->setReportData(s); } TQString ReportView::setReportDetail() { //kdDebug()<<k_funcinfo<<endl; TQString s; if (m_reportTags->alltasksLevel != "-1") { //kdDebug()<<k_funcinfo<<"alltasks level="<<m_reportTags->alltasksLevel<<endl; if (m_reportTags->summarytasksLevel == "-1") { m_reportTags->summarytasksLevel = m_reportTags->alltasksLevel; m_reportTags->summarytasksProps = m_reportTags->alltasksProps; } if (m_reportTags->tasksLevel == "-1") { m_reportTags->tasksLevel = m_reportTags->alltasksLevel; m_reportTags->tasksProps = m_reportTags->alltasksProps; } if (m_reportTags->milestonesLevel == "-1") { m_reportTags->milestonesLevel = m_reportTags->alltasksLevel; m_reportTags->milestonesProps = m_reportTags->alltasksProps; } s+= setTaskChildren(&(mainView()->getProject())); } else if (m_reportTags->summarytasksLevel == "0") { // make a report that has summarytasks as starting points TQPtrListIterator<Node> it(mainView()->getProject().childNodeIterator()); for (; it.current(); ++it) { if (it.current()->type() == Node::Type_Summarytask) { s += setTaskDetail(it.current()); // Now do subtasks s+= setTaskChildren(it.current()); } } } else if (m_reportTags->tasksLevel == "0") { // make a report that has tasks as starting points TQPtrListIterator<Node> it(mainView()->getProject().childNodeIterator()); for (; it.current(); ++it) { if (it.current()->type() == Node::Type_Task) { s += setTaskDetail(it.current()); } if (it.current()->type() == Node::Type_Summarytask) { s+= setTaskChildren(it.current()); if (m_reportTags->summarytasksLevel != "-1") { s += setTaskDetail(it.current()); } } } } else if (m_reportTags->milestonesLevel == "0") { } else if (m_reportTags->resourcegroupsLevel == "0") { // make a report that has resourcegroups as starting points TQPtrListIterator<ResourceGroup> it(mainView()->getProject().resourceGroups()); for (; it.current(); ++it) { s += setResourceGroupDetail(it.current()); } } else if (m_reportTags->resourcesLevel == "0") { // make a report that has resources as starting points TQPtrListIterator<ResourceGroup> it(mainView()->getProject().resourceGroups()); for (; it.current(); ++it) { TQPtrListIterator<Resource> rit(it.current()->resources()); for (; rit.current(); ++rit) { s += setResourceDetail(rit.current()); } } } //kdDebug()<<k_funcinfo<<s<<endl; return s; } TQString ReportView::setResourceGroupDetail(ResourceGroup *group) { //kdDebug()<<k_funcinfo<<group->name()<<endl; TQString s; if (m_reportTags->resourcegroupsLevel != "-1") { m_reportTags->m_resourcegroup = group; //kdDebug()<<k_funcinfo<<group->name()<<": level="<<m_reportTags->resourcegroupsLevel<<endl; s = setDetail("resourcegroup", m_reportTags->resourcegroupsProps, m_reportTags->resourcegroupsLevel); TQPtrListIterator<Resource> rit(group->resources()); for (; rit.current(); ++rit) { s += setResourceDetail(rit.current()); } } return s; } TQString ReportView::setResourceDetail(Resource *res) { //kdDebug()<<k_funcinfo<<res->name()<<endl; TQString s; if (m_reportTags->resourcesLevel != "-1") { m_reportTags->m_resource = res; //kdDebug()<<k_funcinfo<<res->name()<<": level="<<m_reportTags->resourcesLevel<<endl; s = setDetail("resource", m_reportTags->resourcesProps, m_reportTags->resourcesLevel); } return s; } TQString ReportView::setTaskChildren(Node *node) { //kdDebug()<<k_funcinfo<<endl; TQString s; TQPtrListIterator<Node> it(node->childNodeIterator()); for (; it.current(); ++it) { s += setTaskDetail(it.current()); if (it.current()->type() == Node::Type_Summarytask) s+= setTaskChildren(it.current()); } return s; } TQString ReportView::setTaskDetail(Node *node) { //kdDebug()<<k_funcinfo<<endl; TQString s; TQStringList props; TQString level = "-1"; if (node->type() == Node::Type_Task) { props = m_reportTags->tasksProps; level = m_reportTags->tasksLevel; } else if (node->type() == Node::Type_Summarytask) { props = m_reportTags->summarytasksProps; level = m_reportTags->summarytasksLevel; } else if (node->type() == Node::Type_Milestone) { props = m_reportTags->milestonesProps; level = m_reportTags->milestonesLevel; } if (level != "-1") { m_reportTags->m_task = static_cast<Task *>(node); s = setDetail("task", props, level); } return s; } TQString ReportView::setDetail(const TQString & source, TQStringList &properties, TQString &level) { TQString s = "<Row"; s += " level=\"" + level + "\""; for (unsigned int i=0; i < properties.count(); ++i) { //kdDebug()<<k_funcinfo<<"Property: "<<properties[i]<<endl; s += " " + properties[i].section('=', 0, 0) + "="; // Field TQString data = m_reportTags->getData(source, properties[i].section('=', 1, 1)); if (data.isNull()) data = ""; data = data.replace('<', "<"); data = data.replace('>', ">"); data = data.replace('"', """); s += "\"" + data + "\""; // Property //kdDebug()<<k_funcinfo<<s<<endl; } s += "/>\n"; return s; } // Most of this is from KoDocument::loadNativeFormat void ReportView::openTemplateFile(const TQString &file) { if (!TQFileInfo(file).isFile()) { KMessageBox::sorry( this, i18n("Cannot find report template file!"), i18n("Generate Report")); return; } TQFile in; in.setName(file); if (!in.open(IO_ReadOnly)) { KMessageBox::sorry( this, i18n("Cannot open report template file!"), i18n("Generate Report")); return; } // Try to find out whether it is a mime multi part file char buf[5]; if ( in.readBlock( buf, 4 ) < 4 ) { in.close(); KMessageBox::sorry( this, i18n("Cannot read report template file!"), i18n("Generate Report")); return; } if (strncasecmp( buf, "<?xm", 4 ) == 0) { // xml file? in.at(0); // fake //m_reportview->setReportTemplate(&in); loadTemplate(in); in.close(); return; } in.close(); KoStore* store=KoStore::createStore(file, KoStore::Read); if (!store) { KMessageBox::sorry( this, i18n("Cannot open report template file!"), i18n("Generate Report")); return; } bool b = store->open("maindoc.xml"); if ( !b ) { KMessageBox::sorry( this, i18n("Cannot find the proper report template file!"), i18n("Generate Report")); delete store; return; } loadTemplate(*(store->device())); store->close(); } void ReportView::loadTemplate(TQIODevice &dev) { TQString errorMsg; int errorLine; int errorColumn; if (!templateDoc.setContent( &dev , &errorMsg, &errorLine, &errorColumn)) { TQString msg = "Parsing template file failed with "; KMessageBox::sorry( this, msg + errorMsg, i18n("Generate Report")); return; } loadTemplate(templateDoc); } void ReportView::loadTemplate(TQDomDocument &doc) { TQDomNode tpl; TQDomNode child; for (tpl = doc.firstChild(); !tpl.isNull(); tpl = tpl.nextSibling()) if (tpl.nodeName() == "KugarTemplate") break; if (tpl.isNull()) return; m_reportTags->m_project = &(mainView()->getPart()->getProject()); // Get all the child report elements TQDomNodeList children = tpl.childNodes(); int childCount = children.length(); for(int j = 0; j < childCount; j++){ child = children.item(j); if(child.nodeType() == TQDomNode::ElementNode) { TQDomElement e = child.toElement(); //kdDebug()<<child.nodeName()<<endl; // Report Header if(child.nodeName() == "ReportHeader") { handleHeader(child); } else if (child.nodeName() == "PageHeader") { handleHeader(child); } else if(child.nodeName() == "DetailHeader") { handleHeader(child); } else if(child.nodeName() == "Detail") { handleDetail(e); } else if(child.nodeName() == "DetailFooter") { handleHeader(child); } else if(child.nodeName() == "PageFooter") { handleHeader(child); } else if(child.nodeName() == "ReportFooter") { handleHeader(child); } else if(child.nodeName() == "KPlato") { handleKPlato(e); } } } } void ReportView::handleHeader(TQDomNode &node) { TQDomNode child; TQDomNodeList children = node.childNodes(); int childCount = children.length(); for (int j = 0; j < childCount; j++) { child = children.item(j); if (child.nodeName() == "Label") { TQDomNode n = child.attributes().namedItem("Text"); TQString s = n.nodeValue(); if (!s.isEmpty()) { // Translate labels s = i18n(n.nodeValue().latin1()); //NOTE: Not sure if latin1 is ok } TQString r = s; int i = 0, j = 0; do { i = j; if ( ((i = s.find('[', i)) != -1) && ((j = s.find(']', i+1)) != -1) ) { TQString tag = s.mid(i, j-i+1); TQString data = m_reportTags->getData(tag.mid(1, tag.length()-2)); r = r.replace(tag, data); } } while (i != -1 && j != -1); n.setNodeValue(r); //kdDebug()<<" new Text="<<n.nodeValue()<<endl; } else if (child.nodeName() == "Field") { TQDomElement e = child.toElement(); if (!e.isElement()) { continue; // !!!!! } TQString s = e.attribute("Field"); TQString data = m_reportTags->getData(s); e.setAttribute("Text", data); //kdDebug()<<" new Text="<<e.attribute("Text")<<endl; } } } TQStringList ReportView::getProperties(TQDomElement &elem) { TQStringList props; TQDomNodeList list(elem.childNodes()); int childCount = list.length(); for (int j = 0; j < childCount; j++) { TQDomNode child = list.item(j); if (child.nodeName() == "Field") { props.append(child.attributes().namedItem("Field").nodeValue()+"="+child.attributes().namedItem("Field").nodeValue()); } } return props; } void ReportView::handleKPlato(TQDomElement &elem) { TQDomNodeList list(elem.childNodes()); int childCount = list.length(); for (int j = 0; j < childCount; j++) { TQDomNode child = list.item(j); if (child.nodeName() == "Detail") { TQDomElement e = child.toElement(); if (!e.isElement()) { continue; // !!!!! } TQString source = e.attribute("SelectFrom"); TQString level = e.attribute("Level", "-1"); //kdDebug()<<k_funcinfo<<"SelectFrom="<<source<<" Level="<<level<<endl; if (source.isNull() || level == "-1") continue; TQStringList list = TQStringList::split(" ", source); TQStringList::iterator it = list.begin(); for (; it != list.end(); ++it) { //kdDebug()<<k_funcinfo<<(*it)<<endl; if ((*it) == "alltasks") { m_reportTags->alltasksLevel = level; } if ((*it) == "summarytasks") { m_reportTags->summarytasksLevel = level; } if ((*it) == "tasks") { m_reportTags->tasksLevel = level; } if ((*it) == "milestones") { m_reportTags->milestonesLevel = level; } if ((*it) == "resourcegroups") { m_reportTags->resourcegroupsLevel = level; } if ((*it) == "resources") { m_reportTags->resourcesLevel = level; } } } } } void ReportView::handleDetail(TQDomElement &elem) { //kdDebug()<<k_funcinfo<<endl; TQString level = elem.attribute("Level", "-1"); if (level == "-1") { return; } if (level == m_reportTags->alltasksLevel) { m_reportTags->alltasksProps = getProperties(elem); } if (level == m_reportTags->summarytasksLevel) { m_reportTags->summarytasksProps = getProperties(elem); } if (level == m_reportTags->tasksLevel) { m_reportTags->tasksProps = getProperties(elem); } if (level == m_reportTags->milestonesLevel) { m_reportTags->milestonesProps = getProperties(elem); } if (level == m_reportTags->resourcegroupsLevel) { m_reportTags->resourcegroupsProps = getProperties(elem); } if (level == m_reportTags->resourcesLevel) { m_reportTags->resourcesProps = getProperties(elem); } } void ReportView::replaceTags(TQDomNode &node) { if (node.isNull()) return; } void ReportView::getTemplateFile(const TQString &tpl) { KURL url(tpl); TQString localtpl; bool isTemp = false; if (!url.isValid()) { KMessageBox::sorry(this,i18n("Malformed template filename: %1").arg(url.prettyURL())); } else { if (TDEIO::NetAccess::download(url,localtpl,this)) isTemp = true; else KMessageBox::sorry(this,i18n("Unable to download template file: %1").arg(url.prettyURL())); } if (!localtpl.isNull()) { openTemplateFile(localtpl); if (isTemp) TDEIO::NetAccess::removeTempFile(localtpl); } } void ReportView::enableNavigationBtn() { //kdDebug()<<k_funcinfo<<"curr="<<m_reportview->currentPage()<<" count="<<m_reportview->pageCount()<<endl; emit setFirstPageActionEnabled(m_reportview->currentPage() > 0); emit setNextPageActionEnabled(m_reportview->currentPage() < m_reportview->pageCount()-1); emit setPriorPageActionEnabled(m_reportview->currentPage() > 0); emit setLastPageActionEnabled(m_reportview->currentPage() < m_reportview->pageCount()-1); } void ReportView::slotFirstPage() { m_reportview->slotFirstPage(); enableNavigationBtn(); } void ReportView::slotNextPage() { m_reportview->slotNextPage(); enableNavigationBtn(); } void ReportView::slotPrevPage() { m_reportview->slotPrevPage(); enableNavigationBtn(); } void ReportView::slotLastPage() { m_reportview->slotLastPage(); enableNavigationBtn(); } bool ReportView::setContext(Context::Reportview &context) { Q_UNUSED(context); //kdDebug()<<k_funcinfo<<endl; return true; } void ReportView::getContext(Context::Reportview &context) const { Q_UNUSED(context); //kdDebug()<<k_funcinfo<<endl; } void ReportView::slotReportListClicked(TQListViewItem* item) { if (item == m_reportList->selectedItem()) slotReportListSelectionChanged(item); } void ReportView::slotReportListSelectionChanged(TQListViewItem* item) { ReportItem *ri = dynamic_cast<ReportItem*>(item); if (ri == 0) return; draw(ri->url); } } //KPlato namespace #include "kptreportview.moc"