Marco Callieri 9bae8dbd8d qPrintable to qUtf8Printable in the WHOLE project
qUtf8Printable is better to deal with special characters.
also in QT documentation it is said is better when logging strings.
However, we use it also to store filenames and text-based ID, if we only use one, and not alternating between qUtf8Printable and qPrintable, thins should be smoother, but since it is a project-wide change, it is potentially DANGEROUS, NOT YET FULLY TESTED
2018-02-19 16:36:31 +01:00

292 lines
9.4 KiB
C++

/****************************************************************************
* MeshLab o o *
* An extendible mesh processor o o *
* _ O _ *
* Copyright(C) 2005, 2006 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* 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 (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: stdpardialog.cpp,v $
****************************************************************************/
#include <GL/glew.h>
#include <QDockWidget>
#include "edit_align.h"
#include "alignDialog.h"
#include <meshlab/glarea.h>
static QTextEdit *globalLogTextEdit = 0;
MeshNode *AlignDialog::currentNode() { return edit->currentNode(); }
// Global function to write on the log in the lower part of the window.
bool AlignCallBackPos(const int pos, const char * message)
{
assert(globalLogTextEdit);
globalLogTextEdit->insertPlainText(QString(message));
globalLogTextEdit->ensureCursorVisible();
globalLogTextEdit->update();
qApp->processEvents();
return true;
}
// This signal is used to make a connection between the closure of the align dialog and the end of the editing in the GLArea
void AlignDialog::closeEvent(QCloseEvent * /*event*/)
{
emit closing();
}
AlignDialog::AlignDialog(QWidget *parent, EditAlignPlugin *_edit) : QDockWidget(parent)
{
// setWindowFlags( windowFlags() | Qt::WindowStaysOnTopHint | Qt::SubWindow);
//setVisible(false);
AlignDialog::ui.setupUi(this);
this->setWidget(ui.frame);
this->setFeatures(QDockWidget::AllDockWidgetFeatures);
this->setAllowedAreas(Qt::LeftDockWidgetArea);
QPoint p = parent->mapToGlobal(QPoint(0, 0));
this->setFloating(true);
this->setGeometry(p.x() + (parent->width() - width()), p.y() + 40, width(), height());
this->edit = _edit;
// The following connection is used to associate the click with the change of the current mesh.
connect(ui.alignTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(onClickItem(QTreeWidgetItem *, int)));
globalLogTextEdit = ui.logTextEdit;
currentArc = 0;
meshTree = 0;
}
void AlignDialog::setCurrentArc(vcg::AlignPair::Result *_currentArc)
{
assert(meshTree);
// First clear the backgrund of previously selected arc
MeshTreeWidgetItem *oldArcF = A2Tf[currentArc];
MeshTreeWidgetItem *oldArcB = A2Tb[currentArc];
if (oldArcF != NULL)
{
assert(oldArcF->a == currentArc);
oldArcF->setBackground(3, QBrush());
oldArcB->setBackground(3, QBrush());
}
// if we clicked twice on the same arc deselect it
if (_currentArc == currentArc) {
currentArc = 0;
return;
}
MeshTreeWidgetItem *newArcB = A2Tb[_currentArc];
MeshTreeWidgetItem *newArcF = A2Tf[_currentArc];
if (newArcB != NULL)
{
assert(newArcB->a == _currentArc);
newArcB->setBackground(3, QBrush(QColor("#d0ffff")));
newArcF->setBackground(3, QBrush(QColor("#c0ffff")));
}
newArcF->treeWidget()->expandItem(newArcF->parent());
newArcB->treeWidget()->expandItem(newArcB->parent());
currentArc = _currentArc;
updateButtons();
}
void AlignDialog::updateCurrentNodeBackground()
{
static MeshNode *lastCurrentNode = 0;
assert(meshTree);
if (lastCurrentNode && M2T[lastCurrentNode])
M2T[lastCurrentNode]->setBackground(3, QBrush());
MeshTreeWidgetItem *newNodeItem = M2T[currentNode()];
if (newNodeItem != NULL)
{
newNodeItem->setBackground(3, QBrush(QColor(Qt::lightGray)));
lastCurrentNode = currentNode();
}
}
void AlignDialog::setTree(MeshTree *_meshTree)
{
assert(meshTree == 0);
meshTree = _meshTree;
meshTree->cb = AlignCallBackPos;
rebuildTree();
}
void AlignDialog::updateDialog()
{
assert(meshTree != 0);
assert(currentNode() == meshTree->find(currentNode()->m));
updateButtons();
}
void AlignDialog::updateButtons()
{
if (currentNode() == NULL)
return;
if (currentNode()->glued)
ui.glueHereButton->setText("Unglue Mesh ");
else ui.glueHereButton->setText("Glue Here Mesh");
ui.pointBasedAlignButton->setDisabled(currentNode()->glued);
ui.manualAlignButton->setDisabled(currentNode()->glued);
ui.recalcButton->setDisabled(currentArc == 0);
ui.icpParamCurrentButton->setDisabled(currentArc == 0);
ui.baseMeshButton->setDisabled(!currentNode()->glued);
}
MeshTreeWidgetItem::MeshTreeWidgetItem(MeshNode *meshNode)
{
QString meshName = meshNode->m->label();
QString labelText;
setText(0, QString::number(meshNode->Id()));
if (meshNode->glued) setText(2, "*");
if (meshNode->m->visible) setIcon(1, QIcon(":/layer_eye_open.png"));
else setIcon(1, QIcon(":/layer_eye_close.png"));
labelText.sprintf("%s", qUtf8Printable(meshName));
setText(3, labelText);
n = meshNode;
a = 0;
}
MeshTreeWidgetItem::MeshTreeWidgetItem(MeshTree* /*meshTree*/, vcg::AlignPair::Result *A, MeshTreeWidgetItem *parent)
{
n = 0;
a = A;
parent->addChild(this);
QString buf = QString("Arc: %1 -> %2 Area: %3 Err: %4 Sample# %5 (%6)")
.arg((*A).FixName)
.arg((*A).MovName)
.arg((*A).area, 6, 'f', 3)
.arg((*A).err, 6, 'f', 3)
.arg((*A).ap.SampleNum, 6)
.arg((*A).as.LastSampleUsed());
setText(3, buf);
QFont fixedFont("Courier");
std::vector<vcg::AlignPair::Stat::IterInfo> &I = (*A).as.I;
QTreeWidgetItem *itemArcIter;
buf.sprintf("Iter - MinD - Error - Sample - Used - DistR - BordR - AnglR ");
// " 12 123456 1234567 12345 12345 12345 12345 12345
itemArcIter = new QTreeWidgetItem(this);
itemArcIter->setFont(3, fixedFont);
itemArcIter->setText(3, buf);
for (int qi = 0; qi < I.size(); ++qi)
{
buf.sprintf(" %02i %6.2f %7.4f %05i %05i %5i %5i %5i",
qi, I[qi].MinDistAbs, I[qi].pcl50,
I[qi].SampleTested, I[qi].SampleUsed, I[qi].DistanceDiscarded, I[qi].BorderDiscarded, I[qi].AngleDiscarded);
itemArcIter = new QTreeWidgetItem(this);
itemArcIter->setFont(3, fixedFont);
itemArcIter->setText(3, buf);
}
}
void AlignDialog::rebuildTree()
{
currentArc = 0;
gla = edit->_gla;
ui.alignTreeWidget->clear();
M2T.clear();
A2Tf.clear();
A2Tb.clear();
// QList<MeshNode*> &meshList = meshTree->nodeList;
// for (int i = 0; i < meshList.size(); ++i)
for(auto ni=meshTree->nodeMap.begin();ni!=meshTree->nodeMap.end();++ni)
{
MeshNode *mn=ni->second;
// MeshTreeWidgetItem *item = new MeshTreeWidgetItem(meshList.value(i));
MeshTreeWidgetItem *item = new MeshTreeWidgetItem(mn);
// if(meshList.value(i)==currentNode) item->setBackground(0,QBrush(QColor(Qt::lightGray)));
// M2T[meshList.value(i)] = item;
M2T[mn] = item;
ui.alignTreeWidget->addTopLevelItem(item);
}
// Second part add the arcs to the tree
vcg::AlignPair::Result *A;
MeshTreeWidgetItem *parent;
MeshTreeWidgetItem *item;
for (int i = 0; i < meshTree->resultList.size(); ++i)
{
A = &(meshTree->resultList[i]);
// Forward arc
// parent = M2T[meshList.at((*A).FixName)];
parent = M2T[meshTree->nodeMap[(*A).FixName] ];
item = new MeshTreeWidgetItem(meshTree, A, parent);
A2Tf[A] = item;
// Backward arc
// parent = M2T[meshList.at((*A).MovName)];
parent = M2T[meshTree->nodeMap [(*A).MovName] ];
item = new MeshTreeWidgetItem(meshTree, A, parent);
A2Tb[A] = item;
}
ui.alignTreeWidget->resizeColumnToContents(0);
ui.alignTreeWidget->resizeColumnToContents(1);
ui.alignTreeWidget->resizeColumnToContents(2);
assert(currentNode());
updateCurrentNodeBackground();
updateButtons();
}
void AlignDialog::currentMeshChanged(int)
{
this->updateDialog();
this->rebuildTree();
}
// Called when a user click over the tree;
void AlignDialog::onClickItem(QTreeWidgetItem * item, int column)
{
// int row = item->data(1,Qt::DisplayRole).toInt();
MeshTreeWidgetItem *mItem = dynamic_cast<MeshTreeWidgetItem *>(item);
if (!mItem)
return; // user clicked on a iteration info (neither a node nor an arc)
MeshNode * nn = mItem->n;
if (nn) {
if (column == 1)
{
nn->m->visible = !nn->m->visible;
emit updateMeshSetVisibilities();
if (nn->m->visible) mItem->setIcon(1, QIcon(":/layer_eye_open.png"));
else mItem->setIcon(1, QIcon(":/layer_eye_close.png"));
}
else {
this->edit->_md->setCurrentMesh(nn->Id());
updateCurrentNodeBackground();
}
}
else {
assert(mItem->a);
setCurrentArc(mItem->a);
}
gla->update();
updateButtons();
}