zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    聊天工具分享bug
    Git命令查看代码提交次数
    短链接生成实例
    .Net MVC用户注册验证码
    js写验证码
    笔记
    jq获取数组中的某个字段拆分成字符串。
    IIS部署后中文Cookie乱码
    C#反射(Reflection)与特性(Attribute)实例
    jmm
  • 原文地址:https://www.cnblogs.com/herd/p/11203195.html
Copyright © 2011-2022 走看看