diff --git a/src/libs/ui/CMakeLists.txt b/src/libs/ui/CMakeLists.txt index 253a9b66..41753349 100644 --- a/src/libs/ui/CMakeLists.txt +++ b/src/libs/ui/CMakeLists.txt @@ -1,188 +1,190 @@ include_directories( ${PLANKERNEL_INCLUDES} ${PLANMODELS_INCLUDES} ${PLANMAIN_INCLUDES} ${PLANWIDGETS_INCLUDES} ${KDEPIMLIBS_INCLUDE_DIR} ) #add_subdirectory( tests ) ########### KPlato private library ############### if (PLAN_USE_KREPORT) message(STATUS "-- Building plan with reports capability") add_subdirectory(reports/items) set(planreports_LIB_SRC reports/reportview.cpp reports/reportdata.cpp reports/reportsourceeditor.cpp reports/reportscripts.cpp ) set(planreports_ui_LIB_SRCS reports/reportsourceeditor.ui reports/reportnavigator.ui reports/reportsectionswidget.ui reports/reportgroupsectionswidget.ui reports/reporttoolswidget.ui ) endif() set(planui_LIB_SRCS ${planreports_LIB_SRC} Help.cpp TasksEditController.cpp TasksEditDialog.cpp welcome/WelcomeView.cpp reportsgenerator/ReportsGeneratorView.cpp kptganttitemdelegate.cpp kptworkpackagesendpanel.cpp kptworkpackagesenddialog.cpp kptdocumentseditor.cpp kptdocumentspanel.cpp kptitemviewsettup.cpp kptsplitterview.cpp kptrelationeditor.cpp kptdependencyeditor.cpp kptusedefforteditor.cpp kpttaskstatusview.cpp kptcalendareditor.cpp kptviewbase.cpp kptaccountseditor.cpp kptperteditor.cpp kptpertresult.cpp kpttaskeditor.cpp kptresourceeditor.cpp kptscheduleeditor.cpp kptsummarytaskdialog.cpp kptsummarytaskgeneralpanel.cpp kptresourceappointmentsview.cpp kptaccountsviewconfigdialog.cpp kptaccountsview.cpp kpttaskcostpanel.cpp kptmilestoneprogresspanel.cpp kptmilestoneprogressdialog.cpp kpttaskdialog.cpp kptmainprojectdialog.cpp kptmainprojectpanel.cpp kptganttview.cpp + gantt/DateTimeTimeLine.cpp + gantt/DateTimeGrid.cpp kptrelationdialog.cpp kptrequestresourcespanel.cpp kptresourcedialog.cpp kptstandardworktimedialog.cpp kptintervaledit.cpp kpttaskgeneralpanel.cpp kpttaskprogresspanel.cpp kpttaskprogressdialog.cpp kpttaskdescriptiondialog.cpp kptwbsdefinitiondialog.cpp kptwbsdefinitionpanel.cpp kptresourceassignmentview.cpp kptperformancetablewidget.cpp kptresourceallocationeditor.cpp kptworkpackagemergedialog.cpp kptrecalculatedialog.cpp kpthtmlview.cpp locale/localemon.cpp kptlocaleconfigmoneydialog.cpp ResourceAllocationView.cpp performance/PerformanceStatusBase.cpp performance/ProjectStatusView.cpp performance/PerformanceStatusView.cpp ) ki18n_wrap_ui(planui_LIB_SRCS ${planreports_ui_LIB_SRCS} welcome/WelcomeView.ui kptresourceappointmentsdisplayoptions.ui kptganttchartdisplayoptions.ui kptprintingheaderfooter.ui kptganttprintingoptions.ui kptworkpackagesendpanel.ui kptdocumentspanel.ui performance/PerformanceStatus.ui performance/PerformanceStatusViewSettingsPanel.ui kptcpmwidget.ui kptitemviewsettings.ui kptpertresult.ui standardworktimedialogbase.ui kptwbsdefinitionpanelbase.ui kptaccountsviewconfigurepanelbase.ui kptintervaleditbase.ui kpttaskcostpanelbase.ui kpttaskdescriptionpanelbase.ui kptsummarytaskgeneralpanelbase.ui kptmilestoneprogresspanelbase.ui resourcedialogbase.ui kptmainprojectpanelbase.ui relationpanel.ui kpttaskgeneralpanelbase.ui kpttaskprogresspanelbase.ui kptperteditor.ui kptresourceassignmentview.ui kpttaskstatusviewsettingspanel.ui kptworkpackagemergepanel.ui kptrecalculatedialog.ui kptscheduleeditor.ui locale/localemon.ui ) add_library(planui SHARED ${planui_LIB_SRCS}) generate_export_header(planui) target_link_libraries(planui PUBLIC planmain planmodels KF5::KHtml PRIVATE KChart KF5::ItemViews KF5::IconThemes KF5::Archive KF5::TextWidgets # Qt5::Sql ) if (PLAN_USE_KREPORT) target_link_libraries(planui PUBLIC KReport PRIVATE KPropertyWidgets) endif() if(KF5AkonadiContact_FOUND) target_link_libraries(planui PRIVATE KF5::AkonadiContact) endif() set_target_properties(planui PROPERTIES VERSION ${GENERIC_PLAN_LIB_VERSION} SOVERSION ${GENERIC_PLAN_LIB_SOVERSION} ) install(TARGETS planui ${INSTALL_TARGETS_DEFAULT_ARGS}) # reports files install(FILES reportsgenerator/ProjectPerformanceCost.odt reportsgenerator/ProjectPerformance.odt reportsgenerator/TaskStatus.odt DESTINATION ${DATA_INSTALL_DIR}/calligraplan/reports ) diff --git a/src/libs/ui/gantt/DateTimeGrid.cpp b/src/libs/ui/gantt/DateTimeGrid.cpp new file mode 100644 index 00000000..6f747f02 --- /dev/null +++ b/src/libs/ui/gantt/DateTimeGrid.cpp @@ -0,0 +1,74 @@ +/* This file is part of the KDE project + * Copyright (C) 2019 Dag Andersen + * + * 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; either + * version 2 of the License, or (at your option) any later version. + * + * 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 "DateTimeGrid.h" +#include "config.h" + +#include +#include +#include + +using namespace KPlato; + +DateTimeGrid::DateTimeGrid() + : KGantt::DateTimeGrid() + , m_timeLine(new DateTimeTimeLine()) +{} + +void DateTimeGrid::drawDayBackground(QPainter* painter, const QRectF& rect, const QDate& date) +{ + Q_UNUSED(date); + if (m_timeLine->options() & DateTimeTimeLine::Background) { + drawTimeLine(painter, rect); + } +} + +void DateTimeGrid::drawDayForeground(QPainter* painter, const QRectF& rect, const QDate& date) +{ + Q_UNUSED(date); + if (m_timeLine->options() & DateTimeTimeLine::Foreground) { + drawTimeLine(painter, rect); + } +} + +DateTimeTimeLine *DateTimeGrid::timeNow() const +{ + return m_timeLine; +} + +void DateTimeGrid::drawTimeLine(QPainter* painter, const QRectF& rect) +{ + qreal x = dateTimeToChartX(m_timeLine->dateTime()); + if (rect.contains(x, rect.top())) { + painter->save(); + painter->setPen(m_timeLine->pen()); + painter->drawLine(x, rect.top(), x, rect.bottom()); + painter->restore(); + } +} + +qreal DateTimeGrid::dateTimeToChartX( const QDateTime& dt ) const +{ + qreal result = startDateTime().date().daysTo(dt.date())*24.*60.*60.; + result += startDateTime().time().msecsTo(dt.time())/1000.; + result *= dayWidth()/( 24.*60.*60. ); + + return result; +} + diff --git a/src/libs/ui/gantt/DateTimeGrid.h b/src/libs/ui/gantt/DateTimeGrid.h new file mode 100644 index 00000000..99165b88 --- /dev/null +++ b/src/libs/ui/gantt/DateTimeGrid.h @@ -0,0 +1,51 @@ +/* This file is part of the KDE project + * Copyright (C) 2019 Dag Andersen + * + * 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; either + * version 2 of the License, or (at your option) any later version. + * + * 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. + */ + +#ifndef KPLATODATETIMEGRID_H +#define KPLATODATETIMEGRID_H + +#include + +#include "DateTimeTimeLine.h" + +namespace KPlato { + +class DateTimeGrid : public KGantt::DateTimeGrid +{ +public: + DateTimeGrid(); + + DateTimeTimeLine *timeNow() const; + +protected: + void drawDayBackground(QPainter* painter, const QRectF& rect, const QDate& date); + + void drawDayForeground(QPainter* painter, const QRectF& rect, const QDate& date); + + void drawTimeLine(QPainter* painter, const QRectF& rect); + + qreal dateTimeToChartX( const QDateTime& dt ) const; + +private: + DateTimeTimeLine *m_timeLine; +}; + +} + +#endif diff --git a/src/libs/ui/gantt/DateTimeTimeLine.cpp b/src/libs/ui/gantt/DateTimeTimeLine.cpp new file mode 100644 index 00000000..f1d283cf --- /dev/null +++ b/src/libs/ui/gantt/DateTimeTimeLine.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2019 Dag Andersen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "DateTimeTimeLine.h" + +#include +#include +#include +#include +#include +#include +#include + + + +namespace KPlato { + class Q_DECL_HIDDEN DateTimeTimeLine::Private + { + public: + Private() : options(Foreground) {} + + DateTimeTimeLine::Options options; + QDateTime dateTime; + QPen pen; + QTimer timer; + }; + +} + +using namespace KPlato; + +/*!\class KPlato::DateTimeTimeLine + * \ingroup KPlato + * + * This class implements a timeline. + * + * The timeline can optionally be shown in the Background or in the Foreground. + * Default is Foreground. + * + * The pen can be set with setPen(), and must be activated by setting the option UseCustomPen. + * + * The datetime can be set using setDateTime(). + * + * The timeline can priodically moved to the current datetime + * by setting the interval > 0 with setInterval(). + * Setting a zero interval turns the periodically update off. + * + * The timeline is off by default. + * + * For example: + * \code + * // Show a red timeline in the foreground + * timeLine->setOptions(UseCustomPen); + * timeLine->setPen(QPen(Qt:red)); + * // Update the timeline every 5 seconds + * timeLine->setInterval(5000); + * \endcode + */ + +/** + * Create a timeline object. + * + * By default, no timeline is displayed. + */ +DateTimeTimeLine::DateTimeTimeLine() + : d( new Private()) +{ + d->pen = QPen(QApplication::palette().color(QPalette::Highlight), 0); + connect(&d->timer, SIGNAL(timeout()), this, SIGNAL(updated())); +} + +/** + * @return options + */ +DateTimeTimeLine::Options DateTimeTimeLine::options() const +{ + return d->options; +} + +/** + * Set options to @p options. + * If both Background and Foreground are set, Foreground is used. + */ +void DateTimeTimeLine::setOptions(DateTimeTimeLine::Options options) +{ + d->options = options; + if (options & Foreground) { + d->options &= ~Background; + } + Q_EMIT updated(); +} + +/** + * @return the datetime + * If the datetime is not valid, the current datetime is returned. + */ +QDateTime DateTimeTimeLine::dateTime() const +{ + return d->dateTime.isValid() ? d->dateTime : QDateTime::currentDateTime(); +} + +/** + * Set datetime to @p dt. + */ +void DateTimeTimeLine::setDateTime(const QDateTime &dt) +{ + d->dateTime = dt; + Q_EMIT updated(); +} + +/** + * Set timer interval to @p msecs milliseconds. + * Setting a zero time disables the timer. + */ +void DateTimeTimeLine::setInterval(int msecs) +{ + d->timer.stop(); + d->timer.setInterval(msecs); + Q_EMIT updated(); + if (msecs > 0) { + d->timer.start(); + } +} + +/** + * @return the pen to be used to draw the timeline. + * If option UseCustomPen is not set a default pen is returned. + */ +QPen DateTimeTimeLine::pen() const +{ + if (d->options & DateTimeTimeLine::UseCustomPen) { + return d->pen; + } + return QPen(QApplication::palette().color(QPalette::Highlight), 0); +} + +/** + * Set the custom pen to @p pen. + */ +void DateTimeTimeLine::setPen(const QPen &pen) +{ + d->pen = pen; + Q_EMIT updated(); +} diff --git a/src/libs/ui/gantt/DateTimeTimeLine.h b/src/libs/ui/gantt/DateTimeTimeLine.h new file mode 100644 index 00000000..93ae17fa --- /dev/null +++ b/src/libs/ui/gantt/DateTimeTimeLine.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 Dag Andersen + * + * This file is part of the KGantt library. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KPLATODATETIMETIMELINE_H +#define KPLATODATETIMETIMELINE_H + +#include "kganttglobal.h" + +#include + +class QDateTime; + +namespace KPlato { + +class DateTimeTimeLine : public QObject +{ + Q_OBJECT +public: + enum Option { + Foreground = 1, /// Display the timeline in the foreground. + Background = 2, /// Display the timeline in the background. + UseCustomPen = 4, /// Paint the timeline using the pen set with setTimelinePen(). + MaxOptions = 0xFFFF + }; + Q_DECLARE_FLAGS(Options, Option) + + DateTimeTimeLine(); + + DateTimeTimeLine::Options options() const; + void setOptions(DateTimeTimeLine::Options options); + QDateTime dateTime() const; + void setDateTime(const QDateTime &dt); + void setInterval(int msec); + QPen pen() const; + void setPen(const QPen &pen); + +Q_SIGNALS: + void updated(); + +private: + class Private; + Private *d; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(DateTimeTimeLine::Options) + +} + +#endif /* KPLATODATETIMETIMELINE_H */ + diff --git a/src/libs/ui/kptganttview.cpp b/src/libs/ui/kptganttview.cpp index 2029501b..a2c5a4d0 100644 --- a/src/libs/ui/kptganttview.cpp +++ b/src/libs/ui/kptganttview.cpp @@ -1,1461 +1,1467 @@ /* This file is part of the KDE project Copyright (C) 2002 - 2007, 2012 Dag Andersen Copyright (C) 2006 Raphael Langerhorst Copyright (C) 2016 Dag Andersen 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; either version 2 of the License, or (at your option) any later version. 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. */ // clazy:excludeall=qstring-arg #include "kptganttview.h" #include "kptnodeitemmodel.h" #include "kptappointment.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptresource.h" #include "kptrelation.h" #include "kptschedule.h" #include "kptviewbase.h" #include "kptitemviewsettup.h" #include "kptduration.h" #include "kptdatetime.h" #include "kptresourceappointmentsmodel.h" #include "Help.h" #include "kptdebug.h" +#include "gantt/DateTimeTimeLine.h" +#include "gantt/DateTimeGrid.h" +#include "config.h" #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /// The main namespace namespace KPlato { class GanttItemDelegate; //------------------------------------------------- GanttChartDisplayOptionsPanel::GanttChartDisplayOptionsPanel( GanttItemDelegate *delegate, QWidget *parent ) : QWidget( parent ), m_delegate( delegate ) { setupUi( this ); setValues( *delegate ); connect( ui_showTaskName, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showResourceNames, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showDependencies, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showPositiveFloat, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showNegativeFloat, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showCriticalPath, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showCriticalTasks, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showCompletion, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showSchedulingError, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); connect( ui_showTimeConstraint, &QCheckBox::stateChanged, this, &GanttChartDisplayOptionsPanel::changed ); } void GanttChartDisplayOptionsPanel::slotOk() { m_delegate->showTaskName = ui_showTaskName->checkState() == Qt::Checked; m_delegate->showResources = ui_showResourceNames->checkState() == Qt::Checked; m_delegate->showTaskLinks = ui_showDependencies->checkState() == Qt::Checked; m_delegate->showPositiveFloat = ui_showPositiveFloat->checkState() == Qt::Checked; m_delegate->showNegativeFloat = ui_showNegativeFloat->checkState() == Qt::Checked; m_delegate->showCriticalPath = ui_showCriticalPath->checkState() == Qt::Checked; m_delegate->showCriticalTasks = ui_showCriticalTasks->checkState() == Qt::Checked; m_delegate->showProgress = ui_showCompletion->checkState() == Qt::Checked; m_delegate->showSchedulingError = ui_showSchedulingError->checkState() == Qt::Checked; m_delegate->showTimeConstraint = ui_showTimeConstraint->checkState() == Qt::Checked; } void GanttChartDisplayOptionsPanel::setValues( const GanttItemDelegate &del ) { ui_showTaskName->setCheckState( del.showTaskName ? Qt::Checked : Qt::Unchecked ); ui_showResourceNames->setCheckState( del.showResources ? Qt::Checked : Qt::Unchecked ); ui_showDependencies->setCheckState( del.showTaskLinks ? Qt::Checked : Qt::Unchecked ); ui_showPositiveFloat->setCheckState( del.showPositiveFloat ? Qt::Checked : Qt::Unchecked ); ui_showNegativeFloat->setCheckState( del.showNegativeFloat ? Qt::Checked : Qt::Unchecked ); ui_showCriticalPath->setCheckState( del.showCriticalPath ? Qt::Checked : Qt::Unchecked ); ui_showCriticalTasks->setCheckState( del.showCriticalTasks ? Qt::Checked : Qt::Unchecked ); ui_showCompletion->setCheckState( del.showProgress ? Qt::Checked : Qt::Unchecked ); ui_showSchedulingError->setCheckState( del.showSchedulingError ? Qt::Checked : Qt::Unchecked ); ui_showTimeConstraint->setCheckState( del.showTimeConstraint ? Qt::Checked : Qt::Unchecked ); } void GanttChartDisplayOptionsPanel::setDefault() { GanttItemDelegate del; setValues( del ); } //---- GanttViewSettingsDialog::GanttViewSettingsDialog( GanttViewBase *gantt, GanttItemDelegate *delegate, ViewBase *view, bool selectPrint ) : ItemViewSettupDialog( view, gantt->treeView(), true, view ), m_gantt( gantt ) { GanttChartDisplayOptionsPanel *panel = new GanttChartDisplayOptionsPanel( delegate ); /*KPageWidgetItem *page = */insertWidget( 1, panel, i18n( "Chart" ), i18n( "Gantt Chart Settings" ) ); QTabWidget *tab = new QTabWidget(); QWidget *w = ViewBase::createPageLayoutWidget( view ); tab->addTab( w, w->windowTitle() ); m_pagelayout = w->findChild(); Q_ASSERT( m_pagelayout ); m_printingoptions = new GanttPrintingOptionsWidget( this ); m_printingoptions->setOptions( gantt->printingOptions() ); tab->addTab( m_printingoptions, m_printingoptions->windowTitle() ); KPageWidgetItem *page = insertWidget( 2, tab, i18n( "Printing" ), i18n( "Printing Options" ) ); if (selectPrint) { setCurrentPage(page); } connect( this, SIGNAL(accepted()), this, SLOT(slotOk()) ); connect( this, &QDialog::accepted, panel, &GanttChartDisplayOptionsPanel::slotOk ); connect( button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, panel, &GanttChartDisplayOptionsPanel::setDefault ); } void GanttViewSettingsDialog::slotOk() { debugPlan; m_gantt->setPrintingOptions( m_printingoptions->options()); ItemViewSettupDialog::slotOk(); } //------------------------- GanttPrintingOptions::GanttPrintingOptions() : printRowLabels( true ), singlePage( true ) { } bool GanttPrintingOptions::loadContext( const KoXmlElement &settings ) { KoXmlElement e = settings.namedItem( "print-options" ).toElement(); if ( ! e.isNull() ) { printRowLabels = (bool)( e.attribute( "print-rowlabels", "0" ).toInt() ); singlePage = (bool)( e.attribute( "print-singlepage", "0" ).toInt() ); } debugPlan <<"..........."<treeView()->header()->height(); // same header hight m_sceneRect = gantt->graphicsView()->sceneRect(); m_horPages = 1; qreal c = m_sceneRect.width() - printer().pageRect().width(); while ( c > 0 ) { ++m_horPages; c -= printer().pageRect().width(); } m_vertPages = 1; c = m_sceneRect.height() - printer().pageRect().height() - m_headerHeight; while ( c > 0 ) { ++m_vertPages; c -= printer().pageRect().height(); } debugPlan< pages; if ( printer().fromPage() > 0 ) { pages << printer().fromPage(); if ( ! m_gantt->m_printOptions.singlePage ) { int last = printer().toPage(); for ( int i = pages.first() + 1; i <= last; ++i ) { pages << i; } if (m_vertPages > 1) { m_image = QImage(m_sceneRect.width(), m_sceneRect.height() + m_headerHeight, QImage::Format_ARGB32); m_image.fill(Qt::white); QPainter p(&m_image); m_gantt->print(&p, m_image.rect(), m_gantt->m_printOptions.printRowLabels, true); } } } setPageRange( pages ); PrintingDialog::startPrinting( removePolicy ); } QList GanttPrintingDialog::createOptionWidgets() const { //debugPlan; GanttPrintingOptionsWidget *w = new GanttPrintingOptionsWidget(); w->setPrintRowLabels( m_gantt->m_printOptions.printRowLabels ); connect(w->ui_printRowLabels, &QAbstractButton::toggled, this, &GanttPrintingDialog::slotPrintRowLabelsToogled); w->setSinglePage( m_gantt->m_printOptions.singlePage ); connect(w->ui_singlePage, &QAbstractButton::toggled, this, &GanttPrintingDialog::slotSinglePageToogled); const_cast( this )->m_options = w; return QList() << createPageLayoutWidget() << m_options; } void GanttPrintingDialog::slotPrintRowLabelsToogled( bool on ) { m_gantt->m_printOptions.printRowLabels = on; } void GanttPrintingDialog::slotSinglePageToogled( bool on ) { m_gantt->m_printOptions.singlePage = on; printer().setFromTo( documentFirstPage(), documentLastPage() ); } int GanttPrintingDialog::documentLastPage() const { //debugPlan<m_printOptions.singlePage<m_printOptions.singlePage ? documentFirstPage() : m_horPages * m_vertPages; } void GanttPrintingDialog::printPage( int page, QPainter &painter ) { debugPlan<<"page:"<m_printOptions.singlePage; int vert = singlePage ? 0 : p / m_horPages; int hor = singlePage ? 0 : p % m_horPages; // painter.setClipRect( pageRect.adjusted( -1.0, -1.0, 1.0, 1.0 ) ); if (singlePage) { // single page: use KGantt m_gantt->print( &painter, m_sceneRect.left(), m_sceneRect.right(), pageRect, m_gantt->m_printOptions.printRowLabels, true ); } else if (m_vertPages == 1) { // single vertical page: use KGantt qreal hh = vert == 0 ? m_headerHeight : 0; qreal ho = vert > 0 ? m_headerHeight : 0; QRectF sourceRect = QRectF( m_sceneRect.x() + ( pageRect.width() * hor ), m_sceneRect.y() + ( ( pageRect.height() * vert ) - ho ), pageRect.width(), pageRect.height() - hh ); debugPlan<print( &painter, sourceRect.left(), sourceRect.right(), pageRect, hor == 0 && m_gantt->m_printOptions.printRowLabels, true ); } else { // print on multiple vertical pages: use pixmap // QT5TODO Make KGantt able to print multiple pages vertically QRectF sourceRect = m_image.rect(); qreal hh = vert == 0 ? m_headerHeight : 0; qreal ho = vert > 0 ? m_headerHeight : 0; sourceRect = QRectF( sourceRect.x() + ( pageRect.width() * hor ), sourceRect.y() + ( ( pageRect.height() * vert ) - ho ), pageRect.width(), pageRect.height() - hh ); debugPlan<setContextMenuPolicy( Qt::CustomContextMenu ); connect( header(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotHeaderContextMenuRequested(QPoint)) ); } //------------------------------------------- GanttZoomWidget::GanttZoomWidget( QWidget *parent ) : QSlider( parent ), m_hide( true ), m_grid( 0 ) { setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); setGeometry( 0, 0, 200, minimumSizeHint().height() ); setContextMenuPolicy( Qt::PreventContextMenu ); setOrientation( Qt::Horizontal ); setPageStep( 5 ); setMaximum( 125 ); connect(this, &QAbstractSlider::valueChanged, this, &GanttZoomWidget::sliderValueChanged); } void GanttZoomWidget::setEnableHideOnLeave( bool hide ) { m_hide = hide; } void GanttZoomWidget::setGrid( KGantt::DateTimeGrid *grid ) { m_grid = grid; if ( grid ) { int pos = -1; // daywidth always >= 0.1 for ( qreal dw = grid->dayWidth(); dw >= 0.1 && pos < maximum(); ++pos ) { dw *= 1.0 / 1.1; } blockSignals( true ); setValue( pos ); blockSignals( false ); } } void GanttZoomWidget::leaveEvent( QEvent *e ) { if ( m_hide ) { setVisible( false ); } QSlider::leaveEvent( e ); } void GanttZoomWidget::sliderValueChanged( int value ) { //debugPlan<setDayWidth( v ); } } //------------------------------------------- GanttViewBase::GanttViewBase( QWidget *parent ) : KGantt::View( parent ) { - KGantt::DateTimeGrid *g = static_cast( grid() ); + setGrid(new DateTimeGrid()); + DateTimeGrid *g = static_cast( grid() ); g->setUserDefinedUpperScale( new KGantt::DateTimeScaleFormatter(KGantt::DateTimeScaleFormatter::Month, QString::fromLatin1("yyyy-MMMM"))); g->setUserDefinedLowerScale( new KGantt::DateTimeScaleFormatter(KGantt::DateTimeScaleFormatter::Day, QString::fromLatin1("ddd"))); + + g->timeNow()->setInterval(5000); + QLocale locale; g->setWeekStart( locale.firstDayOfWeek() ); const QList weekdays = locale.weekdays(); QSet fd; for ( int i = Qt::Monday; i <= Qt::Sunday; ++i ) { if (!weekdays.contains(static_cast(i))) { fd << static_cast( i ); } } g->setFreeDays( fd ); m_zoomwidget = new GanttZoomWidget( graphicsView() ); m_zoomwidget->setGrid( g ); m_zoomwidget->setEnableHideOnLeave( true ); m_zoomwidget->hide(); m_zoomwidget->move( 6, 6 ); graphicsView()->installEventFilter(this); graphicsView()->setMouseTracking(true); } GanttViewBase::~GanttViewBase() { // HACK: avoid crash due to access of graphicsview scrollbar after death // KGantt tries to sync leftview scrollbar with graphicsview scrollbar // and seems sometimes graphicsview has already been deleted. // Note: this will be fixed in next KGantt release leftView()->verticalScrollBar()->disconnect(); } GanttTreeView *GanttViewBase::treeView() const { GanttTreeView *tv = qobject_cast(const_cast(leftView())); Q_ASSERT(tv); return tv; } bool GanttViewBase::eventFilter(QObject *obj, QEvent *event) { if (obj != graphicsView()) { return false; } if (event->type() == QEvent::HoverMove) { QHoverEvent *e = static_cast( event ); if (e->pos().y() > 7 && e->pos().y() < m_zoomwidget->height() + 5 && e->pos().x() > 7 && e->pos().x() < m_zoomwidget->width() + 5 ) { if ( !m_zoomwidget->isVisible()) { m_zoomwidget->show(); m_zoomwidget->setFocus(); } return true; } } return false; } bool GanttViewBase::loadContext( const KoXmlElement &settings ) { KGantt::DateTimeGrid *g = static_cast( grid() ); g->setScale( static_cast( settings.attribute( "chart-scale", "0" ).toInt() ) ); g->setDayWidth( settings.attribute( "chart-daywidth", "30" ).toDouble() ); return true; } void GanttViewBase::saveContext( QDomElement &settings ) const { KGantt::DateTimeGrid *g = static_cast( grid() ); settings.setAttribute( "chart-scale", QString::number(g->scale()) ); settings.setAttribute( "chart-daywidth", QString::number(g->dayWidth()) ); } //------------------------------------------- NodeGanttViewBase::NodeGanttViewBase( QWidget *parent ) : GanttViewBase( parent ), m_project( 0 ), m_ganttdelegate( new GanttItemDelegate( this ) ) { debugPlan<<"------------------- create NodeGanttViewBase -----------------------"; graphicsView()->setItemDelegate( m_ganttdelegate ); GanttTreeView *tv = new GanttTreeView( this ); tv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); tv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); tv->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); // needed since qt 4.2 setLeftView( tv ); m_rowController = new KGantt::TreeViewRowController( tv, ganttProxyModel() ); setRowController( m_rowController ); tv->header()->setStretchLastSection( true ); NodeSortFilterProxyModel *m = new NodeSortFilterProxyModel( &m_defaultModel, this ); KGantt::View::setModel( m ); } NodeGanttViewBase::~NodeGanttViewBase() { delete m_rowController; } NodeSortFilterProxyModel *NodeGanttViewBase::sfModel() const { return static_cast( KGantt::View::model() ); } void NodeGanttViewBase::setItemModel( ItemModelBase *model ) { sfModel()->setSourceModel( model ); } ItemModelBase *NodeGanttViewBase::model() const { return sfModel()->itemModel(); } void NodeGanttViewBase::setProject( Project *project ) { model()->setProject( project ); m_project = project; } bool NodeGanttViewBase::loadContext( const KoXmlElement &settings ) { treeView()->loadContext( model()->columnMap(), settings ); KoXmlElement e = settings.namedItem( "ganttchart" ).toElement(); if ( ! e.isNull() ) { m_ganttdelegate->showTaskLinks = (bool)( e.attribute( "show-dependencies", "0" ).toInt() ); m_ganttdelegate->showTaskName = (bool)( e.attribute( "show-taskname", "0" ).toInt() ); m_ganttdelegate->showResources = (bool)( e.attribute( "show-resourcenames", "0" ).toInt() ); m_ganttdelegate->showProgress = (bool)( e.attribute( "show-completion", "0" ).toInt() ); m_ganttdelegate->showCriticalPath = (bool)( e.attribute( "show-criticalpath", "0" ).toInt() ); m_ganttdelegate->showCriticalTasks = (bool)( e.attribute( "show-criticaltasks", "0" ).toInt() ); m_ganttdelegate->showPositiveFloat = (bool)( e.attribute( "show-positivefloat", "0" ).toInt() ); m_ganttdelegate->showSchedulingError = (bool)( e.attribute( "show-schedulingerror", "0" ).toInt() ); m_ganttdelegate->showTimeConstraint = (bool)( e.attribute( "show-timeconstraint", "0" ).toInt() ); m_ganttdelegate->showNegativeFloat = (bool)( e.attribute( "show-negativefloat", "0" ).toInt() ); GanttViewBase::loadContext( e ); m_printOptions.loadContext( e ); } return true; } void NodeGanttViewBase::saveContext( QDomElement &settings ) const { debugPlan; treeView()->saveContext( model()->columnMap(), settings ); QDomElement e = settings.ownerDocument().createElement( "ganttchart" ); settings.appendChild( e ); e.setAttribute( "show-dependencies", QString::number(m_ganttdelegate->showTaskLinks) ); e.setAttribute( "show-taskname", QString::number(m_ganttdelegate->showTaskName) ); e.setAttribute( "show-resourcenames", QString::number(m_ganttdelegate->showResources) ); e.setAttribute( "show-completion", QString::number(m_ganttdelegate->showProgress) ); e.setAttribute( "show-criticalpath", QString::number(m_ganttdelegate->showCriticalPath) ); e.setAttribute( "show-criticaltasks",QString::number(m_ganttdelegate->showCriticalTasks) ); e.setAttribute( "show-positivefloat", QString::number(m_ganttdelegate->showPositiveFloat) ); e.setAttribute( "show-schedulingerror", QString::number(m_ganttdelegate->showSchedulingError) ); e.setAttribute( "show-timeconstraint", QString::number(m_ganttdelegate->showTimeConstraint) ); e.setAttribute( "show-negativefloat", QString::number(m_ganttdelegate->showNegativeFloat) ); GanttViewBase::saveContext( e ); m_printOptions.saveContext( e ); } //------------------------------------------- MyKGanttView::MyKGanttView( QWidget *parent ) : NodeGanttViewBase( parent ), m_manager( 0 ) { debugPlan<<"------------------- create MyKGanttView -----------------------"; GanttItemModel *gm = new GanttItemModel( this ); setItemModel( gm ); treeView()->createItemDelegates( gm ); QList show; show << NodeModel::NodeName << NodeModel::NodeCompleted << NodeModel::NodeStartTime << NodeModel::NodeEndTime; treeView()->setDefaultColumns( show ); for ( int i = 0; i < model()->columnCount(); ++i ) { if ( ! show.contains( i ) ) { treeView()->hideColumn( i ); } } setConstraintModel( new KGantt::ConstraintModel( this ) ); KGantt::ProxyModel *m = static_cast( ganttProxyModel() ); m->setRole( KGantt::ItemTypeRole, KGantt::ItemTypeRole ); // To provide correct format m->setRole( KGantt::StartTimeRole, Qt::EditRole ); // To provide correct format m->setRole( KGantt::EndTimeRole, Qt::EditRole ); // To provide correct format m->removeColumn( Qt::DisplayRole ); m->setColumn( KGantt::ItemTypeRole, NodeModel::NodeType ); m->setColumn( KGantt::StartTimeRole, NodeModel::NodeStartTime ); m->setColumn( KGantt::EndTimeRole, NodeModel::NodeEndTime ); m->setColumn( KGantt::TaskCompletionRole, NodeModel::NodeCompleted ); KGantt::DateTimeGrid *g = static_cast( grid() ); g->setDayWidth( 30 ); // TODO: extend QLocale/KGantt to support formats for hourly time display // see bug #349030 // removed custom code here connect( model(), &NodeItemModel::nodeInserted, this, &MyKGanttView::slotNodeInserted ); } GanttItemModel *MyKGanttView::model() const { return static_cast( NodeGanttViewBase::model() ); } void MyKGanttView::setProject( Project *proj ) { clearDependencies(); if ( project() ) { disconnect( project(), &Project::relationToBeModified, this, &MyKGanttView::removeDependency); disconnect( project(), &Project::relationModified, this, &MyKGanttView::addDependency); disconnect( project(), &Project::relationAdded, this, &MyKGanttView::addDependency ); disconnect( project(), &Project::relationToBeRemoved, this, &MyKGanttView::removeDependency ); disconnect( project(), &Project::projectCalculated, this, &MyKGanttView::slotProjectCalculated ); } NodeGanttViewBase::setProject( proj ); if ( proj ) { connect( project(), &Project::relationToBeModified, this, &MyKGanttView::removeDependency); connect( project(), &Project::relationModified, this, &MyKGanttView::addDependency); connect( proj, &Project::relationAdded, this, &MyKGanttView::addDependency ); connect( proj, &Project::relationToBeRemoved, this, &MyKGanttView::removeDependency ); connect( proj, &Project::projectCalculated, this, &MyKGanttView::slotProjectCalculated ); } createDependencies(); } void MyKGanttView::slotProjectCalculated( ScheduleManager *sm ) { if ( m_manager == sm ) { setScheduleManager( sm ); } } void MyKGanttView::setScheduleManager( ScheduleManager *sm ) { clearDependencies(); m_manager = sm; KGantt::DateTimeGrid *g = static_cast( grid() ); if ( sm && project() ) { QDateTime start = project()->startTime( sm->scheduleId() ); if ( g->startDateTime() != start ) { g->setStartDateTime( start ); } } if ( ! g->startDateTime().isValid() ) { g->setStartDateTime( QDateTime::currentDateTime() ); } model()->setScheduleManager( sm ); createDependencies(); } void MyKGanttView::slotNodeInserted( Node *node ) { foreach( Relation *r, node->dependChildNodes() ) { addDependency( r ); } foreach( Relation *r, node->dependParentNodes() ) { addDependency( r ); } } void MyKGanttView::addDependency( Relation *rel ) { QModelIndex par = sfModel()->mapFromSource( model()->index( rel->parent() ) ); QModelIndex ch = sfModel()->mapFromSource( model()->index( rel->child() ) ); // debugPlan<<"addDependency() "<( rel->type() )/*NOTE!!*/ ); if ( ! constraintModel()->hasConstraint( con ) ) { constraintModel()->addConstraint( con ); } } } void MyKGanttView::removeDependency( Relation *rel ) { QModelIndex par = sfModel()->mapFromSource( model()->index( rel->parent() ) ); QModelIndex ch = sfModel()->mapFromSource( model()->index( rel->child() ) ); KGantt::Constraint con( par, ch, KGantt::Constraint::TypeSoft, static_cast( rel->type() )/*NOTE!!*/ ); constraintModel()->removeConstraint( con ); } void MyKGanttView::clearDependencies() { constraintModel()->clear(); // Remove old deps from view // NOTE: This should be handled by KGantt graphicsView()->updateScene(); } void MyKGanttView::createDependencies() { clearDependencies(); if ( project() == 0 || m_manager == 0 ) { return; } foreach ( Node* n, project()->allNodes() ) { foreach ( Relation *r, n->dependChildNodes() ) { addDependency( r ); } } } //------------------------------------------ GanttView::GanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite) : ViewBase(part, doc, parent), m_readWrite( readWrite ), m_project( 0 ) { debugPlan <<" ---------------- KPlato: Creating GanttView ----------------"; QVBoxLayout *l = new QVBoxLayout( this ); l->setMargin( 0 ); m_splitter = new QSplitter( this ); l->addWidget( m_splitter ); m_splitter->setOrientation( Qt::Vertical ); m_gantt = new MyKGanttView( m_splitter ); connect(this, &ViewBase::expandAll, m_gantt->treeView(), &TreeViewBase::slotExpand); connect(this, &ViewBase::collapseAll, m_gantt->treeView(), &TreeViewBase::slotCollapse); setupGui(); updateReadWrite( readWrite ); //connect( m_gantt->constraintModel(), SIGNAL(constraintAdded(Constraint)), this, SLOT(update()) ); debugPlan <constraintModel(); connect( m_gantt->treeView(), &TreeViewBase::contextMenuRequested, this, &GanttView::slotContextMenuRequested ); connect( m_gantt->treeView(), &TreeViewBase::headerContextMenuRequested, this, &ViewBase::slotHeaderContextMenuRequested ); Help::add(this, xi18nc("@info:whatsthis", "Gantt View" "" "Displays scheduled tasks in a Gantt diagram." " The chart area can be zoomed in and out with a slider" " positioned in the upper left corner of the time scale." " You need to hoover over it with the mouse for it to show." "" "This view supports configuration and printing using the context menu of the tree view." "More..." "", Help::page("Manual/Task_Gantt_View"))); } KoPrintJob *GanttView::createPrintJob() { return new GanttPrintingDialog( this, m_gantt ); } void GanttView::setZoom( double ) { //debugPlan <<"setting gantt zoom:" << zoom; //m_gantt->setZoomFactor(zoom,true); NO!!! setZoomFactor() is something else } void GanttView::setupGui() { // create context menu actions actionShowProject = new KToggleAction( i18n( "Show Project" ), this ); // FIXME: Dependencies depend on these methods being called in the correct order connect(actionShowProject, &QAction::triggered, m_gantt, &MyKGanttView::clearDependencies); connect(actionShowProject, &QAction::triggered, m_gantt->model(), &NodeItemModel::setShowProject); connect(actionShowProject, &QAction::triggered, m_gantt, &MyKGanttView::createDependencies); addContextAction( actionShowProject ); createOptionActions(ViewBase::OptionAll); } void GanttView::slotOptions() { debugPlan; GanttViewSettingsDialog *dlg = new GanttViewSettingsDialog( m_gantt, m_gantt->delegate(), this, sender()->objectName() == "print options" ); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void GanttView::slotOptionsFinished( int result ) { GanttViewSettingsDialog *dlg = qobject_cast( sender() ); if ( dlg && result == QDialog::Accepted ) { m_gantt->graphicsView()->updateScene(); } ViewBase::slotOptionsFinished( result ); } void GanttView::clear() { // m_gantt->clear(); } void GanttView::setShowResources( bool on ) { m_gantt->delegate()->showResources = on; } void GanttView::setShowTaskName( bool on ) { m_gantt->delegate()->showTaskName = on; } void GanttView::setShowProgress( bool on ) { m_gantt->delegate()->showProgress = on; } void GanttView::setShowPositiveFloat( bool on ) { m_gantt->delegate()->showPositiveFloat = on; } void GanttView::setShowCriticalTasks( bool on ) { m_gantt->delegate()->showCriticalTasks = on; } void GanttView::setShowCriticalPath( bool on ) { m_gantt->delegate()->showCriticalPath = on; } void GanttView::setShowNoInformation( bool on ) { m_gantt->delegate()->showNoInformation = on; } void GanttView::setShowAppointments( bool on ) { m_gantt->delegate()->showAppointments = on; } void GanttView::setShowTaskLinks( bool on ) { m_gantt->delegate()->showTaskLinks = on; } void GanttView::setProject( Project *project ) { m_gantt->setProject( project ); } void GanttView::setScheduleManager( ScheduleManager *sm ) { if (!sm && scheduleManager()) { // we should only get here if the only schedule manager is scheduled, // or when last schedule manager is deleted m_domdoc.clear(); QDomElement element = m_domdoc.createElement("expanded"); m_domdoc.appendChild(element); m_gantt->treeView()->saveExpanded(element); } bool tryexpand = sm && !scheduleManager(); bool expand = sm && scheduleManager() && sm != scheduleManager(); QDomDocument doc; if (expand) { QDomElement element = doc.createElement("expanded"); doc.appendChild(element); m_gantt->treeView()->saveExpanded(element); } ViewBase::setScheduleManager(sm); m_gantt->setScheduleManager( sm ); if (expand) { m_gantt->treeView()->doExpand(doc); } else if (tryexpand) { m_gantt->treeView()->doExpand(m_domdoc); } } void GanttView::draw( Project &project ) { setProject( &project ); } void GanttView::drawChanges( Project &project ) { if ( m_project != &project ) { setProject( &project ); } } Node *GanttView::currentNode() const { QModelIndex idx = m_gantt->treeView()->selectionModel()->currentIndex(); return m_gantt->model()->node( m_gantt->sfModel()->mapToSource( idx ) ); } void GanttView::slotContextMenuRequested( const QModelIndex &idx, const QPoint &pos ) { debugPlan; QString name; Node *node = m_gantt->model()->node( m_gantt->sfModel()->mapToSource( idx ) ); if ( node ) { switch ( node->type() ) { case Node::Type_Task: name = "taskview_popup"; break; case Node::Type_Milestone: name = "taskview_milestone_popup"; break; case Node::Type_Summarytask: name = "taskview_summary_popup"; break; default: break; } } else debugPlan<<"No node"; m_gantt->treeView()->setContextMenuIndex(idx); if ( name.isEmpty() ) { slotHeaderContextMenuRequested( pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); debugPlan<<"No menu"; return; } emit requestPopupMenu( name, pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); } bool GanttView::loadContext( const KoXmlElement &settings ) { debugPlan; ViewBase::loadContext( settings ); bool show = (bool)(settings.attribute( "show-project", "0" ).toInt() ); actionShowProject->setChecked( show ); m_gantt->model()->setShowProject( show ); // why is this not called by the action? return m_gantt->loadContext( settings ); } void GanttView::saveContext( QDomElement &settings ) const { debugPlan; ViewBase::saveContext( settings ); settings.setAttribute( "show-project", QString::number(actionShowProject->isChecked()) ); m_gantt->saveContext( settings ); } void GanttView::updateReadWrite( bool on ) { // TODO: KGanttView needs read/write mode m_readWrite = on; } //---- MilestoneGanttViewSettingsDialog::MilestoneGanttViewSettingsDialog( GanttViewBase *gantt, ViewBase *view, bool selectPrint ) : ItemViewSettupDialog( view, gantt->treeView(), true, view ), m_gantt( gantt ) { QTabWidget *tab = new QTabWidget(); QWidget *w = ViewBase::createPageLayoutWidget( view ); tab->addTab( w, w->windowTitle() ); m_pagelayout = w->findChild(); Q_ASSERT( m_pagelayout ); m_printingoptions = new GanttPrintingOptionsWidget( this ); m_printingoptions->setOptions( gantt->printingOptions() ); tab->addTab( m_printingoptions, m_printingoptions->windowTitle() ); KPageWidgetItem *page = insertWidget( -1, tab, i18n( "Printing" ), i18n( "Printing Options" ) ); if (selectPrint) { setCurrentPage(page); } connect( this, SIGNAL(accepted()), this, SLOT(slotOk()) ); } void MilestoneGanttViewSettingsDialog::slotOk() { debugPlan; m_gantt->setPrintingOptions( m_printingoptions->options()); ItemViewSettupDialog::slotOk(); } //------------------------ MilestoneKGanttView::MilestoneKGanttView( QWidget *parent ) : NodeGanttViewBase( parent ), m_manager( 0 ) { debugPlan<<"------------------- create MilestoneKGanttView -----------------------"; MilestoneItemModel *mm = new MilestoneItemModel( this ); setItemModel( mm ); treeView()->createItemDelegates( mm ); sfModel()->setFilterRole ( Qt::EditRole ); sfModel()->setFilterFixedString( QString::number( Node::Type_Milestone ) ); sfModel()->setFilterKeyColumn( NodeModel::NodeType ); QList show; show << NodeModel::NodeWBSCode << NodeModel::NodeName << NodeModel::NodeStartTime; treeView()->setDefaultColumns( show ); for ( int i = 0; i < model()->columnCount(); ++i ) { if ( ! show.contains( i ) ) { treeView()->hideColumn( i ); } } treeView()->header()->moveSection(NodeModel::NodeWBSCode, show.indexOf(NodeModel::NodeWBSCode)); treeView()->setRootIsDecorated ( false ); KGantt::ProxyModel *m = static_cast( ganttProxyModel() ); m->setRole( KGantt::ItemTypeRole, KGantt::ItemTypeRole ); // To provide correct format m->setRole( KGantt::StartTimeRole, Qt::EditRole ); // To provide correct format m->setRole( KGantt::EndTimeRole, Qt::EditRole ); // To provide correct format m->removeColumn( Qt::DisplayRole ); m->setColumn( KGantt::ItemTypeRole, NodeModel::NodeType ); m->setColumn( KGantt::StartTimeRole, NodeModel::NodeStartTime ); m->setColumn( KGantt::EndTimeRole, NodeModel::NodeEndTime ); m->setColumn( KGantt::TaskCompletionRole, NodeModel::NodeCompleted ); KGantt::DateTimeGrid *g = static_cast( grid() ); g->setDayWidth( 30 ); // TODO: extend QLocale/KGantt to support formats for hourly time display // see bug #349030 // removed custom code here // TODO: add to context treeView()->sortByColumn(NodeModel::NodeWBSCode, Qt::AscendingOrder); treeView()->setSortingEnabled(true); Help::add(this, xi18nc("@info:whatsthis", "Milestone Gantt View" "" "Displays scheduled milestones in a Gantt diagram." " The chart area can be zoomed in and out with a slider" " positioned in the upper left corner of the time scale." " You need to hoover over it with the mouse for it to show." "" "This view supports configuration and printing using the context menu." "More..." "", Help::page("Manual/Milestone_Gantt_View"))); } MilestoneItemModel *MilestoneKGanttView::model() const { return static_cast( NodeGanttViewBase::model() ); } void MilestoneKGanttView::setProject( Project *proj ) { if ( project() ) { disconnect( project(), &Project::projectCalculated, this, &MilestoneKGanttView::slotProjectCalculated ); } NodeGanttViewBase::setProject( proj ); if ( proj ) { connect( proj, &Project::projectCalculated, this, &MilestoneKGanttView::slotProjectCalculated ); } } void MilestoneKGanttView::slotProjectCalculated( ScheduleManager *sm ) { if ( m_manager == sm ) { setScheduleManager( sm ); } } void MilestoneKGanttView::setScheduleManager( ScheduleManager *sm ) { //debugPlan<setScheduleManager( 0 ); m_manager = sm; KGantt::DateTimeGrid *g = static_cast( grid() ); if ( sm && m_project ) { QDateTime start; foreach ( const Node *n, model()->mileStones() ) { QDateTime nt = n->startTime( sm->scheduleId() ); if ( ! nt.isValid() ) { continue; } if ( ! start.isValid() || start > nt ) { start = nt; debugPlan<name()<startTime( sm->scheduleId() ); } if ( g->startDateTime() != start ) { g->setStartDateTime( start ); } } if ( ! g->startDateTime().isValid() ) { g->setStartDateTime( QDateTime::currentDateTime() ); } model()->setScheduleManager( sm ); } //------------------------------------------ MilestoneGanttView::MilestoneGanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite) : ViewBase(part, doc, parent), m_readWrite( readWrite ), m_project( 0 ) { debugPlan <<" ---------------- Plan: Creating Milesone GanttView ----------------"; QVBoxLayout *l = new QVBoxLayout( this ); l->setMargin( 0 ); m_splitter = new QSplitter( this ); l->addWidget( m_splitter ); m_splitter->setOrientation( Qt::Vertical ); setupGui(); m_gantt = new MilestoneKGanttView( m_splitter ); m_showTaskName = false; // FIXME m_showProgress = false; //FIXME m_showPositiveFloat = false; //FIXME m_showCriticalTasks = false; //FIXME m_showNoInformation = false; //FIXME updateReadWrite( readWrite ); connect( m_gantt->treeView(), &TreeViewBase::contextMenuRequested, this, &MilestoneGanttView::slotContextMenuRequested ); connect( m_gantt->treeView(), &TreeViewBase::headerContextMenuRequested, this, &ViewBase::slotHeaderContextMenuRequested ); } void MilestoneGanttView::setZoom( double ) { //debugPlan <<"setting gantt zoom:" << zoom; //m_gantt->setZoomFactor(zoom,true); NO!!! setZoomFactor() is something else } void MilestoneGanttView::show() { } void MilestoneGanttView::clear() { } void MilestoneGanttView::setProject( Project *project ) { m_gantt->setProject( project ); } void MilestoneGanttView::setScheduleManager( ScheduleManager *sm ) { //debugPlan<setScheduleManager( sm ); } void MilestoneGanttView::draw( Project &project ) { setProject( &project ); } void MilestoneGanttView::drawChanges( Project &project ) { if ( m_project != &project ) { setProject( &project ); } } Node *MilestoneGanttView::currentNode() const { QModelIndex idx = m_gantt->treeView()->selectionModel()->currentIndex(); return m_gantt->model()->node( m_gantt->sfModel()->mapToSource( idx ) ); } void MilestoneGanttView::setupGui() { createOptionActions(ViewBase::OptionAll); } void MilestoneGanttView::slotContextMenuRequested( const QModelIndex &idx, const QPoint &pos ) { debugPlan; QString name; Node *node = m_gantt->model()->node( m_gantt->sfModel()->mapToSource( idx ) ); if ( node ) { switch ( node->type() ) { case Node::Type_Task: name = "taskview_popup"; break; case Node::Type_Milestone: name = "taskview_milestone_popup"; break; case Node::Type_Summarytask: name = "taskview_summary_popup"; break; default: break; } } else debugPlan<<"No node"; m_gantt->treeView()->setContextMenuIndex(idx); if ( name.isEmpty() ) { debugPlan<<"No menu"; slotHeaderContextMenuRequested( pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); return; } emit requestPopupMenu( name, pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); } void MilestoneGanttView::slotOptions() { debugPlan; MilestoneGanttViewSettingsDialog *dlg = new MilestoneGanttViewSettingsDialog( m_gantt, this, sender()->objectName() == "print options" ); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } bool MilestoneGanttView::loadContext( const KoXmlElement &settings ) { debugPlan; ViewBase::loadContext( settings ); return m_gantt->loadContext( settings ); } void MilestoneGanttView::saveContext( QDomElement &settings ) const { debugPlan; ViewBase::saveContext( settings ); return m_gantt->saveContext( settings ); } void MilestoneGanttView::updateReadWrite( bool on ) { m_readWrite = on; } KoPrintJob *MilestoneGanttView::createPrintJob() { return new GanttPrintingDialog( this, m_gantt ); } //-------------------- ResourceAppointmentsGanttViewSettingsDialog::ResourceAppointmentsGanttViewSettingsDialog( GanttViewBase *gantt, ViewBase *view, bool selectPrint ) : ItemViewSettupDialog( view, gantt->treeView(), true, view ) , m_gantt(gantt) { QTabWidget *tab = new QTabWidget(); QWidget *w = ViewBase::createPageLayoutWidget( view ); tab->addTab( w, w->windowTitle() ); m_pagelayout = w->findChild(); Q_ASSERT( m_pagelayout ); m_printingoptions = new GanttPrintingOptionsWidget( this ); m_printingoptions->setOptions( gantt->printingOptions() ); tab->addTab( m_printingoptions, m_printingoptions->windowTitle() ); KPageWidgetItem *page = insertWidget( -1, tab, i18n( "Printing" ), i18n( "Printing Options" ) ); if (selectPrint) { setCurrentPage(page); } connect( this, SIGNAL(accepted()), this, SLOT(slotOk()) ); } void ResourceAppointmentsGanttViewSettingsDialog::slotOk() { debugPlan; m_gantt->setPrintingOptions( m_printingoptions->options()); ItemViewSettupDialog::slotOk(); } //------------------------------------------ ResourceAppointmentsGanttView::ResourceAppointmentsGanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite) : ViewBase(part, doc, parent), m_project( 0 ), m_model( new ResourceAppointmentsGanttModel( this ) ) { debugPlan <<" ---------------- KPlato: Creating ResourceAppointmentsGanttView ----------------"; m_gantt = new GanttViewBase( this ); m_gantt->graphicsView()->setItemDelegate( new ResourceGanttItemDelegate( m_gantt ) ); GanttTreeView *tv = new GanttTreeView( m_gantt ); tv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); tv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); tv->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); // needed since qt 4.2 m_gantt->setLeftView( tv ); connect(this, &ViewBase::expandAll, tv, &TreeViewBase::slotExpand); connect(this, &ViewBase::collapseAll, tv, &TreeViewBase::slotCollapse); m_rowController = new KGantt::TreeViewRowController( tv, m_gantt->ganttProxyModel() ); m_gantt->setRowController( m_rowController ); tv->header()->setStretchLastSection( true ); tv->setTreePosition(-1); KGantt::ProxyModel *m = static_cast( m_gantt->ganttProxyModel() ); m->setRole( KGantt::ItemTypeRole, KGantt::ItemTypeRole ); m->setRole( KGantt::StartTimeRole, KGantt::StartTimeRole ); m->setRole( KGantt::EndTimeRole, KGantt::EndTimeRole ); m->setRole( KGantt::TaskCompletionRole, KGantt::TaskCompletionRole ); m_gantt->setModel( m_model ); QVBoxLayout *l = new QVBoxLayout( this ); l->setMargin( 0 ); l->addWidget( m_gantt ); setupGui(); updateReadWrite( readWrite ); connect( m_gantt->leftView(), SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( m_gantt->leftView(), SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); Help::add(this, xi18nc("@info:whatsthis", "Resource Assignments (Gantt)" "" "Displays the scheduled resource - task assignments in a Gantt diagram." " The chart area can be zoomed in and out with a slider" " positioned in the upper left corner of the time scale." " You need to hoover over it with the mouse for it to show." "" "This view supports configuration and printing using the context menu." "More..." "", Help::page("Manual/Resource_Assignment_Gantt_View"))); } ResourceAppointmentsGanttView::~ResourceAppointmentsGanttView() { delete m_rowController; } void ResourceAppointmentsGanttView::setZoom( double ) { //debugPlan <<"setting gantt zoom:" << zoom; //m_gantt->setZoomFactor(zoom,true); NO!!! setZoomFactor() is something else } Project *ResourceAppointmentsGanttView::project() const { return m_model->project(); } void ResourceAppointmentsGanttView::setProject( Project *project ) { m_model->setProject( project ); } void ResourceAppointmentsGanttView::setScheduleManager( ScheduleManager *sm ) { //debugPlan<saveExpanded(element); } bool tryexpand = sm && !scheduleManager(); bool expand = sm && scheduleManager() && sm != scheduleManager(); QDomDocument doc; if (expand) { QDomElement element = doc.createElement("expanded"); doc.appendChild(element); treeView()->saveExpanded(element); } ViewBase::setScheduleManager(sm); m_model->setScheduleManager( sm ); if (expand) { treeView()->doExpand(doc); } else if (tryexpand) { treeView()->doExpand(m_domdoc); } } void ResourceAppointmentsGanttView::setupGui() { createOptionActions(ViewBase::OptionAll); } Node *ResourceAppointmentsGanttView::currentNode() const { QModelIndex idx = treeView()->selectionModel()->currentIndex(); return m_model->node( idx ); } void ResourceAppointmentsGanttView::slotContextMenuRequested( const QModelIndex &idx, const QPoint &pos ) { debugPlan<node( idx ); if ( n ) { name = "taskview_popup"; } } m_gantt->treeView()->setContextMenuIndex(idx); if ( name.isEmpty() ) { slotHeaderContextMenuRequested( pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); return; } emit requestPopupMenu( name, pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); } void ResourceAppointmentsGanttView::slotOptions() { debugPlan; ItemViewSettupDialog *dlg = new ResourceAppointmentsGanttViewSettingsDialog(m_gantt, this, sender()->objectName() == "print options"); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } bool ResourceAppointmentsGanttView::loadContext( const KoXmlElement &settings ) { debugPlan; ViewBase::loadContext( settings ); m_gantt->loadContext( settings ); return treeView()->loadContext( m_model->columnMap(), settings ); } void ResourceAppointmentsGanttView::saveContext( QDomElement &settings ) const { debugPlan; ViewBase::saveContext( settings ); m_gantt->saveContext( settings ); treeView()->saveContext( m_model->columnMap(), settings ); } void ResourceAppointmentsGanttView::updateReadWrite( bool on ) { m_readWrite = on; } KoPrintJob *ResourceAppointmentsGanttView::createPrintJob() { return new GanttPrintingDialog( this, m_gantt ); } } //KPlato namespace #include "moc_kptganttview.cpp"