/************************************************************************ ** ** @file dialogmdatabase.cpp ** @author Roman Telezhynskyi ** @date 26 7, 2015 ** ** @brief ** @copyright ** This source code is part of the Valentina project, a pattern making ** program, whose allow create and modeling patterns of clothing. ** Copyright (C) 2015 Valentina project ** All Rights Reserved. ** ** Valentina 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. ** ** Valentina 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 Valentina. If not, see . ** *************************************************************************/ #include "dialogmdatabase.h" #include "ui_dialogmdatabase.h" #include "../mapplication.h" #include "../vpatterndb/measurements.h" #include "../vmisc/compatibility.h" #include #include #include #include //--------------------------------------------------------------------------------------------------------------------- DialogMDataBase::DialogMDataBase(const QStringList &list, QWidget *parent) :QDialog(parent), ui(new Ui::DialogMDataBase), selectMode(true), list(list), groupA(nullptr), groupB(nullptr), groupC(nullptr), groupD(nullptr), groupE(nullptr), groupF(nullptr), groupG(nullptr), groupH(nullptr), groupI(nullptr), groupJ(nullptr), groupK(nullptr), groupL(nullptr), groupM(nullptr), groupN(nullptr), groupO(nullptr), groupP(nullptr), groupQ(nullptr) { ui->setupUi(this); #if defined(Q_OS_MAC) setWindowFlags(Qt::Window); #endif InitDataBase(list); ui->treeWidget->installEventFilter(this); connect(ui->treeWidget, &QTreeWidget::itemChanged, this, &DialogMDataBase::UpdateChecks); connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &DialogMDataBase::ShowDescription); connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, &DialogMDataBase::TreeMenu); connect(ui->lineEditSearch, &QLineEdit::textChanged, this, &DialogMDataBase::FilterMeasurements); ReadSettings(); } //--------------------------------------------------------------------------------------------------------------------- DialogMDataBase::DialogMDataBase(QWidget *parent) :QDialog(parent), ui(new Ui::DialogMDataBase), selectMode(false), list(), groupA(nullptr), groupB(nullptr), groupC(nullptr), groupD(nullptr), groupE(nullptr), groupF(nullptr), groupG(nullptr), groupH(nullptr), groupI(nullptr), groupJ(nullptr), groupK(nullptr), groupL(nullptr), groupM(nullptr), groupN(nullptr), groupO(nullptr), groupP(nullptr), groupQ(nullptr) { ui->setupUi(this); #if defined(Q_OS_MAC) setWindowFlags(Qt::Window); #endif InitDataBase(); ui->treeWidget->installEventFilter(this); connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &DialogMDataBase::ShowDescription); connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, &DialogMDataBase::TreeMenu); connect(ui->treeWidget, &QTreeWidget::itemActivated, this, &DialogMDataBase::ShowDescription); connect(ui->lineEditSearch, &QLineEdit::textChanged, this, &DialogMDataBase::FilterMeasurements); ReadSettings(); } //--------------------------------------------------------------------------------------------------------------------- DialogMDataBase::~DialogMDataBase() { WriteSettings(); delete ui; } //--------------------------------------------------------------------------------------------------------------------- QStringList DialogMDataBase::GetNewNames() const { if (selectMode) { QStringList newNames; QTreeWidgetItemIterator it(ui->treeWidget, QTreeWidgetItemIterator::NoChildren | QTreeWidgetItemIterator::Checked ); while (*it) { const QString name = (*it)->data(0, Qt::UserRole).toString(); if (not list.contains(name)) { newNames.append(name); } ++it; } return newNames; } else { return QStringList(); } } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::RetranslateGroups() { RetranslateGroup(groupA, "A. " + tr("Direct Height", "Measurement section"), ListGroupA()); RetranslateGroup(groupB, "B. " + tr("Direct Width", "Measurement section"), ListGroupB()); RetranslateGroup(groupC, "C. " + tr("Indentation", "Measurement section"), ListGroupC()); RetranslateGroup(groupD, "D. " + tr("Hand", "Measurement section"), ListGroupD()); RetranslateGroup(groupE, "E. " + tr("Foot", "Measurement section"), ListGroupE()); RetranslateGroup(groupF, "F. " + tr("Head", "Measurement section"), ListGroupF()); RetranslateGroup(groupG, "G. " + tr("Circumference and Arc", "Measurement section"), ListGroupG()); RetranslateGroup(groupH, "H. " + tr("Vertical", "Measurement section"), ListGroupH()); RetranslateGroup(groupI, "I. " + tr("Horizontal", "Measurement section"), ListGroupI()); RetranslateGroup(groupJ, "J. " + tr("Bust", "Measurement section"), ListGroupJ()); RetranslateGroup(groupK, "K. " + tr("Balance", "Measurement section"), ListGroupK()); RetranslateGroup(groupL, "L. " + tr("Arm", "Measurement section"), ListGroupL()); RetranslateGroup(groupM, "M. " + tr("Leg", "Measurement section"), ListGroupM()); RetranslateGroup(groupN, "N. " + tr("Crotch and Rise", "Measurement section"), ListGroupN()); RetranslateGroup(groupO, "O. " + tr("Men & Tailoring", "Measurement section"), ListGroupO()); RetranslateGroup(groupP, "P. " + tr("Historical & Specialty", "Measurement section"), ListGroupP()); RetranslateGroup(groupQ, "Q. " + tr("Patternmaking measurements", "Measurement section"), ListGroupQ()); ShowDescription(ui->treeWidget->currentItem(), 0); } //--------------------------------------------------------------------------------------------------------------------- QString DialogMDataBase::ImgTag(const QString &number) { QString imgUrl(""); // In case of error const QString filePath = QString("://diagrams/%1.svg") .arg(MapDiagrams(VAbstractApplication::VApp()->TrVars(), number)); if (QFileInfo::exists(filePath)) { // Load your SVG QSvgRenderer renderer; const bool ok = renderer.load(filePath); if (ok) { const QScreen *screen = QGuiApplication::screens().at(0); if (screen) { const QSize defSize = renderer.defaultSize(); // Prepare a QImage with desired characteritisc QImage image(defSize, QImage::Format_RGB32); image.fill(Qt::white); const QRect geometry = screen->geometry(); const int baseHeight = 1440; const int imgHeight = geometry.height() * defSize.height() / baseHeight; QImage scaledImg = image.scaledToHeight(imgHeight); // Get QPainter that paints to the image QPainter painter(&scaledImg); renderer.render(&painter); QByteArray byteArray; QBuffer buffer(&byteArray); scaledImg.save(&buffer, "PNG"); imgUrl = QString(""; } } } return imgUrl; } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::changeEvent(QEvent *event) { if (event->type() == QEvent::LanguageChange) { // retranslate designer form (single inheritance approach) ui->retranslateUi(this); } // remember to call base class implementation QDialog::changeEvent(event); } //--------------------------------------------------------------------------------------------------------------------- bool DialogMDataBase::eventFilter(QObject *target, QEvent *event) { if (target == ui->treeWidget && event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); switch(keyEvent->key()) { case Qt::Key_Up: { const QModelIndex model = ui->treeWidget->indexAbove(ui->treeWidget->currentIndex()); QTreeWidgetItem *item = ui->treeWidget->itemAbove(ui->treeWidget->currentItem()); ShowDescription(item, model.column()); break; } case Qt::Key_Down: { const QModelIndex model = ui->treeWidget->indexBelow(ui->treeWidget->currentIndex()); QTreeWidgetItem *item = ui->treeWidget->itemBelow(ui->treeWidget->currentItem()); ShowDescription(item, model.column()); break; } default: break; } } return QDialog::eventFilter(target, event); } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::UpdateChecks(QTreeWidgetItem *item, int column) { bool diff = false; if (column != 0 && column != -1) { return; } if (item->childCount() != 0 && item->checkState(0) != Qt::PartiallyChecked && column != -1) { bool flag = false; // Check if we could change atleast one children Qt::CheckState checkState = item->checkState(0); for (int i = 0; i < item->childCount(); ++i) { if (not list.contains(item->child(i)->data(0, Qt::UserRole).toString())) { item->child(i)->setCheckState(0, checkState); flag = true; } if (flag == false) // All child in the list { item->setCheckState(0, Qt::Checked); } } } else if (item->childCount() == 0 || column == -1) { QTreeWidgetItem *parent = item->parent(); if (parent == nullptr) { return; } for (int j = 0; j < parent->childCount(); ++j) { if (j != parent->indexOfChild(item) && item->checkState(0) != parent->child(j)->checkState(0)) { diff = true; } } if (diff) { parent->setCheckState(0, Qt::PartiallyChecked); } else { parent->setCheckState(0, item->checkState(0)); } UpdateChecks(parent, -1); } } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::ShowDescription(QTreeWidgetItem *item, int column) { if ((column != 0 && column != -1) || item == nullptr || item->childCount() != 0) { ui->textEdit->clear(); return; } ui->textEdit->setHtml(ItemFullDescription(item)); } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::TreeMenu(const QPoint &pos) { // Because item also will be selected need to show description const QModelIndex model = ui->treeWidget->currentIndex(); QTreeWidgetItem *item = ui->treeWidget->currentItem(); ShowDescription(item, model.column()); QAction *actionCollapseAll = new QAction(tr("Collapse All"), this); connect(actionCollapseAll, &QAction::triggered, ui->treeWidget, &QTreeWidget::collapseAll); QAction *actionExpandeAll = new QAction(tr("Expand All"), this); connect(actionExpandeAll, &QAction::triggered, ui->treeWidget, &QTreeWidget::expandAll); QMenu menu(this); menu.addAction(actionCollapseAll); menu.addAction(actionExpandeAll); if (selectMode) { QString actionName; GlobalCheckState() == Qt::Checked ? actionName = tr("Check all") : actionName = tr("Uncheck all"); QAction *actionRecheck = new QAction(actionName, this); connect(actionRecheck, &QAction::triggered, this, &DialogMDataBase::Recheck); menu.addAction(actionRecheck); } menu.exec(ui->treeWidget->mapToGlobal(pos)); } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::Recheck() { if (selectMode) { const Qt::CheckState check = GlobalCheckState(); ChangeCheckState(groupA, check); ChangeCheckState(groupB, check); ChangeCheckState(groupC, check); ChangeCheckState(groupD, check); ChangeCheckState(groupE, check); ChangeCheckState(groupF, check); ChangeCheckState(groupG, check); ChangeCheckState(groupH, check); ChangeCheckState(groupI, check); ChangeCheckState(groupJ, check); ChangeCheckState(groupK, check); ChangeCheckState(groupL, check); ChangeCheckState(groupM, check); ChangeCheckState(groupN, check); ChangeCheckState(groupO, check); ChangeCheckState(groupP, check); ChangeCheckState(groupQ, check); } } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::FilterMeasurements(const QString &search) { FilterGroup(groupA, search); FilterGroup(groupB, search); FilterGroup(groupC, search); FilterGroup(groupD, search); FilterGroup(groupE, search); FilterGroup(groupF, search); FilterGroup(groupG, search); FilterGroup(groupH, search); FilterGroup(groupI, search); FilterGroup(groupJ, search); FilterGroup(groupK, search); FilterGroup(groupL, search); FilterGroup(groupM, search); FilterGroup(groupN, search); FilterGroup(groupO, search); FilterGroup(groupP, search); FilterGroup(groupQ, search); const QList list = ui->treeWidget->selectedItems(); list.isEmpty() ? ShowDescription(nullptr, -1) : ShowDescription(ConstFirst(list), 0); } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::InitDataBase(const QStringList &list) { InitGroup(&groupA, "A. " + tr("Direct Height", "Measurement section"), ListGroupA(), list); InitGroup(&groupB, "B. " + tr("Direct Width", "Measurement section"), ListGroupB(), list); InitGroup(&groupC, "C. " + tr("Indentation", "Measurement section"), ListGroupC(), list); InitGroup(&groupD, "D. " + tr("Hand", "Measurement section"), ListGroupD(), list); InitGroup(&groupE, "E. " + tr("Foot", "Measurement section"), ListGroupE(), list); InitGroup(&groupF, "F. " + tr("Head", "Measurement section"), ListGroupF(), list); InitGroup(&groupG, "G. " + tr("Circumference and Arc", "Measurement section"), ListGroupG(), list); InitGroup(&groupH, "H. " + tr("Vertical", "Measurement section"), ListGroupH(), list); InitGroup(&groupI, "I. " + tr("Horizontal", "Measurement section"), ListGroupI(), list); InitGroup(&groupJ, "J. " + tr("Bust", "Measurement section"), ListGroupJ(), list); InitGroup(&groupK, "K. " + tr("Balance", "Measurement section"), ListGroupK(), list); InitGroup(&groupL, "L. " + tr("Arm", "Measurement section"), ListGroupL(), list); InitGroup(&groupM, "M. " + tr("Leg", "Measurement section"), ListGroupM(), list); InitGroup(&groupN, "N. " + tr("Crotch and Rise", "Measurement section"), ListGroupN(), list); InitGroup(&groupO, "O. " + tr("Men & Tailoring", "Measurement section"), ListGroupO(), list); InitGroup(&groupP, "P. " + tr("Historical & Specialty", "Measurement section"), ListGroupP(), list); InitGroup(&groupQ, "Q. " + tr("Patternmaking measurements", "Measurement section"), ListGroupQ(), list); } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::InitGroup(QTreeWidgetItem **group, const QString &groupName, const QStringList &mList, const QStringList &list) { *group = AddGroup(groupName); for (auto &m : mList) { AddMeasurement(*group, m, list); } } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::FilterGroup(QTreeWidgetItem *group, const QString &search) { SCASSERT(group != nullptr) bool match = false; for (int i=0; i < group->childCount(); ++i) { QTreeWidgetItem *childItem = group->child(i); const QString description = QTextDocumentFragment::fromHtml(ItemFullDescription(childItem, false)) .toPlainText(); const bool hidden = not childItem->text(0).contains(search, Qt::CaseInsensitive) && not description.contains(search, Qt::CaseInsensitive); childItem->setHidden(hidden); if (not hidden) { match = true; } } group->setHidden(not group->text(0).contains(search, Qt::CaseInsensitive) && not match); } //--------------------------------------------------------------------------------------------------------------------- QTreeWidgetItem *DialogMDataBase::AddGroup(const QString &text) { QTreeWidgetItem *group = new QTreeWidgetItem(ui->treeWidget); group->setText(0, text); group->setToolTip(0, text); group->setExpanded(true); if (selectMode) { group->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); group->setCheckState(0, Qt::Unchecked); group->setBackground(0, QBrush(Qt::lightGray)); } return group; } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::AddMeasurement(QTreeWidgetItem *group, const QString &name, const QStringList &list) { SCASSERT(group != nullptr) QTreeWidgetItem *m = new QTreeWidgetItem(group); if (selectMode) { if (list.contains(name)) { m->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); m->setCheckState(0, Qt::Checked); m->setBackground(0, QBrush(Qt::yellow)); } else { m->setCheckState(0, Qt::Unchecked); } UpdateChecks(m, 0); } const QString text = VAbstractApplication::VApp()->TrVars()->MNumber(name) + ". " + VAbstractApplication::VApp()->TrVars()->MToUser(name); m->setText(0, text); m->setToolTip(0, text); m->setData(0, Qt::UserRole, name); } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::ReadSettings() { restoreGeometry(MApplication::VApp()->TapeSettings()->GetDataBaseGeometry()); } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::WriteSettings() { MApplication::VApp()->TapeSettings()->SetDataBaseGeometry(saveGeometry()); } //--------------------------------------------------------------------------------------------------------------------- QString DialogMDataBase::ItemFullDescription(QTreeWidgetItem *item, bool showImage) const { if (item == nullptr || item->childCount() != 0) { return QString(); } const QString name = item->data(0, Qt::UserRole).toString(); if (name.isEmpty()) { return QString(); } const QString number = VAbstractApplication::VApp()->TrVars()->MNumber(name); QString imgTag; if (showImage) { imgTag = ImgTag(number); } const QString text = QString("

