Amelioration de l'interface Fichier > Exporter

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@42 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
xavierqet
2007-01-20 18:11:42 +00:00
parent 7537202a6a
commit 9a45f81f98
11 changed files with 333 additions and 33 deletions

View File

@@ -33,7 +33,7 @@ AboutQET::AboutQET(QWidget *parent) : QDialog(parent) {
/** /**
@return Le titre QElectroTech avec son icone @return Le titre QElectroTech avec son icone
*/ */
QWidget *AboutQET::titre() { QWidget *AboutQET::titre() const {
QWidget *icone_et_titre = new QWidget(); QWidget *icone_et_titre = new QWidget();
// icone // icone
QLabel *icone = new QLabel(); QLabel *icone = new QLabel();
@@ -54,7 +54,7 @@ QWidget *AboutQET::titre() {
/** /**
@return Le widget contenu par l'onglet « A propos » @return Le widget contenu par l'onglet « A propos »
*/ */
QWidget *AboutQET::ongletAPropos() { QWidget *AboutQET::ongletAPropos() const {
QLabel *apropos = new QLabel( QLabel *apropos = new QLabel(
tr("QElectroTech, une application de r\351alisation de sch\351mas \351lectriques.") + tr("QElectroTech, une application de r\351alisation de sch\351mas \351lectriques.") +
"<br><br>" + "<br><br>" +
@@ -72,7 +72,7 @@ QWidget *AboutQET::ongletAPropos() {
/** /**
@return Le widget contenu par l'onglet « Auteurs » @return Le widget contenu par l'onglet « Auteurs »
*/ */
QWidget *AboutQET::ongletAuteurs() { QWidget *AboutQET::ongletAuteurs() const {
QLabel *auteurs = new QLabel( QLabel *auteurs = new QLabel(
"<span style=\"text-decoration: underline;\">" + "<span style=\"text-decoration: underline;\">" +
tr("Id\351e originale") + tr("Id\351e originale") +
@@ -95,7 +95,7 @@ QWidget *AboutQET::ongletAuteurs() {
/** /**
@return Le widget contenu par l'onglet « Accord de Licence » @return Le widget contenu par l'onglet « Accord de Licence »
*/ */
QWidget *AboutQET::ongletLicence() { QWidget *AboutQET::ongletLicence() const {
QWidget *licence = new QWidget(); QWidget *licence = new QWidget();
// label // label
QLabel *titre_licence = new QLabel(tr("Ce programme est sous licence GNU/GPL.")); QLabel *titre_licence = new QLabel(tr("Ce programme est sous licence GNU/GPL."));

View File

@@ -10,9 +10,9 @@
public: public:
AboutQET(QWidget * = 0); AboutQET(QWidget * = 0);
private: private:
QWidget *titre(); QWidget *titre() const;
QWidget *ongletAPropos(); QWidget *ongletAPropos() const;
QWidget *ongletAuteurs(); QWidget *ongletAuteurs() const;
QWidget *ongletLicence(); QWidget *ongletLicence() const;
}; };
#endif #endif

View File

@@ -97,7 +97,7 @@ Borne::Orientation Borne::orientation() const {
Borne::Orientation ori_def = elt -> defaultOrientation(); Borne::Orientation ori_def = elt -> defaultOrientation();
if (ori_cur == ori_def) return(sens); if (ori_cur == ori_def) return(sens);
else { else {
/* calcul l'angle de rotation implique par l'orientation de l'element parent */ // calcul l'angle de rotation implique par l'orientation de l'element parent
// angle de rotation de la borne sur la scene, divise par 90 // angle de rotation de la borne sur la scene, divise par 90
int angle = ori_cur - ori_def + sens; int angle = ori_cur - ori_def + sens;
while (angle >= 4) angle -= 4; while (angle >= 4) angle -= 4;
@@ -361,7 +361,7 @@ QList<Conducteur *> Borne::conducteurs() const {
@param doc Le Document XML a utiliser pour creer l'element XML @param doc Le Document XML a utiliser pour creer l'element XML
@return un QDomElement representant cette borne @return un QDomElement representant cette borne
*/ */
QDomElement Borne::toXml(QDomDocument &doc) { QDomElement Borne::toXml(QDomDocument &doc) const {
QDomElement qdo = doc.createElement("borne"); QDomElement qdo = doc.createElement("borne");
qdo.setAttribute("x", amarrage_elmt.x()); qdo.setAttribute("x", amarrage_elmt.x());
qdo.setAttribute("y", amarrage_elmt.y()); qdo.setAttribute("y", amarrage_elmt.y());

View File

@@ -34,7 +34,7 @@
// methodes de manipulation des conducteurs lies a cette borne // methodes de manipulation des conducteurs lies a cette borne
bool addConducteur(Conducteur *); bool addConducteur(Conducteur *);
void removeConducteur(Conducteur *); void removeConducteur(Conducteur *);
inline int nbConducteurs() { return(liste_conducteurs.size()); } inline int nbConducteurs() const { return(liste_conducteurs.size()); }
// methodes de lecture // methodes de lecture
QList<Conducteur *> conducteurs() const; QList<Conducteur *> conducteurs() const;
@@ -45,8 +45,9 @@
// methodes relatives a l'import/export au format XML // methodes relatives a l'import/export au format XML
static bool valideXml(QDomElement &); static bool valideXml(QDomElement &);
bool fromXml (QDomElement &); bool fromXml (QDomElement &);
QDomElement toXml (QDomDocument &); QDomElement toXml (QDomDocument &) const;
protected:
// methodes de gestion des evenements // methodes de gestion des evenements
void hoverEnterEvent (QGraphicsSceneHoverEvent *); void hoverEnterEvent (QGraphicsSceneHoverEvent *);
void hoverMoveEvent (QGraphicsSceneHoverEvent *); void hoverMoveEvent (QGraphicsSceneHoverEvent *);

View File

@@ -62,8 +62,8 @@ QPoint Element::setHotspot(QPoint hs) {
if (dimensions.isNull()) hotspot_coord = QPoint(0, 0); if (dimensions.isNull()) hotspot_coord = QPoint(0, 0);
else { else {
// les coordonnees indiquees ne doivent pas depasser les dimensions de l'element // les coordonnees indiquees ne doivent pas depasser les dimensions de l'element
int hsx = hs.x() > dimensions.width() ? dimensions.width() : hs.x(); int hsx = qMin(hs.x(), dimensions.width());
int hsy = hs.y() > dimensions.height() ? dimensions.height() : hs.y(); int hsy = qMin(hs.y(), dimensions.height());
hotspot_coord = QPoint(hsx, hsy); hotspot_coord = QPoint(hsx, hsy);
} }
return(hotspot_coord); return(hotspot_coord);

210
exportdialog.cpp Normal file
View File

@@ -0,0 +1,210 @@
#include "exportdialog.h"
/**
Constructeur
@param schema Le schema a exporter
@param parent Le Widget parent de ce dialogue
*/
ExportDialog::ExportDialog(Schema &schema, QWidget *parent) : QDialog(parent) {
// recupere le schema a exporter, sa taille et ses proportions
schema_schema = &schema;
schema_size = schema_schema -> imageSize();
schema_ratio = (qreal)schema_size.width() / (qreal)schema_size.height();
// la taille du dialogue est fixee
setFixedSize(400, 310);
setWindowTitle(tr("Exporter"));
// le dialogue est un empilement vertical d'elements
QVBoxLayout *vboxLayout = new QVBoxLayout(this);
/* le dialogue comprend une ligne permettant d'indiquer un chemin de fichier (hboxLayout) */
QHBoxLayout *hboxLayout = new QHBoxLayout();
hboxLayout -> addWidget(new QLabel(tr("Nom de fichier :"), this));
hboxLayout -> addWidget(filename = new QLineEdit(this));
hboxLayout -> addWidget(button_browse = new QPushButton(tr("Parcourir"), this));
vboxLayout -> addLayout(hboxLayout);
/* une ligne permettant de choisir le format (hboxLayout1) */
QHBoxLayout *hboxLayout1 = new QHBoxLayout();
hboxLayout1 -> addWidget(new QLabel(tr("Format :"), this));
hboxLayout1 -> addWidget(format = new QComboBox(this));
format -> addItem(tr("PNG (*.png)"), "PNG");
format -> addItem(tr("JPEG (*.jpg)"), "JPG");
format -> addItem(tr("Bitmap (*.bmp)"), "BMP");
vboxLayout -> addLayout(hboxLayout1);
/* un cadre permettant de specifier les dimensions de l'image finale */
vboxLayout -> addWidget(setupDimensionsGroupBox());
/* un cadre permettant de specifier les options de l'image finale */
vboxLayout -> addWidget(setupOptionsGroupBox());
/* et deux boutons */
buttons = new QDialogButtonBox(this);
buttons -> setOrientation(Qt::Horizontal);
buttons -> setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Save);
vboxLayout -> addWidget(buttons);
// ordre des input selectionnes avec la touche tab
setTabOrder(filename, button_browse);
setTabOrder(button_browse, format);
setTabOrder(format, width);
setTabOrder(width, height);
setTabOrder(height, keep_aspect_ratio);
setTabOrder(keep_aspect_ratio, buttons);
// connexions signaux/slots
connect(button_browse, SIGNAL(released()), this, SLOT(slot_chooseAFile()));
connect(width, SIGNAL(valueChanged(int)), this, SLOT(slot_correctHeight()));
connect(keep_aspect_ratio, SIGNAL(stateChanged(int)), this, SLOT(slot_correctHeight()));
connect(height, SIGNAL(valueChanged(int)), this, SLOT(slot_correctWidth()));
connect(buttons, SIGNAL(accepted()), this, SLOT(slot_check()));
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
}
/**
Met en place la partie du dialogue dans lequel l'utilisateur entre les
dimensions souhaitees de l'image.
@return La QGroupBox permettant de regler les dimensions de l'image
*/
QGroupBox *ExportDialog::setupDimensionsGroupBox() {
QGroupBox *groupbox_dimensions = new QGroupBox(tr("Dimensions"), this);
QGridLayout *gridLayout = new QGridLayout(groupbox_dimensions);
// hauteur
gridLayout -> addWidget(new QLabel(tr("Hauteur :"), groupbox_dimensions), 2, 0, 1, 1);
width = new QSpinBox(groupbox_dimensions);
width -> setRange(1, 10000);
width -> setValue(schema_size.width());
gridLayout -> addWidget(width, 0, 1, 1, 1);
gridLayout -> addWidget(new QLabel(tr("px"), groupbox_dimensions), 0, 2, 1, 1);
// largeur
gridLayout -> addWidget(new QLabel(tr("Largeur :"), groupbox_dimensions), 0, 0, 1, 1);
height = new QSpinBox(groupbox_dimensions);
height -> setRange(1, 10000);
height -> setValue(schema_size.height());
gridLayout -> addWidget(height, 2, 1, 1, 1);
gridLayout -> addWidget(new QLabel(tr("px"), groupbox_dimensions), 2, 2, 1, 1);
// conserver les proportions
keep_aspect_ratio = new QCheckBox(tr("Conserver les proportions"), groupbox_dimensions);
keep_aspect_ratio -> setChecked(true);
gridLayout -> addWidget(keep_aspect_ratio, 1, 3, 1, 1);
return(groupbox_dimensions);
}
/**
Met en place la partie du dialogue dans lequel l'utilisateur entre les
options souhaitees de l'image.
@return La QGroupBox permettant de regler les options de l'image
*/
QGroupBox *ExportDialog::setupOptionsGroupBox() {
QGroupBox *groupbox_options = new QGroupBox(tr("Options"), this);
QHBoxLayout *optionshlayout = new QHBoxLayout(groupbox_options);
// exporter la grille
export_grid = new QCheckBox(tr("Exporter la grille"), groupbox_options);
optionshlayout -> addWidget(export_grid);
// Conserver les couleurs
keep_colors = new QCheckBox(tr("Conserver les couleurs"), groupbox_options);
optionshlayout -> addWidget(keep_colors);
return(groupbox_options);
}
void ExportDialog::slot_correctWidth() {
if (!keep_aspect_ratio -> isChecked() || dontchangewidth) return;
dontchangeheight = true;
width -> setValue(qRound(height -> value() * schema_ratio));
dontchangeheight = false;
}
void ExportDialog::slot_correctHeight() {
if (!keep_aspect_ratio -> isChecked() || dontchangeheight) return;
dontchangewidth = true;
height -> setValue(qRound(width -> value() / schema_ratio));
dontchangewidth = false;
}
void ExportDialog::slot_chooseAFile() {
QString user_file = QFileDialog::getSaveFileName(
this,
tr("Exporter vers le fichier"),
QDir::homePath(),
tr("Images (*.png *.bmp *.jpg)")
);
if (user_file != "") {
schema_path = user_file;
filename -> setText(schema_path);
}
}
void ExportDialog::slot_check() {
// verifie que le fichier a ete specifie
if (schema_path == "") {
QMessageBox::information(
this,
tr("Fichier non sp\351cifi\351"),
tr("Vous devez sp\351cifier le chemin du fichier dans lequel sera enregistr\351e l'image."),
QMessageBox::Ok
);
return;
}
// recupere le format a utiliser (acronyme et extension)
QString format_acronym = format -> itemData(format -> currentIndex()).toString();
QString format_extension = "." + format_acronym.toLower();
// corrige l'extension du fichier
if (!schema_path.endsWith(format_extension, Qt::CaseInsensitive)) schema_path += format_extension;
// recupere des informations sur le fichier specifie
QFileInfo file_infos(schema_path);
// verifie qu'il est possible d'ecrire dans le fichier en question
if (file_infos.exists() && !file_infos.isWritable()) {
QMessageBox::critical(
this,
tr("Impossible d'\351crire dans ce fichier"),
tr("Il semblerait que vous n'ayez pas les permissions n\351cessaires pour \351crire dans ce fichier.."),
QMessageBox::Ok
);
return;
}
// ouvre le fichier
QFile fichier(schema_path);
// genere l'image
if (!export_grid -> isChecked()) schema_schema -> setAffichageGrille(false);
QImage image = schema_schema -> toImage(width -> value(), height -> value(), keep_aspect_ratio -> isChecked());
if (!export_grid -> isChecked()) schema_schema -> setAffichageGrille(true);
// convertit l'image en niveaux de gris si besoin
if (!keep_colors -> isChecked()) {
QVector<QRgb> ColorTab;
for (int i = 0 ; i < 256 ; ++ i) ColorTab << qRgb(i, i, i);
image = image.convertToFormat(QImage::Format_Indexed8, ColorTab, Qt::ThresholdDither);
}
// enregistre l'image dans le fichier
image.save(&fichier, format_acronym.toUtf8().data());
fichier.close();
// fermeture du dialogue
accept();
}

45
exportdialog.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef EXPORTDIALOG_H
#define EXPORTDIALOG_H
#include <QtGui>
#include "schema.h"
/**
Cette classe represente le dialogue permettant d'exporter un schema
sous forme d'image selon les desirs de l'utilisateur
*/
class ExportDialog : public QDialog {
Q_OBJECT
public:
ExportDialog(Schema &, QWidget * = 0);
private:
// elements graphiques
QLineEdit *filename;
QPushButton *button_browse;
QComboBox *format;
QSpinBox *width;
QSpinBox *height;
QCheckBox *keep_aspect_ratio;
QCheckBox *export_grid;
QCheckBox *keep_colors;
QDialogButtonBox *buttons;
// booleens pour ne pas avoir de boucle lors de l'edition des dimensions de l'image
bool dontchangewidth;
bool dontchangeheight;
// elements relatifs au traitement effectue par le dialogue
Schema *schema_schema;
QSize schema_size;
QString schema_path;
qreal schema_ratio;
QGroupBox *setupDimensionsGroupBox();
QGroupBox *setupOptionsGroupBox();
public slots:
void slot_correctWidth();
void slot_correctHeight();
void slot_chooseAFile();
void slot_check();
};
#endif

View File

@@ -4,7 +4,7 @@
TEMPLATE = app TEMPLATE = app
TARGET = TARGET =
DEPENDPATH += . DEPENDPATH += . lang
INCLUDEPATH += . INCLUDEPATH += .
# Input # Input
@@ -14,6 +14,7 @@ HEADERS += aboutqet.h \
element.h \ element.h \
elementfixe.h \ elementfixe.h \
elementperso.h \ elementperso.h \
exportdialog.h \
panelappareils.h \ panelappareils.h \
qetapp.h \ qetapp.h \
schema.h \ schema.h \
@@ -24,12 +25,13 @@ SOURCES += aboutqet.cpp \
element.cpp \ element.cpp \
elementfixe.cpp \ elementfixe.cpp \
elementperso.cpp \ elementperso.cpp \
exportdialog.cpp \
main.cpp \ main.cpp \
panelappareils.cpp \ panelappareils.cpp \
qetapp.cpp \ qetapp.cpp \
schema.cpp \ schema.cpp \
schemavue.cpp schemavue.cpp
RESOURCES += qelectrotech.qrc RESOURCES += qelectrotech.qrc
TRANSLATIONS += qet_en.ts TRANSLATIONS += lang/qet_en.ts lang/qt_fr.ts
QT += xml QT += xml

View File

@@ -3,6 +3,7 @@
#include "schema.h" #include "schema.h"
#include "panelappareils.h" #include "panelappareils.h"
#include "aboutqet.h" #include "aboutqet.h"
#include "exportdialog.h"
/** /**
constructeur constructeur
@@ -515,13 +516,12 @@ void QETApp::dialogue_imprimer() {
Gere l'export de schema vers un autre format (PNG pour le moment) Gere l'export de schema vers un autre format (PNG pour le moment)
*/ */
void QETApp::dialogue_exporter() { void QETApp::dialogue_exporter() {
Schema *sc = schemaEnCours() -> scene;
ExportDialog ed(*sc);
ed.exec();
/*
// demande un nom de fichier // demande un nom de fichier
QString nom_fichier = QFileDialog::getSaveFileName(
this,
tr("Exporter vers le fichier"),
QDir::homePath(),
tr("Image PNG (*.png)")
);
// exporte le schema // exporte le schema
if (nom_fichier != "") { if (nom_fichier != "") {
if (!nom_fichier.endsWith(".png", Qt::CaseInsensitive)) nom_fichier += ".png"; if (!nom_fichier.endsWith(".png", Qt::CaseInsensitive)) nom_fichier += ".png";
@@ -533,6 +533,7 @@ void QETApp::dialogue_exporter() {
image.save(&fichier, "PNG"); image.save(&fichier, "PNG");
fichier.close(); fichier.close();
} }
*/
} }
/** /**

View File

@@ -67,16 +67,26 @@ void Schema::drawBackground(QPainter *p, const QRectF &r) {
Exporte le schema vers une image Exporte le schema vers une image
@return Une QImage representant le schema @return Une QImage representant le schema
*/ */
QImage Schema::toImage() { QImage Schema::toImage(int width, int height, bool respectRatio) {
QRectF vue = itemsBoundingRect(); // determine le contenu du schema
// la marge = 5 % de la longueur necessaire QRectF schema_content = itemsBoundingRect();
qreal marge = 0.05 * vue.width();
vue.translate(-marge, -marge);
vue.setWidth(vue.width() + 2.0 * marge);
vue.setHeight(vue.height() + 2.0 * marge);
QSize dimensions_image = vue.size().toSize();
QImage pix = QImage(dimensions_image, QImage::Format_RGB32); // calcule la marge = 5 % de la longueur necessaire
qreal margin = 0.05 * schema_content.width();
// en deduit la zone source utilisee pour l'image
QRectF source_area = schema_content;
source_area.translate(-margin, -margin);
source_area.setWidth(schema_content.width() + 2.0 * margin);
source_area.setHeight(schema_content.height() + 2.0 * margin);
// si les dimensions ne sont pas precisees, l'image est exportee a l'echelle 1:1
QSize image_size = (width == -1 && height == -1) ? source_area.size().toSize() : QSize(width, height);
// initialise une image avec ces dimensions
QImage pix = QImage(image_size, QImage::Format_RGB32);
// prepare le rendu
QPainter p; QPainter p;
bool painter_ok = p.begin(&pix); bool painter_ok = p.begin(&pix);
if (!painter_ok) return(QImage()); if (!painter_ok) return(QImage());
@@ -86,11 +96,41 @@ QImage Schema::toImage() {
p.setRenderHint(QPainter::TextAntialiasing, true); p.setRenderHint(QPainter::TextAntialiasing, true);
p.setRenderHint(QPainter::SmoothPixmapTransform, true); p.setRenderHint(QPainter::SmoothPixmapTransform, true);
render(&p, pix.rect(), vue, Qt::KeepAspectRatio); // deselectionne tous les elements
QList<QGraphicsItem *> selected_elmts = selectedItems();
foreach (QGraphicsItem *qgi, selected_elmts) qgi -> setSelected(false);
// effectue le rendu lui-meme
render(&p, pix.rect(), source_area, respectRatio ? Qt::KeepAspectRatio : Qt::IgnoreAspectRatio);
p.end(); p.end();
// restaure les elements selectionnes
foreach (QGraphicsItem *qgi, selected_elmts) qgi -> setSelected(true);
return(pix); return(pix);
} }
/**
Permet de connaitre les dimensions qu'aura l'image generee par la methode toImage()
@return La taille de l'image generee par toImage()
*/
QSize Schema::imageSize() const {
// determine le contenu du schema
QRectF schema_content = itemsBoundingRect();
// calcule la marge = 5 % de la longueur necessaire
qreal margin = 0.05 * schema_content.width();
// en deduit la zone source utilisee pour l'image
QRectF source_area = schema_content;
source_area.translate(-margin, -margin);
source_area.setWidth(schema_content.width() + 2.0 * margin);
source_area.setHeight(schema_content.height() + 2.0 * margin);
// renvoie la taille de la zone source
return(source_area.size().toSize());
}
/** /**
Exporte tout ou partie du schema Exporte tout ou partie du schema
@param schema Booleen (a vrai par defaut) indiquant si le XML genere doit @param schema Booleen (a vrai par defaut) indiquant si le XML genere doit

View File

@@ -21,7 +21,8 @@
} }
inline void setDepart (QPointF d) { poseur_de_conducteur -> setLine(QLineF(d, poseur_de_conducteur -> line().p2())); } inline void setDepart (QPointF d) { poseur_de_conducteur -> setLine(QLineF(d, poseur_de_conducteur -> line().p2())); }
inline void setArrivee(QPointF a) { poseur_de_conducteur -> setLine(QLineF(poseur_de_conducteur -> line().p1(), a)); } inline void setArrivee(QPointF a) { poseur_de_conducteur -> setLine(QLineF(poseur_de_conducteur -> line().p1(), a)); }
QImage toImage(); QImage toImage(int = -1, int = -1, bool = true);
QSize imageSize() const;
QDomDocument toXml(bool = true); QDomDocument toXml(bool = true);
bool fromXml(QDomDocument &, QPointF = QPointF()); bool fromXml(QDomDocument &, QPointF = QPointF());
QGraphicsItem *getElementById(uint id); QGraphicsItem *getElementById(uint id);