File indexing completed on 2024-11-24 03:57:49
0001 /** 0002 * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 0003 * 0004 * This file is part of the KGantt library. 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "mainwindow.h" 0010 #include "../common/projectmodel.h" 0011 0012 #include <QAction> 0013 #include <QApplication> 0014 #include <QComboBox> 0015 #include <QMenuBar> 0016 #include <QMenu> 0017 #include <QModelIndex> 0018 #include <QItemSelectionModel> 0019 #include <QTreeView> 0020 #include <QDebug> 0021 #include <QBrush> 0022 #include <QPainter> 0023 #include <QPrinter> 0024 #include <QPrintDialog> 0025 #include <QPrintPreviewDialog> 0026 #include <QFileDialog> 0027 #include <QLabel> 0028 #include <QGridLayout> 0029 #include <QVBoxLayout> 0030 #include <QHBoxLayout> 0031 #include <QFileInfo> 0032 #include <QLineEdit> 0033 #include <QCheckBox> 0034 #include <QPushButton> 0035 #include <QDialogButtonBox> 0036 0037 #include <KGanttGlobal> 0038 #include <KGanttView> 0039 #include <KGanttItemDelegate> 0040 #include <KGanttDateTimeGrid> 0041 #include <KGanttStyleOptionGanttItem> 0042 #include <KGanttConstraintModel> 0043 #include <KGanttGraphicsView> 0044 #include <KGanttDateTimeTimeLine> 0045 0046 // Define a printer friendly palette 0047 #define VeryLightGray "#f8f8f8" 0048 #define LightLightGray "#f0f0f0" 0049 #define DarkDarkGray "#b3b3b3" 0050 #define VeryDarkGray "#838383" 0051 class PrintPalette { 0052 public: 0053 PrintPalette() { 0054 orig = QApplication::palette(); 0055 QPalette palette = orig; 0056 // define a palette that works when printing on white paper 0057 palette.setColor(QPalette::Window, Qt::white); 0058 palette.setColor(QPalette::WindowText, Qt::black); 0059 palette.setColor(QPalette::Base, Qt::white); 0060 palette.setColor(QPalette::AlternateBase, VeryLightGray); 0061 palette.setColor(QPalette::ToolTipBase, Qt::white); 0062 palette.setColor(QPalette::ToolTipText, Qt::black); 0063 palette.setColor(QPalette::Text, Qt::black); 0064 palette.setColor(QPalette::Button, Qt::lightGray); 0065 palette.setColor(QPalette::ButtonText, Qt::black); 0066 palette.setColor(QPalette::BrightText, Qt::white); 0067 palette.setColor(QPalette::Link, Qt::blue); 0068 palette.setColor(QPalette::Highlight, Qt::blue); 0069 palette.setColor(QPalette::HighlightedText, Qt::white); 0070 palette.setColor(QPalette::Light, QColor(VeryLightGray)); 0071 palette.setColor(QPalette::Midlight, QColor(LightLightGray)); 0072 palette.setColor(QPalette::Dark, QColor(DarkDarkGray)); 0073 palette.setColor(QPalette::Mid, QColor(VeryDarkGray)); 0074 palette.setColor(QPalette::Shadow, Qt::black); 0075 QApplication::setPalette(palette); 0076 } 0077 ~PrintPalette() { 0078 QApplication::setPalette(orig); 0079 } 0080 QPalette orig; 0081 }; 0082 0083 0084 class ItemTypeComboBox : public QComboBox { 0085 Q_OBJECT 0086 Q_PROPERTY( KGantt::ItemType itemType READ itemType WRITE setItemType ) 0087 public: 0088 explicit ItemTypeComboBox( QWidget* parent = nullptr ); 0089 0090 KGantt::ItemType itemType() const; 0091 public Q_SLOTS: 0092 void setItemType( KGantt::ItemType typ ); 0093 }; 0094 0095 ItemTypeComboBox::ItemTypeComboBox( QWidget* parent ) 0096 : QComboBox( parent ) 0097 { 0098 addItem( tr( "Task" ), QVariant( KGantt::TypeTask ) ); 0099 addItem( tr( "Event" ), QVariant( KGantt::TypeEvent ) ); 0100 addItem( tr( "Summary" ), QVariant( KGantt::TypeSummary ) ); 0101 } 0102 0103 KGantt::ItemType ItemTypeComboBox::itemType() const 0104 { 0105 return static_cast<KGantt::ItemType>( itemData( currentIndex() ).toInt() ); 0106 } 0107 0108 void ItemTypeComboBox::setItemType( KGantt::ItemType typ ) 0109 { 0110 setCurrentIndex( typ-1 ); 0111 } 0112 0113 class MyItemDelegate : public KGantt::ItemDelegate { 0114 public: 0115 explicit MyItemDelegate( QObject* parent = nullptr ); 0116 0117 /*reimp*/ QWidget* createEditor( QWidget* parent, 0118 const QStyleOptionViewItem& option, 0119 const QModelIndex& idx ) const override; 0120 /*reimp*/ void setEditorData( QWidget* editor, const QModelIndex& index ) const override; 0121 /*reimp*/ void setModelData( QWidget* editor, QAbstractItemModel* model, 0122 const QModelIndex & index ) const override; 0123 }; 0124 0125 MyItemDelegate::MyItemDelegate( QObject* parent ) 0126 : KGantt::ItemDelegate( parent ) 0127 { 0128 } 0129 0130 QWidget* MyItemDelegate::createEditor( QWidget* parent, 0131 const QStyleOptionViewItem& option, 0132 const QModelIndex& idx ) const 0133 { 0134 qDebug() << "MyItemDelegate::createEditor("<<parent<<idx<<")"; 0135 if ( idx.isValid() && idx.column() == 1 ) 0136 return new ItemTypeComboBox(parent); 0137 return ItemDelegate::createEditor( parent, option, idx ); 0138 } 0139 0140 void MyItemDelegate::setEditorData ( QWidget* editor, const QModelIndex& index ) const 0141 { 0142 ItemTypeComboBox* c; 0143 if ( (c = qobject_cast<ItemTypeComboBox*>(editor)) && index.isValid() ) { 0144 c->setItemType(static_cast<KGantt::ItemType>(index.data(Qt::EditRole).toInt())); 0145 } else { 0146 ItemDelegate::setEditorData(editor,index); 0147 } 0148 } 0149 0150 void MyItemDelegate::setModelData ( QWidget* editor, QAbstractItemModel* model, 0151 const QModelIndex & index ) const 0152 { 0153 ItemTypeComboBox* c; 0154 if ( (c = qobject_cast<ItemTypeComboBox*>(editor)) && index.isValid() ) { 0155 model->setData(index,c->itemType()); 0156 } else { 0157 ItemDelegate::setModelData(editor,model,index); 0158 } 0159 } 0160 0161 MainWindow::MainWindow( QWidget* parent ) 0162 : QMainWindow( parent ), 0163 m_model( new ProjectModel( this ) ), 0164 m_view( new KGantt::View ) 0165 { 0166 m_view->setModel( m_model ); 0167 0168 m_view->leftView()->setItemDelegateForColumn( 1, new MyItemDelegate( this ) ); 0169 0170 KGantt::DateTimeGrid *grid = new KGantt::DateTimeGrid(); 0171 grid->timeLine()->setPen(QPen(Qt::red)); 0172 grid->timeLine()->setOptions(KGantt::DateTimeTimeLine::UseCustomPen); 0173 grid->timeLine()->setInterval(5000); 0174 grid->setRowSeparators(true); 0175 m_view->setGrid(grid); 0176 0177 0178 setCentralWidget( m_view ); 0179 0180 QMenuBar* mb = menuBar(); 0181 0182 QMenu* fileMenu = new QMenu( tr( "&File" ) ); 0183 0184 #ifndef QT_NO_PRINTER 0185 fileMenu->addAction( tr( "&Save as PDF..." ), this, SLOT(slotFileSavePdf()) ); 0186 fileMenu->addAction( tr( "&Print Preview..." ), this, SLOT(slotFilePrintPreview()) ); 0187 fileMenu->addAction( tr( "&Print..." ), this, SLOT(slotFilePrint()) ); 0188 #endif 0189 0190 fileMenu->addSeparator(); 0191 fileMenu->addAction( tr( "&Quit" ), this, SLOT(slotFileQuit()) ); 0192 0193 mb->addMenu( fileMenu ); 0194 0195 QMenu* toolsMenu = new QMenu( tr( "&Tools" ) ); 0196 0197 toolsMenu->addAction( tr( "&New Item" ), this, SLOT(slotToolsNewItem()) ); 0198 toolsMenu->addAction( tr( "&Add Item" ), this, SLOT(slotToolsAppendItem()) ); 0199 toolsMenu->addSeparator(); 0200 QMenu *alignMenu = toolsMenu->addMenu( tr( "Ali&gn" ) ); 0201 alignMenu->addAction( tr( "&Left" ), this, SLOT(slotAlignLeft()) ); 0202 alignMenu->addAction( tr( "&Center" ), this, SLOT(slotAlignCenter()) ); 0203 alignMenu->addAction( tr( "&Right" ), this, SLOT(slotAlignRight()) ); 0204 alignMenu->addAction( tr( "&Hidden" ), this, SLOT(slotAlignHidden()) ); 0205 toolsMenu->addSeparator(); 0206 toolsMenu->addAction( tr( "&Collapse All" ), this, SLOT(slotCollapseAll()) ); 0207 toolsMenu->addAction( tr( "&Expand All" ), this, SLOT(slotExpandAll()) ); 0208 0209 mb->addMenu( toolsMenu ); 0210 0211 // define some items with different properties 0212 slotToolsAppendItem(); 0213 slotToolsAppendItem(); 0214 slotToolsAppendItem(); 0215 for (int i = 0; i < 3; ++i) { 0216 m_model->setData(m_model->index(i,2,QModelIndex()), QVariant::fromValue(QDateTime::currentDateTime().addDays(i)), KGantt::StartTimeRole); 0217 m_model->setData(m_model->index(i,3,QModelIndex()), QVariant::fromValue(QDateTime::currentDateTime().addDays(i+1)), KGantt::EndTimeRole); 0218 } 0219 slotToolsAppendItem(); 0220 m_model->setData(m_model->index(3,2,QModelIndex()), QVariant::fromValue(QDateTime::currentDateTime()), KGantt::StartTimeRole); 0221 m_model->setData(m_model->index(3,3,QModelIndex()), QVariant::fromValue(QDateTime::currentDateTime().addDays(1)), KGantt::EndTimeRole); 0222 m_model->setData(m_model->index(3,4,QModelIndex()), QVariant::fromValue(50), KGantt::TaskCompletionRole); 0223 0224 m_view->setConstraintModel(new KGantt::ConstraintModel(m_view)); 0225 m_view->constraintModel()->addConstraint(KGantt::Constraint(m_model->index(0,0,QModelIndex()),m_model->index(1,0,QModelIndex()))); 0226 m_view->constraintModel()->addConstraint(KGantt::Constraint(m_model->index(1,0,QModelIndex()),m_model->index(2,0,QModelIndex()))); 0227 // invalid constraint 0228 m_view->constraintModel()->addConstraint(KGantt::Constraint(m_model->index(2,0,QModelIndex()),m_model->index(3,0,QModelIndex()))); 0229 0230 // no info 0231 slotToolsAppendItem(); 0232 m_model->setData(m_model->index(4,2,QModelIndex()), QVariant::fromValue(QDateTime()), KGantt::StartTimeRole); 0233 m_model->setData(m_model->index(4,3,QModelIndex()), QVariant::fromValue(QDateTime()), KGantt::EndTimeRole); 0234 } 0235 0236 SavePdfDialog::SavePdfDialog(QWidget *parent) 0237 : QDialog(parent) 0238 { 0239 setModal(true); 0240 setWindowTitle(tr("Save as PDF")); 0241 QVBoxLayout *l = new QVBoxLayout(this); 0242 setLayout(l); 0243 0244 QHBoxLayout *fileLayout = new QHBoxLayout(this); 0245 l->addLayout(fileLayout); 0246 QLabel *fileLabel = new QLabel(tr("File:"), this); 0247 fileLayout->addWidget(fileLabel); 0248 m_fileEdit = new QLineEdit(this); 0249 fileLabel->setBuddy(m_fileEdit); 0250 m_fileEdit->setText(QFileInfo(QDir::homePath(), "gantt.pdf").absoluteFilePath()); 0251 fileLayout->addWidget(m_fileEdit); 0252 QPushButton *m_fileButton = new QPushButton("...", this); 0253 connect(m_fileButton, SIGNAL(clicked()), this, SLOT(fileButtonClicked())); 0254 fileLayout->addWidget(m_fileButton); 0255 0256 m_rowLabels = new QCheckBox(tr("Row Header"), this); 0257 m_rowLabels->setChecked(true); 0258 l->addWidget(m_rowLabels); 0259 0260 m_columnLabels = new QCheckBox(tr("Column Header"), this); 0261 m_columnLabels->setChecked(true); 0262 l->addWidget(m_columnLabels); 0263 0264 QDialogButtonBox *btnBox = new QDialogButtonBox(this); 0265 btnBox->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel); 0266 connect(btnBox, SIGNAL(accepted()), this, SLOT(accept())); 0267 connect(btnBox, SIGNAL(rejected()), this, SLOT(reject())); 0268 l->addWidget(btnBox); 0269 0270 resize(QSize(400, 100).expandedTo(minimumSizeHint())); 0271 } 0272 0273 void SavePdfDialog::fileButtonClicked() 0274 { 0275 const QString file = QFileDialog::getSaveFileName(this, tr("Choose PDF File..."), QString(), tr("PDF files (*.pdf)")); 0276 if (!file.isEmpty()) 0277 m_fileEdit->setText(file); 0278 } 0279 0280 void MainWindow::slotFileSavePdf() 0281 { 0282 #ifndef QT_NO_PRINTER 0283 SavePdfDialog dialog(this); 0284 if (dialog.exec() != QDialog::Accepted) 0285 return; 0286 0287 const QString file = dialog.m_fileEdit->text(); 0288 if (file.isEmpty()) 0289 return; 0290 0291 const bool drawRowLabels = dialog.m_rowLabels->isChecked(); 0292 const bool drawColumnLabels = dialog.m_columnLabels->isChecked(); 0293 0294 QPrinter printer(QPrinter::HighResolution); 0295 printer.setPageOrientation(QPageLayout::Landscape); 0296 printer.setColorMode(QPrinter::Color); 0297 printer.setPageMargins(QMarginsF(0.2, 0.2, 0.2, 0.2), QPageLayout::Point); 0298 printer.setOutputFormat(QPrinter::PdfFormat); 0299 printer.setOutputFileName(file); 0300 PrintPalette p; 0301 m_view->print(&printer, drawRowLabels, drawColumnLabels); 0302 #endif 0303 } 0304 0305 void MainWindow::slotFilePrint() 0306 { 0307 #ifndef QT_NO_PRINTER 0308 QPrinter printer(QPrinter::HighResolution); 0309 printer.setPageOrientation(QPageLayout::Landscape); 0310 printer.setColorMode(QPrinter::Color); 0311 QPrintDialog dialog(&printer, this); 0312 if (dialog.exec() != QDialog::Accepted) { 0313 return; 0314 } 0315 PrintPalette p; 0316 m_view->print(&printer); 0317 #endif 0318 } 0319 0320 void MainWindow::slotFilePrintPreview() 0321 { 0322 QPrinter printer(QPrinter::HighResolution); 0323 printer.setPageOrientation(QPageLayout::Landscape); 0324 printer.setColorMode(QPrinter::Color); 0325 QPrintPreviewDialog preview(&printer); 0326 connect(&preview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(slotPrintPreviewPaintRequest(QPrinter*))); 0327 preview.exec(); 0328 } 0329 0330 void MainWindow::slotPrintPreviewPaintRequest(QPrinter *printer) 0331 { 0332 PrintPalette p; 0333 m_view->print(printer); 0334 } 0335 0336 void MainWindow::slotFileQuit() 0337 { 0338 // TODO 0339 QApplication::instance()->quit(); 0340 } 0341 0342 void MainWindow::slotToolsNewItem() 0343 { 0344 QModelIndex idx = m_view->selectionModel()->currentIndex(); 0345 if ( idx.isValid() ) { 0346 qDebug() << "MainWindow::slotToolsNewItem" << idx; 0347 m_model->insertRows( 0, 1, m_model->index( idx.row(),0,idx.parent() ) ); 0348 } else { 0349 m_model->insertRows( 0, 1, m_view->rootIndex() ); 0350 } 0351 } 0352 0353 void MainWindow::slotToolsAppendItem() 0354 { 0355 QModelIndex idx = m_view->selectionModel()->currentIndex(); 0356 if ( idx.isValid() ) { 0357 qDebug() << "MainWindow::slotToolsAppendItem" << idx; 0358 m_model->insertRows( m_model->rowCount( idx ), 1, m_model->index( idx.row(),0,idx.parent() ) ); 0359 } else { 0360 m_model->insertRows( m_model->rowCount( m_view->rootIndex() ), 1, m_view->rootIndex() ); 0361 } 0362 } 0363 0364 void MainWindow::slotCollapseAll() 0365 { 0366 // don't use the treeview's collapseAll/expandAll methods but use the one provided by the 0367 // view cause that one will take care to update everyt6hing as needed. 0368 //QTreeView* view = qobject_cast<QTreeView*>( m_view->leftView() ); 0369 //view->collapseAll(); 0370 0371 QModelIndex idx = m_view->selectionModel()->currentIndex(); 0372 if ( idx.isValid() ) 0373 m_view->collapseAll(); 0374 } 0375 0376 void MainWindow::slotExpandAll() 0377 { 0378 // don't use the treeview's collapseAll/expandAll methods but use the one provided by the 0379 // view cause that one will take care to update everyt6hing as needed. 0380 //QTreeView* view = qobject_cast<QTreeView*>( m_view->leftView() ); 0381 //view->expandAll(); 0382 0383 QModelIndex idx = m_view->selectionModel()->currentIndex(); 0384 if ( idx.isValid() ) 0385 m_view->expandAll(); 0386 } 0387 0388 void MainWindow::slotAlignLeft() 0389 { 0390 QModelIndex idx = m_view->selectionModel()->currentIndex(); 0391 if ( idx.isValid() ) { 0392 m_model->setData( idx, KGantt::StyleOptionGanttItem::Left, KGantt::TextPositionRole ); 0393 } 0394 } 0395 0396 void MainWindow::slotAlignCenter() 0397 { 0398 QModelIndex idx = m_view->selectionModel()->currentIndex(); 0399 if ( idx.isValid() ) { 0400 m_model->setData( idx, KGantt::StyleOptionGanttItem::Center, KGantt::TextPositionRole ); 0401 } 0402 } 0403 0404 void MainWindow::slotAlignRight() 0405 { 0406 QModelIndex idx = m_view->selectionModel()->currentIndex(); 0407 if ( idx.isValid() ) { 0408 m_model->setData( idx, KGantt::StyleOptionGanttItem::Right, KGantt::TextPositionRole ); 0409 } 0410 } 0411 0412 void MainWindow::slotAlignHidden() 0413 { 0414 QModelIndex idx = m_view->selectionModel()->currentIndex(); 0415 if ( idx.isValid() ) { 0416 m_model->setData( idx, KGantt::StyleOptionGanttItem::Hidden, KGantt::TextPositionRole ); 0417 } 0418 } 0419 0420 #include "mainwindow.moc"