File indexing completed on 2024-05-12 16:39:27
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998, 1999, 2000 Torben Weis <weis@kde.org> 0003 Copyright (C) 2002 - 2009, 2011, 2012 Dag Andersen <danders@get2net.dk> 0004 Copyright (C) 2019 Dag Andersen <danders@get2net.dk> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 // clazy:excludeall=qstring-arg 0023 #include "view.h" 0024 #include "mainwindow.h" 0025 #include "taskworkpackageview.h" 0026 #include "workpackage.h" 0027 #include "taskcompletiondialog.h" 0028 #include "calligraplanworksettings.h" 0029 #include "kpttaskeditor.h" 0030 #include "kpttaskdescriptiondialog.h" 0031 #include "kptcommonstrings.h" 0032 0033 #include "KoDocumentInfo.h" 0034 #include <KoMainWindow.h> 0035 0036 #include <QApplication> 0037 #include <QLabel> 0038 #include <QString> 0039 #include <QSize> 0040 #include <QTabWidget> 0041 #include <QVBoxLayout> 0042 #include <QPrinter> 0043 #include <QPrintDialog> 0044 #include <QDomDocument> 0045 #include <QPointer> 0046 #include <QMenu> 0047 #include <QAction> 0048 0049 #include <KLocalizedString> 0050 #include <ktoolbar.h> 0051 0052 #include <kxmlguifactory.h> 0053 #include <ktoolinvocation.h> 0054 #include <kactioncollection.h> 0055 #include <QTemporaryFile> 0056 0057 #include <kmessagebox.h> 0058 0059 #include <KoIcon.h> 0060 0061 #include "part.h" 0062 #include "factory.h" 0063 0064 #include "kptviewbase.h" 0065 #include "kptdocumentseditor.h" 0066 0067 #include "kptnode.h" 0068 #include "kptproject.h" 0069 #include "kpttask.h" 0070 #include "kptcommand.h" 0071 #include "kptdocuments.h" 0072 #include "kpttaskprogressdialog.h" 0073 #include "kptcalendar.h" 0074 0075 #include <assert.h> 0076 0077 #include "debugarea.h" 0078 0079 namespace KPlatoWork 0080 { 0081 0082 View::View(Part *part, QWidget *parent, KActionCollection *collection) 0083 : QStackedWidget(parent), 0084 m_part(part), 0085 m_scheduleActionGroup(new QActionGroup(this)), 0086 m_manager(0) 0087 { 0088 m_readWrite = part->isReadWrite(); 0089 debugPlanWork<<m_readWrite; 0090 0091 // Add sub views 0092 createViews(); 0093 0094 // The menu items 0095 // ------ Edit 0096 actionRemoveSelectedPackages = new QAction(koIcon("edit-delete"), i18n("Remove Packages"), this); 0097 collection->addAction("package_remove_selected", actionRemoveSelectedPackages); 0098 connect(actionRemoveSelectedPackages, &QAction::triggered, this, &View::slotRemoveSelectedPackages); 0099 0100 actionRemoveCurrentPackage = new QAction(koIcon("edit-delete"), i18n("Remove Package"), this); 0101 collection->addAction("package_remove_current", actionRemoveCurrentPackage); 0102 connect(actionRemoveCurrentPackage, &QAction::triggered, this, &View::slotRemoveCurrentPackage); 0103 0104 actionViewList = new QAction(koIcon("view-list-tree"), i18n("List"), this); 0105 actionViewList->setToolTip(i18nc("@info:tooltip", "Select task list")); 0106 collection->addAction("view_list", actionViewList); 0107 connect(actionViewList, &QAction::triggered, this, &View::slotViewList); 0108 0109 actionViewGantt = new QAction(koIcon("view-time-schedule"), i18n("Gantt"), this); 0110 actionViewGantt->setToolTip(i18nc("@info:tooltip", "Select timeline")); 0111 collection->addAction("view_gantt", actionViewGantt); 0112 connect(actionViewGantt, &QAction::triggered, this, &View::slotViewGantt); 0113 0114 // actionTaskProgress = new QAction(koIcon("document-edit"), i18n("Progress..."), this); 0115 // collection->addAction("task_progress", actionTaskProgress); 0116 // connect(actionTaskProgress, SIGNAL(triggered(bool)), SLOT(slotTaskProgress())); 0117 0118 //------ Settings 0119 actionConfigure = new QAction(koIcon("configure"), i18n("Configure PlanWork..."), this); 0120 collection->addAction("configure", actionConfigure); 0121 connect(actionConfigure, &QAction::triggered, this, &View::slotConfigure); 0122 0123 //------ Popups 0124 actionEditDocument = new QAction(koIcon("document-edit"), i18n("Edit..."), this); 0125 collection->addAction("edit_document", actionEditDocument); 0126 connect(actionEditDocument, SIGNAL(triggered(bool)), SLOT(slotEditDocument())); 0127 0128 actionViewDocument = new QAction(koIcon("document-preview"), i18nc("@verb", "View..."), this); 0129 collection->addAction("view_document", actionViewDocument); 0130 connect(actionViewDocument, &QAction::triggered, this, &View::slotViewDocument); 0131 0132 // FIXME remove UndoText::removeDocument() when string freeze is lifted 0133 actionRemoveDocument = new QAction(koIcon("list-remove"), UndoText::removeDocument().toString(), this); 0134 collection->addAction("remove_document", actionRemoveDocument); 0135 connect(actionRemoveDocument, &QAction::triggered, this, &View::slotRemoveDocument); 0136 0137 actionSendPackage = new QAction(koIcon("mail-send"), i18n("Send Package..."), this); 0138 collection->addAction("edit_sendpackage", actionSendPackage); 0139 connect(actionSendPackage, &QAction::triggered, this, &View::slotSendPackage); 0140 0141 actionTaskCompletion = new QAction(koIcon("document-edit"), i18n("Edit Progress..."), this); 0142 collection->addAction("task_progress", actionTaskCompletion); 0143 connect(actionTaskCompletion, &QAction::triggered, this, &View::slotTaskCompletion); 0144 0145 actionViewDescription = new QAction(/*koIcon("document_view"),*/ i18n("View Description..."), this); 0146 collection->addAction("task_description", actionViewDescription); 0147 connect(actionViewDescription, &QAction::triggered, this, &View::slotTaskDescription); 0148 0149 0150 updateReadWrite(m_readWrite); 0151 //debugPlanWork<<" end"; 0152 0153 loadContext(); 0154 slotCurrentChanged(currentIndex()); 0155 connect(this, &QStackedWidget::currentChanged, this, &View::slotCurrentChanged); 0156 0157 slotSelectionChanged(); 0158 } 0159 0160 View::~View() 0161 { 0162 saveContext(); 0163 } 0164 0165 void View::slotCurrentChanged(int index) 0166 { 0167 actionViewList->setEnabled(index != 0); 0168 actionViewGantt->setEnabled(index != 1); 0169 saveContext(); 0170 } 0171 0172 void View::slotViewList() 0173 { 0174 debugPlanWork; 0175 setCurrentIndex(0); 0176 } 0177 0178 void View::slotViewGantt() 0179 { 0180 debugPlanWork; 0181 setCurrentIndex(1); 0182 } 0183 0184 void View::createViews() 0185 { 0186 QWidget *v = createTaskWorkPackageView(); 0187 addWidget(v); 0188 v = createGanttView(); 0189 addWidget(v); 0190 } 0191 0192 TaskWorkPackageView *View::createTaskWorkPackageView() 0193 { 0194 TaskWorkPackageView *v = new TaskWorkPackageView(part(), this); 0195 0196 connect(v, &AbstractView::requestPopupMenu, this, &View::slotPopupMenu); 0197 0198 connect(v, &AbstractView::selectionChanged, this, &View::slotSelectionChanged); 0199 v->updateReadWrite(m_readWrite); 0200 v->loadContext(); 0201 return v; 0202 } 0203 0204 TaskWPGanttView *View::createGanttView() 0205 { 0206 TaskWPGanttView *v = new TaskWPGanttView(part(), this); 0207 0208 connect(v, &AbstractView::requestPopupMenu, this, &View::slotPopupMenu); 0209 0210 connect(v, &AbstractView::selectionChanged, this, &View::slotSelectionChanged); 0211 v->updateReadWrite(m_readWrite); 0212 v->loadContext(); 0213 return v; 0214 } 0215 0216 void View::setupPrinter(QPrinter &/*printer*/, QPrintDialog &/*printDialog */) 0217 { 0218 //debugPlanWork; 0219 } 0220 0221 void View::print(QPrinter &/*printer*/, QPrintDialog &/*printDialog*/) 0222 { 0223 } 0224 0225 void View::slotSelectionChanged() 0226 { 0227 bool enable = ! currentView()->selectedNodes().isEmpty(); 0228 actionRemoveSelectedPackages->setEnabled(enable); 0229 actionRemoveCurrentPackage->setEnabled(enable); 0230 } 0231 0232 void View::slotEditCut() 0233 { 0234 //debugPlanWork; 0235 } 0236 0237 void View::slotEditCopy() 0238 { 0239 //debugPlanWork; 0240 } 0241 0242 void View::slotEditPaste() 0243 { 0244 //debugPlanWork; 0245 } 0246 0247 void View::slotProgressChanged(int) 0248 { 0249 } 0250 0251 void View::slotConfigure() 0252 { 0253 } 0254 0255 ScheduleManager *View::currentScheduleManager() const 0256 { 0257 WorkPackage *wp = m_part->findWorkPackage(currentNode()); 0258 return wp ? wp->project()->scheduleManagers().value(0) : nullptr; 0259 } 0260 0261 void View::updateReadWrite(bool readwrite) 0262 { 0263 debugPlanWork<<m_readWrite<<"->"<<readwrite; 0264 m_readWrite = readwrite; 0265 0266 // actionTaskProgress->setEnabled(readwrite); 0267 0268 emit sigUpdateReadWrite(readwrite); 0269 } 0270 0271 Part *View::part() const 0272 { 0273 return m_part; 0274 } 0275 0276 void View::slotPopupMenu(const QString& name, const QPoint & pos) 0277 { 0278 debugPlanWork<<name; 0279 Q_ASSERT(m_part->factory()); 0280 if (m_part->factory() == 0) { 0281 return; 0282 } 0283 QMenu *menu = ((QMenu*) m_part->factory() ->container(name, m_part)); 0284 if (menu == 0) { 0285 return; 0286 } 0287 QList<QAction*> lst; 0288 AbstractView *v = currentView(); 0289 if (v) { 0290 lst = v->contextActionList(); 0291 debugPlanWork<<lst; 0292 if (! lst.isEmpty()) { 0293 menu->addSeparator(); 0294 foreach (QAction *a, lst) { 0295 menu->addAction(a); 0296 } 0297 } 0298 } 0299 menu->exec(pos); 0300 foreach (QAction *a, lst) { 0301 menu->removeAction(a); 0302 } 0303 } 0304 0305 bool View::loadContext() 0306 { 0307 debugPlanWork; 0308 setCurrentIndex(PlanWorkSettings::self()->currentView()); 0309 return true; 0310 } 0311 0312 void View::saveContext() const 0313 { 0314 debugPlanWork; 0315 PlanWorkSettings::self()->setCurrentView(currentIndex()); 0316 PlanWorkSettings::self()->save(); 0317 } 0318 0319 void View::slotEditDocument() 0320 { 0321 slotEditDocument(currentDocument()); 0322 } 0323 0324 void View::slotEditDocument(Document *doc) 0325 { 0326 debugPlanWork<<doc; 0327 if (doc == 0) { 0328 debugPlanWork<<"No document"; 0329 return; 0330 } 0331 if (doc->type() != Document::Type_Product) { 0332 KMessageBox::error(0, i18n("This file is not editable")); 0333 return; 0334 } 0335 part()->editWorkpackageDocument(doc); 0336 } 0337 0338 void View::slotViewDocument() 0339 { 0340 emit viewDocument(currentDocument()); 0341 } 0342 0343 void View::slotRemoveDocument() 0344 { 0345 part()->removeDocument(currentDocument()); 0346 } 0347 0348 void View::slotSendPackage() 0349 { 0350 Node *node = currentNode(); 0351 if (node == 0) { 0352 KMessageBox::error(0, i18n("No work package is selected")); 0353 return; 0354 } 0355 debugPlanWork<<node->name(); 0356 WorkPackage *wp = part()->findWorkPackage(node); 0357 if (wp == 0) { 0358 KMessageBox::error(0, i18n("Cannot find work package")); 0359 return; 0360 } 0361 /* if (wp->isModified()) { 0362 int r = KMessageBox::questionYesNoCancel(0, i18n("This work package has been modified.\nDo you want to save it before sending?"), node->name()); 0363 switch (r) { 0364 case KMessageBox::Cancel: return; 0365 case KMessageBox::Yes: wp->saveToProjects(part()); break; 0366 default: break; 0367 } 0368 }*/ 0369 0370 bool wasmodified = wp->isModified(); 0371 if (wp->sendUrl().isValid()) { 0372 QTemporaryFile temp(wp->sendUrl().toLocalFile() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String(".planwork")); 0373 temp.setAutoRemove(false); 0374 if (! temp.open()) { 0375 KMessageBox::error(0, i18n("Could not open file. Sending is aborted.")); 0376 return; 0377 } 0378 wp->saveNativeFormat(part(), temp.fileName()); 0379 } else { 0380 QTemporaryFile temp(QDir::tempPath() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String(".planwork")); 0381 temp.setAutoRemove(false); 0382 if (! temp.open()) { 0383 KMessageBox::error(0, i18n("Could not open temporary file. Sending is aborted.")); 0384 return; 0385 } 0386 wp->saveNativeFormat(part(), temp.fileName()); 0387 0388 QStringList attachURLs; 0389 attachURLs << temp.fileName(); 0390 0391 QString to = node->projectNode()->leader(); 0392 QString cc; 0393 QString bcc; 0394 QString subject = i18n("Work Package: %1", node->name()); 0395 QString body = node->projectNode()->name(); 0396 QString messageFile; 0397 0398 KToolInvocation::invokeMailer(to, cc, bcc, subject, body, messageFile, attachURLs); 0399 } 0400 wp->setModified(wasmodified); 0401 } 0402 0403 void View::slotTaskDescription() 0404 { 0405 Task *node = qobject_cast<Task*>(currentNode()); 0406 if (node == 0) { 0407 return; 0408 } 0409 QPointer<TaskDescriptionDialog> dlg = new TaskDescriptionDialog(*node, this, true); 0410 dlg->exec(); 0411 delete dlg; 0412 } 0413 0414 AbstractView *View::currentView() const 0415 { 0416 return qobject_cast<AbstractView*>(currentWidget()); 0417 } 0418 0419 Node *View::currentNode() const 0420 { 0421 AbstractView *v = currentView(); 0422 return v ? v->currentNode() : 0; 0423 } 0424 0425 Document *View::currentDocument() const 0426 { 0427 AbstractView *v = currentView(); 0428 return v ? v->currentDocument() : 0; 0429 } 0430 0431 void View::slotTaskProgress() 0432 { 0433 debugPlanWork; 0434 Task *n = qobject_cast<Task*>(currentNode()); 0435 if (n == 0) { 0436 return; 0437 } 0438 StandardWorktime *w = qobject_cast<Project*>(n->projectNode())->standardWorktime(); 0439 QPointer<TaskProgressDialog> dlg = new TaskProgressDialog(*n, currentScheduleManager(), w, this); 0440 if (dlg->exec() == QDialog::Accepted && dlg) { 0441 KUndo2Command *cmd = dlg->buildCommand(); 0442 if (cmd) { 0443 cmd->redo(); //FIXME m_part->addCommand(cmd); 0444 } 0445 } 0446 } 0447 0448 void View::slotTaskCompletion() 0449 { 0450 debugPlanWork; 0451 WorkPackage *wp = m_part->findWorkPackage(currentNode()); 0452 if (wp == 0) { 0453 return; 0454 } 0455 QPointer<TaskCompletionDialog> dlg = new TaskCompletionDialog(*wp, currentScheduleManager(), this); 0456 if (dlg->exec() == QDialog::Accepted && dlg) { 0457 KUndo2Command *cmd = dlg->buildCommand(); 0458 if (cmd) { 0459 m_part->addCommand(cmd); 0460 } 0461 } 0462 delete dlg; 0463 } 0464 0465 void View::slotRemoveSelectedPackages() 0466 { 0467 debugPlanWork; 0468 QList<Node*> lst = currentView()->selectedNodes(); 0469 if (lst.isEmpty()) { 0470 return; 0471 } 0472 m_part->removeWorkPackages(lst); 0473 } 0474 0475 void View::slotRemoveCurrentPackage() 0476 { 0477 debugPlanWork; 0478 Node *n = currentNode(); 0479 if (n == 0) { 0480 return; 0481 } 0482 m_part->removeWorkPackage(n); 0483 } 0484 0485 0486 } //KPlatoWork namespace