Line data Source code
1 : #include <qtreports/engine.hpp> 2 : 3 : #include <QPainter> 4 : #include <QPrintDialog> 5 : #include <QPrintPreviewWidget> 6 : #include <QPrintPreviewDialog> 7 : #include <QDebug> 8 : 9 : #include "parsers/parserfromxml.hpp" 10 : #include "converters/convertertopdf.hpp" 11 : #include "converters/convertertohtml.hpp" 12 : 13 : #include "tags/report.hpp" 14 : #include "converters/convertertoqwidget.hpp" 15 : 16 : namespace qtreports 17 : { 18 29 : Engine::Engine( QObject * parent ) : 19 : QObject( parent ), 20 29 : m_isOpened( false ) 21 29 : {} 22 : 23 3 : Engine::Engine( const QString & path, QObject * parent ) : 24 3 : Engine( parent ) 25 : { 26 3 : open( path ); 27 3 : } 28 : 29 29 : Engine::~Engine() {} 30 : 31 37 : bool Engine::open( const QString & path ) 32 : { 33 37 : if( isOpened() ) 34 : { 35 8 : close(); 36 : } 37 : 38 74 : detail::ParserFromXML parser; 39 37 : if( !parser.parse( path ) ) 40 : { 41 3 : m_lastError = "Parsing error: " + parser.getLastError(); 42 3 : return false; 43 : } 44 : 45 34 : m_isOpened = true; 46 34 : m_compiledPath = path; 47 34 : m_report = parser.getReport(); 48 : #ifdef QT_DEBUG 49 : qDebug() << parser.getLog(); 50 : #endif 51 : //fillColumnsFromReport(); //MB as ProcessedDB::createColumns( ReportPtr ) 52 : 53 34 : return true; 54 : } 55 : 56 9 : void Engine::close() 57 : { 58 9 : m_isOpened = false; 59 9 : m_compiledPath.clear(); 60 9 : m_report.clear(); 61 9 : } 62 : 63 5 : bool Engine::setParameters( const QMap< QString, QVariant > & parameters ) 64 : { 65 5 : if( m_report.isNull() ) 66 : { 67 1 : m_lastError = "Report is empty. Please open report file"; 68 1 : return false; 69 : } 70 : 71 4 : m_report->setParameters( parameters ); 72 : 73 4 : return true; 74 : } 75 : 76 18 : bool Engine::setConnection( const QSqlDatabase & connection ) 77 : { 78 18 : if( !connection.isOpen() ) 79 : { 80 1 : m_lastError = "Connection not open"; 81 1 : return false; 82 : } 83 : 84 17 : if( m_report.isNull() ) 85 : { 86 1 : m_lastError = "Report is empty. Please open report file"; 87 1 : return false; 88 : } 89 : 90 16 : m_dbConnection = connection; 91 : 92 16 : if( !prepareDB() ) 93 : { 94 2 : m_lastError = "Error in prepare db process: " + m_lastError; 95 2 : return false; 96 : } 97 : 98 : //m_report->setRowCount( db.getMaxRowCount() ); 99 : /* 100 : for( auto && field : m_report->getFields() ) 101 : { 102 : auto name = field->getName(); 103 : auto value = db.getColumn( name ); 104 : m_report->setFieldData( name, value ); 105 : } 106 : 107 : db.setParameters( m_report->getParameters() ); 108 : */ 109 14 : return true; 110 : } 111 : 112 1 : bool Engine::setDataSource( const QMap< QString, QVector< QVariant > > & source ) 113 : { 114 : // TODO check parameters 115 : //m_dataSource = columnsSet; 116 : 117 : //detail::ProcessedDB db; 118 1 : if( !prepareDataSource( source ) ) 119 : { 120 0 : m_lastError = "Error in prepare data source: " + m_lastError; 121 0 : return false; 122 : } 123 : 124 : //m_report->setRowCount( db.getMaxRowCount() ); 125 : /* 126 : for( auto && field : m_report->getFields() ) 127 : { 128 : auto name = field->getName(); 129 : auto value = db.getColumn( name ); 130 : m_report->setFieldData( name, value ); 131 : } 132 : */ 133 1 : return true; 134 : } 135 : 136 19 : bool Engine::setQuery( const QString & query ) 137 : { 138 : // TODO check parameters 139 : 140 38 : QStringList queries = query.split( ";", QString::SkipEmptyParts ); 141 38 : QMap< QString, QVariant > param = m_report->getParameters(); 142 : 143 41 : for (int i = 0; i < queries.size(); i++) { 144 30 : for (auto it = param.begin(); it != param.end(); it++) { 145 : 146 16 : QString find = "$P{" + it.key() + "}"; 147 16 : QString to = "'" + it.value().toString() + "'"; 148 8 : if(queries[i].indexOf(find)!=-1) 149 0 : queries[i] = queries[i].replace(find, to); 150 : } 151 : } 152 : 153 38 : return executeQueries(queries); 154 : } 155 : 156 1 : bool Engine::addScript( const QString & script ) 157 : { 158 : // TODO check parameters 159 1 : m_scripts.append( script ); 160 : 161 1 : return true; 162 : } 163 : 164 1 : bool Engine::setDataModel( const QAbstractItemModel & model ) 165 : { 166 : // TODO check parameters 167 : Q_UNUSED( model ); 168 1 : return true; 169 : } 170 : 171 3 : bool Engine::createPDF( const QString & path ) 172 : { 173 3 : if( m_report.isNull() ) 174 : { 175 1 : m_lastError = "Report is empty. Please open report file"; 176 1 : return false; 177 : } 178 : 179 4 : detail::ConverterToPDF converter( m_report ); 180 2 : auto result = converter.convert( path ); 181 2 : if( !result ) 182 : { 183 1 : m_lastError = converter.getLastError(); 184 1 : return false; 185 : } 186 : 187 1 : return true; 188 : } 189 : 190 3 : bool Engine::createHTML( const QString & path ) 191 : { 192 3 : if( m_report.isNull() ) 193 : { 194 1 : m_lastError = "Report is empty. Please open report file"; 195 1 : return false; 196 : } 197 : 198 4 : detail::ConverterToHTML converter( m_report ); 199 2 : auto result = converter.convert( path ); 200 2 : if( !result ) 201 : { 202 1 : m_lastError = converter.getLastError(); 203 1 : return false; 204 : } 205 : 206 1 : return true; 207 : } 208 : 209 3 : QWidgetPtr Engine::createWidget() 210 : { 211 3 : if( m_report.isNull() ) 212 : { 213 1 : m_lastError = "Report is empty. Please open report file"; 214 1 : return QWidgetPtr(); 215 : } 216 : 217 4 : detail::ConverterToQWidget converter( m_report ); 218 2 : auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Report ); 219 2 : if( !result ) 220 : { 221 1 : m_lastError = converter.getLastError(); 222 1 : return QWidgetPtr(); 223 : } 224 : 225 1 : return converter.getQWidget(); 226 : } 227 : 228 3 : QWidgetPtr Engine::createLayout() 229 : { 230 3 : if( m_report.isNull() ) 231 : { 232 1 : m_lastError = "Report is empty. Please open report file"; 233 1 : return QWidgetPtr(); 234 : } 235 : 236 4 : detail::ConverterToQWidget converter( m_report ); 237 2 : auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Layout ); 238 2 : if( !result ) 239 : { 240 1 : m_lastError = converter.getLastError(); 241 1 : return QWidgetPtr(); 242 : } 243 : 244 1 : return converter.getQWidget(); 245 : } 246 : 247 3 : QPrintPreviewDialogPtr Engine::getPrintPreviewDialog() 248 : { 249 3 : if( m_report.isNull() ) 250 : { 251 1 : m_lastError = "Report is empty. Please open report file"; 252 1 : return QPrintPreviewDialogPtr(); 253 : } 254 : 255 2 : if (!prepareDB()) { 256 1 : return QPrintPreviewDialogPtr(); 257 : } 258 : 259 2 : QSharedPointer<QPrinter> printer; 260 2 : QPrintPreviewDialogPtr preview(new QPrintPreviewDialog( printer.get() )); 261 : connect( 262 1 : preview.get(), &QPrintPreviewDialog::paintRequested, 263 : this, &Engine::drawPreview 264 2 : ); 265 : 266 1 : return preview; 267 : } 268 : 269 1 : void Engine::drawPreview( QPrinter * printer ) 270 : { 271 1 : auto temp = m_report->getOrientation(); 272 1 : m_report->setOrientation( printer->orientation() ); 273 2 : detail::ConverterToQWidget converter( m_report ); 274 1 : auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Report ); 275 1 : m_report->setOrientation( temp ); 276 1 : if( !result ) 277 : { 278 0 : m_lastError = converter.getLastError(); 279 0 : return; 280 : } 281 : 282 2 : auto widgets = converter.getPages(); 283 1 : if( widgets.isEmpty() ) 284 : { 285 0 : m_lastError = "Cannot print widget: all pages is empty"; 286 0 : return; 287 : } 288 : 289 2 : auto widget = widgets.value( 0 ); 290 : 291 1 : QRectF rect = printer->pageRect(); 292 2 : QPainter painter( printer ); 293 1 : qreal scale = rect.width() / widget->width(); 294 : 295 1 : widget->resize( widget->width(), rect.height() / scale ); 296 1 : painter.scale( scale, scale ); 297 : 298 3 : for( int i = 0; i < widgets.size(); ++i ) 299 : { 300 2 : i != 0 ? printer->newPage() : 0; 301 2 : widget = widgets.value( i ); 302 2 : if( widget.isNull() ) 303 : { 304 0 : m_lastError = "Error in print process: printed widget is empty"; 305 0 : return; 306 : } 307 : 308 : //Magic 309 2 : widget->show(); 310 2 : widget->hide(); 311 2 : widget->render( &painter ); 312 : } 313 : } 314 : 315 18 : bool Engine::prepareDB() 316 : { 317 18 : return setQuery( m_report->getQuery() ); 318 : } 319 : 320 20 : bool Engine::prepareDataSource( const QMap< QString, QVector< QVariant > > & source ) 321 : { 322 40 : QMapIterator< QString, QVector< QVariant > > iterator( source ); 323 20 : if (!iterator.hasNext()) 324 : { 325 3 : m_lastError = "Query has not rerurned result"; 326 3 : return false; 327 : } 328 : 329 123 : while( iterator.hasNext() ) 330 : { 331 53 : iterator.next(); 332 106 : auto field = m_report->getField( iterator.key() ); 333 53 : if( field.isNull() ) 334 : { 335 0 : m_lastError = "Report not have column: " + iterator.key(); 336 0 : return false; 337 : } 338 : 339 53 : field->setData( iterator.value() ); 340 : } 341 : 342 17 : m_report->fillGroupsData(getReport()); 343 : 344 17 : return true; 345 : } 346 : 347 : //void Engine::fillColumnsFromReport() 348 : //{ 349 : // for( auto && field : m_report->getFields() ) 350 : // { 351 : // db.addEmptyColumn( field->getName() ); 352 : // } 353 : //} 354 : 355 19 : bool Engine::executeQueries( const QStringList & queries ) 356 : { 357 38 : QMap< QString, QVector< QVariant > > data; 358 38 : QSqlQueryModel model; 359 41 : for( auto && query : queries ) 360 : { 361 22 : model.setQuery( query, m_dbConnection ); 362 : 363 137 : for( int row = 0; row < model.rowCount(); row++ ) 364 : { 365 230 : QSqlRecord rec = model.record( row ); 366 460 : for( int col = 0; col < rec.count(); col++ ) 367 : { 368 690 : auto columnName = rec.fieldName( col ); 369 690 : auto fieldValue = rec.field( col ).value(); 370 : //db.appendColumnData( columnName, fieldValue ); 371 345 : data[ columnName ].append( fieldValue ); 372 : } 373 : } 374 : } 375 : 376 38 : return prepareDataSource( data ); 377 : } 378 : 379 44 : bool Engine::isOpened() const 380 : { 381 44 : return m_isOpened; 382 : } 383 : 384 31 : detail::ReportPtr Engine::getReport() const 385 : { 386 31 : return m_report; 387 : } 388 : 389 62 : const QString Engine::getLastError() const 390 : { 391 62 : return m_lastError; 392 : } 393 : 394 : }