diff --git a/src/backend/pivot/PivotTable.cpp b/src/backend/pivot/PivotTable.cpp index b9c66d8dd..ce8cffdd4 100644 --- a/src/backend/pivot/PivotTable.cpp +++ b/src/backend/pivot/PivotTable.cpp @@ -1,562 +1,573 @@ /*************************************************************************** File : PivotTable.cpp Project : LabPlot Description : Aspect providing pivot table functionality -------------------------------------------------------------------- Copyright : (C) 2019 Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "PivotTable.h" #include "PivotTablePrivate.h" #include "kdefrontend/pivot/PivotTableView.h" #include "kdefrontend/pivot/HierarchicalHeaderView.h" #include "backend/lib/commandtemplates.h" #include "backend/lib/trace.h" #include "backend/lib/XmlStreamReader.h" #include "backend/spreadsheet/Spreadsheet.h" #include #include #include #include #include #include #include #include #include #include +#include + /*! \class PivotTable \brief Aspect providing a pivot table. \ingroup backend */ PivotTable::PivotTable(const QString& name, bool loading) : AbstractPart(name), d(new PivotTablePrivate(this)) { Q_UNUSED(loading) } //############################################################################## //########################## getter methods ################################## //############################################################################## BASIC_D_READER_IMPL(PivotTable, PivotTable::DataSourceType, dataSourceType, dataSourceType) BASIC_D_READER_IMPL(PivotTable, Spreadsheet*, dataSourceSpreadsheet, dataSourceSpreadsheet) CLASS_D_READER_IMPL(PivotTable, QString, dataSourceConnection, dataSourceConnection) CLASS_D_READER_IMPL(PivotTable, QString, dataSourceTable, dataSourceTable) QAbstractItemModel* PivotTable::dataModel() const { return d->dataModel; } void PivotTable::setHorizontalHeaderModel(QAbstractItemModel* model) const { d->horizontalHeaderModel = dynamic_cast(model); qDebug()<<"model in set " << d->horizontalHeaderModel << " " << model; } void PivotTable::setVerticalHeaderModel(QAbstractItemModel* model) const { d->verticalHeaderModel = dynamic_cast(model); } //############################################################################## //################# setter methods and undo commands ########################## //############################################################################## STD_SETTER_CMD_IMPL_F_S(PivotTable, SetDataSourceType, PivotTable::DataSourceType, dataSourceType, recalculate) void PivotTable::setDataSourceType(DataSourceType type) { if (type != d->dataSourceType) exec(new PivotTableSetDataSourceTypeCmd(d, type, ki18n("%1: data source type changed"))); } STD_SETTER_CMD_IMPL_F_S(PivotTable, SetDataSourceSpreadsheet, Spreadsheet*, dataSourceSpreadsheet, recalculate) void PivotTable::setDataSourceSpreadsheet(Spreadsheet* spreadsheet) { if (spreadsheet != d->dataSourceSpreadsheet) exec(new PivotTableSetDataSourceSpreadsheetCmd(d, spreadsheet, ki18n("%1: data source spreadsheet changed"))); } const QStringList& PivotTable::dimensions() const { return d->dimensions; } const QStringList& PivotTable::measures() const { return d->measures; } const QStringList& PivotTable::rows() const { return d->rows; } void PivotTable::addToRows(const QString& field) { d->addToRows(field); } void PivotTable::removeFromRows(const QString& field) { d->removeFromRows(field); } const QStringList& PivotTable::columns() const { return d->columns; } void PivotTable::addToColumns(const QString& dimension) { d->addToColumns(dimension); } void PivotTable::removeFromColumns(const QString& field) { d->removeFromColumns(field); } bool PivotTable::exportView() const { return true; } bool PivotTable::printView() { return true; } bool PivotTable::printPreview() const { return true; } /*! Constructs a primary view on me. This method may be called multiple times during the life time of an Aspect, or it might not get called at all. Aspects must not depend on the existence of a view for their operation. */ QWidget* PivotTable::view() const { if (!m_partView) { m_view = new PivotTableView(const_cast(this)); m_partView = m_view; } return m_partView; } /*! Returns a new context menu. The caller takes ownership of the menu. */ QMenu* PivotTable::createContextMenu() { QMenu* menu = AbstractPart::createContextMenu(); Q_ASSERT(menu); emit requestProjectContextMenu(menu); return menu; } /*! Returns an icon to be used for decorating my views. */ QIcon PivotTable::icon() const { return QIcon::fromTheme("labplot-spreadsheet"); } //############################################################################## //###################### Private implementation ############################### //############################################################################## PivotTablePrivate::PivotTablePrivate(PivotTable* owner) : q(owner) , dataModel(new QStandardItemModel) // horizontalHeaderModel(new HierarchicalHeaderModel), // verticalHeaderModel(new HierarchicalHeaderModel) { } PivotTablePrivate::~PivotTablePrivate() { } QString PivotTablePrivate::name() const { return q->name(); } void PivotTablePrivate::addToRows(const QString& field) { rows << field; recalculate(); } void PivotTablePrivate::removeFromRows(const QString& field) { rows.removeOne(field); recalculate(); } void PivotTablePrivate::addToColumns(const QString& dimension) { columns << dimension; recalculate(); } void PivotTablePrivate::removeFromColumns(const QString& field) { columns.removeOne(field); recalculate(); } /* QStringList PivotTablePrivate::members(const QString& dimension, PivotTable::SortType sort) { //check whether we have the members already if (m_members.contains(dimension)) return m_members.value(dimension); QStringList members; //construct the query QString query; swich case (sort) { case PivotTable::NoSort: query = "SELECT DISTINCT " + dimension " FROM pivot;"; break; case PivotTable::SortAscending: query = "SELECT DISTINCT " + dimension " FROM pivot ASC;"; break; case PivotTable::SortDescending: query = "SELECT DISTINCT " + dimension " FROM pivot DESC;"; break; } //execute the query QSqlQuery q; if (!q.exec(query)) { KMessageBox::error(nullptr, i18n("Failed to process the query.") + "\n" + q.lastError().databaseText()); return members; } //copy the results to the string list while (query.next()) members << query.value(0).toString(); //cache the members of the new dimension m_members[dimension] = members; return members; } */ void PivotTablePrivate::recalculate() { //clear the previos result dataModel->clear(); horizontalHeaderModel->clear(); verticalHeaderModel->clear(); //nothing to do if no spreadsheet is set yet if (dataSourceType == PivotTable::DataSourceSpreadsheet && !dataSourceSpreadsheet) return; if (rows.isEmpty() && columns.isEmpty() && !showTotals) { //notify about the new result - emit q->changed(); + emit q->changed(); return; } WAIT_CURSOR; if (dataSourceType == PivotTable::DataSourceSpreadsheet && !m_dbCreated) createDb(); //construct the SQL statement string QString query{"SELECT "}; QString groupByString; if (!showNulls) { //if we don't need to show combinations with empty intersections, put everything into GROUP BY if (!rows.isEmpty()) groupByString = rows.join(','); if (!columns.isEmpty()) { if (!groupByString.isEmpty()) groupByString += ','; groupByString += columns.join(','); } if (!groupByString.isEmpty()) { query += groupByString; // if (showTotals) query += ", COUNT(*) FROM pivot"; query += " GROUP BY " + groupByString; if (!sortDimension.isEmpty()) { switch (sortType) { case PivotTable::NoSort: query += " ORDER BY " + sortDimension; break; case PivotTable::SortAscending: query += " ORDER BY " + sortDimension + " ASC"; break; case PivotTable::SortDescending: query += " ORDER BY " + sortDimension + " DESC"; break; } } } else { //no dimensions selected, show totals only query += "COUNT(*) FROM pivot"; } } else { } - QDEBUG(query); + //QDEBUG(query); + + qDebug()<<"query is " << query; //execute the query QSqlQuery sqlQuery; if (!sqlQuery.exec(query)) { RESET_CURSOR; KMessageBox::error(nullptr, i18n("Failed to process the query.") + "\n" + sqlQuery.lastError().databaseText()); emit q->changed(); return; } //copy the result into the models int rowsCount = sqlQuery.size(); int columnsCount = sqlQuery.record().count(); int firstValueIndex = rows.size() + columns.size(); int valuesCount = columnsCount - firstValueIndex; - DEBUG("nubmer of columns " << columnsCount); - DEBUG("number rows: " << rowsCount); - DEBUG("number values: " << valuesCount); - DEBUG("index of the first value column: " << firstValueIndex); +// DEBUG("nubmer of columns " << columnsCount); +// DEBUG("number rows: " << rowsCount); +// DEBUG("number values: " << valuesCount); +// DEBUG("index of the first value column: " << firstValueIndex); + + qDebug() << "number of columns " << columnsCount; + qDebug() << "number of rows" << rowsCount; + qDebug() << "number of values" << valuesCount; + qDebug() << "index of first value column " << firstValueIndex; qDebug()<<"model in recalculate " << horizontalHeaderModel; if (!horizontalHeaderModel) { RESET_CURSOR; return; } //resize the hierarhical header models if (columns.isEmpty() && rows.isEmpty()) { //no labels provided, show the total count only //vertical header verticalHeaderModel->setColumnCount(0); verticalHeaderModel->setRowCount(0); //horizontal header horizontalHeaderModel->setColumnCount(1); horizontalHeaderModel->setRowCount(1); horizontalHeaderModel->setData(horizontalHeaderModel->index(0, 0), "Totals", Qt::DisplayRole); } else if (columns.isEmpty()) { //no column labels provided, we have: //* all labels on rows // -> one column for the vertical header with the number of rows equal to the number of record sets in the result query //* only values on columns // -> one row for the horizontal header with the number of columns equal to the number of values //vertical header verticalHeaderModel->setColumnCount(rows.count()); //horizontal header - horizontalHeaderModel->setColumnCount(valuesCount); + horizontalHeaderModel->setColumnCount(valuesCount); horizontalHeaderModel->setRowCount(1); //TODO: only "Totals" value at the moment, needs to be extended later when we allow to add other values horizontalHeaderModel->setData(horizontalHeaderModel->index(0, 0), "Totals", Qt::DisplayRole); } else if (rows.isEmpty()) { //no row labels provided, we have: //* all labels on rows // -> one column for the vertical header with the number of rows equal to the number of record sets in the result query //* only values on columns // -> one row for the horizontal header with the number of columns equal to the number of values //vertical header //horizontal header // for (int i = 0; i < columns.size(); ++i) // horizontalHeaderModel->setData(horizontalHeaderModel->index(0, i), columns.at(i), Qt::DisplayRole); } else { //TODO: } //handle the data model dataModel->setColumnCount(valuesCount); if (rowsCount != -1) dataModel->setRowCount(rowsCount); int row = 0; //add values to the data models if (columns.isEmpty() && rows.isEmpty()) { } else if (columns.isEmpty()) { qDebug()<<"everything on rows"; while (sqlQuery.next()) { qDebug()<<"row: " << row; - horizontalHeaderModel->setRowCount(row+1); + verticalHeaderModel->setRowCount(row+1); for (int i = 0; i < firstValueIndex; ++i) { qDebug()<<"adding to the horizontal header " << sqlQuery.value(i); - horizontalHeaderModel->setData(horizontalHeaderModel->index(row, i), sqlQuery.value(i), Qt::DisplayRole); + verticalHeaderModel->setData(verticalHeaderModel->index(row, i), sqlQuery.value(i), Qt::DisplayRole); } //values for (int i = firstValueIndex; i < columnsCount; ++i) { QString value = sqlQuery.value(i).toString(); qDebug()<<"adding value " << value; if (rowsCount == -1) dataModel->setRowCount(row + 1); dataModel->setItem(row, i - firstValueIndex, new QStandardItem(value)); } ++row; } + verticalHeaderModel->setSpan(0,0,0,rows.count()); + } else if (rows.isEmpty()) { qDebug()<<"everything on columns"; // for (int i = firstValueIndex; i < columnsCount; ++i) { // QString value = sqlQuery.value(i).toString(); // if (rowsCount == -1) // dataModel->setRowCount(row + 1); // dataModel->setItem(0, i - firstValueIndex + row, new QStandardItem(value)); // } } else { //TODO } //notify about the new result emit q->changed(); RESET_CURSOR; } void PivotTablePrivate::createDb() { for (auto* col : dataSourceSpreadsheet->children()) { if (col->isNumeric()) measures << col->name(); else dimensions << col->name(); } PERFTRACE("export spreadsheet to SQLite database"); QApplication::processEvents(QEventLoop::AllEvents, 0); //create database const QStringList& drivers = QSqlDatabase::drivers(); QString driver; if (drivers.contains(QLatin1String("QSQLITE3"))) driver = QLatin1String("QSQLITE3"); else driver = QLatin1String("QSQLITE"); QSqlDatabase db = QSqlDatabase::addDatabase(driver); db.open(); //create table const int cols = dataSourceSpreadsheet->columnCount(); QString query = QLatin1String("create table ") + QLatin1String("pivot") + QLatin1String(" ("); for (int i = 0; i < cols; ++i) { Column* col = dataSourceSpreadsheet->column(i); if (i != 0) query += QLatin1String(", "); query += QLatin1String("\"") + col->name() + QLatin1String("\" "); switch (col->columnMode()) { case AbstractColumn::Numeric: query += QLatin1String("REAL"); break; case AbstractColumn::Integer: query += QLatin1String("INTEGER"); break; case AbstractColumn::Text: case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: query += QLatin1String("TEXT"); break; } } query += QLatin1Char(')'); QSqlQuery q; if (!q.exec(query)) { RESET_CURSOR; KMessageBox::error(nullptr, i18n("Failed to create the SQLite database.") + "\n" + q.lastError().databaseText()); db.close(); return; } //create bulk insert statement { PERFTRACE("Create the bulk insert statement"); q.exec(QLatin1String("BEGIN TRANSACTION;")); query = "INSERT INTO '" + QLatin1String("pivot") + "' ("; for (int i = 0; i < cols; ++i) { if (i != 0) query += QLatin1String(", "); query += QLatin1Char('\'') + dataSourceSpreadsheet->column(i)->name() + QLatin1Char('\''); } query += QLatin1String(") VALUES "); for (int i = 0; i < dataSourceSpreadsheet->rowCount(); ++i) { if (i != 0) query += QLatin1String(","); query += QLatin1Char('('); for (int j = 0; j < cols; ++j) { Column* col = dataSourceSpreadsheet->column(j); if (j != 0) query += QLatin1String(", "); QString text = col->asStringColumn()->textAt(i); text = text.replace("'", "''"); query += QLatin1Char('\'') + text + QLatin1Char('\''); } query += QLatin1String(")"); } query += QLatin1Char(';'); } //insert values if (!q.exec(query)) { RESET_CURSOR; KMessageBox::error(nullptr, i18n("Failed to insert values into the table.")); QDEBUG(query); QDEBUG("bulk insert error " << q.lastError().databaseText()); } else q.exec(QLatin1String("COMMIT TRANSACTION;")); m_dbCreated = true; } //############################################################################## //################## Serialization/Deserialization ########################### //############################################################################## /*! Saves as XML. */ void PivotTable::save(QXmlStreamWriter* writer) const { writer->writeStartElement("pivotTable"); writeBasicAttributes(writer); writeCommentElement(writer); //TODO: writer->writeEndElement(); } /*! Loads from XML. */ bool PivotTable::load(XmlStreamReader* reader, bool preview) { Q_UNUSED(preview); if (!readBasicAttributes(reader)) return false; //TODO: return !reader->hasError(); } diff --git a/src/kdefrontend/pivot/HierarchicalHeaderView.cpp b/src/kdefrontend/pivot/HierarchicalHeaderView.cpp index 09236b144..41e4b9493 100755 --- a/src/kdefrontend/pivot/HierarchicalHeaderView.cpp +++ b/src/kdefrontend/pivot/HierarchicalHeaderView.cpp @@ -1,632 +1,705 @@ /* Copyright 2016 Lee Cho Kang. * email: pzesseto@gmail.com * This file is part of the HierarchicalHeaderView. * * The HierarchicalHeaderView is free software: you can redistribute it * and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * The HierarchicalHeaderView is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with the HierarchicalHeaderView. If not, see http://www.gnu.org/licenses/. */ /* * HierarchicalHeaderView.h * Created on: 2016. 6. 13. */ #include "HierarchicalHeaderView.h" #include #include #include #include #include #include +#include + HierarchicalHeaderItem::HierarchicalHeaderItem(HierarchicalHeaderItem* parent): row_prop(0),column_prop(0),parent_item(parent) { } HierarchicalHeaderItem::HierarchicalHeaderItem(int arow, int acolumn, HierarchicalHeaderItem* parent): row_prop(arow),column_prop(acolumn),parent_item(parent) { } HierarchicalHeaderItem::~HierarchicalHeaderItem() = default; HierarchicalHeaderItem* HierarchicalHeaderItem::insertChild(int row, int col) { HierarchicalHeaderItem* newChild = new HierarchicalHeaderItem(row,col,this); child_items.insert(QPair(row,col),newChild); return newChild; } const HierarchicalHeaderItem* HierarchicalHeaderItem::child(int row,int col) const { QHash,HierarchicalHeaderItem*>::const_iterator itr = child_items.find(QPair(row,col)); if (itr != child_items.end()) return itr.value(); - return 0; + return nullptr; } HierarchicalHeaderItem* HierarchicalHeaderItem::child(int row,int col) { QHash,HierarchicalHeaderItem*>::iterator itr = child_items.find(QPair(row,col)); if (itr != child_items.end()) return itr.value(); - return 0; + return nullptr; } void HierarchicalHeaderItem::setText(const QString& text) { role_datas.insert(Qt::DisplayRole,text); } QVariant HierarchicalHeaderItem::data(int role) const { QHash::const_iterator itr = role_datas.find(role); if (itr != role_datas.end()) return itr.value(); return QVariant(); } void HierarchicalHeaderItem::setData(const QVariant& data, int role) { role_datas.insert(role,data); } int HierarchicalHeaderItem::column() const { return column_prop; } int HierarchicalHeaderItem::row() const { return row_prop; } HierarchicalHeaderItem* HierarchicalHeaderItem::parent() { return parent_item; } void HierarchicalHeaderItem::clear() { QList items = child_items.values(); foreach (HierarchicalHeaderItem* item, child_items) { - if (item) delete item; + if (item) { + delete item; + } } child_items.clear(); } -//########### +/********************************************************************************************** + * MODEL IMPLEMENTATION + * + * ********************************************************************************************/ HierarchicalHeaderModel::HierarchicalHeaderModel(QObject* parent) : QAbstractTableModel(parent), m_rootItem(new HierarchicalHeaderItem()) { } HierarchicalHeaderModel::HierarchicalHeaderModel(int rows, int cols, QObject* parent) : QAbstractTableModel(parent),m_rowCount(rows),m_columnCount(cols),m_rootItem(new HierarchicalHeaderItem()) { + maxWidthArr = new int[m_columnCount]; + for(int col=0; colclear(); delete m_rootItem; + delete maxWidthArr; +} + +void HierarchicalHeaderModel::setBaseSectionSize(QSize size) +{ + + baseSectionSize = size; + + if(orientation == Qt::Vertical){ + for (int row=0;rowsetData(this->index(row,col),baseSectionSize,Qt::SizeHintRole); + } + return; + } + + for (int row=0;rowsetData(this->index(row,col),baseSectionSize,Qt::SizeHintRole); + } +} + +void HierarchicalHeaderModel::setOrientation(Qt::Orientation orient) +{ + orientation = orient; } QModelIndex HierarchicalHeaderModel::index(int row, int column, const QModelIndex & parent) const { if (!hasIndex(row,column,parent)) return QModelIndex(); HierarchicalHeaderItem* parentItem; if (!parent.isValid()) parentItem = m_rootItem; // parent item is always the m_rootItem on table model else parentItem = static_cast(parent.internalPointer()); // no effect HierarchicalHeaderItem* childItem = parentItem->child(row,column); if (!childItem) childItem = parentItem->insertChild(row,column); return createIndex(row,column,childItem); - return QModelIndex(); } void HierarchicalHeaderModel::setRowCount(int count) { m_rowCount = count; // if (horizontalHeaderModel->rowCount() > 1) // horizontalHeaderModel->removeRows(1, horizontalHeaderModel->rowCount() - 1); // else if (horizontalHeaderModel->rowCount() < 1) // horizontalHeaderModel->insertRows(0, 1); } void HierarchicalHeaderModel::setColumnCount(int count) { m_columnCount = count; + + maxWidthArr = new int[m_columnCount]; + for(int col=0; colindex(row, column); if (rowSpanCount > 0) setData(index, rowSpanCount, ROW_SPAN_ROLE); if (columnSpanCount) setData(index, columnSpanCount, COLUMN_SPAN_ROLE); } int HierarchicalHeaderModel::rowCount(const QModelIndex& parent) const { Q_UNUSED(parent); return m_rowCount; } int HierarchicalHeaderModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); return m_columnCount; } QVariant HierarchicalHeaderModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); if (index.row() >= m_rowCount || index.row() < 0 || index.column() >= m_columnCount || index.column() < 0) return QVariant(); HierarchicalHeaderItem* item = static_cast(index.internalPointer()); return item->data(role); } bool HierarchicalHeaderModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (index.isValid()) { HierarchicalHeaderItem* item = static_cast(index.internalPointer()); if (role == COLUMN_SPAN_ROLE) { int col = index.column(); int span = value.toInt(); if (span > 0) { // span size should be more than 1, else nothing to do if (col+span-1 >= m_columnCount) // span size should be less than whole columns, span = m_columnCount-col; item->setData(span,COLUMN_SPAN_ROLE); } } else if (role == ROW_SPAN_ROLE) { int row = index.row(); int span = value.toInt(); if (span > 0) { // span size should be more than 1, else nothing to do if (row+span-1 >= m_rowCount) span = m_rowCount-row; item->setData(span,ROW_SPAN_ROLE); } - } else + } + else if (role == Qt::DisplayRole || role == Qt::EditRole){ + item->setData(value, role); + if(orientation == Qt::Vertical) + { + int width = value.toString().length()*10; + int col = index.column(); + if(width > maxWidthArr[col]) + maxWidthArr[col] = width; + } + } + else item->setData(value,role); return true; } return false; } Qt::ItemFlags HierarchicalHeaderModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::ItemIsEnabled; return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; } void HierarchicalHeaderModel::clear() { +// setRowCount(0); +// setColumnCount(0); +// m_rootItem->clear(); } -//######################### +/********************************************************************************************** + * VIEW IMPLEMENTATION + * + * ********************************************************************************************/ HierarchicalHeaderView::HierarchicalHeaderView(Qt::Orientation orientation, int rows, int columns, QWidget* parent): QHeaderView(orientation,parent) { QSize baseSectionSize; if (orientation == Qt::Horizontal) { baseSectionSize.setWidth(defaultSectionSize()); baseSectionSize.setHeight(20); } else { baseSectionSize.setWidth(50); baseSectionSize.setHeight(defaultSectionSize()); } // create header model HierarchicalHeaderModel* headerModel = new HierarchicalHeaderModel(rows,columns); // set default size of item for (int row=0; rowsetData(headerModel->index(row,col),baseSectionSize,Qt::SizeHintRole); setModel(headerModel); connect(this, SIGNAL(sectionResized(int, int, int)), this, SLOT(onSectionResized(int,int,int))); } HierarchicalHeaderView::HierarchicalHeaderView(Qt::Orientation orientation, QWidget* parent): QHeaderView(orientation,parent) { - QSize baseSectionSize; if (orientation == Qt::Horizontal) { baseSectionSize.setWidth(defaultSectionSize()); baseSectionSize.setHeight(20); } else { baseSectionSize.setWidth(50); baseSectionSize.setHeight(defaultSectionSize()); } m_model = new HierarchicalHeaderModel(); setModel(m_model); connect(this, SIGNAL(sectionResized(int, int, int)), this, SLOT(onSectionResized(int,int,int))); } HierarchicalHeaderView::~HierarchicalHeaderView() = default; + +QSize HierarchicalHeaderView::getBaseSectionSize() const +{ + return baseSectionSize; +} + +void HierarchicalHeaderView::setNewModel(HierarchicalHeaderModel* model) +{ + m_model = model; + setModel(m_model); +} + HierarchicalHeaderModel* HierarchicalHeaderView::hierarchicalModel() const { return m_model; } + + void HierarchicalHeaderView::setRowHeight(int row, int rowHeight) { const int cols = m_model->columnCount(); for (int col = 0; col < cols; ++col) { QSize size = m_model->index(row,col).data(Qt::SizeHintRole).toSize(); size.setHeight(rowHeight); m_model->setData(m_model->index(row, col), size, Qt::SizeHintRole); } if (orientation() == Qt::Vertical) resizeSection(row, rowHeight); } void HierarchicalHeaderView::setColumnWidth(int col, int colWidth) { const int rows = m_model->rowCount(); for (int row = 0; row < rows; ++row) { QSize size = m_model->index(row,col).data(Qt::SizeHintRole).toSize(); size.setWidth(colWidth); m_model->setData(m_model->index(row,col), size, Qt::SizeHintRole); } if (orientation() == Qt::Horizontal) resizeSection(col, colWidth); } void HierarchicalHeaderView::setCellBackgroundColor(const QModelIndex& index, const QColor& color) { m_model->setData(index, color, Qt::BackgroundRole); } void HierarchicalHeaderView::setCellForegroundColor(const QModelIndex& index, const QColor& color) { m_model->setData(index, color, Qt::ForegroundRole); } void HierarchicalHeaderView::mousePressEvent(QMouseEvent* event) { QHeaderView::mousePressEvent(event); QPoint pos = event->pos(); QModelIndex index = indexAt(pos); const int OTN = orientation(); if (index.isValid()) { int beginSection = -1; int endSection = -1; int numbers = 0; numbers = getSectionRange(index,&beginSection,&endSection); if (numbers > 0) { emit sectionPressed(beginSection,endSection); return; } else { const int LEVEL_CNT = (OTN == Qt::Horizontal)?m_model->rowCount():m_model->columnCount(); int logicalIdx = (OTN == Qt::Horizontal)?index.column():index.row(); int curLevel = (OTN == Qt::Horizontal)?index.row():index.column(); for (int i=0; iindex(i,logicalIdx):m_model->index(logicalIdx,i); numbers = getSectionRange(cellIndex,&beginSection,&endSection); if (numbers > 0) { if (beginSection <= logicalIdx && logicalIdx <= endSection) { int beginLevel = (OTN == Qt::Horizontal)?cellIndex.row():cellIndex.column(); QVariant levelSpanCnt = cellIndex.data((OTN == Qt::Horizontal)?ROW_SPAN_ROLE:COLUMN_SPAN_ROLE); if (!levelSpanCnt.isValid()) continue; int endLevel = beginLevel + levelSpanCnt.toInt()-1; if (beginLevel <= curLevel && curLevel <= endLevel) { emit sectionPressed(beginSection,endSection); break; } } } } } } } QModelIndex HierarchicalHeaderView::indexAt(const QPoint& pos) const { const int OTN = orientation(); const int ROWS = m_model->rowCount(); const int COLS = m_model->columnCount(); int logicalIdx = logicalIndexAt(pos); if (OTN == Qt::Horizontal) { int dY=0; for (int row=0; rowindex(row,logicalIdx); dY += cellIndex.data(Qt::SizeHintRole).toSize().height(); if (pos.y() <= dY) return cellIndex; } } else { int dX=0; for (int col=0; colindex(logicalIdx,col); dX += cellIndex.data(Qt::SizeHintRole).toSize().width(); if (pos.x() <= dX) return cellIndex; } } return QModelIndex(); } void HierarchicalHeaderView::paintSection(QPainter* painter, const QRect& rect, int logicalIdx) const { const int OTN = orientation(); const int LEVEL_CNT = (OTN == Qt::Horizontal)?m_model->rowCount():m_model->columnCount(); for (int i=0; iindex(i,logicalIdx):m_model->index(logicalIdx,i); QSize cellSize=cellIndex.data(Qt::SizeHintRole).toSize(); QRect sectionRect(rect); // set position of the cell if (OTN == Qt::Horizontal) sectionRect.setTop(rowSpanSize(logicalIdx,0,i)); // distance from 0 to i-1 rows else sectionRect.setLeft(columnSpanSize(logicalIdx,0,i)); sectionRect.setSize(cellSize); // check up span column or row QModelIndex colSpanIdx = columnSpanIndex(cellIndex); QModelIndex rowSpanIdx = rowSpanIndex(cellIndex); if (colSpanIdx.isValid()) { int colSpanFrom = colSpanIdx.column(); int colSpanCnt = colSpanIdx.data(COLUMN_SPAN_ROLE).toInt(); int colSpanTo = colSpanFrom+colSpanCnt-1; int colSpan = columnSpanSize(cellIndex.row(),colSpanFrom,colSpanCnt); if (OTN == Qt::Horizontal) sectionRect.setLeft(sectionViewportPosition(colSpanFrom)); else { sectionRect.setLeft(columnSpanSize(logicalIdx,0,colSpanFrom)); i = colSpanTo; } sectionRect.setWidth(colSpan); // check up if the column span index has row span QVariant subRowSpanData = colSpanIdx.data(ROW_SPAN_ROLE); if (subRowSpanData.isValid()) { int subRowSpanFrom = colSpanIdx.row(); int subRowSpanCnt = subRowSpanData.toInt(); int subRowSpanTo = subRowSpanFrom+subRowSpanCnt-1; int subRowSpan = rowSpanSize(colSpanFrom,subRowSpanFrom,subRowSpanCnt); if (OTN == Qt::Vertical) sectionRect.setTop(sectionViewportPosition(subRowSpanFrom)); else { sectionRect.setTop(rowSpanSize(colSpanFrom,0,subRowSpanFrom)); i = subRowSpanTo; } sectionRect.setHeight(subRowSpan); } cellIndex=colSpanIdx; } if (rowSpanIdx.isValid()) { int rowSpanFrom = rowSpanIdx.row(); int rowSpanCnt = rowSpanIdx.data(ROW_SPAN_ROLE).toInt(); int rowSpanTo = rowSpanFrom+rowSpanCnt-1; int rowSpan = rowSpanSize(cellIndex.column(),rowSpanFrom,rowSpanCnt); if (OTN == Qt::Vertical) sectionRect.setTop(sectionViewportPosition(rowSpanFrom)); else { sectionRect.setTop(rowSpanSize(logicalIdx,0,rowSpanFrom)); i = rowSpanTo; } sectionRect.setHeight(rowSpan); // check up if the row span index has column span QVariant subColSpanData = rowSpanIdx.data(COLUMN_SPAN_ROLE); if (subColSpanData.isValid()) { int subColSpanFrom = rowSpanIdx.column(); int subColSpanCnt = subColSpanData.toInt(); int subColSpanTo = subColSpanFrom+subColSpanCnt-1; int subColSpan = columnSpanSize(rowSpanFrom,subColSpanFrom,subColSpanCnt); if (OTN == Qt::Horizontal) sectionRect.setLeft(sectionViewportPosition(subColSpanFrom)); else { sectionRect.setLeft(columnSpanSize(rowSpanFrom,0,subColSpanFrom)); i = subColSpanTo; } sectionRect.setWidth(subColSpan); } cellIndex=rowSpanIdx; } // draw section with style QStyleOptionHeader sectionStyle; initStyleOption(§ionStyle); sectionStyle.textAlignment = Qt::AlignCenter; sectionStyle.iconAlignment = Qt::AlignVCenter; sectionStyle.section = logicalIdx; sectionStyle.text = cellIndex.data(Qt::DisplayRole).toString(); sectionStyle.rect = sectionRect; // file background or foreground color of the cell QVariant bg = cellIndex.data(Qt::BackgroundRole); QVariant fg = cellIndex.data(Qt::ForegroundRole); if (bg.canConvert()) { QBrush bgBrush = bg.value(); sectionStyle.palette.setBrush(QPalette::Button, bgBrush); sectionStyle.palette.setBrush(QPalette::Window, bgBrush); } if (fg.canConvert()) sectionStyle.palette.setBrush(QPalette::ButtonText, fg.value()); painter->save(); qDrawShadePanel(painter,sectionStyle.rect,sectionStyle.palette,false,1,§ionStyle.palette.brush(QPalette::Button)); style()->drawControl(QStyle::CE_HeaderLabel, §ionStyle, painter); painter->restore(); } } QSize HierarchicalHeaderView::sectionSizeFromContents(int logicalIndex) const { const int OTN = orientation(); const int LEVEL_CNT = (OTN == Qt::Horizontal)?m_model->rowCount():m_model->columnCount(); QSize siz = QHeaderView::sectionSizeFromContents(logicalIndex); for (int i=0; iindex(i,logicalIndex):m_model->index(logicalIndex,i); QModelIndex colSpanIdx = columnSpanIndex(cellIndex); QModelIndex rowSpanIdx = rowSpanIndex(cellIndex); siz=cellIndex.data(Qt::SizeHintRole).toSize(); if (colSpanIdx.isValid()) { int colSpanFrom = colSpanIdx.column(); int colSpanCnt = colSpanIdx.data(COLUMN_SPAN_ROLE).toInt(); int colSpanTo = colSpanFrom + colSpanCnt -1; siz.setWidth(columnSpanSize(colSpanIdx.row(),colSpanFrom,colSpanCnt)); if (OTN == Qt::Vertical) i = colSpanTo; } if (rowSpanIdx.isValid()) { int rowSpanFrom = rowSpanIdx.row(); int rowSpanCnt = rowSpanIdx.data(ROW_SPAN_ROLE).toInt(); int rowSpanTo = rowSpanFrom + rowSpanCnt-1; siz.setHeight(rowSpanSize(rowSpanIdx.column(),rowSpanFrom,rowSpanCnt)); if (OTN == Qt::Horizontal) i = rowSpanTo; } } return siz; } QModelIndex HierarchicalHeaderView::columnSpanIndex(const QModelIndex& currentIdx) const { const int curRow = currentIdx.row(); const int curCol = currentIdx.column(); int i = curCol; while (i >= 0) { QModelIndex spanIndex = m_model->index(curRow,i); QVariant span = spanIndex.data(COLUMN_SPAN_ROLE); if (span.isValid() && spanIndex.column()+span.toInt()-1 >= curCol) return spanIndex; i--; } return QModelIndex(); } QModelIndex HierarchicalHeaderView::rowSpanIndex(const QModelIndex& currentIdx) const { const int curRow = currentIdx.row(); const int curCol = currentIdx.column(); int i = curRow; while (i >= 0) { QModelIndex spanIndex = m_model->index(i,curCol); QVariant span = spanIndex.data(ROW_SPAN_ROLE); if (span.isValid() && spanIndex.row()+span.toInt()-1 >= curRow) return spanIndex; i--; } return QModelIndex(); } int HierarchicalHeaderView::columnSpanSize(int row, int from, int spanCount) const { int span = 0; for (int i=from; iindex(row,i).data(Qt::SizeHintRole).toSize(); span += cellSize.width(); } return span; } int HierarchicalHeaderView::rowSpanSize(int column, int from, int spanCount) const { int span = 0; for (int i=from; iindex(i,column).data(Qt::SizeHintRole).toSize(); span += cellSize.height(); } return span; } /** * @return section numbers */ int HierarchicalHeaderView::getSectionRange(QModelIndex& index, int* beginSection, int* endSection) const { // check up section range from the index QModelIndex colSpanIdx = columnSpanIndex(index); QModelIndex rowSpanIdx = rowSpanIndex(index); if (colSpanIdx.isValid()) { int colSpanFrom = colSpanIdx.column(); int colSpanCnt = colSpanIdx.data(COLUMN_SPAN_ROLE).toInt(); int colSpanTo = colSpanFrom+colSpanCnt-1; if (orientation() == Qt::Horizontal) { *beginSection = colSpanFrom; *endSection = colSpanTo; index = colSpanIdx; return colSpanCnt; } else { // check up if the column span index has row span QVariant subRowSpanData = colSpanIdx.data(ROW_SPAN_ROLE); if (subRowSpanData.isValid()) { int subRowSpanFrom = colSpanIdx.row(); int subRowSpanCnt = subRowSpanData.toInt(); int subRowSpanTo = subRowSpanFrom+subRowSpanCnt-1; *beginSection = subRowSpanFrom; *endSection = subRowSpanTo; index = colSpanIdx; return subRowSpanCnt; } } } if (rowSpanIdx.isValid()) { int rowSpanFrom = rowSpanIdx.row(); int rowSpanCnt = rowSpanIdx.data(ROW_SPAN_ROLE).toInt(); int rowSpanTo = rowSpanFrom+rowSpanCnt-1; if (orientation() == Qt::Vertical) { *beginSection = rowSpanFrom; *endSection = rowSpanTo; index = rowSpanIdx; return rowSpanCnt; } else { // check up if the row span index has column span QVariant subColSpanData = rowSpanIdx.data(COLUMN_SPAN_ROLE); if (subColSpanData.isValid()) { int subColSpanFrom = rowSpanIdx.column(); int subColSpanCnt = subColSpanData.toInt(); int subColSpanTo = subColSpanFrom+subColSpanCnt-1; *beginSection = subColSpanFrom; *endSection = subColSpanTo; index = rowSpanIdx; return subColSpanCnt; } } } return 0; } void HierarchicalHeaderView::onSectionResized(int logicalIndex,int oldSize,int newSize) { - if (!m_model) + Q_UNUSED(oldSize); + + if (!m_model) return; const int OTN = orientation(); const int LEVEL_CNT = (OTN == Qt::Horizontal)?m_model->rowCount():m_model->columnCount(); int pos = sectionViewportPosition(logicalIndex); int xx = (OTN == Qt::Horizontal)?pos:0; int yy = (OTN == Qt::Horizontal)?0:pos; QRect sectionRect(xx,yy,0,0); for (int i=0; iindex(i,logicalIndex):m_model->index(logicalIndex,i); QSize cellSize=cellIndex.data(Qt::SizeHintRole).toSize(); // set position of cell if (OTN == Qt::Horizontal) { sectionRect.setTop(rowSpanSize(logicalIndex,0,i)); cellSize.setWidth(newSize); } else { sectionRect.setLeft(columnSpanSize(logicalIndex,0,i)); cellSize.setHeight(newSize); } m_model->setData(cellIndex,cellSize,Qt::SizeHintRole); QModelIndex colSpanIdx = columnSpanIndex(cellIndex); QModelIndex rowSpanIdx = rowSpanIndex(cellIndex); if (colSpanIdx.isValid()) { int colSpanFrom = colSpanIdx.column(); if (OTN == Qt::Horizontal) sectionRect.setLeft(sectionViewportPosition(colSpanFrom)); else sectionRect.setLeft(columnSpanSize(logicalIndex,0,colSpanFrom)); } if (rowSpanIdx.isValid()) { int rowSpanFrom = rowSpanIdx.row(); if (OTN == Qt::Vertical) sectionRect.setTop(sectionViewportPosition(rowSpanFrom)); else sectionRect.setTop(rowSpanSize(logicalIndex,0,rowSpanFrom)); } QRect rToUpdate(sectionRect); rToUpdate.setWidth(viewport()->width()-sectionRect.left()); rToUpdate.setHeight(viewport()->height()-sectionRect.top()); viewport()->update(rToUpdate.normalized()); } } diff --git a/src/kdefrontend/pivot/HierarchicalHeaderView.h b/src/kdefrontend/pivot/HierarchicalHeaderView.h index 398c80805..abd18e06b 100755 --- a/src/kdefrontend/pivot/HierarchicalHeaderView.h +++ b/src/kdefrontend/pivot/HierarchicalHeaderView.h @@ -1,129 +1,148 @@ /* Copyright 2016 Lee Cho Kang. * email: pzesseto@gmail.com * This file is part of the HierarchicalHeaderView. * * The HierarchicalHeaderView is free software: you can redistribute it * and/or modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * The HierarchicalHeaderView is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with the HierarchicalHeaderView. If not, see http://www.gnu.org/licenses/. */ /* * HierarchicalHeaderView.h * Created on: 2016. 6. 13. */ #ifndef HIERARCHICALHEADERVIEW_H #define HIERARCHICALHEADERVIEW_H #include #include #include #include #include enum eRbHeaderRole { - COLUMN_SPAN_ROLE = Qt::UserRole+1, - ROW_SPAN_ROLE, - COLUMN_SIZE_ROLE, - ROW_SIZE_ROLE, + COLUMN_SPAN_ROLE = Qt::UserRole+1, + ROW_SPAN_ROLE, + COLUMN_SIZE_ROLE, + ROW_SIZE_ROLE, }; class HierarchicalHeaderItem { public: HierarchicalHeaderItem(HierarchicalHeaderItem* parent = nullptr); HierarchicalHeaderItem(int row, int column, HierarchicalHeaderItem* parent = nullptr); ~HierarchicalHeaderItem(); HierarchicalHeaderItem* insertChild(int row, int col); const HierarchicalHeaderItem* child(int row,int col) const; HierarchicalHeaderItem* child(int row,int col); void setData(const QVariant& data, int role); QVariant data(int role=Qt::UserRole+1) const; int column() const; int row() const; HierarchicalHeaderItem* parent(); void setText(const QString&); void clear(); private: int row_prop; int column_prop; HierarchicalHeaderItem* parent_item; QHash,HierarchicalHeaderItem*> child_items; QHash role_datas; }; +/**************************************************************************************************** + * + * MODEL DECLARATIONS + * *************************************************************************************************/ class HierarchicalHeaderModel: public QAbstractTableModel { Q_OBJECT public: HierarchicalHeaderModel(QObject* parent = nullptr); HierarchicalHeaderModel(int rows, int cols, QObject* parent = nullptr); virtual ~HierarchicalHeaderModel(); public: void setRowCount(int); void setColumnCount(int); void setSpan(int row, int column, int rowSpanCount, int columnSpanCount); QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent=QModelIndex()) const override; int columnCount(const QModelIndex &parent=QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex &index) const override; void clear(); + void setBaseSectionSize(QSize size); + void setOrientation(Qt::Orientation orient); private: int m_rowCount{0}; int m_columnCount{0}; HierarchicalHeaderItem* m_rootItem{nullptr}; + + int *maxWidthArr; + QSize baseSectionSize; + Qt::Orientation orientation; }; +/**************************************************************************************************** + * + * VIEW DECLARATIONS + * *************************************************************************************************/ + class HierarchicalHeaderView : public QHeaderView { Q_OBJECT public: HierarchicalHeaderView(Qt::Orientation orientation, QWidget* parent = nullptr); HierarchicalHeaderView(Qt::Orientation orientation, int rows, int columns, QWidget* parent = nullptr); ~HierarchicalHeaderView() override; HierarchicalHeaderModel* hierarchicalModel() const; void setRowHeight(int row, int height); void setColumnWidth(int col, int width); void setCellBackgroundColor(const QModelIndex&, const QColor&); void setCellForegroundColor(const QModelIndex&, const QColor&); + QSize getBaseSectionSize() const; + void setNewModel(HierarchicalHeaderModel* model); + protected: void mousePressEvent(QMouseEvent*) override; QModelIndex indexAt(const QPoint&) const override; void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const override; QSize sectionSizeFromContents(int logicalIndex) const override; QModelIndex columnSpanIndex(const QModelIndex&) const; QModelIndex rowSpanIndex(const QModelIndex&) const; int columnSpanSize(int row, int from, int spanCount) const; int rowSpanSize(int column, int from, int spanCount) const; int getSectionRange(QModelIndex& index, int* beginSection, int* endSection) const; protected slots: void onSectionResized(int logicalIndex,int oldSize,int newSize); signals: void sectionPressed(int from, int to); private: HierarchicalHeaderModel* m_model{nullptr}; + QSize baseSectionSize; }; #endif diff --git a/src/kdefrontend/pivot/PivotTableView.cpp b/src/kdefrontend/pivot/PivotTableView.cpp index 38cb37ce1..c6493c8ce 100644 --- a/src/kdefrontend/pivot/PivotTableView.cpp +++ b/src/kdefrontend/pivot/PivotTableView.cpp @@ -1,208 +1,224 @@ /*************************************************************************** File : PivotTableView.cpp Project : LabPlot Description : View class for PivotTable -------------------------------------------------------------------- Copyright : (C) 2019 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "PivotTableView.h" #include "HierarchicalHeaderView.h" #include "backend/pivot/PivotTable.h" #include "backend/lib/macros.h" #include "backend/lib/trace.h" #include #include #include #include #include #include #include #include #include #include #include #include +#include + /*! \class PivotTableView \brief View class for PivotTable \ingroup commonfrontend */ PivotTableView::PivotTableView(PivotTable* pivotTable, bool readOnly) : QWidget(), m_pivotTable(pivotTable), m_tableView(new QTableView(this)), m_horizontalHeaderView(new HierarchicalHeaderView(Qt::Horizontal, m_tableView)), m_verticalHeaderView(new HierarchicalHeaderView(Qt::Vertical, m_tableView)), m_readOnly(readOnly) { auto* layout = new QHBoxLayout(this); layout->setContentsMargins(0,0,0,0); layout->addWidget(m_tableView); m_tableView->setSelectionMode(QAbstractItemView::ExtendedSelection); if (m_readOnly) m_tableView->setEditTriggers(QTableView::NoEditTriggers); m_tableView->setHorizontalHeader(m_horizontalHeaderView); m_horizontalHeaderView->setHighlightSections(true); m_horizontalHeaderView->setSectionResizeMode(QHeaderView::ResizeToContents); m_horizontalHeaderView->setSectionsClickable(true); m_tableView->setVerticalHeader(m_verticalHeaderView); m_verticalHeaderView->setHighlightSections(true); m_verticalHeaderView->setSectionResizeMode(QHeaderView::ResizeToContents); m_verticalHeaderView->setSectionsClickable(true); init(); } PivotTableView::~PivotTableView() = default; void PivotTableView::init() { initActions(); initMenus(); //models //TODO: at the moment we keep the data model in m_pivotTable, the header models are kept in HierarchicalHeaderView. //re-design this. Let's keep all the models in m_pivotTable and set them here for the views. m_tableView->setModel(m_pivotTable->dataModel()); m_pivotTable->setHorizontalHeaderModel(m_horizontalHeaderView->hierarchicalModel()); m_pivotTable->setVerticalHeaderModel(m_verticalHeaderView->hierarchicalModel()); connect(m_pivotTable, &PivotTable::changed, this, &PivotTableView::changed); } void PivotTableView::initActions() { } void PivotTableView::initMenus() { } void PivotTableView::connectActions() { } void PivotTableView::fillToolBar(QToolBar* toolBar) { Q_UNUSED(toolBar); } /*! * Populates the menu \c menu with the pivot table and pivot table view relevant actions. * The menu is used * - as the context menu in PivotTableView * - as the "pivot table menu" in the main menu-bar (called form MainWin) * - as a part of the pivot table context menu in project explorer */ void PivotTableView::createContextMenu(QMenu* menu) { Q_ASSERT(menu); } void PivotTableView::goToCell() { bool ok; int col = QInputDialog::getInt(nullptr, i18n("Go to Cell"), i18n("Enter column"), 1, 1, m_tableView->model()->columnCount(), 1, &ok); if (!ok) return; int row = QInputDialog::getInt(nullptr, i18n("Go to Cell"), i18n("Enter row"), 1, 1, m_tableView->model()->rowCount(), 1, &ok); if (!ok) return; goToCell(row-1, col-1); } void PivotTableView::goToCell(int row, int col) { QModelIndex index = m_tableView->model()->index(row, col); m_tableView->scrollTo(index); m_tableView->setCurrentIndex(index); } bool PivotTableView::exportView() { return true; } bool PivotTableView::printView() { QPrinter printer; auto* dlg = new QPrintDialog(&printer, this); dlg->setWindowTitle(i18nc("@title:window", "Print Spreadsheet")); bool ret; if ((ret = dlg->exec()) == QDialog::Accepted) { print(&printer); } delete dlg; return ret; } bool PivotTableView::printPreview() { QPrintPreviewDialog* dlg = new QPrintPreviewDialog(this); connect(dlg, &QPrintPreviewDialog::paintRequested, this, &PivotTableView::print); return dlg->exec(); } /*! prints the complete spreadsheet to \c printer. */ void PivotTableView::print(QPrinter* printer) const { WAIT_CURSOR; QPainter painter (printer); RESET_CURSOR; } void PivotTableView::changed() { -} + qDebug() << "in PivotTableView::changed()"; + HierarchicalHeaderModel* horizontalHeaderModel = static_cast(m_horizontalHeaderView->hierarchicalModel()); + HierarchicalHeaderModel* verticalHeaderModel = static_cast(m_verticalHeaderView->hierarchicalModel()); + + horizontalHeaderModel->setOrientation(Qt::Horizontal); + verticalHeaderModel->setOrientation(Qt::Vertical); + +// qDebug() << " setting size for horizontal header"; +// qDebug() << " rows, cols = " << horizontalHeaderModel->rowCount() << ", " << horizontalHeaderModel->columnCount(); + horizontalHeaderModel->setBaseSectionSize(m_horizontalHeaderView->getBaseSectionSize()); + +// qDebug() << "settign size for vertical header"; +// qDebug() << " rows, cols = " << verticalHeaderModel->rowCount() << ", " << verticalHeaderModel->columnCount(); + verticalHeaderModel->setBaseSectionSize(m_verticalHeaderView->getBaseSectionSize()); + } void PivotTableView::exportToFile(const QString& path, const bool exportHeader, const QString& separator, QLocale::Language language) const { Q_UNUSED(exportHeader); Q_UNUSED(separator); Q_UNUSED(language); QFile file(path); if (!file.open(QFile::WriteOnly | QFile::Truncate)) return; PERFTRACE("export pivot table to file"); } void PivotTableView::exportToLaTeX(const QString & path, const bool exportHeaders, const bool gridLines, const bool captions, const bool latexHeaders, const bool skipEmptyRows, const bool exportEntire) const { Q_UNUSED(exportHeaders); Q_UNUSED(gridLines); Q_UNUSED(captions); Q_UNUSED(latexHeaders); Q_UNUSED(skipEmptyRows); Q_UNUSED(exportEntire); QFile file(path); if (!file.open(QFile::WriteOnly | QFile::Truncate)) return; PERFTRACE("export pivot table to latex"); }