Qt kdChart 甘特图案例

KDChart  甘特图在Qt中的加载使用案例,代码来自官方

mainwindow.h

/****************************************************************************
** Copyright (C) 2001-2018 Klaralvdalens Datakonsult AB.  All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QItemSelection>
#include <QMainWindow>

QT_BEGIN_NAMESPACE
class QStandardItemModel;
class QCloseEvent;
namespace Ui {
    class MainWindow;
}
QT_END_NAMESPACE

namespace KDGantt {
    class ConstraintModel;
    class DateTimeGrid;
    class Legend;
}

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    explicit MainWindow( QWidget * parent = 0, Qt::WindowFlags flags = 0 );
    virtual ~MainWindow();
    virtual void closeEvent(QCloseEvent *event);

private slots:
    void addNewEntry();
    void removeEntry();
    void showContextMenu( const QPoint& );
    void enableActions( const QItemSelection& selected );
    void zoomIn();
    void zoomOut();
    void zoomFit();
    void scaleAuto();
    void scaleHour();
    void scaleDay();
    void scaleWeek();
    void scaleMonth();

private:
    void initModel();
    void initActions();
    void initItemDelegate();
    void initGrid();

    void setReadOnly( const QModelIndex& index, bool readOnly );
    void addConstraint( const QModelIndex& index1, const QModelIndex& index2 );

    QStandardItemModel* model;
    KDGantt::ConstraintModel* constraintModel;
    KDGantt::DateTimeGrid* grid;
    KDGantt::Legend* smallLegend;
    KDGantt::Legend* detailedLegend;

    QAction* newEntryAction;
    QAction* removeEntryAction;
    QAction* zoomInAction;
    QAction* zoomOutAction;
    QAction* zoomFitAction;

    Ui::MainWindow* ui;
};

#endif /* MAINWINDOW_H */

entrydialog.h

/****************************************************************************
** Copyright (C) 2001-2018 Klaralvdalens Datakonsult AB.  All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/

#ifndef ENTRYDIALOG_H
#define ENTRYDIALOG_H

#include <QDateTime>
#include <QDialog>
#include <QModelIndex>

QT_BEGIN_NAMESPACE
class QAbstractItemModel;
namespace Ui {
    class EntryDialog;
}
QT_END_NAMESPACE

namespace KDGantt {
    class ConstraintModel;
}

class EntryDialog : public QDialog {
    Q_OBJECT

public:
    explicit EntryDialog( const QAbstractItemModel* model, QWidget* parent = 0, Qt::WindowFlags f = 0 );
    void initFrom( const QModelIndex& index, const KDGantt::ConstraintModel* constraintModel );
    
    QString name() const;
    int type() const;
    QDateTime startDate() const;
    QDateTime endDate() const;
    int completion() const;
    bool readOnly() const;
    QModelIndex depends() const;
    QString legend() const;

private slots:
    void updateEndDate( const QDateTime& startDate );
    void disableEditing( bool disable );
    void typeChanged( int index );
    
private:
    void init();
    void addDependItem( const QAbstractItemModel* model, const QModelIndex& index, int indent = 0 );
    
    QList<QPersistentModelIndex> indexList;
    const QAbstractItemModel* model;
    Ui::EntryDialog* ui;
};

#endif /* ENTRYDIALOG_H */

entrydelegate.h

/****************************************************************************
** Copyright (C) 2001-2018 Klaralvdalens Datakonsult AB.  All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/

#ifndef ENTRYDELEGATE_H
#define ENTRYDELEGATE_H

#include <QItemDelegate>

namespace KDGantt {
    class ConstraintModel;
}

class EntryDelegate : public QItemDelegate {
public:
    explicit EntryDelegate( KDGantt::ConstraintModel* constraintModel, QObject* parent = 0 );
    
    bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
    
private:
    void addConstraint(const QModelIndex & index1, const QModelIndex & index2);
    void setReadOnly(const QModelIndex & index, bool readOnly);
    
    KDGantt::ConstraintModel* constraintModel;
};

#endif /* ENTRYDELEGATE_H */