%1
%2. %3

" "

%4

") .arg(imgTag, number, VAbstractApplication::VApp()->TrVars()->GuiText(name), VAbstractApplication::VApp()->TrVars()->Description(name)); return text; } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::RetranslateGroup(QTreeWidgetItem *group, const QString &groupText, const QStringList &list) { group->setText(0, groupText); group->setToolTip(0, groupText); for (int i=0; iTrVars()->MNumber(name) + ". " + VAbstractApplication::VApp()->TrVars()->MToUser(name); QTreeWidgetItem *m = group->child(index); m->setText(0, text); m->setToolTip(0, text); } //--------------------------------------------------------------------------------------------------------------------- void DialogMDataBase::ChangeCheckState(QTreeWidgetItem *group, Qt::CheckState check) { SCASSERT(group != nullptr) group->setCheckState(0, check); } //--------------------------------------------------------------------------------------------------------------------- Qt::CheckState DialogMDataBase::GlobalCheckState() const { SCASSERT(groupA != nullptr) SCASSERT(groupB != nullptr) SCASSERT(groupC != nullptr) SCASSERT(groupD != nullptr) SCASSERT(groupE != nullptr) SCASSERT(groupF != nullptr) SCASSERT(groupG != nullptr) SCASSERT(groupH != nullptr) SCASSERT(groupI != nullptr) SCASSERT(groupJ != nullptr) SCASSERT(groupK != nullptr) SCASSERT(groupL != nullptr) SCASSERT(groupM != nullptr) SCASSERT(groupN != nullptr) SCASSERT(groupO != nullptr) SCASSERT(groupP != nullptr) SCASSERT(groupQ != nullptr) if (selectMode) { if (groupA->checkState(0) == Qt::Unchecked && groupB->checkState(0) == Qt::Unchecked && groupC->checkState(0) == Qt::Unchecked && groupD->checkState(0) == Qt::Unchecked && groupE->checkState(0) == Qt::Unchecked && groupF->checkState(0) == Qt::Unchecked && groupG->checkState(0) == Qt::Unchecked && groupH->checkState(0) == Qt::Unchecked && groupI->checkState(0) == Qt::Unchecked && groupJ->checkState(0) == Qt::Unchecked && groupK->checkState(0) == Qt::Unchecked && groupL->checkState(0) == Qt::Unchecked && groupM->checkState(0) == Qt::Unchecked && groupN->checkState(0) == Qt::Unchecked && groupO->checkState(0) == Qt::Unchecked && groupP->checkState(0) == Qt::Unchecked && groupQ->checkState(0) == Qt::Unchecked) { return Qt::Checked; } else if (groupA->checkState(0) == Qt::Checked && groupB->checkState(0) == Qt::Checked && groupC->checkState(0) == Qt::Checked && groupD->checkState(0) == Qt::Checked && groupE->checkState(0) == Qt::Checked && groupF->checkState(0) == Qt::Checked && groupG->checkState(0) == Qt::Checked && groupH->checkState(0) == Qt::Checked && groupI->checkState(0) == Qt::Checked && groupJ->checkState(0) == Qt::Checked && groupK->checkState(0) == Qt::Checked && groupL->checkState(0) == Qt::Checked && groupM->checkState(0) == Qt::Checked && groupN->checkState(0) == Qt::Checked && groupO->checkState(0) == Qt::Checked && groupP->checkState(0) == Qt::Checked && groupQ->checkState(0) == Qt::Checked) { return Qt::Unchecked; } return Qt::Checked; } return Qt::Unchecked; }