entrydelegate.cpp
/****************************************************************************
** Copyright (C) 2001-2018 Klaralvdalens Datakonsult AB.  All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/

#include "entrydelegate.h"

#include "entrydialog.h"

#include <KDGanttConstraintModel>
#include <KDGanttGlobal>
#include <QEvent>
#include <QModelIndex>
#include <QStandardItemModel>
#include <QPointer>

EntryDelegate::EntryDelegate( KDGantt::ConstraintModel* constraintModel, QObject* parent )
    : QItemDelegate( parent )
{
    this->constraintModel = constraintModel;
}

bool EntryDelegate::editorEvent( QEvent* event, QAbstractItemModel *model, const QStyleOptionViewItem& option, const QModelIndex& index )
{
    if ( event->type() != QEvent::MouseButtonDblClick )
        return false;

    if ( !index.isValid() )
        return QItemDelegate::editorEvent( event, model, option, index );

    QPointer<EntryDialog> dialog = new EntryDialog( model );
    dialog->initFrom( index, constraintModel );
    dialog->setWindowTitle( tr( "Edit Entry" ) );
    dialog->exec();  
    if ( !dialog )
        return false;
    
    int row = index.row();
    const QModelIndex parent = index.parent();
    model->setData( model->index( row, 0, parent ), dialog->name() );
    model->setData( model->index( row, 1, parent ), dialog->type() );
    if ( dialog->type() != KDGantt::TypeSummary ) {
        model->setData( model->index( row, 2, parent ), dialog->startDate(), KDGantt::StartTimeRole );
        model->setData( model->index( row, 3, parent ), dialog->endDate(), KDGantt::EndTimeRole );
    }
    model->setData( model->index( row, 4, parent ), dialog->completion() );
    model->setData( model->index( row, 5, parent ), dialog->legend() );
    
    addConstraint( dialog->depends(), model->index( row, 0, parent ) );
    setReadOnly( model->index( row, 0, parent ), dialog->readOnly() );

    delete dialog;
    return true;
}

void EntryDelegate::setReadOnly(const QModelIndex & index, bool readOnly)
{
    int row = index.row();
    QModelIndex parent = index.parent();
    QStandardItem* item;
    const QStandardItemModel* model = qobject_cast<const QStandardItemModel*>( index.model() );
    if ( !model )
        return;
    
    item = model->itemFromIndex( model->index( row, 0, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );
    
    item = model->itemFromIndex( model->index( row, 1, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );
    
    item = model->itemFromIndex( model->index( row, 2, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );
    
    item = model->itemFromIndex( model->index( row, 3, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );
    
    item = model->itemFromIndex( model->index( row, 4, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );
}

void EntryDelegate::addConstraint(const QModelIndex & index1, const QModelIndex & index2)
{
    if ( !index1.isValid() || !index2.isValid() )
        return;

    KDGantt::Constraint c( index1, index2 );
    constraintModel->addConstraint( c );
}
entrydialog.cpp
/****************************************************************************
** Copyright (C) 2001-2018 Klaralvdalens Datakonsult AB.  All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/

#include "entrydialog.h"

#include "ui_entrydialog.h"

#include <KDGanttConstraintModel>
#include <KDGanttGlobal>
#include <QAbstractItemModel>
#include <QDateTime>
#include <QPersistentModelIndex>

Q_DECLARE_METATYPE( QPersistentModelIndex );

EntryDialog::EntryDialog( const QAbstractItemModel* model, QWidget* parent, Qt::WindowFlags f )
    : QDialog( parent, f ),
      indexList( QList<QPersistentModelIndex>() ),
      ui( new Ui::EntryDialog )
{
    ui->setupUi( this );
    this->model = model;
    init();
}

void EntryDialog::init()
{
    ui->type->addItem( tr( "Event" ), KDGantt::TypeEvent );
    ui->type->addItem( tr( "Task" ), KDGantt::TypeTask );
    ui->type->addItem( tr( "Summary" ), KDGantt::TypeSummary );
    ui->type->addItem( tr( "Multi" ), KDGantt::TypeMulti );
    
    for (int row = 0; row < model->rowCount(); ++row )
        addDependItem( model, model->index( row, 0 ) );
    
    connect( ui->startDate, SIGNAL( dateTimeChanged( const QDateTime& ) ), this, SLOT( updateEndDate( const QDateTime& ) ) );
    connect( ui->readOnly, SIGNAL( toggled( bool ) ), this, SLOT( disableEditing( bool ) ) );
    connect( ui->type, SIGNAL( currentIndexChanged( int ) ), this, SLOT( typeChanged( int ) ) );
    
    ui->startDate->setDateTime( QDateTime::currentDateTime() );
    typeChanged( 0 );
}

void EntryDialog::initFrom( const QModelIndex & index, const KDGantt::ConstraintModel* constraintModel )
{
    int row = index.row();
    const QModelIndex parent = index.parent();
    
    ui->name->setText( model->data( model->index( row, 0, parent ) ).toString() );
    ui->legend->setText( model->data( model->index( row, 5, parent ) ).toString() );
    int idx = ui->type->findData( model->data( model->index( row, 1, parent ) ).toInt() );
    ui->type->setCurrentIndex( idx );
    ui->startDate->setDateTime( model->data( model->index( row, 2, parent ), KDGantt::StartTimeRole ).toDateTime() );
    ui->endDate->setDateTime( model->data( model->index( row, 3, parent ), KDGantt::EndTimeRole ).toDateTime() );
    ui->completion->setValue( model->data( model->index( row, 4, parent ) ).toInt() );
    ui->readOnly->setChecked( !(model->flags( model->index( row, 0, parent ) ) & Qt::ItemIsEditable) );
    
    QList<KDGantt::Constraint> constraints = constraintModel->constraintsForIndex( model->index( row, 0, parent ) );
    if ( constraints.isEmpty() )
        return;
    
    QModelIndex constraintIndex;
    for ( int i = 0; i < constraints.size(); ++i ) {
        KDGantt::Constraint constraint = constraints[i];
        if ( constraint.endIndex() == index ) {
            constraintIndex = constraint.startIndex();
            break;
        }
    }
    
    if ( !constraintIndex.isValid() )
        return;
    
    ui->depends->setCurrentIndex( indexList.indexOf( constraintIndex ) + 1 );
}

void EntryDialog::addDependItem( const QAbstractItemModel* model, const QModelIndex & index, int indent)
{
    indexList << QPersistentModelIndex( index );
    QString str = QString( "%1%2" ).arg( QString().fill( ' ', indent ) ).arg( model->data( index ).toString() );
    ui->depends->addItem( str );
    
    for (int row = 0; row < model->rowCount( index ); ++row )
        addDependItem( model, model->index( row, 0, index ), indent + 2 );
}

QString EntryDialog::name() const
{
    return ui->name->text();
}

int EntryDialog::type() const
{
    return ui->type->itemData( ui->type->currentIndex() ).toInt();
}

QDateTime EntryDialog::startDate() const
{
    return ui->startDate->dateTime();
}

QDateTime EntryDialog::endDate() const
{
    return ui->endDate->dateTime();
}

int EntryDialog::completion() const
{
    return ui->completion->value();
}

void EntryDialog::updateEndDate(const QDateTime & startDate)
{
    ui->endDate->setMinimumDate( startDate.date() );
    ui->endDate->setMinimumTime( startDate.time() );
}

bool EntryDialog::readOnly() const
{
    return ui->readOnly->isChecked();
}

QModelIndex EntryDialog::depends() const
{
    if ( ui->depends->currentIndex() == 0 )
        return QModelIndex();

    QPersistentModelIndex index = indexList[ ui->depends->currentIndex() - 1 ];
    if ( index.isValid() )
        return index;
    
    return QModelIndex();
}

QString EntryDialog::legend() const
{
    return ui->legend->text();
}

void EntryDialog::disableEditing(bool disable)
{
    ui->name->setEnabled( !disable );
    ui->type->setEnabled( !disable );
    ui->completion->setEnabled( !disable );
    ui->startDate->setEnabled( !disable );
    ui->endDate->setEnabled( !disable );
    ui->depends->setEnabled( !disable );
}

void EntryDialog::typeChanged(int index)
{
    if ( ! index ) {
        ui->label_EndDate->hide();
        ui->endDate->hide();
    } else {
        ui->label_EndDate->show();
        ui->endDate->show();
    }
}

mainwindow.cpp
/****************************************************************************
** Copyright (C) 2001-2018 Klaralvdalens Datakonsult AB.  All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/

#include "mainwindow.h"

#include "ui_mainwindow.h"
#include "entrydelegate.h"
#include "entrydialog.h"

#include <algorithm>

#include <KDGanttConstraintModel>
#include <KDGanttDateTimeGrid>
#include <KDGanttGraphicsView>
#include <KDGanttLegend>
#include <QAbstractItemView>
#include <QDebug>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QTreeView>
#include <QCloseEvent>
#include <QPointer>
#include <QScrollBar>

class MyStandardItem : public QStandardItem {
public:
  MyStandardItem( const QVariant& v ) : QStandardItem()
  {
    setData( v, Qt::DisplayRole );
  }
  MyStandardItem( const QString& v ) : QStandardItem()
  {
    setData( v, Qt::DisplayRole );
  }
};

MainWindow::MainWindow( QWidget* parent, Qt::WindowFlags flags )
    : QMainWindow( parent, flags ),
      smallLegend( 0 ),
      detailedLegend( 0 ),
      ui( new Ui::MainWindow )
{
    ui->setupUi( this );

    initModel();
    initActions();
    initItemDelegate();
    initGrid();

    QTreeView* leftView = qobject_cast<QTreeView*>( ui->ganttView->leftView() );
    Q_ASSERT( leftView );
    leftView->setColumnHidden( 1, true );
    leftView->setColumnHidden( 2, true );
    leftView->setColumnHidden( 3, true );
    leftView->setColumnHidden( 4, true );
    leftView->setColumnHidden( 5, true );
    leftView->header()->setStretchLastSection( true );

    connect( ui->ganttView->leftView(), SIGNAL( customContextMenuRequested( const QPoint& ) ),
             this, SLOT( showContextMenu( const QPoint& ) ) );
    connect( ui->ganttView->selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
             this, SLOT( enableActions( const QItemSelection& ) ) );
}

MainWindow::~MainWindow()
{
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    delete smallLegend;
    delete detailedLegend;
    event->accept();
}

void MainWindow::initModel()
{
    model = new QStandardItemModel( 0, 6, this );
    model->setHeaderData( 0, Qt::Horizontal, tr( "Tree View of Entries" ) );
    ui->ganttView->setModel( model );

    QStandardItemModel* lmodel = new QStandardItemModel;
    lmodel->appendRow( QList<QStandardItem*>()
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( KDGantt::TypeEvent )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QString::fromLatin1("Event") ) );
    lmodel->appendRow( QList<QStandardItem*>()
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( KDGantt::TypeTask )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QString::fromLatin1("Task") ) );
    lmodel->appendRow( QList<QStandardItem*>()
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( KDGantt::TypeSummary )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QVariant() )
        << new MyStandardItem( QString::fromLatin1("Summary") ) );

    smallLegend = new KDGantt::Legend();
    smallLegend->setWindowTitle( tr( "Legend" ) );
    smallLegend->show();
    smallLegend->setModel( lmodel );

    detailedLegend = new KDGantt::Legend();
    detailedLegend->setWindowTitle( tr( "List" ) );
    detailedLegend->show();
    detailedLegend->setModel( model );

    constraintModel = new KDGantt::ConstraintModel( this );
    ui->ganttView->setConstraintModel( constraintModel );
}

void MainWindow::initActions()
{
    newEntryAction = new QAction( tr( "New entry" ), this );
    newEntryAction->setShortcut( QKeySequence::New );
    connect( newEntryAction, SIGNAL( triggered() ), this, SLOT( addNewEntry() ) );

    removeEntryAction = new QAction( tr( "Remove entry" ), this );
    removeEntryAction->setShortcut( QKeySequence::Delete );
    connect( removeEntryAction, SIGNAL( triggered() ), this, SLOT( removeEntry() ) );

    zoomInAction = new QAction( tr( "Zoom In" ), this );
    zoomInAction->setShortcut( QKeySequence::ZoomIn );
    connect( zoomInAction, SIGNAL( triggered() ), this, SLOT( zoomIn() ) );

    zoomOutAction = new QAction( tr( "Zoom Out" ), this );
    zoomOutAction->setShortcut( QKeySequence::ZoomOut );
    connect( zoomOutAction, SIGNAL( triggered() ), this, SLOT( zoomOut() ) );

    zoomFitAction = new QAction( tr( "Zoom to Fit" ), this );
    connect( zoomFitAction, SIGNAL( triggered() ), this, SLOT( zoomFit() ) );

    ui->ganttView->leftView()->setContextMenuPolicy( Qt::CustomContextMenu );
    ui->ganttView->leftView()->addAction( newEntryAction );
    ui->ganttView->leftView()->addAction( removeEntryAction );

    QMenu* entryMenu = menuBar()->addMenu( tr( "Entry" ) );
    entryMenu->addAction( newEntryAction );
    entryMenu->addAction( removeEntryAction );

    QMenu* zoomMenu = menuBar()->addMenu( tr( "Zoom" ) );
    zoomMenu->addAction( zoomInAction );
    zoomMenu->addAction( zoomOutAction );
    zoomMenu->addAction( zoomFitAction );
    
    QMenu* scaleMenu = menuBar()->addMenu( tr( "Scale" ) );
    
    scaleMenu->addAction( tr( "Auto" ), this, SLOT(scaleAuto()) );
    scaleMenu->addAction( tr( "Hour" ), this, SLOT(scaleHour()) );
    scaleMenu->addAction( tr( "Day" ), this, SLOT(scaleDay()) );
    scaleMenu->addAction( tr( "Week" ), this, SLOT(scaleWeek()) );
    scaleMenu->addAction( tr( "Month" ), this, SLOT(scaleMonth()) );

    enableActions( QItemSelection() );
}

void MainWindow::initItemDelegate()
{
    EntryDelegate* delegate = new EntryDelegate( constraintModel, this );
    ui->ganttView->leftView()->setItemDelegate( delegate );
}

void MainWindow::initGrid()
{
    grid = new KDGantt::DateTimeGrid();
    grid->setDayWidth( 70 );
    ui->ganttView->setGrid( grid );
}

void MainWindow::showContextMenu( const QPoint& pos )
{
    if ( !ui->ganttView->leftView()->indexAt( pos ).isValid() )
        ui->ganttView->selectionModel()->clearSelection();

    QMenu menu( ui->ganttView->leftView() );
    menu.addAction( newEntryAction );
    menu.addAction( removeEntryAction );
    menu.exec( ui->ganttView->leftView()->viewport()->mapToGlobal( pos ) );
}

void MainWindow::enableActions(const QItemSelection & selected)
{
    if ( selected.indexes().isEmpty() ) {
        newEntryAction->setEnabled( true );
        removeEntryAction->setEnabled( false );
        return;
    }

    QModelIndex selectedIndex = selected.indexes()[0];

    if ( model->data( model->index( selectedIndex.row(), 1 ) ) == KDGantt::TypeEvent ||
        model->data( model->index( selectedIndex.row(), 1 ) ) == KDGantt::TypeTask ) {
        newEntryAction->setEnabled( false );
        removeEntryAction->setEnabled( true );
        return;
    }

    newEntryAction->setEnabled( true );
    removeEntryAction->setEnabled( true );
}

void MainWindow::addNewEntry()
{
    QPointer<EntryDialog> dialog = new EntryDialog( model );
    dialog->setWindowTitle( tr( "New Entry") );
    if ( dialog->exec() == QDialog::Rejected || !dialog ) {
        delete dialog;
        return;
    }

    QModelIndexList selectedIndexes = ui->ganttView->selectionModel()->selectedIndexes();
    const QModelIndex parent = selectedIndexes.value( 0 );

    if ( !model->insertRow( model->rowCount( parent ), parent ) )
        return;

    int row = model->rowCount( parent ) - 1;
    if ( row == 0 && parent.isValid() )
        model->insertColumns( model->columnCount( parent ), 5, parent );

    model->setData( model->index( row, 0, parent ), dialog->name() );
    model->setData( model->index( row, 1, parent ), dialog->type() );
    if ( dialog->type() != KDGantt::TypeSummary ) {
        model->setData( model->index( row, 2, parent ), dialog->startDate(), KDGantt::StartTimeRole );
        model->setData( model->index( row, 3, parent ), dialog->endDate(), KDGantt::EndTimeRole );
    }
    model->setData( model->index( row, 4, parent ), dialog->completion() );
    const QString legend( dialog->legend() );
    if ( ! legend.isEmpty() )
        model->setData( model->index( row, 5, parent ), legend );

    addConstraint( dialog->depends(), model->index( row, 0, parent ) );
    setReadOnly( model->index( row, 0, parent ), dialog->readOnly() );

    delete dialog;
}

void MainWindow::setReadOnly(const QModelIndex & index, bool readOnly)
{
    int row = index.row();
    const QModelIndex parent = index.parent();
    QStandardItem* item;

    item = model->itemFromIndex( model->index( row, 0, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );

    item = model->itemFromIndex( model->index( row, 1, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );

    item = model->itemFromIndex( model->index( row, 2, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );

    item = model->itemFromIndex( model->index( row, 3, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );

    item = model->itemFromIndex( model->index( row, 4, parent ) );
    item->setFlags( readOnly ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable );
}

void MainWindow::addConstraint(const QModelIndex & index1, const QModelIndex & index2)
{
    if ( !index1.isValid() || !index2.isValid() )
        return;

    KDGantt::Constraint c( index1, index2 );
    ui->ganttView->constraintModel()->addConstraint( c );
}

void MainWindow::removeEntry()
{
    QModelIndexList selectedIndexes = ui->ganttView->selectionModel()->selectedIndexes();
    QModelIndex index = selectedIndexes.value( 0 );

    if ( !index.isValid() )
        return;

    model->removeRow( index.row(), index.parent() );
}

void MainWindow::zoomIn()
{
    qreal dayWidth = grid->dayWidth() + 10;
    if ( dayWidth > 400 )
        grid->setScale( KDGantt::DateTimeGrid::ScaleHour );

    grid->setDayWidth( dayWidth );
}

void MainWindow::zoomOut()
{
    qreal dayWidth = grid->dayWidth() - 10;
    if ( dayWidth < 10 )
        dayWidth = 10;

    if ( dayWidth <= 400 )
        grid->setScale( KDGantt::DateTimeGrid::ScaleDay );

    grid->setDayWidth( dayWidth );
}

void MainWindow::zoomFit()
{
    QModelIndexList selectedIndexes = ui->ganttView->selectionModel()->selectedIndexes();

    if ( selectedIndexes.isEmpty() ) {
        return;
    }

    KDGantt::Span span;
    Q_FOREACH( QModelIndex idx, selectedIndexes ) {
        const KDGantt::Span s = grid->mapToChart( grid->model()->index( idx.row(), 0 ) );
        if ( span.isValid() ) {
            span = span.expandedTo( s );
        } else {
            span = s;
        }
    }

    span.setLength( span.length()+20 );
    span.setStart( span.start()-10 );

    qDebug() << selectedIndexes << span;

    const qreal view_width = ui->ganttView->graphicsView()->viewport()->width();
    const QDateTime start = grid->mapFromChart( span.start() ).value<QDateTime>();
    const QDateTime end = grid->mapFromChart( span.end() ).value<QDateTime>();

    qreal delta = start.date().daysTo(end.date());
    delta += start.time().msecsTo(end.time())/( 1000.*24.*60.*60. );

    qDebug() << view_width << "/" << delta;
    grid->setDayWidth( view_width/( std::max( (qreal)1., delta ) ) );
    qDebug() << "daywidth set to" << grid->dayWidth();
    qDebug() << "start scroll to" << grid->mapToChart( start );
    ui->ganttView->graphicsView()->horizontalScrollBar()->setValue( grid->mapToChart( start ) );
}

void MainWindow::scaleAuto()
{
    KDGantt::DateTimeGrid* grid = static_cast<KDGantt::DateTimeGrid*>(ui->ganttView->grid());
    grid->setScale( KDGantt::DateTimeGrid::ScaleAuto );
}

void MainWindow::scaleHour()
{
    KDGantt::DateTimeGrid* grid = static_cast<KDGantt::DateTimeGrid*>(ui->ganttView->grid());
    grid->setScale( KDGantt::DateTimeGrid::ScaleHour );
}

void MainWindow::scaleDay()
{
    KDGantt::DateTimeGrid* grid = static_cast<KDGantt::DateTimeGrid*>(ui->ganttView->grid());
    grid->setScale( KDGantt::DateTimeGrid::ScaleDay );
}

void MainWindow::scaleWeek()
{
    KDGantt::DateTimeGrid* grid = static_cast<KDGantt::DateTimeGrid*>(ui->ganttView->grid());
    grid->setScale( KDGantt::DateTimeGrid::ScaleWeek );
}

void MainWindow::scaleMonth()
{
    KDGantt::DateTimeGrid* grid = static_cast<KDGantt::DateTimeGrid*>(ui->ganttView->grid());
    grid->setScale( KDGantt::DateTimeGrid::ScaleMonth );
}
    

main.cpp

/****************************************************************************
** Copyright (C) 2001-2018 Klaralvdalens Datakonsult AB.  All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/

#include <QApplication>

#include "mainwindow.h"

int main( int argc, char* argv[] )
{
    QApplication app( argc, argv );
    
    MainWindow mainWin;
    mainWin.show();
    
    return app.exec();
}

ui_mainwindow.h

/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.12.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H

#include <KDGanttView>
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_MainWindow
{
public:
    QWidget *centralwidget;
    QVBoxLayout *vboxLayout;
    KDGantt::View *ganttView;
    QMenuBar *menubar;
    QStatusBar *statusbar;

    void setupUi(QMainWindow *MainWindow)
    {
        if (MainWindow->objectName().isEmpty())
            MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
        MainWindow->resize(556, 330);
        MainWindow->setContextMenuPolicy(Qt::DefaultContextMenu);
        centralwidget = new QWidget(MainWindow);
        centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
        vboxLayout = new QVBoxLayout(centralwidget);
        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
        ganttView = new KDGantt::View(centralwidget);
        ganttView->setObjectName(QString::fromUtf8("ganttView"));

        vboxLayout->addWidget(ganttView);

        MainWindow->setCentralWidget(centralwidget);
        menubar = new QMenuBar(MainWindow);
        menubar->setObjectName(QString::fromUtf8("menubar"));
        menubar->setGeometry(QRect(0, 0, 556, 29));
        MainWindow->setMenuBar(menubar);
        statusbar = new QStatusBar(MainWindow);
        statusbar->setObjectName(QString::fromUtf8("statusbar"));
        MainWindow->setStatusBar(statusbar);

        retranslateUi(MainWindow);

        QMetaObject::connectSlotsByName(MainWindow);
    } // setupUi

    void retranslateUi(QMainWindow *MainWindow)
    {
        MainWindow->setWindowTitle(QApplication::translate("MainWindow", "KD Gantt Example", nullptr));
    } // retranslateUi

};

namespace Ui {
    class MainWindow: public Ui_MainWindow {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_MAINWINDOW_H

ui_entrydialog.h

/********************************************************************************
** Form generated from reading UI file 'entrydialog.ui'
**
** Created by: Qt User Interface Compiler version 5.12.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef UI_ENTRYDIALOG_H
#define UI_ENTRYDIALOG_H

#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDateTimeEdit>
#include <QtWidgets/QDialog>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QVBoxLayout>

QT_BEGIN_NAMESPACE

class Ui_EntryDialog
{
public:
    QVBoxLayout *vboxLayout;
    QHBoxLayout *hboxLayout;
    QLabel *label;
    QLineEdit *name;
    QHBoxLayout *hboxLayout1;
    QLabel *label_6;
    QLineEdit *legend;
    QGridLayout *gridLayout;
    QLabel *label_2;
    QComboBox *type;
    QSpacerItem *spacerItem;
    QLabel *label_3;
    QDateTimeEdit *startDate;
    QLabel *label_5;
    QSpinBox *completion;
    QLabel *label_EndDate;
    QDateTimeEdit *endDate;
    QCheckBox *readOnly;
    QLabel *dependsLabel;
    QComboBox *depends;
    QDialogButtonBox *buttonBox;

    void setupUi(QDialog *EntryDialog)
    {
        if (EntryDialog->objectName().isEmpty())
            EntryDialog->setObjectName(QString::fromUtf8("EntryDialog"));
        EntryDialog->resize(439, 206);
        vboxLayout = new QVBoxLayout(EntryDialog);
        vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
        hboxLayout = new QHBoxLayout();
        hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
        label = new QLabel(EntryDialog);
        label->setObjectName(QString::fromUtf8("label"));

        hboxLayout->addWidget(label);

        name = new QLineEdit(EntryDialog);
        name->setObjectName(QString::fromUtf8("name"));

        hboxLayout->addWidget(name);


        vboxLayout->addLayout(hboxLayout);

        hboxLayout1 = new QHBoxLayout();
        hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
        label_6 = new QLabel(EntryDialog);
        label_6->setObjectName(QString::fromUtf8("label_6"));

        hboxLayout1->addWidget(label_6);

        legend = new QLineEdit(EntryDialog);
        legend->setObjectName(QString::fromUtf8("legend"));

        hboxLayout1->addWidget(legend);


        vboxLayout->addLayout(hboxLayout1);

        gridLayout = new QGridLayout();
        gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
        label_2 = new QLabel(EntryDialog);
        label_2->setObjectName(QString::fromUtf8("label_2"));

        gridLayout->addWidget(label_2, 0, 0, 1, 1);

        type = new QComboBox(EntryDialog);
        type->setObjectName(QString::fromUtf8("type"));

        gridLayout->addWidget(type, 0, 1, 1, 1);

        spacerItem = new QSpacerItem(41, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

        gridLayout->addItem(spacerItem, 0, 2, 1, 1);

        label_3 = new QLabel(EntryDialog);
        label_3->setObjectName(QString::fromUtf8("label_3"));

        gridLayout->addWidget(label_3, 0, 3, 1, 1);

        startDate = new QDateTimeEdit(EntryDialog);
        startDate->setObjectName(QString::fromUtf8("startDate"));
        startDate->setCalendarPopup(true);

        gridLayout->addWidget(startDate, 0, 4, 1, 1);

        label_5 = new QLabel(EntryDialog);
        label_5->setObjectName(QString::fromUtf8("label_5"));

        gridLayout->addWidget(label_5, 1, 0, 1, 1);

        completion = new QSpinBox(EntryDialog);
        completion->setObjectName(QString::fromUtf8("completion"));
        completion->setMaximum(100);

        gridLayout->addWidget(completion, 1, 1, 1, 1);

        label_EndDate = new QLabel(EntryDialog);
        label_EndDate->setObjectName(QString::fromUtf8("label_EndDate"));

        gridLayout->addWidget(label_EndDate, 1, 3, 1, 1);

        endDate = new QDateTimeEdit(EntryDialog);
        endDate->setObjectName(QString::fromUtf8("endDate"));
        endDate->setCalendarPopup(true);

        gridLayout->addWidget(endDate, 1, 4, 1, 1);

        readOnly = new QCheckBox(EntryDialog);
        readOnly->setObjectName(QString::fromUtf8("readOnly"));

        gridLayout->addWidget(readOnly, 2, 0, 1, 2);

        dependsLabel = new QLabel(EntryDialog);
        dependsLabel->setObjectName(QString::fromUtf8("dependsLabel"));

        gridLayout->addWidget(dependsLabel, 2, 3, 1, 1);

        depends = new QComboBox(EntryDialog);
        depends->addItem(QString());
        depends->setObjectName(QString::fromUtf8("depends"));

        gridLayout->addWidget(depends, 2, 4, 1, 1);


        vboxLayout->addLayout(gridLayout);

        buttonBox = new QDialogButtonBox(EntryDialog);
        buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
        buttonBox->setOrientation(Qt::Horizontal);
        buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);

        vboxLayout->addWidget(buttonBox);


        retranslateUi(EntryDialog);
        QObject::connect(buttonBox, SIGNAL(accepted()), EntryDialog, SLOT(accept()));
        QObject::connect(buttonBox, SIGNAL(rejected()), EntryDialog, SLOT(reject()));

        QMetaObject::connectSlotsByName(EntryDialog);
    } // setupUi

    void retranslateUi(QDialog *EntryDialog)
    {
        label->setText(QApplication::translate("EntryDialog", "Name", nullptr));
        label_6->setText(QApplication::translate("EntryDialog", "Legend", nullptr));
        label_2->setText(QApplication::translate("EntryDialog", "Type", nullptr));
        label_3->setText(QApplication::translate("EntryDialog", "Start date", nullptr));
        label_5->setText(QApplication::translate("EntryDialog", "Completion", nullptr));
        completion->setSuffix(QApplication::translate("EntryDialog", "%", nullptr));
        label_EndDate->setText(QApplication::translate("EntryDialog", "End date", nullptr));
        readOnly->setText(QApplication::translate("EntryDialog", "Read Only", nullptr));
        dependsLabel->setText(QApplication::translate("EntryDialog", "Depends on", nullptr));
        depends->setItemText(0, QApplication::translate("EntryDialog", "- None -", nullptr));

        Q_UNUSED(EntryDialog);
    } // retranslateUi

};

namespace Ui {
    class EntryDialog: public Ui_EntryDialog {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_ENTRYDIALOG_H

legend_example.pro

#include( $${TOP_SOURCE_DIR}/examples/examples.pri )

HEADERS += mainwindow.h 
           entrydialog.h 
           entrydelegate.h

SOURCES += main.cpp 
           mainwindow.cpp 
           entrydialog.cpp 
           entrydelegate.cpp

FORMS += mainwindow.ui 
         entrydialog.ui

greaterThan(QT_MAJOR_VERSION, 4):QT += printsupport

message( "Building ''$$TARGET'' using LIBS ''$$LIBS''" )

unix|win32: LIBS += -LE:/Qt/Qt5.12.2/5.12.2/msvc2015_64/lib/ -lkdchartd

INCLUDEPATH += E:/Qt/Qt5.12.2/5.12.2/msvc2015_64/include
DEPENDPATH += E:/Qt/Qt5.12.2/5.12.2/msvc2015_64/include

INCLUDEPATH += E:/Qt/Qt5.12.2/5.12.2/msvc2015_64/include/KDChart
DEPENDPATH += E:/Qt/Qt5.12.2/5.12.2/msvc2015_64/include/KDChart

INCLUDEPATH += E:/Qt/Qt5.12.2/5.12.2/msvc2015_64/include/KDGantt
DEPENDPATH += E:/Qt/Qt5.12.2/5.12.2/msvc2015_64/include/KDGantt

运行效果:


----------------------------------------------------------------

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(3,0,0x1d563494fc0,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

QWindowsWindow::setGeometry: Unable to set geometry 439x206+734+412 on QWidgetWindow/'EntryDialogWindow'. Resulting geometry: 452x206+734+412 (frame: 9, 38, 9, 9, custom margin: 0, 0, 0, 0, minimum size: 452x206, maximum size: 16777215x16777215).

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime

Skipping item QModelIndex(4,0,0x1d564202660,KDGantt::ProxyModel(0x1d55f32cdd8)) because it doesn't contain QDateTime


----------------------------------------------------------------








如果想修改为自定义样式:
参考:https://www.cnblogs.com/qnkk123/p/7685477.html
设置每个item的颜色:
topitem->setData(249, KDGantt::ItemColor_R);
topitem->setData(171, KDGantt::ItemColor_G);
topitem->setData(82, KDGantt::ItemColor_B);

kdChart中,颜色的修改是:

 void ItemDelegate::paintGanttItem( QPainter* painter,
                                   const StyleOptionGanttItem& opt,
                                   const QModelIndex& idx )
void ItemDelegate::paintGanttItem( QPainter* painter,
                                   const StyleOptionGanttItem& opt,
                                   const QModelIndex& idx )
{
    if ( !idx.isValid() ) return;

    const ItemType typ = static_cast<ItemType>( idx.model()->data( idx, ItemTypeRole ).toInt() );
    const QString& txt = opt.text;
    QRectF itemRect = opt.itemRect;
    QRectF boundingRect = opt.boundingRect;
    boundingRect.setY( itemRect.y() );
    boundingRect.setHeight( itemRect.height() );
    painter->save();

    int color_r = idx.model()->data( idx, ItemColor_R ).toInt();
    int color_g = idx.model()->data( idx, ItemColor_G ).toInt();
    int color_b = idx.model()->data( idx, ItemColor_B ).toInt();

    QColor itemColor(color_r, color_g, color_b);

    QPen pen(itemColor);
    if ( opt.state & QStyle::State_Selected ) pen.setWidth( 2*pen.width() );
    painter->setPen( pen );
    painter->setBrush( QBrush(Qt::white, Qt::Dense1Pattern) );

    bool drawText = true;
    qreal pw = painter->pen().width()/2.;
    switch ( typ ) {
    case TypeTask:
        if ( itemRect.isValid() ) {
            // TODO
            qreal pw = painter->pen().width()/2.;
            pw-=1;
            QRectF r = itemRect;
            r.translate( 0., r.height()/6. );
            r.setHeight( 2.*r.height()/3. );
            painter->setBrushOrigin( itemRect.topLeft() );
            painter->save();
            painter->translate( 0.5, 0.5 );
            painter->drawRect( r );
            bool ok;
            qreal completion = idx.model()->data( idx, KDGantt::TaskCompletionRole ).toReal( &ok );
            if ( ok ) {
                qreal h = r.height();
                QRectF cr( r.x(), r.y()+h/4.,
                           r.width()*completion/100., h/2.+1 /*??*/ );
                QColor compcolor( painter->pen().color() );
                compcolor.setAlpha( 150 );
                painter->fillRect( cr, compcolor );
            }
            painter->restore();
        }
        break;
    case TypeSummary:
        if ( opt.itemRect.isValid() ) {
            // TODO
            pw-=1;
            const QRectF r = QRectF( opt.itemRect ).adjusted( -pw, -pw, pw, pw );
            QPainterPath path;
            const qreal deltaY = r.height()/2.;
            const qreal deltaXBezierControl = .25*qMin( r.width(), r.height() );
            const qreal deltaX = qMin( r.width()/2., r.height() );
            path.moveTo( r.topLeft() );
            path.lineTo( r.topRight() );
            path.lineTo( QPointF( r.right(), r.top() + 2.*deltaY ) );
            //path.lineTo( QPointF( r.right()-3./2.*delta, r.top() + delta ) );
            path.quadTo( QPointF( r.right()-deltaXBezierControl, r.top() + deltaY ), QPointF( r.right()-deltaX, r.top() + deltaY ) );
            //path.lineTo( QPointF( r.left()+3./2.*delta, r.top() + delta ) );
            path.lineTo( QPointF( r.left() + deltaX, r.top() + deltaY ) );
            path.quadTo( QPointF( r.left()+deltaXBezierControl, r.top() + deltaY ), QPointF( r.left(), r.top() + 2.*deltaY ) );
            path.closeSubpath();
            painter->setBrushOrigin( itemRect.topLeft() );
            painter->save();
            painter->translate( 0.5, 0.5 );
            painter->drawPath( path );
            painter->restore();
        }
        break;
    case TypeEvent: /* TODO */
        //qDebug() << opt.boundingRect << opt.itemRect;
        if ( opt.boundingRect.isValid() ) {
            const qreal pw = painter->pen().width() / 2. - 1;
            const QRectF r = QRectF( opt.itemRect ).adjusted( -pw, -pw, pw, pw ).translated( -opt.itemRect.height()/2, 0 );
            QPainterPath path;
            const qreal delta = static_cast< int >( r.height() / 2 );
            path.moveTo( delta, 0. );
            path.lineTo( 2.*delta, delta );
            path.lineTo( delta, 2.*delta );
            path.lineTo( 0., delta );
            path.closeSubpath();
            painter->save();
            painter->translate( r.topLeft() );
            painter->translate( 0, 0.5 );
            painter->drawPath( path );
            painter->restore();
#if 0
            painter->setBrush( Qt::NoBrush );
            painter->setPen( Qt::black );
            painter->drawRect( opt.boundingRect );
            painter->setPen( Qt::red );
            painter->drawRect( r );
#endif
        }
        break;
    default:
        drawText = false;
        break;
    }

    Qt::Alignment ta;
    switch ( opt.displayPosition ) {
        case StyleOptionGanttItem::Left: ta = Qt::AlignLeft; break;
        case StyleOptionGanttItem::Right: ta = Qt::AlignRight; break;
        case StyleOptionGanttItem::Center: ta = Qt::AlignCenter; break;
        case StyleOptionGanttItem::Hidden: drawText = false; break;
    }
    if ( drawText ) {
        painter->drawText( boundingRect, ta | Qt::AlignVCenter, txt );
    }

    painter->restore();
}

拖动事件:

在文件kdganttgraphicsview.h中添加信号

void signal_dataChanged( const QModelIndex & index );


void GraphicsView::Private::slotDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight )
{
    const QModelIndex parent = topLeft.parent();
    for ( int row = topLeft.row(); row <= bottomRight.row(); ++row ) {
        scene.updateRow( scene.summaryHandlingModel()->index( row, 0, parent ) );
    }

    emit q->signal_dataChanged(topLeft);
}

外部使用:

connect(ui->ganttView->graphicsView(), SIGNAL(signal_dataChanged(const QModelIndex&)), this, SLOT(onCheckTask(const QModelIndex&)));

修改显示的日期格式,效果:

 

上面显示年月,下面显示多少号,显示号很简单:

 grid.setUserDefinedLowerScale(new KDGantt::DateTimeScaleFormatter(KDGantt::DateTimeScaleFormatter::Day,QString::fromLatin1("dd"),QString::fromLatin1("%1"),Qt::AlignHCenter));

其中有个格式:QString::fromLatin1("dd"),dd:号, ddd:星期几

使用这个函数,只能显示年或者月或者天,不能组合显示,所有重写DateTimeScaleFormatter;

class MyDateTimeScaleFormatter : public KDGantt::DateTimeScaleFormatter 
{
public:
    MyDateTimeScaleFormatter() : DateTimeScaleFormatter(Month, "MM"){}

    /*reimp*/QDateTime nextRangeBegin(const QDateTime& datetime) const
    {
        return currentRangeBegin(datetime).addMonths(1);
    }
    /*reimp*/QDateTime currentRangeBegin(const QDateTime& datetime) const
    {
        return datetime;
    }

    /*reimp*/QString text(const QDateTime& dt) const
    {
        return QObject::tr("%1年%2月").arg(dt.date().year()).arg(dt.date().month());
    }
};
grid.setUserDefinedUpperScale(new MyDateTimeScaleFormatter()); // 显示在上面

这部分转自:

https://www.cnblogs.com/qnkk123/p/7685477.html

原文地址:https://www.cnblogs.com/herd/p/11203195.html