Compare commits

..

1 Commits
0.3rc ... 0.1b

Author SHA1 Message Date
xavierqet
5762b3943b Tag de la version 0.1 beta
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/tags/0.1b@253 bfdf4180-ca20-0410-9c96-a3a8aa849046
2007-12-23 16:20:42 +00:00
2815 changed files with 22338 additions and 315244 deletions

187
CREDIT
View File

@@ -1,181 +1,6 @@
[en]
Thanks to Qt Software for their Qt library ( http://www.qtsoftware.com/ ), licensed under GNU/GPL.
Thanks to Everaldo Coelho for the Crystal SVG icons theme ( http://www.iconfinder.com/iconsets/crystalproject) licensed under LGPL.
Thanks to Nuno Pinheiro for the Oxygen icons theme ( http://www.oxygen-icons.org/ ) licensed under LGPL but also for the QElectroTech-dedicated icons.
Thanks to the KDE project ( http://www.kde.org/ ).
Thanks to Loic for his mathematics-related explanations.
Thanks to Remi Collet for the Fedora packaging.
Thanks to Laurent Trinques for the Debian packaging.
Thanks to `trem' for the Mandriva packaging.
Thanks to TuxFamily ( http://tuxfamily.org/ ) for hosting the project.
Thanks to `Nishiki' for his elements and his support.
Thanks to qtcentre.org for their SingleApplication class.
Thanks to Alfredo Carreto for his Spanish translations and fixing Spanish translations ( http://electronicosmx.comxa.com )
Thanks to 'Dr.Slump' and Sivio for their translations in Italian
Thanks to Jose Carlos Martins for his translations in Portuguese
Thanks to Pavel Fric for his translations in Czech
Thanks to Pawel Smiech for His Polish translations
Thanks to Yuriy Litkevich for his translations into Russian
Thanks to Youssef Ouamalkran for his translations Catatan
Thanks to Gabi Mandoc for his translations in Romanian
Thanks to Markus Budde and Jonas Stein and Noah Braden for his translations into German
Thanks to Mohamed Souabni for his translations into Arabic
Thanks to Uroš Platiše for his translations into Slovenian
Thanks to Antun Marakovic for his translations Croatian
Thanks to Nikos Papadopoylos && Yannis Gyftomitros their Greek translations
Thanks to Markos Chandras for Gentoo packaging.
[fr]
Merci à Qt Software pour la bibliothèque Qt ( http://www.qtsoftware.com/ ), sous licence GNU/GPL.
Merci à Everaldo Coelho pour le thème d'icônes Crystal SVG ( http://www.iconfinder.com/iconsets/crystalproject ) sous licence LGPL.
Merci à Nuno Pinheiro pour le thème d'icônes Oxygen ( http://www.oxygen-icons.org/ ) sous licence LGPL mais aussi pour les icônes dédiées à QElectroTech
Merci au projet KDE ( http://www.kde.org/ ).
Merci à Loic pour ses explications d'ordre mathématique.
Merci à Remi Collet pour les paquets Fedora.
Merci à Laurent Trinques pour les paquets Debian.
Merci à `trem' pour les paquets Mandriva.
Merci à TuxFamily ( http://tuxfamily.org/ ) pour l'hébergement du projet.
Merci à `Nishiki' pour ses éléments et son soutien.
Merci à qtcentre.org pour leur classe SingleApplication.
Merci à Alfredo Carreto pour ses traductions et corrections en espagnol ( http://electronicosmx.comxa.com )
Merci à 'Dr.Slump' et Sivio pour leurs traductions en italien
Merci à Jose Carlos Martins pour ses traductions en portugais
Merci à Pavel Fric pour ses traductions en Tchèque
Merci à Pawel Smiech pour ses traductions en polonais
Merci à Yuriy Litkevich pour ses traductions en russe
Merci à Youssef Ouamalkran pour ses traductions en catatan
Merci à Gabi Mandoc pour ses traductions en Roumain
Merci à Markus Budde et Jonas Stein et Noah Braden pour ses traductions en allemand
Merci à Mohamed Souabni pour ses traductions en arabe
Merci à Uroš Platiše pour ses traductions en Slovene
Merci à Antun Marakovic pour ses traductions Croate
Merci à Nikos Papadopoylos && Yannis Gyftomitros pour leurs traductions en grec
Merci à Markos Chandras pour les paquets Gentoo
[ru]
Спасибо Qt Software за их библиотеку Qt ( http://www.qtsoftware.com/ ), лицензированную на условиях GNU/GPL.
Спасибо Everaldo Coelho за тему значков Crystal SVG ( http://www.iconfinder.com/iconsets/crystalproject ) лицензированную на условиях LGPL.
Спасибо Nuno Pinheiro за тему значков Oxygen ( http://www.oxygen-icons.org/ ) лицензированную на условиях LGPL, а также за значки связанные с QElectroTech.
Спасибо проекту KDE ( http://www.kde.org/ ).
Спасибо Loic за объяснения связанные с математикой.
Спасибо Remi Collet за пакет для Fedora.
Спасибо Laurent Trinques за пакет для Debian.
Спасибо `trem' за пакет для Mandriva.
Спасибо TuxFamily ( http://tuxfamily.org/ ) за хостинг для проекта.
Спасибо `Nishiki' за элементы и поддержку.
Спасибо qtcentre.org за их класс SingleApplication.
Спасибо Alfredo Carreto за исправления и перевод на испанский ( http://electronicosmx.comxa.com )
Спасибо 'Dr.Slump' за исправления и перевод
[pt]
Agradecimentos a Qt Software pela sua biblioteca Qt ( http://www.qtsoftware.com/ ), licenciada de acordo com a GNU/GPL.
Agradecimentos a Everaldo Coelho pelo tema de ícones Crystal SVG ( http://www.iconfinder.com/iconsets/crystalproject ), licenciado de acordo com a LGPL.
Agradecimentos a Nuno Pinheiro pelo tema de ícones Oxygen e em especial pelos ícones dedicados ao programa QElectroTech ( http://www.oxygen-icons.org/ ), lincenciado de acordo com a LGPL.
Agradecimentos ao projecto KDE ( http://www.kde.org/ ).
Agradecimentos a Loic pelas suas explicações relacionadas com problemas matemáticos.
Agradecimentos a Remi Collet pela criação dos pacotes para Fedora.
Agradecimentos a Laurent Trinques pela criação dos pacotes para Debian.
Agradecimentos a "trem" pela criação dos pacotes para Mandriva.
Agradecimentos a TuxFamily ( http://tuxfamily.org/ ) por albergarem este projecto.
Agradecimentos a "Nishiki" pela criação de elementos e o seu suporte.
Agradecimentos a qtcentre.org pela classe SingleApplication.
Agradecimentos a Alfredo Carreto pela tradução para Espanhol e pela correcção de traduções em Espanhol ( http://electronicosmx.comxa.com ).
Agradecimentos a 'Dr.Slump'pela tradução para italiano
[es]
Agradecimientos a Qt Software por su biblioteca Qt ( http://www.qtsoftware.com/ ), licenciada bajo GNU/GPL.
Agradecimientos a Everaldo Coelho por el tema de icónos Crystal SVG ( http://www.iconfinder.com/iconsets/crystalproject ), licenciado bajo LGPL.
Agradecimientos a Nuno Pinheiro por el tema de icónos Oxygen y especialmente por los icónos dedicados al programa QElectroTech ( http://www.oxygen-icons.org/ ), licenciado bajo LGPL.
Agradecimientos al proyecto KDE ( http://www.kde.org/ ).
Agradecimientos a Loic por sus explicaciones relacionadas con problemas matemáticos.
Agradecimientos a Remi Collet por criación de paquetes para Fedora.
Agradecimientos a Laurent Trinques por la creación de paquetes para Debian.
Agradecimientos a "trem" por creación de paquetes para Mandriva.
Agradecimientos a TuxFamily ( http://tuxfamily.org/ ) por el alojamiento de este proyecto.
Agradecimientos a "Nishiki" por creación de elementos e de su suporte.
Agradecimientos a qtcentre.org por classe SingleApplication.
Agradecimientos a Alfredo Carreto por sus traducciones en español y correcciones de traducción en español ( http://electronicosmx.comxa.com)
Agradecimientos a 'Dr.Slump' por sus traducciones en italiano
[cs]
Díky Qt Software za jejich knihovnu Qt ( http://www.qtsoftware.com/ ), pod licencí GNU/GPL.
Díky Everaldovi Coelho za téma Crystal SVG icons theme ( http://www.iconfinder.com/iconsets/crystalproject ) pod licencí LGPL.
Díky Nunovi Pinheirovi za téma ikon Oxygen ( http://www.oxygen-icons.org/ ) pod licencí LGPL ale také za ikony věnované QElectroTech.
Díky projektu KDE ( http://www.kde.org/ ).
Díky Loicovi za jeho vysvětlení vztahující se k matematice.
Díky Remi Colletovi za balíček pro Fedoru.
Díky Laurentu Trinquesovi za balíček pro Debian.
Díky `trem' za balíček pro Mandrivu.
Díky TuxFamily ( http://tuxfamily.org/ ) za poskytování hostingu pro projekt.
Díky `Nishiki' za jeho prvky a jeho podporu.
Díky qtcentre.org za jejich třídu SingleApplication.
Poděkování Alfredovi Carretovi za jeho španělský překlad a opravy španělského překladu ( http://electronicosmx.comxa.com )
Dìky 'Dr.Slump' za jeho italianský překlad
[pl]
Podziękowania dla Qt Software, za biblioteki Qt (http://www.qtsoftware.com/) na licencji GNU / GPL.
Podziękowania dla Everaldo Coelho, za ikony Crystal SVG ( http://www.iconfinder.com/iconsets/crystalproject) na licencji LGPL.
Podziękowania dla Nun Pinheiro, za ikony Oxygen (http://www.oxygen-icons.org/) na licencji LGPL, a także za ikony przeznaczone do projektu QElectroTech.
Podziękowania dla projektu KDE (http://www.kde.org/).
Podziękowania dla Loic, za pomoc w rozwiązaniu problemów matematycznych.
Podziękowania dla Remi Collet, za pakiety dla Fedory.
Podziękowania dla Laurent Trinquesovi, za pakiety dla Debiana.
Podziękowania dla "trem", za pakiety dla Mandrivy.
Podziękowania dla TuxFamily (http://tuxfamily.org/), za organizację projektu.
Podziękowanie dla "Nishiki", zajego elementy i poparcie.
Podziękowania dla qtcentre.org, za klasę SingleApplication.
Podziękowania dla Alfredo Carreto, za jego tłumaczenie na język hiszpański i korektę ( http://electronicosmx.comxa.com)
[it]
Grazie a Qt Software per le loro librerie Qt (http://www.qtsoftware.com/), licenzate sotto GNU/GPL.
Grazie a Everaldo Coelho per il tema icone Crystal SVG ( http://www.iconfinder.com/iconsets/crystalproject) licenzato sotto LGPL.
Grazie a Nuno Pinheiro per il tema icone Oxygen (http://www.oxygen-icons.org/) licenzato sotto LGPL ma anche per le icone dedicate a QElectroTech.
Grazie al progetto KDE (http://www.kde.org/).
Grazie a Loic per le sue spiegazioni matematiche.
Grazie a Remi Collet per i pacchetti per Fedora.
Grazie a Laurent Trinques per i pacchetti per Debian.
Grazie a `trem' per i pacchetti per Mandriva.
Grazie a TuxFamily (http://tuxfamily.org/) per l'ospitalità al progetto.
Grazie a `Nishiki' per i suoi elementi ed il supporto.
Grazie a qtcentre.org per la loro classe SingleApplication.
Grazie a Alfredo Carreto per le traduzioni e le correzioni in spagnolo (http://electronicosmx.comxa.com).
Grazie a 'Dr.Slump' e 'Silvio' per la traduzione in italiano.
Grazie a Jose Carlos Martins per la traduzione in portoghese.
Grazie a Pavel Fric per la traduzione in ceco.
Grazie a Pawel Smiech per la traduzione in polacco.
Grazie a Yuriy Litkevich per la traduzione in russo .
Grazie a Youssef Ouamalkran per la traduzione in catalano.
Grazie a Gabi Mandoc per la traduzione in rumeno.
Grazie a Markus Budde e Jonas Stein per la traduzione in tedesco.
Grazie a Mohammed Souabni per la traduzione in arabo.
Grazie a Uroš Platiše per la traduzione in sloveno.
Grazie a Antun Marakovic per la traduzione in croato.
Grazie a Nikos Papadopoylos e Yannis Gyftomitros per la traduzione in greco.
Grazie a Markos Chandras per i pacchetti per Gentoo.
[el]
Ευχαριστίες στην Qt Software για την βιβλιοθήκη Qt ( http://www.qtsoftware.com/ ), αδειοδοτημένο ως GNU/GPL.
Ευχαριστίες στον Everaldo Coelho για τα εικονίδια του θέματος Crystal SVG ( http://www.iconfinder.com/iconsets/crystalproject) αδειοδοτημένο ως LGPL.
Ευχαριστίες to Nuno Pinheiro για τα εικονίδια του θέματος Oxygen ( http://www.oxygen-icons.org/ ) αδειοδοτημένο ως LGPL και επίσης για τα εικονίδια ειδικά για το QElectroTech.
Ευχαριστίες στο έργο KDE ( http://www.kde.org/ ).
Ευχαριστίες στον Loic για τις εξηγήσεις σχετικές με μαθηματικά.
Ευχαριστίες στον Remi Collet για τα πακέτα Fedora.
Ευχαριστίες στον Laurent Trinques για τα πακέτα Debian.
Ευχαριστίες στον `trem' για τα πακέτα Mandriva.
Ευχαριστίες στο TuxFamily ( http://tuxfamily.org/ ) για τη φιλοξενία του έργου.
Ευχαριστίες στον `Nishiki' για τα στοιχεία και την υποστήριξη του.
Ευχαριστίες στο qtcentre.org για την κλάση SingleApplication.
Ευχαριστίες στον Alfredo Carreto για τις μεταφράσεις του και για την επισκευή της Ισπανικής μετάφρασης ( http://electronicosmx.comxa.com )
Ευχαριστίες στον 'Dr.Slump' και τον Sivio για τις μεταφράσεις τους στα Ιταλικά
Ευχαριστίες στον Jose Carlos Martins για την μετάφραση στα Πορτογαλικά
Ευχαριστίες στον Pavel Fric Για την μετάφραση στα Τσέχικα
Ευχαριστίες στον Pawel Smiech για την Πολωνική μετάφραση
Ευχαριστίες στον Yuriy Litkevich για τις μεταφράσεις του στα Ρώσικα
Ευχαριστίες στον Youssef Ouamalkran για τις μεταφράσεις του στα Καταλανικά
Ευχαριστίες στον Gabi Mandoc για τις μεταφράσεις του στα Ρουμανικά
Ευχαριστίες στους Markus Budde και Jonas Stein για τις μεταφράσεις τους στα Γερμανικά
Ευχαριστίες στον Mohamed Souabni για τις μεταφράσεις του στα Αραβικά
Ευχαριστίες στον Uroš Platiše για τις μεταφράσεις του στα Σλοβένικα
Ευχαριστίες στον Antun Marakovic για τις μεταφράσεις του στα Κροατικά
Ευχαριστίες στους Νίκο Παπαδόπουλο και Γιάννη Γυφτομήτρο για τις μεταφράσεις τους στα Ελληνικά
Ευχαριστίες στον Markos Chandras για τα πακέτα Gentoo.
Merci <20> Trolltech pour la biblioth<74>que Qt ( http://trolltech.com/ ), sous
licence GNU/GPL.
Merci <20> Everaldo Coelho pour le th<EFBFBD>me d'ic<69>nes Crystal SVG (
http://www.everaldo.com/crystal/ ) sous licence LGPL, ainsi qu'au projet KDE (
http://www.kde.org/ ).
Merci <20> Loic pour ses explications d'ordre math<74>matique.

View File

@@ -1,86 +0,0 @@
====== Changelog 0.11 -> 0.2 ======
À partir de la version 0.2, QElectroTech est disponible en français, anglais, mais aussi :
* en espagnol, grâce aux traductions de Youssef ;
* en russe, grâce aux traductions de Yuriy ;
* en portugais, grâce aux traductions de José.
L'application utilise désormais le thème d'icônes Oxygen, réalisé par Nuno Pinheiro pour le projet KDE.
===== Notion de fichier projet =====
Un fichier .qet peut désormais contenir zéro, un ou plusieurs schémas électriques. Les éléments composant ces schémas sont embarqués dans le fichier projet au moment où ils sont posés sur un schéma. Le panel d'éléments affiche donc désormais :
* les projets ouverts, avec, sous chaque projet :
* les schémas de ce projet,
* la collection embarquée du projet (catégories et éléments utilisés dans les schémas)
* la collection commune fournie par QET,
* et la collection personnelle de l'utilisateur.
===== Éditeur de schémas =====
* Il est désormais possible de déplacer et copier les catégories et éléments par simple glisser-déposer (drag'n drop) dans le panel d'éléments.
* La collection embarquée est manipulable au même titre que la collection utilisateur. Les éléments inutilisés dans le projet apparaissent sur fond rouge et un dialogue permet de les purger rapidement.
* Chaque projet embarque également (au niveau de ses propriétés) les paramétrages par défaut pour les nouveaux schémas, cartouches et conducteurs.
* Il est possible de changer l'ordre des schémas dans le projet en déplaçant les onglets qui les représente. Dans le champ "Folio" des cartouches, on peut se référer à la position du schéma courant ou au nombre total de schémas dans le projet en écrivant respectivement %id et %total.
* Lors du chargement d'un fichier .qet, si des éléments ne sont pas trouvés, ils sont remplacés par un élément "fantôme", ce qui évite de perdre certaines informations lors de l'enregistrement du fichier.
* Le rendu avec un zoom réduit a été amélioré.
* Enfin, le logiciel gère l'ouverture en lecture seule d'un fichier projet.
==== Impression et export ====
À partir de la version 0.2, QElectroTech :
* propose d'utiliser une imprimante réelle ou bien de générer un document PDF ou PostScript, et ce sous Windows comme sous X11.
* génère un aperçu avant l'impression d'un projet. Cet aperçu permet de choisir les options d'impression mais également les schémas à imprimer ou non.
À noter toutefois une limitation pour les impressions PDF/PS sous Windows : le dialogue de mise en page, permettant de spécifier le format du papier ainsi que ses marges, n'est pas disponible.
Le dialogue "Exporter" (pour générer un fichier image d'un schéma) a également été refait dans l'optique d'un export simultané de tous les schémas du projet.
===== Éditeur d'éléments =====
* Lorsque l'on dessine une ligne dans l'éditeur d'éléments, il est possible de choisir un embout différent pour chaque extrémité, comme par exemple une flèche, un cercle, un carré ou, tout simplement, un bout de ligne normal.
* La forme "Rectangle" a été ajoutée.
* On peut enregistrer un élément en désignant un fichier (= comportement en 0.11) ou bien en choisissant un élément cible dans une liste reprenant l'arborescence du panel d'éléments.
* Si l'on maintient la touche Shift lorsque l'on ajoute une partie (droite, cercle, texte, ...), l'outil en cours est conservé après le dessin. Sinon l'éditeur repasse sur l'outil de sélection.
* La grille a été améliorée : sa densité varie en fonction du zoom ; les points correspondant à ceux de la grille de l'éditeur de schémas sont mis en valeur.
* L'accrochage à la grille (aka "snap to grid", également connu sous le nom de grille magnétique ou encore grille aimantée) a été ajouté. Le dessin s'y accroche désormais avec une précision de 1px. On peut travailler en coordonnées libres en maintenant la touche Ctrl enfoncée durant le dessin.
* Le copier-coller a été implémenté : il est possible de coller :
* avec le bouton du milieu de la souris
* en choisissant une "zone de collage" sur l'élément (Ctrl+Shift+V)
* directement (Ctrl+V) : les parties collées sont placées à côté des parties copiées ; si on recolle les parties, elles sont collées encore un cran à côté, et ce de manière incrémentale.
* Des contrôles sont désormais effectués à l'enregistrement : présence de bornes, respect du cadre, etc.
* Uniformisation des menus par rapport à l'éditeur de schémas
====== Changelog 0.1 -> 0.11 ======
===== Fonctionnalités et interface =====
* L'application est désormais capable d'ouvrir un fichier élément passe en paramètre
* L'application se lance désormais une seule fois par utilisateur
* Lors de l'ouverture d'un fichier en dehors de l'application alors que QET est déjà démarré celui-ci essaye de s'afficher ou d'attirer l'attention de l'utilisateur.
* L'application vérifie que ce fichier n'est pas déjà ouvert dans tous les éditeurs de schémas / éléments.
* Ajout de fichiers permettant d'automatiser les associations de fichiers sous Windows (.bat et .reg) et X11 (.desktop et .xml)
* Ajout de menus "Récemment ouverts" pour accéder aux fichiers récents dans les éditeurs de schémas et éléments.
* Ajout d'un splash screen
* La hauteur du schéma est désormais gérée via un système de lignes, dont le nombre et la hauteur sont ajustables.
* Il est également possible d'afficher ou non les en-têtes des lignes et/ou des colonnes.
* Ajout d'une option --lang-dir
* Ajout d'une description dans le dialogue des options d'impression
* Ajout de pages de manuel Unix (`man') en anglais et en français
===== Corrections de bugs =====
* Bug #12 : QET provoquait une erreur de segmentation dès son démarrage dans un environnement sans systray
* Bug #14 : il manquait un / dans le chemin proposé lors de l'impression vers un PDF
* Bug #15 : Mauvais positionnement des champs de texte sur le schéma
* Bug #16 : Mauvaise gestion des modifications du texte d'un conducteur
* La classe DiagramView écrivait sur la sortie d'erreur sans fin de ligne
* L'option --config-dir était mal prise en compte
* Après fermeture d'un schema, le menu Fenêtres n'était pas correctement mis à jour
* Les textes des éléments, des conducteurs, du cartouche ainsi que les textes indépendants utilisent désormais tous la même police.
* Remise à niveau de l'impression suite au passage à Qt 4.4
===== Code et détails techniques =====
* Corrections pour que QET compile avec gcc-4.3
* Les classes Conductor et Element héritent désormais de QObject (dépendance sur Qt 4.4)
* Affinage du constructeur de la classe QETApp
* Moins d'avertissements à la compilation (testé avec gcc 4.3)
* Moins d'inclusions non pertinentes
* Nettoyage du trunk : déplacement des sources dans un sous-répertoire

1322
Doxyfile

File diff suppressed because it is too large Load Diff

View File

@@ -1,136 +0,0 @@
[en]
The elements collection provided along with QElectroTech is provided as is and
without any warranty of fitness for your purpose or working.
The usage, the modification and the integration of the elements into electric
diagrams is allowed without any condition, whatever the final license of the
diagrams is.
If you redistribute all or a part of the QElectroTech collection, with or
without any modification, out of an electric diagram, you must respect the
conditions of the CC-BY license:
This work is licensed under the Creative Commons Attribution 3.0 License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative
Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
[fr]
La collection d'éléments fournie avec QElectroTech est fournie telle quelle et
sans la moindre garantie qu'elle convienne à votre utilisation ou qu'elle
fonctionne.
L'utilisation, la modification et l'intégration des éléments dans des schémas
électriques est autorisée sans condition, quelle que soit la licence finale des
schémas.
Si vous redistribuez tout ou partie de la collection QElectroTech, avec ou sans
modification, en dehors d'un schéma électrique, vous devrez respecter les
conditions de la licence CC-BY :
Cette création est mise à disposition selon le Contrat Paternité 3.0
disponible en ligne http://creativecommons.org/licenses/by/3.0/ ou par
courrier postal à Creative Commons, 171 Second Street, Suite 300, San Francisco,
California 94105, USA.
[ru]
Коллекция элементов, поставляемая вместе с QElectroTech, поставляется "как есть"
и без каких-либо гарантий пригодности для той или иной цели или работы.
Использование, изменение и интеграция элементов в электрическую
схему разрешается без каких-либо условий, безотносительно конечной лицензии на
схему.
Если Вы распространяете всю или часть коллекции QElectroTech, с или без
изменений, отдельно от электрической схемы, Вы должны соблюдать условия лицензии
CC-BY:
Эта работа лицензирована на условиях Creative Commons Attribution 3.0 License.
Чтобы увидеть копию этой лицензии, посетите
http://creativecommons.org/licenses/by/3.0/ или отправте письмо в Creative
Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
(данный перевод, на русский язык, является вольным и выполнен не юристом!)
[pt]
A colecção de elementos fornecida com o programa QElectroTech é fornecida como é
e sem nenhuma garantia da aptidão para o seu uso e sem garantia de que funciona.
É permitido, sem condição alguma, qualquer que seja a licença final, usar,
editar e incluir estes elementos em esquemas eléctricos.
Se você redistribuir uma parte ou toda a colecção de elementos do programa
QElectroTech, tendo editado ou não os elementos, sem ser num esquema eléctrico,
tem de respeitar as condições da licença CC-BY:
Este trabalho está licenciado de acordo com os termos da licença Creative
Commons Attribution 3.0 License.
Para ver uma cópia da licença visite http://creativecommons.org/licenses/by/3.0/
ou envie uma carta para o endereço Creative Commons, 171 Second Street, Suite
300, San Francisco, California, 94105, USA.
[es]
La colección de elementos QElectrotech es distruibida tal cual y sin ninguna
garantía a la conveniencia de su uso y sin garantía de que funciona.
Se permite sin condicione alguna, cualquiera que sea la licencia final, usar,
editar, e incluir estos elementos en esquemas eléctricos.
Si usted redistribuye una parte de la colección o toda la collección de
QElectrotech, con o sin ediciones, fuera de un esquema eléctrico, tiene que
respetar las condiciones de la licencia CC-BY:
Esta obra está bajo una licencia Reconocimiento 3.0 de Creative Commons.
Para ver una copia de esta licencia, visite
http://creativecommons.org/licenses/by/3.0/ o envie una carta a Creative
Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
[ca]
La col·lecció de símbols QElectrotech és distribuïda tal qual i sense cap
garantia d'idoneïtat d'ús ni de funcionament.
Es permet incondicionalment, amb independència de la llicència final, emprar,
editar, i incloure aquests símbols en esquemes elèctrics.
Si vostè redistribueix una part de la col·lecció de QElectrotech o tota ella,
amb condicions o sense, separadament d'un esquema elèctric, haurà de respectar
les condicions de la llicència CC-BY:
Aquesta obra es troba sota una llicència Reconeixement 3.0 de Creative Commons.
Per veure una còpia d'aquesta llicència visiti
http://creativecommons.org/licenses/by/3.0/ o enviï una carta a Creative
Commons, 171 Second Street, Suite 300, San Francisco, California 94105,
[cs]
Sbírka prvků poskytovaná společně s QElectroTechem je poskytována tak, jak je,
bez záruky nebo vhodnosti pro váš účal nebo práci.
Používání, úpravy a začlenění prvků do nákresů elektrických
obvodů se povoluje bez jakýchkoli podmínek, cokoli je konečná licence nákresu.
Pokud rozdáte celou nebo část ze sbírky QElectroTechu, s nebo bez
jakýchkoli úprav, mimo elektrický nákres, musíte brát ohledy na podmínky
licence CC-BY:
tato práce je licencována pod licencí Creative Commons Attribution 3.0 License.
Kopii této licence si můžete prohlédnout, navštivte
http://creativecommons.org/licenses/by/3.0/ nebo pošlete dopis Creative
Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
[pl]
Biblioteka elementów dostarczana wraz z QElectroTech jest w formie "taka jaka jest",
bez żadnych gwarancji przydatności.
Dozwolona jest edycja, modyfikacja i użytkowanie elementów bez żadnych warunków
i bez względu na końcową licencję tworzonych schematów.
W przypadku wykorzystywania całości lub części biblioteki elementów QElectroTech
do innych celów niż tworzenie schematów elektrycznych, należy przestrzegać
warunków licencji CC-BY:
Niniejsza praca jest licencjonowana na zasadach Creative Commons Attribution 3.0 License.
Aby zobaczyć kopię licencji, należy odwiedzić stronę internetową:
http://creativecommons.org/licenses/by/3.0/ lub wysłać list do Creative
Commons, 171 Second Street, Suite 300, San Francisco, Kalifornia 94105, USA.
[it]
La collezione di elementi che si trova in QElectroTech è fornita così com'è
senza alcuna garanzia di usabilità o funzionamento.
L'uso, la modifica e l'integrazione degli elementi negli schemi elettrici
è permessa senza condizioni, qualunque si ala licenza dello schema finale.
Distribuendo tutto o parte della collezione di QElettroTech, con o senza
modifiche, fuori da uno schema elettrico, bisogna rispettare le condizioni
della licenza CC-BY:
Questo lavoro è licenziato sotto la Licenza Creative Commons 3.0.
Per vedere una copia di questa licenza, visitate il sito
http://creativecommons.org/licenses/by/3.0/ o inviate una lettera a Creative
Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
[el]
Η συλλογή στοιχείων που παρέχεται μαζί με το QElectroTech παρέχεται ως έχει και
χωρίς καμία εγγύηση καταλληλότητας για συγκεκριμένο σκοπό ή την εργασία σας.
Η χρήση, η τροποποίηση και η ενσωμάτωση των στοιχείων στα ηλεκτρικά
διαγράμματα επιτρέπεται χωρίς καμία προϋπόθεση, όποια και αν είναι η τελική άδεια
των διαγραμμάτων.
Εάν αναδιανείμετε το σύνολο ή ένα μέρος της συλλογής του QElectroTech, με ή
χωρίς καμία τροποποίηση, έξω από ένα ηλεκτρικό διάγραμμα, θα πρέπει να σεβαστείτε
τους όρους της άδειας CC-BY:
Το έργο αυτό είναι υπό την άδεια Creative Commons Attribution 3.0 License.
Για να δείτε ένα αντίγραφο της άδειας αυτής, επισκεφτείτε το
http://creativecommons.org/licenses/by/3.0/ ή στείλτε μια επιστολή στο Creative
Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.

109
INSTALL
View File

@@ -1,109 +0,0 @@
[en]
Requirements :
libQt4 (see packages libqt4*)
cupsys-bsd for printing
Howto compile :
$ qmake (qmake-qt4 for Debian-based systems)
$ make
# umask 0022
# make install
[fr]
Pré-requis :
libQt4 (paquets libqt4*)
cupsys-bsd pour l'impression
Comment compiler :
$ qmake (qmake-qt4 pour les systèmes basés sur Debian)
$ make
# umask 0022
# make install
[ru]
Зависимости:
libQt4 (пакет libqt4*)
cupsys-bsd для печати
Как компилировать?:
$ qmake (qmake-qt4 для систем основанных на Debian)
$ make
# umask 0022
# make install
[pt]
Dependências:
libQt4 (ver pacotes libqt4*)
cupsys-bsd para impressão
Como compilar:
$ qmake (qmake-qt4 para sistemas baseados em Debian)
$ make
# umask 0022
# make install
[es]
Dependencias:
libQt4 (paquetes libqt4*)
cupsys-bsd para imprimir
Cómo compilar:
$ qmake (qmake-qt4 para los sistemas basados en Debian)
$ make
# umask 0022
# make install
[ca]
Dependències:
libQt4 (paquets libqt4*)
cupsys-bsd per imprimir
Com compilar:
$ qmake (qmake-qt4 pels sistemes basats en Debian)
$ make
# umask 0022
# make install
[cs]
Požadavky :
libQt4 (viz balíček libqt4*)
cupsys-bsd kvůli tisku
Jak program sestavit :
$ qmake (qmake-qt4 u systémů založených na Debianu)
$ make
# umask 0022
# make install
[pl]
Zależności:
libQt4 (pakiety libqt4 *)
cupsys-bsd do druku
Sposób kompilacji:
$ qmake (qmake-qt4 dla systemów opartych na Debianie)
$ make
# umask 0022
# make install
[it]
Dipendenze:
libQt4 (vedi pacchetti libqt4*)
cupsys-bsd per la stampa
Come compilare:
$ qmake (qmake-qt4 per sistemi basati su Debian)
$ make
# umask 0022
# make install
[el]
Απαιτήσεις:
libQt4 (see packages libqt4*)
cupsys-bsd for printing
Πως να το μεταγλωττίσετε:
$ qmake (qmake-qt4 for Debian-based systems)
$ make
# umask 0022
# make install

35
README
View File

@@ -1,35 +0,0 @@
[en]
QElectroTech is a Qt4 application to design electric diagrams.
It uses XML files for elements and diagrams, and includes both a diagram editor, a element editor, and an titleblock editor.
[fr]
QElectroTech est une application Qt4 pour réaliser des schémas électriques.
QET utilise le format XML pour ses éléments et ses schémas et inclut un éditeur de schémas, un éditeur d'élément, ainsi qu'un editeur de cartouche.
[ru]
QElectroTech - приложение написанное на Qt4 и предназначенное для разработки электрических схем.
Оно использует XML-файлы для элементов и схем, и включает, как редактор схем, так и редактор элементов.
[pt]
QElectroTech é uma aplicação baseada em Qt4 para desenhar esquemas eléctricos.
QET utiliza ficheiros XML para os elementos e para os esquemas e inclui um editor de esquemas e um editor de elementos.
[es]
QElectroTech es una aplicación Qt4 para diseñar esquemas eléctricos.
Utiliza archivos XML para los elementos y esquemas, e incluye un editor de esquemas y un editor de elemento.
[cs]
QElectroTech je aplikací Qt4 určenou pro návrh nákresů elektrických obvodů.
Pro prvky a nákresy používá soubory XML, a zahrnuje v sobě jak editor nákresů, tak editor prvků.
[pl]
QElectroTech to aplikacja napisana w Qt4, przeznaczona do tworzenia schematów elektrycznych.
Wykorzystuje XML do zapisywania plików elementów i projektów. Posiada edytor schematów i elementów.
[it]
QElectroTech è una applicazione fatta in Qt4 per disegnare schemi elettrici.
QET usa il formato XML per i suoi elementi e schemi, includendo anche un editor per gli stessi.
[el]
Το QElectroTech είναι μια εφαρμογή Qt4 για σχεδίαση ηλεκτρικών διαγραμμάτων.
Χρησιμοποιεί αρχεία XML για στοιχεία και διαγράμματα, και περιλαμβάνει επεξεργαστή διαγραμμάτων καθώς και επεξεργαστή στοιχείων.

138
aboutqet.cpp Normal file
View File

@@ -0,0 +1,138 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aboutqet.h"
#include "qet.h"
/**
Constructeur
@param parent Le QWidget parent de la boite de dialogue
*/
AboutQET::AboutQET(QWidget *parent) : QDialog(parent) {
// Titre, taille, comportement...
setWindowTitle(tr("\300 propos de QElectrotech"));
setMinimumWidth(680);
setMinimumHeight(350);
setModal(true);
// Trois onglets
QTabWidget *onglets = new QTabWidget(this);
onglets -> addTab(ongletAPropos(), tr("\300 &propos"));
onglets -> addTab(ongletAuteurs(), tr("A&uteurs"));
onglets -> addTab(ongletLicence(), tr("&Accord de licence"));
// Un bouton pour fermer la boite de dialogue
QDialogButtonBox *boutons = new QDialogButtonBox(QDialogButtonBox::Close);
connect(boutons, SIGNAL(accepted()), this, SLOT(accept()));
connect(boutons, SIGNAL(rejected()), this, SLOT(accept()));
// Le tout dans une disposition verticale
QVBoxLayout *disposition = new QVBoxLayout();
disposition -> addWidget(titre());
disposition -> addWidget(onglets);
disposition -> addWidget(boutons);
setLayout(disposition);
}
/**
Destructeur
*/
AboutQET::~AboutQET() {
}
/**
@return Le titre QElectroTech avec son icone
*/
QWidget *AboutQET::titre() const {
QWidget *icone_et_titre = new QWidget();
// icone
QLabel *icone = new QLabel();
icone -> setPixmap(QIcon(":/ico/qelectrotech.png").pixmap(48, 48));
// label "QElectroTech"
QLabel *titre = new QLabel("<span style=\"font-weight:0;font-size:16pt;\">QElectroTech v" + QET::version + "</span>");
titre -> setTextFormat(Qt::RichText);
// le tout dans une grille
QGridLayout *dispo_horiz = new QGridLayout();
dispo_horiz -> addWidget(icone, 0, 0);
dispo_horiz -> addWidget(titre, 0, 1);
dispo_horiz -> setColumnStretch(0, 1);
dispo_horiz -> setColumnStretch(1, 100);
icone_et_titre -> setLayout(dispo_horiz);
return(icone_et_titre);
}
/**
@return Le widget contenu par l'onglet <20> A propos <20>
*/
QWidget *AboutQET::ongletAPropos() const {
QLabel *apropos = new QLabel(
tr("QElectroTech, une application de r\351alisation de sch\351mas \351lectriques.") +
"<br><br>" +
tr("\251 2006-2007 Les d\351veloppeurs de QElectroTech") +
"<br><br>"
"<a href=\"http://qelectrotech.tuxfamily.org/\">"
"http://qelectrotech.tuxfamily.org/</a>"
);
apropos -> setAlignment(Qt::AlignCenter);
apropos -> setOpenExternalLinks(true);
apropos -> setTextFormat(Qt::RichText);
return(apropos);
}
/**
@return Le widget contenu par l'onglet <20> Auteurs <20>
*/
QWidget *AboutQET::ongletAuteurs() const {
QLabel *auteurs = new QLabel(
"<span style=\"text-decoration: underline;\">" +
tr("Id\351e originale") +
"</span> : Beno\356t Ansieau "
"&lt;<a href=\"mailto:benoit.ansieau@gmail.com\">"
"benoit.ansieau@gmail.com</a>&gt;"
"<br><br>"
"<span style=\"text-decoration: underline;\">" +
tr("Programmation") +
"</span> : Xavier Guerrin "
"&lt;<a href=\"mailto:xavier.guerrin@gmail.com\">"
"xavier.guerrin@gmail.com</a>&gt;"
);
auteurs -> setAlignment(Qt::AlignCenter);
auteurs -> setOpenExternalLinks(true);
auteurs -> setTextFormat(Qt::RichText);
return(auteurs);
}
/**
@return Le widget contenu par l'onglet <20> Accord de Licence <20>
*/
QWidget *AboutQET::ongletLicence() const {
QWidget *licence = new QWidget();
// label
QLabel *titre_licence = new QLabel(tr("Ce programme est sous licence GNU/GPL."));
// texte de la GNU/GPL dans une zone de texte scrollable non editable
QTextEdit *texte_licence = new QTextEdit();
texte_licence -> setPlainText(QET::license());
texte_licence -> setReadOnly(true);
// le tout dans une disposition verticale
QVBoxLayout *dispo_licence = new QVBoxLayout();
dispo_licence -> addWidget(titre_licence);
dispo_licence -> addWidget(texte_licence);
licence -> setLayout(dispo_licence);
return(licence);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -17,15 +17,15 @@
*/
#ifndef ABOUTQET_H
#define ABOUTQET_H
#include <QDialog>
class QLabel;
#include <QtGui>
/**
This class represents the "About QElectroTech" dialog.
Cette classe represente la boite de dialogue
« A propos de QElectroTech »
*/
class AboutQET : public QDialog {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
AboutQET(QWidget * = 0);
virtual ~AboutQET();
@@ -33,14 +33,11 @@ class AboutQET : public QDialog {
private:
AboutQET(AboutQET &);
// methods
// methodes
private:
QWidget *title() const;
QWidget *aboutTab() const;
QWidget *authorsTab() const;
QWidget *translatorsTab() const;
QWidget *contributorsTab() const;
QWidget *licenseTab() const;
void addAuthor(QLabel *, const QString &, const QString &, const QString &) const;
QWidget *titre() const;
QWidget *ongletAPropos() const;
QWidget *ongletAuteurs() const;
QWidget *ongletLicence() const;
};
#endif

231
borderinset.cpp Normal file
View File

@@ -0,0 +1,231 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "borderinset.h"
#include "qetapp.h"
/**
Constructeur simple : construit une bordure de 15 colonnes de 50x500 avec
un cartouche de 400x50.
@param parent QObject parent de ce BorderInset
*/
BorderInset::BorderInset(QObject *parent) : QObject(parent) {
nb_columns = qMax(3, QETApp::settings().value("diagrameditor/defaultcols", 15).toInt());
min_nb_columns = 3;
columns_width = QETApp::settings().value("diagrameditor/defaultcolsize", 50.0).toDouble();
columns_height = QETApp::settings().value("diagrameditor/defaultheight", 500.0).toDouble();
min_columns_height = 80.0;
inset_width = nb_columns * columns_width;
inset_height = 50.0;
columns_header_height = 20.0;
display_inset = true;
display_columns = true;
display_border = true;
updateRectangles();
bi_author = QETApp::settings().value("diagrameditor/defaultauthor").toString();
bi_title = QETApp::settings().value("diagrameditor/defaulttitle").toString();
bi_folio = QETApp::settings().value("diagrameditor/defaultfolio").toString();
bi_filename = QETApp::settings().value("diagrameditor/defaultfilename").toString();
QString settings_date = QETApp::settings().value("diagrameditor/defaultdate").toString();
if (settings_date == "now") bi_date = QDate::currentDate();
else if (settings_date.isEmpty() || settings_date == "null") bi_date = QDate();
else bi_date = QDate::fromString(settings_date, "yyyyMMdd");
}
/**
Destructeur - ne fait rien
*/
BorderInset::~BorderInset() {
}
/**
Methode recalculant les rectangles composant le cadre et le cartouche en
fonction des attributs de taille
*/
void BorderInset::updateRectangles() {
// rectangle delimitant le schema
QRectF previous_border = border;
border = QRectF(0, 0, nb_columns * columns_width, columns_height);
if (border != previous_border) emit(borderChanged(previous_border, border));
// rectangles relatifs au cartouche
inset = QRectF(border.bottomLeft().x(), border.bottomLeft().y(), inset_width, inset_height);
inset_author = QRectF(inset.topLeft(), QSizeF(2.0 * inset_width / 9.0, 0.5 * inset_height));
inset_date = QRectF(inset_author.bottomLeft(), inset_author.size());
inset_title = QRectF(inset_author.topRight(), QSizeF(5.0 * inset_width / 9.0, inset_height));
inset_file = QRectF(inset_title.topRight(), inset_author.size());
inset_folio = QRectF(inset_file.bottomLeft(), inset_author.size());
}
/**
Dessine le cadre et le cartouche
@param qp QPainter a utiliser pour dessiner le cadre et le cartouche
@param x Abscisse du cadre
@param y Ordonnee du cadre
*/
void BorderInset::draw(QPainter *qp, qreal x, qreal y) {
// translate tous les rectangles
border .translate(x, y);
inset .translate(x, y);
inset_author.translate(x, y);
inset_date .translate(x, y);
inset_title .translate(x, y);
inset_file .translate(x, y);
inset_folio .translate(x, y);
// prepare le QPainter
qp -> save();
qp -> setPen(Qt::black);
qp -> setBrush(Qt::NoBrush);
// dessine le cadre
if (display_border) qp -> drawRect(border);
// dessine la numerotation des colonnes
if (display_columns) {
qp -> setBrush(Qt::white);
for (int i = 1 ; i <= nb_columns ; ++ i) {
QRectF numbered_rectangle = QRectF(
border.topLeft().x() + ((i - 1) * columns_width),
border.topLeft().y(),
columns_width,
columns_header_height
);
qp -> drawRect(numbered_rectangle);
qp -> drawText(numbered_rectangle, Qt::AlignVCenter | Qt::AlignCenter, QString("%1").arg(i));
}
}
// dessine le cartouche
if (display_inset) {
qp -> setBrush(Qt::white);
qp -> drawRect(inset);
qp -> drawRect(inset_author);
qp -> drawText(inset_author, Qt::AlignVCenter | Qt::AlignLeft, tr(" Auteur : ") + bi_author);
qp -> drawRect(inset_date);
qp -> drawText(inset_date, Qt::AlignVCenter | Qt::AlignLeft, tr(" Date : ") + bi_date.toString("dd/MM/yyyy"));
qp -> drawRect(inset_title);
qp -> drawText(inset_title, Qt::AlignVCenter | Qt::AlignCenter, tr("Titre du document : ") + bi_title);
qp -> drawRect(inset_file);
qp -> drawText(inset_file, Qt::AlignVCenter | Qt::AlignLeft, tr(" Fichier : ") + bi_filename);
qp -> drawRect(inset_folio);
qp -> drawText(inset_folio, Qt::AlignVCenter | Qt::AlignLeft, tr(" Folio : ") + bi_folio);
}
qp -> restore();
// annule la translation des rectangles
border .translate(-x, -y);
inset .translate(-x, -y);
inset_author.translate(-x, -y);
inset_date .translate(-x, -y);
inset_title .translate(-x, -y);
inset_file .translate(-x, -y);
inset_folio .translate(-x, -y);
}
/**
Ajoute une colonne.
*/
void BorderInset::addColumn() {
++ nb_columns;
setInsetWidth(nb_columns * columns_width);
updateRectangles();
}
/**
Enleve une colonne. Il doit rester au moins 3 colonnes.
*/
void BorderInset::removeColumn() {
if (nb_columns == min_nb_columns) return;
-- nb_columns;
setInsetWidth(nb_columns * columns_width);
updateRectangles();
}
/**
Permet de changer le nombre de colonnes.
Si ce nombre de colonnes est inferieur au minimum requis, cette fonction ne
fait rien
@param nb_c nouveau nombre de colonnes
@see minNbColumns()
*/
void BorderInset::setNbColumns(int nb_c) {
if (nb_c < min_nb_columns) return;
nb_columns = nb_c;
setInsetWidth(nb_columns * columns_width);
updateRectangles();
}
/**
Change la largeur des colonnes ; celle-ci doit rester comprise entre 10 et
200px.
*/
void BorderInset::setColumnsWidth(const qreal &new_cw) {
columns_width = qBound(10.0, new_cw, 200.0);
updateRectangles();
}
/**
Change la hauteur des en-tetes contenant les numeros de colonnes. Celle-ci
doit rester comprise entre 5 et 50 px.
*/
void BorderInset::setColumnsHeaderHeight(const qreal &new_chh) {
columns_header_height = qBound(5.0, new_chh, 50.0);
updateRectangles();
}
/**
Change la hauteur des colonnes (et donc du cadre). Cette hauteur doit
rester superieure a la hauteur des en-tetes de colonnes + 20px.
*/
void BorderInset::setColumnsHeight(const qreal &new_ch) {
columns_height = qMax(columns_header_height + min_columns_height, new_ch);
updateRectangles();
}
/**
Change la largeur du cartouche. Cette largeur doit rester comprise entre
100px et la largeur du cartouche
*/
void BorderInset::setInsetWidth(const qreal &new_iw) {
inset_width = qMax(100.0, qMin(nb_columns * columns_width, new_iw));
updateRectangles();
}
/**
Change la hauteur du cartouche. Cette largeur doit rester comprise entre
20px et la hauteur du cartouche.
*/
void BorderInset::setInsetHeight(const qreal &new_ih) {
inset_height = qMax(20.0, qMin(columns_height, new_ih));
updateRectangles();
}
/**
Ajuste la largeur du cartouche de facon a ce que celui-ci soit aussi large
que le schema
*/
void BorderInset::adjustInsetToColumns() {
setInsetWidth(nbColumn() * columnsWidth());
}

182
borderinset.h Normal file
View File

@@ -0,0 +1,182 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BORDERINSET_H
#define BORDERINSET_H
#include "insetproperties.h"
#include <QObject>
#include <QRectF>
#include <QPainter>
#include <QDate>
/**
Cette classe represente l'ensemble bordure + cartouche qui encadre le
schema electrique.
*/
class BorderInset : public QObject {
Q_OBJECT
// constructeurs, destructeur
public:
BorderInset(QObject * = 0);
virtual ~BorderInset();
private:
BorderInset(const BorderInset &);
// methodes
public:
void draw(QPainter *, qreal = 0.0, qreal = 0.0);
// methodes d'acces en lecture aux dimensions
/// @return le nombre de colonnes du schema
int nbColumn() const { return(nb_columns); }
/// @return la taille des colonnes en pixels
qreal columnsWidth() const { return(columns_width); }
/// @return la hauteur, en pixels, des en-tetes des colonnes
qreal columnsHeaderHeight() const { return(columns_header_height); }
/// @return la hauteur des colonnes, en-tetes inclus
qreal columnsHeight() const { return(columns_height); }
/// @return la largeur de la bordure
qreal borderWidth() const { return(nb_columns * columns_width); }
/// @return la hauteur de la bordure
qreal borderHeight() const { return(columns_height + inset_height); }
/// @return la largeur du cartouche
qreal insetWidth() const { return(inset_width); }
/// @return la hauteur du cartouche
qreal insetHeight() const { return(inset_height); }
/// @return la hauteur minimale acceptee des colonnes
qreal minColumnsHeight() const { return(min_columns_height); }
/// @return le nombre minimum accepte de colonnes
int minNbColumns() const { return(min_nb_columns); }
// methodes d'acces en lecture aux informations du cartouche
/// @return le champ "Auteur" du cartouche
QString author() const { return(bi_author); }
/// @return le champ "Date" du cartouche
QDate date() const { return(bi_date); }
/// @return le champ "Titre" du cartouche
QString title() const { return(bi_title); }
/// @return le champ "Folio" du cartouche
QString folio() const { return(bi_folio); }
/// @return le champ "Fichier" du cartouche
QString fileName() const { return(bi_filename); }
// methodes d'acces en lecture aux options
/// @return true si le cartouche est affiche, false sinon
bool insetIsDisplayed() const { return(display_inset); }
/// @return true si les entetes des colonnes sont affiches, false sinon
bool columnsAreDisplayed() const { return(display_columns); }
/// @return true si la bordure est affichee, false sinon
bool borderIsDisplayed() const { return(display_border); }
// methodes d'acces en ecriture aux dimensions
void addColumn ();
void removeColumn ();
void setNbColumns (int);
void setColumnsWidth (const qreal &);
void setColumnsHeaderHeight(const qreal &);
void setColumnsHeight (const qreal &);
void setInsetWidth (const qreal &);
void setInsetHeight (const qreal &);
void adjustInsetToColumns ();
// methodes d'acces en ecriture aux informations du cartouche
/// @param author le nouveau contenu du champ "Auteur"
void setAuthor (const QString &author) { bi_author = author; }
/// @param date le nouveau contenu du champ "Date"
void setDate (const QDate &date) { bi_date = date; }
/// @param title le nouveau contenu du champ "Titre"
void setTitle (const QString &title) { bi_title = title; }
/// @param folio le nouveau contenu du champ "Folio"
void setFolio (const QString &folio) { bi_folio = folio; }
/// @param filename le nouveau contenu du champ "Fichier"
void setFileName (const QString &filename) { bi_filename = filename; }
/// @return les proprietes du cartouches
InsetProperties exportInset() {
InsetProperties ip;
ip.author = bi_author;
ip.date = bi_date;
ip.title = bi_title;
ip.folio = bi_folio;
ip.filename = bi_filename;
return(ip);
}
/// @param ip les nouvelles proprietes du cartouche
void importInset(const InsetProperties &ip) {
bi_author = ip.author;
bi_date = ip.date;
bi_title = ip.title;
bi_folio = ip.folio;
bi_filename = ip.filename;
}
// methodes d'acces en ecriture aux options
/// @param di true pour afficher le cartouche, false sinon
void displayInset (bool di) { display_inset = di; }
/// @param dc true pour afficher les entetes des colonnes, false sinon
void displayColumns (bool dc) { display_columns = dc; }
/// @param db true pour afficher la bordure du schema, false sinon
void displayBorder (bool db) { display_border = db; }
private:
void updateRectangles();
// signaux
signals:
/**
Signal emis lorsque la bordure change
@param old_border Ancienne bordure
@param new_border Nouvelle bordure
*/
void borderChanged(QRectF old_border, QRectF new_border);
// attributs
private:
// informations du cartouche
QString bi_author;
QDate bi_date;
QString bi_title;
QString bi_folio;
QString bi_filename;
// dimensions du cadre et du cartouche
int nb_columns;
int min_nb_columns;
qreal columns_width;
qreal columns_header_height;
qreal columns_height;
qreal min_columns_height;
qreal inset_width;
qreal inset_height;
// rectangles utilises pour le dessin
QRectF border;
QRectF inset;
QRectF inset_author;
QRectF inset_date;
QRectF inset_title;
QRectF inset_file;
QRectF inset_folio;
// booleens pour les options de dessin
bool display_inset;
bool display_columns;
bool display_border;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -19,11 +19,9 @@
#include "conductor.h"
#include "conductorsegment.h"
#include "conductorsegmentprofile.h"
#include "conductortextitem.h"
#include "element.h"
#include "diagram.h"
#include "diagramcommands.h"
#include "conductorautonumerotation.h"
#define PR(x) qDebug() << #x " = " << x;
bool Conductor::pen_and_brush_initialized = false;
@@ -32,29 +30,21 @@ QBrush Conductor::conductor_brush = QBrush();
QBrush Conductor::square_brush = QBrush(Qt::darkGreen);
/**
Constructeur
@param p1 Premiere Borne a laquelle le conducteur est lie
@param p2 Seconde Borne a laquelle le conducteur est lie
@param parent_diagram QGraphicsScene a laquelle appartient le conducteur
@param p1 Premiere Borne a laquelle le conducteur est lie
@param p2 Seconde Borne a laquelle le conducteur est lie
@param parent Element parent du conducteur (0 par defaut)
@param scene QGraphicsScene a laquelle appartient le conducteur
*/
Conductor::Conductor(Terminal *p1, Terminal* p2, Diagram *parent_diagram) :
QObject(),
QGraphicsPathItem(0, parent_diagram),
Conductor::Conductor(Terminal *p1, Terminal* p2, Element *parent, QGraphicsScene *scene) :
QGraphicsPathItem(parent, scene),
terminal1(p1),
terminal2(p2),
destroyed_(false),
text_item(0),
destroyed(false),
segments(NULL),
moving_point(false),
moving_segment(false),
previous_z_value(zValue()),
modified_path(false),
has_to_save_profile(false),
segments_squares_scale_(1.0),
must_highlight_(Conductor::None)
has_to_save_profile(false)
{
//set Zvalue at 9 to be upper than the DiagramImageItem and bottom of element(10)
setZValue(9);
previous_z_value = zValue();
// ajout du conducteur a la liste de conducteurs de chacune des deux bornes
bool ajout_p1 = terminal1 -> addConductor(this);
bool ajout_p2 = terminal2 -> addConductor(this);
@@ -81,19 +71,18 @@ Conductor::Conductor(Terminal *p1, Terminal* p2, Diagram *parent_diagram) :
conductor_profiles.insert(Qt::BottomRightCorner, ConductorProfile());
// calcul du rendu du conducteur
generateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation());
priv_calculeConductor(terminal1 -> amarrageConductor(), terminal1 -> orientation(), terminal2 -> amarrageConductor(), terminal2 -> orientation());
setFlags(QGraphicsItem::ItemIsSelectable);
setAcceptsHoverEvents(true);
// ajout du champ de texte editable
text_item = new ConductorTextItem(properties_.text, this);
text_item = new DiagramTextItem();
text_item -> setFlag(QGraphicsItem::ItemIsMovable, false);
text_item -> setTextInteractionFlags(Qt::TextEditorInteraction);
text_item -> setPlainText(properties_.text);
text_item -> previous_text = properties_.text;
calculateTextItemPosition();
connect(
text_item,
SIGNAL(diagramTextChanged(DiagramTextItem *, const QString &, const QString &)),
this,
SLOT(displayedTextChanged())
);
text_item -> setParentItem(this);
}
/**
@@ -110,20 +99,51 @@ Conductor::~Conductor() {
}
/**
Met a jour la representation graphique du conducteur en recalculant son
trace. Cette fonction est typiquement appelee lorsqu'une seule des bornes du
conducteur a change de position.
Met a jour la representation graphique du conducteur.
@param rect Rectangle a mettre a jour
@see QGraphicsPathItem::update()
*/
void Conductor::updatePath(const QRectF &rect) {
void Conductor::update(const QRectF &rect) {
// appelle la bonne fonction pour calculer l'aspect du conducteur
if (nbSegments() && !conductor_profiles[currentPathType()].isNull()) {
priv_modifieConductor(
terminal1 -> amarrageConductor(), terminal1 -> orientation(),
terminal2 -> amarrageConductor(), terminal2 -> orientation()
);
} else {
priv_calculeConductor(
terminal1 -> amarrageConductor(), terminal1 -> orientation(),
terminal2 -> amarrageConductor(), terminal2 -> orientation()
);
}
calculateTextItemPosition();
QGraphicsPathItem::update(rect);
}
/**
Met a jour la representation graphique du conducteur en considerant que la
borne b a pour position pos. Cette fonction est appelee lorsqu'une seule
des bornes du conducteur a change de position.
@param rect Rectangle a mettre a jour
@param b Borne
@param newpos position de la borne b
*/
void Conductor::updateWithNewPos(const QRectF &rect, const Terminal *b, const QPointF &newpos) {
QPointF p1, p2;
p1 = terminal1 -> dockConductor();
p2 = terminal2 -> dockConductor();
if (segmentsCount() && !conductor_profiles[currentPathType()].isNull())
updateConductorPath(p1, terminal1 -> orientation(), p2, terminal2 -> orientation());
if (b == terminal1) {
p1 = newpos;
p2 = terminal2 -> amarrageConductor();
} else if (b == terminal2) {
p1 = terminal1 -> amarrageConductor();
p2 = newpos;
} else {
p1 = terminal1 -> amarrageConductor();
p2 = terminal2 -> amarrageConductor();
}
if (nbSegments() && !conductor_profiles[currentPathType()].isNull())
priv_modifieConductor(p1, terminal1 -> orientation(), p2, terminal2 -> orientation());
else
generateConductorPath(p1, terminal1 -> orientation(), p2, terminal2 -> orientation());
priv_calculeConductor(p1, terminal1 -> orientation(), p2, terminal2 -> orientation());
calculateTextItemPosition();
QGraphicsPathItem::update(rect);
}
@@ -162,13 +182,11 @@ void Conductor::segmentsToPath() {
@param p2 Coordonnees du point d'amarrage de la borne 2
@param o2 Orientation de la borne 2
*/
void Conductor::updateConductorPath(const QPointF &p1, QET::Orientation o1, const QPointF &p2, QET::Orientation o2) {
Q_UNUSED(o1);
Q_UNUSED(o2);
void Conductor::priv_modifieConductor(const QPointF &p1, QET::Orientation, const QPointF &p2, QET::Orientation) {
ConductorProfile &conductor_profile = conductor_profiles[currentPathType()];
Q_ASSERT_X(conductor_profile.segmentsCount(QET::Both) > 1, "Conductor::priv_modifieConductor", "pas de points a modifier");
Q_ASSERT_X(conductor_profile.nbSegments(QET::Both) > 1, "Conductor::priv_modifieConductor", "pas de points a modifier");
Q_ASSERT_X(!conductor_profile.isNull(), "Conductor::priv_modifieConductor", "pas de profil utilisable");
// recupere les coordonnees fournies des bornes
@@ -290,7 +308,7 @@ QHash<ConductorSegmentProfile *, qreal> Conductor::shareOffsetBetweenSegments(
@param p2 Coordonnees du point d'amarrage de la borne 2
@param o2 Orientation de la borne 2
*/
void Conductor::generateConductorPath(const QPointF &p1, QET::Orientation o1, const QPointF &p2, QET::Orientation o2) {
void Conductor::priv_calculeConductor(const QPointF &p1, QET::Orientation o1, const QPointF &p2, QET::Orientation o2) {
QPointF sp1, sp2, depart, newp1, newp2, arrivee, depart0, arrivee0;
QET::Orientation ori_depart, ori_arrivee;
@@ -332,40 +350,40 @@ void Conductor::generateConductorPath(const QPointF &p1, QET::Orientation o1, co
if (depart.y() < arrivee.y()) {
// trajet descendant
if ((ori_depart == QET::North && (ori_arrivee == QET::South || ori_arrivee == QET::West)) || (ori_depart == QET::East && ori_arrivee == QET::West)) {
// cas "3"
// cas « 3 »
int ligne_inter_x = qRound(depart.x() + arrivee.x()) / 2;
while (ligne_inter_x % Diagram::xGrid) -- ligne_inter_x;
points << QPointF(ligne_inter_x, depart.y());
points << QPointF(ligne_inter_x, arrivee.y());
} else if ((ori_depart == QET::South && (ori_arrivee == QET::North || ori_arrivee == QET::East)) || (ori_depart == QET::West && ori_arrivee == QET::East)) {
// cas "4"
// cas « 4 »
int ligne_inter_y = qRound(depart.y() + arrivee.y()) / 2;
while (ligne_inter_y % Diagram::yGrid) -- ligne_inter_y;
points << QPointF(depart.x(), ligne_inter_y);
points << QPointF(arrivee.x(), ligne_inter_y);
} else if ((ori_depart == QET::North || ori_depart == QET::East) && (ori_arrivee == QET::North || ori_arrivee == QET::East)) {
points << QPointF(arrivee.x(), depart.y()); // cas "2"
points << QPointF(arrivee.x(), depart.y()); // cas « 2 »
} else {
points << QPointF(depart.x(), arrivee.y()); // cas "1"
points << QPointF(depart.x(), arrivee.y()); // cas « 1 »
}
} else {
// trajet montant
if ((ori_depart == QET::West && (ori_arrivee == QET::East || ori_arrivee == QET::South)) || (ori_depart == QET::North && ori_arrivee == QET::South)) {
// cas "3"
// cas « 3 »
int ligne_inter_y = qRound(depart.y() + arrivee.y()) / 2;
while (ligne_inter_y % Diagram::yGrid) -- ligne_inter_y;
points << QPointF(depart.x(), ligne_inter_y);
points << QPointF(arrivee.x(), ligne_inter_y);
} else if ((ori_depart == QET::East && (ori_arrivee == QET::West || ori_arrivee == QET::North)) || (ori_depart == QET::South && ori_arrivee == QET::North)) {
// cas "4"
// cas « 4 »
int ligne_inter_x = qRound(depart.x() + arrivee.x()) / 2;
while (ligne_inter_x % Diagram::xGrid) -- ligne_inter_x;
points << QPointF(ligne_inter_x, depart.y());
points << QPointF(ligne_inter_x, arrivee.y());
} else if ((ori_depart == QET::West || ori_depart == QET::North) && (ori_arrivee == QET::West || ori_arrivee == QET::North)) {
points << QPointF(depart.x(), arrivee.y()); // cas "2"
points << QPointF(depart.x(), arrivee.y()); // cas « 2 »
} else {
points << QPointF(arrivee.x(), depart.y()); // cas "1"
points << QPointF(arrivee.x(), depart.y()); // cas « 1 »
}
}
@@ -419,57 +437,33 @@ QPointF Conductor::extendTerminal(const QPointF &terminal, QET::Orientation term
@param options Les options de style pour le conducteur
@param qw Le QWidget sur lequel on dessine
*/
void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWidget *qw) {
Q_UNUSED(qw);
void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWidget */*qw*/) {
qp -> save();
qp -> setRenderHint(QPainter::Antialiasing, false);
// determine la couleur du conducteur
QColor final_conductor_color(properties_.color);
if (must_highlight_ == Normal) {
final_conductor_color = QColor::fromRgb(69, 137, 255, 255);
} else if (must_highlight_ == Alert) {
final_conductor_color =QColor::fromRgb(255, 69, 0, 255);
} else if (isSelected()) {
final_conductor_color = Qt::red;
} else {
if (Diagram *parent_diagram = diagram()) {
if (!parent_diagram -> drawColoredConductors()) {
final_conductor_color = Qt::black;
}
}
}
// affectation du QPen et de la QBrush modifies au QPainter
qp -> setBrush(conductor_brush);
QPen final_conductor_pen = conductor_pen;
// modification du QPen generique pour lui affecter la couleur et le style adequats
final_conductor_pen.setColor(final_conductor_color);
final_conductor_pen.setStyle(properties_.style);
final_conductor_pen.setJoinStyle(Qt::SvgMiterJoin); // meilleur rendu des pointilles
// utilisation d'un trait "cosmetique" en-dessous d'un certain zoom
if (options && options -> levelOfDetail < 1.0) {
final_conductor_pen.setCosmetic(true);
qp -> setPen(conductor_pen);
if (isSelected()) {
QPen tmp = qp -> pen();
tmp.setColor(Qt::red);
qp -> setPen(tmp);
}
qp -> setPen(final_conductor_pen);
// dessin du conducteur
qp -> drawPath(path());
if (properties_.type == ConductorProperties::Single) {
qp -> setBrush(final_conductor_color);
if (isSelected()) qp -> setBrush(Qt::red);
properties_.singleLineProperties.draw(
qp,
middleSegment() -> isHorizontal() ? QET::Horizontal : QET::Vertical,
QRectF(middleSegment() -> middle() - QPointF(12.0, 12.0), QSizeF(24.0, 24.0))
QRectF(middleSegment() -> middle() - QPointF(10.0, 7.5), QSizeF(20.0, 15.0))
);
if (isSelected()) qp -> setBrush(Qt::NoBrush);
}
// decalage ideal pour le rendu centre d'un carre / cercle de 2.0 px de cote / diametre
qreal pretty_offset = (options -> levelOfDetail == 1 ? 1.0 : 1.0);
// decalage ideal pour le rendu centre d'un carre / cercle de 5.0 px de cote / diametre
qreal pretty_offset = (options -> levelOfDetail == 1 ? 2.0 : 2.5);
// dessin des points d'accroche du conducteur si celui-ci est selectionne
if (isSelected()) {
@@ -482,10 +476,10 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi
if (i > 1) {
qp -> fillRect(
QRectF(
((previous_point.x() + point.x()) / 2.0 ) - pretty_offset * segments_squares_scale_,
((previous_point.y() + point.y()) / 2.0 ) - pretty_offset * segments_squares_scale_,
2.0 * segments_squares_scale_,
2.0 * segments_squares_scale_
((previous_point.x() + point.x()) / 2.0 ) - pretty_offset,
((previous_point.y() + point.y()) / 2.0 ) - pretty_offset,
5.0,
5.0
),
square_brush
);
@@ -497,13 +491,12 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi
// dessine les eventuelles jonctions
QList<QPointF> junctions_list = junctions();
if (!junctions_list.isEmpty()) {
final_conductor_pen.setStyle(Qt::SolidLine);
QBrush junction_brush(final_conductor_color, Qt::SolidPattern);
qp -> setPen(final_conductor_pen);
QBrush junction_brush(Qt::SolidPattern);
junction_brush.setColor(isSelected() ? Qt::red : Qt::black);
qp -> setBrush(junction_brush);
qp -> setRenderHint(QPainter::Antialiasing, true);
foreach(QPointF point, junctions_list) {
qp -> drawEllipse(QRectF(point.x() - pretty_offset, point.y() - pretty_offset, 2.0, 2.0));
qp -> drawEllipse(QRectF(point.x() - pretty_offset, point.y() - pretty_offset, 5.0, 5.0));
}
}
qp -> restore();
@@ -513,7 +506,7 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi
Methode de preparation a la destruction du conducteur ; le conducteur se detache de ses deux bornes
*/
void Conductor::destroy() {
destroyed_ = true;
destroyed = true;
terminal1 -> removeConductor(this);
terminal2 -> removeConductor(this);
}
@@ -523,13 +516,6 @@ Diagram *Conductor::diagram() const {
return(qobject_cast<Diagram *>(scene()));
}
/**
@return le champ de texte associe a ce conducteur
*/
ConductorTextItem *Conductor::textItem() const {
return(text_item);
}
/**
Methode de validation d'element XML
@param e Un element XML sense represente un Conducteur
@@ -575,25 +561,22 @@ void Conductor::mousePressEvent(QGraphicsSceneMouseEvent *e) {
if (hasClickedOn(press_point, segment -> secondPoint())) {
moving_point = true;
moving_segment = false;
previous_z_value = zValue();
setZValue(5000.0);
moved_segment = segment;
break;
} else if (hasClickedOn(press_point, segment -> middle())) {
moving_point = false;
moving_segment = true;
previous_z_value = zValue();
setZValue(5000.0);
moved_segment = segment;
break;
}
segment = segment -> nextSegment();
}
if (moving_segment || moving_point) {
// en cas de debut de modification de conducteur, on memorise la position du champ de texte
before_mov_text_pos_ = text_item -> pos();
}
}
QGraphicsPathItem::mousePressEvent(e);
if (e -> modifiers() & Qt::ControlModifier) {
setSelected(!isSelected());
}
}
/**
@@ -612,7 +595,6 @@ void Conductor::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
mouse_x = qRound(mouse_x / (Diagram::xGrid * 1.0)) * Diagram::xGrid;
mouse_y = qRound(mouse_y / (Diagram::yGrid * 1.0)) * Diagram::yGrid;
}
if (moving_point) {
// la modification par points revient bientot
/*
@@ -660,36 +642,11 @@ void Conductor::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
saveProfile();
has_to_save_profile = false;
}
if (!(e -> modifiers() & Qt::ControlModifier)) {
QGraphicsPathItem::mouseReleaseEvent(e);
}
setZValue(previous_z_value);
QGraphicsPathItem::mouseReleaseEvent(e);
calculateTextItemPosition();
}
/**
Gere l'entree de la souris dans la zone du conducteur
@param e Le QGraphicsSceneHoverEvent decrivant l'evenement
*/
void Conductor::hoverEnterEvent(QGraphicsSceneHoverEvent *e) {
Q_UNUSED(e);
segments_squares_scale_ = 2.0;
if (isSelected()) {
update();
}
}
/**
Gere la sortie de la souris de la zone du conducteur
@param e Le QGraphicsSceneHoverEvent decrivant l'evenement
*/
void Conductor::hoverLeaveEvent(QGraphicsSceneHoverEvent *e) {
Q_UNUSED(e);
segments_squares_scale_ = 1.0;
if (isSelected()) {
update();
}
}
/**
Gere les mouvements de souris au dessus du conducteur
@param e Le QGraphicsSceneHoverEvent decrivant l'evenement
@@ -716,76 +673,19 @@ void Conductor::hoverMoveEvent(QGraphicsSceneHoverEvent *e) {
QGraphicsPathItem::hoverMoveEvent(e);
}
/**
Gere les changements relatifs au conducteur
Reimplemente ici pour :
* positionner le conducteur en avant-plan lorsqu'il est selectionne
@param change Type de changement
@param value Valeur relative au changement
*/
QVariant Conductor::itemChange(GraphicsItemChange change, const QVariant &value) {
if (change == QGraphicsItem::ItemSelectedChange) {
if (value.toBool()) {
// le conducteur vient de se faire selectionner
previous_z_value = zValue();
setZValue(qAbs(previous_z_value) + 10000);
} else {
// le conducteur vient de se faire deselectionner
setZValue(previous_z_value);
}
} else if (change == QGraphicsItem::ItemSceneHasChanged) {
// permet de positionner correctement le texte du conducteur lors de son ajout a un schema
calculateTextItemPosition();
} else if (change == QGraphicsItem::ItemVisibleHasChanged) {
// permet de positionner correctement le texte du conducteur lors de son ajout a un schema
calculateTextItemPosition();
}
return(QGraphicsPathItem::itemChange(change, value));
}
/**
@return Le rectangle delimitant l'espace de dessin du conducteur
*/
QRectF Conductor::boundingRect() const {
QRectF retour = QGraphicsPathItem::boundingRect();
retour.adjust(-11.0, -11.0, 11.0, 11.0);
retour.adjust(-5.0, -5.0, 5.0, 5.0);
return(retour);
}
/**
@return La forme / zone "cliquable" du conducteur (epaisseur : 5.0px).
@see variableShape()
@return La forme / zone "cliquable" du conducteur
*/
QPainterPath Conductor::shape() const {
return(variableShape(5.0));
}
/**
@return la distance en dessous de laquelle on considere qu'un point est a
proximite du trajet du conducteur. La valeur est actuellement fixee a
60.0px.
*/
qreal Conductor::nearDistance() const {
return(60.0);
}
/**
@return la zone dans laquelle dont on considere que tous les points sont a
proximite du trajet du conducteur.
@see nearDistance()
@see variableShape()
*/
QPainterPath Conductor::nearShape() const {
return(variableShape(nearDistance()));
}
/**
@return la forme du conducteur
@param thickness la moitie de l'epaisseur voulue pour cette forme
*/
QPainterPath Conductor::variableShape(const qreal &thickness) const {
qreal my_thickness = qAbs(thickness);
QList<QPointF> points = segmentsToPoints();
QPainterPath area;
QPointF previous_point;
@@ -814,31 +714,21 @@ QPainterPath Conductor::variableShape(const qreal &thickness) const {
qreal p2_x = point2 -> x();
qreal p2_y = point2 -> y();
area.setFillRule(Qt::OddEvenFill);
area.addRect(p1_x - my_thickness, p1_y - my_thickness, my_thickness * 2.0 + p2_x - p1_x, my_thickness * 2.0 + p2_y - p1_y);
area.addRect(p1_x - 5.0, p1_y - 5.0, 10.0 + p2_x - p1_x, 10.0 + p2_y - p1_y);
}
previous_point = point;
area.setFillRule(Qt::WindingFill);
area.addRect(point.x() - my_thickness, point.y() - my_thickness, my_thickness * 2.0, my_thickness * 2.0 );
area.addRect(point.x() - 5.0, point.y() - 5.0, 10.0, 10.0);
}
return(area);
}
/**
@param point un point, exprime dans les coordonnees du conducteur
@return true si le point est a proximite du conducteur, c-a-d a moins de
60px du conducteur.
*/
bool Conductor::isNearConductor(const QPointF &point) {
return(variableShape(60.1).contains(point));
}
/**
Renvoie une valeur donnee apres l'avoir bornee entre deux autres valeurs,
en y ajoutant une marge interne.
@param tobound valeur a borner
@param bound1 borne 1
@param bound2 borne 2
@param space marge interne ajoutee
@return La valeur bornee
*/
qreal Conductor::conductor_bound(qreal tobound, qreal bound1, qreal bound2, qreal space) {
@@ -866,7 +756,7 @@ qreal Conductor::conductor_bound(qreal tobound, qreal bound, bool positive) {
@param type Type de Segments
@return Le nombre de segments composant le conducteur.
*/
uint Conductor::segmentsCount(QET::ConductorSegmentType type) const {
uint Conductor::nbSegments(QET::ConductorSegmentType type) const {
QList<ConductorSegment *> segments_list = segmentsList();
if (type == QET::Both) return(segments_list.count());
uint nb_seg = 0;
@@ -945,18 +835,6 @@ bool Conductor::fromXml(QDomElement &e) {
// recupere la "configuration" du conducteur
properties_.fromXml(e);
readProperties();
qreal user_pos_x, user_pos_y;
if (
QET::attributeIsAReal(e, "userx", &user_pos_x) &&
QET::attributeIsAReal(e, "usery", &user_pos_y)
) {
text_item -> forceMovedByUser(true);
text_item -> setPos(user_pos_x, user_pos_y);
}
if (e.hasAttribute("rotation")) {
text_item -> setRotationAngle(e.attribute("rotation").toDouble());
text_item -> forceRotateByUser(true);
}
// parcourt les elements XML "segment" et en extrait deux listes de longueurs
// les segments non valides sont ignores
@@ -989,19 +867,17 @@ bool Conductor::fromXml(QDomElement &e) {
qreal width = 0.0, height = 0.0;
foreach (qreal t, segments_x) width += t;
foreach (qreal t, segments_y) height += t;
QPointF t1 = terminal1 -> dockConductor();
QPointF t2 = terminal2 -> dockConductor();
QPointF t1 = terminal1 -> amarrageConductor();
QPointF t2 = terminal2 -> amarrageConductor();
qreal expected_width = t2.x() - t1.x();
qreal expected_height = t2.y() - t1.y();
// on considere que le trajet est incoherent a partir d'une unite de difference avec l'espacement entre les bornes
qreal precision = std::numeric_limits<qreal>::epsilon();
if (
qAbs(expected_width - width) > 1.0 ||
qAbs(expected_height - height) > 1.0
) {
qDebug() << "Conductor::fromXml : les segments du conducteur ne semblent pas coherents - utilisation d'un trajet automatique";
return(false);
}
expected_width > width + precision ||\
expected_width < width - precision ||\
expected_height > height + precision ||\
expected_height < height - precision
) return(false);
/* on recree les segments a partir des donnes XML */
// cree la liste de points
@@ -1044,20 +920,13 @@ QDomElement Conductor::toXml(QDomDocument &d, QHash<Terminal *, int> &table_adr_
foreach(ConductorSegment *segment, segmentsList()) {
current_segment = d.createElement("segment");
current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical");
current_segment.setAttribute("length", QString("%1").arg(segment -> length()));
current_segment.setAttribute("length", segment -> length());
e.appendChild(current_segment);
}
}
// exporte la "configuration" du conducteur
properties_.toXml(e);
if (text_item -> wasRotateByUser()) {
e.setAttribute("rotation", QString("%1").arg(text_item -> rotationAngle()));
}
if (text_item -> wasMovedByUser()) {
e.setAttribute("userx", QString("%1").arg(text_item -> pos().x()));
e.setAttribute("usery", QString("%1").arg(text_item -> pos().y()));
}
properties_.toXml(d, e);
return(e);
}
@@ -1117,26 +986,8 @@ ConductorSegment *Conductor::middleSegment() {
@see middleSegment()
*/
void Conductor::calculateTextItemPosition() {
if (!text_item) return;
//position
if (text_item -> wasMovedByUser()) {
// le champ de texte a ete deplace par l'utilisateur :
// on verifie qu'il est encore a proximite du conducteur
QPointF text_item_pos = text_item -> pos();
QPainterPath near_shape = nearShape();
if (!near_shape.contains(text_item_pos)) {
text_item -> setPos(movePointIntoPolygon(text_item_pos, near_shape));
}
} else {
// positionnement automatique basique
text_item -> setPos(middleSegment() -> middle());
//rotation
if (!text_item -> wasRotateByUser()) {
middleSegment() -> isVertical()? text_item -> setRotationAngle(properties_.verti_rotate_text):
text_item -> setRotationAngle(properties_.horiz_rotate_text);
}
}
if (properties_.type != ConductorProperties::Multi) return;
text_item -> setPos(middleSegment() -> middle());
}
/**
@@ -1149,14 +1000,7 @@ void Conductor::saveProfile(bool undo) {
conductor_profiles[current_path_type].fromConductor(this);
Diagram *dia = diagram();
if (undo && dia) {
ChangeConductorCommand *undo_object = new ChangeConductorCommand(
this,
old_profile,
conductor_profiles[current_path_type],
current_path_type
);
undo_object -> setConductorTextItemMove(before_mov_text_pos_, text_item -> pos());
dia -> undoStack().push(undo_object);
dia -> undoStack().push(new ChangeConductorCommand(this, old_profile, conductor_profiles[current_path_type], current_path_type));
}
}
@@ -1187,10 +1031,10 @@ void Conductor::setProfile(const ConductorProfile &cp, Qt::Corner path_type) {
// si le type de trajet correspond a l'actuel
if (currentPathType() == path_type) {
if (conductor_profiles[path_type].isNull()) {
generateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation());
priv_calculeConductor(terminal1 -> amarrageConductor(), terminal1 -> orientation(), terminal2 -> amarrageConductor(), terminal2 -> orientation());
modified_path = false;
} else {
updateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation());
priv_modifieConductor(terminal1 -> amarrageConductor(), terminal1 -> orientation(), terminal2 -> amarrageConductor(), terminal2 -> orientation());
modified_path = true;
}
if (type() == ConductorProperties::Multi) {
@@ -1214,6 +1058,7 @@ QString Conductor::text() const {
*/
void Conductor::setText(const QString &t) {
text_item -> setPlainText(t);
text_item -> previous_text = t;
}
/// @param p les proprietes de ce conducteur
@@ -1231,79 +1076,10 @@ ConductorProperties Conductor::properties() const {
Relit les proprietes et les applique
*/
void Conductor::readProperties() {
// la couleur n'est vraiment applicable que lors du rendu du conducteur
setText(properties_.text);
calculateTextItemPosition();
text_item -> setVisible(properties_.type == ConductorProperties::Multi);
}
/**
S'assure que le texte du conducteur est a une position raisonnable
Cette methode ne fait rien si ce conducteur n'affiche pas son champ de
texte.
*/
void Conductor::adjustTextItemPosition() {
calculateTextItemPosition();
}
/**
@return true si le conducteur est mis en evidence
*/
Conductor::Highlight Conductor::highlight() const {
return(must_highlight_);
}
/**
@param hl true pour mettre le conducteur en evidence, false sinon
*/
void Conductor::setHighlighted(Conductor::Highlight hl) {
must_highlight_ = hl;
update();
}
/**
* @brief Conductor::autoText
*lance l'autoNumerotation sur ce conducteur
*/
void Conductor::autoText() {
ConductorAutoNumerotation can(this);
can.numerate();
}
/**
Met a jour les proprietes du conducteur apres modification du champ de texte affiche
*/
void Conductor::displayedTextChanged() {
// verifie que le texte a reellement change
if (text_item -> toPlainText() == properties_.text) return;
if (Diagram *my_diagram = diagram()) {
int qmbreturn=0;
//if conductor isn't alone at this potential
//ask user to apply text on every conductors of this potential
if (relatedPotentialConductors().size() >= 1){
qmbreturn = QMessageBox::question(diagramEditor(), tr("Textes de conducteurs"),
tr("Voulez-vous appliquer le nouveau texte \n"
"\340 l'ensemble des conducteurs de ce potentiel ?"),
QMessageBox::No| QMessageBox::Yes, QMessageBox::Yes);
if (qmbreturn == QMessageBox::Yes){
ConductorAutoNumerotation can(this);
can.applyText(text_item -> toPlainText());
}
}
if (qmbreturn == 0 || qmbreturn == QMessageBox::No) {
// initialise l'objet UndoCommand correspondant
ConductorProperties new_properties(properties_);
new_properties.text = text_item -> toPlainText();
ChangeConductorPropertiesCommand *ccpc = new ChangeConductorPropertiesCommand(this);
ccpc -> setOldSettings(properties_);
ccpc -> setNewSettings(new_properties);
my_diagram -> undoStack().push(ccpc);
}
}
}
/**
@return les conducteurs avec lesquels ce conducteur partage des bornes
communes
@@ -1316,80 +1092,6 @@ QSet<Conductor *> Conductor::relatedConductors() const {
return(other_conductors);
}
/**
* @param t_list terminaux a ne pas inclure dans la recherche
* @return les conducteurs avec lesquels ce conducteur partage
* le meme potentiel electrique a l'exception de lui même
*/
QSet<Conductor *> Conductor::relatedPotentialConductors(QList <Terminal *> *t_list) {
if (t_list == 0)
t_list = new QList <Terminal *>;
QSet <Conductor *> other_conductors;
//renvoie tous les conducteurs du terminal 1
if (t_list->contains(terminal1) == false) {
t_list->append(terminal1);
QList <Conductor *> other_conductors_list_t1 = terminal1 -> conductors();
other_conductors_list_t1.removeAll(this);
//recherche les conducteurs connecté au conducteur déjà trouvé
foreach (Conductor *c, other_conductors_list_t1) {
other_conductors += c -> relatedPotentialConductors(t_list);
}
other_conductors += other_conductors_list_t1.toSet();
}
//renvoie tous les conducteurs du terminal 2
if (t_list->contains(terminal2) == false) {
t_list->append(terminal2);
QList <Conductor *> other_conductors_list_t2 = terminal2 -> conductors();
other_conductors_list_t2.removeAll(this);
//recherche les conducteurs connecté au conducteur déjà trouvé
foreach (Conductor *c, other_conductors_list_t2) {
other_conductors += c -> relatedPotentialConductors(t_list);
}
other_conductors += other_conductors_list_t2.toSet();
}
other_conductors.remove(const_cast<Conductor *>(this));
return(other_conductors);
}
/**
* @return l'editeur de schemas parent ou 0
*/
QETDiagramEditor* Conductor::diagramEditor() const {
QWidget *w = const_cast<QGraphicsView *>(diagram() -> views().at(0));
while (w -> parentWidget() && !w -> isWindow()) {
w = w -> parentWidget();
}
return(qobject_cast<QETDiagramEditor *>(w));
}
/**
@param a reel
@param b reel
@param c reel
@return true si a est entre b et c ou est egal a l'un des deux
*/
bool isBetween(qreal a, qreal b, qreal c) {
if (b <= c) {
return(a >= b && a <= c);
} else {
return(a <= b && a >= c);
}
}
/**
@param a point
@param b point
@param c point
@return true si le point a est contenu dans le rectangle delimite par les points b et c
*/
bool isContained(const QPointF &a, const QPointF &b, const QPointF &c) {
return(
isBetween(a.x(), b.x(), c.x()) &&
isBetween(a.y(), b.y(), c.y())
);
}
/**
@return la liste des positions des jonctions avec d'autres conducteurs
*/
@@ -1431,8 +1133,9 @@ QList<QPointF> Conductor::junctions() const {
// parcoure les segments a la recherche d'un point commun
for (int j = 0 ; j < c_segments.count() ; ++ j) {
ConductorSegment *segment = c_segments[j];
QRectF rect(segment -> firstPoint(), segment -> secondPoint());
// un point commun a ete trouve sur ce segment
if (isContained(conductor_point, segment -> firstPoint(), segment -> secondPoint())) {
if (rect.contains(conductor_point)) {
is_junction = true;
// ce point commun ne doit pas etre une bifurcation identique a celle-ci
QList<ConductorBend> other_conductor_bends = c -> bends();
@@ -1539,7 +1242,7 @@ Qt::Corner Conductor::movementType(const QPointF &start, const QPointF &end) {
/// @return le type de trajet actuel de ce conducteur
Qt::Corner Conductor::currentPathType() const {
return(movementType(terminal1 -> dockConductor(), terminal2 -> dockConductor()));
return(movementType(terminal1 -> amarrageConductor(), terminal2 -> amarrageConductor()));
}
/// @return les profils de ce conducteur
@@ -1553,10 +1256,10 @@ ConductorProfilesGroup Conductor::profiles() const {
void Conductor::setProfiles(const ConductorProfilesGroup &cpg) {
conductor_profiles = cpg;
if (conductor_profiles[currentPathType()].isNull()) {
generateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation());
priv_calculeConductor(terminal1 -> amarrageConductor(), terminal1 -> orientation(), terminal2 -> amarrageConductor(), terminal2 -> orientation());
modified_path = false;
} else {
updateConductorPath(terminal1 -> dockConductor(), terminal1 -> orientation(), terminal2 -> dockConductor(), terminal2 -> orientation());
priv_modifieConductor(terminal1 -> amarrageConductor(), terminal1 -> orientation(), terminal2 -> amarrageConductor(), terminal2 -> orientation());
modified_path = true;
}
if (type() == ConductorProperties::Multi) {
@@ -1572,55 +1275,3 @@ void Conductor::deleteSegments() {
segments = NULL;
}
}
/**
@param point Un point situe a l'exterieur du polygone
@param polygon Le polygone dans lequel on veut rapatrier le point
@return la position du point, une fois ramene dans le polygone, ou plus
exactement sur le bord du polygone
*/
QPointF Conductor::movePointIntoPolygon(const QPointF &point, const QPainterPath &polygon) {
// decompose le polygone en lignes et points
QList<QPolygonF> polygons = polygon.simplified().toSubpathPolygons();
QList<QLineF> lines;
QList<QPointF> points;
foreach(QPolygonF polygon, polygons) {
if (polygon.count() <= 1) continue;
// on recense les lignes et les points
for (int i = 1 ; i < polygon.count() ; ++ i) {
lines << QLineF(polygon.at(i - 1), polygon.at(i));
points << polygon.at(i -1);
}
}
// on fait des projetes orthogonaux du point sur les differents segments du
// polygone, en les triant par longueur croissante
QMap<qreal, QPointF> intersections;
foreach (QLineF line, lines) {
QPointF intersection_point;
if (QET::orthogonalProjection(point, line, &intersection_point)) {
intersections.insert(QLineF(intersection_point, point).length(), intersection_point);
}
}
if (intersections.count()) {
// on determine la plus courte longueur pour un projete orthogonal
QPointF the_point = intersections[intersections.keys().first()];
return(the_point);
} else {
// determine le coin du polygone le plus proche du point exterieur
qreal minimum_length = -1;
int point_index = -1;
for (int i = 0 ; i < points.count() ; ++ i) {
qreal length = qAbs(QLineF(points.at(i), point).length());
if (minimum_length < 0 || length < minimum_length) {
minimum_length = length;
point_index = i;
}
}
// on connait desormais le coin le plus proche du texte
// aucun projete orthogonal n'a donne quoi que ce soit, on met le texte sur un des coins du polygone
return(points.at(point_index));
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -21,59 +21,49 @@
#include "terminal.h"
#include "conductorprofile.h"
#include "conductorproperties.h"
#include "qetdiagrameditor.h"
#include "diagramtextitem.h"
class ConductorSegment;
class ConductorTextItem;
class Element;
typedef QPair<QPointF, Qt::Corner> ConductorBend;
typedef QHash<Qt::Corner, ConductorProfile> ConductorProfilesGroup;
/**
This class represents a conductor, i.e. a wire between two element
terminals.
Cette classe represente un conducteur. Un conducteur relie deux bornes d'element.
*/
class Conductor : public QObject, public QGraphicsPathItem {
class Conductor : public QGraphicsPathItem {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
Conductor(Terminal *, Terminal *, Diagram * = 0);
Conductor(Terminal *, Terminal *, Element * = 0, QGraphicsScene * = 0);
virtual ~Conductor();
private:
Conductor(const Conductor &);
// attributes
// attributs
public:
enum { Type = UserType + 1001 };
enum Highlight { None, Normal, Alert };
/// First terminal the wire is attached to
/// premiere borne a laquelle le fil est rattache
Terminal *terminal1;
/// Second terminal the wire is attached to
/// deuxieme borne a laquelle le fil est rattache
Terminal *terminal2;
// methods
// methodes
public:
/**
Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a
Conductor.
@return the QGraphicsItem type
permet de caster un QGraphicsItem en Conductor avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
void destroy();
/// @return true if this conductor is destroyed
bool isDestroyed() const { return(destroyed_); }
/// @return true si ce conducteur est detruit
bool isDestroyed() const { return(destroyed); }
Diagram *diagram() const;
ConductorTextItem *textItem() const;
void updatePath(const QRectF & = QRectF());
void updateWithNewPos(const QRectF &, const Terminal *, const QPointF &);
void update(const QRectF & = QRectF());
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
QRectF boundingRect() const;
virtual QPainterPath shape() const;
virtual qreal nearDistance() const;
virtual QPainterPath nearShape() const;
virtual QPainterPath variableShape(const qreal &) const;
virtual bool isNearConductor(const QPointF &);
qreal length();
ConductorSegment *middleSegment();
bool containsPoint(const QPointF &) const;
@@ -90,65 +80,47 @@ class Conductor : public QObject, public QGraphicsPathItem {
void setProfiles(const ConductorProfilesGroup &);
ConductorProfilesGroup profiles() const;
void readProperties();
void adjustTextItemPosition();
virtual Highlight highlight() const;
virtual void setHighlighted(Highlight);
void autoText();
QSet<Conductor *> relatedPotentialConductors(QList <Terminal *> *t_list=0);
QETDiagramEditor* diagramEditor() const;
public slots:
void displayedTextChanged();
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *);
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *);
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *);
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
/// Functional properties
/// caracteristiques du conducteur
ConductorProperties properties_;
/// Whether this conductor is still valid
bool destroyed_;
/// Text input for non simple, non-singleline conductors
ConductorTextItem *text_item;
/// Segments composing the conductor
/// booleen indiquant si le fil est encore valide
bool destroyed;
/// champ de texte editable pour les conducteurs non unifilaires
DiagramTextItem *text_item;
/// segments composant le conducteur
ConductorSegment *segments;
/// Attributs related to mouse interaction
/// attributs lies aux manipulations a la souris
QPointF press_point;
bool moving_point;
bool moving_segment;
int moved_point;
qreal previous_z_value;
ConductorSegment *moved_segment;
QPointF before_mov_text_pos_;
/// Whether the conductor was manually modified by users
/// booleen indiquant si le conducteur a ete modifie manuellement par l'utilisateur
bool modified_path;
/// Whether the current profile should be saved as soon as possible
/// booleen indiquant s'il faut sauver le profil courant au plus tot
bool has_to_save_profile;
/// conductor profile: "photography" of what the conductor is supposed to look
/// like - there is one profile per kind of traject
/// profil du conducteur : "photo" de ce a quoi le conducteur doit ressembler - il y a un profil par type de trajet
ConductorProfilesGroup conductor_profiles;
/// QPen et QBrush objects used to draw conductors
/// QPen et QBrush utilises pour dessiner les conducteurs
static QPen conductor_pen;
static QBrush conductor_brush;
static QBrush square_brush;
static bool pen_and_brush_initialized;
/// Scale factor to render square used to move segments
qreal segments_squares_scale_;
/// Define whether and how the conductor should be highlighted
Highlight must_highlight_;
private:
void segmentsToPath();
void saveProfile(bool = true);
void generateConductorPath(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
void updateConductorPath(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
uint segmentsCount(QET::ConductorSegmentType = QET::Both) const;
void priv_calculeConductor(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
void priv_modifieConductor(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
uint nbSegments(QET::ConductorSegmentType = QET::Both) const;
QList<QPointF> segmentsToPoints() const;
QSet<Conductor *> relatedConductors() const;
QList<ConductorBend> bends() const;
@@ -165,6 +137,5 @@ class Conductor : public QObject, public QGraphicsPathItem {
static qreal conductor_bound(qreal, qreal, qreal, qreal = 0.0);
static qreal conductor_bound(qreal, qreal, bool);
static Qt::Corner movementType(const QPointF &, const QPointF &);
static QPointF movePointIntoPolygon(const QPointF &, const QPainterPath &);
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -100,7 +100,7 @@ qreal ConductorProfile::height() const{
@param type Type de Segments
@return Le nombre de segments composant le conducteur.
*/
uint ConductorProfile::segmentsCount(QET::ConductorSegmentType type) const {
uint ConductorProfile::nbSegments(QET::ConductorSegmentType type) const {
if (type == QET::Both) return(segments.count());
uint nb_seg = 0;
foreach(ConductorSegmentProfile *csp, segments) {

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -22,34 +22,34 @@
class Conductor;
class ConductorSegmentProfile;
/**
This class represents the profile of a conductor, i.e. its primary
characteristics.
Cette classe contient le profil (= les caracteristiques essentielles) d'un
conducteur.
*/
class ConductorProfile {
public:
// constructors, destructor
// constructeurs, destructeur
ConductorProfile();
ConductorProfile(Conductor *conductor);
ConductorProfile(const ConductorProfile &);
ConductorProfile &operator=(const ConductorProfile &);
virtual ~ConductorProfile();
// attributes
// attributs
public:
/// Segments composing the conductor
/// Segment composant le profil du conducteur
QList<ConductorSegmentProfile *> segments;
/// Orientation of the start terminal
/// Orientation de la borne de depart du profil
QET::Orientation beginOrientation;
/// Orientation of the end terminal.
/// Orientation de la borne d'arrivee du profil
QET::Orientation endOrientation;
// methods
// methodes
public:
bool isNull() const;
void setNull();
qreal width() const;
qreal height() const;
uint segmentsCount(QET::ConductorSegmentType) const;
uint nbSegments(QET::ConductorSegmentType) const;
QList<ConductorSegmentProfile *> horizontalSegments();
QList<ConductorSegmentProfile *> verticalSegments();
void fromConductor(Conductor *);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -23,7 +23,6 @@
SingleLineProperties::SingleLineProperties() :
hasGround(true),
hasNeutral(true),
is_pen(false),
phases(1)
{
}
@@ -45,15 +44,6 @@ unsigned short int SingleLineProperties::phasesCount() {
return(phases);
}
/**
@return true if the singleline conductor should be drawn using the PEN
(Protective Earth Neutral) representation and if it features the ground and
the neutral.
*/
bool SingleLineProperties::isPen() const {
return(hasNeutral && hasGround && is_pen);
}
/**
Dessine les symboles propres a un conducteur unifilaire
@param painter QPainter a utiliser pour dessiner les symboles
@@ -69,33 +59,38 @@ void SingleLineProperties::draw(QPainter *painter, QET::ConductorSegmentType dir
QPen pen(painter -> pen());
pen.setCapStyle(Qt::FlatCap);
pen.setJoinStyle(Qt::MiterJoin);
pen.setStyle(Qt::SolidLine);
painter -> setPen(pen);
painter -> setRenderHint(QPainter::Antialiasing, true);
uint symbols_count = (hasNeutral ? 1 : 0) + (hasGround ? 1 : 0) - (isPen() ? 1 : 0) + phases;
qreal interleave_base = (direction == QET::Horizontal ? rect.width() : rect.height());
qreal interleave = interleave_base / (symbols_count + 1);;
qreal symbol_width = interleave_base / 12;
uint symbols_count = (hasNeutral ? 1 : 0) + (hasGround ? 1 : 0) + phases;
qreal interleave;
qreal symbol_width;
if (direction == QET::Horizontal) {
interleave = rect.width() / (symbols_count + 1);
symbol_width = rect.width() / 12;
for (uint i = 1 ; i <= symbols_count ; ++ i) {
// dessine le tronc du symbole
QPointF symbol_p1(rect.x() + (i * interleave) + symbol_width, rect.y() + rect.height() * 0.75);
QPointF symbol_p2(rect.x() + (i * interleave) - symbol_width, rect.y() + rect.height() * 0.25);
painter -> drawLine(QLineF(symbol_p1, symbol_p2));
for (uint i = 1 ; i <= symbols_count ; ++ i) {
// dessine le tronc du symbole
QPointF symbol_p1, symbol_p2;
if (direction == QET::Horizontal) {
symbol_p1 = QPointF(rect.x() + (i * interleave) + symbol_width, rect.y() + rect.height() * 0.75);
symbol_p2 = QPointF(rect.x() + (i * interleave) - symbol_width, rect.y() + rect.height() * 0.25);
} else {
symbol_p2 = QPointF(rect.x() + rect.width() * 0.75, rect.y() + (i * interleave) - symbol_width);
symbol_p1 = QPointF(rect.x() + rect.width() * 0.25, rect.y() + (i * interleave) + symbol_width);
}
painter -> drawLine(QLineF(symbol_p1, symbol_p2));
// dessine le reste des symboles terre et neutre
if (isPen()) {
if (i == 1) {
drawPen(painter, direction, symbol_p2, symbol_width);
// dessine le reste des symboles terre et neutre
if (hasGround && i == 1) {
drawGround(painter, direction, symbol_p2, symbol_width * 2.0);
} else if (hasNeutral && ((i == 1 && !hasGround) || (i == 2 && hasGround))) {
drawNeutral(painter, direction, symbol_p2, symbol_width * 1.35);
}
} else {
}
} else {
interleave = rect.height() / (symbols_count + 1);
symbol_width = rect.height() / 12;
for (uint i = 1 ; i <= symbols_count ; ++ i) {
// dessine le tronc du symbole
QPointF symbol_p2(rect.x() + rect.width() * 0.75, rect.y() + (i * interleave) - symbol_width);
QPointF symbol_p1(rect.x() + rect.width() * 0.25, rect.y() + (i * interleave) + symbol_width);
painter -> drawLine(QLineF(symbol_p1, symbol_p2));
// dessine le reste des symboles terre et neutre
if (hasGround && i == 1) {
drawGround(painter, direction, symbol_p2, symbol_width * 2.0);
} else if (hasNeutral && ((i == 1 && !hasGround) || (i == 2 && hasGround))) {
@@ -145,8 +140,7 @@ void SingleLineProperties::drawGround(QPainter *painter, QET::ConductorSegmentTy
@param center centre du cercle
@param size diametre du cercle
*/
void SingleLineProperties::drawNeutral(QPainter *painter, QET::ConductorSegmentType direction, QPointF center, qreal size) {
Q_UNUSED(direction);
void SingleLineProperties::drawNeutral(QPainter *painter, QET::ConductorSegmentType, QPointF center, qreal size) {
painter -> save();
// prepare le QPainter
@@ -165,43 +159,19 @@ void SingleLineProperties::drawNeutral(QPainter *painter, QET::ConductorSegmentT
}
/**
Draw the PEN (Protective Earth Neutral) symbol using \a painter at position \a
center, using a size hint of \a size.
@param direction Indicate the direction of the underlying conductor segment
*/
void SingleLineProperties::drawPen(QPainter *painter, QET::ConductorSegmentType direction, QPointF center, qreal size) {
painter -> save();
//painter -> setBrush(Qt::white);
// desine le cercle representant le neutre
//painter -> drawEllipse(
// QRectF(
// center - QPointF(size * 1.5 / 2.0, size * 1.5 / 2.0),
// QSizeF(size * 1.5, size * 1.5)
// )
//);
drawNeutral(painter, direction, center, size * 1.5);
int offset = (size * 1.5 / 2.0);
QPointF pos = center + (direction == QET::Horizontal ? QPointF(0.0, -offset - 0.5) : QPointF(offset + 0.5, 0.0));
drawGround(painter, direction, pos, 2.0 * size);
painter -> restore();
}
/**
Exporte les parametres du conducteur unifilaire sous formes d'attributs XML
exporte les parametres du conducteur unifilaire sous formes d'attributs XML
ajoutes a l'element e.
@param d Document XML ; utilise pour ajouter (potentiellement) des elements XML
@param e Element XML auquel seront ajoutes des attributs
*/
void SingleLineProperties::toXml(QDomElement &e) const {
void SingleLineProperties::toXml(QDomDocument &, QDomElement &e) const {
e.setAttribute("ground", hasGround ? "true" : "false");
e.setAttribute("neutral", hasNeutral ? "true" : "false");
e.setAttribute("phase", phases);
if (isPen()) e.setAttribute("pen", "true");
}
/**
Importe les parametres du conducteur unifilaire a partir des attributs XML
importe les parametres du conducteur unifilaire a partir des attributs XML
de l'element e
@param e Element XML dont les attributs seront lus
*/
@@ -209,72 +179,29 @@ void SingleLineProperties::fromXml(QDomElement &e) {
hasGround = e.attribute("ground") == "true";
hasNeutral = e.attribute("neutral") == "true";
setPhasesCount(e.attribute("phase").toInt());
is_pen = (hasGround && hasNeutral && e.attribute("pen", "false") == "true");
}
/**
Constructeur : par defaut, les proprietes font un conducteur
multifilaire noir dont le texte est "_"
*/
ConductorProperties::ConductorProperties() :
type(Multi),
color(Qt::black),
text("_"),
verti_rotate_text(270),
horiz_rotate_text(0),
style(Qt::SolidLine)
{
}
/**
Destructeur
*/
ConductorProperties::~ConductorProperties() {
}
/**
Exporte les parametres du conducteur sous formes d'attributs XML
exporte les parametres du conducteur sous formes d'attributs XML
ajoutes a l'element e.
@param d Document XML ; utilise pour ajouter (potentiellement) des elements XML
@param e Element XML auquel seront ajoutes des attributs
*/
void ConductorProperties::toXml(QDomElement &e) const {
void ConductorProperties::toXml(QDomDocument &d, QDomElement &e) const {
e.setAttribute("type", typeToString(type));
if (color != QColor(Qt::black)) {
e.setAttribute("color", color.name());
}
if (type == Single) {
singleLineProperties.toXml(e);
singleLineProperties.toXml(d, e);
} else if (type == Multi) {
e.setAttribute("num", text);
e.setAttribute("vertirotatetext", verti_rotate_text);
e.setAttribute("horizrotatetext", horiz_rotate_text);
}
QString conductor_style = writeStyle();
if (!conductor_style.isEmpty()) {
e.setAttribute("style", conductor_style);
}
}
/**
Importe les parametres du conducteur unifilaire a partir des attributs XML
importe les parametres du conducteur unifilaire a partir des attributs XML
de l'element e
@param e Element XML dont les attributs seront lus
*/
void ConductorProperties::fromXml(QDomElement &e) {
// recupere la couleur du conducteur
QColor xml_color= QColor(e.attribute("color"));
if (xml_color.isValid()) {
color = xml_color;
} else {
color = QColor(Qt::black);
}
// lit le style du conducteur
readStyle(e.attribute("style"));
if (e.attribute("type") == typeToString(Single)) {
// recupere les parametres specifiques a un conducteur unifilaire
singleLineProperties.fromXml(e);
@@ -284,39 +211,25 @@ void ConductorProperties::fromXml(QDomElement &e) {
} else {
// recupere le champ de texte
text = e.attribute("num");
verti_rotate_text = e.attribute("vertirotatetext").toDouble();
horiz_rotate_text = e.attribute("horizrotatetext").toDouble();
type = Multi;
}
}
/**
@param settings Parametres a ecrire
@param prefix prefixe a ajouter devant les noms des parametres
@param prefix prefix a ajouter devant les noms des parametres
*/
void ConductorProperties::toSettings(QSettings &settings, const QString &prefix) const {
settings.setValue(prefix + "color", color.name());
settings.setValue(prefix + "style", writeStyle());
settings.setValue(prefix + "type", typeToString(type));
settings.setValue(prefix + "text", text);
settings.setValue(prefix + "vertirotatetext", QString::number(verti_rotate_text));
settings.setValue(prefix + "horizrotatetext", QString::number(horiz_rotate_text));
singleLineProperties.toSettings(settings, prefix);
}
/**
@param settings Parametres a lire
@param prefix prefixe a ajouter devant les noms des parametres
@param prefix prefix a ajouter devant les noms des parametres
*/
void ConductorProperties::fromSettings(QSettings &settings, const QString &prefix) {
// recupere la couleur dans les parametres
QColor settings_color = QColor(settings.value(prefix + "color").toString());
if (settings_color.isValid()) {
color = settings_color;
} else {
color = QColor(Qt::black);
}
QString setting_type = settings.value(prefix + "type", typeToString(Multi)).toString();
if (setting_type == typeToString(Single)) {
type = Single;
@@ -327,11 +240,6 @@ void ConductorProperties::fromSettings(QSettings &settings, const QString &prefi
}
singleLineProperties.fromSettings(settings, prefix);
text = settings.value(prefix + "text", "_").toString();
verti_rotate_text = settings.value((prefix + "vertirotatetext"), "270").toDouble();
horiz_rotate_text = settings.value((prefix + "horizrotatetext"), "0").toDouble();
// lit le style du conducteur
readStyle(settings.value(prefix + "style").toString());
}
/**
@@ -353,11 +261,7 @@ QString ConductorProperties::typeToString(ConductorType t) {
int ConductorProperties::operator==(const ConductorProperties &other) {
return(
other.type == type &&\
other.color == color &&\
other.style == style &&\
other.text == text &&\
other.verti_rotate_text == verti_rotate_text &&\
other.horiz_rotate_text == horiz_rotate_text &&\
other.singleLineProperties == singleLineProperties
);
}
@@ -369,55 +273,11 @@ int ConductorProperties::operator==(const ConductorProperties &other) {
int ConductorProperties::operator!=(const ConductorProperties &other) {
return(
other.type != type ||\
other.color != color ||\
other.style != style ||\
other.text != text ||\
other.verti_rotate_text != verti_rotate_text ||\
other.horiz_rotate_text != horiz_rotate_text ||\
other.singleLineProperties != singleLineProperties
);
}
/**
Applique les styles passes en parametre dans cet objet
@param style_string Chaine decrivant le style du conducteur
*/
void ConductorProperties::readStyle(const QString &style_string) {
style = Qt::SolidLine; // style par defaut
if (style_string.isEmpty()) return;
// recupere la liste des couples style / valeur
QStringList styles = style_string.split(";", QString::SkipEmptyParts);
QRegExp rx("^\\s*([a-z-]+)\\s*:\\s*([a-z-]+)\\s*$");
foreach (QString style_str, styles) {
if (rx.exactMatch(style_str)) {
QString style_name = rx.cap(1);
QString style_value = rx.cap(2);
if (style_name == "line-style") {
if (style_value == "dashed") style = Qt::DashLine;
else if (style_value == "dashdotted") style = Qt::DashDotLine;
else if (style_value == "normal") style = Qt::SolidLine;
}
}
}
}
/**
Exporte le style du conducteur sous forme d'une chaine de caracteres
@return une chaine de caracteres decrivant le style du conducteur
*/
QString ConductorProperties::writeStyle() const {
if (style == Qt::DashLine) {
return("line-style: dashed;");
} else if (style == Qt::DashDotLine) {
return("line-style: dashdotted");
} else {
return(QString());
}
}
/**
@param other l'autre ensemble de proprietes avec lequel il faut effectuer la comparaison
@return true si les deux ensembles de proprietes sont identiques, false sinon
@@ -426,7 +286,6 @@ int SingleLineProperties::operator==(const SingleLineProperties &other) const {
return(
other.hasGround == hasGround &&\
other.hasNeutral == hasNeutral &&\
other.is_pen == is_pen &&\
other.phases == phases
);
}
@@ -447,7 +306,6 @@ void SingleLineProperties::toSettings(QSettings &settings, const QString &prefix
settings.setValue(prefix + "hasGround", hasGround);
settings.setValue(prefix + "hasNeutral", hasNeutral);
settings.setValue(prefix + "phases", phases);
settings.setValue(prefix + "pen", is_pen);
}
/**
@@ -458,5 +316,4 @@ void SingleLineProperties::fromSettings(QSettings &settings, const QString &pref
hasGround = settings.value(prefix + "hasGround", true).toBool();
hasNeutral = settings.value(prefix + "hasNeutral", true).toBool();
phases = settings.value(prefix + "phases", 1).toInt();
is_pen = settings.value(prefix + "pen", false).toBool();
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -21,7 +21,7 @@
#include <QtGui>
#include <QtXml>
/**
This class represents the properties of a singleline conductor.
Cette classe represente les proprietes specifiques a un conducteur unifilaire
*/
class SingleLineProperties {
public:
@@ -30,19 +30,16 @@ class SingleLineProperties {
void setPhasesCount(int);
unsigned short int phasesCount();
bool isPen() const;
void draw(QPainter *, QET::ConductorSegmentType, const QRectF &);
void toXml(QDomElement &) const;
void toXml(QDomDocument &, QDomElement &) const;
void fromXml(QDomElement &);
void toSettings(QSettings &, const QString & = QString()) const;
void fromSettings(QSettings &, const QString & = QString());
/// Whether the singleline conductor should display the ground symbol
/// indique si le conducteur unifilaire doit afficher le symbole terre
bool hasGround;
/// Whether the singleline conductor should display the neutral symbol
/// indique si le conducteur unifilaire doit afficher le symbole neutre
bool hasNeutral;
/// Protective Earth Neutral: visually merge neutral and ground
bool is_pen;
int operator==(const SingleLineProperties &) const;
int operator!=(const SingleLineProperties &) const;
@@ -51,56 +48,53 @@ class SingleLineProperties {
unsigned short int phases;
void drawGround (QPainter *, QET::ConductorSegmentType, QPointF, qreal);
void drawNeutral(QPainter *, QET::ConductorSegmentType, QPointF, qreal);
void drawPen(QPainter *, QET::ConductorSegmentType, QPointF, qreal);
};
/**
This class represents the functional properties of a particular conductor,
i.e. properties other than path and terminals.
Cette classe represente les proprietes specifiques a un conducteur,
en dehors de ses bornes et de son trajet.
*/
class ConductorProperties {
// constructors, destructor
// constructeurs, destructeur
public:
ConductorProperties();
virtual ~ConductorProperties();
/**
Constructeur : par defaut, les proprietes font un conducteur
multifilaire dont le texte est "_"
*/
ConductorProperties() : type(Multi), text("_") {
}
/// Destructeur
virtual ~ConductorProperties() {
}
/**
Represents the kind of a particular conductor:
* Simple: no symbols, no text input
* Single: singleline symbols, no text input
* Multi: text input, no symbol
Represente le type d'un conducteur :
* Simple : ni symbole ni champ de texte
* Single : symboles unifilaires, pas de champ de texte
* Multi : champ de texte, pas de symbole
*/
enum ConductorType { Simple, Single, Multi };
// attributes
/// Conductor type
// attributs
/// type du conducteur
ConductorType type;
/// Conductor color
QColor color;
/// Texte displayed for multiline conductors
QString text;
/// rotation angle texte
double verti_rotate_text;
double horiz_rotate_text;
/// conducteur style (Qt::SolidLine or Qt::DashLine)
Qt::PenStyle style;
/// properties for singleline conductors
/// texte affiche si le conducteur est multifilaire
QString text;
/// proprietes si le conducteur est unifilaire
SingleLineProperties singleLineProperties;
// methods
void toXml(QDomElement &) const;
// methodes
void toXml(QDomDocument &, QDomElement &) const;
void fromXml(QDomElement &);
void toSettings(QSettings &, const QString & = QString()) const;
void fromSettings(QSettings &, const QString & = QString());
static QString typeToString(ConductorType);
// operators
// operateurs
int operator==(const ConductorProperties &);
int operator!=(const ConductorProperties &);
private:
void readStyle(const QString &);
QString writeStyle() const;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -16,10 +16,7 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "conductorpropertieswidget.h"
#include <QtGui>
#include "conductor.h"
#include "qeticons.h"
#include "qetapp.h"
/**
Constructeur
@@ -46,10 +43,9 @@ ConductorPropertiesWidget::ConductorPropertiesWidget(const ConductorProperties &
/// construit l'interface du widget
void ConductorPropertiesWidget::buildInterface() {
setFocusPolicy(Qt::StrongFocus);
setMinimumSize(380, 280);
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout -> setContentsMargins(0, 0, 0, 0);
QGroupBox *groupbox = new QGroupBox(tr("Type de conducteur"));
main_layout -> addWidget(groupbox);
@@ -66,42 +62,11 @@ void ConductorPropertiesWidget::buildInterface() {
multiline_layout -> addWidget(text);
multiline_layout -> addWidget(text_field);
QGridLayout *rotate_text_layout = new QGridLayout;
QLabel *rotate_label = new QLabel(tr("Rotation du texte sur conducteur :"));
rotate_text_layout -> addWidget(rotate_label, 0, 0);
QLabel *verti_text = new QLabel(tr("Vertical"));
verti_select = QETApp::createTextOrientationSpinBoxWidget();
rotate_text_layout -> addWidget(verti_text, 1, 0);
rotate_text_layout -> setAlignment(verti_text, Qt::AlignCenter);
rotate_text_layout -> addWidget(verti_select, 2, 0);
QLabel *horiz_text = new QLabel(tr("Horizontal"));
horiz_select = QETApp::createTextOrientationSpinBoxWidget();
rotate_text_layout -> addWidget(horiz_text, 1, 1);
rotate_text_layout -> setAlignment(horiz_text, Qt::AlignCenter);
rotate_text_layout -> addWidget(horiz_select, 2, 1);
singleline = new QRadioButton(tr("Unifilaire"));
ground_checkbox = new QCheckBox(tr("terre"));
ground_checkbox -> setIcon(QET::Icons::Ground);
neutral_checkbox = new QCheckBox(tr("neutre"));
neutral_checkbox -> setIcon(QET::Icons::Neutral);
merge_checkbox = new QCheckBox(tr("PEN", "Protective Earth Neutral"));
merge_checkbox -> setToolTip(tr("Protective Earth Neutral", "Tooltip displaying the meaning of the 'PEN' acronym"));
QVBoxLayout *singleline_layout5 = new QVBoxLayout();
singleline_layout5 -> addWidget(ground_checkbox);
singleline_layout5 -> addWidget(neutral_checkbox);
QHBoxLayout *singleline_layout4 = new QHBoxLayout();
singleline_layout4 -> addLayout(singleline_layout5);
singleline_layout4 -> addWidget(merge_checkbox, 4, Qt::AlignVCenter | Qt::AlignLeft);
QHBoxLayout *singleline_layout3 = new QHBoxLayout();
phase_checkbox = new QCheckBox(tr("phase"));
phase_checkbox -> setIcon(QET::Icons::Phase);
phase_checkbox -> setIcon(QIcon(":/ico/phase.png"));
phase_slider = new QSlider(Qt::Horizontal);
phase_slider -> setRange(1, 3);
phase_spinbox = new QSpinBox();
@@ -111,50 +76,26 @@ void ConductorPropertiesWidget::buildInterface() {
singleline_layout3 -> addWidget(phase_spinbox);
QVBoxLayout *singleline_layout2 = new QVBoxLayout();
singleline_layout2 -> addLayout(singleline_layout4);
ground_checkbox = new QCheckBox(tr("terre"));
ground_checkbox -> setIcon(QIcon(":/ico/ground.png"));
neutral_checkbox = new QCheckBox(tr("neutre"));
neutral_checkbox -> setIcon(QIcon(":/ico/neutral.png"));
singleline_layout2 -> addWidget(ground_checkbox);
singleline_layout2 -> addWidget(neutral_checkbox);
singleline_layout2 -> addLayout(singleline_layout3);
QHBoxLayout *singleline_layout1 = new QHBoxLayout();
preview = new QLabel();
preview -> setFixedSize(150, 150);
preview -> setFixedSize(96, 96);
singleline_layout1 -> addWidget(preview);
singleline_layout1 -> addLayout(singleline_layout2);
QGroupBox *groupbox2 = new QGroupBox(tr("Apparence du conducteur"));
main_layout -> addWidget(groupbox2);
QVBoxLayout *groupbox2_layout = new QVBoxLayout();
groupbox2 -> setLayout(groupbox2_layout);
QHBoxLayout *color_layout = new QHBoxLayout();
QLabel *text1 = new QLabel(tr("Couleur :"));
color_button = new QPushButton("");
color_layout -> addWidget(text1);
color_layout -> addWidget(color_button);
QHBoxLayout *style_layout = new QHBoxLayout();
QLabel *text2 = new QLabel(tr("Style :", "conductor line style"));
line_style = new QComboBox();
line_style -> addItem(tr("Trait plein", "conductor style: solid line"), Qt::SolidLine);
line_style -> addItem(tr("Trait en pointill\351s", "conductor style: dashed line"), Qt::DashLine);
line_style -> addItem(tr("Traits et points", "conductor style: dashed and dotted line"), Qt::DashDotLine);
style_layout -> addWidget(text2);
style_layout -> addWidget(line_style);
setColorButton(properties_.color);
int index = line_style -> findData(properties_.style);
if (index != -1) line_style -> setCurrentIndex(index);
groupbox_layout -> addWidget(simple);
groupbox_layout -> addWidget(multiline);
groupbox_layout -> addLayout(multiline_layout);
groupbox_layout -> addLayout(rotate_text_layout);
groupbox_layout -> addWidget(singleline);
groupbox_layout -> addLayout(singleline_layout1);
groupbox2_layout -> addLayout(color_layout);
groupbox2_layout -> addLayout(style_layout);
radio_buttons = new QButtonGroup(this);
radio_buttons -> addButton(simple, ConductorProperties::Simple);
radio_buttons -> addButton(multiline, ConductorProperties::Multi);
@@ -170,44 +111,10 @@ void ConductorPropertiesWidget::buildConnections() {
connect(phase_spinbox, SIGNAL(valueChanged(int)), phase_slider, SLOT(setValue(int)));
connect(ground_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
connect(neutral_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
connect(merge_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
connect(phase_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
connect(phase_slider, SIGNAL(valueChanged(int)), this, SLOT(updateConfig()));
connect(radio_buttons, SIGNAL(buttonClicked(int)), this, SLOT(updateConfig()));
connect(text_field, SIGNAL(textChanged(const QString &)), this, SLOT(updateConfig()));
connect(line_style, SIGNAL(currentIndexChanged(int)), this, SLOT(updateConfig()));
connect(color_button, SIGNAL(clicked()), this, SLOT(chooseColor()));
connect(verti_select, SIGNAL(editingFinished(double)), this, SLOT(updateConfig()));
connect(horiz_select, SIGNAL(editingFinished(double)), this, SLOT(updateConfig()));
}
/**
Demande a l'utilisateur de choisir une couleur via un dialogue approprie.
*/
void ConductorPropertiesWidget::chooseColor() {
QColor user_chosen_color = QColorDialog::getColor(properties_.color);
if (user_chosen_color.isValid()) {
setColorButton(user_chosen_color);
updateConfig();
}
}
/**
@return la couleur actuelle du bouton permettant de choisir la couleur du
conducteur
*/
QColor ConductorPropertiesWidget::colorButton() const {
return(color_button -> palette().color(QPalette::Button));
}
/**
Change la couleur du bouton permettant de choisir la couleur du conducteur
@param color Nouvelle couleur a afficher
*/
void ConductorPropertiesWidget::setColorButton(const QColor &color) {
QPalette palette;
palette.setColor(QPalette::Button, color);
color_button -> setPalette(palette);
}
/// Enleve les connexions signaux/slots
@@ -216,34 +123,22 @@ void ConductorPropertiesWidget::destroyConnections() {
disconnect(phase_spinbox, SIGNAL(valueChanged(int)), phase_slider, SLOT(setValue(int)));
disconnect(ground_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
disconnect(neutral_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
disconnect(merge_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
disconnect(phase_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
disconnect(phase_slider, SIGNAL(valueChanged(int)), this, SLOT(updateConfig()));
disconnect(radio_buttons, SIGNAL(buttonClicked(int)), this, SLOT(updateConfig()));
disconnect(text_field, SIGNAL(textChanged(const QString &)), this, SLOT(updateConfig()));
disconnect(color_button, SIGNAL(clicked()), this, SLOT(chooseColor()));
disconnect(line_style, SIGNAL(currentIndexChanged(int)), this, SLOT(updateConfig()));
disconnect(verti_select, SIGNAL(editingFinished(double)), this, SLOT(updateConfig()));
disconnect(horiz_select, SIGNAL(editingFinished(double)), this, SLOT(updateConfig()));
}
/// Destructeur
ConductorPropertiesWidget::~ConductorPropertiesWidget() {
delete verti_select;
delete horiz_select;
}
/// Met a jour les proprietes
void ConductorPropertiesWidget::updateConfig() {
properties_.type = static_cast<ConductorProperties::ConductorType>(radio_buttons -> checkedId());
properties_.color = colorButton();
properties_.style = static_cast<Qt::PenStyle>(line_style -> itemData(line_style -> currentIndex()).toInt());
properties_.text = text_field -> text();
properties_.verti_rotate_text = verti_select -> value();
properties_.horiz_rotate_text = horiz_select -> value();
properties_.singleLineProperties.hasGround = ground_checkbox -> isChecked();
properties_.singleLineProperties.hasNeutral = neutral_checkbox -> isChecked();
properties_.singleLineProperties.is_pen = merge_checkbox -> isChecked();
properties_.singleLineProperties.setPhasesCount(phase_checkbox -> isChecked() ? phase_spinbox -> value() : 0);
updateDisplay();
@@ -254,19 +149,12 @@ void ConductorPropertiesWidget::updateDisplay() {
destroyConnections();
setConductorType(properties_.type);
setColorButton(properties_.color);
int index = line_style -> findData(properties_.style);
if (index != -1) line_style -> setCurrentIndex(index);
text_field -> setText(properties_.text);
ground_checkbox -> setChecked(properties_.singleLineProperties.hasGround);
neutral_checkbox -> setChecked(properties_.singleLineProperties.hasNeutral);
merge_checkbox -> setChecked(properties_.singleLineProperties.is_pen);
merge_checkbox -> setEnabled(!isReadOnly() && properties_.type == ConductorProperties::Single && ground_checkbox -> isChecked() && neutral_checkbox -> isChecked());
phase_spinbox -> setValue(properties_.singleLineProperties.phasesCount());
phase_slider -> setValue(properties_.singleLineProperties.phasesCount());
phase_checkbox -> setChecked(properties_.singleLineProperties.phasesCount());
verti_select -> setValue(properties_.verti_rotate_text);
horiz_select -> setValue(properties_.horiz_rotate_text);
buildConnections();
updatePreview();
@@ -308,7 +196,6 @@ void ConductorPropertiesWidget::setConductorType(ConductorProperties::ConductorT
phase_spinbox -> setEnabled(sl);
ground_checkbox -> setEnabled(sl);
neutral_checkbox -> setEnabled(sl);
merge_checkbox -> setEnabled(sl);
}
/// @param p les nouvelles proprietes
@@ -321,46 +208,3 @@ void ConductorPropertiesWidget::setConductorProperties(const ConductorProperties
ConductorProperties ConductorPropertiesWidget::conductorProperties() const {
return(properties_);
}
/**
@return true si ce widget est en lecture seule, false sinon
*/
bool ConductorPropertiesWidget::isReadOnly() const {
return(text_field -> isReadOnly());
}
/**
@param ro true pour passer ce widget en lecture seule, false sinon
*/
void ConductorPropertiesWidget::setReadOnly(bool ro) {
// enable or disable all child widgets according to the read only state
simple -> setDisabled(ro);
multiline -> setDisabled(ro);
singleline -> setDisabled(ro);
text_field -> setReadOnly(ro);
phase_checkbox -> setDisabled(ro);
phase_spinbox -> setReadOnly(ro);
ground_checkbox -> setDisabled(ro);
neutral_checkbox -> setDisabled(ro);
merge_checkbox -> setDisabled(ro);
color_button -> setDisabled(ro);
line_style -> setDisabled(ro);
// if the widget is not read-only, we still need to disable some widgets for consistency
if (!ro) {
updateDisplay();
}
}
/**
Gere le focus de ce widget
*/
void ConductorPropertiesWidget::focusInEvent(QFocusEvent *event) {
if (properties_.type == ConductorProperties::Multi) {
text_field -> setFocus(Qt::ActiveWindowFocusReason);
text_field -> selectAll();
} else if (properties_.type == ConductorProperties::Single) {
phase_spinbox -> setFocus(Qt::ActiveWindowFocusReason);
phase_spinbox -> selectAll();
}
QWidget::focusInEvent(event);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -17,17 +17,17 @@
*/
#ifndef CONDUCTOR_PROPERTIES_WIDGET_H
#define CONDUCTOR_PROPERTIES_WIDGET_H
#include "conductorproperties.h"
#include "qtextorientationspinboxwidget.h"
#include <QWidget>
#include "conductor.h"
#include <QtGui>
/**
This widget enables users to change the properties of a particular
conductor; these properties include singleline symbols, style, color, and
conductor type but exclude the path it draws.
Ce widget permet a l utilisateur d'editer les proprietes d'un conducteur.
Par proprietes, on entend non pas le trajet effectue par le conducteur mais
les options supplementaires : symboles unifilaires, presence ou non d'un
champ de texte, contenu de ce champ de texte, etc.
*/
class ConductorPropertiesWidget : public QWidget {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
ConductorPropertiesWidget(QWidget * = 0);
ConductorPropertiesWidget(const ConductorProperties &, QWidget * = 0);
@@ -36,35 +36,25 @@ class ConductorPropertiesWidget : public QWidget {
private:
ConductorPropertiesWidget(const ConductorPropertiesWidget &);
// methods
// methodes
public:
void setConductorProperties(const ConductorProperties &);
ConductorProperties conductorProperties() const;
bool isReadOnly() const;
void setReadOnly(bool);
private:
void setConductorType(ConductorProperties::ConductorType);
void setColorButton(const QColor &);
QColor colorButton() const;
public slots:
void updatePreview();
void updateConfig();
void updateDisplay();
void chooseColor();
protected:
void focusInEvent(QFocusEvent *);
// private attributes
// attributs prives
private:
QButtonGroup *radio_buttons;
QRadioButton *simple;
QRadioButton *multiline;
QLineEdit *text_field;
QTextOrientationSpinBoxWidget *verti_select;
QTextOrientationSpinBoxWidget *horiz_select;
QRadioButton *singleline;
QCheckBox *phase_checkbox;
QSlider *phase_slider;
@@ -72,13 +62,10 @@ class ConductorPropertiesWidget : public QWidget {
QCheckBox *ground_checkbox;
QCheckBox *neutral_checkbox;
QLabel *preview;
QPushButton *color_button;
QComboBox *line_style;
QCheckBox *merge_checkbox;
ConductorProperties properties_;
// private methods
// methodes privees
void buildInterface();
void buildConnections();
void destroyConnections();

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,11 +20,11 @@
#include <QPointF>
#include "qet.h"
/**
This class represents a conductor segment.
Cette classe represente un segment de conducteur.
*/
class ConductorSegment {
// constructors, destructor
// constructeurs, destructeur
public:
ConductorSegment(const QPointF &, const QPointF &, ConductorSegment * = NULL, ConductorSegment * = NULL);
virtual ~ConductorSegment();
@@ -32,14 +32,14 @@ class ConductorSegment {
private:
ConductorSegment(const ConductorSegment &);
// attributes
// attributs
private:
ConductorSegment *previous_segment;
ConductorSegment *next_segment;
QPointF point1;
QPointF point2;
// methods
// methodes
public:
void moveX(const qreal &);
void moveY(const qreal &);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,16 +20,16 @@
#include <QtCore>
#include "conductorsegment.h"
/**
This class embeds the profile (i.e. main characteristics) of a conductor
segment.
Cette classe contient le profil (= les caracteristiques essentielles) d'un
segment de conducteur.
*/
class ConductorSegmentProfile {
// constructors, destructor
// constructeurs, destructeur
public:
/**
Constructor
@param l segment length
@param ori true if the segment is horizontal, false if it is vertical
Constructeur
@param l longueur du segment
@param ori true si le segment est horizontal, false s'il est vertical
*/
ConductorSegmentProfile(qreal l, bool ori = true) :
length(l),
@@ -38,8 +38,8 @@ class ConductorSegmentProfile {
}
/**
Constructor
@param segment Segment the profile should be copied from.
Constructeur
@param segment ConductorSegment dont il faut extraire le profil
*/
ConductorSegmentProfile(ConductorSegment *segment) :
length(segment -> length()),
@@ -47,15 +47,15 @@ class ConductorSegmentProfile {
{
}
/// Destructor
/// Destructeur
virtual ~ConductorSegmentProfile() {
}
// attributes
// attributs
public:
/// segment length
/// longueur du segment
qreal length;
/// segment orientation
/// orientation du segment
bool isHorizontal;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -16,7 +16,6 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "configdialog.h"
#include "configpages.h"
#include "qetapp.h"
/**
@@ -24,17 +23,22 @@
@param parent QWidget parent
*/
ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) {
setWindowTitle(tr("Configurer QElectroTech"));
// liste des pages
pages_list = new QListWidget();
pages_list -> setViewMode(QListView::IconMode);
pages_list -> setIconSize(QSize(110, 110));
pages_list -> setIconSize(QSize(48, 48));
pages_list -> setMovement(QListView::Static);
pages_list -> setMinimumWidth(150);
pages_list -> setMaximumWidth(150);
pages_list -> setMinimumWidth(135);
pages_list -> setMaximumWidth(135);
pages_list -> setSpacing(4);
// pages
pages_widget = new QStackedWidget();
addPage(new NewDiagramPage());
buildPagesList();
// boutons
buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
@@ -53,12 +57,6 @@ ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) {
connect(buttons, SIGNAL(accepted()), this, SLOT(applyConf()));
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
connect(pages_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(changePage(QListWidgetItem *, QListWidgetItem*)));
#ifdef Q_WS_MAC
if (parent) {
setWindowFlags(Qt::Sheet);
}
#endif
}
/// Destructeur
@@ -79,21 +77,14 @@ void ConfigDialog::changePage(QListWidgetItem *current, QListWidgetItem *previou
void ConfigDialog::buildPagesList() {
pages_list -> clear();
foreach(ConfigPage *page, pages) {
addPageToList(page);
QListWidgetItem *new_button = new QListWidgetItem(pages_list);
new_button -> setIcon(page -> icon());
new_button -> setText(page -> title());
new_button -> setTextAlignment(Qt::AlignHCenter);
new_button -> setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}
}
/**
Add the \a page ConfigPage to this configuration dialog.
*/
void ConfigDialog::addPageToList(ConfigPage *page) {
QListWidgetItem *new_button = new QListWidgetItem(pages_list);
new_button -> setIcon(page -> icon());
new_button -> setText(page -> title());
new_button -> setTextAlignment(Qt::AlignHCenter);
new_button -> setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}
/**
Applique la configuration de toutes les pages
*/
@@ -111,5 +102,4 @@ void ConfigDialog::addPage(ConfigPage *page) {
if (!page || pages.contains(page)) return;
pages << page;
pages_widget -> addWidget(page);
addPageToList(page);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -18,36 +18,35 @@
#ifndef CONFIG_DIALOG_H
#define CONFIG_DIALOG_H
#include <QDialog>
class ConfigPage;
#include "configpages.h"
class QListWidget;
class QListWidgetItem;
class QStackedWidget;
class QDialogButtonBox;
/**
This class represents the configuration dialog for QElectroTech.
It displays "configuration pages", each page having to provide an icon and
a title.
Cette classe represente le dialogue de configuration de QElectroTech.
Il s'agit d'un dialogue affichant des "pages de configuration".
Chaque page de configuration doit fournir une icone et un titre.
*/
class ConfigDialog : public QDialog {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
ConfigDialog(QWidget * = 0);
virtual ~ConfigDialog();
private:
ConfigDialog(const ConfigDialog &);
// methods
// methodes
public slots:
void changePage(QListWidgetItem *, QListWidgetItem *);
void changePage(QListWidgetItem *, QListWidgetItem *);
void applyConf();
void addPage(ConfigPage *);
private:
void buildPagesList();
void addPageToList(ConfigPage *);
// attributes
// attributs
private:
QListWidget *pages_list;
QStackedWidget *pages_widget;

136
configpages.cpp Normal file
View File

@@ -0,0 +1,136 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "configpages.h"
#include "qetapp.h"
/**
Constructeur
@param parent QWidget parent
*/
NewDiagramPage::NewDiagramPage(QWidget *parent) : ConfigPage(parent) {
// acces a la configuration de QElectroTech
QSettings &settings = QETApp::settings();
// recupere les dimensions du schema
int columns_count_value = settings.value("diagrameditor/defaultcols", 15).toInt();
int columns_width_value = qRound(settings.value("diagrameditor/defaultcolsize", 50.0).toDouble());
int columns_height_value = qRound(settings.value("diagrameditor/defaultheight", 500.0).toDouble());
QVBoxLayout *vlayout1 = new QVBoxLayout();
QLabel *title = new QLabel(tr("Nouveau sch\351ma"));
vlayout1 -> addWidget(title);
QFrame *horiz_line = new QFrame();
horiz_line -> setFrameShape(QFrame::HLine);
vlayout1 -> addWidget(horiz_line);
QHBoxLayout *hlayout1 = new QHBoxLayout();
QVBoxLayout *vlayout2 = new QVBoxLayout();
QGroupBox *diagram_size_box = new QGroupBox(tr("Dimensions du sch\351ma"));
diagram_size_box -> setMinimumWidth(300);
QGridLayout *diagram_size_box_layout = new QGridLayout(diagram_size_box);
QLabel *ds1 = new QLabel(tr("Colonnes :"));
columns_count = new QSpinBox(diagram_size_box);
columns_count -> setMinimum(3); /// @todo methode statique pour recuperer ca
columns_count -> setValue(columns_count_value);
columns_width = new QSpinBox(diagram_size_box);
columns_width -> setMinimum(1);
columns_width -> setSingleStep(10);
columns_width -> setValue(columns_width_value);
columns_width -> setPrefix(tr("\327"));
columns_width -> setSuffix(tr("px"));
QLabel *ds2 = new QLabel(tr("Hauteur :"));
columns_height = new QSpinBox(diagram_size_box);
columns_height -> setRange(80, 10000); /// @todo methode statique pour recuperer ca
columns_height -> setSingleStep(80);
columns_height -> setValue(columns_height_value);
diagram_size_box_layout -> addWidget(ds1, 0, 0);
diagram_size_box_layout -> addWidget(columns_count, 0, 1);
diagram_size_box_layout -> addWidget(columns_width, 0, 2);
diagram_size_box_layout -> addWidget(ds2, 1, 0);
diagram_size_box_layout -> addWidget(columns_height, 1, 1);
ipw = new InsetPropertiesWidget(QETDiagramEditor::defaultInsetProperties(), true, this);
// proprietes par defaut des conducteurs
ConductorProperties cp;
cp.fromSettings(settings, "diagrameditor/defaultconductor");
cpw = new ConductorPropertiesWidget(cp);
vlayout2 -> addWidget(diagram_size_box);
vlayout2 -> addWidget(ipw);
hlayout1 -> addLayout(vlayout2);
hlayout1 -> addWidget(cpw);
vlayout1 -> addLayout(hlayout1);
vlayout1 -> addStretch(1);
hlayout1 -> setAlignment(cpw, Qt::AlignTop);
setLayout(vlayout1);
}
/// Destructeur
NewDiagramPage::~NewDiagramPage() {
}
/**
Applique la configuration de cette page
*/
void NewDiagramPage::applyConf() {
QSettings &settings = QETApp::settings();
// dimensions des nouveaux schemas
settings.setValue("diagrameditor/defaultcols", columns_count -> value());
settings.setValue("diagrameditor/defaultcolsize", columns_width -> value());
settings.setValue("diagrameditor/defaultheight", columns_height -> value());
// proprietes du cartouche
InsetProperties inset = ipw-> insetProperties();
settings.setValue("diagrameditor/defaulttitle", inset.title);
settings.setValue("diagrameditor/defaultauthor", inset.author);
settings.setValue("diagrameditor/defaultfilename", inset.filename);
settings.setValue("diagrameditor/defaultfolio", inset.folio);
QString date_setting_value;
if (inset.useDate == InsetProperties::UseDateValue) {
if (inset.date.isNull()) date_setting_value = "null";
else date_setting_value = inset.date.toString("yyyyMMdd");
} else {
date_setting_value = "now";
}
settings.setValue("diagrameditor/defaultdate", date_setting_value);
// proprietes par defaut des conducteurs
cpw -> conductorProperties().toSettings(settings, "diagrameditor/defaultconductor");
}
/// @return l'icone de cette page
QIcon NewDiagramPage::icon() const {
return(QIcon(":/ico/conf_new_diagram.png"));
}
/// @return le titre de cette page
QString NewDiagramPage::title() const {
return(tr("Nouveau sch\351ma"));
}

72
configpages.h Normal file
View File

@@ -0,0 +1,72 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIG_PAGES_H
#define CONFIG_PAGES_H
#include <QtGui>
#include "conductorpropertieswidget.h"
#include "insetpropertieswidget.h"
/**
Cette classe abstraite contient les methodes que toutes les pages de
configuration doivent implementer.
*/
class ConfigPage : public QWidget {
Q_OBJECT
public:
/**
Constructeur
@param parent QWidget parent
*/
ConfigPage(QWidget *parent) : QWidget(parent) {};
/// Destructeur
virtual ~ConfigPage() {};
/// Applique la configuration saisie par l'utilisateur dans la page de configuration
virtual void applyConf() = 0;
/// @return le titre de la page de configuration
virtual QString title() const = 0;
/// @return l'icone de la page de configuration
virtual QIcon icon() const = 0;
};
/**
Cette classe represente la page de configuration des nouveaux schemas.
*/
class NewDiagramPage : public ConfigPage {
Q_OBJECT
// constructeurs, destructeur
public:
NewDiagramPage(QWidget * = 0);
virtual ~NewDiagramPage();
private:
NewDiagramPage(const NewDiagramPage &);
// methodes
public:
void applyConf();
QString title() const;
QIcon icon() const;
// attributs
public:
QSpinBox *columns_count; ///< Widget d'edition du nombre par defaut de colonnes
QSpinBox *columns_width; ///< Widget d'edition de la largeur par defaut des colonnes
QSpinBox *columns_height; ///< Widget d'edition de la hauteur par defaut des colonnes
InsetPropertiesWidget *ipw; ///< Widget d'edition des proprietes par defaut du cartouche
ConductorPropertiesWidget *cpw; ///< Widget d'edition des proprietes par defaut des conducteurs
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -19,151 +19,119 @@
#include "elementtextitem.h"
#include "diagram.h"
#include "qetapp.h"
#include "partline.h"
#include "elementdefinition.h"
#include <iostream>
/**
Constructeur de la classe CustomElement. Permet d'instancier un element
utilisable comme un element fixe a la difference que l'element perso est
construit a partir d'une description au format XML. Celle-ci est recuperee
a l'emplacement indique.
@param location Emplacement de la definition d'element a utiliser
Constructeur de la classe ElementPerso. Permet d'instancier un element
utilisable comme un element fixe a la difference que l'element perso lit
sa description (noms, dessin, comportement) dans un fichier XML a fournir
en parametre.
@param nom_fichier Le chemin du fichier XML decrivant l'element
@param qgi Le QGraphicsItem parent de cet element
@param s Le Schema affichant cet element
@param state Un pointeur facultatif vers un entier. La valeur de cet entier
@param etat Un pointeur facultatif vers un entier. La valeur de cet entier
sera changee de maniere a refleter le deroulement de l'instanciation :
- 0 : L'instanciation a reussi
- 1 : l'emplacement n'a pas permis d'acceder a une definition d'element
- 2 : la definition n'etait pas lisible
- 3 : la definition n'etait pas valide / exploitable / utilisable
- 4 : Le document XML n'est pas un element "definition"
- 1 : Le fichier n'existe pas
- 2 : Le fichier n'a pu etre ouvert
- 3 : Le fichier n'est pas un document XML
- 4 : Le document XML n'a pas une "definition" comme racine
- 5 : Les attributs de la definition ne sont pas presents et / ou valides
- 6 : La definition est vide
- 7 : L'analyse d'un element XML decrivant une partie du dessin de l'element a echoue
- 8 : Aucune partie du dessin n'a pu etre chargee
*/
CustomElement::CustomElement(const ElementsLocation &location, QGraphicsItem *qgi, Diagram *s, int *state) :
FixedElement(qgi, s),
elmt_state(-1),
location_(location),
forbid_antialiasing(false)
{
// recupere la definition de l'element
ElementsCollectionItem *element_item = QETApp::collectionItem(location);
ElementDefinition *element_definition;
if (
!element_item ||\
!element_item -> isElement() ||\
!(element_definition = qobject_cast<ElementDefinition *>(element_item))
) {
if (state) *state = 1;
elmt_state = 1;
CustomElement::CustomElement(QString &nom_fichier, QGraphicsItem *qgi, Diagram *s, int *etat) : FixedElement(qgi, s) {
nomfichier = nom_fichier;
// pessimisme inside : par defaut, ca foire
elmt_etat = -1;
// le fichier doit exister
QFileInfo infos_file(nomfichier);
if (!infos_file.exists() || !infos_file.isFile()) {
if (etat != NULL) *etat = 1;
elmt_etat = 1;
return;
}
if (!element_definition -> isReadable()) {
if (state) *state = 2;
elmt_state = 2;
// le fichier doit etre lisible
QFile fichier(nomfichier);
if (!fichier.open(QIODevice::ReadOnly)) {
if (etat != NULL) *etat = 2;
elmt_etat = 2;
return;
}
if (element_definition -> isNull()) {
if (state) *state = 3;
elmt_state = 3;
// le fichier doit etre un document XML
QDomDocument document_xml;
if (!document_xml.setContent(&fichier)) {
if (etat != NULL) *etat = 3;
elmt_etat = 3;
return;
}
buildFromXml(element_definition -> xml(), &elmt_state);
if (state) *state = elmt_state;
if (elmt_state) return;
if (state) *state = 0;
elmt_state = 0;
}
CustomElement::CustomElement(const QDomElement &xml_def_elmt, QGraphicsItem *qgi, Diagram *s, int *state) : FixedElement(qgi, s) {
int elmt_state = -1;
buildFromXml(xml_def_elmt, &elmt_state);
if (state) *state = elmt_state;
}
/**
Construit l'element personnalise a partir d'un element XML representant sa
definition.
@param xml_def_elmt
@param state Un pointeur facultatif vers un entier. La valeur de cet entier
sera changee de maniere a refleter le deroulement de l'instanciation :
- 0 : La construction s'est bien passee
- 4 : Le document XML n'est pas un element "definition"
- 5 : Les attributs de la definition ne sont pas presents et / ou valides
- 6 : La definition est vide
- 7 : L'analyse d'un element XML decrivant une partie du dessin de l'element a echoue
- 8 : Aucune partie du dessin n'a pu etre chargee
@return true si le chargement a reussi, false sinon
*/
bool CustomElement::buildFromXml(const QDomElement &xml_def_elmt, int *state) {
if (xml_def_elmt.tagName() != "definition" || xml_def_elmt.attribute("type") != "element") {
if (state) *state = 4;
return(false);
// la racine est supposee etre une definition d'element
QDomElement racine = document_xml.documentElement();
if (racine.tagName() != "definition" || racine.attribute("type") != "element") {
if (etat != NULL) *etat = 4;
elmt_etat = 4;
return;
}
// verifie basiquement que la version actuelle est capable de lire ce fichier
if (xml_def_elmt.hasAttribute("version")) {
if (racine.hasAttribute("version")) {
bool conv_ok;
qreal element_version = xml_def_elmt.attribute("version").toDouble(&conv_ok);
qreal element_version = racine.attribute("version").toDouble(&conv_ok);
if (conv_ok && QET::version.toDouble() < element_version) {
std::cerr << qPrintable(
QObject::tr("Avertissement : l'\351l\351ment "
" a \351t\351 enregistr\351 avec une version"
QObject::tr("Avertissement : l'\351l\351ment ") + nom_fichier
+ QObject::tr(" a \351t\351 enregistr\351 avec une version"
" ult\351rieure de QElectroTech.")
) << std::endl;
);
}
}
// ces attributs doivent etre presents et valides
int w, h, hot_x, hot_y;
if (
!QET::attributeIsAnInteger(xml_def_elmt, QString("width"), &w) ||\
!QET::attributeIsAnInteger(xml_def_elmt, QString("height"), &h) ||\
!QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_x"), &hot_x) ||\
!QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_y"), &hot_y) ||\
!validOrientationAttribute(xml_def_elmt)
!QET::attributeIsAnInteger(racine, QString("width"), &w) ||\
!QET::attributeIsAnInteger(racine, QString("height"), &h) ||\
!QET::attributeIsAnInteger(racine, QString("hotspot_x"), &hot_x) ||\
!QET::attributeIsAnInteger(racine, QString("hotspot_y"), &hot_y) ||\
!validOrientationAttribute(racine)
) {
if (state) *state = 5;
return(false);
if (etat != NULL) *etat = 5;
elmt_etat = 5;
return;
}
// on peut d'ores et deja specifier la taille et le hotspot
setSize(w, h);
setHotspot(QPoint(hot_x, hot_y));
setInternalConnections(xml_def_elmt.attribute("ic") == "true");
setInternalConnections(racine.attribute("ic") == "true");
// la definition est supposee avoir des enfants
if (xml_def_elmt.firstChild().isNull()) {
if (state) *state = 6;
return(false);
if (racine.firstChild().isNull()) {
if (etat != NULL) *etat = 6;
elmt_etat = 6;
return;
}
// initialisation du QPainter (pour dessiner l'element)
QPainter qp;
qp.begin(&drawing);
QPainter low_zoom_qp;
low_zoom_qp.begin(&low_zoom_drawing);
QPen tmp;
tmp.setWidthF(1.0); // ligne vaudou pour prise en compte du setCosmetic - ne pas enlever
tmp.setCosmetic(true);
low_zoom_qp.setPen(tmp);
qp.begin(&dessin);
QPen t;
t.setColor(Qt::black);
t.setWidthF(1.0);
t.setJoinStyle(Qt::MiterJoin);
qp.setPen(t);
// extrait les noms de la definition XML
names.fromXml(xml_def_elmt);
setToolTip(name());
names.fromXml(racine);
setToolTip(nom());
// parcours des enfants de la definition : parties du dessin
int parsed_elements_count = 0;
for (QDomNode node = xml_def_elmt.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
int nb_elements_parses = 0;
for (QDomNode node = racine.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
QDomElement elmts = node.toElement();
if (elmts.isNull()) continue;
if (elmts.tagName() == "description") {
@@ -172,17 +140,11 @@ bool CustomElement::buildFromXml(const QDomElement &xml_def_elmt, int *state) {
for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
QDomElement qde = n.toElement();
if (qde.isNull()) continue;
if (parseElement(qde, qp)) {
++ parsed_elements_count;
QString current_tag = qde.tagName();
if (current_tag != "terminal" && current_tag != "input") {
forbid_antialiasing = true;
parseElement(qde, low_zoom_qp);
forbid_antialiasing = false;
}
} else {
if (state) *state = 7;
return(false);
if (parseElement(qde, qp)) ++ nb_elements_parses;
else {
if (etat != NULL) *etat = 7;
elmt_etat = 7;
return;
}
}
}
@@ -190,16 +152,19 @@ bool CustomElement::buildFromXml(const QDomElement &xml_def_elmt, int *state) {
// fin du dessin
qp.end();
low_zoom_qp.end();
// il doit y avoir au moins un element charge
if (!parsed_elements_count) {
if (state) *state = 8;
return(false);
} else {
if (state) *state = 0;
return(true);
if (!nb_elements_parses) {
if (etat != NULL) *etat = 8;
elmt_etat = 8;
return;
}
// fermeture du fichier
fichier.close();
if (etat != NULL) *etat = 0;
elmt_etat = 0;
}
/**
@@ -220,15 +185,10 @@ QList<Conductor *> CustomElement::conductors() const {
return(conductors);
}
/// @return la liste des textes de cet element
QList<ElementTextItem *> CustomElement::texts() const {
return(list_texts_);
}
/**
@return Le nombre de bornes que l'element possede
*/
int CustomElement::terminalsCount() const {
int CustomElement::nbTerminals() const {
return(list_terminals.size());
}
@@ -237,12 +197,8 @@ int CustomElement::terminalsCount() const {
@param qp Le QPainter a utiliser pour dessiner l'element
@param options Les options graphiques
*/
void CustomElement::paint(QPainter *qp, const QStyleOptionGraphicsItem *options) {
if (options && options -> levelOfDetail < 1.0) {
low_zoom_drawing.play(qp);
} else {
drawing.play(qp);
}
void CustomElement::paint(QPainter *qp, const QStyleOptionGraphicsItem *) {
dessin.play(qp);
}
/**
@@ -255,12 +211,12 @@ void CustomElement::paint(QPainter *qp, const QStyleOptionGraphicsItem *options)
formes peuvent avoir un attribut style. @see setPainterStyle
@param e L'element XML a analyser
@param qp Le QPainter a utiliser pour dessiner l'element perso
@param s Le schema sur lequel sera affiche l'element perso
@return true si l'analyse reussit, false sinon
*/
bool CustomElement::parseElement(QDomElement &e, QPainter &qp) {
if (e.tagName() == "terminal") return(parseTerminal(e));
else if (e.tagName() == "line") return(parseLine(e, qp));
else if (e.tagName() == "rect") return(parseRect(e, qp));
else if (e.tagName() == "ellipse") return(parseEllipse(e, qp));
else if (e.tagName() == "circle") return(parseCircle(e, qp));
else if (e.tagName() == "arc") return(parseArc(e, qp));
@@ -283,129 +239,14 @@ bool CustomElement::parseElement(QDomElement &e, QPainter &qp) {
*/
bool CustomElement::parseLine(QDomElement &e, QPainter &qp) {
// verifie la presence et la validite des attributs obligatoires
qreal x1, y1, x2, y2;
double x1, y1, x2, y2;
if (!QET::attributeIsAReal(e, QString("x1"), &x1)) return(false);
if (!QET::attributeIsAReal(e, QString("y1"), &y1)) return(false);
if (!QET::attributeIsAReal(e, QString("x2"), &x2)) return(false);
if (!QET::attributeIsAReal(e, QString("y2"), &y2)) return(false);
QET::EndType first_end = QET::endTypeFromString(e.attribute("end1"));
QET::EndType second_end = QET::endTypeFromString(e.attribute("end2"));
qreal length1, length2;
if (!QET::attributeIsAReal(e, QString("length1"), &length1)) length1 = 1.5;
if (!QET::attributeIsAReal(e, QString("length2"), &length2)) length2 = 1.5;
qp.save();
setPainterStyle(e, qp);
QPen t = qp.pen();
t.setJoinStyle(Qt::MiterJoin);
qp.setPen(t);
QLineF line(x1, y1, x2, y2);
QPointF point1(line.p1());
QPointF point2(line.p2());
qreal line_length(line.length());
qreal pen_width = qp.pen().widthF();
// determine s'il faut dessiner les extremites
bool draw_1st_end, draw_2nd_end;
qreal reduced_line_length = line_length - (length1 * PartLine::requiredLengthForEndType(first_end));
draw_1st_end = first_end && reduced_line_length >= 0;
if (draw_1st_end) {
reduced_line_length -= (length2 * PartLine::requiredLengthForEndType(second_end));
} else {
reduced_line_length = line_length - (length2 * PartLine::requiredLengthForEndType(second_end));
}
draw_2nd_end = second_end && reduced_line_length >= 0;
// dessine la premiere extremite
QPointF start_point, stop_point;
if (draw_1st_end) {
QList<QPointF> four_points1(PartLine::fourEndPoints(point1, point2, length1));
if (first_end == QET::Circle) {
qp.drawEllipse(QRectF(four_points1[0] - QPointF(length1, length1), QSizeF(length1 * 2.0, length1 * 2.0)));
start_point = four_points1[1];
} else if (first_end == QET::Diamond) {
qp.drawPolygon(QPolygonF() << four_points1[1] << four_points1[2] << point1 << four_points1[3]);
start_point = four_points1[1];
} else if (first_end == QET::Simple) {
qp.drawPolyline(QPolygonF() << four_points1[3] << point1 << four_points1[2]);
start_point = point1;
} else if (first_end == QET::Triangle) {
qp.drawPolygon(QPolygonF() << four_points1[0] << four_points1[2] << point1 << four_points1[3]);
start_point = four_points1[0];
}
// ajuste le depart selon l'epaisseur du trait
if (pen_width && (first_end == QET::Simple || first_end == QET::Circle)) {
start_point = QLineF(start_point, point2).pointAt(pen_width / 2.0 / line_length);
}
} else {
start_point = point1;
}
// dessine la seconde extremite
if (draw_2nd_end) {
QList<QPointF> four_points2(PartLine::fourEndPoints(point2, point1, length2));
if (second_end == QET::Circle) {
qp.drawEllipse(QRectF(four_points2[0] - QPointF(length2, length2), QSizeF(length2 * 2.0, length2 * 2.0)));
stop_point = four_points2[1];
} else if (second_end == QET::Diamond) {
qp.drawPolygon(QPolygonF() << four_points2[2] << point2 << four_points2[3] << four_points2[1]);
stop_point = four_points2[1];
} else if (second_end == QET::Simple) {
qp.drawPolyline(QPolygonF() << four_points2[3] << point2 << four_points2[2]);
stop_point = point2;
} else if (second_end == QET::Triangle) {
qp.drawPolygon(QPolygonF() << four_points2[0] << four_points2[2] << point2 << four_points2[3] << four_points2[0]);
stop_point = four_points2[0];
}
// ajuste l'arrivee selon l'epaisseur du trait
if (pen_width && (second_end == QET::Simple || second_end == QET::Circle)) {
stop_point = QLineF(point1, stop_point).pointAt((line_length - (pen_width / 2.0)) / line_length);
}
} else {
stop_point = point2;
}
qp.drawLine(start_point, stop_point);
qp.restore();
return(true);
}
/**
Analyse un element XML suppose representer un rectangle. Si l'analyse
reussit, le rectangle est ajoute au dessin.
Le rectangle est defini par les attributs suivants :
- x : abscisse du coin superieur gauche du rectangle
- y : ordonnee du coin superieur gauche du rectangle
- width : largeur du rectangle
- height : hauteur du rectangle
@param e L'element XML a analyser
@param qp Le QPainter a utiliser pour dessiner l'element perso
@return true si l'analyse reussit, false sinon
*/
bool CustomElement::parseRect(QDomElement &e, QPainter &qp) {
// verifie la presence des attributs obligatoires
qreal rect_x, rect_y, rect_w, rect_h;
if (!QET::attributeIsAReal(e, QString("x"), &rect_x)) return(false);
if (!QET::attributeIsAReal(e, QString("y"), &rect_y)) return(false);
if (!QET::attributeIsAReal(e, QString("width"), &rect_w)) return(false);
if (!QET::attributeIsAReal(e, QString("height"), &rect_h)) return(false);
qp.save();
setPainterStyle(e, qp);
// force le type de jointures pour les rectangles
QPen p = qp.pen();
p.setJoinStyle(Qt::MiterJoin);
qp.setPen(p);
qp.drawRect(QRectF(rect_x, rect_y, rect_w, rect_h));
qp.drawLine(QLineF(x1, y1, x2, y2));
qp.restore();
return(true);
}
@@ -421,10 +262,11 @@ bool CustomElement::parseRect(QDomElement &e, QPainter &qp) {
@param e L'element XML a analyser
@param qp Le QPainter a utiliser pour dessiner l'element perso
@return true si l'analyse reussit, false sinon
@todo utiliser des attributs plus coherents : x et y = centre, rayon = vrai rayon
*/
bool CustomElement::parseCircle(QDomElement &e, QPainter &qp) {
// verifie la presence des attributs obligatoires
qreal cercle_x, cercle_y, cercle_r;
double cercle_x, cercle_y, cercle_r;
if (!QET::attributeIsAReal(e, QString("x"), &cercle_x)) return(false);
if (!QET::attributeIsAReal(e, QString("y"), &cercle_y)) return(false);
if (!QET::attributeIsAReal(e, QString("diameter"), &cercle_r)) return(false);
@@ -447,10 +289,11 @@ bool CustomElement::parseCircle(QDomElement &e, QPainter &qp) {
@param e L'element XML a analyser
@param qp Le QPainter a utiliser pour dessiner l'element perso
@return true si l'analyse reussit, false sinon
@todo utiliser des attributs plus coherents : x et y = centre
*/
bool CustomElement::parseEllipse(QDomElement &e, QPainter &qp) {
// verifie la presence des attributs obligatoires
qreal ellipse_x, ellipse_y, ellipse_l, ellipse_h;
double ellipse_x, ellipse_y, ellipse_l, ellipse_h;
if (!QET::attributeIsAReal(e, QString("x"), &ellipse_x)) return(false);
if (!QET::attributeIsAReal(e, QString("y"), &ellipse_y)) return(false);
if (!QET::attributeIsAReal(e, QString("width"), &ellipse_l)) return(false);
@@ -478,7 +321,7 @@ bool CustomElement::parseEllipse(QDomElement &e, QPainter &qp) {
*/
bool CustomElement::parseArc(QDomElement &e, QPainter &qp) {
// verifie la presence des attributs obligatoires
qreal arc_x, arc_y, arc_l, arc_h, arc_s, arc_a;
double arc_x, arc_y, arc_l, arc_h, arc_s, arc_a;
if (!QET::attributeIsAReal(e, QString("x"), &arc_x)) return(false);
if (!QET::attributeIsAReal(e, QString("y"), &arc_y)) return(false);
if (!QET::attributeIsAReal(e, QString("width"), &arc_l)) return(false);
@@ -511,20 +354,17 @@ bool CustomElement::parsePolygon(QDomElement &e, QPainter &qp) {
else break;
}
if (i < 3) return(false);
QVector<QPointF> points(i-1);
QPointF points[i-1];
for (int j = 1 ; j < i ; ++ j) {
points.insert(
j - 1,
QPointF(
e.attribute(QString("x%1").arg(j)).toDouble(),
e.attribute(QString("y%1").arg(j)).toDouble()
)
points[j-1] = QPointF(
e.attribute(QString("x%1").arg(j)).toDouble(),
e.attribute(QString("y%1").arg(j)).toDouble()
);
}
qp.save();
setPainterStyle(e, qp);
if (e.attribute("closed") == "false") qp.drawPolyline(points.data(), i-1);
else qp.drawPolygon(points.data(), i-1);
if (e.attribute("closed") == "false") qp.drawPolyline(points, i-1);
else qp.drawPolygon(points, i-1);
qp.restore();
return(true);
}
@@ -550,53 +390,8 @@ bool CustomElement::parseText(QDomElement &e, QPainter &qp) {
qp.save();
setPainterStyle(e, qp);
// determine la police a utiliser et en recupere les metriques associees
QFont used_font = QETApp::diagramTextsFont(size);
QFontMetrics qfm(used_font);
QColor text_color = (e.attribute("color") != "white"? Qt::black : Qt::white);
// instancie un QTextDocument (comme la classe QGraphicsTextItem) pour
// generer le rendu graphique du texte
QTextDocument text_document;
text_document.setDefaultFont(used_font);
text_document.setPlainText(e.attribute("text"));
// Se positionne aux coordonnees indiquees dans la description du texte
qp.setTransform(QTransform(), false);
qp.translate(pos_x, pos_y);
// Pivote le systeme de coordonnees du QPainter pour effectuer le rendu
// dans le bon sens
qreal default_rotation_angle = 0.0;
if (QET::attributeIsAReal(e, "rotation", &default_rotation_angle)) {
qp.rotate(default_rotation_angle);
}
/*
Deplace le systeme de coordonnees du QPainter pour effectuer le rendu au
bon endroit ; note : on soustrait l'ascent() de la police pour
determiner le coin superieur gauche du texte alors que la position
indiquee correspond a la baseline.
*/
QPointF qpainter_offset(0.0, -qfm.ascent());
// ajuste le decalage selon la marge du document texte
#if QT_VERSION >= 0x040500
text_document.setDocumentMargin(0.0);
#else
// il semblerait qu'avant Qt 4.5, le documentMargin vaille 2.0 (et pas 4.0)
qpainter_offset.rx() -= 2.0;
qpainter_offset.ry() -= 2.0;
#endif
qp.translate(qpainter_offset);
// force the palette used to render the QTextDocument
QAbstractTextDocumentLayout::PaintContext ctx;
ctx.palette.setColor(QPalette::Text, text_color);
text_document.documentLayout() -> draw(&qp, ctx);
qp.setFont(QFont(QString(QETApp::diagramTextsFont()), size));
qp.drawText(QPointF(pos_x, pos_y), e.attribute("text"));
qp.restore();
return(true);
}
@@ -610,36 +405,23 @@ bool CustomElement::parseText(QDomElement &e, QPainter &qp) {
- une taille
- le fait de subir les rotations de l'element ou non
@param e L'element XML a analyser
@return Un pointeur vers l'objet ElementTextItem ainsi cree si l'analyse reussit, 0 sinon
@param s Le schema sur lequel l'element perso sera affiche
@return true si l'analyse reussit, false sinon
*/
ElementTextItem *CustomElement::parseInput(QDomElement &e) {
bool CustomElement::parseInput(QDomElement &e) {
qreal pos_x, pos_y;
int size;
if (
!QET::attributeIsAReal(e, "x", &pos_x) ||\
!QET::attributeIsAReal(e, "y", &pos_y) ||\
!QET::attributeIsAnInteger(e, "size", &size)
) return(0);
) return(false);
ElementTextItem *eti = new ElementTextItem(e.attribute("text"), this);
eti -> setFont(QETApp::diagramTextsFont(size));
// position du champ de texte
eti -> setOriginalPos(QPointF(pos_x, pos_y));
eti -> setFont(QFont(QETApp::diagramTextsFont(), size));
eti -> setPos(pos_x, pos_y);
// rotation du champ de texte
qreal original_rotation_angle = 0.0;
QET::attributeIsAReal(e, "rotation", &original_rotation_angle);
eti -> setOriginalRotationAngle(original_rotation_angle);
eti -> setRotationAngle(original_rotation_angle);
// comportement du champ lorsque son element parent est pivote
eti -> setFollowParentRotations(e.attribute("rotate") == "true");
list_texts_ << eti;
return(eti);
if (e.attribute("rotate") == "true") eti -> setFollowParentRotations(true);
return(true);
}
/**
@@ -650,24 +432,23 @@ ElementTextItem *CustomElement::parseInput(QDomElement &e) {
- orientation : orientation de la borne = Nord (n), Sud (s), Est (e) ou Ouest (w)
@param e L'element XML a analyser
@return Un pointeur vers l'objet Terminal ainsi cree, 0 sinon
@param s Le schema sur lequel l'element perso sera affiche
@return true si l'analyse reussit, false sinon
*/
Terminal *CustomElement::parseTerminal(QDomElement &e) {
bool CustomElement::parseTerminal(QDomElement &e) {
// verifie la presence et la validite des attributs obligatoires
qreal terminalx, terminaly;
double terminalx, terminaly;
QET::Orientation terminalo;
if (!QET::attributeIsAReal(e, QString("x"), &terminalx)) return(0);
if (!QET::attributeIsAReal(e, QString("y"), &terminaly)) return(0);
if (!e.hasAttribute("orientation")) return(0);
if (!QET::attributeIsAReal(e, QString("x"), &terminalx)) return(false);
if (!QET::attributeIsAReal(e, QString("y"), &terminaly)) return(false);
if (!e.hasAttribute("orientation")) return(false);
if (e.attribute("orientation") == "n") terminalo = QET::North;
else if (e.attribute("orientation") == "s") terminalo = QET::South;
else if (e.attribute("orientation") == "e") terminalo = QET::East;
else if (e.attribute("orientation") == "w") terminalo = QET::West;
else return(0);
Terminal *new_terminal = new Terminal(terminalx, terminaly, terminalo, this, qobject_cast<Diagram *>(scene()));
new_terminal -> setZValue(420); // valeur arbitraire pour maintenir les bornes au-dessus des champs de texte
list_terminals << new_terminal;
return(new_terminal);
else return(false);
list_terminals << new Terminal(terminalx, terminaly, terminalo, this, qobject_cast<Diagram *>(scene()));
return(true);
}
/**
@@ -676,7 +457,6 @@ Terminal *CustomElement::parseTerminal(QDomElement &e) {
@param aa Booleen a true pour activer l'antialiasing, a false pour le desactiver
*/
void CustomElement::setQPainterAntiAliasing(QPainter &qp, bool aa) {
if (forbid_antialiasing) aa = false;
qp.setRenderHint(QPainter::Antialiasing, aa);
qp.setRenderHint(QPainter::TextAntialiasing, aa);
qp.setRenderHint(QPainter::SmoothPixmapTransform, aa);
@@ -701,7 +481,7 @@ void CustomElement::setQPainterAntiAliasing(QPainter &qp, bool aa) {
@param e Element XML
@return true si l'attribut "orientation" est valide, false sinon
*/
bool CustomElement::validOrientationAttribute(const QDomElement &e) {
bool CustomElement::validOrientationAttribute(QDomElement &e) {
return(ori.fromString(e.attribute("orientation")));
}
@@ -710,9 +490,7 @@ bool CustomElement::validOrientationAttribute(const QDomElement &e) {
l'element XML e au QPainter qp
Les styles possibles sont :
- line-style : style du trait
- dashed : trait en pointilles (tirets)
- dashdotted : Traits et points
- dotted : trait en pointilles (points)
- dashed : trait en pointilles
- normal : trait plein [par defaut]
- line-weight : epaiseur du trait
- thin : trait fin
@@ -720,16 +498,10 @@ bool CustomElement::validOrientationAttribute(const QDomElement &e) {
- filling : remplissage de la forme
- white : remplissage blanc
- black : remplissage noir
- red : remplissage rouge
- blue : remplissage bleu
- green : remplissage vert
- none : pas de remplissage [par defaut]
- color : couleur du trait et du texte
- white : trait noir [par defaut]
- black : trait blanc
- red : trait rouge
- blue : trait bleu
- green : trait vert
Les autres valeurs ne sont pas prises en compte.
@param e L'element XML a parser
@@ -741,12 +513,9 @@ void CustomElement::setPainterStyle(QDomElement &e, QPainter &qp) {
QBrush brush = qp.brush();
// attributs par defaut
pen.setJoinStyle(Qt::BevelJoin);
pen.setJoinStyle(Qt::MiterJoin);
pen.setCapStyle(Qt::SquareCap);
pen.setColor(Qt::black);
pen.setColor(Qt::red);
pen.setColor(Qt::blue);
pen.setColor(Qt::green);
pen.setStyle(Qt::SolidLine);
pen.setWidthF(1.0);
brush.setStyle(Qt::NoBrush);
@@ -762,8 +531,6 @@ void CustomElement::setPainterStyle(QDomElement &e, QPainter &qp) {
QString style_value = rx.cap(2);
if (style_name == "line-style") {
if (style_value == "dashed") pen.setStyle(Qt::DashLine);
else if (style_value == "dotted") pen.setStyle(Qt::DotLine);
else if (style_value == "dashdoted") pen.setStyle(Qt::DashDotLine);
else if (style_value == "normal") pen.setStyle(Qt::SolidLine);
} else if (style_name == "line-weight") {
if (style_value == "thin") pen.setWidth(0);
@@ -776,15 +543,6 @@ void CustomElement::setPainterStyle(QDomElement &e, QPainter &qp) {
} else if (style_value == "black") {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::black);
} else if (style_value == "blue") {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::blue);
} else if (style_value == "red") {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::red);
} else if (style_value == "green") {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::green);
} else if (style_value == "none") {
brush.setStyle(Qt::NoBrush);
}
@@ -793,12 +551,6 @@ void CustomElement::setPainterStyle(QDomElement &e, QPainter &qp) {
pen.setColor(QColor(0, 0, 0, pen.color().alpha()));
} else if (style_value == "white") {
pen.setColor(QColor(255, 255, 255, pen.color().alpha()));
} else if (style_value == "red") {
pen.setColor(Qt::red);
}else if (style_value == "blue") {
pen.setColor(Qt::blue);
}else if (style_value == "green") {
pen.setColor(Qt::green);
}
}
}

124
customelement.h Normal file
View File

@@ -0,0 +1,124 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ELEMENTPERSO_H
#define ELEMENTPERSO_H
#include "fixedelement.h"
#include <QtGui>
#include "nameslist.h"
class CustomElementPart;
/**
Cette classe represente un element electrique. Elle est utilisable
comme un element fixe. La difference est que l'element perso lit
sa description (noms, dessin, comportement) dans un fichier XML a fournir
en parametre.
*/
class CustomElement : public FixedElement {
// constructeurs, destructeur
public:
CustomElement(QString &, QGraphicsItem * = 0, Diagram * = 0, int * = NULL);
virtual ~CustomElement();
friend class CustomElementPart;
private:
CustomElement(const CustomElement &);
// attributs
private:
int elmt_etat; // contient le code d'erreur si l'instanciation a echoue ou 0 si l'instanciation s'est bien passe
NamesList names;
QString nomfichier;
QPicture dessin;
QList<Terminal *> list_terminals;
// methodes
public:
virtual QList<Terminal *> terminals() const;
virtual QList<Conductor *> conductors() const;
virtual int nbTerminals() const;
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *);
QString typeId() const;
QString fichier() const;
bool isNull() const;
int etat() const;
QString nom() const;
private:
bool parseElement(QDomElement &, QPainter &);
bool parseLine(QDomElement &, QPainter &);
bool parseEllipse(QDomElement &, QPainter &);
bool parseCircle(QDomElement &, QPainter &);
bool parseArc(QDomElement &, QPainter &);
bool parsePolygon(QDomElement &, QPainter &);
bool parseText(QDomElement &, QPainter &);
bool parseInput(QDomElement &);
bool parseTerminal(QDomElement &);
void setQPainterAntiAliasing(QPainter &, bool);
bool validOrientationAttribute(QDomElement &);
void setPainterStyle(QDomElement &, QPainter &);
};
/**
@return L'ID du type de l'element ; pour un CustomElement, cela revient au
nom du fichier
@see fichier()
*/
inline QString CustomElement::typeId() const {
return(nomfichier);
}
/**
@return L'adresse du fichier contenant la description XML de cet element
*/
inline QString CustomElement::fichier() const {
return(nomfichier);
}
/**
@return true si cet element est nul, c'est-a-dire si le chargement de sa
description XML a echoue
*/
inline bool CustomElement::isNull() const {
return(elmt_etat != 0);
}
/**
@return Un entier representant l'etat de l'element :
- 0 : L'instanciation a reussi
- 1 : Le fichier n'existe pas
- 2 : Le fichier n'a pu etre ouvert
- 3 : Le fichier n'est pas un document XML
- 4 : Le document XML n'a pas une "definition" comme racine
- 5 : Les attributs de la definition ne sont pas presents et / ou valides
- 6 : La definition est vide
- 7 : L'analyse d'un element XML decrivant une partie du dessin de l'element a echoue
- 8 : Aucune partie du dessin n'a pu etre chargee
*/
inline int CustomElement::etat() const {
return(elmt_etat);
}
/**
@return Le nom de l'element
*/
inline QString CustomElement::nom() const {
return(names.name(QFileInfo(nomfichier).baseName()));
}
#endif

648
diagram.cpp Normal file
View File

@@ -0,0 +1,648 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include "qetapp.h"
#include "conductor.h"
#include "customelement.h"
#include "diagram.h"
#include "exportdialog.h"
#include "diagramcommands.h"
#include "diagramcontent.h"
const int Diagram::xGrid = 10;
const int Diagram::yGrid = 10;
const qreal Diagram::margin = 5.0;
/**
Constructeur
@param parent Le QObject parent du schema
*/
Diagram::Diagram(QObject *parent) :
QGraphicsScene(parent),
draw_grid(true),
use_border(true),
moved_elements_fetched(false),
qgi_manager(this),
draw_terminals(true)
{
setBackgroundBrush(Qt::white);
conductor_setter = new QGraphicsLineItem(0, 0);
conductor_setter -> setZValue(1000000);
QPen t;
t.setColor(Qt::black);
t.setWidthF(1.5);
t.setStyle(Qt::DashLine);
conductor_setter -> setPen(t);
conductor_setter -> setLine(QLineF(QPointF(0.0, 0.0), QPointF(0.0, 0.0)));
connect(this, SIGNAL(selectionChanged()), this, SLOT(slot_checkSelectionEmptinessChange()));
// lit les caracteristiques des conducteurs par defaut dans la configuration
defaultConductorProperties.fromSettings(QETApp::settings(), "diagrameditor/defaultconductor");
}
/**
Destructeur
*/
Diagram::~Diagram() {
if (conductor_setter -> scene()) removeItem(conductor_setter);
delete conductor_setter;
}
/**
Dessine l'arriere-plan du schema, cad la grille.
@param p Le QPainter a utiliser pour dessiner
@param r Le rectangle de la zone a dessiner
*/
void Diagram::drawBackground(QPainter *p, const QRectF &r) {
p -> save();
// desactive tout antialiasing, sauf pour le texte
p -> setRenderHint(QPainter::Antialiasing, false);
p -> setRenderHint(QPainter::TextAntialiasing, true);
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
// dessine un fond blanc
p -> setPen(Qt::NoPen);
p -> setBrush(Qt::white);
p -> drawRect(r);
if (draw_grid) {
// dessine les points de la grille
p -> setPen(Qt::black);
p -> setBrush(Qt::NoBrush);
qreal limite_x = r.x() + r.width();
qreal limite_y = r.y() + r.height();
int g_x = (int)ceil(r.x());
while (g_x % xGrid) ++ g_x;
int g_y = (int)ceil(r.y());
while (g_y % yGrid) ++ g_y;
for (int gx = g_x ; gx < limite_x ; gx += xGrid) {
for (int gy = g_y ; gy < limite_y ; gy += yGrid) {
p -> drawPoint(gx, gy);
}
}
}
if (use_border) border_and_inset.draw(p, margin, margin);
p -> restore();
}
/**
Gere les enfoncements de touches du clavier
@param e QKeyEvent decrivant l'evenement clavier
*/
void Diagram::keyPressEvent(QKeyEvent *e) {
QPointF movement;
switch(e -> key()) {
case Qt::Key_Left: movement = QPointF(-xGrid, 0.0); break;
case Qt::Key_Right: movement = QPointF(+xGrid, 0.0); break;
case Qt::Key_Up: movement = QPointF(0.0, -yGrid); break;
case Qt::Key_Down: movement = QPointF(0.0, +yGrid); break;
}
if (!movement.isNull() && !focusItem()) {
moveElements(movement);
}
QGraphicsScene::keyPressEvent(e);
}
/**
Gere les relachements de touches du clavier
@param e QKeyEvent decrivant l'evenement clavier
*/
void Diagram::keyReleaseEvent(QKeyEvent *e) {
// detecte le relachement d'une touche de direction ( = deplacement d'elements)
if (
(e -> key() == Qt::Key_Left || e -> key() == Qt::Key_Right ||\
e -> key() == Qt::Key_Up || e -> key() == Qt::Key_Down) &&\
!current_movement.isNull() && !e -> isAutoRepeat()
) {
// cree un objet d'annulation pour le mouvement qui vient de se finir
undoStack().push(new MoveElementsCommand(this, selectedContent(), current_movement));
invalidateMovedElements();
current_movement = QPointF();
}
QGraphicsScene::keyReleaseEvent(e);
}
/**
Exporte le schema vers une image
@return Une QImage representant le schema
*/
bool Diagram::toPaintDevice(QPaintDevice &pix, int width, int height, Qt::AspectRatioMode aspectRatioMode) {
// determine la zone source = contenu du schema + marges
QRectF source_area;
if (!use_border) {
source_area = itemsBoundingRect();
source_area.translate(-margin, -margin);
source_area.setWidth (source_area.width () + 2.0 * margin);
source_area.setHeight(source_area.height() + 2.0 * margin);
} else {
source_area = QRectF(
0.0,
0.0,
border_and_inset.borderWidth () + 2.0 * margin,
border_and_inset.borderHeight() + 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);
// prepare le rendu
QPainter p;
if (!p.begin(&pix)) return(false);
// rendu antialiase
p.setRenderHint(QPainter::Antialiasing, true);
p.setRenderHint(QPainter::TextAntialiasing, true);
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
// deselectionne tous les elements
QList<QGraphicsItem *> selected_elmts = selectedItems();
foreach (QGraphicsItem *qgi, selected_elmts) qgi -> setSelected(false);
// effectue le rendu lui-meme
render(&p, QRect(QPoint(0, 0), image_size), source_area, aspectRatioMode);
p.end();
// restaure les elements selectionnes
foreach (QGraphicsItem *qgi, selected_elmts) qgi -> setSelected(true);
return(true);
}
/**
Permet de connaitre les dimensions qu'aura l'image generee par la methode toImage()
@return La taille de l'image generee par toImage()
*/
QSize Diagram::imageSize() const {
// determine la zone source = contenu du schema + marges
qreal image_width, image_height;
if (!use_border) {
QRectF items_rect = itemsBoundingRect();
image_width = items_rect.width();
image_height = items_rect.height();
} else {
image_width = border_and_inset.borderWidth();
image_height = border_and_inset.borderHeight();
}
image_width += 2.0 * margin;
image_height += 2.0 * margin;
// renvoie la taille de la zone source
return(QSizeF(image_width, image_height).toSize());
}
/**
Exporte tout ou partie du schema
@param diagram Booleen (a vrai par defaut) indiquant si le XML genere doit
representer tout le schema ou seulement les elements selectionnes
@return Un Document XML (QDomDocument)
*/
QDomDocument Diagram::toXml(bool diagram) {
// document
QDomDocument document;
// racine de l'arbre XML
QDomElement racine = document.createElement("diagram");
// proprietes du schema
if (diagram) {
if (!border_and_inset.author().isNull()) racine.setAttribute("author", border_and_inset.author());
if (!border_and_inset.date().isNull()) racine.setAttribute("date", border_and_inset.date().toString("yyyyMMdd"));
if (!border_and_inset.title().isNull()) racine.setAttribute("title", border_and_inset.title());
if (!border_and_inset.fileName().isNull()) racine.setAttribute("filename", border_and_inset.fileName());
if (!border_and_inset.folio().isNull()) racine.setAttribute("folio", border_and_inset.folio());
racine.setAttribute("cols", border_and_inset.nbColumn());
racine.setAttribute("colsize", border_and_inset.columnsWidth());
racine.setAttribute("height", border_and_inset.columnsHeight());
// type de conducteur par defaut
QDomElement default_conductor = document.createElement("defaultconductor");
defaultConductorProperties.toXml(document, default_conductor);
racine.appendChild(default_conductor);
}
document.appendChild(racine);
// si le schema ne contient pas d'element (et donc pas de conducteurs), on retourne de suite le document XML
if (items().isEmpty()) return(document);
// creation de trois listes : une qui contient les elements, une qui contient les conducteurs, une qui contient les champs de texte
QList<Element *> list_elements;
QList<Conductor *> list_conductors;
QList<DiagramTextItem *> list_texts;
// Determine les elements a <20> XMLiser <20>
foreach(QGraphicsItem *qgi, items()) {
if (Element *elmt = qgraphicsitem_cast<Element *>(qgi)) {
if (diagram) list_elements << elmt;
else if (elmt -> isSelected()) list_elements << elmt;
} else if (Conductor *f = qgraphicsitem_cast<Conductor *>(qgi)) {
if (diagram) list_conductors << f;
// lorsqu'on n'exporte pas tout le diagram, il faut retirer les conducteurs non selectionnes
// et pour l'instant, les conducteurs non selectionnes sont les conducteurs dont un des elements n'est pas relie
else if (f -> terminal1 -> parentItem() -> isSelected() && f -> terminal2 -> parentItem() -> isSelected()) list_conductors << f;
} else if (DiagramTextItem *dti = qgraphicsitem_cast<DiagramTextItem *>(qgi)) {
if (!dti -> parentItem()) {
if (diagram) list_texts << dti;
else if (dti -> isSelected()) list_texts << dti;
}
}
}
// table de correspondance entre les adresses des bornes et leurs ids
QHash<Terminal *, int> table_adr_id;
// enregistrement des elements
if (!list_elements.isEmpty()) {
QDomElement elements = document.createElement("elements");
foreach(Element *elmt, list_elements) {
elements.appendChild(elmt -> toXml(document, table_adr_id));
}
racine.appendChild(elements);
}
// enregistrement des conducteurs
if (!list_conductors.isEmpty()) {
QDomElement conductors = document.createElement("conductors");
foreach(Conductor *cond, list_conductors) {
conductors.appendChild(cond -> toXml(document, table_adr_id));
}
racine.appendChild(conductors);
}
// enregistrement des champs de texte
if (!list_texts.isEmpty()) {
QDomElement inputs = document.createElement("inputs");
foreach(DiagramTextItem *dti, list_texts) {
inputs.appendChild(dti -> toXml(document));
}
racine.appendChild(inputs);
}
// on retourne le document XML ainsi genere
return(document);
}
/**
Importe le diagram decrit dans un document XML. Si une position est
precisee, les elements importes sont positionnes de maniere a ce que le
coin superieur gauche du plus petit rectangle pouvant les entourant tous
(le bounding rect) soit a cette position.
@param document Le document XML a analyser
@param position La position du diagram importe
@param consider_informations Si vrai, les informations complementaires
(auteur, titre, ...) seront prises en compte
@param content_ptr si ce pointeur vers un DiagramContentn'est pas NULL, il
sera rempli avec le contenu ajoute au schema par le fromXml
@return true si l'import a reussi, false sinon
*/
bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_informations, DiagramContent *content_ptr) {
QDomElement root = document.documentElement();
// le premier element doit etre un schema
if (root.tagName() != "diagram") return(false);
// lecture des attributs de ce schema
if (consider_informations) {
border_and_inset.setAuthor(root.attribute("author"));
border_and_inset.setTitle(root.attribute("title"));
border_and_inset.setDate(QDate::fromString(root.attribute("date"), "yyyyMMdd"));
border_and_inset.setFileName(root.attribute("filename"));
border_and_inset.setFolio(root.attribute("folio"));
bool ok;
// nombre de colonnes
int nb_cols = root.attribute("cols").toInt(&ok);
if (ok) border_and_inset.setNbColumns(nb_cols);
// taille des colonnes
double col_size = root.attribute("colsize").toDouble(&ok);
if (ok) border_and_inset.setColumnsWidth(col_size);
// hauteur du schema
double height = root.attribute("height").toDouble(&ok);
if (ok) border_and_inset.setColumnsHeight(height);
border_and_inset.adjustInsetToColumns();
// repere le permier element "defaultconductor"
for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
QDomElement elmts = node.toElement();
if(elmts.isNull() || elmts.tagName() != "defaultconductor") continue;
defaultConductorProperties.fromXml(elmts);
break;
}
}
// si la racine n'a pas d'enfant : le chargement est fini (schema vide)
if (root.firstChild().isNull()) return(true);
// chargement de tous les elements du fichier XML
QList<Element *> added_elements;
QHash<int, Terminal *> table_adr_id;
foreach (QDomElement e, QET::findInDomElement(root, "elements", "element")) {
if (!Element::valideXml(e)) continue;
// cree un element dont le type correspond a l'id type
QString type_id = e.attribute("type");
QString chemin_fichier = QETApp::realPath(type_id);
CustomElement *nvel_elmt = new CustomElement(chemin_fichier);
if (nvel_elmt -> isNull()) {
QString debug_message = QString("Le chargement de la description de l'element %1 a echoue avec le code d'erreur %2").arg(chemin_fichier).arg(nvel_elmt -> etat());
delete nvel_elmt;
qDebug(debug_message.toLatin1().data());
continue;
}
// charge les caracteristiques de l'element
if (nvel_elmt -> fromXml(e, table_adr_id)) {
// ajout de l'element au schema et a la liste des elements ajoutes
addItem(nvel_elmt);
added_elements << nvel_elmt;
} else {
delete nvel_elmt;
qDebug("Le chargement des parametres d'un element a echoue");
}
}
// chargement de tous les textes du fichiers XML
QList<DiagramTextItem *> added_texts;
foreach (QDomElement f, QET::findInDomElement(root, "inputs", "input")) {
DiagramTextItem *dti = new DiagramTextItem(0, this);
dti -> fromXml(f);
added_texts << dti;
}
// gere la translation des nouveaux elements et texte si celle-ci est demandee
if (position != QPointF()) {
// determine quel est le coin superieur gauche du rectangle entourant les elements ajoutes
qreal minimum_x = 0, minimum_y = 0;
bool init = false;
QList<QGraphicsItem *> added_items;
foreach (Element *added_element, added_elements) added_items << added_element;
foreach (DiagramTextItem *added_text, added_texts) added_items << added_text;
foreach (QGraphicsItem *item, added_items) {
QPointF csg = item -> mapToScene(item -> boundingRect()).boundingRect().topLeft();
qreal px = csg.x();
qreal py = csg.y();
if (!init) {
minimum_x = px;
minimum_y = py;
init = true;
} else {
if (px < minimum_x) minimum_x = px;
if (py < minimum_y) minimum_y = py;
}
}
qreal diff_x = position.x() - minimum_x;
qreal diff_y = position.y() - minimum_y;
foreach (Element *added_element, added_elements) {
added_element -> setPos(added_element -> pos().x() + diff_x, added_element -> pos().y() + diff_y);
}
foreach (DiagramTextItem *added_text, added_texts) {
added_text -> setPos(added_text -> pos().x() + diff_x, added_text -> pos().y() + diff_y);
}
}
// chargement de tous les Conducteurs du fichier XML
QList<Conductor *> added_conductors;
foreach (QDomElement f, QET::findInDomElement(root, "conductors", "conductor")) {
if (!Conductor::valideXml(f)) continue;
// verifie que les bornes que le conducteur relie sont connues
int id_p1 = f.attribute("terminal1").toInt();
int id_p2 = f.attribute("terminal2").toInt();
if (table_adr_id.contains(id_p1) && table_adr_id.contains(id_p2)) {
// pose le conducteur... si c'est possible
Terminal *p1 = table_adr_id.value(id_p1);
Terminal *p2 = table_adr_id.value(id_p2);
if (p1 != p2) {
bool can_add_conductor = true;
bool cia = ((Element *)p2 -> parentItem()) -> internalConnections();
if (!cia) {
foreach(QGraphicsItem *item, p2 -> parentItem() -> children()) {
if (item == p1) can_add_conductor = false;
}
}
if (can_add_conductor) {
Conductor *c = new Conductor(table_adr_id.value(id_p1), table_adr_id.value(id_p2), 0, this);
c -> fromXml(f);
added_conductors << c;
}
}
} else qDebug() << "Le chargement du conductor" << id_p1 << id_p2 << "a echoue";
}
// remplissage des listes facultatives
if (content_ptr != NULL) {
content_ptr -> elements = added_elements;
content_ptr -> conductorsToMove = added_conductors;
content_ptr -> textFields = added_texts;
}
return(true);
}
/**
Verifie si la selection est passe d'un etat ou elle est vide a un etat ou
elle ne l'est pas, et inversement. Si c'est le cas, le signal
EmptinessChanged() est emis.
*/
void Diagram::slot_checkSelectionEmptinessChange() {
static bool selection_was_empty = true;
bool selection_is_empty = selectedItems().isEmpty();
if (selection_was_empty != selection_is_empty) {
emit(selectionEmptinessChanged());
selection_was_empty = selection_is_empty;
}
}
/**
@return Le rectangle (coordonnees par rapport a la scene) delimitant le bord du schema
*/
QRectF Diagram::border() const {
return(
QRectF(
margin,
margin,
border_and_inset.borderWidth(),
border_and_inset.borderHeight()
)
);
}
/// oublie la liste des elements et conducteurs en mouvement
void Diagram::invalidateMovedElements() {
if (!moved_elements_fetched) return;
moved_elements_fetched = false;
elements_to_move.clear();
conductors_to_move.clear();
conductors_to_update.clear();
texts_to_move.clear();
}
/// reconstruit la liste des elements et conducteurs en mouvement
void Diagram::fetchMovedElements() {
// recupere les elements deplaces
foreach (QGraphicsItem *item, selectedItems()) {
if (Element *elmt = qgraphicsitem_cast<Element *>(item)) {
elements_to_move << elmt;
} else if (DiagramTextItem *t = qgraphicsitem_cast<DiagramTextItem *>(item)) {
if (!t -> parentItem()) texts_to_move << t;
}
}
// pour chaque element deplace, determine les conducteurs qui seront modifies
foreach(Element *elmt, elements_to_move) {
foreach(Terminal *terminal, elmt -> terminals()) {
foreach(Conductor *conductor, terminal -> conductors()) {
Terminal *other_terminal;
if (conductor -> terminal1 == terminal) {
other_terminal = conductor -> terminal2;
} else {
other_terminal = conductor -> terminal1;
}
// si les deux elements du conducteur sont deplaces
if (elements_to_move.contains(static_cast<Element *>(other_terminal -> parentItem()))) {
conductors_to_move << conductor;
} else {
conductors_to_update.insert(conductor, terminal);
}
}
}
}
moved_elements_fetched = true;
}
/**
Deplace les elements, conducteurs et textes selectionnes en gerant au
mieux les conducteurs (seuls les conducteurs dont un seul des elements
est deplace sont recalcules, les autres sont deplaces).
@param diff Translation a effectuer
@param dontmove QGraphicsItem (optionnel) a ne pas deplacer ; note : ce
parametre ne concerne que les elements et les champs de texte.
*/
void Diagram::moveElements(const QPointF &diff, QGraphicsItem *dontmove) {
// inutile de deplacer les autres elements s'il n'y a pas eu de mouvement concret
if (diff.isNull()) return;
current_movement += diff;
// deplace les elements selectionnes
foreach(Element *element, elementsToMove()) {
if (dontmove != NULL && element == dontmove) continue;
element -> setPos(element -> pos() + diff);
}
// deplace certains conducteurs
foreach(Conductor *conductor, conductorsToMove()) {
conductor -> setPos(conductor -> pos() + diff);
}
// recalcule les autres conducteurs
const QHash<Conductor *, Terminal *> &conductors_modify = conductorsToUpdate();
foreach(Conductor *conductor, conductors_modify.keys()) {
conductor -> updateWithNewPos(QRectF(), conductors_modify[conductor], conductors_modify[conductor] -> amarrageConductor());
}
// deplace les champs de texte
foreach(DiagramTextItem *dti, textsToMove()) {
if (dontmove != NULL && dti == dontmove) continue;
dti -> setPos(dti -> pos() + diff);
}
}
/**
Definit s'il faut afficher ou non les bornes
@param dt true pour afficher les bornes, false sinon
*/
void Diagram::setDrawTerminals(bool dt) {
foreach(QGraphicsItem *qgi, items()) {
if (Terminal *t = qgraphicsitem_cast<Terminal *>(qgi)) {
t -> setVisible(dt);
}
}
}
/**
@return la liste des conducteurs selectionnes sur le schema
*/
QSet<Conductor *> Diagram::selectedConductors() const {
QSet<Conductor *> conductors_set;
foreach(QGraphicsItem *qgi, selectedItems()) {
if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
conductors_set << c;
}
}
return(conductors_set);
}
/// @return true si le presse-papier semble contenir un schema
bool Diagram::clipboardMayContainDiagram() {
QString clipboard_text = QApplication::clipboard() -> text().trimmed();
bool may_be_diagram = clipboard_text.startsWith("<diagram") && clipboard_text.endsWith("</diagram>");
return(may_be_diagram);
}
/**
@return Le contenu du schema. Les conducteurs sont tous places dans
conductorsToMove.
*/
DiagramContent Diagram::content() const {
DiagramContent dc;
foreach(QGraphicsItem *qgi, items()) {
if (Element *e = qgraphicsitem_cast<Element *>(qgi)) {
dc.elements << e;
} else if (DiagramTextItem *dti = qgraphicsitem_cast<DiagramTextItem *>(qgi)) {
dc.textFields << dti;
} else if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
dc.conductorsToMove << c;
}
}
return(dc);
}
/**
@return le contenu selectionne du schema.
*/
DiagramContent Diagram::selectedContent() {
invalidateMovedElements();
DiagramContent dc;
dc.elements = elementsToMove().toList();
dc.textFields = textsToMove().toList();
dc.conductorsToMove = conductorsToMove().toList();
dc.conductorsToUpdate = conductorsToUpdate();
// recupere les conducteurs selectionnes isoles (= non deplacables mais supprimables)
foreach(QGraphicsItem *qgi, items()) {
if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
if (
c -> isSelected() &&\
!c -> terminal1 -> parentItem() -> isSelected() &&\
!c -> terminal2 -> parentItem() -> isSelected()
) {
dc.otherConductors << c;
}
}
}
invalidateMovedElements();
return(dc);
}

266
diagram.h Normal file
View File

@@ -0,0 +1,266 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCHEMA_H
#define SCHEMA_H
#include <QtGui>
#include <QtXml>
#include "qetdiagrameditor.h"
#include "borderinset.h"
#include "qgimanager.h"
#include "conductorproperties.h"
class Element;
class Terminal;
class Conductor;
class DiagramTextItem;
class DiagramContent;
/**
Cette classe represente un schema electrique.
Elle gere les differents elements et conducteurs qui le composent
et en effectue le rendu graphique.
*/
class Diagram : public QGraphicsScene {
Q_OBJECT
// constructeurs, destructeur
public:
Diagram(QObject * = 0);
virtual ~Diagram();
private:
Diagram(const Diagram &diagram);
// attributs
public:
/**
Represente les options possibles pour l'affichage du schema :
* EmptyBorder : N'afficher que la bordure
* Inset : Afficher le cartouche
* Columns : Afficher les colonnes
*/
enum BorderOptions { EmptyBorder, Inset, Columns };
/// Proprietes par defaut des nouveaux conducteurs
ConductorProperties defaultConductorProperties;
/// Dimensions et cartouches du schema
BorderInset border_and_inset;
/// Mouvement en cours lors d'un deplacement d'elements et conducteurs
QPointF current_movement;
/// taille de la grille en abscisse
static const int xGrid;
/// taille de la grille en ordonnee
static const int yGrid;
/// marge autour du schema
static const qreal margin;
private:
QGraphicsLineItem *conductor_setter;
bool draw_grid;
bool use_border;
bool moved_elements_fetched;
QSet<Element *> elements_to_move;
QSet<Conductor *> conductors_to_move;
QHash<Conductor *, Terminal *> conductors_to_update;
QSet<DiagramTextItem *> texts_to_move;
QGIManager qgi_manager;
QUndoStack undo_stack;
bool draw_terminals;
// methodes
protected:
virtual void drawBackground(QPainter *, const QRectF &);
virtual void keyPressEvent(QKeyEvent *);
virtual void keyReleaseEvent(QKeyEvent *);
public:
static bool clipboardMayContainDiagram();
// fonctions relatives a la pose de conducteurs
void setConductor(bool);
void setConductorStart (QPointF);
void setConductorStop(QPointF);
// fonctions relatives a l'import / export XML
QDomDocument toXml(bool = true);
bool fromXml(QDomDocument &, QPointF = QPointF(), bool = true, DiagramContent * = NULL);
// fonctions relatives aux options graphiques
void setDisplayGrid(bool);
bool displayGrid();
void setUseBorder(bool);
bool useBorder();
void setBorderOptions(BorderOptions);
BorderOptions borderOptions();
bool drawTerminals() const;
void setDrawTerminals(bool);
QRectF border() const;
bool toPaintDevice(QPaintDevice &, int = -1, int = -1, Qt::AspectRatioMode = Qt::KeepAspectRatio);
QSize imageSize() const;
void invalidateMovedElements();
void fetchMovedElements();
const QSet<Element *> &elementsToMove();
const QSet<Conductor *> &conductorsToMove();
const QHash<Conductor *, Terminal *> &conductorsToUpdate();
const QSet<DiagramTextItem *> &textsToMove();
QSet<Conductor *> selectedConductors() const;
DiagramContent content() const;
DiagramContent selectedContent();
void moveElements(const QPointF &, QGraphicsItem * = NULL);
QUndoStack &undoStack();
QGIManager &qgiManager();
private slots:
void slot_checkSelectionEmptinessChange();
signals:
/**
Ce signal est emis lorsque la selection passe de l'etat rempli (par un
nombre quelconque d'elements et conducteurs) a l'etat vide et
vice-versa.
*/
void selectionEmptinessChanged();
};
/**
Permet d'ajouter ou enlever le <20> poseur de conducteur <20>, c'est-a-dire la
droite en pointilles qui apparait lorsqu'on pose un conducteur entre deux
bornes.
@param pf true pour ajouter le poseur de conducteur, false pour l'enlever
*/
inline void Diagram::setConductor(bool pf) {
if (pf) {
if (!conductor_setter -> scene()) addItem(conductor_setter);
} else {
if (conductor_setter -> scene()) removeItem(conductor_setter);
}
}
/**
Specifie les coordonnees du point de depart du poseur de conducteur
@param d Le nouveau point de depart du poseur de conducteur
*/
inline void Diagram::setConductorStart(QPointF d) {
conductor_setter -> setLine(QLineF(d, conductor_setter -> line().p2()));
}
/**
Specifie les coordonnees du point d'arrivee du poseur de conducteur
@param a Le nouveau point d'arrivee du poseur de conducteur
*/
inline void Diagram::setConductorStop(QPointF a) {
conductor_setter -> setLine(QLineF(conductor_setter -> line().p1(), a));
}
/**
Permet de specifier si la grille du schema doit etre dessinee ou non
@param dg true pour afficher la grille, false pour ne pas l'afficher
*/
inline void Diagram::setDisplayGrid(bool dg) {
draw_grid = dg;
}
/**
Permet de savoir si la grille du schema est dessinee ou non
@return true si la grille est affichee , false sinon
*/
inline bool Diagram::displayGrid() {
return(draw_grid);
}
/**
Permet de specifier si le cadre du schema doit etre pris en compte pour
determiner le contour du schema.
@param ub true pour prendre le schema en compte, false sinon
*/
inline void Diagram::setUseBorder(bool ub) {
use_border = ub;
}
/**
Permet de savoir si le cadre du schema est pris en compte pour
determiner le contour du schema.
*/
inline bool Diagram::useBorder() {
return(use_border);
}
/**
Permet de definir les options du cadre, des colonnes et du cartouche.
@param bo Un OU binaire entre les options possibles
@see BorderOptions
*/
inline void Diagram::setBorderOptions(Diagram::BorderOptions bo) {
border_and_inset.displayBorder(!(bo & EmptyBorder));
border_and_inset.displayColumns(bo & Columns);
border_and_inset.displayInset(bo & Inset);
}
/**
Permet de savoir les options du cadre, des colonnes et du cartouche.
@return Un OU binaire entre les options possibles
@see BorderOptions
*/
inline Diagram::BorderOptions Diagram::borderOptions() {
BorderOptions retour = EmptyBorder;
if (border_and_inset.insetIsDisplayed()) retour = (BorderOptions)(retour|Inset);
if (border_and_inset.columnsAreDisplayed()) retour = (BorderOptions)(retour|Columns);
return(retour);
}
/// @return la liste des elements a deplacer
inline const QSet<Element *> &Diagram::elementsToMove() {
if (!moved_elements_fetched) fetchMovedElements();
return(elements_to_move);
}
/// @return la liste des conducteurs a deplacer
inline const QSet<Conductor *> &Diagram::conductorsToMove() {
if (!moved_elements_fetched) fetchMovedElements();
return(conductors_to_move);
}
/// @return la liste des conducteurs a modifier (typiquement les conducteurs dont seul un element est deplace)
inline const QHash<Conductor *, Terminal *> &Diagram::conductorsToUpdate() {
if (!moved_elements_fetched) fetchMovedElements();
return(conductors_to_update);
}
/// @return la liste des textes a deplacer
inline const QSet<DiagramTextItem *> &Diagram::textsToMove() {
if (!moved_elements_fetched) fetchMovedElements();
return(texts_to_move);
}
/// @return la pile d'annulations de ce schema
inline QUndoStack &Diagram::undoStack() {
return(undo_stack);
}
/// @return le egstionnaire de QGraphicsItem de ce schema
inline QGIManager &Diagram::qgiManager() {
return(qgi_manager);
}
/// @return true si les bornes sont affichees, false sinon
inline bool Diagram::drawTerminals() const {
return(draw_terminals);
}
#endif

625
diagramcommands.cpp Normal file
View File

@@ -0,0 +1,625 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "diagramcommands.h"
#include "element.h"
#include "conductor.h"
#include "diagram.h"
#include "qgimanager.h"
/**
Constructeur
@param d Schema auquel on ajoute un element
@param elmt Element ajoute
@param p Position a laquelle l'element est ajoute
@param parent QUndoCommand parent
*/
AddElementCommand::AddElementCommand(
Diagram *d,
Element *elmt,
const QPointF &p,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("ajouter 1 ") + elmt -> nom(), parent),
element(elmt),
diagram(d),
position(p)
{
diagram -> qgiManager().manage(element);
}
/// Destructeur
AddElementCommand::~AddElementCommand() {
diagram -> qgiManager().release(element);
}
/// Annule l'ajout
void AddElementCommand::undo() {
diagram -> removeItem(element);
}
/// Refait l'ajout
void AddElementCommand::redo() {
diagram -> addItem(element);
element -> setPos(position);
element -> setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
}
/**
Constructeur
@param dia Schema auquel on ajoute du texte
@param text Texte ajoute
@param pos Position a laquelle le texte est ajoute
@param parent QUndoCommand parent
*/
AddTextCommand::AddTextCommand(Diagram *dia, DiagramTextItem *text, const QPointF &pos, QUndoCommand *parent) :
QUndoCommand(QObject::tr("Ajouter un champ de texte"), parent),
textitem(text),
diagram(dia),
position(pos)
{
diagram -> qgiManager().manage(textitem);
}
/// Destructeur
AddTextCommand::~AddTextCommand() {
diagram -> qgiManager().release(textitem);
}
/// Annule l'ajout
void AddTextCommand::undo() {
diagram -> removeItem(textitem);
}
/// Refait l'ajour
void AddTextCommand::redo() {
diagram -> addItem(textitem);
textitem -> setPos(position);
}
/**
Constructeur
@param d Schema auquel on ajoute un conducteur
@param c Conducteur ajoute
@param parent QUndoCommand parent
*/
AddConductorCommand::AddConductorCommand(
Diagram *d,
Conductor *c,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("ajouter un conducteur"), parent),
conductor(c),
diagram(d)
{
diagram -> qgiManager().manage(conductor);
}
/// Destructeur
AddConductorCommand::~AddConductorCommand() {
diagram -> qgiManager().release(conductor);
}
/// Annule l'ajout
void AddConductorCommand::undo() {
// detache le conducteur sans le detruire
conductor -> terminal1 -> removeConductor(conductor);
conductor -> terminal2 -> removeConductor(conductor);
diagram -> removeItem(conductor);
}
/// Refait l'ajout
void AddConductorCommand::redo() {
diagram -> addItem(conductor);
}
/**
Constructeur
@param dia Schema dont on supprime des elements et conducteurs
@param content Contenu supprime
@param parent QUndoCommand parent
*/
DeleteElementsCommand::DeleteElementsCommand(
Diagram *dia,
const DiagramContent &content,
QUndoCommand *parent
) :
QUndoCommand(parent),
removed_content(content),
diagram(dia)
{
setText(QObject::tr("supprimer ") + removed_content.sentence(DiagramContent::All));
diagram -> qgiManager().manage(removed_content.items(DiagramContent::All));
}
/// Destructeur
DeleteElementsCommand::~DeleteElementsCommand() {
diagram -> qgiManager().release(removed_content.items(DiagramContent::All));
}
/// annule les suppressions
void DeleteElementsCommand::undo() {
// remet les elements
foreach(Element *e, removed_content.elements) {
diagram -> addItem(e);
}
// remet les conducteurs
foreach(Conductor *c, removed_content.conductors(DiagramContent::AnyConductor)) {
diagram -> addItem(c);
c -> terminal1 -> addConductor(c);
c -> terminal2 -> addConductor(c);
}
// remet les textes
foreach(DiagramTextItem *t, removed_content.textFields) {
diagram -> addItem(t);
}
}
/// refait les suppressions
void DeleteElementsCommand::redo() {
// enleve les conducteurs
foreach(Conductor *c, removed_content.conductors(DiagramContent::AnyConductor)) {
c -> terminal1 -> removeConductor(c);
c -> terminal2 -> removeConductor(c);
diagram -> removeItem(c);
}
// enleve les elements
foreach(Element *e, removed_content.elements) {
diagram -> removeItem(e);
}
// enleve les textes
foreach(DiagramTextItem *t, removed_content.textFields) {
diagram -> removeItem(t);
}
}
/**
Constructeur
@param dia Schema sur lequel on colle les elements et conducteurs
@param c Contenu a coller sur le schema
@param parent QUndoCommand parent
*/
PasteDiagramCommand::PasteDiagramCommand(
Diagram *dia,
const DiagramContent &c,
QUndoCommand *parent
) :
QUndoCommand(parent),
content(c),
diagram(dia),
filter(DiagramContent::Elements|DiagramContent::TextFields|DiagramContent::ConductorsToMove),
first_redo(true)
{
setText(QObject::tr("coller ") + content.sentence(filter));
diagram -> qgiManager().manage(content.items(filter));
}
/// Destructeur
PasteDiagramCommand::~PasteDiagramCommand() {
diagram -> qgiManager().release(content.items(filter));
}
/// annule le coller
void PasteDiagramCommand::undo() {
// enleve les conducteurs
foreach(Conductor *c, content.conductorsToMove) {
c -> terminal1 -> removeConductor(c);
c -> terminal2 -> removeConductor(c);
diagram -> removeItem(c);
}
// enleve les elements
foreach(Element *e, content.elements) diagram -> removeItem(e);
// enleve les textes
foreach(DiagramTextItem *t, content.textFields) diagram -> removeItem(t);
}
/// refait le coller
void PasteDiagramCommand::redo() {
if (first_redo) first_redo = false;
else {
// pose les elements
foreach(Element *e, content.elements) diagram -> addItem(e);
// pose les conducteurs
foreach(Conductor *c, content.conductorsToMove) {
diagram -> addItem(c);
c -> terminal1 -> addConductor(c);
c -> terminal2 -> addConductor(c);
}
// pose les textes
foreach(DiagramTextItem *t, content.textFields) diagram -> addItem(t);
}
foreach(Element *e, content.elements) e -> setSelected(true);
foreach(Conductor *c, content.conductorsToMove) c -> setSelected(true);
foreach(DiagramTextItem *t, content.textFields) t -> setSelected(true);
}
/**
Constructeur
@param dia Schema dont on coupe des elements et conducteurs
@param content Contenu coupe
@param parent QUndoCommand parent
*/
CutDiagramCommand::CutDiagramCommand(
Diagram *dia,
const DiagramContent &content,
QUndoCommand *parent
) :
DeleteElementsCommand(dia, content, parent)
{
setText(QObject::tr("couper ") + content.sentence(DiagramContent::All));
}
/// Destructeur
CutDiagramCommand::~CutDiagramCommand() {
}
/**
Constructeur
@param dia Schema sur lequel on deplace des elements
@param diagram_content Contenu a deplacer
@param m translation subie par les elements
@param parent QUndoCommand parent
*/
MoveElementsCommand::MoveElementsCommand(
Diagram *dia,
const DiagramContent &diagram_content,
const QPointF &m,
QUndoCommand *parent
) :
QUndoCommand(parent),
diagram(dia),
content_to_move(diagram_content),
movement(m),
first_redo(true)
{
setText(QObject::tr("d\351placer ") + content_to_move.sentence(DiagramContent::Elements|DiagramContent::TextFields|DiagramContent::ConductorsToUpdate|DiagramContent::ConductorsToMove));
}
/// Destructeur
MoveElementsCommand::~MoveElementsCommand() {
}
/// annule le deplacement
void MoveElementsCommand::undo() {
move(-movement);
}
/// refait le deplacement
void MoveElementsCommand::redo() {
if (first_redo) first_redo = false;
else move(movement);
}
/**
deplace les elements et conducteurs
@param actual_movement translation a effectuer sur les elements et conducteurs
*/
void MoveElementsCommand::move(const QPointF &actual_movement) {
// deplace les elements
foreach(Element *element, content_to_move.elements) {
element -> setPos(element -> pos() + actual_movement);
}
// deplace certains conducteurs
foreach(Conductor *conductor, content_to_move.conductorsToMove) {
conductor -> setPos(conductor -> pos() + actual_movement);
}
// recalcule les autres conducteurs
foreach(Conductor *conductor, content_to_move.conductorsToUpdate.keys()) {
conductor -> updateWithNewPos(
QRectF(),
content_to_move.conductorsToUpdate[conductor],
content_to_move.conductorsToUpdate[conductor] -> amarrageConductor()
);
}
// deplace les textes
foreach(DiagramTextItem *text, content_to_move.textFields) {
text -> setPos(text -> pos() + actual_movement);
}
}
/**
Constructeur
@param dti Champ de texte modifie
@param before texte avant
@param after texte apres
@param parent QUndoCommand parent
*/
ChangeDiagramTextCommand::ChangeDiagramTextCommand(
DiagramTextItem *dti,
const QString &before,
const QString &after,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("modifier le texte"), parent),
text_item(dti),
text_before(before),
text_after(after),
first_redo(true)
{
}
/// destructeur
ChangeDiagramTextCommand::~ChangeDiagramTextCommand() {
}
/// annule la modification de texte
void ChangeDiagramTextCommand::undo() {
text_item -> setPlainText(text_before);
text_item -> previous_text = text_before;
}
/// refait la modification de texte
void ChangeDiagramTextCommand::redo() {
if (first_redo) first_redo = false;
else {
text_item -> setPlainText(text_after);
text_item -> previous_text = text_after;
}
}
/**
Constructeur
@param elements Elements a pivoter associes a leur orientation d'origine
@param parent QUndoCommand parent
*/
RotateElementsCommand::RotateElementsCommand(const QHash<Element *, QET::Orientation> &elements, QUndoCommand *parent) :
QUndoCommand(QObject::tr("pivoter ") + QET::ElementsAndConductorsSentence(elements.count(), 0), parent),
elements_to_rotate(elements)
{
}
/// Destructeur
RotateElementsCommand::~RotateElementsCommand() {
}
/// defait le pivotement
void RotateElementsCommand::undo() {
foreach(Element *e, elements_to_rotate.keys()) {
e -> setOrientation(elements_to_rotate[e]);
}
}
/// refait le pivotement
void RotateElementsCommand::redo() {
foreach(Element *e, elements_to_rotate.keys()) {
e -> setOrientation(e -> orientation().next());
e -> update();
}
}
/**
Constructeur
@param c Conducteur modifie
@param old_p ancien profil du conducteur
@param new_p nouveau profil du conducteur
@param path_t Trajectoire du trajet modifie
@param parent QUndoCommand parent
*/
ChangeConductorCommand::ChangeConductorCommand(
Conductor *c,
const ConductorProfile &old_p,
const ConductorProfile &new_p,
Qt::Corner path_t,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("modifier un conducteur"), parent),
conductor(c),
old_profile(old_p),
new_profile(new_p),
path_type(path_t),
first_redo(true)
{
}
/// Destructeur
ChangeConductorCommand::~ChangeConductorCommand() {
}
/// Annule la modification du conducteur
void ChangeConductorCommand::undo() {
conductor -> setProfile(old_profile, path_type);
}
/// Refait la modification du conducteur
void ChangeConductorCommand::redo() {
if (first_redo) first_redo = false;
else conductor -> setProfile(new_profile, path_type);
}
/**
Constructeur
@param cp Conducteurs reinitialises, associes a leur ancien profil
@param parent QUndoCommand parent
*/
ResetConductorCommand::ResetConductorCommand(
const QHash<Conductor *, ConductorProfilesGroup> &cp,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("R\351initialiser ") + QET::ElementsAndConductorsSentence(0, cp.count()), parent),
conductors_profiles(cp)
{
}
/// Destructeur
ResetConductorCommand::~ResetConductorCommand() {
}
/// Annule la reinitialisation des conducteurs
void ResetConductorCommand::undo() {
foreach(Conductor *c, conductors_profiles.keys()) {
c -> setProfiles(conductors_profiles[c]);
}
}
/// Refait la reinitialisation des conducteurs
void ResetConductorCommand::redo() {
foreach(Conductor *c, conductors_profiles.keys()) {
c -> setProfiles(ConductorProfilesGroup());
}
}
/**
Constructeur
@param d Schema dont on modifie le cartouche
@param old_ip Anciennes proprietes du cartouche
@param new_ip Nouvelles proprietes du cartouche
@param parent QUndoCommand parent
*/
ChangeInsetCommand::ChangeInsetCommand(
Diagram *d,
const InsetProperties &old_ip,
const InsetProperties &new_ip,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("modifier le cartouche"), parent),
diagram(d),
old_inset(old_ip),
new_inset(new_ip)
{
}
/// Destructeur
ChangeInsetCommand::~ChangeInsetCommand() {
}
/// Annule la modification de cartouche
void ChangeInsetCommand::undo() {
diagram -> border_and_inset.importInset(old_inset);
diagram -> invalidate(diagram -> border());
}
/// Refait la modification de cartouche
void ChangeInsetCommand::redo() {
diagram -> border_and_inset.importInset(new_inset);
diagram -> invalidate(diagram -> border());
}
/**
Constructeur
@param dia Schema modifie
@param parent QUndoCommand parent
*/
ChangeBorderCommand::ChangeBorderCommand(Diagram *dia, QUndoCommand *parent) :
QUndoCommand(QObject::tr("modifier les dimensions du sch\351ma"), parent),
diagram(dia),
columnsCountDifference(0),
columnsHeightDifference(0.0),
columnsWidthDifference(0.0),
headersHeightDifference(0.0)
{
}
/// Destructeur
ChangeBorderCommand::~ChangeBorderCommand() {
}
/**
Applique les changements au schema
@param coeff comme les changements s'expriment sous forme de nombres dont
il suffit d'inverser le signe pour les annuler, ces valeurs sont ici
multipliees par le coefficient passe en parametre avant d'etre appliquees.
Pour resumer : 1 pour refaire, -1 pour annuler.
*/
void ChangeBorderCommand::applyChanges(int coeff) {
// reference vers l'objet border_and_inset du schema
BorderInset &border = diagram -> border_and_inset;
if (columnsCountDifference) {
border.setNbColumns(border.nbColumn() + (columnsCountDifference * coeff));
}
if (columnsHeightDifference) {
border.setColumnsHeight(border.columnsHeight() + (columnsHeightDifference * coeff));
}
if (columnsWidthDifference) {
border.setColumnsWidth(border.columnsWidth() + (columnsWidthDifference * coeff));
}
if (headersHeightDifference) {
border.setColumnsHeaderHeight(border.columnsHeaderHeight() + (headersHeightDifference * coeff));
}
border.adjustInsetToColumns();
}
/// Annule les changements apportes au schema
void ChangeBorderCommand::undo() {
applyChanges(-1);
}
/// Refait les changements apportes au schema
void ChangeBorderCommand::redo() {
applyChanges(1);
}
/**
Constructeur
@param c Le conducteur dont on modifie les proprietes
@param parent QUndoCommand parent
*/
ChangeConductorPropertiesCommand::ChangeConductorPropertiesCommand(Conductor *c, QUndoCommand *parent) :
QUndoCommand(QObject::tr("modifier les propri\351t\351s d'un conducteur"), parent),
conductor(c),
old_settings_set(false),
new_settings_set(false)
{
}
/// Destructeur
ChangeConductorPropertiesCommand::~ChangeConductorPropertiesCommand() {
}
/// definit l'ancienne configuration
void ChangeConductorPropertiesCommand::setOldSettings(const ConductorProperties &properties) {
old_properties = properties;
old_settings_set = true;
}
/// definit la nouvelle configuration
void ChangeConductorPropertiesCommand::setNewSettings(const ConductorProperties &properties) {
new_properties = properties;
new_settings_set = true;
}
/**
Annule les changements - Attention : les anciens et nouveaux parametres
doivent avoir ete definis a l'aide de setNewSettings et setOldSettings
*/
void ChangeConductorPropertiesCommand::undo() {
if (old_settings_set && new_settings_set) {
conductor -> setProperties(old_properties);
conductor -> update();
}
}
/**
Refait les changements - Attention : les anciens et nouveaux parametres
doivent avoir ete definis a l'aide de setNewSettings et setOldSettings
*/
void ChangeConductorPropertiesCommand::redo() {
if (old_settings_set && new_settings_set) {
conductor -> setProperties(new_properties);
conductor -> update();
}
}

394
diagramcommands.h Normal file
View File

@@ -0,0 +1,394 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DIAGRAM_COMMANDS_H
#define DIAGRAM_COMMANDS_H
#include "qet.h"
#include "diagram.h"
#include "diagramcontent.h"
#include "diagramtextitem.h"
#include "conductor.h"
#include "conductorproperties.h"
#include <QtGui>
/**
Cette classe represente l'action d'ajouter un element au schema
*/
class AddElementCommand : public QUndoCommand {
// constructeurs, destructeur
public:
AddElementCommand(Diagram *, Element *, const QPointF &, QUndoCommand * = 0);
virtual ~AddElementCommand();
private:
AddElementCommand(const AddElementCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// element ajoute
Element *element;
/// schema sur lequel on ajoute l'element
Diagram *diagram;
/// position de l'element sur le schema
QPointF position;
};
/**
Cette classe represente l'action d'ajouter du texte au schema
*/
class AddTextCommand : public QUndoCommand {
// constructeurs, destructeur
public:
AddTextCommand(Diagram *, DiagramTextItem *, const QPointF &, QUndoCommand * = 0);
virtual ~AddTextCommand();
private:
AddTextCommand(const AddTextCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// texte ajoute
DiagramTextItem *textitem;
/// schema sur lequel on ajoute le texte
Diagram *diagram;
/// position du texte sur le schema
QPointF position;
};
/**
Cette classe represente l'action d'ajouter un conducteur au schema
*/
class AddConductorCommand : public QUndoCommand {
// constructeurs, destructeur
public:
AddConductorCommand(Diagram *, Conductor *, QUndoCommand * = 0);
virtual ~AddConductorCommand();
private:
AddConductorCommand(const AddConductorCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// conducteur ajoute
Conductor *conductor;
/// schema auquel on ajoute le conducteur
Diagram *diagram;
};
/**
Cette classe represente l'action de supprimer des elements et / ou
conducteurs d'un schema
*/
class DeleteElementsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
DeleteElementsCommand(Diagram *, const DiagramContent &, QUndoCommand * = 0);
virtual ~DeleteElementsCommand();
private:
DeleteElementsCommand(const DeleteElementsCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// contenu enleve
DiagramContent removed_content;
/// schema dont on supprime des elements et conducteurs
Diagram *diagram;
};
/**
Cette classe represente l'action de coller quelque chose sur un schema
*/
class PasteDiagramCommand : public QUndoCommand {
// constructeurs, destructeur
public:
PasteDiagramCommand(Diagram *, const DiagramContent &, QUndoCommand * = 0);
virtual ~PasteDiagramCommand();
private:
PasteDiagramCommand(const PasteDiagramCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// contenu ajoute
DiagramContent content;
/// schema sur lequel on colle les elements et conducteurs
Diagram *diagram;
/// entien pour filtrer le contenu du schema
int filter;
/// booleen pour empecher le premier appel a redo
bool first_redo;
};
/**
Cette classe represente l'action de supprimer des elements et / ou
conducteurs d'un schema
*/
class CutDiagramCommand : public DeleteElementsCommand {
// constructeurs, destructeur
public:
CutDiagramCommand(Diagram *, const DiagramContent &, QUndoCommand * = 0);
virtual ~CutDiagramCommand();
private:
CutDiagramCommand(const CutDiagramCommand &);
};
/**
Cette classe represente l'action de deplacer des elements et des
conducteurs sur un schema
*/
class MoveElementsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
MoveElementsCommand(Diagram *, const DiagramContent &, const QPointF &m, QUndoCommand * = 0);
virtual ~MoveElementsCommand();
private:
MoveElementsCommand(const MoveElementsCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
virtual void move(const QPointF &);
// attributs
private:
/// schema sur lequel on deplace les elements
Diagram *diagram;
/// contenu a deplacer
DiagramContent content_to_move;
/// mouvement effectue
QPointF movement;
/// booleen pour ne pas executer le premier redo()
bool first_redo;
};
/**
Cette classe represente la modification d'un champ de texte
*/
class ChangeDiagramTextCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangeDiagramTextCommand(DiagramTextItem *, const QString &before, const QString &after, QUndoCommand * = 0);
virtual ~ChangeDiagramTextCommand();
private:
ChangeDiagramTextCommand(const ChangeDiagramTextCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// DiagramTextItem modifie
DiagramTextItem *text_item;
/// texte avant changement
QString text_before;
/// texte apres changement
QString text_after;
/// booleen pour ne pas executer le premier redo()
bool first_redo;
};
/**
Cette classe represente l'action de pivoter plusieurs elements
*/
class RotateElementsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
RotateElementsCommand(const QHash<Element *, QET::Orientation> &elements, QUndoCommand * = 0);
virtual ~RotateElementsCommand();
private:
RotateElementsCommand(const RotateElementsCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// elements pivotes associes a leur ancienne orientation
QHash<Element *, QET::Orientation> elements_to_rotate;
};
/**
Cette classe represente l'action de modifier un conducteur
*/
class ChangeConductorCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangeConductorCommand(Conductor *, const ConductorProfile &, const ConductorProfile &, Qt::Corner, QUndoCommand * = 0);
virtual ~ChangeConductorCommand();
private:
ChangeConductorCommand(const ChangeConductorCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// conducteur modifie
Conductor *conductor;
/// profil avant changement
ConductorProfile old_profile;
/// profil apres changement
ConductorProfile new_profile;
/// Type de trajet
Qt::Corner path_type;
/// booleen pour ne pas executer le premier redo()
bool first_redo;
};
/**
Cette classe represente l'action de reinitialiser des conducteurs
*/
class ResetConductorCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ResetConductorCommand(const QHash<Conductor *, ConductorProfilesGroup> &, QUndoCommand * = 0);
virtual ~ResetConductorCommand();
private:
ResetConductorCommand(const ResetConductorCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// conducteurs reinitialises associes a leur ancien profil
QHash<Conductor *, ConductorProfilesGroup> conductors_profiles;
};
/**
Cette classe represente l'action de modifier les informations du cartouche d'un schema
*/
class ChangeInsetCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangeInsetCommand(Diagram *, const InsetProperties &, const InsetProperties &, QUndoCommand * = 0);
virtual ~ChangeInsetCommand();
private:
ChangeInsetCommand(const ChangeInsetCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// schema modifie
Diagram *diagram;
/// proprietes avant changement
InsetProperties old_inset;
/// proprietes apres changement
InsetProperties new_inset;
};
/**
Cette classe represente l'action de modifier :
-le nombre de colonnes d'un schema
-la hauteur des colonnes
-la largeur des colonnes
-la hauteur des en-tetes des colonnes
*/
class ChangeBorderCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangeBorderCommand(Diagram *, QUndoCommand * = 0);
virtual ~ChangeBorderCommand();
private:
ChangeBorderCommand(const ChangeBorderCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
private:
virtual void applyChanges(int = 1);
// attributs
private:
/// schema modifie
Diagram *diagram;
public:
/// nombre de colonnes ajoutees / enlevees
int columnsCountDifference;
/// delta pour la hauteur des colonnes
qreal columnsHeightDifference;
/// delta pour la largeur des colonnes
qreal columnsWidthDifference;
/// delta pour la hauteur des entetes des colonnes
qreal headersHeightDifference;
};
/**
Cette classe represente l'action de modifier les proprietes d'un conducteur
*/
class ChangeConductorPropertiesCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangeConductorPropertiesCommand(Conductor *, QUndoCommand * = 0);
virtual ~ChangeConductorPropertiesCommand();
private:
ChangeConductorPropertiesCommand(const ChangeConductorPropertiesCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
virtual void setOldSettings(const ConductorProperties &);
virtual void setNewSettings(const ConductorProperties &);
// attributs
private:
/// conducteur modifie
Conductor *conductor;
/// anciennes proprietes
ConductorProperties old_properties;
/// nouvelles proprietes
ConductorProperties new_properties;
/// booleens indiquant si les proprietes ont ete definies ou non
bool old_settings_set;
bool new_settings_set;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -18,9 +18,8 @@
#include "diagramcontent.h"
#include <QGraphicsItem>
#include "element.h"
#include "independenttextitem.h"
#include "diagramtextitem.h"
#include "conductor.h"
#include "diagramimageitem.h"
/**
Constructeur par defaut. Ne contient rien.
@@ -34,7 +33,6 @@ DiagramContent::DiagramContent() {
DiagramContent::DiagramContent(const DiagramContent &other) :
elements(other.elements),
textFields(other.textFields),
images(other.images),
conductorsToUpdate(other.conductorsToUpdate),
conductorsToMove(other.conductorsToMove),
otherConductors(other.otherConductors)
@@ -52,16 +50,11 @@ DiagramContent::~DiagramContent() {
@return tous les conducteurs
*/
QList<Conductor *> DiagramContent::conductors(int filter) const {
QSet<Conductor *> result;
QList<Conductor *> result;
if (filter & ConductorsToMove) result += conductorsToMove;
if (filter & ConductorsToUpdate) result += conductorsToUpdate;
if (filter & ConductorsToUpdate) result += conductorsToUpdate.keys();
if (filter & OtherConductors) result += otherConductors;
if (filter & SelectedOnly) {
foreach(Conductor *conductor, result) {
if (!conductor -> isSelected()) result.remove(conductor);
}
}
return(result.toList());
return(result);
}
/**
@@ -70,7 +63,6 @@ QList<Conductor *> DiagramContent::conductors(int filter) const {
void DiagramContent::clear() {
elements.clear();
textFields.clear();
images.clear();
conductorsToUpdate.clear();
conductorsToMove.clear();
otherConductors.clear();
@@ -85,12 +77,6 @@ QList<QGraphicsItem *> DiagramContent::items(int filter) const {
foreach(QGraphicsItem *qgi, conductors(filter)) items_list << qgi;
if (filter & Elements) foreach(QGraphicsItem *qgi, elements) items_list << qgi;
if (filter & TextFields) foreach(QGraphicsItem *qgi, textFields) items_list << qgi;
if (filter & Images) foreach(QGraphicsItem *qgi, images) items_list << qgi;
if (filter & SelectedOnly) {
foreach(QGraphicsItem *qgi, items_list) {
if (!qgi -> isSelected()) items_list.removeOne(qgi);
}
}
return(items_list);
}
@@ -100,28 +86,11 @@ QList<QGraphicsItem *> DiagramContent::items(int filter) const {
*/
int DiagramContent::count(int filter) const {
int count = 0;
if (filter == SelectedOnly) {
if (filter == Elements) foreach(Element *element, elements) { if (element -> isSelected()) ++ count; }
if (filter == TextFields) foreach(DiagramTextItem *dti, textFields) { if (dti -> isSelected()) ++ count; }
if (filter == Images) foreach(DiagramImageItem *dii, images) { if (dii -> isSelected()) ++ count; }
if (filter == ConductorsToMove) foreach(Conductor *conductor, conductorsToMove) { if (conductor -> isSelected()) ++ count; }
if (filter == ConductorsToUpdate) foreach(Conductor *conductor, conductorsToUpdate) { if (conductor -> isSelected()) ++ count; }
if (filter == OtherConductors) foreach(Conductor *conductor, otherConductors) { if (conductor -> isSelected()) ++ count; }
} else if (filter == All) {
count += elements.count();
count += textFields.count();
count += images.count();
count += conductorsToMove.count();
count += conductorsToUpdate.count();
count += otherConductors.count();
} else {
if (filter == Elements) count += elements.count();
if (filter == TextFields) count += textFields.count();
if (filter == Images) count += images.count();
if (filter == ConductorsToMove) count += conductorsToMove.count();
if (filter == ConductorsToUpdate) count += conductorsToUpdate.count();
if (filter == OtherConductors) count += otherConductors.count();
}
if (filter & Elements) count += elements.count();
if (filter & TextFields) count += textFields.count();
if (filter & ConductorsToMove) count += conductorsToMove.count();
if (filter & ConductorsToUpdate) count += conductorsToUpdate.count();
if (filter & OtherConductors) count += otherConductors.count();
return(count);
}
@@ -135,14 +104,12 @@ QString DiagramContent::sentence(int filter) const {
int elements_count = (filter & Elements) ? elements.count() : 0;
int conductors_count = conductors(filter).count();
int textfields_count = (filter & TextFields) ? textFields.count() : 0;
int images_count = (filter & Images) ? images.count() : 0;
return(
QET::ElementsAndConductorsSentence(
elements_count,
conductors_count,
textfields_count,
images_count
textfields_count
)
);
}
@@ -150,18 +117,14 @@ QString DiagramContent::sentence(int filter) const {
/**
Permet de debugger un contenu de schema
@param d Object QDebug a utiliser pour l'affichage des informations de debug
@param content Contenu de schema a debugger
@param c Contenu de schema a debugger
*/
QDebug &operator<<(QDebug d, DiagramContent &content) {
Q_UNUSED(content);
QDebug &operator<<(QDebug d, DiagramContent &c) {
d << "DiagramContent {" << "\n";
/*
FIXME Le double-heritage QObject / QGraphicsItem a casse cet operateur
d << " elements :" << c.elements << "\n";
d << " conductorsToUpdate :" << c.conductorsToUpdate << "\n";
d << " conductorsToUpdate :" << c.conductorsToUpdate.keys() << "\n";
d << " conductorsToMove :" << c.conductorsToMove << "\n";
d << " otherConductors :" << c.otherConductors << "\n";
*/
d << "}";
return(d.space());
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,16 +20,17 @@
#include <QtGui>
class Conductor;
class Element;
class IndependentTextItem;
class DiagramImageItem;
class Terminal;
class DiagramTextItem;
/**
This class provides a container that makes the transmission of diagram content
to other functions/methods easier. The different kind of items are made
available through a handful of filter-aware methods. Considering selected
elements are to be moved, the filter notably distinguishes conductors to be
moved from those to be updated.
Please note this container does not systematically contains a whole
diagram: it may describe only a part of it, e.g. selected items.
Cette classe est un conteneur pour passer facilement le contenu d'un schema
a une fonction. Il permet d'acceder rapidement aux differents types de
composants que l'on peut trouver sur un schema, comme les elements, les
champs de texte, les conducteurs (a deplacer ou a mettre a jour, en cas de
deplacements), etc.
A noter que ce container ne contient pas systematiquement l'integralite
d'un schema. Il peut n'en contenir qu'une partie, typiquement les
composants selectionnes.
*/
class DiagramContent {
public:
@@ -37,31 +38,27 @@ class DiagramContent {
DiagramContent(const DiagramContent &);
~DiagramContent();
/// Used to filter the different items carried by this container.
/// Permet de filtrer facilement les differentes parties d'un schema
enum Filter {
Elements = 1,
TextFields = 2,
Images = 3,
ConductorsToMove = 4,
ConductorsToUpdate = 8,
OtherConductors = 16,
AnyConductor = 28,
All = 31,
SelectedOnly = 32
All = 31
};
/// Hold electrical elements
QSet<Element *> elements;
/// Hold independent text items
QSet<IndependentTextItem *> textFields;
/// Hold image
QSet<DiagramImageItem *> images;
/// Hold conductors that would get updated considering electrical elements are moved
QSet<Conductor *> conductorsToUpdate;
/// Hold conductors that would be moved as is considering electrical elements are moved
QSet<Conductor *> conductorsToMove;
/// Hold conductors that would be left untouched considering electrical elements are moved
QSet<Conductor *> otherConductors;
/// Elements de texte du schema
QList<Element *> elements;
/// Champs de texte du schema
QList<DiagramTextItem *> textFields;
/// Conducteurs a mettre a jour du schema
QHash<Conductor *, Terminal *> conductorsToUpdate;
/// Conducteurs a deplacer du schema
QList<Conductor *> conductorsToMove;
/// Conducteurs isoles (ni a deplacer, ni a mettre a jour)
QList<Conductor *> otherConductors;
QList<Conductor *> conductors(int = AnyConductor) const;
QList<QGraphicsItem *> items(int = All) const;

200
diagramtextitem.cpp Normal file
View File

@@ -0,0 +1,200 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "diagramtextitem.h"
#include "diagramcommands.h"
/**
Constructeur
@param parent Le QGraphicsItem parent du champ de texte
@param scene La scene a laquelle appartient le champ de texte
*/
DiagramTextItem::DiagramTextItem(QGraphicsItem *parent, QGraphicsScene *scene) :
QGraphicsTextItem(parent, scene)
{
setDefaultTextColor(Qt::black);
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
}
/**
Constructeur
@param parent Le QGraphicsItem parent du champ de texte
@param scene La scene a laquelle appartient le champ de texte
@param text Le texte affiche par le champ de texte
*/
DiagramTextItem::DiagramTextItem(const QString &text, QGraphicsItem *parent, QGraphicsScene *scene) :
QGraphicsTextItem(text, parent, scene),
previous_text(text)
{
setDefaultTextColor(Qt::black);
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
}
/// Destructeur
DiagramTextItem::~DiagramTextItem() {
}
/// @return le Diagram auquel ce texte appartient, ou 0 si ce texte est independant
Diagram *DiagramTextItem::diagram() const {
return(qobject_cast<Diagram *>(scene()));
}
/**
gere la perte de focus du champ de texte
*/
void DiagramTextItem::focusOutEvent(QFocusEvent *e) {
QGraphicsTextItem::focusOutEvent(e);
// si le texte a ete modifie
if (toPlainText() != previous_text) {
if (Diagram *dia = diagram()) {
dia -> undoStack().push(new ChangeDiagramTextCommand(this, previous_text, toPlainText()));
previous_text = toPlainText();
}
}
// deselectionne le texte
QTextCursor cursor = textCursor();
cursor.clearSelection();
setTextCursor(cursor);
if (flags() & QGraphicsItem::ItemIsMovable) {
// hack a la con pour etre re-entrant
setTextInteractionFlags(Qt::NoTextInteraction);
QTimer::singleShot(0, this, SIGNAL(lostFocus()));
}
}
/**
Permet de lire le texte a mettre dans le champ a partir d'un element XML.
Cette methode se base sur la position du champ pour assigner ou non la
valeur a ce champ.
@param e L'element XML representant le champ de texte
*/
void DiagramTextItem::fromXml(const QDomElement &e) {
setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble());
setPlainText(e.attribute("text"));
previous_text = e.attribute("text");
}
/**
@param document Le document XML a utiliser
@return L'element XML representant ce champ de texte
*/
QDomElement DiagramTextItem::toXml(QDomDocument &document) const {
QDomElement result = document.createElement("input");
result.setAttribute("x", pos().x());
result.setAttribute("y", pos().y());
result.setAttribute("text", toPlainText());
return(result);
}
/**
Gere les double-clics sur ce champ de texte.
@param event un QGraphicsSceneMouseEvent decrivant le double-clic
*/
void DiagramTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
if (flags() & QGraphicsItem::ItemIsMovable && !(textInteractionFlags() & Qt::TextEditable)) {
// rend le champ de texte editable
setTextInteractionFlags(Qt::TextEditorInteraction);
// simule un clic simple, ce qui edite le champ de texte
QGraphicsSceneMouseEvent *mouseEvent = new QGraphicsSceneMouseEvent(QEvent::GraphicsSceneMousePress);
mouseEvent -> setAccepted(true);
mouseEvent -> setPos(event -> pos());
mouseEvent -> setScenePos(event -> scenePos());
mouseEvent -> setScreenPos(event -> screenPos());
mouseEvent -> setButtonDownPos(Qt::LeftButton, event -> buttonDownPos(Qt::LeftButton));
mouseEvent -> setButtonDownScreenPos(Qt::LeftButton, event -> buttonDownScreenPos(Qt::LeftButton));
mouseEvent -> setButtonDownScenePos(Qt::LeftButton, event -> buttonDownScenePos(Qt::LeftButton));
mouseEvent -> setWidget(event -> widget());
QGraphicsTextItem::mousePressEvent(mouseEvent);
delete mouseEvent;
} else {
QGraphicsTextItem::mouseDoubleClickEvent(event);
}
}
/**
Gere les mouvements de souris lies au champ de texte
*/
void DiagramTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
if (textInteractionFlags() & Qt::TextEditable) {
QGraphicsTextItem::mouseMoveEvent(e);
} else if ((flags() & QGraphicsItem::ItemIsMovable) && (e -> buttons() & Qt::LeftButton)) {
QPointF oldPos = pos();
setPos(mapToParent(e -> pos()) - matrix().map(e -> buttonDownPos(Qt::LeftButton)));
if (Diagram *diagram_ptr = diagram()) {
diagram_ptr -> moveElements(pos() - oldPos, this);
}
} else e -> ignore();
}
/**
Gere le relachement de souris
Cette methode a ete reimplementee pour tenir a jour la liste des elements
et conducteurs a deplacer au niveau du schema.
*/
void DiagramTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
if (Diagram *diagram_ptr = diagram()) {
if ((flags() & QGraphicsItem::ItemIsMovable) && (!diagram_ptr -> current_movement.isNull())) {
diagram_ptr -> undoStack().push(
new MoveElementsCommand(
diagram_ptr,
diagram_ptr -> selectedContent(),
diagram_ptr -> current_movement
)
);
diagram_ptr -> current_movement = QPointF();
}
diagram_ptr -> invalidateMovedElements();
}
QGraphicsTextItem::mouseReleaseEvent(e);
}
/**
Change la position du champ de texte en veillant a ce qu'il
reste sur la grille du schema auquel il appartient.
@param p Nouvelles coordonnees de l'element
*/
void DiagramTextItem::setPos(const QPointF &p) {
if (p == pos()) return;
// pas la peine de positionner sur la grille si l'element n'est pas sur un Diagram
if (scene()) {
// arrondit l'abscisse a 10 px pres
int p_x = qRound(p.x() / (Diagram::xGrid * 1.0)) * Diagram::xGrid;
// arrondit l'ordonnee a 10 px pres
int p_y = qRound(p.y() / (Diagram::yGrid * 1.0)) * Diagram::yGrid;
QGraphicsTextItem::setPos(p_x, p_y);
} else QGraphicsTextItem::setPos(p);
}
/**
Change la position du champ de texte en veillant a ce que l'il
reste sur la grille du schema auquel il appartient.
@param x Nouvelle abscisse de l'element
@param y Nouvelle ordonnee de l'element
*/
void DiagramTextItem::setPos(qreal x, qreal y) {
setPos(QPointF(x, y));
}
/// Rend le champ de texte non focusable
void DiagramTextItem::setNonFocusable() {
setFlag(QGraphicsTextItem::ItemIsFocusable, false);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2012 Xavier Guerrin
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -15,44 +15,53 @@
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INDEPENDENT_TEXT_ITEM_H
#define INDEPENDENT_TEXT_ITEM_H
#ifndef DIAGRAM_TEXT_ITEM_H
#define DIAGRAM_TEXT_ITEM_H
#include <QtGui>
#include "diagramtextitem.h"
#include "diagram.h"
/**
This class represents an independent text field on a particular diagram.
It may be moved, edited, and rotated.
Cette classe represente un champ de texte editable sur le schema.
*/
class IndependentTextItem : public DiagramTextItem {
class DiagramTextItem : public QGraphicsTextItem {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
IndependentTextItem(Diagram * = 0);
IndependentTextItem(const QString &, Diagram* = 0);
virtual ~IndependentTextItem();
DiagramTextItem(QGraphicsItem * = 0, QGraphicsScene * = 0);
DiagramTextItem(const QString &, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~DiagramTextItem();
// attributes
// attributs
public:
enum { Type = UserType + 1005 };
enum { Type = UserType + 1004 };
/// Texte precedent
QString previous_text;
// methods
// methodes
public:
/**
Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into an
IndependentTextItem.
Cette methode permet d'utiliser qgraphicsitem_cast sur cet objet
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
Diagram *diagram() const;
virtual void fromXml(const QDomElement &);
virtual QDomElement toXml(QDomDocument &) const;
virtual void setPos(const QPointF &);
virtual void setPos(qreal, qreal);
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
virtual void focusOutEvent(QFocusEvent *);
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
private:
bool first_move_;
QPointF mouse_to_origin_movement_;
// signaux
signals:
/// signal emis lorsque le champ de texte perd le focus
void lostFocus();
// slots
public slots:
void setNonFocusable();
};
#endif

960
diagramview.cpp Normal file
View File

@@ -0,0 +1,960 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "diagramview.h"
#include "diagram.h"
#include "customelement.h"
#include "exportdialog.h"
#include "conductor.h"
#include "diagramcommands.h"
#include "conductorpropertieswidget.h"
#include "insetpropertieswidget.h"
/**
Constructeur
@param parent Le QWidegt parent de cette vue de schema
*/
DiagramView::DiagramView(QWidget *parent) : QGraphicsView(parent), is_adding_text(false) {
setInteractive(true);
setCacheMode(QGraphicsView::CacheBackground);
setOptimizationFlags(QGraphicsView::DontSavePainterState|QGraphicsView::DontAdjustForAntialiasing);
// active l'antialiasing
setRenderHint(QPainter::Antialiasing, true);
setRenderHint(QPainter::TextAntialiasing, true);
setRenderHint(QPainter::SmoothPixmapTransform, true);
setScene(scene = new Diagram(this));
scene -> undoStack().setClean();
setDragMode(RubberBandDrag);
setAcceptDrops(true);
setWindowIcon(QIcon(":/ico/qet-16.png"));
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
setAlignment(Qt::AlignLeft | Qt::AlignTop);
adjustSceneRect();
updateWindowTitle();
context_menu = new QMenu(this);
paste_here = new QAction(QIcon(":/ico/paste.png"), tr("Coller ici"), this);
connect(paste_here, SIGNAL(triggered()), this, SLOT(pasteHere()));
connect(scene, SIGNAL(selectionEmptinessChanged()), this, SIGNAL(selectionChanged()));
connect(&(scene -> border_and_inset), SIGNAL(borderChanged(QRectF, QRectF)), this, SLOT(adjustSceneRect()));
connect(&(scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(updateWindowTitle()));
}
/**
Destructeur
*/
DiagramView::~DiagramView() {
}
/**
appelle la methode select sur tous les elements de la liste d'elements
*/
void DiagramView::selectAll() {
if (scene -> items().isEmpty()) return;
QPainterPath path;
path.addRect(scene -> itemsBoundingRect());
scene -> setSelectionArea(path);
}
/**
appelle la methode deselect sur tous les elements de la liste d'elements
*/
void DiagramView::selectNothing() {
if (scene -> items().isEmpty()) return;
scene -> clearSelection();
}
/**
Inverse l'etat de selection de tous les elements de la liste d'elements
*/
void DiagramView::selectInvert() {
if (scene -> items().isEmpty()) return;
foreach (QGraphicsItem *item, scene -> items()) item -> setSelected(!item -> isSelected());
}
/**
Supprime les composants selectionnes
*/
void DiagramView::deleteSelection() {
DiagramContent removed_content = scene -> selectedContent();
scene -> clearSelection();
scene -> undoStack().push(new DeleteElementsCommand(scene, removed_content));
adjustSceneRect();
}
/**
Pivote les composants selectionnes
*/
void DiagramView::rotateSelection() {
QHash<Element *, QET::Orientation> elements_to_rotate;
foreach (QGraphicsItem *item, scene -> selectedItems()) {
if (Element *e = qgraphicsitem_cast<Element *>(item)) {
elements_to_rotate.insert(e, e -> orientation().current());
}
}
if (elements_to_rotate.isEmpty()) return;
scene -> undoStack().push(new RotateElementsCommand(elements_to_rotate));
}
/**
accepte ou refuse le drag'n drop en fonction du type de donnees entrant
@param e le QDragEnterEvent correspondant au drag'n drop tente
*/
void DiagramView::dragEnterEvent(QDragEnterEvent *e) {
if (e -> mimeData() -> hasFormat("text/plain")) e -> acceptProposedAction();
else e-> ignore();
}
/**
gere les dragleaveevent
@param e le QDragEnterEvent correspondant au drag'n drop sortant
*/
void DiagramView::dragLeaveEvent(QDragLeaveEvent *) {
}
/**
accepte ou refuse le drag'n drop en fonction du type de donnees entrant
@param e le QDragMoveEvent correspondant au drag'n drop tente
*/
void DiagramView::dragMoveEvent(QDragMoveEvent *e) {
if (e -> mimeData() -> hasFormat("text/plain")) e -> acceptProposedAction();
else e-> ignore();
}
/**
gere les depots (drop) acceptes sur le Diagram
@param e le QDropEvent correspondant au drag'n drop effectue
*/
void DiagramView::dropEvent(QDropEvent *e) {
QString fichier = e -> mimeData() -> text();
int etat;
Element *el = new CustomElement(fichier, 0, 0, &etat);
if (etat) delete el;
else {
diagram() -> undoStack().push(new AddElementCommand(diagram(), el, mapToScene(e -> pos())));
adjustSceneRect();
}
}
/**
Passe le Diagram en mode visualisation
*/
void DiagramView::setVisualisationMode() {
setDragMode(ScrollHandDrag);
setInteractive(false);
emit(modeChanged());
}
/**
Passe le Diagram en mode Selection
*/
void DiagramView::setSelectionMode() {
setDragMode(RubberBandDrag);
setInteractive(true);
emit(modeChanged());
}
/**
Agrandit le schema (+33% = inverse des -25 % de zoomMoins())
*/
void DiagramView::zoomIn() {
scale(4.0/3.0, 4.0/3.0);
adjustGridToZoom();
}
/**
Retrecit le schema (-25% = inverse des +33 % de zoomPlus())
*/
void DiagramView::zoomOut() {
scale(0.75, 0.75);
adjustGridToZoom();
}
/**
Agrandit ou rectrecit le schema de facon a ce que tous les elements du
schema soient visibles a l'ecran. S'il n'y a aucun element sur le schema,
le zoom est reinitialise
*/
void DiagramView::zoomFit() {
adjustSceneRect();
fitInView(sceneRect(), Qt::KeepAspectRatio);
adjustGridToZoom();
}
/**
Reinitialise le zoom
*/
void DiagramView::zoomReset() {
resetMatrix();
adjustGridToZoom();
}
/**
copie les elements selectionnes du schema dans le presse-papier puis les supprime
*/
void DiagramView::cut() {
copy();
DiagramContent cut_content = scene -> selectedContent();
scene -> clearSelection();
scene -> undoStack().push(new CutDiagramCommand(scene, cut_content));
}
/**
copie les elements selectionnes du schema dans le presse-papier
*/
void DiagramView::copy() {
QClipboard *presse_papier = QApplication::clipboard();
QString contenu_presse_papier = scene -> toXml(false).toString(4);
if (presse_papier -> supportsSelection()) presse_papier -> setText(contenu_presse_papier, QClipboard::Selection);
presse_papier -> setText(contenu_presse_papier);
}
/**
Importe les elements contenus dans le presse-papier dans le schema
@param pos coin superieur gauche (en coordonnees de la scene) du rectangle
englobant le contenu colle
@param clipboard_mode Type de presse-papier a prendre en compte
*/
void DiagramView::paste(const QPointF &pos, QClipboard::Mode clipboard_mode) {
QString texte_presse_papier = QApplication::clipboard() -> text(clipboard_mode);
if ((texte_presse_papier).isEmpty()) return;
QDomDocument document_xml;
if (!document_xml.setContent(texte_presse_papier)) return;
// objet pour recuperer le contenu ajoute au schema par le coller
DiagramContent content_pasted;
scene -> fromXml(document_xml, pos, false, &content_pasted);
// si quelque chose a effectivement ete ajoute au schema, on cree un objet d'annulation
if (content_pasted.count()) {
scene -> clearSelection();
scene -> undoStack().push(new PasteDiagramCommand(scene, content_pasted));
adjustSceneRect();
}
}
/// Colle le contenu du presse-papier sur le schema a la position de la souris
void DiagramView::pasteHere() {
paste(mapToScene(paste_here_pos));
}
/**
gere les clics et plus particulierement le clic du milieu (= coller pour X11)
*/
void DiagramView::mousePressEvent(QMouseEvent *e) {
if (e -> buttons() == Qt::MidButton) {
paste(mapToScene(e -> pos()), QClipboard::Selection);
} else {
if (is_adding_text && e -> buttons() == Qt::LeftButton) {
DiagramTextItem *dti = new DiagramTextItem();
dti -> setPlainText("_");
dti -> previous_text = "_";
scene -> undoStack().push(new AddTextCommand(scene, dti, e -> pos()));
adjustSceneRect();
is_adding_text = false;
emit(textAdded(false));
}
QGraphicsView::mousePressEvent(e);
}
}
/**
Ouvre un fichier *.qet dans cette DiagramView
@param n_fichier Nom du fichier a ouvrir
@param erreur Si le pointeur est specifie, cet entier est mis a 0 en cas de reussite de l'ouverture, 1 si le fichier n'existe pas, 2 si le fichier n'est pas lisible, 3 si le fichier n'est pas un element XML, 4 si l'ouverture du fichier a echoue pour une autre raison (c'est pas ca qui manque ^^)
@return true si l'ouverture a reussi, false sinon
*/
bool DiagramView::open(QString n_fichier, int *erreur) {
// verifie l'existence du fichier
if (!QFileInfo(n_fichier).exists()) {
if (erreur != NULL) *erreur = 1;
return(false);
}
// ouvre le fichier
QFile fichier(n_fichier);
if (!fichier.open(QIODevice::ReadOnly)) {
if (erreur != NULL) *erreur = 2;
return(false);
}
// lit son contenu dans un QDomDocument
QDomDocument document;
if (!document.setContent(&fichier)) {
if (erreur != NULL) *erreur = 3;
fichier.close();
return(false);
}
fichier.close();
/**
La notion de projet (ensemble de documents [schemas, nomenclatures,
...] et d'elements) n'est pas encore geree.
Toutefois, pour gerer au mieux la transition de la 0.1 a la 0.2,
les schemas enregistres (element XML "diagram") sont integres dans un
pseudo projet (element XML "project").
S'il y a plusieurs schemas dans un projet, tous les schemas seront
ouverts comme etant des fichiers separes
*/
// repere les schemas dans le fichier
QDomElement root = document.documentElement();
// cas 1 : l'element racine est un "diagram" : un seul schema, pas de probleme
if (root.tagName() == "diagram") {
// construit le schema a partir du QDomDocument
QDomDocument &doc = document;
if (scene -> fromXml(doc)) {
if (erreur != NULL) *erreur = 0;
file_name = n_fichier;
scene -> undoStack().setClean();
updateWindowTitle();
return(true);
} else {
if (erreur != NULL) *erreur = 4;
return(false);
}
// cas 2 : l'element racine est un "project"
} else if (root.tagName() == "project") {
// verifie basiquement que la version actuelle est capable de lire ce fichier
if (root.hasAttribute("version")) {
bool conv_ok;
qreal diagram_version = root.attribute("version").toDouble(&conv_ok);
if (conv_ok && QET::version.toDouble() < diagram_version) {
QMessageBox::warning(
0,
tr("Avertissement"),
tr("Ce document semble avoir \351t\351 enregistr\351 avec une "
"version ult\351rieure de QElectroTech. Il est possible que "
"l'ouverture de tout ou partie de ce document \351choue.")
);
}
}
// compte le nombre de schemas dans le projet
QList<QDomElement> diagrams;
QDomNodeList diagram_nodes = root.elementsByTagName("diagram");
for (uint i = 0 ; i < diagram_nodes.length() ; ++ i) {
if (diagram_nodes.at(i).isElement()) {
diagrams << diagram_nodes.at(i).toElement();
}
}
// il n'y aucun schema la-dedans
if (!diagrams.count()) {
if (erreur != NULL) *erreur = 4;
return(false);
} else {
bool keep_doc_name = diagrams.count() == 1;
bool current_dv_loaded = false;
for (int i = 0 ; i < diagrams.count() ; ++ i) {
// cree un QDomDocument representant le schema
QDomDocument diagram_doc;
diagram_doc.appendChild(diagram_doc.importNode(diagrams[i], true));
// charge le premier schema valide et cree de nouveau DiagramView pour les suivants
if (!current_dv_loaded) {
if (scene -> fromXml(diagram_doc)) {
if (keep_doc_name) file_name = n_fichier;
scene -> undoStack().setClean();
updateWindowTitle();
current_dv_loaded = true;
}
} else {
DiagramView *new_dv = new DiagramView(parentWidget());
if (new_dv -> scene -> fromXml(diagram_doc)) {
if (keep_doc_name) new_dv -> file_name = n_fichier;
new_dv -> scene -> undoStack().setClean();
new_dv -> updateWindowTitle();
diagramEditor() -> addDiagramView(new_dv);
} else {
delete(new_dv);
}
}
}
return(true);
}
} else {
if (erreur != NULL) *erreur = 4;
return(false);
}
}
/**
Gere la fermeture du schema.
@param event Le QCloseEvent decrivant l'evenement
*/
void DiagramView::closeEvent(QCloseEvent *event) {
bool retour;
// si le schema est modifie
if (!isWindowModified()) {
retour = true;
} else {
// demande d'abord a l'utilisateur s'il veut enregistrer le schema en cours
QMessageBox::StandardButton reponse = QMessageBox::question(
this,
tr("Enregistrer le sch\351ma en cours ?"),
tr("Voulez-vous enregistrer le sch\351ma ") + windowTitle() + tr(" ?"),
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
QMessageBox::Cancel
);
switch(reponse) {
case QMessageBox::Cancel: retour = false; break; // l'utilisateur annule : echec de la fermeture
case QMessageBox::Yes: retour = save(); break; // l'utilisateur dit oui : la reussite depend de l'enregistrement
default: retour = true; // l'utilisateur dit non ou ferme le dialogue: c'est reussi
}
}
if (retour) {
event -> accept();
delete this;
} else event -> ignore();
}
/**
Methode enregistrant le schema dans le dernier nom de fichier connu.
Si aucun nom de fichier n'est connu, cette methode appelle la methode saveAs
@return true si l'enregistrement a reussi, false sinon
*/
bool DiagramView::save() {
if (file_name.isEmpty()) return(saveAs());
else return(saveDiagramToFile(file_name));
}
/**
Cette methode demande un nom de fichier a l'utilisateur pour enregistrer le schema
Si aucun nom n'est entre, elle renvoie faux.
Si le nom ne se termine pas par l'extension .qet, celle-ci est ajoutee.
Si l'enregistrement reussit, le nom du fichier est conserve et la fonction renvoie true.
Sinon, faux est renvoye.
@return true si l'enregistrement a reussi, false sinon
*/
bool DiagramView::saveAs() {
// demande un nom de fichier a l'utilisateur pour enregistrer le schema
QString n_fichier = QFileDialog::getSaveFileName(
this,
tr("Enregistrer sous"),
(file_name.isEmpty() ? QDir::homePath() : QDir(file_name)).absolutePath(),
tr("Sch\351ma QElectroTech (*.qet)")
);
// si aucun nom n'est entre, renvoie faux.
if (n_fichier.isEmpty()) return(false);
// si le nom ne se termine pas par l'extension .qet, celle-ci est ajoutee
if (!n_fichier.endsWith(".qet", Qt::CaseInsensitive)) n_fichier += ".qet";
// tente d'enregistrer le fichier
bool resultat_enregistrement = saveDiagramToFile(n_fichier);
// si l'enregistrement reussit, le nom du fichier est conserve
if (resultat_enregistrement) {
file_name = n_fichier;
updateWindowTitle();
}
// retourne un booleen representatif de la reussite de l'enregistrement
return(resultat_enregistrement);
}
/**
Gere les actions liees a la rollette de la souris
@param e QWheelEvent decrivant l'evenement rollette
*/
void DiagramView::wheelEvent(QWheelEvent *e) {
// si la touche Ctrl est enfoncee, on zoome / dezoome
if (e -> modifiers() & Qt::ControlModifier) {
if (e -> delta() > 0) {
zoomIn();
} else {
zoomOut();
}
} else {
QAbstractScrollArea::wheelEvent(e);
}
}
/**
Methode privee gerant l'enregistrement du fichier XML. S'il n'est pas possible
d'ecrire dans le fichier, cette fonction affiche un message d'erreur et renvoie false.
Autrement, elle renvoie true.
@param n_fichier Nom du fichier dans lequel l'arbre XML doit etre ecrit
@return true si l'enregistrement a reussi, false sinon
*/
bool DiagramView::saveDiagramToFile(QString &n_fichier) {
QFile fichier(n_fichier);
if (!fichier.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::warning(this, tr("Erreur"), tr("Impossible d'ecrire dans ce fichier"));
return(false);
}
QTextStream out(&fichier);
out.setCodec("UTF-8");
// l'export XML du schema est encapsule dans un pseudo-projet
QDomDocument final_document;
QDomElement project_root = final_document.createElement("project");
project_root.setAttribute("version", QET::version);
project_root.appendChild(final_document.importNode(scene -> toXml().documentElement(), true));
final_document.appendChild(project_root);
out << final_document.toString(4);
fichier.close();
scene -> undoStack().setClean();
return(true);
}
/**
Exporte le schema.
*/
void DiagramView::dialogExport() {
ExportDialog ed(scene, this);
ed.exec();
}
/**
Imprime le schema.
*/
void DiagramView::dialogPrint() {
// initialise l'acces a l'imprimante
QPrinter qprin;
#ifndef Q_OS_WIN32
qprin.setOutputFormat(QPrinter::PdfFormat);
#endif
qprin.setOrientation(QPrinter::Landscape);
qprin.setPageSize(QPrinter::A4);
QPrintDialog qpd(&qprin, this);
if (qpd.exec() == QDialog::Accepted) {
QPainter qp(&qprin);
// impression physique (!= fichier PDF)
if (qprin.outputFileName().isEmpty()) {
// lorsqu'on imprime en paysage sur imprimante reelle, il faut pivoter soi-meme le rendu
if (qprin.orientation() == QPrinter::Landscape) {
qp.rotate(90.0);
qp.translate(0.0, -qprin.pageRect().height());
}
}
scene -> setDisplayGrid(false);
scene -> setDrawTerminals(false);
scene -> render(&qp, QRectF(), scene -> border(), Qt::KeepAspectRatio);
scene -> setDrawTerminals(true);
scene -> setDisplayGrid(true);
}
}
/**
Edite les informations du schema.
*/
void DiagramView::dialogEditInfos() {
// recupere le cartouche du schema
InsetProperties inset = scene -> border_and_inset.exportInset();
// recupere les dimensions du schema
int columns_count_value = scene -> border_and_inset.nbColumn();
int columns_width_value = qRound(scene -> border_and_inset.columnsWidth());
int columns_height_value = qRound(scene -> border_and_inset.columnsHeight());
// construit le dialogue
QDialog popup;
popup.setMinimumWidth(400);
popup.setWindowTitle(tr("Propri\351t\351s du sch\351ma"));
QGroupBox *diagram_size_box = new QGroupBox(tr("Dimensions du sch\351ma"), &popup);
QGridLayout diagram_size_box_layout(diagram_size_box);
QLabel *ds1 = new QLabel(tr("Colonnes :"));
QSpinBox *columns_count = new QSpinBox(diagram_size_box);
columns_count -> setMinimum(scene -> border_and_inset.minNbColumns());
columns_count -> setValue(columns_count_value);
QSpinBox *columns_width = new QSpinBox(diagram_size_box);
columns_width -> setMinimum(1);
columns_width -> setSingleStep(10);
columns_width -> setValue(columns_width_value);
columns_width -> setPrefix(tr("\327"));
columns_width -> setSuffix(tr("px"));
QLabel *ds2 = new QLabel(tr("Hauteur :"));
QSpinBox *columns_height = new QSpinBox(diagram_size_box);
columns_height -> setRange(qRound(scene -> border_and_inset.minColumnsHeight()), 10000);
columns_height -> setSingleStep(80);
columns_height -> setValue(columns_height_value);
diagram_size_box_layout.addWidget(ds1, 0, 0);
diagram_size_box_layout.addWidget(columns_count, 0, 1);
diagram_size_box_layout.addWidget(columns_width, 0, 2);
diagram_size_box_layout.addWidget(ds2, 1, 0);
diagram_size_box_layout.addWidget(columns_height, 1, 1);
diagram_size_box_layout.setColumnStretch(0, 1);
diagram_size_box_layout.setColumnStretch(1, 1);
diagram_size_box_layout.setColumnStretch(2, 1);
diagram_size_box_layout.setColumnStretch(3, 500);
InsetPropertiesWidget *inset_infos = new InsetPropertiesWidget(inset, false, &popup);
// boutons
QDialogButtonBox boutons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(&boutons, SIGNAL(accepted()), &popup, SLOT(accept()));
connect(&boutons, SIGNAL(rejected()), &popup, SLOT(reject()));
// ajout dans une disposition verticale
QVBoxLayout layout_v(&popup);
layout_v.addWidget(diagram_size_box);
layout_v.addWidget(inset_infos);
layout_v.addStretch();
layout_v.addWidget(&boutons);
// si le dialogue est accepte
if (popup.exec() == QDialog::Accepted) {
InsetProperties new_inset = inset_infos -> insetProperties();
// s'il y a des modifications au cartouche
if (new_inset != inset) {
scene -> undoStack().push(new ChangeInsetCommand(scene, inset, new_inset));
}
// s'il y a des modifications aux dimensions du schema
if (
columns_count_value != columns_count -> value() ||\
columns_width_value != columns_width -> value() ||\
columns_height_value != columns_height -> value()
) {
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
cbc -> columnsCountDifference = columns_count -> value() - columns_count_value;
cbc -> columnsWidthDifference = columns_width -> value() - columns_width_value;
cbc -> columnsHeightDifference = columns_height -> value() - columns_height_value;
scene -> undoStack().push(cbc);
}
}
}
/**
@return true s'il y a des elements selectionnes sur le schema, false sinon
*/
bool DiagramView::hasSelectedItems() {
return(scene -> selectedItems().size() > 0);
}
/**
Ajoute une colonne au schema.
*/
void DiagramView::addColumn() {
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
cbc -> columnsCountDifference = 1;
scene -> undoStack().push(cbc);
}
/**
Enleve une colonne au schema.
*/
void DiagramView::removeColumn() {
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
cbc -> columnsCountDifference = -1;
scene -> undoStack().push(cbc);
}
/**
Agrandit le schema en hauteur
*/
void DiagramView::expand() {
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
cbc -> columnsHeightDifference = 80.0;
scene -> undoStack().push(cbc);
}
/**
Retrecit le schema en hauteur
*/
void DiagramView::shrink() {
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
cbc -> columnsHeightDifference = -80.0;
scene -> undoStack().push(cbc);
}
/**
Ajuste le sceneRect (zone du schema visualisee par le DiagramView) afin que
celui inclut a la fois les elements dans et en dehors du cadre et le cadre
lui-meme.
*/
void DiagramView::adjustSceneRect() {
QRectF old_scene_rect = sceneRect();
// rectangle delimitant l'ensemble des elements
QRectF elements_bounding_rect = scene -> itemsBoundingRect();
// rectangle contenant le cadre = colonnes + cartouche
QRectF border_bounding_rect = scene -> border().adjusted(-Diagram::margin, -Diagram::margin, Diagram::margin, Diagram::margin);
// ajuste la sceneRect
QRectF new_scene_rect = elements_bounding_rect.united(border_bounding_rect);
setSceneRect(new_scene_rect);
// met a jour la scene
scene -> update(old_scene_rect.united(new_scene_rect));
}
/**
Met a jour le titre du widget
*/
void DiagramView::updateWindowTitle() {
QString window_title;
if (file_name.isNull()) window_title += tr("nouveau sch\351ma");
else window_title += file_name;
window_title += "[*]";
setWindowTitle(window_title);
setWindowModified(!(scene -> undoStack().isClean()));
}
/**
Active ou desactive le dessin de grille selon la quantite de pixels affichee
*/
void DiagramView::adjustGridToZoom() {
QRectF viewed_scene = viewedSceneRect();
scene -> setDisplayGrid(viewed_scene.width() < 2000 || viewed_scene.height() < 2000);
}
/**
@return le rectangle du schema (classe Diagram) visualise par ce DiagramView
*/
QRectF DiagramView::viewedSceneRect() const {
// recupere la taille du widget viewport
QSize viewport_size = viewport() -> size();
// recupere la transformation viewport -> scene
QTransform view_to_scene = viewportTransform().inverted();
// mappe le coin superieur gauche et le coin inferieur droit de la viewport sur la scene
QPointF scene_left_top = view_to_scene.map(QPointF(0.0, 0.0));
QPointF scene_right_bottom = view_to_scene.map(QPointF(viewport_size.width(), viewport_size.height()));
// en deduit le rectangle visualise par la scene
return(QRectF(scene_left_top, scene_right_bottom));
}
/**
Affiche un dialogue permettant d'editer le conducteur selectionne.
Ne fait rien s'il y a 0 ou plusieurs conducteurs selectionnes.
*/
void DiagramView::editConductor() {
QList<Conductor *> selected_conductors(scene -> selectedConductors().toList());
// on ne peut editer qu'un conducteur a la fois
if (selected_conductors.count() != 1) return;
Conductor *edited_conductor = selected_conductors.first();
editConductor(edited_conductor);
}
/**
Edite le conducteur passe en parametre
@param edited_conductor Conducteur a editer
*/
void DiagramView::editConductor(Conductor *edited_conductor) {
if (!edited_conductor) return;
// initialise l'editeur de proprietes pour le conducteur
ConductorProperties old_properties = edited_conductor -> properties();
ConductorPropertiesWidget *cpw = new ConductorPropertiesWidget(old_properties);
// l'insere dans un dialogue
QDialog conductor_dialog;
conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s d'un conducteur"));
QVBoxLayout *dialog_layout = new QVBoxLayout(&conductor_dialog);
dialog_layout -> addWidget(cpw);
dialog_layout -> addStretch();
QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog_layout -> addWidget(dbb);
connect(dbb, SIGNAL(accepted()), &conductor_dialog, SLOT(accept()));
connect(dbb, SIGNAL(rejected()), &conductor_dialog, SLOT(reject()));
// execute le dialogue et met a jour le conducteur
if (conductor_dialog.exec() == QDialog::Accepted) {
// recupere les nouvelles proprietes
ConductorProperties new_properties = cpw -> conductorProperties();
if (new_properties != old_properties) {
// initialise l'objet UndoCommand correspondant
ChangeConductorPropertiesCommand *ccpc = new ChangeConductorPropertiesCommand(edited_conductor);
ccpc -> setOldSettings(old_properties);
ccpc -> setNewSettings(new_properties);
diagram() -> undoStack().push(ccpc);
}
}
}
/**
Reinitialise le profil des conducteurs selectionnes
*/
void DiagramView::resetConductors() {
// recupere les conducteurs selectionnes
QSet<Conductor *> selected_conductors = scene -> selectedConductors();
// repere les conducteurs modifies (= profil non nul)
QHash<Conductor *, ConductorProfilesGroup> conductors_and_profiles;
foreach(Conductor *conductor, selected_conductors) {
ConductorProfilesGroup profile = conductor -> profiles();
if (
!profile[Qt::TopLeftCorner].isNull() ||\
!profile[Qt::TopRightCorner].isNull() ||\
!profile[Qt::BottomLeftCorner].isNull() ||\
!profile[Qt::BottomRightCorner].isNull()
) {
conductors_and_profiles.insert(conductor, profile);
}
}
if (conductors_and_profiles.isEmpty()) return;
scene -> undoStack().push(new ResetConductorCommand(conductors_and_profiles));
}
/**
Lance un dialogue permettant de modifier les proprietes par defaut des
futurs nouveaux conducteurs
*/
void DiagramView::editDefaultConductorProperties() {
// initialise l'editeur de proprietes pour le conducteur
ConductorPropertiesWidget *cpw = new ConductorPropertiesWidget(scene -> defaultConductorProperties);
// l'insere dans un dialogue
QDialog conductor_dialog;
conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s par d\351faut des conducteurs"));
QVBoxLayout *dialog_layout = new QVBoxLayout(&conductor_dialog);
dialog_layout -> addWidget(cpw);
QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog_layout -> addWidget(dbb);
connect(dbb, SIGNAL(accepted()), &conductor_dialog, SLOT(accept()));
connect(dbb, SIGNAL(rejected()), &conductor_dialog, SLOT(reject()));
// execute le dialogue et met a jour le conducteur
if (conductor_dialog.exec() == QDialog::Accepted) {
scene -> defaultConductorProperties = cpw -> conductorProperties();
}
}
/**
Gere les evenements de la DiagramView
@param e Evenement
*/
bool DiagramView::event(QEvent *e) {
// fait en sorte que les raccourcis clavier arrivent prioritairement sur la
// vue plutot que de remonter vers les QMenu / QAction
if (e -> type() == QEvent::ShortcutOverride && scene -> focusItem()) {
e -> accept();
return(true);
}
return(QGraphicsView::event(e));
}
/**
Passe le DiagramView en mode "ajout de texte". Un clic cree alors un
nouveau champ de texte.
*/
void DiagramView::addText() {
is_adding_text = true;
}
/**
Gere le menu contextuel
@param e Evenement decrivant la demande de menu contextuel
*/
void DiagramView::contextMenuEvent(QContextMenuEvent *e) {
if (QGraphicsItem *qgi = scene -> itemAt(mapToScene(e -> pos()))) {
if (!qgi -> isSelected()) scene -> clearSelection();
qgi -> setSelected(true);
}
if (QETDiagramEditor *qde = diagramEditor()) {
context_menu -> clear();
if (scene -> selectedItems().isEmpty()) {
paste_here_pos = e -> pos();
paste_here -> setEnabled(Diagram::clipboardMayContainDiagram());
context_menu -> addAction(paste_here);
context_menu -> addSeparator();
context_menu -> addAction(qde -> infos_diagram);
context_menu -> addAction(qde -> add_column);
context_menu -> addAction(qde -> remove_column);
context_menu -> addAction(qde -> expand_diagram);
context_menu -> addAction(qde -> shrink_diagram);
} else {
context_menu -> addAction(qde -> cut);
context_menu -> addAction(qde -> copy);
context_menu -> addSeparator();
context_menu -> addAction(qde -> delete_selection);
context_menu -> addAction(qde -> rotate_selection);
context_menu -> addSeparator();
context_menu -> addAction(qde -> conductor_prop);
context_menu -> addAction(qde -> conductor_reset);
}
// affiche le menu contextuel
context_menu -> popup(e -> globalPos());
}
e -> accept();
}
/// @return l'editeur de schemas parent ou 0
QETDiagramEditor *DiagramView::diagramEditor() const {
// remonte la hierarchie des widgets
QWidget *w = const_cast<DiagramView *>(this);
while (w -> parentWidget() && !w -> isWindow()) {
w = w -> parentWidget();
}
// la fenetre est supposee etre un QETDiagramEditor
return(qobject_cast<QETDiagramEditor *>(w));
}
/**
Gere les double-clics sur le schema
*/
void DiagramView::mouseDoubleClickEvent(QMouseEvent *e) {
BorderInset &bi = scene -> border_and_inset;
// recupere le rectangle corespondant au cartouche
QRectF inset_rect(
Diagram::margin,
Diagram::margin + bi.columnsHeight(),
bi.insetWidth(),
bi.insetHeight()
);
// recupere le rectangle correspondant aux en-tetes des colonnes
QRectF columns_rect(
Diagram::margin,
Diagram::margin,
bi.borderWidth(),
bi.columnsHeaderHeight()
);
// coordonnees du clic par rapport au schema
QPointF click_pos = viewportTransform().inverted().map(e -> pos());
// detecte le double-clic sur le cartouche ou les colonnes
if (QGraphicsItem *qgi = itemAt(e -> pos())) {
if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
editConductor(c);
} else {
QGraphicsView::mouseDoubleClickEvent(e);
}
} else if (inset_rect.contains(click_pos) || columns_rect.contains(click_pos)) {
// edite les proprietes du schema
dialogEditInfos();
} else {
QGraphicsView::mouseDoubleClickEvent(e);
}
}

118
diagramview.h Normal file
View File

@@ -0,0 +1,118 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DIAGRAMVIEW_H
#define DIAGRAMVIEW_H
#include <QtGui>
class Diagram;
class QETDiagramEditor;
class Conductor;
/**
Classe representant graphiquement un schema electrique
*/
class DiagramView : public QGraphicsView {
Q_OBJECT
// constructeurs, destructeur
public:
DiagramView(QWidget * = 0);
virtual ~DiagramView();
private:
DiagramView(const DiagramView &);
// attributs
public:
/// Nom de fichier du schema edite
QString file_name;
private:
Diagram *scene;
QMenu *context_menu;
QAction *paste_here;
QPoint paste_here_pos;
bool is_adding_text;
// methodes
public:
bool open(QString, int * = NULL);
void closeEvent(QCloseEvent *);
bool save();
bool saveAs();
void dialogExport();
void dialogEditInfos();
void dialogPrint();
void addColumn();
void removeColumn();
void expand();
void shrink();
/// @return Le schema visualise par ce DiagramView
Diagram *diagram() { return(scene); }
QETDiagramEditor *diagramEditor() const;
bool hasSelectedItems();
void addText();
protected:
virtual void mouseDoubleClickEvent(QMouseEvent *);
virtual void contextMenuEvent(QContextMenuEvent *);
virtual void wheelEvent(QWheelEvent *);
virtual bool event(QEvent *);
private:
bool saveDiagramToFile(QString &);
void mousePressEvent(QMouseEvent *);
void dragEnterEvent(QDragEnterEvent *);
void dragLeaveEvent(QDragLeaveEvent *);
void dragMoveEvent(QDragMoveEvent *);
void dropEvent(QDropEvent *);
QRectF viewedSceneRect() const;
signals:
/// Signal emis lorsque la selection change
void selectionChanged();
/// Signal emis lorsque le mode de selection change
void modeChanged();
/// Signal emis lorsqu'un texte a ete pose
void textAdded(bool);
public slots:
void selectNothing();
void selectAll();
void selectInvert();
void deleteSelection();
void rotateSelection();
void setVisualisationMode();
void setSelectionMode();
void zoomIn();
void zoomOut();
void zoomFit();
void zoomReset();
void cut();
void copy();
void paste(const QPointF & = QPointF(), QClipboard::Mode = QClipboard::Clipboard);
void pasteHere();
void adjustSceneRect();
void updateWindowTitle();
void editConductor();
void editConductor(Conductor *);
void resetConductors();
void editDefaultConductorProperties();
private slots:
void adjustGridToZoom();
};
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -16,7 +16,6 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "arceditor.h"
#include "styleeditor.h"
#include "partarc.h"
/**
@@ -25,11 +24,10 @@
@param arc L'arc a editer
@param parent le Widget parent
*/
ArcEditor::ArcEditor(QETElementEditor *editor, PartArc *arc, QWidget *parent) :
ElementItemEditor(editor, parent),
part(arc)
{
style_ = new StyleEditor(editor);
ArcEditor::ArcEditor(QETElementEditor *editor, PartArc *arc, QWidget *parent) : ElementItemEditor(editor, parent) {
part = arc;
x = new QLineEdit();
y = new QLineEdit();
h = new QLineEdit();
@@ -44,11 +42,9 @@ ArcEditor::ArcEditor(QETElementEditor *editor, PartArc *arc, QWidget *parent) :
h -> setValidator(new QDoubleValidator(h));
v -> setValidator(new QDoubleValidator(v));
QVBoxLayout *v_layout = new QVBoxLayout(this);
QGridLayout *grid = new QGridLayout();
QGridLayout *grid = new QGridLayout(this);
grid -> addWidget(new QLabel(tr("Centre : ")), 0, 0);
grid -> addWidget(new QLabel("x"), 1, 0, Qt::AlignRight);
grid -> addWidget(new QLabel("x"), 1, 0);
grid -> addWidget(x, 1, 1);
grid -> addWidget(new QLabel("y"), 1, 2);
grid -> addWidget(y, 1, 3);
@@ -61,10 +57,6 @@ ArcEditor::ArcEditor(QETElementEditor *editor, PartArc *arc, QWidget *parent) :
grid -> addWidget(start_angle, 5, 1);
grid -> addWidget(new QLabel(tr("Angle :")), 6, 0);
grid -> addWidget(angle, 6, 1);
v_layout -> addWidget(style_);
v_layout -> addLayout(grid);
updateForm();
activeConnections(true);
@@ -74,48 +66,16 @@ ArcEditor::ArcEditor(QETElementEditor *editor, PartArc *arc, QWidget *parent) :
ArcEditor::~ArcEditor() {
}
/**
Permet de specifier a cet editeur quelle primitive il doit editer. A noter
qu'un editeur peut accepter ou refuser d'editer une primitive.
L'editeur d'arc acceptera d'editer la primitive new_part s'il s'agit d'un
objet de la classe PartArc.
@param new_part Nouvelle primitive a editer
@return true si l'editeur a accepter d'editer la primitive, false sinon
*/
bool ArcEditor::setPart(CustomElementPart *new_part) {
if (!new_part) {
part = 0;
style_ -> setPart(0);
return(true);
}
if (PartArc *part_arc = dynamic_cast<PartArc *>(new_part)) {
part = part_arc;
style_ -> setPart(part);
updateForm();
return(true);
} else {
return(false);
}
}
/**
@return la primitive actuellement editee, ou 0 si ce widget n'en edite pas
*/
CustomElementPart *ArcEditor::currentPart() const {
return(part);
}
/**
Met a jour l'arc a partir a partir des donnees du formulaire
*/
void ArcEditor::updateArc() {
if (!part) return;
part -> setProperty("x", x -> text().toDouble());
part -> setProperty("y", y -> text().toDouble());
part -> setProperty("diameter_h", h -> text().toDouble());
part -> setProperty("diameter_v", v -> text().toDouble());
part -> setProperty("start_angle", -start_angle -> value() + 90);
part -> setProperty("angle", -angle -> value());
part -> setProperty("x", x -> text().toDouble());
part -> setProperty("y", y -> text().toDouble());
part -> setProperty("diameter_h", h -> text().toDouble());
part -> setProperty("diameter_v", v -> text().toDouble());
part -> setStartAngle(-start_angle -> value() + 90);
part -> setAngle(-angle -> value());
}
/// Met a jour l'abscisse du centre de l'arc et cree un objet d'annulation
@@ -135,7 +95,6 @@ void ArcEditor::updateArcA() { addChangePartCommand(tr("angle"),
Met a jour le formulaire d'edition
*/
void ArcEditor::updateForm() {
if (!part) return;
activeConnections(false);
x -> setText(part -> property("x").toString());
y -> setText(part -> property("y").toString());

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,31 +20,26 @@
#include <QtGui>
#include "elementitemeditor.h"
class PartArc;
class StyleEditor;
/**
This class provides a widget to edit elliptical arcs within the element editor.
Cette classe represente le widget d'edition d'un arc dans l'editeur
d'element.
*/
class ArcEditor : public ElementItemEditor {
Q_OBJECT
// constructors, destructor
//constructeurs, destructeur
public:
ArcEditor(QETElementEditor *, PartArc * = 0, QWidget * = 0);
virtual ~ArcEditor();
ArcEditor(QETElementEditor *, PartArc *, QWidget * = 0);
~ArcEditor();
private:
ArcEditor(const ArcEditor &);
// attributes
// attributs
private:
PartArc *part;
StyleEditor *style_;
QLineEdit *x, *y, *h, *v;
QSpinBox *angle, *start_angle;
// methods
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
// methodes
public slots:
void updateArc();
void updateArcX();

99
editor/circleeditor.cpp Normal file
View File

@@ -0,0 +1,99 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "circleeditor.h"
#include "partcircle.h"
/**
Constructeur
@param editor L'editeur d'element concerne
@param circle Le cercle a editer
@param parent le Widget parent
*/
CircleEditor::CircleEditor(QETElementEditor *editor, PartCircle *circle, QWidget *parent) : ElementItemEditor(editor, parent) {
part = circle;
x = new QLineEdit();
y = new QLineEdit();
r = new QLineEdit();
x -> setValidator(new QDoubleValidator(x));
y -> setValidator(new QDoubleValidator(y));
r -> setValidator(new QDoubleValidator(r));
QGridLayout *grid = new QGridLayout(this);
grid -> addWidget(new QLabel(tr("Centre : ")), 0, 0);
grid -> addWidget(new QLabel("x"), 1, 0);
grid -> addWidget(x, 1, 1);
grid -> addWidget(new QLabel("y"), 1, 2);
grid -> addWidget(y, 1, 3);
grid -> addWidget(new QLabel(tr("Diam\350tre : ")), 2, 0);
grid -> addWidget(r, 2, 1);
activeConnections(true);
updateForm();
}
/// Destructeur
CircleEditor::~CircleEditor() {
}
/**
met a jour le cercle a partir des donnees du formulaire
*/
void CircleEditor::updateCircle() {
part -> setProperty("x", x -> text().toDouble());
part -> setProperty("y", y -> text().toDouble());
part -> setProperty("diameter", r -> text().toDouble());
}
/// Met a jour l'abscisse du cercle et cree un objet d'annulation
void CircleEditor::updateCircleX() { addChangePartCommand(tr("abscisse"), part, "x", x -> text().toDouble()); }
/// Met a jour l'ordonnee du cercle et cree un objet d'annulation
void CircleEditor::updateCircleY() { addChangePartCommand(tr("ordonn\351e"), part, "y", y -> text().toDouble()); }
/// Met a jour le diametre du cercle et cree un objet d'annulation
void CircleEditor::updateCircleD() { addChangePartCommand(tr("diam\350tre"), part, "diameter", r -> text().toDouble()); }
/**
Met a jour le formulaire d'edition
*/
void CircleEditor::updateForm() {
activeConnections(false);
x -> setText(part -> property("x").toString());
y -> setText(part -> property("y").toString());
r -> setText(part -> property("diameter").toString());
activeConnections(true);
}
/**
Active ou desactive les connexionx signaux/slots entre les widgets internes.
@param active true pour activer les connexions, false pour les desactiver
*/
void CircleEditor::activeConnections(bool active) {
if (active) {
connect(x, SIGNAL(editingFinished()), this, SLOT(updateCircleX()));
connect(y, SIGNAL(editingFinished()), this, SLOT(updateCircleY()));
connect(r, SIGNAL(editingFinished()), this, SLOT(updateCircleD()));
} else {
disconnect(x, SIGNAL(editingFinished()), this, SLOT(updateCircleX()));
disconnect(y, SIGNAL(editingFinished()), this, SLOT(updateCircleY()));
disconnect(r, SIGNAL(editingFinished()), this, SLOT(updateCircleD()));
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -15,41 +15,36 @@
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RECTANGLE_EDITOR_H
#define RECTANGLE_EDITOR_H
#ifndef CIRCLE_EDITOR_H
#define CIRCLE_EDITOR_H
#include <QtGui>
#include "elementitemeditor.h"
class PartRectangle;
class StyleEditor;
class PartCircle;
/**
This class provides a widget to edit rectangles within the element editor.
Cette classe represente un editeur de cercle.
Elle permet d'editer a travers une interface graphique les
proprietes d'une cercle composant le dessin d'un element.
*/
class RectangleEditor : public ElementItemEditor {
class CircleEditor : public ElementItemEditor {
Q_OBJECT
// constructors, destructor
// Constructeurs, destructeur
public:
RectangleEditor(QETElementEditor *, PartRectangle * = 0, QWidget * = 0);
virtual ~RectangleEditor();
CircleEditor(QETElementEditor *, PartCircle *, QWidget * = 0);
virtual ~CircleEditor();
private:
RectangleEditor(const RectangleEditor &);
CircleEditor(const CircleEditor &);
// attributes
// attributs
private:
PartRectangle *part;
StyleEditor *style_;
QLineEdit *x, *y, *w, *h;
// methods
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
PartCircle *part;
QLineEdit *x, *y, *r;
// methodes
public slots:
void updateRectangle();
void updateRectangleX();
void updateRectangleY();
void updateRectangleW();
void updateRectangleH();
void updateCircle();
void updateCircleX();
void updateCircleY();
void updateCircleD();
void updateForm();
private:

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -27,8 +27,6 @@ void CustomElementGraphicPart::stylesToXml(QDomElement &qde) const {
css_like_styles += "line-style:";
if (_linestyle == DashedStyle) css_like_styles += "dashed";
if (_linestyle == DottedStyle) css_like_styles += "dotted";
if (_linestyle == DashdottedStyle)css_like_styles += "dashdotted";
else if (_linestyle == NormalStyle) css_like_styles += "normal";
css_like_styles += ";line-weight:";
@@ -40,17 +38,10 @@ void CustomElementGraphicPart::stylesToXml(QDomElement &qde) const {
if (_filling == NoneFilling) css_like_styles += "none";
else if (_filling == BlackFilling) css_like_styles += "black";
else if (_filling == WhiteFilling) css_like_styles += "white";
else if (_filling == GreenFilling) css_like_styles += "green";
else if (_filling == BlueFilling) css_like_styles += "blue";
else if (_filling == RedFilling) css_like_styles += "red";
css_like_styles += ";color:";
if (_color == WhiteColor) css_like_styles += "white";
else if (_color == BlackColor) css_like_styles += "black";
else if (_color == GreenColor) css_like_styles += "green";
else if (_color == RedColor) css_like_styles += "red";
else if (_color == BlueColor) css_like_styles += "blue";
qde.setAttribute("style", css_like_styles);
qde.setAttribute("antialias", _antialiased ? "true" : "false");
@@ -74,7 +65,6 @@ void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde) {
QString style_value = rx.cap(2);
if (style_name == "line-style") {
if (style_value == "dashed") _linestyle = DashedStyle;
if (style_value == "dotted") _linestyle = DottedStyle;
else if (style_value == "normal") _linestyle = NormalStyle;
// il n'y a pas de else car les valeurs non conformes sont ignorees (idem par la suite)
} else if (style_name == "line-weight") {
@@ -84,21 +74,18 @@ void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde) {
} else if (style_name == "filling") {
if (style_value == "white") _filling = WhiteFilling;
else if (style_value == "black") _filling = BlackFilling;
else if (style_value == "red") _filling = RedFilling;
else if (style_value == "green") _filling = GreenFilling;
else if (style_value == "blue") _filling = BlueFilling;
else if (style_value == "none") _filling = NoneFilling;
} else if (style_name == "color") {
if (style_value == "black") _color = BlackColor;
else if (style_value == "white") _color = WhiteColor;
else if (style_value == "green") _color = GreenColor;
else if (style_value == "red") _color = RedColor;
else if (style_value == "blue") _color = BlueColor;
}
}
// recupere l'antialiasing
_antialiased = qde.attribute("antialias") == "true";
// met a jour l'editeur de style
style_editor -> updateForm();
}
/**
@@ -123,8 +110,6 @@ void CustomElementGraphicPart::applyStylesToQPainter(QPainter &painter) const {
// applique le style de trait
if (_linestyle == DashedStyle) pen.setStyle(Qt::DashLine);
if (_linestyle == DashdottedStyle) pen.setStyle(Qt::DashDotLine);
if (_linestyle == DottedStyle) pen.setStyle(Qt::DotLine);
else if (_linestyle == NormalStyle) pen.setStyle(Qt::SolidLine);
// applique l'epaisseur de trait
@@ -141,23 +126,11 @@ void CustomElementGraphicPart::applyStylesToQPainter(QPainter &painter) const {
} else if (_filling == WhiteFilling) {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::white);
} else if (_filling == GreenFilling) {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::green);
} else if (_filling == RedFilling) {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::red);
} else if (_filling == BlueFilling) {
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::blue);
}
// applique la couleur de trait
if (_color == WhiteColor) pen.setColor(QColor(255, 255, 255, pen.color().alpha()));
else if (_color == BlackColor) pen.setColor(QColor( 0, 0, 0, pen.color().alpha()));
else if (_color == GreenColor) pen.setColor(QColor(Qt::green));
else if (_color == RedColor) pen.setColor(QColor(Qt::red));
else if (_color == BlueColor) pen.setColor(QColor(Qt::blue));
// applique l'antialiasing
@@ -169,6 +142,13 @@ void CustomElementGraphicPart::applyStylesToQPainter(QPainter &painter) const {
painter.setBrush(brush);
}
/**
@return Le widget permettant d'editer les styles
*/
QWidget *CustomElementGraphicPart::elementInformations() {
return(style_editor);
}
/**
Specifie la valeur d'une propriete de style donnee.
@param property propriete a modifier. Valeurs acceptees :
@@ -180,16 +160,25 @@ void CustomElementGraphicPart::applyStylesToQPainter(QPainter &painter) const {
@param value Valeur a attribuer a la propriete
*/
void CustomElementGraphicPart::setProperty(const QString &property, const QVariant &value) {
bool change_made = false;
if (property == "line-style") {
setLineStyle(static_cast<LineStyle>(value.toInt()));
change_made = true;
} else if (property == "line-weight") {
setLineWeight(static_cast<LineWeight>(value.toInt()));
change_made = true;
} else if (property == "filling") {
setFilling(static_cast<Filling>(value.toInt()));
change_made = true;
} else if (property == "color") {
setColor(static_cast<Color>(value.toInt()));
change_made = true;
} else if (property == "antialias") {
setAntialiased(value.toBool());
change_made = true;
}
if (change_made) {
style_editor -> updateForm();
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -23,50 +23,43 @@
class QETElementEditor;
typedef CustomElementGraphicPart CEGP;
/**
This class represents an element visual/geometric primitive. It provides
methods to manage style attributes common to most primitives.
Cette classe represente une partie graphique d'element
Elle encapsule des methodes afin de gerer les attributs de style communs
a la plupart des parties d'elements
*/
class CustomElementGraphicPart : public CustomElementPart {
public:
/// This enum lists the various line styles available to draw primitives.
/// Qualifie le style de ligne utilise pour dessiner la partie
enum LineStyle {
NormalStyle, ///< Normal line
DashedStyle, ///< Dashed line
DottedStyle, ///< Dotted line
DashdottedStyle ///< Dashdotted line
NormalStyle, ///< Ligne pleine
DashedStyle ///< Ligne pointillee
};
/// This enum lists the various line weights available to draw primitives.
/// Qualifie l'epaisseur de ligne utilisee pour dessiner la partie
enum LineWeight {
NormalWeight, ///< Normal line
ThinWeight, ///< Thin line
NoneWeight ///< Invisible line
NormalWeight, ///< Ligne normale
ThinWeight, ///< Ligne fine
NoneWeight ///< Ligne invisible
};
/// This enum lists the various filling colors available to draw primitives.
/// Qualifie la couleur utilisee pour remplir la partie
enum Filling {
NoneFilling, ///< No filling (i.e. transparent)
BlackFilling, ///< Black filling
WhiteFilling, ///< White filling
GreenFilling, ///< Green filling
RedFilling, ///< Red filling
BlueFilling ///< Green filling
NoneFilling, ///< Remplissage transparent
BlackFilling, ///< Remplissage en noir
WhiteFilling ///< Remplissage en blanc
};
/// This enum lists the various line colors available to draw primitives.
/// Qualifie la couleur de ligne utilisee pour dessiner la partie
enum Color {
BlackColor, ///< Black line
WhiteColor, ///< White line
GreenColor, ///< Green line
RedColor, ///< Red line
BlueColor ///< Blue line
BlackColor, ///< Ligne noire
WhiteColor ///< Ligne blanche
};
// constructors, destructor
// constructeurs, destructeur
public:
/**
Constructor
@param editor Element editor this primitive lives in.
Constructeur
@param editor Editeur d'element auquel cette partie est rattachee
*/
CustomElementGraphicPart(QETElementEditor *editor) :
CustomElementPart(editor),
@@ -76,13 +69,15 @@ class CustomElementGraphicPart : public CustomElementPart {
_color(BlackColor),
_antialiased(false)
{
style_editor = new StyleEditor(elementEditor(), this);
};
/// Destructor
/// Destructeur
virtual ~CustomElementGraphicPart() {
delete style_editor;
};
// attributes
// attributs
private:
LineStyle _linestyle;
LineWeight _lineweight;
@@ -90,7 +85,11 @@ class CustomElementGraphicPart : public CustomElementPart {
Color _color;
bool _antialiased;
// methods
protected:
/// Widget d'edition des styles de cette partie graphique
StyleEditor *style_editor;
//methodes
public:
void setLineStyle(LineStyle);
void setLineWeight(LineWeight);
@@ -104,6 +103,7 @@ class CustomElementGraphicPart : public CustomElementPart {
Color color() const;
bool antialiased() const;
QWidget *elementInformations();
void setProperty(const QString &, const QVariant &);
QVariant property(const QString &);
@@ -115,75 +115,75 @@ class CustomElementGraphicPart : public CustomElementPart {
};
/**
Set the primitive line style.
@param ls the new line style
Change le style de trait
@param ls Le nouveau style de trait
*/
inline void CustomElementGraphicPart::setLineStyle(LineStyle ls) {
_linestyle = ls;
}
/**
Set the primitive line weight.
@param lw the new line weight
Change l'epaisseur de trait
@param lw La nouvelle epaisseur de trait
*/
inline void CustomElementGraphicPart::setLineWeight(LineWeight lw) {
_lineweight = lw;
}
/**
Set the filling color.
@param f the new filling color
Change la couleur de remplissage
@param f La nouvelle couleur de remplissage
*/
inline void CustomElementGraphicPart::setFilling(Filling f) {
_filling = f;
}
/**
Set the line color.
@param c the new line color
Change la couleur de trait
@param c La nouvelle couleur de trait
*/
inline void CustomElementGraphicPart::setColor(Color c) {
_color = c;
}
/**
@return the current line style
@return Le style de trait
*/
inline CustomElementGraphicPart::LineStyle CustomElementGraphicPart::lineStyle() const {
return(_linestyle);
}
/**
@return the current line weight
@return L'epaisseur de trait
*/
inline CustomElementGraphicPart::LineWeight CustomElementGraphicPart::lineWeight() const {
return(_lineweight);
}
/**
@return the current filling color
@return La couleur de remplissage
*/
inline CustomElementGraphicPart::Filling CustomElementGraphicPart::filling() const {
return(_filling);
}
/**
@return the current line color
@return La couleur de trait
*/
inline CustomElementGraphicPart::Color CustomElementGraphicPart::color() const {
return(_color);
}
/**
Set whether the primitive should be drawn antialiased.
@param aa True to enable antialiasing, false to disable it.
Definit si la partie doit etre antialiasee ou non
@param aa True pour activer l'antialiasing, false pour le desactiver
*/
inline void CustomElementGraphicPart::setAntialiased(bool aa) {
_antialiased = aa;
}
/**
@return whether the primitive is drawn antialiased.
@return true si la partie est antialiasee, false sinon
*/
inline bool CustomElementGraphicPart::antialiased() const {
return(_antialiased);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2012 Xavier Guerrin
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -15,22 +15,21 @@
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TITLEBLOCK_SLASH_DIMENSION_H
#define TITLEBLOCK_SLASH_DIMENSION_H
#include "qet.h"
#include "customelementpart.h"
#include "customelement.h"
#include "qetelementeditor.h"
/**
This struct is a simple container associating a length with its type.
@see TitleBlockColumnLength
*/
struct TitleBlockDimension {
// constructor
TitleBlockDimension(int, QET::TitleBlockColumnLength = QET::Absolute);
// methods
QString toString() const;
QString toShortString() const;
// attribute
QET::TitleBlockColumnLength type; ///< Kind of length
int value; ///< Numeric value
};
#endif
/// @return le QETElementEditor auquel cet editeur appartient
QETElementEditor *CustomElementPart::elementEditor() const {
return(element_editor);
}
/// @return l'ElementScene contenant les parties editees par cet editeur
ElementScene *CustomElementPart::elementScene() const {
return(element_editor -> elementScene());
}
/// @return la QUndoStack a utiliser pour les annulations
QUndoStack &CustomElementPart::undoStack() const {
return(elementScene() -> undoStack());
}

View File

@@ -0,0 +1,87 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CUSTOM_ELEMENT_PART_H
#define CUSTOM_ELEMENT_PART_H
#include <QtGui>
#include <QtXml>
#include <QImage>
class CustomElement;
class QETElementEditor;
class ElementScene;
/**
Cette classe abstraite represente une partie de la representation graphique
d'un element de schema electrique. Les attributs et methodes qu'elle
encapsule ne sont pas integres directement dans la classe CustomElement
afin de ne pas alourdir celle-ci. Il est en effet inutile pour cette classe
de retenir sa conception graphique autrement que sous la forme d'une
QImage.
*/
class CustomElementPart {
// constructeurs, destructeur
public:
/**
Constructeur
@param editor Editeur d'element auquel cette partie est rattachee
*/
CustomElementPart(QETElementEditor *editor) : element_editor(editor) {}
/// Destructeur
virtual ~CustomElementPart() {}
private:
CustomElementPart(const CustomElementPart &);
// attributs
private:
QETElementEditor *element_editor;
// methodes
public:
/**
Charge la partie depuis un element XML sense le decrire
*/
virtual void fromXml(const QDomElement &) = 0;
/**
Enregistre la partie dans un document XML
*/
virtual const QDomElement toXml(QDomDocument &) const = 0;
/// @return un widget suppose decrire et/ou permettre de modifier la partie
virtual QWidget *elementInformations() = 0;
/**
Permet de modifier une des proprietes de la partie
*/
virtual void setProperty(const QString &, const QVariant &) = 0;
/**
Permet de lire une des proprietes de la partie
*/
virtual QVariant property(const QString &) = 0;
/**
@return true si la partie n'est pas pertinente, false sinon
Typiquement, une partie non pertinente n'est pas conservee lors de
l'enregistrement de l'element.
*/
virtual bool isUseless() const = 0;
/// @return un pointeur vers l'editeur d'element parent
virtual QETElementEditor *elementEditor() const;
/// @return un pointeur vers la scene d'edition parente
virtual ElementScene *elementScene() const;
/// @return la pile d'annulations a utiliser
virtual QUndoStack &undoStack() const;
/// @return le nom de la partie
virtual QString name() const = 0;
};
#endif

504
editor/editorcommands.cpp Normal file
View File

@@ -0,0 +1,504 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "editorcommands.h"
/*** DeletePartsCommand ***/
/**
Constructeur
@param scene ElementScene concernee
@param parts Liste des parties supprimees
@param parent QUndoCommand parent
*/
DeletePartsCommand::DeletePartsCommand(
ElementScene *scene,
const QList<QGraphicsItem *> parts,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("suppression"), parent),
deleted_parts(parts),
editor_scene(scene)
{
foreach(QGraphicsItem *qgi, deleted_parts) {
editor_scene -> qgiManager().manage(qgi);
}
}
/// Destructeur : detruit egalement les parties supprimees
DeletePartsCommand::~DeletePartsCommand() {
foreach(QGraphicsItem *qgi, deleted_parts) {
editor_scene -> qgiManager().release(qgi);
}
}
/// Restaure les parties supprimees
void DeletePartsCommand::undo() {
foreach(QGraphicsItem *qgi, deleted_parts) {
editor_scene -> addItem(qgi);
}
}
/// Supprime les parties
void DeletePartsCommand::redo() {
foreach(QGraphicsItem *qgi, deleted_parts) {
editor_scene -> removeItem(qgi);
}
}
/*** MovePartsCommand ***/
/**
Constructeur
@param m Mouvement sous forme de QPointF
@param scene ElementScene concernee
@param parts Liste des parties deplacees
@param parent QUndoCommand parent
*/
MovePartsCommand::MovePartsCommand(
const QPointF &m,
ElementScene *scene,
const QList<QGraphicsItem *> parts,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("d\351placement"), parent),
movement(m),
first_redo(true)
{
moved_parts = parts;
editor_scene = scene;
}
/// Destructeur
MovePartsCommand::~MovePartsCommand() {
}
/// Annule le deplacement
void MovePartsCommand::undo() {
foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(-movement.x(), -movement.y());
}
/// Refait le deplacement
void MovePartsCommand::redo() {
// le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire
if (first_redo) {
first_redo = false;
return;
}
foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(movement.x(), movement.y());
}
/*** AddPartCommand ***/
/**
Constructeur
@param name Nom de la partie ajoutee
@param scene ElementScene concernee
@param p partie ajoutee
@param parent QUndoCommand parent
*/
AddPartCommand::AddPartCommand(
const QString &name,
ElementScene *scene,
QGraphicsItem *p,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("ajout ") + name, parent),
part(p),
editor_scene(scene),
first_redo(true)
{
editor_scene -> qgiManager().manage(part);
}
/// Destructeur
AddPartCommand::~AddPartCommand() {
editor_scene -> qgiManager().release(part);
}
/// Annule l'ajout
void AddPartCommand::undo() {
editor_scene -> removeItem(part);
}
/// Refait l'ajout
void AddPartCommand::redo() {
// le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire
if (first_redo) {
editor_scene -> clearSelection();
part -> setSelected(true);
first_redo = false;
return;
}
editor_scene -> addItem(part);
}
/**
Constructeur
@param name nom de la propriete modifiee
@param part partie modifiee
@param prop propriete modifiee
@param old_v ancienne valeur
@param new_v nouvelle valeur
@param parent qUndoCommand parent
*/
ChangePartCommand::ChangePartCommand(
const QString &name,
CustomElementPart *part,
const QString &prop,
const QVariant &old_v,
const QVariant &new_v,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("modification ") + name, parent),
cep(part),
property(prop),
old_value(old_v),
new_value(new_v)
{
}
/// Destructeur
ChangePartCommand::~ChangePartCommand() {
}
/// Annule le changement
void ChangePartCommand::undo() {
cep -> setProperty(property, old_value);
}
/// Refait le changement
void ChangePartCommand::redo() {
cep -> setProperty(property, new_value);
}
/**
Constructeur
@param p Polygone edite
@param o_points points avant le changement
@param n_points points apres le changement
@param parent QUndoCommand parent
*/
ChangePolygonPointsCommand::ChangePolygonPointsCommand(
PartPolygon *p,
const QVector<QPointF> &o_points,
const QVector<QPointF> &n_points,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("modification points polygone"), parent),
polygon(p),
old_points(o_points),
new_points(n_points)
{
}
/// Destructeur
ChangePolygonPointsCommand::~ChangePolygonPointsCommand() {
}
/// Annule le changement
void ChangePolygonPointsCommand::undo() {
polygon -> setPolygon(old_points);
}
/// Refait le changement
void ChangePolygonPointsCommand::redo() {
polygon -> setPolygon(new_points);
}
/**
Constructeur
@param element_scene Element edite
@param size_1 Dimensions de l'element avant le changement
@param size_2 Dimensions de l'element apres le changement
@param hotspot_1 Point de saisie de l'element avant le changement
@param hotspot_2 Point de saisie de l'element apres le changement
@param o Eventuel decalage a appliquer aux parties de l'element edite
@param parent QUndoCommand parent
*/
ChangeHotspotCommand::ChangeHotspotCommand(
ElementScene *element_scene,
const QSize &size_1,
const QSize &size_2,
const QPoint &hotspot_1,
const QPoint &hotspot_2,
const QPoint &o,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("modification dimensions/hotspot"), parent),
element(element_scene),
size_before(size_1),
size_after(size_2),
hotspot_before(hotspot_1),
hotspot_after(hotspot_2),
offset(o)
{
}
/// Destructeur
ChangeHotspotCommand::~ChangeHotspotCommand() {
}
/// Annule le changement
void ChangeHotspotCommand::undo() {
QRectF sc(element -> sceneContent());
element -> setWidth(size_before.width());
element -> setHeight(size_before.height());
element -> setHotspot(hotspot_before);
if (!offset.isNull()) applyOffset(-offset);
element -> update(element -> sceneContent().unite(sc));
}
/// Refait le changement
void ChangeHotspotCommand::redo() {
QRectF sc(element -> sceneContent());
element -> setWidth(size_after.width());
element -> setHeight(size_after.height());
element -> setHotspot(hotspot_after);
if (!offset.isNull()) applyOffset(offset);
element -> update(element -> sceneContent().unite(sc));
}
/**
Applique une translation aux parties de l'element edite
@param o Translation a appliquer
*/
void ChangeHotspotCommand::applyOffset(const QPointF &o) {
foreach(QGraphicsItem *qgi, element -> items()) {
qgi -> translate(o.x(), o.y());
}
}
/**
Constructeur
@param element_scene Element edite
@param before Listes des noms avant changement
@param after Listes des noms apres changement
@param parent QUndoCommand parent
*/
ChangeNamesCommand::ChangeNamesCommand(
ElementScene *element_scene,
const NamesList &before,
const NamesList &after,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("modification noms"), parent),
names_before(before),
names_after(after),
element(element_scene)
{
}
/// Destructeur
ChangeNamesCommand::~ChangeNamesCommand() {
}
/// Annule le changement
void ChangeNamesCommand::undo() {
element -> setNames(names_before);
}
/// Refait le changement
void ChangeNamesCommand::redo() {
element -> setNames(names_after);
}
/**
Constructeur
@param element_scene Element edite
@param before Orientations avant changement
@param after Orientations apres changement
@param parent QUndoCommand parent
*/
ChangeOrientationsCommand::ChangeOrientationsCommand(
ElementScene *element_scene,
const OrientationSet &before,
const OrientationSet &after,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("modification orientations"), parent),
ori_before(before),
ori_after(after),
element(element_scene)
{
}
/// Destructeur
ChangeOrientationsCommand::~ChangeOrientationsCommand() {
}
/// Annule le changement
void ChangeOrientationsCommand::undo() {
element -> setOrientations(ori_before);
}
/// Refait le changement
void ChangeOrientationsCommand::redo() {
element -> setOrientations(ori_after);
}
/**
Constructeur
@param elmt ElementScene concernee
@param o Option decrivant le type de traitement applique aux zValues des parties de l'element
@param parent QUndoCommand parent
*/
ChangeZValueCommand::ChangeZValueCommand(
ElementScene *elmt,
ChangeZValueCommand::Option o,
QUndoCommand *parent
) :
QUndoCommand(parent),
element(elmt),
option(o)
{
// recupere les parties de l'elements, sauf les bornes
QList<QGraphicsItem *> items_list = element -> zItems();
// prend un snapshot des zValues
foreach(QGraphicsItem *qgi, items_list) undo_hash.insert(qgi, qgi -> zValue());
// choisit le nom en fonction du traitement
if (option == BringForward) {
setText(QObject::tr("amener au premier plan"));
applyBringForward(items_list);
} else if (option == Raise) {
setText(QObject::tr("rapprocher"));
applyRaise(items_list);
} else if (option == Lower) {
setText(QObject::tr("\351loigner"));
applyLower(items_list);
} else if (option == SendBackward) {
setText(QObject::tr("envoyer au fond"));
applySendBackward(items_list);
}
}
/// Destructeur
ChangeZValueCommand::~ChangeZValueCommand() {
}
/// Annule les changements de zValue
void ChangeZValueCommand::undo() {
foreach(QGraphicsItem *qgi, undo_hash.keys()) qgi -> setZValue(undo_hash[qgi]);
}
/// Refait les changements de zValue
void ChangeZValueCommand::redo() {
foreach(QGraphicsItem *qgi, redo_hash.keys()) qgi -> setZValue(redo_hash[qgi]);
}
/**
Amene les elements selectionnes au premier plan
@param items_list Liste des elements (selectionnes et non selectionnes)
*/
void ChangeZValueCommand::applyBringForward(const QList<QGraphicsItem *> &items_list) {
QList<QGraphicsItem *> non_selected_items = items_list;
QList<QGraphicsItem *> selected_items;
foreach(QGraphicsItem *qgi, non_selected_items) {
if (qgi -> isSelected()) {
selected_items << qgi;
non_selected_items.removeAt(non_selected_items.indexOf(qgi));
}
}
int z = 1;
foreach(QGraphicsItem *qgi, non_selected_items) redo_hash.insert(qgi, z ++);
foreach(QGraphicsItem *qgi, selected_items) redo_hash.insert(qgi, z ++);
}
/**
Remonte les elements selectionnes d'un plan
@param items_list Liste des elements (selectionnes et non selectionnes)
*/
void ChangeZValueCommand::applyRaise(const QList<QGraphicsItem *> &items_list) {
QList<QGraphicsItem *> my_items_list = items_list;
for (int i = my_items_list.count() - 2 ; i >= 0 ; -- i) {
if (my_items_list[i] -> isSelected()) {
if (!my_items_list[i +1] -> isSelected()) {
my_items_list.swap(i, i + 1);
}
}
}
int z = 1;
foreach(QGraphicsItem *qgi, my_items_list) redo_hash.insert(qgi, z ++);
}
/**
Descend les elements selectionnes d'un plan
@param items_list Liste des elements (selectionnes et non selectionnes)
*/
void ChangeZValueCommand::applyLower(const QList<QGraphicsItem *> &items_list) {
QList<QGraphicsItem *> my_items_list = items_list;
for (int i = 1 ; i < my_items_list.count() ; ++ i) {
if (my_items_list[i] -> isSelected()) {
if (!my_items_list[i - 1] -> isSelected()) {
my_items_list.swap(i, i - 1);
}
}
}
int z = 1;
foreach(QGraphicsItem *qgi, my_items_list) redo_hash.insert(qgi, z ++);
}
/**
Envoie les elements selectionnes au fond
@param items_list Liste des elements (selectionnes et non selectionnes)
*/
void ChangeZValueCommand::applySendBackward(const QList<QGraphicsItem *> &items_list) {
QList<QGraphicsItem *> non_selected_items = items_list;
QList<QGraphicsItem *> selected_items;
foreach(QGraphicsItem *qgi, non_selected_items) {
if (qgi -> isSelected()) {
selected_items << qgi;
non_selected_items.removeAt(non_selected_items.indexOf(qgi));
}
}
int z = 1;
foreach(QGraphicsItem *qgi, selected_items) redo_hash.insert(qgi, z ++);
foreach(QGraphicsItem *qgi, non_selected_items) redo_hash.insert(qgi, z ++);
}
/**
Constructeur
@param elmt ElementScene concernee
@param allow true pour que les connexions internes soient acceptees, false sinon
@param parent QUndoCommand parent
*/
AllowInternalConnectionsCommand::AllowInternalConnectionsCommand(ElementScene *elmt, bool allow, QUndoCommand *parent) :
QUndoCommand(QObject::tr("modification connexions internes"), parent),
element(elmt),
ic(allow)
{
}
/// Destructeur
AllowInternalConnectionsCommand::~AllowInternalConnectionsCommand() {
}
/// Annule le changement d'autorisation pour les connexions internes
void AllowInternalConnectionsCommand::undo() {
element -> setInternalConnections(!ic);
}
/// Refait le changement d'autorisation pour les connexions internes
void AllowInternalConnectionsCommand::redo() {
element -> setInternalConnections(ic);
}

311
editor/editorcommands.h Normal file
View File

@@ -0,0 +1,311 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EDITOR_COMMANDS_H
#define EDITOR_COMMANDS_H
#include "customelementpart.h"
#include "partpolygon.h"
#include "elementscene.h"
#include "qgimanager.h"
#include <QtGui>
/**
Cette classe represente l'action de supprimer une ou plusieurs
parties lors de l'edition d'un element
*/
class DeletePartsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
DeletePartsCommand(ElementScene *, const QList<QGraphicsItem *>, QUndoCommand * = 0);
virtual ~DeletePartsCommand();
private:
DeletePartsCommand(const DeletePartsCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// Liste des parties supprimees
QList<QGraphicsItem *> deleted_parts;
/// scene sur laquelle se produisent les actions
ElementScene *editor_scene;
};
/**
Cette classe represente l'action de deplacer une ou plusieurs
parties lors de l'edition d'un element
*/
class MovePartsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
MovePartsCommand(const QPointF &, ElementScene *, const QList<QGraphicsItem *>, QUndoCommand * = 0);
virtual ~MovePartsCommand();
private:
MovePartsCommand(const MovePartsCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// Liste des parties supprimees
QList<QGraphicsItem *> moved_parts;
/// scene sur laquelle se produisent les actions
ElementScene *editor_scene;
/// translation appliquee
QPointF movement;
/// booleen pour eviter d'appeler redo() lors de la construction de l'objet
bool first_redo;
};
/**
Cette classe represente l'action d'ajouter une partie lors de l'edition
d'un element
*/
class AddPartCommand : public QUndoCommand {
// constructeurs, destructeur
public:
AddPartCommand(const QString &, ElementScene *, QGraphicsItem *, QUndoCommand * = 0);
virtual ~AddPartCommand();
private:
AddPartCommand(const AddPartCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// Liste des parties supprimees
QGraphicsItem *part;
/// scene sur laquelle se produisent les actions
ElementScene *editor_scene;
/// booleen pour eviter d'appeler redo() lors de la construction de l'objet
bool first_redo;
};
/**
Cette classe represente l'action de modifier une propriete d'une partie
lors de l'edition d'un element
*/
class ChangePartCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangePartCommand(const QString &, CustomElementPart *, const QString &, const QVariant &, const QVariant &, QUndoCommand * = 0);
virtual ~ChangePartCommand();
private:
ChangePartCommand(const ChangePartCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// Partie modifiee
CustomElementPart *cep;
/// Propriete modifiee
QString property;
/// ancienne valeur
QVariant old_value;
/// nouvelle valeur
QVariant new_value;
};
/**
Cette classe represente l'action de modifier les points composants un polygone
*/
class ChangePolygonPointsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangePolygonPointsCommand(PartPolygon *, const QVector<QPointF> &, const QVector<QPointF> &, QUndoCommand * = 0);
virtual ~ChangePolygonPointsCommand();
private:
ChangePolygonPointsCommand(const ChangePolygonPointsCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
/// Polygone modifie
PartPolygon *polygon;
/// anciens points
QVector<QPointF> old_points;
/// nouveaux points
QVector<QPointF> new_points;
};
/**
Cette classe represente l'action de modifier les dimensions et le point de saisie d'un element
*/
class ChangeHotspotCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangeHotspotCommand(ElementScene *, const QSize &, const QSize &, const QPoint &, const QPoint &, const QPoint & = QPoint(), QUndoCommand * = 0);
virtual ~ChangeHotspotCommand();
private:
ChangeHotspotCommand(const ChangeHotspotCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
private:
void applyOffset(const QPointF &);
// attributs
/// Element edite auquel il faut appliquer les modifications
ElementScene *element;
/// dimensions avant l'action
QSize size_before;
/// dimensions apres l'action
QSize size_after;
/// point de saisie avant l'action
QPoint hotspot_before;
/// point de saisie apres l'action
QPoint hotspot_after;
/// decalage a appliquer aux elements
QPoint offset;
};
/**
Cette classe represente l'action de changer les noms d'un element
*/
class ChangeNamesCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangeNamesCommand(ElementScene *, const NamesList &, const NamesList &, QUndoCommand * = 0);
virtual ~ChangeNamesCommand();
private:
ChangeNamesCommand(const ChangeNamesCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// Liste des noms avant changement
NamesList names_before;
/// Liste des noms apres changement
NamesList names_after;
/// Element edite auquel il faut appliquer les modifications
ElementScene *element;
};
/**
Cette classe represente l'action de changer les noms d'un element
*/
class ChangeOrientationsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
ChangeOrientationsCommand(ElementScene *, const OrientationSet &, const OrientationSet &, QUndoCommand * = 0);
virtual ~ChangeOrientationsCommand();
private:
ChangeOrientationsCommand(const ChangeOrientationsCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// Orientations avant changement
OrientationSet ori_before;
/// Orientations apres changement
OrientationSet ori_after;
/// Element edite auquel il faut appliquer les modifications
ElementScene *element;
};
/**
Cette classe represente l'action de changer les noms d'un element
*/
class ChangeZValueCommand : public QUndoCommand {
// constructeurs, destructeur
public:
/// Qualifie le type de changement de zValue
enum Option {
BringForward, ///< Amene la partie a l'avant-plan ; elle a alors la plus haute zValue
Raise, ///< Amene la partie un plan au-dessus ; la zValue de la partie est incrementee
Lower, ///< Envoie la partie un plan en-dessous ; la zValue de la partie est decrementee
SendBackward ///< Envoie la partie a l'arriere-plan ; elle a alors la plus faible zValue
};
ChangeZValueCommand(ElementScene *, Option, QUndoCommand * = 0);
virtual ~ChangeZValueCommand();
private:
ChangeZValueCommand(const ChangeZValueCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
private:
void applyBringForward(const QList<QGraphicsItem *> &);
void applyRaise(const QList<QGraphicsItem *> &);
void applyLower(const QList<QGraphicsItem *> &);
void applySendBackward(const QList<QGraphicsItem *> &);
// attributs
private:
/// zValues avant changement
QHash<QGraphicsItem *, qreal> undo_hash;
/// zValues apres changement
QHash<QGraphicsItem *, qreal> redo_hash;
/// Element edite auquel il faut appliquer les modifications
ElementScene *element;
/// type de traitement
Option option;
};
/**
Cette classe represente l'action d'autoriser ou non les connexions
internes pour un element.
*/
class AllowInternalConnectionsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
AllowInternalConnectionsCommand(ElementScene *, bool, QUndoCommand * = 0);
virtual ~AllowInternalConnectionsCommand();
private:
AllowInternalConnectionsCommand(const AllowInternalConnectionsCommand &);
// methodes
public:
virtual void undo();
virtual void redo();
// attributs
private:
/// Element edite auquel il faut appliquer les modifications
ElementScene *element;
/// autorisation des connexions internes apres modification
bool ic;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -47,23 +47,15 @@ QUndoStack &ElementItemEditor::undoStack() const {
/**
Ajoute une ChangePartCommand a l'UndoStack. L'ancienne valeur sera
automatiquement recuperee. A noter que cette methode ne fait rien si
l'ancienne valeur et la nouvelle sont egales ou encore si part vaut 0
automatiquement recuperee.
@param desc nom de la propriete modifiee
@param part partie modifiee
@param prop propriete modifiee
@param new_v nouvelle valeur
*/
void ElementItemEditor::addChangePartCommand(const QString &desc, CustomElementPart *part, const QString &prop, const QVariant &new_v) {
// ne fait rien si part vaut 0
if (!part) return;
// recupere l'ancienne valeur
QVariant old_v = part -> property(prop);
// ne fait rien si l'ancienne valeur et la nouvelle sont egales
if (old_v == new_v) return;
undoStack().push(
new ChangePartCommand(
desc + " " + element_type_name,
@@ -84,12 +76,3 @@ QString ElementItemEditor::elementTypeName() const {
void ElementItemEditor::setElementTypeName(const QString &name) {
element_type_name = name;
}
/**
Detache l'editeur de la primitive qu'il edite.
Equivaut a setPart(0)
@see setPart
*/
void ElementItemEditor::detach() {
setPart(0);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -22,20 +22,21 @@ class QETElementEditor;
class ElementScene;
class CustomElementPart;
/**
This is the base class for primitives editors within the element editor. It
provides methods to access the editor itself, the undo stack, the edition
scene and even a method to easily take a ChangePartCommand into account.
Cette classe est la classe de base pour les editeurs de aprties dans
l'editeur d'element. Elle fournit des methodes pour acceder facilement
a l'editeur, a la pile d'annulation, a la scene d'edition ou encore pour
ajouter facilement une annulation de type ChangePartCommand.
*/
class ElementItemEditor : public QWidget {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
ElementItemEditor(QETElementEditor *, QWidget * = 0);
virtual ~ElementItemEditor() {};
private:
ElementItemEditor(const ElementItemEditor &);
// methods
// methodes
public:
virtual QETElementEditor *elementEditor() const;
virtual ElementScene *elementScene() const;
@@ -43,12 +44,8 @@ class ElementItemEditor : public QWidget {
virtual void addChangePartCommand(const QString &, CustomElementPart *, const QString &, const QVariant &);
virtual QString elementTypeName() const;
virtual void setElementTypeName(const QString &);
virtual void detach();
virtual bool setPart(CustomElementPart *) = 0;
virtual CustomElementPart *currentPart() const = 0;
virtual void updateForm() = 0;
// attributes
// attributs
private:
QETElementEditor *element_editor;
QString element_type_name;

732
editor/elementscene.cpp Normal file
View File

@@ -0,0 +1,732 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "elementscene.h"
#include "qetelementeditor.h"
#include <cmath>
#include "partline.h"
#include "partellipse.h"
#include "partcircle.h"
#include "partpolygon.h"
#include "partterminal.h"
#include "parttext.h"
#include "parttextfield.h"
#include "partarc.h"
#include "hotspoteditor.h"
#include "editorcommands.h"
const int ElementScene::xGrid = 10;
const int ElementScene::yGrid = 10;
/**
Constructeur
@param editor L'editeur d'element concerne
@param parent le Widget parent
*/
ElementScene::ElementScene(QETElementEditor *editor, QObject *parent) :
QGraphicsScene(parent),
_width(3),
_height(7),
_hotspot(15, 35),
internal_connections(false),
qgi_manager(this),
element_editor(editor)
{
current_polygon = NULL;
undo_stack.setClean();
}
/// Destructeur
ElementScene::~ElementScene() {
}
/**
Passe la scene en mode "selection et deplacement de parties"
*/
void ElementScene::slot_move() {
behavior = Normal;
}
/**
Passe la scene en mode "ajout de ligne"
*/
void ElementScene::slot_addLine() {
behavior = Line;
}
/**
Passe la scene en mode "ajout de cercle"
*/
void ElementScene::slot_addCircle() {
behavior = Circle;
}
/**
Passe la scene en mode "ajout d'ellipse"
*/
void ElementScene::slot_addEllipse() {
behavior = Ellipse;
}
/**
Passe la scene en mode "ajout de polygone"
*/
void ElementScene::slot_addPolygon() {
behavior = Polygon;
}
/**
Passe la scene en mode "ajout de texte statique"
*/
void ElementScene::slot_addText() {
behavior = Text;
}
/**
Passe la scene en mode "ajout de borne"
*/
void ElementScene::slot_addTerminal() {
behavior = Terminal;
}
/**
Passe la scene en mode "ajout d'arc de cercle"
*/
void ElementScene::slot_addArc() {
behavior = Arc;
}
/**
Passe la scene en mode "ajout de champ de texte"
*/
void ElementScene::slot_addTextField() {
behavior = TextField;
}
/**
Gere les mouvements de la souris
@param e objet decrivant l'evenement
*/
void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
QRectF temp_rect;
qreal radius;
QPointF temp_point;
QPolygonF temp_polygon;
if (e -> buttons() & Qt::LeftButton) {
switch(behavior) {
case Line:
current_line -> setLine(QLineF(current_line -> line().p1(), e -> scenePos()));
break;
case Ellipse:
temp_rect = current_ellipse -> rect();
temp_rect.setBottomRight(e -> scenePos());
current_ellipse -> setRect(temp_rect);
break;
case Arc:
temp_rect = current_arc -> rect();
temp_rect.setBottomRight(e -> scenePos());
current_arc -> setRect(temp_rect);
break;
case Circle:
temp_rect = current_circle -> rect();
temp_point = e -> scenePos() - current_circle -> mapToScene(temp_rect.center());
radius = sqrt(pow(temp_point.x(), 2) + pow(temp_point.y(), 2));
temp_rect = QRectF(
temp_rect.center() - QPointF(radius, radius),
QSizeF(2.0 * radius, 2.0 * radius)
);
current_circle -> setRect(temp_rect);
break;
case Polygon:
if (current_polygon == NULL) break;
temp_polygon = current_polygon -> polygon();
temp_polygon.pop_back();
temp_polygon << e -> scenePos();
current_polygon -> setPolygon(temp_polygon);
break;
case Normal:
default:
QGraphicsScene::mouseMoveEvent(e);
}
} else if (behavior == Polygon && current_polygon != NULL) {
temp_polygon = current_polygon -> polygon();
temp_polygon.pop_back();
temp_polygon << e -> scenePos();
current_polygon -> setPolygon(temp_polygon);
} else QGraphicsScene::mouseMoveEvent(e);
}
/**
Gere les appuis sur les boutons de la souris
@param e objet decrivant l'evenement
*/
void ElementScene::mousePressEvent(QGraphicsSceneMouseEvent *e) {
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
QPolygonF temp_polygon;
if (e -> button() & Qt::LeftButton) {
switch(behavior) {
case Line:
current_line = new PartLine(element_editor, 0, this);
current_line -> setLine(QLineF(e -> scenePos(), e -> scenePos()));
break;
case Ellipse:
current_ellipse = new PartEllipse(element_editor, 0, this);
current_ellipse -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
current_ellipse -> setProperty("antialias", true);
break;
case Arc:
current_arc = new PartArc(element_editor, 0, this);
current_arc -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
current_arc -> setProperty("antialias", true);
break;
case Circle:
current_circle = new PartCircle(element_editor, 0, this);
current_circle -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
current_circle -> setProperty("antialias", true);
break;
case Polygon:
if (current_polygon == NULL) {
current_polygon = new PartPolygon(element_editor, 0, this);
temp_polygon = QPolygonF(0);
} else temp_polygon = current_polygon -> polygon();
// au debut, on insere deux points
if (!temp_polygon.count()) temp_polygon << e -> scenePos();
temp_polygon << e -> scenePos();
current_polygon -> setPolygon(temp_polygon);
break;
case Normal:
default:
QGraphicsScene::mousePressEvent(e);
if (!selectedItems().isEmpty()) fsi_pos = selectedItems().first() -> scenePos();
}
} else QGraphicsScene::mousePressEvent(e);
}
/**
Gere les relachements de boutons de la souris
@param e objet decrivant l'evenement
*/
void ElementScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
PartTerminal *terminal;
PartText *text;
PartTextField *textfield;
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
if (e -> button() & Qt::LeftButton) {
switch(behavior) {
case Line:
if (qgiManager().manages(current_line)) break;
undo_stack.push(new AddPartCommand(tr("ligne"), this, current_line));
emit(partsAdded());
break;
case Ellipse:
if (qgiManager().manages(current_ellipse)) break;
current_ellipse -> setRect(current_ellipse -> rect().normalized());
undo_stack.push(new AddPartCommand(tr("ellipse"), this, current_ellipse));
emit(partsAdded());
break;
case Arc:
if (qgiManager().manages(current_arc)) break;
current_arc-> setRect(current_arc -> rect().normalized());
undo_stack.push(new AddPartCommand(tr("arc"), this, current_arc));
emit(partsAdded());
break;
case Circle:
if (qgiManager().manages(current_circle)) break;
current_circle -> setRect(current_circle -> rect().normalized());
undo_stack.push(new AddPartCommand(tr("cercle"), this, current_circle));
emit(partsAdded());
break;
case Terminal:
terminal = new PartTerminal(element_editor, 0, this);
terminal -> setPos(e -> scenePos());
undo_stack.push(new AddPartCommand(tr("borne"), this, terminal));
emit(partsAdded());
break;
case Text:
text = new PartText(element_editor, 0, this);
text -> setPos(e -> scenePos());
undo_stack.push(new AddPartCommand(tr("texte"), this, text));
emit(partsAdded());
break;
case TextField:
textfield = new PartTextField(element_editor, 0, this);
textfield -> setPos(e -> scenePos());
undo_stack.push(new AddPartCommand(tr("champ de texte"), this, textfield));
emit(partsAdded());
break;
case Normal:
default:
QGraphicsScene::mouseReleaseEvent(e);
// detecte les deplacements de parties
if (!selectedItems().isEmpty()) {
QPointF movement = selectedItems().first() -> scenePos() - fsi_pos;
if (!movement.isNull()) {
undo_stack.push(new MovePartsCommand(movement, this, selectedItems()));
}
}
}
} else if (e -> button() & Qt::RightButton) {
if (behavior == Polygon) {
behavior = Normal;
undo_stack.push(new AddPartCommand(tr("polygone"), this, current_polygon));
current_polygon = NULL;
emit(partsAdded());
emit(needNormalMode());
} else QGraphicsScene::mouseReleaseEvent(e);
} else QGraphicsScene::mouseReleaseEvent(e);
}
/**
Dessine l'arriere-plan de l'editeur, cad la grille.
@param p Le QPainter a utiliser pour dessiner
@param r Le rectangle de la zone a dessiner
*/
void ElementScene::drawBackground(QPainter *p, const QRectF &r) {
p -> save();
// desactive tout antialiasing, sauf pour le texte
p -> setRenderHint(QPainter::Antialiasing, false);
p -> setRenderHint(QPainter::TextAntialiasing, true);
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
// dessine un fond blanc
p -> setPen(Qt::NoPen);
p -> setBrush(Qt::white);
p -> drawRect(r);
// encadre la zone dessinable de l'element
QRectF drawable_area(-_hotspot.x(), -_hotspot.y(), width(), height());
p -> setPen(Qt::black);
p -> setBrush(Qt::NoBrush);
p -> drawRect(drawable_area);
if (r.width() < 2500 && r.height() < 2500) {
// dessine les points de la grille
p -> setPen(Qt::black);
p -> setBrush(Qt::NoBrush);
qreal limite_x = r.x() + r.width();
qreal limite_y = r.y() + r.height();
int g_x = (int)ceil(r.x());
while (g_x % xGrid) ++ g_x;
int g_y = (int)ceil(r.y());
while (g_y % yGrid) ++ g_y;
for (int gx = g_x ; gx < limite_x ; gx += xGrid) {
for (int gy = g_y ; gy < limite_y ; gy += yGrid) {
p -> drawPoint(gx, gy);
}
}
}
p -> restore();
}
/**
Dessine l'arriere-plan de l'editeur, cad l'indicateur de hotspot.
@param p Le QPainter a utiliser pour dessiner
@param r Le rectangle de la zone a dessiner
*/
void ElementScene::drawForeground(QPainter *p, const QRectF &) {
p -> save();
// desactive tout antialiasing, sauf pour le texte
p -> setRenderHint(QPainter::Antialiasing, false);
p -> setRenderHint(QPainter::TextAntialiasing, true);
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
p -> setPen(Qt::red);
p -> setBrush(Qt::NoBrush);
p -> drawLine(QLineF(0.0, -_hotspot.y(), 0.0, height() - _hotspot.y()));
p -> drawLine(QLineF(-_hotspot.x(), 0.0, width() - _hotspot.x(), 0.0));
p -> restore();
}
/**
Exporte l'element en XML
@return un document XML decrivant l'element
*/
const QDomDocument ElementScene::toXml() const {
// document XML
QDomDocument xml_document;
// racine du document XML
QDomElement root = xml_document.createElement("definition");
root.setAttribute("type", "element");
root.setAttribute("width", QString("%1").arg(_width * 10));
root.setAttribute("height", QString("%1").arg(_height * 10));
root.setAttribute("hotspot_x", QString("%1").arg(_hotspot.x()));
root.setAttribute("hotspot_y", QString("%1").arg(_hotspot.y()));
root.setAttribute("orientation", ori.toString());
root.setAttribute("version", QET::version);
if (internal_connections) root.setAttribute("ic", "true");
// noms de l'element
root.appendChild(_names.toXml(xml_document));
QDomElement description = xml_document.createElement("description");
// description de l'element
foreach(QGraphicsItem *qgi, zItems(true)) {
if (CustomElementPart *ce = dynamic_cast<CustomElementPart *>(qgi)) {
if (ce -> isUseless()) continue;
description.appendChild(ce -> toXml(xml_document));
}
}
root.appendChild(description);
xml_document.appendChild(root);
return(xml_document);
}
/**
Lit un element depuis un document XML
@param xml_document un document XML decrivant l'element
*/
void ElementScene::fromXml(const QDomDocument &xml_document) {
QString error_message;
bool state = true;
// la racine est supposee etre une definition d'element
QDomElement root = xml_document.documentElement();
if (root.tagName() != "definition" || root.attribute("type") != "element") {
state = false;
error_message = tr("Ce document XML n'est pas une definition d'\351l\351ment.");
}
// dimensions et hotspot
if (state) {
// ces attributs doivent etre presents et valides
int w, h, hot_x, hot_y;
if (
!QET::attributeIsAnInteger(root, QString("width"), &w) ||\
!QET::attributeIsAnInteger(root, QString("height"), &h) ||\
!QET::attributeIsAnInteger(root, QString("hotspot_x"), &hot_x) ||\
!QET::attributeIsAnInteger(root, QString("hotspot_y"), &hot_y)
) {
state = false;
error_message = tr("Les dimensions ou le point de saisie ne sont pas valides.");
} else {
setWidth(w);
setHeight(h);
setHotspot(QPoint(hot_x, hot_y));
}
}
// orientations et connexions internes
if (state) {
internal_connections = (root.attribute("ic") == "true");
if (!ori.fromString(root.attribute("orientation"))) {
state = false;
error_message = tr("Les orientations ne sont pas valides.");
}
}
// extrait les noms de la definition XML
if (state) {
_names.fromXml(root);
}
// parcours des enfants de la definition : parties de l'element
if (state) {
for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
QDomElement elmts = node.toElement();
if (elmts.isNull()) continue;
if (elmts.tagName() == "description") {
// gestion de la description graphique de l'element
// = parcours des differentes parties du dessin
int z = 1;
for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
QDomElement qde = n.toElement();
if (qde.isNull()) continue;
CustomElementPart *cep;
if (qde.tagName() == "line") cep = new PartLine (element_editor, 0, this);
else if (qde.tagName() == "ellipse") cep = new PartEllipse (element_editor, 0, this);
else if (qde.tagName() == "circle") cep = new PartCircle (element_editor, 0, this);
else if (qde.tagName() == "polygon") cep = new PartPolygon (element_editor, 0, this);
else if (qde.tagName() == "terminal") cep = new PartTerminal (element_editor, 0, this);
else if (qde.tagName() == "text") cep = new PartText (element_editor, 0, this);
else if (qde.tagName() == "input") cep = new PartTextField(element_editor, 0, this);
else if (qde.tagName() == "arc") cep = new PartArc (element_editor, 0, this);
else continue;
if (QGraphicsItem *qgi = dynamic_cast<QGraphicsItem *>(cep)) qgi -> setZValue(z++);
cep -> fromXml(qde);
}
}
}
}
}
/**
@return un rectangle englobant toutes les parties ainsi que le
"bounding rect" de l'element
*/
QRectF ElementScene::sceneContent() const {
return(itemsBoundingRect().unite(QRectF(-_hotspot, QSizeF(width(), height()))));
}
/**
@return la pile d'annulations de cet editeur d'element
*/
QUndoStack &ElementScene::undoStack() {
return(undo_stack);
}
/**
@return le gestionnaire de QGraphicsItem de cet editeur d'element
*/
QGIManager &ElementScene::qgiManager() {
return(qgi_manager);
}
/**
Selectionne tout
*/
void ElementScene::slot_selectAll() {
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(true);
}
/**
Deselectionne tout
*/
void ElementScene::slot_deselectAll() {
clearSelection();
}
/**
Inverse la selection
*/
void ElementScene::slot_invertSelection() {
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(!qgi -> isSelected());
}
/**
Supprime les elements selectionnes
*/
void ElementScene::slot_delete() {
// verifie qu'il y a qqc de selectionne
QList<QGraphicsItem *> selected_items = selectedItems();
if (selected_items.isEmpty()) return;
// efface tout ce qui est selectionne
undo_stack.push(new DeletePartsCommand(this, selected_items));
emit(partsRemoved());
}
/**
Lance un dialogue pour editer les dimensions et le point de saisie
(hotspot) de l'element.
*/
void ElementScene::slot_editSizeHotSpot() {
// cree un dialogue
QDialog dialog_sh;
dialog_sh.setModal(true);
dialog_sh.setMinimumSize(400, 230);
dialog_sh.setWindowTitle(tr("\311diter la taille et le point de saisie"));
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog_sh);
// ajoute un HotspotEditor au dialogue
HotspotEditor *hotspot_editor = new HotspotEditor();
hotspot_editor -> setElementWidth(static_cast<uint>(width() / 10));
hotspot_editor -> setElementHeight(static_cast<uint>(height() / 10));
hotspot_editor -> setHotspot(hotspot());
hotspot_editor -> setOldHotspot(hotspot());
hotspot_editor -> setPartsRect(itemsBoundingRect());
hotspot_editor -> setPartsRectEnabled(true);
dialog_layout -> addWidget(hotspot_editor);
// ajoute deux boutons au dialogue
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog_layout -> addWidget(dialog_buttons);
connect(dialog_buttons, SIGNAL(accepted()), &dialog_sh, SLOT(accept()));
connect(dialog_buttons, SIGNAL(rejected()), &dialog_sh, SLOT(reject()));
// lance le dialogue
if (dialog_sh.exec() != QDialog::Accepted) return;
QSize new_size(hotspot_editor -> elementSize());
QSize old_size(width(), height());
QPoint new_hotspot(hotspot_editor -> hotspot());
QPoint old_hotspot(_hotspot);
if (new_size != old_size || new_hotspot != old_hotspot) {
undo_stack.push(new ChangeHotspotCommand(this, old_size, new_size, old_hotspot, new_hotspot, hotspot_editor -> offsetParts()));
}
}
/**
Lance un dialogue pour editer les noms de cete element
*/
void ElementScene::slot_editOrientations() {
// cree un dialogue
QDialog dialog_ori;
dialog_ori.setModal(true);
dialog_ori.setMinimumSize(400, 260);
dialog_ori.setWindowTitle(tr("\311diter les orientations"));
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog_ori);
// ajoute un champ explicatif au dialogue
QLabel *information_label = new QLabel(tr("L'orientation par d\351faut est l'orientation dans laquelle s'effectue la cr\351ation de l'\351l\351ment."));
information_label -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
information_label -> setWordWrap(true);
dialog_layout -> addWidget(information_label);
// ajoute un OrientationSetWidget au dialogue
OrientationSetWidget *ori_widget = new OrientationSetWidget();
ori_widget -> setOrientationSet(ori);
dialog_layout -> addWidget(ori_widget);
// ajoute une case a cocher pour les connexions internes
QCheckBox *ic_checkbox = new QCheckBox(tr("Autoriser les connexions internes"));
ic_checkbox -> setChecked(internal_connections);
dialog_layout -> addWidget(ic_checkbox);
dialog_layout -> addStretch();
// ajoute deux boutons au dialogue
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog_layout -> addWidget(dialog_buttons);
connect(dialog_buttons, SIGNAL(accepted()), &dialog_ori, SLOT(accept()));
connect(dialog_buttons, SIGNAL(rejected()), &dialog_ori, SLOT(reject()));
// lance le dialogue
if (dialog_ori.exec() == QDialog::Accepted) {
OrientationSet new_ori = ori_widget -> orientationSet();
if (new_ori != ori) {
undoStack().push(new ChangeOrientationsCommand(this, ori, new_ori));
}
if (ic_checkbox -> isChecked() != internal_connections) {
undoStack().push(new AllowInternalConnectionsCommand(this, ic_checkbox -> isChecked()));
}
}
}
/**
Lance un dialogue pour editer les noms de cet element
*/
void ElementScene::slot_editNames() {
// cree un dialogue
QDialog dialog;
dialog.setModal(true);
dialog.setMinimumSize(400, 330);
dialog.setWindowTitle(tr("\311diter les noms"));
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog);
// ajoute un champ explicatif au dialogue
QLabel *information_label = new QLabel(tr("Vous pouvez sp\351cifier le nom de l'\351l\351ment dans plusieurs langues."));
information_label -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
information_label -> setWordWrap(true);
dialog_layout -> addWidget(information_label);
// ajoute un NamesListWidget au dialogue
NamesListWidget *names_widget = new NamesListWidget();
names_widget -> setNames(_names);
dialog_layout -> addWidget(names_widget);
// ajoute deux boutons au dialogue
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog_layout -> addWidget(dialog_buttons);
connect(dialog_buttons, SIGNAL(accepted()), names_widget, SLOT(check()));
connect(names_widget, SIGNAL(inputChecked()), &dialog, SLOT(accept()));
connect(dialog_buttons, SIGNAL(rejected()), &dialog, SLOT(reject()));
// lance le dialogue
if (dialog.exec() == QDialog::Accepted) {
NamesList new_names(names_widget -> names());
if (new_names != _names) undoStack().push(new ChangeNamesCommand(this, _names, new_names));
}
}
/**
Amene les elements selectionnes au premier plan
*/
void ElementScene::slot_bringForward() {
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::BringForward));
emit(partsZValueChanged());
}
/**
Remonte les elements selectionnes d'un plan
*/
void ElementScene::slot_raise() {
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::Raise));
emit(partsZValueChanged());
}
/**
Descend les elements selectionnes d'un plan
*/
void ElementScene::slot_lower() {
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::Lower));
emit(partsZValueChanged());
}
/**
Envoie les elements selectionnes au fond
*/
void ElementScene::slot_sendBackward() {
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::SendBackward));
emit(partsZValueChanged());
}
/**
@param include_terminals true pour inclure les bornes, false sinon
@return les parties de l'element ordonnes par zValue croissante
*/
QList<QGraphicsItem *> ElementScene::zItems(bool include_terminals) const {
// recupere les elements
QList<QGraphicsItem *> all_items_list(items());
// enleve les bornes
QList<QGraphicsItem *> terminals;
foreach(QGraphicsItem *qgi, all_items_list) {
if (qgraphicsitem_cast<PartTerminal *>(qgi)) {
all_items_list.removeAt(all_items_list.indexOf(qgi));
terminals << qgi;
}
}
// ordonne les parties par leur zValue
QMultiMap<qreal, QGraphicsItem *> mm;
foreach(QGraphicsItem *qgi, all_items_list) mm.insert(qgi -> zValue(), qgi);
all_items_list.clear();
QMapIterator<qreal, QGraphicsItem *> i(mm);
while (i.hasNext()) {
i.next();
all_items_list << i.value();
}
// rajoute eventuellement les bornes
if (include_terminals) all_items_list += terminals;
return(all_items_list);
}
/**
Supprime les parties de l'element et les objets d'annulations.
Les autres caracteristiques sont conservees.
*/
void ElementScene::reset() {
// supprime les objets d'annulation
undoStack().clear();
// enleve les elements de la scene
foreach (QGraphicsItem *qgi, items()) {
removeItem(qgi);
qgiManager().release(qgi);
}
}

238
editor/elementscene.h Normal file
View File

@@ -0,0 +1,238 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ELEMENT_SCENE_H
#define ELEMENT_SCENE_H
#include <QtGui>
#include <QtXml>
#include "nameslistwidget.h"
#include "orientationsetwidget.h"
#include "qgimanager.h"
class QETElementEditor;
class PartLine;
class PartEllipse;
class PartCircle;
class PartPolygon;
class PartArc;
/**
Cette classe est le canevas permettant l'edition d'un element electrique.
Elle regroupe les differentes parties composant le dessin de l'element mais
egalement les informations complementaires : dimensions, orientations,
noms.
*/
class ElementScene : public QGraphicsScene {
Q_OBJECT
// enum
enum Behavior { Normal, Line, Circle, Ellipse, Polygon, Text, Terminal, Arc, TextField };
// constructeurs, destructeur
public:
ElementScene(QETElementEditor *, QObject * = 0);
virtual ~ElementScene();
private:
ElementScene(const ElementScene &);
// attributs
public:
static const int xGrid; ///< Taille horizontale de la grille
static const int yGrid; ///< Taille verticale de la grille
private:
/// longueur de l'element en dizaines de pixels
uint _width;
/// hauteur de l'element en dizaines de pixels
uint _height;
/// position du point de saisie
QPoint _hotspot;
/// Liste des noms de l'element
NamesList _names;
/// Liste des orientations de l'element
OrientationSet ori;
/// booleen indiquant si les bornes de l'element peuvent etre reliees a des bornes de ce meme element
bool internal_connections;
/// Gestionnaire de QGraphicsItem
QGIManager qgi_manager;
/// Pile des actions annulables
QUndoStack undo_stack;
/// Position du premier item selectionne (utilise pour annuler les deplacements)
QPointF fsi_pos;
/// Variables relatives a la gestion du dessin des parties sur la scene
Behavior behavior;
PartLine *current_line;
PartEllipse *current_ellipse;
PartCircle *current_circle;
PartPolygon *current_polygon;
PartArc *current_arc;
QETElementEditor *element_editor;
// methodes
public:
void setWidth(const uint &);
uint width() const;
void setHeight(const uint &);
uint height() const;
void setHotspot(const QPoint &);
QPoint hotspot() const;
void setNames(const NamesList &);
NamesList names() const;
OrientationSet orientations();
void setOrientations(const OrientationSet &);
bool internalConnections();
void setInternalConnections(bool);
virtual const QDomDocument toXml() const;
virtual void fromXml(const QDomDocument &);
virtual void reset();
virtual QList<QGraphicsItem *> zItems(bool = false) const;
QRectF sceneContent() const;
QUndoStack &undoStack();
QGIManager &qgiManager();
protected:
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
virtual void drawBackground(QPainter *, const QRectF &);
virtual void drawForeground(QPainter *, const QRectF &);
public slots:
void slot_move();
void slot_addLine();
void slot_addCircle();
void slot_addEllipse();
void slot_addPolygon();
void slot_addText();
void slot_addArc();
void slot_addTerminal();
void slot_addTextField();
void slot_selectAll();
void slot_deselectAll();
void slot_invertSelection();
void slot_delete();
void slot_editSizeHotSpot();
void slot_editNames();
void slot_editOrientations();
void slot_bringForward();
void slot_raise();
void slot_lower();
void slot_sendBackward();
signals:
/**
Signal emis lorsque la scene exige que l'editeur d'element repasse
en mode normal
*/
void needNormalMode();
/// Signal emis lorsqu'une ou plusieurs parties sont ajoutees
void partsAdded();
/// Signal emis lorsqu'une ou plusieurs parties sont enlevees
void partsRemoved();
/// Signal emis lorsque la zValue d'une ou plusieurs parties change
void partsZValueChanged();
};
/**
@param wid Nouvelle largeur de l'element edite
*/
inline void ElementScene::setWidth(const uint &wid) {
_width = wid;
while (_width % 10) ++ _width;
_width /= 10;
}
/**
@return la largeur de l'element edite
*/
inline uint ElementScene::width() const {
return(_width * 10);
}
/**
@param hei Nouvelle hauteur de l'element edite
*/
inline void ElementScene::setHeight(const uint &hei) {
_height = hei;
while (_height % 10) ++ _height;
_height /= 10;
}
/**
@return la largeur de l'element edite
*/
inline uint ElementScene::height() const {
return(_height * 10);
}
/**
@param hs Nouveau point de saisie de l'element edite
*/
inline void ElementScene::setHotspot(const QPoint &hs) {
_hotspot = hs;
}
/**
@return le point de saisie de l'element edite
*/
inline QPoint ElementScene::hotspot() const {
return(_hotspot);
}
/**
@param nameslist Nouvel ensemble de noms de l'element edite
*/
inline void ElementScene::setNames(const NamesList &nameslist) {
_names = nameslist;
}
/**
@return l'ensemble de noms de l'element edite
*/
inline NamesList ElementScene::names() const {
return(_names);
}
/**
@return l'ensemble d'orientations de l'element edite
*/
inline OrientationSet ElementScene::orientations() {
return(ori);
}
/**
@param orientation_set Nouvel ensemble d'orientations de l'element edite
*/
inline void ElementScene::setOrientations(const OrientationSet &orientation_set) {
ori = orientation_set;
}
/**
@return true si les connexions internes sont acceptees, false sinon
*/
inline bool ElementScene::internalConnections() {
return(internal_connections);
}
/**
@param ic true pour que les connexions internes soient acceptees, false sinon
*/
inline void ElementScene::setInternalConnections(bool ic) {
internal_connections = ic;
}
#endif

66
editor/elementview.cpp Normal file
View File

@@ -0,0 +1,66 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "elementview.h"
/**
Constructeur
@param scene ElementScene visualisee par cette ElementView
@param parent QWidget parent de cette ElementView
*/
ElementView::ElementView(ElementScene *scene, QWidget *parent) :
QGraphicsView(scene, parent),
scene_(scene)
{
setInteractive(true);
setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
//setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
//setSceneRect(QRectF(0.0, 0.0, 50.0, 200.0));
scale(4.0, 4.0);
}
/// Destructeur
ElementView::~ElementView() {
}
/// @return l'ElementScene visualisee par cette ElementView
ElementScene *ElementView::scene() const {
return(scene_);
}
/**
Definit l'ElementScene visualisee par cette ElementView
@param s l'ElementScene visualisee par cette ElementView
*/
void ElementView::setScene(ElementScene *s) {
QGraphicsView::setScene(s);
scene_ = s;
}
/**
Gere les evenements envoyes a la vue.
Methode reimplentee pour gerer le conflit de raccourcis avec Suppr
(supprimer une partie ou supprimer le caractere suivant)
@param e evenement a gerer
*/
bool ElementView::event(QEvent *e) {
if (e -> type() == QEvent::ShortcutOverride && scene_ -> focusItem()) {
e -> accept();
return(true);
}
return(QGraphicsView::event(e));
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2012 Xavier Guerrin
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -15,29 +15,33 @@
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TREE_COLOR_ANIMATION_H
#define TREE_COLOR_ANIMATION_H
#include <QtGui>
#ifndef ELEMENT_VIEW_H
#define ELEMENT_VIEW_H
#include <QGraphicsView>
#include "elementscene.h"
/**
This class allows animating a background color change for a
set of QTreeWidgetItem.
Cette classe represente un widget permettant de visualiser une
ElementScene, c'est-a-dire la classe d'edition des elements.
*/
class TreeColorAnimation : public QVariantAnimation {
// Constructors, destructor
class ElementView : public QGraphicsView {
Q_OBJECT
// constructeurs, destructeur
public:
TreeColorAnimation(const QList<QTreeWidgetItem *> &items, QObject * = 0);
virtual ~TreeColorAnimation();
ElementView(ElementScene *, QWidget * = 0);
virtual ~ElementView();
// methods
public:
QList<QTreeWidgetItem *> items() const;
protected:
void updateCurrentValue(const QVariant &);
// attributes
private:
QList<QTreeWidgetItem *> items_; ///< Items this object will animate
ElementView(const ElementView &);
// methodes
public:
ElementScene *scene() const;
void setScene(ElementScene *);
protected:
bool event(QEvent *);
//attributs
private:
ElementScene *scene_;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -16,7 +16,6 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ellipseeditor.h"
#include "styleeditor.h"
#include "partellipse.h"
/**
@@ -25,11 +24,9 @@
@param ellipse L'ellipse a editer
@param parent le Widget parent
*/
EllipseEditor::EllipseEditor(QETElementEditor *editor, PartEllipse *ellipse, QWidget *parent) :
ElementItemEditor(editor, parent),
part(ellipse)
{
style_ = new StyleEditor(editor);
EllipseEditor::EllipseEditor(QETElementEditor *editor, PartEllipse *ellipse, QWidget *parent) : ElementItemEditor(editor, parent) {
part = ellipse;
x = new QLineEdit();
y = new QLineEdit();
@@ -41,11 +38,9 @@ EllipseEditor::EllipseEditor(QETElementEditor *editor, PartEllipse *ellipse, QWi
h -> setValidator(new QDoubleValidator(h));
v -> setValidator(new QDoubleValidator(v));
QVBoxLayout *v_layout = new QVBoxLayout(this);
QGridLayout *grid = new QGridLayout();
QGridLayout *grid = new QGridLayout(this);
grid -> addWidget(new QLabel(tr("Centre : ")), 0, 0);
grid -> addWidget(new QLabel("x"), 1, 0, Qt::AlignRight);
grid -> addWidget(new QLabel("x"), 1, 0);
grid -> addWidget(x, 1, 1);
grid -> addWidget(new QLabel("y"), 1, 2);
grid -> addWidget(y, 1, 3);
@@ -55,9 +50,6 @@ EllipseEditor::EllipseEditor(QETElementEditor *editor, PartEllipse *ellipse, QWi
grid -> addWidget(new QLabel(tr("vertical :")), 4, 0);
grid -> addWidget(v, 4, 1);
v_layout -> addWidget(style_);
v_layout -> addLayout(grid);
activeConnections(true);
updateForm();
}
@@ -66,46 +58,14 @@ EllipseEditor::EllipseEditor(QETElementEditor *editor, PartEllipse *ellipse, QWi
EllipseEditor::~EllipseEditor() {
}
/**
Permet de specifier a cet editeur quelle primitive il doit editer. A noter
qu'un editeur peut accepter ou refuser d'editer une primitive.
L'editeur d'ellipse acceptera d'editer la primitive new_part s'il s'agit
d'un objet de la classe PartEllipse.
@param new_part Nouvelle primitive a editer
@return true si l'editeur a accepter d'editer la primitive, false sinon
*/
bool EllipseEditor::setPart(CustomElementPart *new_part) {
if (!new_part) {
part = 0;
style_ -> setPart(0);
return(true);
}
if (PartEllipse *part_ellipse = dynamic_cast<PartEllipse *>(new_part)) {
part = part_ellipse;
style_ -> setPart(part);
updateForm();
return(true);
} else {
return(false);
}
}
/**
@return la primitive actuellement editee, ou 0 si ce widget n'en edite pas
*/
CustomElementPart *EllipseEditor::currentPart() const {
return(part);
}
/**
Met a jour l'ellipse a partir des donnees du formulaire
*/
void EllipseEditor::updateEllipse() {
if (!part) return;
part -> setProperty("x", x -> text().toDouble());
part -> setProperty("y", y -> text().toDouble());
part -> setProperty("diameter_h", h -> text().toDouble());
part -> setProperty("diameter_v", v -> text().toDouble());
part -> setProperty("y", x -> text().toDouble());
part -> setProperty("diameter_h", x -> text().toDouble());
part -> setProperty("diameter_v", x -> text().toDouble());
}
/// Met a jour l'abscisse du centre de l'ellipse et cree un objet d'annulation
@@ -121,7 +81,6 @@ void EllipseEditor::updateEllipseV() { addChangePartCommand(tr("diam\350tre vert
Met a jour le formulaire d'edition
*/
void EllipseEditor::updateForm() {
if (!part) return;
activeConnections(false);
x -> setText(part -> property("x").toString());
y -> setText(part -> property("y").toString());

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,30 +20,25 @@
#include <QtGui>
#include "elementitemeditor.h"
class PartEllipse;
class StyleEditor;
/**
This class provides a widget to edit ellipses within the element editor.
Cette classe represente le widget d'edition d'une ellipse dans l'editeur
d'element.
*/
class EllipseEditor : public ElementItemEditor {
Q_OBJECT
// constructors, destructor
//constructeurs, destructeur
public:
EllipseEditor(QETElementEditor *, PartEllipse * = 0, QWidget * = 0);
virtual ~EllipseEditor();
EllipseEditor(QETElementEditor *, PartEllipse *, QWidget * = 0);
~EllipseEditor();
private:
EllipseEditor(const EllipseEditor &);
// attributes
// attributs
private:
PartEllipse *part;
StyleEditor *style_;
QLineEdit *x, *y, *h, *v;
// methods
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
// methodes
public slots:
void updateEllipse();
void updateEllipseX();

115
editor/lineeditor.cpp Normal file
View File

@@ -0,0 +1,115 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "lineeditor.h"
#include "partline.h"
/**
Constructeur
@param editor L'editeur d'element concerne
@param line La ligne a editer
@param parent le Widget parent
*/
LineEditor::LineEditor(QETElementEditor *editor, PartLine *line, QWidget *parent) : ElementItemEditor(editor, parent) {
part = line;
x1 = new QLineEdit();
y1 = new QLineEdit();
x2 = new QLineEdit();
y2 = new QLineEdit();
x1 -> setValidator(new QDoubleValidator(x1));
y1 -> setValidator(new QDoubleValidator(y1));
x2 -> setValidator(new QDoubleValidator(x2));
y2 -> setValidator(new QDoubleValidator(y2));
QGridLayout *grid = new QGridLayout(this);
grid -> addWidget(new QLabel("x1"), 0, 0);
grid -> addWidget(x1, 0, 1);
grid -> addWidget(new QLabel("y1"), 0, 2);
grid -> addWidget(y1, 0, 3);
grid -> addWidget(new QLabel("x2"), 1, 0);
grid -> addWidget(x2, 1, 1);
grid -> addWidget(new QLabel("y2"), 1, 2);
grid -> addWidget(y2, 1, 3);
updateForm();
}
/// Destructeur
LineEditor::~LineEditor() {
}
/**
Met a jour la ligne a partir des donnees du formulaire
*/
void LineEditor::updateLine() {
part -> setLine(
QLineF(
part -> mapFromScene(
x1 -> text().toDouble(),
y1 -> text().toDouble()
),
part -> mapFromScene(
x2 -> text().toDouble(),
y2 -> text().toDouble()
)
)
);
}
/// Met a jour l'abscisse du premier point de la ligne et cree un objet d'annulation
void LineEditor::updateLineX1() { addChangePartCommand(tr("abscisse point 1"), part, "x1", x1 -> text().toDouble()); }
/// Met a jour l'ordonnee du premier point de la ligne et cree un objet d'annulation
void LineEditor::updateLineY1() { addChangePartCommand(tr("ordonn\351e point 1"), part, "y1", y1 -> text().toDouble()); }
/// Met a jour l'abscisse du second point de la ligne et cree un objet d'annulation
void LineEditor::updateLineX2() { addChangePartCommand(tr("abscisse point 2"), part, "x2", x2 -> text().toDouble()); }
/// Met a jour l'ordonnee du second point de la ligne et cree un objet d'annulation
void LineEditor::updateLineY2() { addChangePartCommand(tr("ordonn\351e point 2"), part, "y2", y2 -> text().toDouble()); }
/**
Met a jour le formulaire d'edition
*/
void LineEditor::updateForm() {
activeConnections(false);
QPointF p1(part -> sceneP1());
QPointF p2(part -> sceneP2());
x1 -> setText(QString("%1").arg(p1.x()));
y1 -> setText(QString("%1").arg(p1.y()));
x2 -> setText(QString("%1").arg(p2.x()));
y2 -> setText(QString("%1").arg(p2.y()));
activeConnections(true);
}
/**
Active ou desactive les connexionx signaux/slots entre les widgets internes.
@param active true pour activer les connexions, false pour les desactiver
*/
void LineEditor::activeConnections(bool active) {
if (active) {
connect(x1, SIGNAL(editingFinished()), this, SLOT(updateLineX1()));
connect(y1, SIGNAL(editingFinished()), this, SLOT(updateLineY1()));
connect(x2, SIGNAL(editingFinished()), this, SLOT(updateLineX2()));
connect(y2, SIGNAL(editingFinished()), this, SLOT(updateLineY2()));
} else {
connect(x1, SIGNAL(editingFinished()), this, SLOT(updateLineX1()));
connect(y1, SIGNAL(editingFinished()), this, SLOT(updateLineY1()));
connect(x2, SIGNAL(editingFinished()), this, SLOT(updateLineX2()));
connect(y2, SIGNAL(editingFinished()), this, SLOT(updateLineY2()));
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,42 +20,31 @@
#include <QtGui>
#include "elementitemeditor.h"
class PartLine;
class StyleEditor;
/**
This class provides a widget to edit lines within the element editor.
Cette classe represente le widget d'edition d'une ligne dans l'editeur
d'element.
*/
class LineEditor : public ElementItemEditor {
Q_OBJECT
// constructors, destructor
//constructeurs, destructeur
public:
LineEditor(QETElementEditor *, PartLine * = 0, QWidget * = 0);
virtual ~LineEditor();
LineEditor(QETElementEditor *, PartLine *, QWidget * = 0);
~LineEditor();
private:
LineEditor(const LineEditor &);
// attributes
// attributs
private:
PartLine *part;
StyleEditor *style_;
QLineEdit *x1, *y1, *x2, *y2;
QComboBox *end1_type, *end2_type;
QLineEdit *end1_length, *end2_length;
// methods
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
// methodes
public slots:
void updateLine();
void updateLineX1();
void updateLineY1();
void updateLineX2();
void updateLineY2();
void updateLineEndType1();
void updateLineEndLength1();
void updateLineEndType2();
void updateLineEndLength2();
void updateForm();
private:

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -16,6 +16,7 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "partarc.h"
#include "arceditor.h"
/**
Constructeur
@@ -29,11 +30,12 @@ PartArc::PartArc(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene
_angle(-90),
start_angle(0)
{
setFlags(QGraphicsItem::ItemIsSelectable);
#if QT_VERSION >= 0x040600
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
#endif
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new ArcEditor(elementEditor(), this);
informations -> setElementTypeName(name());
style_editor -> appendWidget(informations);
style_editor -> setElementTypeName(name());
}
/// Destructeur
@@ -46,15 +48,11 @@ PartArc::~PartArc() {
@param options Options pour affiner le rendu
@param widget Widget sur lequel le rendu est effectue
*/
void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) {
Q_UNUSED(widget);
void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
applyStylesToQPainter(*painter);
// enleve systematiquement la couleur de fond
painter -> setBrush(Qt::NoBrush);
QPen t = painter -> pen();
t.setCosmetic(options && options -> levelOfDetail < 1.0);
painter -> setPen(t);
if (isSelected()) {
// dessine l'ellipse en noir
painter -> drawEllipse(rect());
@@ -63,7 +61,6 @@ void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options,
t.setColor(Qt::red);
painter -> setPen(t);
}
painter -> drawArc(rect(), start_angle * 16, _angle * 16);
if (isSelected()) {
// dessine la croix au centre de l'ellipse
@@ -83,12 +80,12 @@ void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options,
const QDomElement PartArc::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("arc");
QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", QString("%1").arg(top_left.x()));
xml_element.setAttribute("y", QString("%1").arg(top_left.y()));
xml_element.setAttribute("width", QString("%1").arg(rect().width()));
xml_element.setAttribute("height", QString("%1").arg(rect().height()));
xml_element.setAttribute("start", QString("%1").arg(start_angle));
xml_element.setAttribute("angle", QString("%1").arg(_angle));
xml_element.setAttribute("x", top_left.x());
xml_element.setAttribute("y", top_left.y());
xml_element.setAttribute("width", rect().width());
xml_element.setAttribute("height", rect().height());
xml_element.setAttribute("start", start_angle);
xml_element.setAttribute("angle", _angle);
stylesToXml(xml_element);
return(xml_element);
}
@@ -162,7 +159,6 @@ void PartArc::setProperty(const QString &property, const QVariant &value) {
} else if (property == "angle") {
setAngle(value.toInt());
}
update();
}
/**
@@ -204,8 +200,8 @@ QVariant PartArc::property(const QString &property) {
*/
QVariant PartArc::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemPositionHasChanged) {
updateCurrentPartEditor();
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsEllipseItem::itemChange(change, value));
@@ -255,41 +251,3 @@ int PartArc::startAngle() const {
bool PartArc::isUseless() const {
return(rect().isNull() || !angle());
}
/**
@return the minimum, margin-less rectangle this part can fit into, in scene
coordinates. It is different from boundingRect() because it is not supposed
to imply any margin, and it is different from shape because it is a regular
rectangle, not a complex shape.
*/
QRectF PartArc::sceneGeometricRect() const {
return(mapToScene(rect()).boundingRect());
}
/**
Start the user-induced transformation, provided this primitive is contained
within the \a initial_selection_rect bounding rectangle.
*/
void PartArc::startUserTransformation(const QRectF &initial_selection_rect) {
Q_UNUSED(initial_selection_rect)
saved_points_.clear();
saved_points_ << mapToScene(rect().topLeft()) << mapToScene(rect().bottomRight());
}
/**
Handle the user-induced transformation from \a initial_selection_rect to \a new_selection_rect
*/
void PartArc::handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect) {
QList<QPointF> mapped_points = mapPoints(initial_selection_rect, new_selection_rect, saved_points_);
setRect(QRectF(mapFromScene(mapped_points.at(0)), mapFromScene(mapped_points.at(1))));
}
/**
@return le rectangle delimitant cette partie.
*/
QRectF PartArc::boundingRect() const {
qreal adjust = 1.5;
QRectF r(QGraphicsEllipseItem::boundingRect().normalized());
r.adjust(-adjust, -adjust, adjust, adjust);
return(r);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -19,12 +19,13 @@
#define PART_ARC_H
#include <QtGui>
#include "customelementgraphicpart.h"
class ArcEditor;
/**
This class represents an elliptical arc primitive which may be used to
compose the drawing of an electrical element within the element editor.
Cette classe represente un arc pouvant etre utilise pour composer le
dessin d'un element dans l'editeur d'element.
*/
class PartArc : public QGraphicsEllipseItem, public CustomElementGraphicPart {
// constructors, destructor
// constructeurs, destructeur
public:
PartArc(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartArc();
@@ -32,27 +33,25 @@ class PartArc : public QGraphicsEllipseItem, public CustomElementGraphicPart {
private:
PartArc(const PartArc &);
// attributes
// attributs
private:
ArcEditor *informations;
int _angle;
int start_angle;
// methods
// methodes
public:
enum { Type = UserType + 1101 };
/**
Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a
PartArc.
@return the QGraphicsItem type
permet de caster un QGraphicsItem en PartArc avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
virtual QString name() const { return(QObject::tr("arc", "element part name")); }
virtual QString xmlName() const { return(QString("arc")); }
virtual QString name() const { return(QObject::tr("arc")); }
virtual const QDomElement toXml(QDomDocument &) const;
virtual void fromXml(const QDomElement &);
virtual QPointF sceneTopLeft() const;
virtual QRectF boundingRect() const;
virtual void setAngle(int);
virtual void setStartAngle(int);
virtual int angle() const;
@@ -60,14 +59,8 @@ class PartArc : public QGraphicsEllipseItem, public CustomElementGraphicPart {
virtual void setProperty(const QString &, const QVariant &);
virtual QVariant property(const QString &);
virtual bool isUseless() const;
virtual QRectF sceneGeometricRect() const;
virtual void startUserTransformation(const QRectF &);
virtual void handleUserTransformation(const QRectF &, const QRectF &);
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
QList<QPointF> saved_points_;
};
#endif

199
editor/partcircle.cpp Normal file
View File

@@ -0,0 +1,199 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "partcircle.h"
#include "circleeditor.h"
/**
Constructeur
@param editor L'editeur d'element concerne
@param parent Le QGraphicsItem parent de ce cercle
@param scene La scene sur laquelle figure ce cercle
*/
PartCircle::PartCircle(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsEllipseItem(parent, scene), CustomElementGraphicPart(editor) {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new CircleEditor(elementEditor(), this);
informations -> setElementTypeName(name());
style_editor -> appendWidget(informations);
style_editor -> setElementTypeName(name());
}
/// Destructeur
PartCircle::~PartCircle() {
}
/**
Dessine le cercle
@param painter QPainter a utiliser pour rendre le dessin
@param options Options pour affiner le rendu
@param widget Widget sur lequel le rendu est effectue
*/
void PartCircle::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
if (isSelected()) {
t.setColor(Qt::red);
painter -> setPen(t);
}
painter -> drawEllipse(rect());
if (isSelected()) {
painter -> setRenderHint(QPainter::Antialiasing, false);
painter -> setPen((painter -> brush().color() == QColor(Qt::black) && painter -> brush().isOpaque()) ? Qt::yellow : Qt::blue);
QPointF center = rect().center();
painter -> drawLine(QLineF(center.x() - 2.0, center.y(), center.x() + 2.0, center.y()));
painter -> drawLine(QLineF(center.x(), center.y() - 2.0, center.x(), center.y() + 2.0));
}
}
/**
Exporte le cercle en XML
@param xml_document Document XML a utiliser pour creer l'element XML
@return un element XML decrivant le cercle
*/
const QDomElement PartCircle::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("circle");
QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", top_left.x());
xml_element.setAttribute("y", top_left.y());
xml_element.setAttribute("diameter", rect().width());
stylesToXml(xml_element);
return(xml_element);
}
/**
Importe les proprietes d'un cercle depuis un element XML
@param qde Element XML a lire
*/
void PartCircle::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
qreal diameter = qde.attribute("diameter", "0").toDouble();
setRect(
QRectF(
mapFromScene(
qde.attribute("x", "0").toDouble(),
qde.attribute("y", "0").toDouble()
),
QSizeF(
diameter,
diameter
)
)
);
}
/**
Specifie la valeur d'une propriete donnee du cercle
@param property propriete a modifier. Valeurs acceptees :
* x : abscisse du centre du cercle
* y : ordonnee du centre du cercle
* diameter : diametre du cercle
@param value Valeur a attribuer a la propriete
*/
void PartCircle::setProperty(const QString &property, const QVariant &value) {
CustomElementGraphicPart::setProperty(property, value);
if (!value.canConvert(QVariant::Double)) return;
if (property == "x") {
QRectF current_rect = rect();
QPointF current_pos = mapToScene(current_rect.center());
setRect(current_rect.translated(value.toDouble() - current_pos.x(), 0.0));
} else if (property == "y") {
QRectF current_rect = rect();
QPointF current_pos = mapToScene(current_rect.center());
setRect(current_rect.translated(0.0, value.toDouble() - current_pos.y()));
} else if (property == "diameter") {
QRectF current_rect = rect();
qreal new_diameter = qAbs(value.toDouble());
current_rect.translate(
(new_diameter - current_rect.width()) / -2.0,
(new_diameter - current_rect.height()) / -2.0
);
current_rect.setSize(QSizeF(new_diameter, new_diameter));
setRect(current_rect);
}
}
/**
Permet d'acceder a la valeur d'une propriete de style donnee.
@param property propriete lue. Valeurs acceptees :
* x : abscisse du centre du cercle
* y : ordonnee du centre du cercle
* diameter : diametre du cercle
@return La valeur de la propriete property
*/
QVariant PartCircle::property(const QString &property) {
// appelle la methode property de CustomElementGraphicpart pour les styles
QVariant style_property = CustomElementGraphicPart::property(property);
if (style_property != QVariant()) return(style_property);
if (property == "x") {
return(mapToScene(rect().center()).x());
} else if (property == "y") {
return(mapToScene(rect().center()).y());
} else if (property == "diameter") {
return(rect().width());
}
return(QVariant());
}
/**
Gere les changements intervenant sur cette partie
@param change Type de changement
@param value Valeur numerique relative au changement
*/
QVariant PartCircle::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsEllipseItem::itemChange(change, value));
}
/**
@return le coin superieur gauche du rectangle dans lequel s'inscrit
le cercle, dans les coordonnees de la scene.
*/
QPointF PartCircle::sceneTopLeft() const {
return(mapToScene(rect().topLeft()));
}
/**
@return le centre du cercle, dans les coordonnees de la scene.
*/
QPointF PartCircle::sceneCenter() const {
return(mapToScene(rect().center()));
}
/**
@return le rectangle delimitant cette partie.
*/
QRectF PartCircle::boundingRect() const {
qreal adjust = 1.5;
QRectF r(QGraphicsEllipseItem::boundingRect());
r.adjust(-adjust, -adjust, adjust, adjust);
return(r);
}
/**
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
conservee / enregistree.
Un cercle est pertinent des lors que son rayon n'est pas nul
*/
bool PartCircle::isUseless() const {
return(rect().isNull());
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -15,50 +15,48 @@
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PART_RECTANGLE_H
#define PART_RECTANGLE_H
#ifndef PART_CIRCLE_H
#define PART_CIRCLE_H
#include <QtGui>
#include "customelementgraphicpart.h"
class CircleEditor;
/**
This class represents a rectangle primitive which may be used to compose the
drawing of an electrical element within the element editor.
Cette classe represente un cercle pouvant etre utilise pour composer le
dessin d'un element dans l'editeur d'element.
*/
class PartRectangle : public QGraphicsRectItem, public CustomElementGraphicPart {
// constructors, destructor
class PartCircle : public QGraphicsEllipseItem, public CustomElementGraphicPart {
// constructeurs, destructeur
public:
PartRectangle(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartRectangle();
PartCircle(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartCircle();
private:
PartRectangle(const PartRectangle &);
PartCircle(const PartCircle &);
// methods
// attributs
private:
CircleEditor *informations;
// methodes
public:
enum { Type = UserType + 1109 };
enum { Type = UserType + 1102 };
/**
Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a
PartRectangle.
@return the QGraphicsItem type
permet de caster un QGraphicsItem en PartCircle avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
virtual QString name() const { return(QObject::tr("rectangle", "element part name")); }
virtual QString xmlName() const { return(QString("rect")); }
virtual QString name() const { return(QObject::tr("cercle")); }
virtual const QDomElement toXml(QDomDocument &) const;
virtual void fromXml(const QDomElement &);
virtual QPointF sceneTopLeft() const;
virtual QRectF boundingRect() const;
QPointF sceneCenter() const;
virtual void setProperty(const QString &, const QVariant &);
virtual QVariant property(const QString &);
virtual bool isUseless() const;
virtual QRectF sceneGeometricRect() const;
virtual void startUserTransformation(const QRectF &);
virtual void handleUserTransformation(const QRectF &, const QRectF &);
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
QList<QPointF> saved_points_;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -16,6 +16,7 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "partellipse.h"
#include "ellipseeditor.h"
/**
Constructeur
@@ -24,11 +25,12 @@
@param scene La scene sur laquelle figure cette ellipse
*/
PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsEllipseItem(parent, scene), CustomElementGraphicPart(editor) {
setFlags(QGraphicsItem::ItemIsSelectable);
#if QT_VERSION >= 0x040600
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
#endif
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new EllipseEditor(elementEditor(), this);
informations -> setElementTypeName(name());
style_editor -> appendWidget(informations);
style_editor -> setElementTypeName(name());
}
/// Destructeur
@@ -41,15 +43,13 @@ PartEllipse::~PartEllipse() {
@param options Options pour affiner le rendu
@param widget Widget sur lequel le rendu est effectue
*/
void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) {
Q_UNUSED(widget);
void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
t.setCosmetic(options && options -> levelOfDetail < 1.0);
if (isSelected()) {
t.setColor(Qt::red);
painter -> setPen(t);
}
painter -> setPen(t);
painter -> drawEllipse(rect());
if (isSelected()) {
painter -> setRenderHint(QPainter::Antialiasing, false);
@@ -66,18 +66,12 @@ void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
@return un element XML decrivant l'ellipse
*/
const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const {
QDomElement xml_element;
if (qFuzzyCompare(rect().width(), rect().height())) {
xml_element = xml_document.createElement("circle");
xml_element.setAttribute("diameter", QString("%1").arg(rect().width()));
} else {
xml_element = xml_document.createElement("ellipse");
xml_element.setAttribute("width", QString("%1").arg(rect().width()));
xml_element.setAttribute("height", QString("%1").arg(rect().height()));
}
QDomElement xml_element = xml_document.createElement("ellipse");
QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", QString("%1").arg(top_left.x()));
xml_element.setAttribute("y", QString("%1").arg(top_left.y()));
xml_element.setAttribute("x", top_left.x());
xml_element.setAttribute("y", top_left.y());
xml_element.setAttribute("width", rect().width());
xml_element.setAttribute("height", rect().height());
stylesToXml(xml_element);
return(xml_element);
}
@@ -88,20 +82,16 @@ const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const {
*/
void PartEllipse::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
qreal width, height;
if (qde.tagName() == "ellipse") {
width = qde.attribute("width", "0").toDouble();
height = qde.attribute("height", "0").toDouble();
} else {
width = height = qde.attribute("diameter", "0").toDouble();
}
setRect(
QRectF(
mapFromScene(
qde.attribute("x", "0").toDouble(),
qde.attribute("y", "0").toDouble()
),
QSizeF(width, height)
QSizeF(
qde.attribute("width", "0").toDouble(),
qde.attribute("height", "0").toDouble()
)
)
);
}
@@ -139,7 +129,6 @@ void PartEllipse::setProperty(const QString &property, const QVariant &value) {
current_rect.setHeight(new_height);
setRect(current_rect);
}
update();
}
/**
@@ -175,8 +164,8 @@ QVariant PartEllipse::property(const QString &property) {
*/
QVariant PartEllipse::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemPositionHasChanged) {
updateCurrentPartEditor();
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsEllipseItem::itemChange(change, value));
@@ -198,42 +187,3 @@ QPointF PartEllipse::sceneTopLeft() const {
bool PartEllipse::isUseless() const {
return(rect().isNull());
}
/**
@return the minimum, margin-less rectangle this part can fit into, in scene
coordinates. It is different from boundingRect() because it is not supposed
to imply any margin, and it is different from shape because it is a regular
rectangle, not a complex shape.
*/
QRectF PartEllipse::sceneGeometricRect() const {
return(mapToScene(rect()).boundingRect());
}
/**
Start the user-induced transformation, provided this primitive is contained
within the \a initial_selection_rect bounding rectangle.
*/
void PartEllipse::startUserTransformation(const QRectF &initial_selection_rect) {
Q_UNUSED(initial_selection_rect)
// we keep track of our own rectangle at the moment in scene coordinates too
saved_points_.clear();
saved_points_ << mapToScene(rect().topLeft()) << mapToScene(rect().bottomRight());
}
/**
Handle the user-induced transformation from \a initial_selection_rect to \a new_selection_rect
*/
void PartEllipse::handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect) {
QList<QPointF> mapped_points = mapPoints(initial_selection_rect, new_selection_rect, saved_points_);
setRect(QRectF(mapFromScene(mapped_points.at(0)), mapFromScene(mapped_points.at(1))));
}
/**
@return le rectangle delimitant cette partie.
*/
QRectF PartEllipse::boundingRect() const {
qreal adjust = 1.5;
QRectF r(QGraphicsEllipseItem::boundingRect().normalized());
r.adjust(-adjust, -adjust, adjust, adjust);
return(r);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -19,12 +19,13 @@
#define PART_ELLIPSE_H
#include <QtGui>
#include "customelementgraphicpart.h"
class EllipseEditor;
/**
This class represents an ellipse primitive which may be used to compose the
drawing of an electrical element within the element editor.
Cette classe represente une ellipse pouvant etre utilisee pour composer le
dessin d'un element dans l'editeur d'element.
*/
class PartEllipse : public QGraphicsEllipseItem, public CustomElementGraphicPart {
// constructors, destructor
// constructeurs, destructeur
public:
PartEllipse(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartEllipse();
@@ -32,33 +33,28 @@ class PartEllipse : public QGraphicsEllipseItem, public CustomElementGraphicPart
private:
PartEllipse(const PartEllipse &);
// methods
// attributs
private:
EllipseEditor *informations;
// methodes
public:
enum { Type = UserType + 1103 };
/**
Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a
PartEllipse.
@return the QGraphicsItem type
permet de caster un QGraphicsItem en PartEllipse avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
virtual QString name() const { return(QObject::tr("ellipse", "element part name")); }
virtual QString xmlName() const { return(QString("ellipse")); }
virtual QString name() const { return(QObject::tr("ellipse")); }
virtual const QDomElement toXml(QDomDocument &) const;
virtual void fromXml(const QDomElement &);
virtual QPointF sceneTopLeft() const;
virtual QRectF boundingRect() const;
virtual void setProperty(const QString &, const QVariant &);
virtual QVariant property(const QString &);
virtual bool isUseless() const;
virtual QRectF sceneGeometricRect() const;
virtual void startUserTransformation(const QRectF &);
virtual void handleUserTransformation(const QRectF &, const QRectF &);
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
QList<QPointF> saved_points_;
};
#endif

254
editor/partline.cpp Normal file
View File

@@ -0,0 +1,254 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "partline.h"
#include "lineeditor.h"
#include <cmath>
/**
Constructeur
@param editor L'editeur d'element concerne
@param parent Le QGraphicsItem parent de cette ligne
@param scene La scene sur laquelle figure cette ligne
*/
PartLine::PartLine(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsLineItem(parent, scene), CustomElementGraphicPart(editor) {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new LineEditor(elementEditor(), this);
informations -> setElementTypeName(name());
style_editor -> appendWidget(informations);
style_editor -> setElementTypeName(name());
}
/// Destructeur
PartLine::~PartLine() {
}
/**
Dessine la ligne
@param painter QPainter a utiliser pour rendre le dessin
@param options Options pour affiner le rendu
@param widget Widget sur lequel le rendu est effectue
*/
void PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem */*q*/, QWidget */*w*/) {
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
if (isSelected()) {
t.setColor(Qt::red);
painter -> setPen(t);
}
painter -> setBrush(Qt::NoBrush);
painter -> drawLine(line());
}
/**
Exporte la ligne en XML
@param xml_document Document XML a utiliser pour creer l'element XML
@return un element XML decrivant la ligne
*/
const QDomElement PartLine::toXml(QDomDocument &xml_document) const {
QPointF p1(sceneP1());
QPointF p2(sceneP2());
QDomElement xml_element = xml_document.createElement("line");
xml_element.setAttribute("x1", p1.x());
xml_element.setAttribute("y1", p1.y());
xml_element.setAttribute("x2", p2.x());
xml_element.setAttribute("y2", p2.y());
stylesToXml(xml_element);
return(xml_element);
}
/**
Importe les proprietes d'une ligne depuis un element XML
@param qde Element XML a lire
*/
void PartLine::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
setLine(
QLineF(
mapFromScene(
qde.attribute("x1", "0").toDouble(),
qde.attribute("y1", "0").toDouble()
),
mapFromScene(
qde.attribute("x2", "0").toDouble(),
qde.attribute("y2", "0").toDouble()
)
)
);
}
/**
Specifie la valeur d'une propriete donnee de la ligne
@param property propriete a modifier. Valeurs acceptees :
* x1 : abscisse du premier point
* y1 : ordonnee du second point
* x2 : abscisse du premier point
* y2 : ordonnee du second point
@param value Valeur a attribuer a la propriete
*/
void PartLine::setProperty(const QString &property, const QVariant &value) {
CustomElementGraphicPart::setProperty(property, value);
if (!value.canConvert(QVariant::Double)) return;
QPointF new_p1(sceneP1()), new_p2(sceneP2());
bool setline = true;
if (property == "x1") {
new_p1.setX(value.toDouble());
} else if (property == "y1") {
new_p1.setY(value.toDouble());
} else if (property == "x2") {
new_p2.setX(value.toDouble());
} else if (property == "y2") {
new_p2.setY(value.toDouble());
} else setline = false;
setLine(QLineF(mapFromScene(new_p1), mapFromScene(new_p2)));
}
/**
Permet d'acceder a la valeur d'une propriete donnee de la ligne
@param property propriete lue. Valeurs acceptees :
* x1 : abscisse du premier point
* y1 : ordonnee du second point
* x2 : abscisse du premier point
* y2 : ordonnee du second point
@return La valeur de la propriete property
*/
QVariant PartLine::property(const QString &property) {
// appelle la methode property de CustomElementGraphicpart pour les styles
QVariant style_property = CustomElementGraphicPart::property(property);
if (style_property != QVariant()) return(style_property);
if (property == "x1") {
return(sceneP1().x());
} else if (property == "y1") {
return(sceneP1().y());
} else if (property == "x2") {
return(sceneP2().x());
} else if (property == "y2") {
return(sceneP2().y());
}
return(QVariant());
}
/**
Gere les changements intervenant sur cette partie
@param change Type de changement
@param value Valeur numerique relative au changement
*/
QVariant PartLine::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsLineItem::itemChange(change, value));
}
/**
@return le premier point, dans les coordonnees de la scene.
*/
QPointF PartLine::sceneP1() const {
return(mapToScene(line().p1()));
}
/**
@return le second point, dans les coordonnees de la scene.
*/
QPointF PartLine::sceneP2() const {
return(mapToScene(line().p2()));
}
/**
@return la forme selectionnable de la ligne
*/
QPainterPath PartLine::shape() const {
QList<QPointF> points = fourShapePoints();
QPainterPath t;
t.setFillRule(Qt::WindingFill);
t.moveTo(points.at(0));
t.lineTo(points.at(1));
t.lineTo(points.at(2));
t.lineTo(points.at(3));
t.lineTo(points.at(0));
return(t);
}
/**
@return une liste contenant les deux points de la droite + les 4 points entourant ces deux points
*/
QList<QPointF> PartLine::fourShapePoints() const {
const qreal marge = 2.0;
// on a donc A(xa , ya) et B(xb, yb)
QPointF a = line().p1();
QPointF b = line().p2();
QList<QPointF> result;
// cas particulier : la droite se ramene a un point
if (a == b) {
result << QPointF(a.x() - marge, a.y() - marge);
result << QPointF(a.x() - marge, a.y() + marge);
result << QPointF(a.x() + marge, a.y() + marge);
result << QPointF(a.x() + marge, a.y() - marge);
} else {
// on calcule le vecteur AB : (xb-xa, yb-ya)
QPointF v_ab = b - a;
// et la distance AB : racine des coordonnees du vecteur au carre
qreal ab = sqrt(pow(v_ab.x(), 2) + pow(v_ab.y(), 2));
// ensuite on definit le vecteur u(a, b) qui est egal au vecteur AB divise
// par sa longueur et multiplie par la longueur de la marge que tu veux
// laisser
QPointF u = v_ab / ab * marge;
// on definit le vecteur v(-b , a) qui est perpendiculaire a AB
QPointF v(-u.y(), u.x());
QPointF m = -u + v; // on a le vecteur M = -u + v
QPointF n = -u - v; // et le vecteur N=-u-v
QPointF h = a + m; // H = A + M
QPointF k = a + n; // K = A + N
QPointF i = b - n; // I = B - N
QPointF j = b - m; // J = B - M
result << h << i << j << k;
}
return(result);
}
/**
@return le rectangle delimitant cette partie.
*/
QRectF PartLine::boundingRect() const {
qreal adjust = 1.5;
QRectF r(QGraphicsLineItem::boundingRect());
r.adjust(-adjust, -adjust, adjust, adjust);
return(r);
}
/**
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
conservee / enregistree.
Une ligne est pertinente des lors que ses deux points sont differents
*/
bool PartLine::isUseless() const {
return(sceneP1() == sceneP2());
}

66
editor/partline.h Normal file
View File

@@ -0,0 +1,66 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PART_LINE_H
#define PART_LINE_H
#include <QtGui>
#include "customelementgraphicpart.h"
class LineEditor;
/**
Cette classe represente une ligne pouvant etre utilisee pour composer le
dessin d'un element dans l'editeur d'element.
*/
class PartLine : public QGraphicsLineItem, public CustomElementGraphicPart {
// constructeurs, destructeur
public:
PartLine(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartLine();
private:
PartLine(const PartLine &);
// attributs
private:
LineEditor *informations;
// methodes
public:
enum { Type = UserType + 1104 };
/**
permet de caster un QGraphicsItem en PartLine avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
virtual QString name() const { return(QObject::tr("ligne")); }
virtual const QDomElement toXml(QDomDocument &) const;
virtual void fromXml(const QDomElement &);
virtual QPointF sceneP1() const;
virtual QPointF sceneP2() const;
virtual QPainterPath shape() const;
virtual QRectF boundingRect() const;
virtual void setProperty(const QString &, const QVariant &);
virtual QVariant property(const QString &);
virtual bool isUseless() const;
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
QList<QPointF> fourShapePoints() const;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -17,6 +17,7 @@
*/
#include "partpolygon.h"
#include "qet.h"
#include "polygoneditor.h"
/**
Constructeur
@@ -29,11 +30,12 @@ PartPolygon::PartPolygon(QETElementEditor *editor, QGraphicsItem *parent, QGraph
CustomElementGraphicPart(editor),
closed(false)
{
setFlags(QGraphicsItem::ItemIsSelectable);
#if QT_VERSION >= 0x040600
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
#endif
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setAcceptedMouseButtons(Qt::LeftButton);
informations = new PolygonEditor(elementEditor(), this);
informations -> setElementTypeName(name());
style_editor -> appendWidget(informations);
style_editor -> setElementTypeName(name());
}
/// Destructeur
@@ -77,8 +79,8 @@ const QDomElement PartPolygon::toXml(QDomDocument &xml_document) const {
int i = 1;
foreach(QPointF point, polygon()) {
point = mapToScene(point);
xml_element.setAttribute(QString("x%1").arg(i), QString("%1").arg(point.x()));
xml_element.setAttribute(QString("y%1").arg(i), QString("%1").arg(point.y()));
xml_element.setAttribute(QString("x%1").arg(i), point.x());
xml_element.setAttribute(QString("y%1").arg(i), point.y());
++ i;
}
if (!closed) xml_element.setAttribute("closed", "false");
@@ -92,13 +94,13 @@ const QDomElement PartPolygon::toXml(QDomDocument &xml_document) const {
@param options Options pour affiner le rendu
@param widget Widget sur lequel le rendu est effectue
*/
void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) {
Q_UNUSED(widget);
void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
applyStylesToQPainter(*painter);
QPen t = painter -> pen();
t.setCosmetic(options && options -> levelOfDetail < 1.0);
if (isSelected()) t.setColor(Qt::red);
painter -> setPen(t);
if (isSelected()) {
t.setColor(Qt::red);
painter -> setPen(t);
}
if (closed) painter -> drawPolygon(polygon());
else painter -> drawPolyline(polygon());
}
@@ -112,7 +114,6 @@ void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
void PartPolygon::setProperty(const QString &property, const QVariant &value) {
CustomElementGraphicPart::setProperty(property, value);
if (property == "closed") closed = value.toBool();
update();
}
/**
@@ -137,8 +138,8 @@ QVariant PartPolygon::property(const QString &property) {
*/
QVariant PartPolygon::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemPositionHasChanged) {
updateCurrentPartEditor();
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsPolygonItem::itemChange(change, value));
@@ -162,51 +163,3 @@ bool PartPolygon::isUseless() const {
return(true);
}
/**
@return the minimum, margin-less rectangle this part can fit into, in scene
coordinates. It is different from boundingRect() because it is not supposed
to imply any margin, and it is different from shape because it is a regular
rectangle, not a complex shape.
*/
QRectF PartPolygon::sceneGeometricRect() const {
return(mapToScene(polygon().boundingRect()).boundingRect());
}
/**
Start the user-induced transformation, provided this primitive is contained
within the \a initial_selection_rect bounding rectangle.
*/
void PartPolygon::startUserTransformation(const QRectF &initial_selection_rect) {
Q_UNUSED(initial_selection_rect)
saved_points_ = mapToScene(polygon()).toList();
}
/**
Handle the user-induced transformation from \a initial_selection_rect to \a new_selection_rect
*/
void PartPolygon::handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect) {
QList<QPointF> mapped_points = mapPoints(initial_selection_rect, new_selection_rect, saved_points_);
setPolygon(mapFromScene(QPolygonF(mapped_points.toVector())));
}
/**
@reimp CustomElementPart::preferredScalingMethod
This method is called by the decorator when it needs to determine the best
way to interactively scale a primitive. It is typically called when only a
single primitive is being scaled.
This reimplementation systematically returns QET::RoundScaleRatios.
*/
QET::ScalingMethod PartPolygon::preferredScalingMethod() const {
return(QET::RoundScaleRatios);
}
/**
@return le rectangle delimitant cette partie.
*/
QRectF PartPolygon::boundingRect() const {
qreal adjust = 1.5;
QRectF r(QGraphicsPolygonItem::boundingRect());
r.adjust(-adjust, -adjust, adjust, adjust);
return(r);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -19,12 +19,13 @@
#define PART_POLYGON_H
#include <QtGui>
#include "customelementgraphicpart.h"
class PolygonEditor;
/**
This class represents a polygon primitive which may be used to compose the
drawing of an electrical element within the element editor.
Cette classe represente un polygone pouvant etre utilise pour composer le
dessin d'un element dans l'editeur d'element.
*/
class PartPolygon : public QGraphicsPolygonItem, public CustomElementGraphicPart {
// constructors, destructor
// constructeurs, destructeur
public:
PartPolygon(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartPolygon();
@@ -32,53 +33,56 @@ class PartPolygon : public QGraphicsPolygonItem, public CustomElementGraphicPart
private:
PartPolygon(const PartPolygon &);
// attributes
// attributs
private:
bool closed;
PolygonEditor *informations;
// methods
/**
constructeur
paint()
widget bidon pour l'edition
methode pour poser le polygone :
-mousePressEvent = pose un nouveau point
-mouseMoveEvent = deplace ce point
-mouveReleaseEvent = finalise ce point
utiliser QPolygonF ; memoriser le point en cours (tout comme le
partploygon en cours) et ne l'ajouter au qpolygonf que lors du
mouseReleaseEvent
*/
// methodes
public:
enum { Type = UserType + 1105 };
/**
Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a
PartPolygon.
@return the QGraphicsItem type
permet de caster un QGraphicsItem en PartPolygon avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
virtual QString name() const { return(QObject::tr("polygone", "element part name")); }
virtual QString xmlName() const { return(QString("polygon")); }
virtual QString name() const { return(QObject::tr("polygone")); }
void fromXml(const QDomElement &);
const QDomElement toXml(QDomDocument &) const;
virtual QRectF boundingRect() const;
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
void setClosed(bool c);
bool isClosed() const;
void setProperty(const QString &, const QVariant &);
virtual QVariant property(const QString &);
virtual bool isUseless() const;
virtual QRectF sceneGeometricRect() const;
virtual void startUserTransformation(const QRectF &);
virtual void handleUserTransformation(const QRectF &, const QRectF &);
virtual QET::ScalingMethod preferredScalingMethod() const;
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
QList<QPointF> saved_points_;
};
/**
Whether the polygon should be closed.
@param c true for the polygon to be closed, false otherwise
Specifie si le polygone doit etre ferme
@param c true pour un polygone ferme, false sinon
*/
inline void PartPolygon::setClosed(bool c) {
closed = c;
}
/**
Indicate whether the polygon is closed.
@return true if the polygon is closed, false otherwise
Indique si le polygone est ferme
@return true si le polygone est ferme, false sinon
*/
inline bool PartPolygon::isClosed() const {
return(closed);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -17,6 +17,7 @@
*/
#include "partterminal.h"
#include "terminal.h"
#include "terminaleditor.h"
/**
Constructeur
@@ -29,17 +30,17 @@ PartTerminal::PartTerminal(QETElementEditor *editor, QGraphicsItem *parent, QGra
QGraphicsItem(parent, scene),
_orientation(QET::North)
{
informations = new TerminalEditor(elementEditor(), this);
informations -> setElementTypeName(name());
updateSecondPoint();
setFlags(QGraphicsItem::ItemIsSelectable);
#if QT_VERSION >= 0x040600
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
#endif
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setZValue(100000);
}
/// Destructeur
PartTerminal::~PartTerminal() {
}
delete informations;
};
/**
Importe les proprietes d'une borne depuis un element XML
@@ -75,14 +76,20 @@ const QDomElement PartTerminal::toXml(QDomDocument &xml_document) const {
return(xml_element);
}
/**
@return Le widget permettant d'editer cette borne
*/
QWidget *PartTerminal::elementInformations() {
return(informations);
}
/**
Dessine la borne
@param p QPainter a utiliser pour rendre le dessin
@param painter QPainter a utiliser pour rendre le dessin
@param options Options pour affiner le rendu
@param widget Widget sur lequel le rendu est effectue
*/
void PartTerminal::paint(QPainter *p, const QStyleOptionGraphicsItem *options, QWidget *widget) {
Q_UNUSED(widget);
void PartTerminal::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) {
p -> save();
// annulation des renderhints
@@ -92,17 +99,16 @@ void PartTerminal::paint(QPainter *p, const QStyleOptionGraphicsItem *options, Q
QPen t;
t.setWidthF(1.0);
t.setCosmetic(options && options -> levelOfDetail < 1.0);
// dessin de la borne en rouge
t.setColor(isSelected() ? Terminal::neutralColor : Qt::red);
t.setColor(isSelected() ? Terminal::couleur_neutre : Qt::red);
p -> setPen(t);
p -> drawLine(QPointF(0.0, 0.0), second_point);
// dessin du point d'amarrage au conducteur en bleu
t.setColor(isSelected() ? Qt::red : Terminal::neutralColor);
t.setColor(isSelected() ? Qt::red : Terminal::couleur_neutre);
p -> setPen(t);
p -> setBrush(Terminal::neutralColor);
p -> setBrush(Terminal::couleur_neutre);
p -> drawPoint(QPointF(0.0, 0.0));
p -> restore();
}
@@ -140,6 +146,7 @@ void PartTerminal::setOrientation(QET::Orientation ori) {
prepareGeometryChange();
_orientation = ori;
updateSecondPoint();
informations -> updateForm();
}
/**
@@ -189,8 +196,8 @@ QVariant PartTerminal::property(const QString &property) {
*/
QVariant PartTerminal::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemPositionHasChanged) {
updateCurrentPartEditor();
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
informations -> updateForm();
}
}
return(QGraphicsItem::itemChange(change, value));
@@ -219,30 +226,3 @@ void PartTerminal::updateSecondPoint() {
bool PartTerminal::isUseless() const {
return(false);
}
/**
@return the minimum, margin-less rectangle this part can fit into, in scene
coordinates. It is different from boundingRect() because it is not supposed
to imply any margin, and it is different from shape because it is a regular
rectangle, not a complex shape.
*/
QRectF PartTerminal::sceneGeometricRect() const {
return(sceneBoundingRect());
}
/**
Start the user-induced transformation, provided this primitive is contained
within the \a initial_selection_rect bounding rectangle.
*/
void PartTerminal::startUserTransformation(const QRectF &initial_selection_rect) {
Q_UNUSED(initial_selection_rect)
saved_position_ = scenePos();
}
/**
Handle the user-induced transformation from \a initial_selection_rect to \a new_selection_rect
*/
void PartTerminal::handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect) {
QPointF mapped_point = mapPoints(initial_selection_rect, new_selection_rect, QList<QPointF>() << saved_position_).first();
setPos(mapped_point);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,36 +20,38 @@
#include "customelementpart.h"
#include "qet.h"
#include <QtGui>
class TerminalEditor;
class QETElementEditor;
/**
This class represents a terminal which may be used to compose the drawing of
an electrical element within the element editor.
Cette classe represente une borne pouvant etre utilisee pour composer le
dessin d'un element dans l'editeur d'element.
*/
class PartTerminal : public CustomElementPart, public QGraphicsItem {
public:
// constructors, destructor
// constructeurs, destructeur
PartTerminal(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartTerminal();
private:
PartTerminal(const PartTerminal &);
// attributes
// attributs
private:
QET::Orientation _orientation;
QPointF second_point;
TerminalEditor *informations;
// methods
// methodes
public:
enum { Type = UserType + 1106 };
/**
Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a
PartTerminal.
@return the QGraphicsItem type
permet de caster un QGraphicsItem en PartTerminal avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
virtual QString name() const { return(QObject::tr("borne", "element part name")); }
virtual QString xmlName() const { return(QString("terminal")); }
virtual QString name() const { return(QObject::tr("borne")); }
virtual void fromXml(const QDomElement &);
virtual const QDomElement toXml(QDomDocument &) const;
virtual QWidget *elementInformations();
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
virtual QRectF boundingRect() const;
QET::Orientation orientation() const;
@@ -57,17 +59,11 @@ class PartTerminal : public CustomElementPart, public QGraphicsItem {
virtual void setProperty(const QString &, const QVariant &);
virtual QVariant property(const QString &);
virtual bool isUseless() const;
virtual QRectF sceneGeometricRect() const;
virtual void startUserTransformation(const QRectF &);
virtual void handleUserTransformation(const QRectF &, const QRectF &);
protected:
QVariant itemChange(GraphicsItemChange, const QVariant &);
private:
void updateSecondPoint();
private:
QPointF saved_position_;
};
#endif

219
editor/parttext.cpp Normal file
View File

@@ -0,0 +1,219 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parttext.h"
#include "texteditor.h"
#include "elementscene.h"
#include "qetapp.h"
/**
Constructeur
@param editor L'editeur d'element concerne
@param parent Le QGraphicsItem parent de ce texte statique
@param scene La scene sur laquelle figure ce texte statique
*/
PartText::PartText(QETElementEditor *editor, QGraphicsItem *parent, ElementScene *scene) :
QGraphicsTextItem(parent, scene),
CustomElementPart(editor)
{
setDefaultTextColor(Qt::black);
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setPlainText(QObject::tr("T"));
infos = new TextEditor(elementEditor(), this);
infos -> setElementTypeName(name());
}
/// Destructeur
PartText::~PartText() {
delete infos;
}
/**
Importe les proprietes d'un texte statique depuis un element XML
@param xml_element Element XML a lire
*/
void PartText::fromXml(const QDomElement &xml_element) {
bool ok;
int font_size = xml_element.attribute("size").toInt(&ok);
if (!ok || font_size < 1) font_size = 20;
setFont(QFont(QString(QETApp::diagramTextsFont()), font_size));
setPlainText(xml_element.attribute("text"));
setPos(
xml_element.attribute("x").toDouble(),
xml_element.attribute("y").toDouble()
);
}
/**
Exporte le texte statique en XML
@param xml_document Document XML a utiliser pour creer l'element XML
@return un element XML decrivant le texte statique
*/
const QDomElement PartText::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("text");
xml_element.setAttribute("x", QString("%1").arg((scenePos() + margin()).x()));
xml_element.setAttribute("y", QString("%1").arg((scenePos() + margin()).y()));
xml_element.setAttribute("text", toPlainText());
xml_element.setAttribute("size", font().pointSize());
return(xml_element);
}
/**
@return Le widget permettant d'editer ce texte statique
*/
QWidget *PartText::elementInformations() {
return(infos);
}
/**
Retourne la position du texte, l'origine etant le point en bas a gauche du
texte (et pas du cadre)
@return la position du texte
*/
QPointF PartText::pos() const {
return(QGraphicsTextItem::pos() + margin());
}
/**
Specifie la position du texte statique
@param left_corner_pos Nouvelle position
*/
void PartText::setPos(const QPointF &left_corner_pos) {
QGraphicsTextItem::setPos(left_corner_pos - margin());
}
/**
Specifie la position du texte statique
@param x abscisse de la nouvelle position
@param y ordonnee de la nouvelle position
*/
void PartText::setPos(qreal x, qreal y) {
QGraphicsTextItem::setPos(QPointF(x, y) - margin());
}
/**
@return Les coordonnees du point situe en bas a gauche du texte.
*/
QPointF PartText::margin() const {
QFont used_font = font();
QFontMetrics qfm(used_font);
QPointF margin(
(boundingRect().width () - qfm.width(toPlainText())) / 2.0,
((boundingRect().height() - used_font.pointSizeF()) / 3.0) + used_font.pointSizeF()
);
return(margin);
}
/**
Permet a l'element texte de redevenir deplacable a la fin de l'edition de texte
@param e Le QFocusEvent decrivant la perte de focus
*/
void PartText::focusOutEvent(QFocusEvent *e) {
QGraphicsTextItem::focusOutEvent(e);
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
}
/**
Permet a l'element texte de devenir editable lorsqu'on double-clique dessus
@param e Le QGraphicsSceneMouseEvent qui decrit le double-clic
*/
void PartText::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *e) {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
setTextInteractionFlags(Qt::TextEditorInteraction);
QGraphicsTextItem::mouseDoubleClickEvent(e);
setFocus(Qt::MouseFocusReason);
}
/**
Specifie la valeur d'une propriete donnee du texte statique
@param property propriete a modifier. Valeurs acceptees :
* x : abscisse de la position
* y : ordonnee de la position
* size : taille du texte
* text : texte
@param value Valeur a attribuer a la propriete
*/
void PartText::setProperty(const QString &property, const QVariant &value) {
if (property == "x") {
if (!value.canConvert(QVariant::Double)) return;
setPos(value.toDouble(), pos().y());
} else if (property == "y") {
if (!value.canConvert(QVariant::Double)) return;
setPos(pos().x(), value.toDouble());
} else if (property == "size") {
if (!value.canConvert(QVariant::Int)) return;
setFont(QFont(font().family(), value.toInt()));
} else if (property == "text") {
setPlainText(value.toString());
}
}
/**
Permet d'acceder a la valeur d'une propriete donnee du texte statique
@param property propriete lue. Valeurs acceptees :
* x : abscisse de la position
* y : ordonnee de la position
* size : taille du texte
* text : texte
@return La valeur de la propriete property
*/
QVariant PartText::property(const QString &property) {
if (property == "x") {
return((scenePos() + margin()).x());
} else if (property == "y") {
return((scenePos() + margin()).y());
} else if (property == "size") {
return(font().pointSize());
} else if (property == "text") {
return(toPlainText());
}
return(QVariant());
}
/**
Gere les changements intervenant sur cette partie
@param change Type de changement
@param value Valeur numerique relative au changement
*/
QVariant PartText::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
infos -> updateForm();
}
}
return(QGraphicsTextItem::itemChange(change, value));
}
/**
@return le rectangle delimitant cette partie.
*/
QRectF PartText::boundingRect() const {
QRectF r = QGraphicsTextItem::boundingRect();
r.adjust(0.0, -2.0, 0.0, 0.0);
return(r);
}
/**
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
conservee / enregistree.
Un texte statique n'est pas pertinent lorsque son texte est vide.
*/
bool PartText::isUseless() const {
return(toPlainText().isEmpty());
}

67
editor/parttext.h Normal file
View File

@@ -0,0 +1,67 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PART_TEXT_H
#define PART_TEXT_H
#include <QtGui>
#include "customelementpart.h"
class TextEditor;
/**
Cette classe represente un texte pouvant etre utilise pour composer le
dessin d'un element dans l'editeur d'element.
*/
class PartText : public QGraphicsTextItem, public CustomElementPart {
// constructeurs, destructeur
public:
PartText(QETElementEditor *, QGraphicsItem * = 0, ElementScene * = 0);
virtual ~PartText();
private:
PartText(const PartText &);
// attributs
TextEditor *infos;
// methodes
public:
enum { Type = UserType + 1107 };
/**
permet de caster un QGraphicsItem en PartText avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
virtual QString name() const { return(QObject::tr("texte")); }
void fromXml(const QDomElement &);
const QDomElement toXml(QDomDocument &) const;
QWidget *elementInformations();
QPointF pos() const;
void setPos(const QPointF &);
void setPos(qreal, qreal);
virtual void setProperty(const QString &, const QVariant &);
virtual QVariant property(const QString &);
virtual bool isUseless() const;
protected:
virtual void focusOutEvent(QFocusEvent *);
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
QRectF boundingRect() const;
private:
QPointF margin() const;
};
#endif

244
editor/parttextfield.cpp Normal file
View File

@@ -0,0 +1,244 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parttextfield.h"
#include "textfieldeditor.h"
#include "qetapp.h"
/**
Constructeur
@param editor L'editeur d'element concerne
@param parent Le QGraphicsItem parent de ce champ de texte
@param scene La scene sur laquelle figure ce champ de texte
*/
PartTextField::PartTextField(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) :
QGraphicsTextItem(parent, scene),
CustomElementPart(editor),
follow_parent_rotations(true)
{
setDefaultTextColor(Qt::black);
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
setPlainText(QObject::tr("_"));
infos = new TextFieldEditor(elementEditor(), this);
infos -> setElementTypeName(name());
}
/// Destructeur
PartTextField::~PartTextField() {
delete infos;
}
/**
Importe les proprietes d'un champ de texte depuis un element XML
@param xml_element Element XML a lire
*/
void PartTextField::fromXml(const QDomElement &xml_element) {
bool ok;
int font_size = xml_element.attribute("size").toInt(&ok);
if (!ok || font_size < 1) font_size = 20;
setFont(QFont(QString(QETApp::diagramTextsFont()), font_size));
setPlainText(xml_element.attribute("text"));
setPos(
xml_element.attribute("x").toDouble(),
xml_element.attribute("y").toDouble()
);
follow_parent_rotations = (xml_element.attribute("rotate") == "true");
}
/**
Exporte le champ de texte en XML
@param xml_document Document XML a utiliser pour creer l'element XML
@return un element XML decrivant le champ de texte
*/
const QDomElement PartTextField::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("input");
xml_element.setAttribute("x", QString("%1").arg((scenePos() + margin()).x()));
xml_element.setAttribute("y", QString("%1").arg((scenePos() + margin()).y()));
xml_element.setAttribute("text", toPlainText());
xml_element.setAttribute("size", font().pointSize());
if (follow_parent_rotations) xml_element.setAttribute("rotate", "true");
return(xml_element);
}
/**
@return Le widget permettant d'editer ce champ de texte
*/
QWidget *PartTextField::elementInformations() {
return(infos);
}
/**
Retourne la position du texte, l'origine etant le point en bas a gauche du
texte (et pas du cadre)
@return la position du texte
*/
QPointF PartTextField::pos() const {
return(QGraphicsTextItem::pos() + margin());
}
/**
Specifie la position du champ de texte
@param left_corner_pos Nouvelle position
*/
void PartTextField::setPos(const QPointF &left_corner_pos) {
QGraphicsTextItem::setPos(left_corner_pos - margin());
}
/**
Specifie la position du champ de texte
@param x abscisse de la nouvelle position
@param y ordonnee de la nouvelle position
*/
void PartTextField::setPos(qreal x, qreal y) {
QGraphicsTextItem::setPos(QPointF(x, y) - margin());
}
/**
@return true si le champ de texte suit les rotation de l'element, false
sinon
*/
bool PartTextField::followParentRotations() {
return(follow_parent_rotations);
}
/**
@param fpr true pour que le champ de texte suive les rotation de
l'element, false sinon
*/
void PartTextField::setFollowParentRotations(bool fpr) {
follow_parent_rotations = fpr;
}
/**
@return Les coordonnees du point situe en bas a gauche du texte.
*/
QPointF PartTextField::margin() const {
QFont used_font = font();
QFontMetrics qfm(used_font);
QPointF margin(
(boundingRect().width () - qfm.width(toPlainText())) / 2.0,
((boundingRect().height() - used_font.pointSizeF()) / 3.0) + used_font.pointSizeF()
);
return(margin);
}
/**
Permet a l'element texte de redevenir deplacable a la fin de l'edition de texte
@param e Le QFocusEvent decrivant la perte de focus
*/
void PartTextField::focusOutEvent(QFocusEvent *e) {
QGraphicsTextItem::focusOutEvent(e);
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
}
/**
Permet a l'element texte de devenir editable lorsqu'on double-clique dessus
@param e Le QGraphicsSceneMouseEvent qui decrit le double-clic
*/
void PartTextField::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *e) {
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
setTextInteractionFlags(Qt::TextEditorInteraction);
QGraphicsTextItem::mouseDoubleClickEvent(e);
setFocus(Qt::MouseFocusReason);
}
/**
Specifie la valeur d'une propriete donnee du champ de texte
@param property propriete a modifier. Valeurs acceptees :
* x : abscisse de la position
* y : ordonnee de la position
* size : taille du texte
* text : texte
* rotate : suivi de la rotation de l'element parent
@param value Valeur a attribuer a la propriete
*/
void PartTextField::setProperty(const QString &property, const QVariant &value) {
if (property == "x") {
if (!value.canConvert(QVariant::Double)) return;
setPos(value.toDouble(), pos().y());
} else if (property == "y") {
if (!value.canConvert(QVariant::Double)) return;
setPos(pos().x(), value.toDouble());
} else if (property == "size") {
if (!value.canConvert(QVariant::Int)) return;
setFont(QFont(font().family(), value.toInt()));
} else if (property == "text") {
setPlainText(value.toString());
} else if (property == "rotate") {
follow_parent_rotations = value.toBool();
}
}
/**
Permet d'acceder a la valeur d'une propriete donnee du champ de texte
@param property propriete lue. Valeurs acceptees :
* x : abscisse de la position
* y : ordonnee de la position
* size : taille du texte
* text : texte
* rotate : suivi de la rotation de l'element parent
@return La valeur de la propriete property
*/
QVariant PartTextField::property(const QString &property) {
if (property == "x") {
return((scenePos() + margin()).x());
} else if (property == "y") {
return((scenePos() + margin()).y());
} else if (property == "size") {
return(font().pointSize());
} else if (property == "text") {
return(toPlainText());
} else if (property == "rotate") {
return(follow_parent_rotations);
}
return(QVariant());
}
/**
Gere les changements intervenant sur cette partie
@param change Type de changement
@param value Valeur numerique relative au changement
*/
QVariant PartTextField::itemChange(GraphicsItemChange change, const QVariant &value) {
if (scene()) {
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
infos -> updateForm();
}
}
return(QGraphicsTextItem::itemChange(change, value));
}
/**
@return le rectangle delimitant cette partie.
*/
QRectF PartTextField::boundingRect() const {
QRectF r = QGraphicsTextItem::boundingRect();
r.adjust(0.0, -2.0, 0.0, 0.0);
return(r);
}
/**
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
conservee / enregistree.
Un champ de texte est toujours pertinent ; cette fonction renvoie donc
toujours false
*/
bool PartTextField::isUseless() const {
return(false);
}

73
editor/parttextfield.h Normal file
View File

@@ -0,0 +1,73 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PART_TEXTFIELD_H
#define PART_TEXTFIELD_H
#include <QtGui>
#include "customelementpart.h"
class TextFieldEditor;
class QETElementEditor;
/**
Cette classe represente un champ de texte editable pouvant etre utilise
pour composer le dessin d'un element dans l'editeur d'element.
L'utilisateur peut specifier un valeur par defaut. Le champ sera editable
lorsque l'element sera pose sur un schema.
*/
class PartTextField : public QGraphicsTextItem, public CustomElementPart {
// constructeurs, destructeur
public:
PartTextField(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
virtual ~PartTextField();
private:
PartTextField(const PartTextField &);
// attributs
TextFieldEditor *infos;
bool follow_parent_rotations;
// methodes
public:
enum { Type = UserType + 1108 };
/**
permet de caster un QGraphicsItem en PartTextField avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
virtual QString name() const { return(QObject::tr("champ de texte")); }
void fromXml(const QDomElement &);
const QDomElement toXml(QDomDocument &) const;
QWidget *elementInformations();
QPointF pos() const;
void setPos(const QPointF &);
void setPos(qreal, qreal);
bool followParentRotations();
void setFollowParentRotations(bool);
virtual void setProperty(const QString &, const QVariant &);
virtual QVariant property(const QString &);
virtual bool isUseless() const;
protected:
virtual void focusOutEvent(QFocusEvent *);
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
QRectF boundingRect() const;
private:
QPointF margin() const;
};
#endif

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -19,7 +19,6 @@
#include "partpolygon.h"
#include "elementscene.h"
#include "editorcommands.h"
#include "qetmessagebox.h"
/**
Constructeur
@@ -29,12 +28,10 @@
*/
PolygonEditor::PolygonEditor(QETElementEditor *editor, PartPolygon *p, QWidget *parent) :
ElementItemEditor(editor, parent),
part(p),
points_list(this),
close_polygon(tr("Polygone ferm\351"), this)
{
style_ = new StyleEditor(editor);
part = p;
// prepare la liste de points
points_list.setColumnCount(2);
QStringList headers;
@@ -45,7 +42,6 @@ PolygonEditor::PolygonEditor(QETElementEditor *editor, PartPolygon *p, QWidget *
// layout
QVBoxLayout *layout = new QVBoxLayout(this);
layout -> addWidget(style_);
layout -> addWidget(new QLabel(tr("Points du polygone :")));
layout -> addWidget(&points_list);
layout -> addWidget(&close_polygon);
@@ -69,13 +65,12 @@ void PolygonEditor::updatePolygon() {
Met a jour les points du polygone et cree un objet d'annulation
*/
void PolygonEditor::updatePolygonPoints() {
if (!part) return;
QVector<QPointF> points = getPointsFromTree();
if (points.count() < 2) {
QET::MessageBox::warning(
QMessageBox::warning(
this,
tr("Erreur", "message box title"),
tr("Le polygone doit comporter au moins deux points.", "message box content")
tr("Erreur"),
tr("Le polygone doit comporter au moins deux points.")
);
return;
}
@@ -86,7 +81,6 @@ void PolygonEditor::updatePolygonPoints() {
Met a jour l'etat ferme ou non du polygone
*/
void PolygonEditor::updatePolygonClosedState() {
if (!part) return;
undoStack().push(
new ChangePartCommand(
tr("fermeture du polygone"),
@@ -102,9 +96,8 @@ void PolygonEditor::updatePolygonClosedState() {
Met a jour le formulaire d'edition
*/
void PolygonEditor::updateForm() {
if (!part) return;
activeConnections(false);
while(points_list.takeTopLevelItem(0)) {}
while(points_list.takeTopLevelItem(0));
foreach(QPointF point, part -> polygon()) {
point = part -> mapToScene(point);
QStringList qsl;
@@ -117,43 +110,11 @@ void PolygonEditor::updateForm() {
activeConnections(true);
}
/**
Permet de specifier a cet editeur quelle primitive il doit editer. A noter
qu'un editeur peut accepter ou refuser d'editer une primitive.
L'editeur de polygone acceptera d'editer la primitive new_part s'il s'agit
d'un objet de la classe PartPolygon.
@param new_part Nouvelle primitive a editer
@return true si l'editeur a accepter d'editer la primitive, false sinon
*/
bool PolygonEditor::setPart(CustomElementPart *new_part) {
if (!new_part) {
part = 0;
style_ -> setPart(0);
return(true);
}
if (PartPolygon *part_polygon = dynamic_cast<PartPolygon *>(new_part)) {
part = part_polygon;
style_ -> setPart(part);
updateForm();
return(true);
} else {
return(false);
}
}
/**
@return la primitive actuellement editee, ou 0 si ce widget n'en edite pas
*/
CustomElementPart *PolygonEditor::currentPart() const {
return(part);
}
/**
@return Un vecteur contenant les points composant le polygone a partir du
formulaire d'edition
*/
QVector<QPointF> PolygonEditor::getPointsFromTree() {
if (!part) return(QVector<QPointF>());
QVector<QPointF> points;
for(int i = 0 ; i < points_list.topLevelItemCount() ; ++ i) {
QTreeWidgetItem *qtwi = points_list.topLevelItem(i);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -19,34 +19,29 @@
#define POLYGON_EDITOR_H
#include "elementitemeditor.h"
class PartPolygon;
class StyleEditor;
/**
This class provides a widget to edit polygons within the element editor.
Cette classe represente le widget d'edition d'un polygone dans l'editeur
d'element.
*/
class PolygonEditor : public ElementItemEditor {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
PolygonEditor(QETElementEditor *, PartPolygon * = 0, QWidget * = 0);
PolygonEditor(QETElementEditor *, PartPolygon *, QWidget * = 0);
virtual ~PolygonEditor();
private:
PolygonEditor(const PolygonEditor &);
// attributes
// attributs
private:
PartPolygon *part;
StyleEditor *style_;
QTreeWidget points_list;
QCheckBox close_polygon;
// methods
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
// methodes
private:
QVector<QPointF> getPointsFromTree();

733
editor/qetelementeditor.cpp Normal file
View File

@@ -0,0 +1,733 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qetelementeditor.h"
#include "qetapp.h"
#include "elementscene.h"
#include "elementview.h"
#include "customelementpart.h"
#include "newelementwizard.h"
#include "elementitemeditor.h"
/**
Constructeur
@param parent QWidget parent
*/
QETElementEditor::QETElementEditor(QWidget *parent) :
QMainWindow(parent),
read_only(false),
min_title(tr("QElectroTech - \311diteur d'\351l\351ment")),
_filename(QString())
{
setWindowTitle(min_title);
setWindowIcon(QIcon(":/ico/qet.png"));
setupInterface();
setupActions();
setupMenus();
// la fenetre est maximisee par defaut
setMinimumSize(QSize(500, 350));
setWindowState(Qt::WindowMaximized);
// lecture des parametres
readSettings();
// affichage
show();
}
/// Destructeur
QETElementEditor::~QETElementEditor() {
}
/**
Met en place les actions
*/
void QETElementEditor::setupActions() {
new_element = new QAction(QIcon(":/ico/new.png"), tr("&Nouveau"), this);
open = new QAction(QIcon(":/ico/open.png"), tr("&Ouvrir"), this);
save = new QAction(QIcon(":/ico/save.png"), tr("&Enregistrer"), this);
save_as = new QAction(QIcon(":/ico/saveas.png"), tr("Enregistrer sous"), this);
reload = new QAction(QIcon(":/ico/reload.png"), tr("Recharger"), this);
quit = new QAction(QIcon(":/ico/exit.png"), tr("&Quitter"), this);
selectall = new QAction( tr("Tout s\351lectionner"), this);
deselectall = new QAction( tr("D\351s\351lectionner tout"), this);
inv_select = new QAction( tr("Inverser la s\351lection"), this);
edit_delete = new QAction(QIcon(":/ico/delete.png"), tr("&Supprimer"), this);
edit_size_hs = new QAction(QIcon(":/ico/hotspot.png"), tr("\311diter la taille et le point de saisie"), this);
edit_names = new QAction(QIcon(":/ico/names.png"), tr("\311diter les noms"), this);
edit_ori = new QAction(QIcon(":/ico/orientations.png"), tr("\311diter les orientations"), this);
edit_raise = new QAction(QIcon(":/ico/raise.png"), tr("Rapprocher"), this);
edit_lower = new QAction(QIcon(":/ico/lower.png"), tr("\311loigner"), this);
edit_backward = new QAction(QIcon(":/ico/send_backward.png"),tr("Envoyer au fond"), this);
edit_forward = new QAction(QIcon(":/ico/bring_forward.png"),tr("Amener au premier plan"), this);
move = new QAction(QIcon(":/ico/select.png"), tr("D\351placer un objet"), this);
add_line = new QAction(QIcon(":/ico/line.png"), tr("Ajouter une ligne"), this);
add_ellipse = new QAction(QIcon(":/ico/ellipse.png"), tr("Ajouter une ellipse"), this);
add_circle = new QAction(QIcon(":/ico/circle.png"), tr("Ajouter un cercle"), this);
add_polygon = new QAction(QIcon(":/ico/polygon.png"), tr("Ajouter un polygone"), this);
add_text = new QAction(QIcon(":/ico/text.png"), tr("Ajouter du texte"), this);
add_arc = new QAction(QIcon(":/ico/arc.png"), tr("Ajouter un arc de cercle"), this);
add_terminal = new QAction(QIcon(":/ico/terminal.png"), tr("Ajouter une borne"), this);
add_textfield = new QAction(QIcon(":/ico/textfield.png"), tr("Ajouter un champ de texte"), this);
undo = ce_scene -> undoStack().createUndoAction(this, tr("Annuler"));
redo = ce_scene -> undoStack().createRedoAction(this, tr("Refaire"));
undo -> setIcon(QIcon(":/ico/undo.png"));
redo -> setIcon(QIcon(":/ico/redo.png"));
undo -> setShortcuts(QKeySequence::Undo);
redo -> setShortcuts(QKeySequence::Redo);
new_element -> setShortcut(QKeySequence::New);
open -> setShortcut(QKeySequence::Open);
save -> setShortcut(QKeySequence::Save);
reload -> setShortcut(QKeySequence::Refresh);
quit -> setShortcut(QKeySequence(tr("Ctrl+Q")));
selectall -> setShortcut(QKeySequence::SelectAll);
deselectall -> setShortcut(QKeySequence(tr("Ctrl+Shift+A")));
inv_select -> setShortcut(QKeySequence(tr("Ctrl+I")));
edit_delete -> setShortcut(QKeySequence(tr("Suppr")));
edit_names -> setShortcut(QKeySequence(tr("Ctrl+E")));
edit_size_hs -> setShortcut(QKeySequence(tr("Ctrl+R")));
edit_ori -> setShortcut(QKeySequence(tr("Ctrl+T")));
edit_raise -> setShortcut(QKeySequence(tr("Ctrl+Shift+Up")));
edit_lower -> setShortcut(QKeySequence(tr("Ctrl+Shift+Down")));
edit_backward -> setShortcut(QKeySequence(tr("Ctrl+Shift+End")));
edit_forward -> setShortcut(QKeySequence(tr("Ctrl+Shift+Home")));
connect(new_element, SIGNAL(triggered()), this, SLOT(slot_new()));
connect(open, SIGNAL(triggered()), this, SLOT(slot_open()));
connect(save, SIGNAL(triggered()), this, SLOT(slot_save()));
connect(save_as, SIGNAL(triggered()), this, SLOT(slot_saveAs()));
connect(reload, SIGNAL(triggered()), this, SLOT(slot_reload()));
connect(quit, SIGNAL(triggered()), this, SLOT(close()));
connect(selectall, SIGNAL(triggered()), ce_scene, SLOT(slot_selectAll()));
connect(deselectall, SIGNAL(triggered()), ce_scene, SLOT(slot_deselectAll()));
connect(inv_select, SIGNAL(triggered()), ce_scene, SLOT(slot_invertSelection()));
connect(edit_delete, SIGNAL(triggered()), ce_scene, SLOT(slot_delete()));
connect(edit_size_hs, SIGNAL(triggered()), ce_scene, SLOT(slot_editSizeHotSpot()));
connect(edit_names, SIGNAL(triggered()), ce_scene, SLOT(slot_editNames()));
connect(edit_ori, SIGNAL(triggered()), ce_scene, SLOT(slot_editOrientations()));
connect(edit_forward, SIGNAL(triggered()), ce_scene, SLOT(slot_bringForward()));
connect(edit_raise, SIGNAL(triggered()), ce_scene, SLOT(slot_raise()));
connect(edit_lower, SIGNAL(triggered()), ce_scene, SLOT(slot_lower()));
connect(edit_backward, SIGNAL(triggered()), ce_scene, SLOT(slot_sendBackward()));
connect(move, SIGNAL(triggered()), ce_scene, SLOT(slot_move()));
connect(add_line, SIGNAL(triggered()), ce_scene, SLOT(slot_addLine()));
connect(add_ellipse, SIGNAL(triggered()), ce_scene, SLOT(slot_addEllipse()));
connect(add_circle, SIGNAL(triggered()), ce_scene, SLOT(slot_addCircle()));
connect(add_polygon, SIGNAL(triggered()), ce_scene, SLOT(slot_addPolygon()));
connect(add_text, SIGNAL(triggered()), ce_scene, SLOT(slot_addText()));
connect(add_arc, SIGNAL(triggered()), ce_scene, SLOT(slot_addArc()));
connect(add_terminal, SIGNAL(triggered()), ce_scene, SLOT(slot_addTerminal()));
connect(add_textfield, SIGNAL(triggered()), ce_scene, SLOT(slot_addTextField()));
connect(move, SIGNAL(triggered()), this, SLOT(slot_setRubberBandToView()));
connect(add_line, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_ellipse, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_circle, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_polygon, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_text, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_arc, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_terminal, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(add_textfield, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
connect(ce_scene, SIGNAL(needNormalMode()), this, SLOT(slot_setNormalMode()));
move -> setCheckable(true);
add_line -> setCheckable(true);
add_ellipse -> setCheckable(true);
add_circle -> setCheckable(true);
add_polygon -> setCheckable(true);
add_text -> setCheckable(true);
add_arc -> setCheckable(true);
add_terminal -> setCheckable(true);
add_textfield -> setCheckable(true);
parts = new QActionGroup(this);
parts -> addAction(move);
parts -> addAction(add_line);
parts -> addAction(add_ellipse);
parts -> addAction(add_circle);
parts -> addAction(add_polygon);
parts -> addAction(add_text);
parts -> addAction(add_arc);
parts -> addAction(add_textfield);
parts -> addAction(add_terminal);
parts -> setExclusive(true);
parts_toolbar = new QToolBar(tr("Parties"), this);
parts_toolbar -> setObjectName("parts");
foreach (QAction *action, parts -> actions()) parts_toolbar -> addAction(action);
move -> setChecked(true);
parts_toolbar -> setAllowedAreas(Qt::AllToolBarAreas);
/*
QAction *xml_preview = new QAction(QIcon(":/ico/info.png"), tr("XML"), this);
connect(xml_preview, SIGNAL(triggered()), this, SLOT(xmlPreview()));
parts_toolbar -> addAction(xml_preview);
*/
addToolBar(Qt::LeftToolBarArea, parts_toolbar);
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateInformations()));
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateMenus()));
connect(&(ce_scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(slot_updateMenus()));
connect(&(ce_scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(slot_updateTitle()));
}
/**
Met en place les menus.
*/
void QETElementEditor::setupMenus() {
file_menu = new QMenu(tr("Fichier"), this);
edit_menu = new QMenu(tr("\311dition"), this);
display_menu = new QMenu(tr("Affichage"), this);
tools_menu = new QMenu(tr("Outils"), this);
help_menu = new QMenu(tr("Aide"), this);
file_menu -> setTearOffEnabled(true);
edit_menu -> setTearOffEnabled(true);
display_menu -> setTearOffEnabled(true);
tools_menu -> setTearOffEnabled(true);
help_menu -> setTearOffEnabled(true);
file_menu -> addAction(new_element);
file_menu -> addAction(open);
file_menu -> addAction(save);
file_menu -> addAction(save_as);
file_menu -> addSeparator();
file_menu -> addAction(reload);
file_menu -> addSeparator();
file_menu -> addAction(quit);
edit_menu -> addAction(undo);
edit_menu -> addAction(redo);
edit_menu -> addSeparator();
edit_menu -> addAction(selectall);
edit_menu -> addAction(deselectall);
edit_menu -> addAction(inv_select);
edit_menu -> addSeparator();
edit_menu -> addAction(edit_delete);
edit_menu -> addSeparator();
edit_menu -> addAction(edit_names);
edit_menu -> addAction(edit_size_hs);
edit_menu -> addAction(edit_ori);
edit_menu -> addSeparator();
edit_menu -> addAction(edit_forward);
edit_menu -> addAction(edit_raise);
edit_menu -> addAction(edit_lower);
edit_menu -> addAction(edit_backward);
// menu Affichage > Afficher
QMenu *display_toolbars = createPopupMenu();
display_toolbars -> setTearOffEnabled(true);
display_toolbars -> setTitle(tr("Afficher"));
display_menu -> addMenu(display_toolbars);
menuBar() -> addMenu(file_menu);
menuBar() -> addMenu(edit_menu);
menuBar() -> addMenu(display_menu);
/*
menuBar() -> addMenu(tools_menu);
menuBar() -> addMenu(help_menu);
*/
}
/**
Met a jour les menus
*/
void QETElementEditor::slot_updateMenus() {
bool selected_items = !ce_scene -> selectedItems().isEmpty();
edit_delete -> setEnabled(selected_items);
edit_forward -> setEnabled(selected_items);
edit_raise -> setEnabled(selected_items);
edit_lower -> setEnabled(selected_items);
edit_backward -> setEnabled(selected_items);
save -> setEnabled(!ce_scene -> undoStack().isClean());
}
/**
Met a jour le titre de la fenetre
*/
void QETElementEditor::slot_updateTitle() {
QString title = min_title;
title += " - " + ce_scene -> names().name() + " ";
if (_filename != QString()) {
if (!ce_scene -> undoStack().isClean()) title += tr("[Modifi\351]");
if (isReadOnly()) title += tr(" [lecture seule]");
}
setWindowTitle(title);
}
/**
Met en place l'interface
*/
void QETElementEditor::setupInterface() {
// editeur
ce_scene = new ElementScene(this, this);
ce_scene -> slot_move();
ce_view = new ElementView(ce_scene, this);
slot_setRubberBandToView();
setCentralWidget(ce_view);
// widget par defaut dans le QDockWidget
default_informations = new QLabel();
// panel sur le cote pour editer les parties
tools_dock = new QDockWidget(tr("Informations"), this);
tools_dock -> setObjectName("informations");
tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
tools_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
tools_dock -> setMinimumWidth(290);
addDockWidget(Qt::RightDockWidgetArea, tools_dock);
QWidget *info_widget = new QWidget();
info_widget -> setLayout(new QVBoxLayout(info_widget));
tools_dock -> setWidget(info_widget);
// panel sur le cote pour les annulations
undo_dock = new QDockWidget(tr("Annulations"), this);
undo_dock -> setObjectName("undo");
undo_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
undo_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
undo_dock -> setMinimumWidth(290);
addDockWidget(Qt::RightDockWidgetArea, undo_dock);
QUndoView* undo_view = new QUndoView(&(ce_scene -> undoStack()), this);
undo_view -> setEmptyLabel(tr("Aucune modification"));
undo_dock -> setWidget(undo_view);
// panel sur le cote pour la liste des parties
parts_list = new QListWidget(this);
parts_list -> setSelectionMode(QAbstractItemView::ExtendedSelection);
connect(ce_scene, SIGNAL(partsAdded()), this, SLOT(slot_createPartsList()));
connect(ce_scene, SIGNAL(partsRemoved()), this, SLOT(slot_createPartsList()));
connect(ce_scene, SIGNAL(partsZValueChanged()), this, SLOT(slot_createPartsList()));
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updatePartsList()));
connect(parts_list, SIGNAL(itemSelectionChanged()), this, SLOT(slot_updateSelectionFromPartsList()));
parts_dock = new QDockWidget(tr("Parties"), this);
parts_dock -> setObjectName("parts_list");
parts_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
parts_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
parts_dock -> setMinimumWidth(290);
tabifyDockWidget(undo_dock, parts_dock);
parts_dock -> setWidget(parts_list);
slot_updateInformations();
slot_createPartsList();
// barre d'etat
statusBar() -> showMessage(tr("\311diteur d'\351l\351ments"));
}
/**
Passe l'editeur d'element en mode selection : le pointeur deplace les
elements selectionnes et il est possible d'utiliser un rectangle de selection.
*/
void QETElementEditor::slot_setRubberBandToView() {
ce_view -> setDragMode(QGraphicsView::RubberBandDrag);
}
/**
Passe l'editeur d'element en mode immobile (utilise pour la lecture seule)
*/
void QETElementEditor::slot_setNoDragToView() {
ce_view -> setDragMode(QGraphicsView::NoDrag);
}
/**
Passe l'editeur en mode normal
*/
void QETElementEditor::slot_setNormalMode() {
if (!move -> isChecked()) move -> setChecked(true);
ce_view -> setDragMode(QGraphicsView::RubberBandDrag);
ce_scene -> slot_move();
}
/**
Met a jour la zone d'information et d'edition.
Si plusieurs parties sont selectionnees, seul leur nombre est affiche.
Sinon, le widget d'edition de la partie est insere.
@see CustomElementPart::elementInformations()
*/
void QETElementEditor::slot_updateInformations() {
QList<QGraphicsItem *> selected_qgis = ce_scene -> selectedItems();
QList<CustomElementPart *> selected_parts;
foreach(QGraphicsItem *qgi, selected_qgis) {
if (CustomElementPart *cep = dynamic_cast<CustomElementPart *>(qgi)) {
selected_parts.append(cep);
}
}
// recupere le layout
QLayout *layout = tools_dock -> widget() -> layout();
// enleve les widgets deja presents
QLayoutItem *qli;
while ((qli = layout -> takeAt(0)) != 0) {
if (QWidget *w = qli -> widget()) {
layout -> removeWidget(w);
w -> setParent(0);
w -> hide();
}
}
if (selected_parts.size() == 1) {
// recupere le premier CustomElementPart et en ajoute le widget d'edition
QWidget *edit_widget = selected_parts.first() -> elementInformations();
layout -> addWidget(edit_widget);
edit_widget -> show();
} else {
default_informations -> setText(
selected_parts.size() ?
QString("%1").arg(selected_parts.size()) + tr(" parties s\351lectionn\351es.") :
tr("Aucune partie s\351lectionn\351e.")
);
layout -> addWidget(default_informations);
default_informations -> show();
}
}
/**
Affiche le code XML correspondant a l'element dans son etat actuel dans
une boite de dialogue.
*/
void QETElementEditor::xmlPreview() {
QMessageBox::information(
this,
"Export XML",
ce_scene -> toXml().toString(4)
);
}
/**
Charge un fichier
@param filepath Chemin du fichier a charger
*/
void QETElementEditor::fromFile(const QString &filepath) {
bool state = true;
QString error_message;
// le fichier doit exister
QFileInfo infos_file(filepath);
if (!infos_file.exists() || !infos_file.isFile()) {
state = false;
error_message = tr("Le fichier ") + filepath + tr(" n'existe pas.");
}
// le fichier doit etre lisible
QFile file(filepath);
if (state) {
if (!file.open(QIODevice::ReadOnly)) {
state = false;
error_message = tr("Impossible d'ouvrir le fichier ") + filepath + ".";
}
}
// le fichier doit etre un document XML
QDomDocument document_xml;
if (state) {
if (!document_xml.setContent(&file)) {
state = false;
error_message = tr("Ce fichier n'est pas un document XML valide");
}
file.close();
}
if (!state) {
QMessageBox::critical(this, tr("Erreur"), error_message);
return;
}
// chargement de l'element
ce_scene -> fromXml(document_xml);
slot_createPartsList();
// gestion de la lecture seule
if (!infos_file.isWritable()) {
QMessageBox::warning(
this,
tr("\311dition en lecture seule"),
tr("Vous n'avez pas les privil\350ges n\351cessaires pour modifier cet \351lement. Il sera donc ouvert en lecture seule.")
);
setReadOnly(true);
}
// memorise le fichier
setFileName(filepath);
}
/**
Enregistre l'element vers un fichier
@param fn Chemin du fichier a enregistrer
@return true en cas de reussite, false sinon
*/
bool QETElementEditor::toFile(const QString &fn) {
QFile file(fn);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::warning(this, tr("Erreur"), tr("Impossible d'ecrire dans ce fichier"));
return(false);
}
QTextStream out(&file);
out.setCodec("UTF-8");
out << ce_scene -> toXml().toString(4);
file.close();
return(true);
}
/**
specifie si l'editeur d'element doit etre en mode lecture seule
@param ro true pour activer le mode lecture seule, false pour le desactiver
*/
void QETElementEditor::setReadOnly(bool ro) {
read_only = ro;
// active / desactive les actions
foreach (QAction *action, parts -> actions()) action -> setEnabled(!ro);
// active / desactive les interactions avec la scene
ce_view -> setInteractive(!ro);
// active / desactive l'edition de la taille, du hotspot, des noms et des orientations
selectall -> setEnabled(!ro);
deselectall -> setEnabled(!ro);
inv_select -> setEnabled(!ro);
undo -> setEnabled(!ro);
redo -> setEnabled(!ro);
edit_delete -> setEnabled(!ro);
edit_size_hs -> setEnabled(!ro);
edit_names -> setEnabled(!ro);
edit_ori -> setEnabled(!ro);
parts_list -> setEnabled(!ro);
}
/**
@return true si l'editeur d'element est en mode lecture seule
*/
bool QETElementEditor::isReadOnly() const {
return(read_only);
}
/**
Lance l'assistant de creation d'un nouvel element.
*/
void QETElementEditor::slot_new() {
NewElementWizard new_element_wizard;
new_element_wizard.exec();
}
/**
Ouvre un fichier
*/
void QETElementEditor::slot_open() {
// demande un nom de fichier a ouvrir a l'utilisateur
QString user_filename = QFileDialog::getOpenFileName(
this,
tr("Ouvrir un fichier"),
_filename.isEmpty() ? QETApp::customElementsDir() : QDir(_filename).absolutePath(),
tr("\311l\351ments QElectroTech (*.elmt);;Fichiers XML (*.xml);;Tous les fichiers (*)")
);
if (user_filename.isEmpty()) return;
QETElementEditor *cee = new QETElementEditor();
cee -> fromFile(user_filename);
cee -> show();
}
/**
Recharge l'element edite
*/
void QETElementEditor::slot_reload() {
// impossible de recharger un element non enregistre
if (_filename.isEmpty()) return;
// s'il ya des modifications, on demande a l'utilisateur s'il est certain
// de vouloir recharger
if (!ce_scene -> undoStack().isClean()) {
QMessageBox::StandardButton answer = QMessageBox::question(
this,
tr("Recharger l'\351l\351ment"),
tr("Vous avez efffectu\351 des modifications sur cet \351l\351ment. Si vous le rechargez, ces modifications seront perdues. Voulez-vous vraiment recharger l'\351l\351ment ?"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
QMessageBox::Cancel
);
if (answer != QMessageBox::Yes) return;
}
// recharge l'element
ce_scene -> reset();
fromFile(_filename);
}
/**
Enregistre l'element en cours d'edition.
Si le nom du fichier en cours n'est pas connu, cette methode equivaut a
l'action "Enregistrer sous"
@see slot_saveAs()
*/
bool QETElementEditor::slot_save() {
// si on ne connait pas le nom du fichier en cours, enregistrer revient a enregistrer sous
if (_filename.isEmpty()) return(slot_saveAs());
// sinon on enregistre dans le nom de fichier connu
bool result_save = toFile(_filename);
if (result_save) ce_scene -> undoStack().setClean();
return(result_save);
}
/**
Demande un nom de fichier a l'utilisateur et enregistre l'element
*/
bool QETElementEditor::slot_saveAs() {
// demande un nom de fichier a l'utilisateur pour enregistrer l'element
QString fn = QFileDialog::getSaveFileName(
this,
tr("Enregistrer sous"),
_filename.isEmpty() ? QETApp::customElementsDir() : QDir(_filename).absolutePath(),
tr("\311l\351ments QElectroTech (*.elmt)")
);
// si aucun nom n'est entre, renvoie faux.
if (fn.isEmpty()) return(false);
// si le nom ne se termine pas par l'extension .elmt, celle-ci est ajoutee
if (!fn.endsWith(".elmt", Qt::CaseInsensitive)) fn += ".elmt";
// tente d'enregistrer le fichier
bool result_save = toFile(fn);
// si l'enregistrement reussit, le nom du fichier est conserve
if (result_save) {
setFileName(fn);
ce_scene -> undoStack().setClean();
}
// retourne un booleen representatif de la reussite de l'enregistrement
return(result_save);
}
/**
@return true si l'element peut etre ferme.
Un element peut etre ferme s'il ne comporte aucune modification.
Si l'element comporte des modifications, la question est posee a
l'utilisateur.
*/
bool QETElementEditor::canClose() {
if (ce_scene -> undoStack().isClean()) return(true);
// demande d'abord a l'utilisateur s'il veut enregistrer l'element en cours
QMessageBox::StandardButton answer = QMessageBox::question(
this,
tr("Enregistrer l'\351l\351ment en cours ?"),
tr("Voulez-vous enregistrer l'\351l\351ment ") + ce_scene -> names().name() + tr(" ?"),
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
QMessageBox::Cancel
);
bool result;
switch(answer) {
case QMessageBox::Cancel: result = false; break; // l'utilisateur annule : echec de la fermeture
case QMessageBox::Yes: result = slot_save(); break; // l'utilisateur dit oui : la reussite depend de l'enregistrement
default: result = true; // l'utilisateur dit non ou ferme le dialogue: c'est reussi
}
return(result);
}
/**
Permet de quitter l'editeur lors de la fermeture de la fenetre principale
@param qce Le QCloseEvent correspondant a l'evenement de fermeture
*/
void QETElementEditor::closeEvent(QCloseEvent *qce) {
if (canClose()) {
writeSettings();
setAttribute(Qt::WA_DeleteOnClose);
qce -> accept();
} else qce -> ignore();
}
/**
Remplit la liste des parties
*/
void QETElementEditor::slot_createPartsList() {
parts_list -> blockSignals(true);
parts_list -> clear();
QList<QGraphicsItem *> qgis = ce_scene -> zItems(true);
for (int j = qgis.count() - 1 ; j >= 0 ; -- j) {
QGraphicsItem *qgi = qgis[j];
if (CustomElementPart *cep = dynamic_cast<CustomElementPart *>(qgi)) {
QString part_desc = cep -> name();
QListWidgetItem *qlwi = new QListWidgetItem(part_desc);
QVariant v;
v.setValue<QGraphicsItem *>(qgi);
qlwi -> setData(42, v);
parts_list -> addItem(qlwi);
qlwi -> setSelected(qgi -> isSelected());
}
}
parts_list -> blockSignals(false);
}
/**
Met a jour la selection dans la liste des parties
*/
void QETElementEditor::slot_updatePartsList() {
if (parts_list -> count() != ce_scene -> items().count()) {
slot_createPartsList();
} else {
parts_list -> blockSignals(true);
int i = 0;
QList<QGraphicsItem *> items = ce_scene -> zItems(true);
for (int j = items.count() - 1 ; j >= 0 ; -- j) {
QGraphicsItem *qgi = items[j];
QListWidgetItem *qlwi = parts_list -> item(i);
if (qlwi) qlwi -> setSelected(qgi -> isSelected());
++ i;
}
parts_list -> blockSignals(false);
}
}
/**
Met a jour la selection des parties de l'element a partir de la liste des
parties
*/
void QETElementEditor::slot_updateSelectionFromPartsList() {
ce_scene -> blockSignals(true);
parts_list -> blockSignals(true);
for (int i = 0 ; i < parts_list -> count() ; ++ i) {
QListWidgetItem *qlwi = parts_list -> item(i);
QGraphicsItem *qgi = qlwi -> data(42).value<QGraphicsItem *>();
if (qgi) {
qgi -> setSelected(qlwi -> isSelected());
}
}
parts_list -> blockSignals(false);
ce_scene -> blockSignals(false);
slot_updateInformations();
}
/// Lit les parametres de l'editeur d'element
void QETElementEditor::readSettings() {
QSettings &settings = QETApp::settings();
// dimensions et position de la fenetre
QVariant geometry = settings.value("elementeditor/geometry");
if (geometry.isValid()) restoreGeometry(geometry.toByteArray());
// etat de la fenetre (barres d'outils, docks...)
QVariant state = settings.value("elementeditor/state");
if (state.isValid()) restoreState(state.toByteArray());
}
/// Enregistre les parametres de l'editeur d'element
void QETElementEditor::writeSettings() {
QSettings &settings = QETApp::settings();
settings.setValue("elementeditor/geometry", saveGeometry());
settings.setValue("elementeditor/state", saveState());
}

200
editor/qetelementeditor.h Normal file
View File

@@ -0,0 +1,200 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CUSTOM_ELEMENT_EDITOR_H
#define CUSTOM_ELEMENT_EDITOR_H
#include <QtGui>
#include "elementscene.h"
#include "orientationset.h"
class ElementView;
/**
Cette classe represente un editeur d'element. Elle permet a l'utilisateur
de dessiner, modifier et parametrer un element electrique. Le dessin se
fait par ajout de parties (Part).
*/
class QETElementEditor : public QMainWindow {
Q_OBJECT
// constructeur, destructeur
public:
QETElementEditor(QWidget * = 0);
virtual ~QETElementEditor();
private:
QETElementEditor(const QETElementEditor &);
// attributs
private:
/// booleen indiquant si l'editeur est en mode "lecture seule" ou non
bool read_only;
/// menus
QMenu *file_menu, *edit_menu, *display_menu, *tools_menu, *help_menu;
/// vue sur la scene d'edition
ElementView *ce_view;
/// scene d'edition
ElementScene *ce_scene;
/// container pour les widgets d'edition des parties
QDockWidget *tools_dock;
/// container pour la liste des annulations
QDockWidget *undo_dock;
/// Container pour la liste des parties
QDockWidget *parts_dock;
/// Liste des parties
QListWidget *parts_list;
/// actions du menu fichier
QAction *new_element, *open, *save, *save_as, *reload, *quit;
/// actions du menu edition
QAction *selectall, *deselectall, *inv_select;
QAction *undo, *redo;
QAction *edit_delete, *edit_size_hs, *edit_names, *edit_ori;
QAction *edit_raise, *edit_lower, *edit_backward, *edit_forward;
/// barre d'outils
QToolBar *parts_toolbar;
/// actions de la barre d'outils
QActionGroup *parts;
QAction *move, *add_line, *add_circle, *add_ellipse, *add_polygon, *add_text;
QAction *add_arc, *add_terminal, *add_textfield;
/// label affiche lors de la selection de plusieurs elements
QLabel *default_informations;
/// titre minimal
QString min_title;
/// Nom de fichier
QString _filename;
// methodes
public:
void setSize(const QSize &);
QSize size() const;
void setHotspot(const QPoint &);
QPoint hotspot() const;
void setNames(const NamesList &);
void setOrientations(const OrientationSet &orientation_set);
OrientationSet orientations() const;
void setFileName(const QString &);
QString fileName() const;
void setReadOnly(bool);
bool isReadOnly() const;
void fromFile(const QString &);
bool toFile(const QString &);
ElementScene *elementScene() const;
void readSettings();
void writeSettings();
protected:
void closeEvent(QCloseEvent *);
private:
void setupActions();
void setupMenus();
void setupInterface();
bool canClose();
public slots:
void slot_new();
void slot_open();
void slot_reload();
bool slot_save();
bool slot_saveAs();
void slot_setRubberBandToView();
void slot_setNoDragToView();
void slot_setNormalMode();
void slot_updateInformations();
void slot_updateMenus();
void slot_updateTitle();
void slot_createPartsList();
void slot_updatePartsList();
void slot_updateSelectionFromPartsList();
void xmlPreview();
};
/**
@param siz La nouvelle taille de l'element edite
*/
inline void QETElementEditor::setSize(const QSize &siz) {
ce_scene -> setWidth(siz.width());
ce_scene -> setHeight(siz.height());
}
/**
@return la taille de l'element edite
*/
inline QSize QETElementEditor::size() const {
return(
QSize(
ce_scene -> width(),
ce_scene -> height()
)
);
}
/**
@param hs Le nouveau point de saisie de l'element edite
*/
inline void QETElementEditor::setHotspot(const QPoint &hs) {
ce_scene -> setHotspot(hs);
}
/**
@return le point de saisie de l'element edite
*/
inline QPoint QETElementEditor::hotspot() const {
return(ce_scene -> hotspot());
}
/**
@param nameslist le nouvel ensemble de noms de l'element edite
*/
inline void QETElementEditor::setNames(const NamesList &nameslist) {
ce_scene -> setNames(nameslist);
}
/**
@param orientation_set le nouvel ensemble d'orientations de l'element edite
*/
inline void QETElementEditor::setOrientations(const OrientationSet &orientation_set) {
ce_scene -> setOrientations(orientation_set);
}
/**
@return le nouvel ensemble d'orientations de l'element edite
*/
inline OrientationSet QETElementEditor::orientations() const {
return(ce_scene -> orientations());
}
/**
@param fn Le nouveau nom de fichier de l'element edite
*/
inline void QETElementEditor::setFileName(const QString &fn) {
_filename = fn;
slot_updateTitle();
}
/**
@return le nomde fichier de l'element edite
*/
inline QString QETElementEditor::fileName() const {
return(_filename);
}
/**
@return la scene d'edition de l'element
*/
inline ElementScene *QETElementEditor::elementScene() const {
return(ce_scene);
}
#endif

180
editor/styleeditor.cpp Normal file
View File

@@ -0,0 +1,180 @@
/*
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "styleeditor.h"
#include "customelementgraphicpart.h"
/**
Constructeur
@param editor L'editeur d'element concerne
@param p La partie a editer
@param parent le Widget parent
*/
StyleEditor::StyleEditor(QETElementEditor *editor, CustomElementGraphicPart *p, QWidget *parent) : ElementItemEditor(editor, parent), part(p) {
// couleur
color = new QButtonGroup(this);
color -> addButton(black_color = new QRadioButton(tr("Noir")), CustomElementGraphicPart::BlackColor);
color -> addButton(white_color = new QRadioButton(tr("Blanc")), CustomElementGraphicPart::WhiteColor);
// style
style = new QButtonGroup(this);
style -> addButton(normal_style = new QRadioButton(tr("Normal")), CustomElementGraphicPart::NormalStyle);
style -> addButton(dashed_style = new QRadioButton(tr("Pointill\351")), CustomElementGraphicPart::DashedStyle);
style -> button(part -> lineStyle()) -> setChecked(true);
// epaisseur
weight = new QButtonGroup(this);
weight -> addButton(none_weight = new QRadioButton(tr("Nulle")), CustomElementGraphicPart::NoneWeight);
weight -> addButton(thin_weight = new QRadioButton(tr("Fine")), CustomElementGraphicPart::ThinWeight);
weight -> addButton(normal_weight = new QRadioButton(tr("Normale")), CustomElementGraphicPart::NormalWeight);
// remplissage
filling = new QButtonGroup(this);
filling -> addButton(no_filling = new QRadioButton(tr("Aucun")), CustomElementGraphicPart::NoneFilling );
filling -> addButton(black_filling = new QRadioButton(tr("Noir")), CustomElementGraphicPart::BlackFilling);
filling -> addButton(white_filling = new QRadioButton(tr("Blanc")), CustomElementGraphicPart::WhiteFilling);
// antialiasing
antialiasing = new QCheckBox(tr("Antialiasing"));
updateForm();
main_layout = new QVBoxLayout();
main_layout -> addWidget(antialiasing);
main_layout -> addWidget(new QLabel("<u>" + tr("Trait :") + "</u> "));
QHBoxLayout *color_layout = new QHBoxLayout();
color_layout -> addWidget(new QLabel(tr("Couleur : ")));
color_layout -> addWidget(black_color);
color_layout -> addWidget(white_color);
color_layout -> addStretch();
main_layout -> addItem(color_layout);
QHBoxLayout *style_layout = new QHBoxLayout();
style_layout -> addWidget(new QLabel(tr("Style : ")));
style_layout -> addWidget(normal_style);
style_layout -> addWidget(dashed_style);
style_layout -> addStretch();
main_layout -> addItem(style_layout);
QHBoxLayout *weight_layout = new QHBoxLayout();
weight_layout -> addWidget(new QLabel(tr("\311paisseur : ")));
weight_layout -> addWidget(none_weight);
weight_layout -> addWidget(thin_weight);
weight_layout -> addWidget(normal_weight);
weight_layout -> addStretch();
main_layout -> addItem(weight_layout);
main_layout -> addWidget(new QLabel("<u>" + tr("Remplissage :") + "</u> "));
QHBoxLayout *filling_layout = new QHBoxLayout();
filling_layout -> addWidget(no_filling);
filling_layout -> addWidget(black_filling);
filling_layout -> addWidget(white_filling);
filling_layout -> addStretch();
main_layout -> addItem(filling_layout);
main_layout -> addStretch();
setLayout(main_layout);
}
/// Destructeur
StyleEditor::~StyleEditor() {
}
/**
Met a jour le style de la partie a partir des donnees du formulaire
*/
void StyleEditor::updatePart() {
// applique l'antialiasing
part -> setAntialiased(antialiasing -> isChecked());
// applique la couleur
part -> setColor(static_cast<CEGP::Color>(color -> checkedId()));
// applique le style
part -> setLineStyle(static_cast<CEGP::LineStyle>(style -> checkedId()));
// applique l'epaisseur
part -> setLineWeight(static_cast<CEGP::LineWeight>(weight -> checkedId()));
// applique le remplissage
part -> setFilling(static_cast<CEGP::Filling>(filling -> checkedId()));
}
/// Met a jour l'antialiasing et cree un objet d'annulation
void StyleEditor::updatePartAntialiasing() { addChangePartCommand("style antialiasing", part, "antialias", antialiasing -> isChecked()); }
/// Met a jour la couleur du trait et cree un objet d'annulation
void StyleEditor::updatePartColor() { addChangePartCommand("style couleur", part, "color", color -> checkedId()); }
/// Met a jour le style du trait et cree un objet d'annulation
void StyleEditor::updatePartLineStyle() { addChangePartCommand("style ligne", part, "line-style", style -> checkedId()); }
/// Met a jour l'epaisseur du trait et cree un objet d'annulation
void StyleEditor::updatePartLineWeight() { addChangePartCommand("style epaisseur", part, "line-weight", weight -> checkedId()); }
/// Met a jour la couleur de fond et cree un objet d'annulation
void StyleEditor::updatePartFilling() { addChangePartCommand("style remplissage", part, "filling", filling -> checkedId()); }
/**
Met a jour le formulaire d'edition
*/
void StyleEditor::updateForm() {
activeConnections(false);
// lit l'antialiasing
antialiasing -> setChecked(part -> antialiased());
// lit la couleur
color -> button(part -> color()) -> setChecked(true);
// lit le style
style -> button(part -> lineStyle()) -> setChecked(true);
// lit l'epaisseur
weight -> button(part -> lineWeight()) -> setChecked(true);
// lit le remplissage
filling -> button(part -> filling()) -> setChecked(true);
activeConnections(true);
}
/**
Ajoute un widget en bas de l'editeur de style
@param w Widget a inserer
*/
void StyleEditor::appendWidget(QWidget *w) {
main_layout -> insertWidget(7, w);
}
/**
Active ou desactive les connexionx signaux/slots entre les widgets internes.
@param active true pour activer les connexions, false pour les desactiver
*/
void StyleEditor::activeConnections(bool active) {
if (active) {
connect(color, SIGNAL(buttonClicked(int)), this, SLOT(updatePartColor()));
connect(style, SIGNAL(buttonClicked(int)), this, SLOT(updatePartLineStyle()));
connect(weight, SIGNAL(buttonClicked(int)), this, SLOT(updatePartLineWeight()));
connect(filling, SIGNAL(buttonClicked(int)), this, SLOT(updatePartFilling()));
connect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePartAntialiasing()));
} else {
disconnect(color, SIGNAL(buttonClicked(int)), this, SLOT(updatePartColor()));
disconnect(style, SIGNAL(buttonClicked(int)), this, SLOT(updatePartLineStyle()));
disconnect(weight, SIGNAL(buttonClicked(int)), this, SLOT(updatePartLineWeight()));
disconnect(filling, SIGNAL(buttonClicked(int)), this, SLOT(updatePartFilling()));
disconnect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePartAntialiasing()));
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -21,36 +21,34 @@
#include "elementitemeditor.h"
class CustomElementGraphicPart;
/**
This class provides a widget to edit styles (color, pen style and thickness,
filling, antialiasing) common to most primitives within the element editor.
Its appendWidget() method makes the insertion of another widget below it
easier.
Cette classe represente un widget d'edition des styles que peut comporter
une partie d'elements (couleur, epaisseur et style du trait, remplissage,
antialiasing). Elle peut accueillir un widget sous cette interface grace a
la methode appendWidget.
*/
class StyleEditor : public ElementItemEditor {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
StyleEditor(QETElementEditor *, CustomElementGraphicPart * = 0, QWidget * = 0);
StyleEditor(QETElementEditor *, CustomElementGraphicPart *, QWidget * = 0);
virtual ~StyleEditor();
private:
StyleEditor(const StyleEditor &);
// attributes
// attributs
private:
CustomElementGraphicPart *part;
QVBoxLayout *main_layout;
QButtonGroup *style, *weight;
QRadioButton *black_color, *white_color, *normal_style, *dashed_style, *dashdotted_style, *dotted_style, *green_color, *red_color, *blue_color;
QButtonGroup *color, *style, *weight, *filling;
QRadioButton *black_color, *white_color, *normal_style, *dashed_style;
QRadioButton *none_weight, *thin_weight, *normal_weight, *no_filling;
QRadioButton *black_filling, *white_filling, *green_filling, *red_filling, *blue_filling;
QRadioButton *black_filling, *white_filling;
QCheckBox *antialiasing;
QComboBox *filling_color, *outline_color;
// methods
//methodes
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
void appendWidget(QWidget *w);
public slots:
void updatePart();

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -17,7 +17,6 @@
*/
#include "terminaleditor.h"
#include "partterminal.h"
#include "qeticons.h"
/**
Constructeur
@@ -25,10 +24,9 @@
@param term La borne a editer
@param parent QWidget parent de ce widget
*/
TerminalEditor::TerminalEditor(QETElementEditor *editor, PartTerminal *term, QWidget *parent) :
ElementItemEditor(editor, parent),
part(term)
{
TerminalEditor::TerminalEditor(QETElementEditor *editor, PartTerminal *term, QWidget *parent) : ElementItemEditor(editor, parent) {
part = term;
qle_x = new QLineEdit();
qle_y = new QLineEdit();
@@ -36,10 +34,10 @@ TerminalEditor::TerminalEditor(QETElementEditor *editor, PartTerminal *term, QWi
qle_y -> setValidator(new QDoubleValidator(qle_y));
orientation = new QComboBox();
orientation -> addItem(QET::Icons::North, tr("Nord"), QET::North);
orientation -> addItem(QET::Icons::East, tr("Est"), QET::East);
orientation -> addItem(QET::Icons::South, tr("Sud"), QET::South);
orientation -> addItem(QET::Icons::West, tr("Ouest"), QET::West);
orientation -> addItem(QIcon(":/ico/north.png"), tr("Nord"), QET::North);
orientation -> addItem(QIcon(":/ico/east.png"), tr("Est"), QET::East);
orientation -> addItem(QIcon(":/ico/south.png"), tr("Sud"), QET::South);
orientation -> addItem(QIcon(":/ico/west.png"), tr("Ouest"), QET::West);
QVBoxLayout *main_layout = new QVBoxLayout();
main_layout -> addWidget(new QLabel(tr("Position : ")));
@@ -66,40 +64,10 @@ TerminalEditor::TerminalEditor(QETElementEditor *editor, PartTerminal *term, QWi
TerminalEditor::~TerminalEditor() {
};
/**
Permet de specifier a cet editeur quelle primitive il doit editer. A noter
qu'un editeur peut accepter ou refuser d'editer une primitive.
L'editeur de borne acceptera d'editer la primitive new_part s'il s'agit d'un
objet de la classe PartTerminal.
@param new_part Nouvelle primitive a editer
@return true si l'editeur a accepter d'editer la primitive, false sinon
*/
bool TerminalEditor::setPart(CustomElementPart *new_part) {
if (!new_part) {
part = 0;
return(true);
}
if (PartTerminal *part_terminal = dynamic_cast<PartTerminal *>(new_part)) {
part = part_terminal;
updateForm();
return(true);
} else {
return(false);
}
}
/**
@return la primitive actuellement editee, ou 0 si ce widget n'en edite pas
*/
CustomElementPart *TerminalEditor::currentPart() const {
return(part);
}
/**
Met a jour la borne a partir des donnees du formulaire
*/
void TerminalEditor::updateTerminal() {
if (!part) return;
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
part -> setOrientation(
static_cast<QET::Orientation>(
@@ -121,7 +89,6 @@ void TerminalEditor::updateTerminalO() { addChangePartCommand(tr("orientation"),
Met a jour le formulaire d'edition
*/
void TerminalEditor::updateForm() {
if (!part) return;
activeConnections(false);
qle_x -> setText(part -> property("x").toString());
qle_y -> setText(part -> property("y").toString());

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -21,28 +21,26 @@
#include "elementitemeditor.h"
class PartTerminal;
/**
This class provides a widget to edit terminals within the element editor.
Cette classe represente un editeur de borne.
Elle permet d'editer a travers une interface graphique les
proprietes d'une borne d'element.
*/
class TerminalEditor : public ElementItemEditor {
Q_OBJECT
// Constructors, destructor
// Constructeurs, destructeur
public:
TerminalEditor(QETElementEditor *, PartTerminal * = 0, QWidget * = 0);
TerminalEditor(QETElementEditor *, PartTerminal *, QWidget * = 0);
virtual ~TerminalEditor();
private:
TerminalEditor(const TerminalEditor &);
// attributes
// attributs
private:
PartTerminal *part;
QLineEdit *qle_x, *qle_y;
QComboBox *orientation;
// methods
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
// methodes
public slots:
void updateTerminal();
void updateTerminalX();

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -17,8 +17,6 @@
*/
#include "texteditor.h"
#include "parttext.h"
#include "qetapp.h"
#include "qtextorientationspinboxwidget.h"
/**
Constructeur
@@ -26,24 +24,14 @@
@param text Champ de texte a editer
@param parent QWidget parent de ce widget
*/
TextEditor::TextEditor(QETElementEditor *editor, PartText *text, QWidget *parent) :
ElementItemEditor(editor, parent),
part(text)
{
TextEditor::TextEditor(QETElementEditor *editor, PartText *text, QWidget *parent) : ElementItemEditor(editor, parent) {
part = text;
qle_x = new QLineEdit();
qle_y = new QLineEdit();
qle_text = new QLineEdit();
font_size = new QSpinBox();
font_size -> setRange(0, 144);
black_color_ = new QRadioButton(tr("Noir", "element text part color"));
white_color_ = new QRadioButton(tr("Blanc", "element text part color"));
color_ = new QButtonGroup(this);
color_ -> addButton(black_color_, true);
color_ -> addButton(white_color_, false);
connect(color_, SIGNAL(buttonClicked(int)), this, SLOT(updateTextC()));
QLabel *rotation_angle_label = new QLabel(tr("Angle de rotation : "));
rotation_angle_label -> setWordWrap(true);
rotation_angle_ = QETApp::createTextOrientationSpinBoxWidget();
qle_x -> setValidator(new QDoubleValidator(qle_x));
qle_y -> setValidator(new QDoubleValidator(qle_y));
@@ -63,23 +51,10 @@ TextEditor::TextEditor(QETElementEditor *editor, PartText *text, QWidget *parent
fs -> addWidget(font_size);
main_layout -> addLayout(fs);
QHBoxLayout *color_layout = new QHBoxLayout();
color_layout -> addWidget(new QLabel(tr("Couleur : ")));
color_layout -> addWidget(black_color_);
color_layout -> addWidget(white_color_);
color_layout -> addStretch();
main_layout -> addLayout(color_layout);
QHBoxLayout *t = new QHBoxLayout();
t -> addWidget(new QLabel(tr("Texte : ")));
t -> addWidget(qle_text);
QHBoxLayout *rotation_angle_layout = new QHBoxLayout();
rotation_angle_layout -> addWidget(rotation_angle_label);
rotation_angle_layout -> addWidget(rotation_angle_);
main_layout -> addLayout(t);
main_layout -> addLayout(rotation_angle_layout);
main_layout -> addStretch();
setLayout(main_layout);
@@ -92,40 +67,10 @@ TextEditor::TextEditor(QETElementEditor *editor, PartText *text, QWidget *parent
TextEditor::~TextEditor() {
}
/**
Permet de specifier a cet editeur quelle primitive il doit editer. A noter
qu'un editeur peut accepter ou refuser d'editer une primitive.
L'editeur de texte statique acceptera d'editer la primitive new_part s'il
s'agit d'un objet de la classe PartText.
@param new_part Nouvelle primitive a editer
@return true si l'editeur a accepter d'editer la primitive, false sinon
*/
bool TextEditor::setPart(CustomElementPart *new_part) {
if (!new_part) {
part = 0;
return(true);
}
if (PartText *part_text = dynamic_cast<PartText *>(new_part)) {
part = part_text;
updateForm();
return(true);
} else {
return(false);
}
}
/**
@return la primitive actuellement editee, ou 0 si ce widget n'en edite pas
*/
CustomElementPart *TextEditor::currentPart() const {
return(part);
}
/**
Met a jour le champ de texte a partir des donnees du formulaire
*/
void TextEditor::updateText() {
if (!part) return;
part -> setProperty("size", font_size -> value());
part -> setPlainText(qle_text -> text());
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
@@ -136,28 +81,19 @@ void TextEditor::updateTextX() { addChangePartCommand(tr("abscisse"), part, "
/// Met a jour l'ordonnee de la position du texte et cree un objet d'annulation
void TextEditor::updateTextY() { addChangePartCommand(tr("ordonn\351e"), part, "y", qle_y -> text().toDouble()); updateForm(); }
/// Met a jour le texte et cree un objet d'annulation
void TextEditor::updateTextT() { addChangePartCommand(tr("contenu"), part, "text", qle_text -> text()); }
void TextEditor::updateTextT() { addChangePartCommand(tr("texte"), part, "text", qle_text -> text()); }
/// Met a jour la taille du texte et cree un objet d'annulation
void TextEditor::updateTextS() { addChangePartCommand(tr("taille"), part, "size", font_size -> value()); }
/// Update the text color and create an undo object
void TextEditor::updateTextC() { addChangePartCommand(tr("couleur", "undo caption"), part, "color", color_ -> checkedId()); }
/// Met a jour l'angle de rotation du champ de texte et cree un objet d'annulation
void TextEditor::updateTextRotationAngle() { addChangePartCommand(tr("angle de rotation"), part, "rotation angle", rotation_angle_ -> value()); }
/**
Met a jour le formulaire a partir du champ de texte
*/
void TextEditor::updateForm() {
if (!part) return;
activeConnections(false);
qle_x -> setText(part -> property("x").toString());
qle_y -> setText(part -> property("y").toString());
qle_text -> setText(part -> property("text").toString());
font_size -> setValue(part -> property("size").toInt());
if (QAbstractButton *button = color_ -> button(part -> property("color").toBool())) {
button -> setChecked(true);
}
rotation_angle_ -> setValue(part -> property("rotation angle").toDouble());
activeConnections(true);
}
@@ -167,12 +103,10 @@ void TextEditor::activeConnections(bool active) {
connect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTextY()));
connect(qle_text, SIGNAL(editingFinished()), this, SLOT(updateTextT()));
connect(font_size, SIGNAL(editingFinished()), this, SLOT(updateTextS()));
connect(rotation_angle_, SIGNAL(editingFinished()), this, SLOT(updateTextRotationAngle()));
} else {
disconnect(qle_x, SIGNAL(editingFinished()), this, SLOT(updateTextX()));
disconnect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTextY()));
disconnect(qle_text, SIGNAL(editingFinished()), this, SLOT(updateTextT()));
disconnect(font_size, SIGNAL(editingFinished()), this, SLOT(updateTextS()));
disconnect(rotation_angle_, SIGNAL(editingFinished()), this, SLOT(updateTextRotationAngle()));
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,42 +20,33 @@
#include <QtGui>
#include "elementitemeditor.h"
class PartText;
class QTextOrientationSpinBoxWidget;
/**
This class provides a widget to edit static texts within the element
editor.
Cette classe represente un editeur de champ de texte non editable
Elle permet d'editer a travers une interface graphique les
proprietes d'un champ de texte non editable.
*/
class TextEditor : public ElementItemEditor {
Q_OBJECT
// Constructors, destructor
// Constructeurs, destructeur
public:
TextEditor(QETElementEditor *, PartText * = 0, QWidget * = 0);
TextEditor(QETElementEditor *, PartText *, QWidget * = 0);
virtual ~TextEditor();
private:
TextEditor(const TextEditor &);
// attributes
// attributs
private:
PartText *part;
QLineEdit *qle_x, *qle_y, *qle_text;
QSpinBox *font_size;
QButtonGroup *color_;
QRadioButton *black_color_, *white_color_;
QTextOrientationSpinBoxWidget *rotation_angle_;
// methods
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
// methodes
public slots:
void updateText();
void updateTextX();
void updateTextY();
void updateTextT();
void updateTextS();
void updateTextC();
void updateTextRotationAngle();
void updateForm();
private:

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -17,28 +17,23 @@
*/
#include "textfieldeditor.h"
#include "parttextfield.h"
#include "qtextorientationspinboxwidget.h"
#include "qetapp.h"
/**
Constructeur
@param editor L'editeur d'element concerne
@param textfield Le champ de texte a editer
@param parent QWidget parent
*/
TextFieldEditor::TextFieldEditor(QETElementEditor *editor, PartTextField *textfield, QWidget *parent) :
ElementItemEditor(editor, parent),
part(textfield)
{
TextFieldEditor::TextFieldEditor(QETElementEditor *editor, PartTextField *textfield, QWidget *parent) : ElementItemEditor(editor, parent) {
part = textfield;
qle_x = new QLineEdit();
qle_y = new QLineEdit();
qle_text = new QLineEdit();
font_size = new QSpinBox();
font_size -> setRange(0, 144);
rotate = new QCheckBox(tr("Ne pas subir les rotations de l'\351l\351ment parent"));
rotate = new QCheckBox(tr("Maintenir horizontal malgr\351\n les rotations de l'\351l\351ment"));
rotate -> setChecked(true);
QLabel *rotation_angle_label = new QLabel(tr("Angle de rotation par d\351faut : "));
rotation_angle_label -> setWordWrap(true);
rotation_angle_ = QETApp::createTextOrientationSpinBoxWidget();
qle_x -> setValidator(new QDoubleValidator(qle_x));
qle_y -> setValidator(new QDoubleValidator(qle_y));
@@ -63,11 +58,6 @@ TextFieldEditor::TextFieldEditor(QETElementEditor *editor, PartTextField *textfi
t -> addWidget(qle_text);
main_layout -> addLayout(t);
QHBoxLayout *rotation_angle_layout = new QHBoxLayout();
rotation_angle_layout -> addWidget(rotation_angle_label);
rotation_angle_layout -> addWidget(rotation_angle_);
main_layout -> addLayout(rotation_angle_layout);
QHBoxLayout *r = new QHBoxLayout();
r -> addWidget(rotate);
main_layout -> addLayout(r);
@@ -81,40 +71,10 @@ TextFieldEditor::TextFieldEditor(QETElementEditor *editor, PartTextField *textfi
TextFieldEditor::~TextFieldEditor() {
}
/**
Permet de specifier a cet editeur quelle primitive il doit editer. A noter
qu'un editeur peut accepter ou refuser d'editer une primitive.
L'editeur de texte dynamique acceptera d'editer la primitive new_part s'il
s'agit d'un objet de la classe PartTextField.
@param new_part Nouvelle primitive a editer
@return true si l'editeur a accepter d'editer la primitive, false sinon
*/
bool TextFieldEditor::setPart(CustomElementPart *new_part) {
if (!new_part) {
part = 0;
return(true);
}
if (PartTextField *part_textfield = dynamic_cast<PartTextField *>(new_part)) {
part = part_textfield;
updateForm();
return(true);
} else {
return(false);
}
}
/**
@return la primitive actuellement editee, ou 0 si ce widget n'en edite pas
*/
CustomElementPart *TextFieldEditor::currentPart() const {
return(part);
}
/**
Met a jour le champ de texte a partir des donnees du formulaire
*/
void TextFieldEditor::updateTextField() {
if (!part) return;
part -> setProperty("size", font_size -> value());
part -> setPlainText(qle_text -> text());
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
@@ -126,26 +86,22 @@ void TextFieldEditor::updateTextFieldX() { addChangePartCommand(tr("abscisse"),
/// Met a jour l'ordonnee de la position du champ de texte et cree un objet d'annulation
void TextFieldEditor::updateTextFieldY() { addChangePartCommand(tr("ordonn\351e"), part, "y", qle_y -> text().toDouble()); updateForm(); }
/// Met a jour le texte du champ de texte et cree un objet d'annulation
void TextFieldEditor::updateTextFieldT() { addChangePartCommand(tr("contenu"), part, "text", qle_text -> text()); }
void TextFieldEditor::updateTextFieldT() { addChangePartCommand(tr("texte"), part, "text", qle_text -> text()); }
/// Met a jour la taille du champ de texte et cree un objet d'annulation
void TextFieldEditor::updateTextFieldS() { addChangePartCommand(tr("taille"), part, "size", font_size -> value()); }
/// Met a jour la taille du champ de texte et cree un objet d'annulation
void TextFieldEditor::updateTextFieldR() { addChangePartCommand(tr("propri\351t\351"), part, "rotate", !rotate -> isChecked()); }
/// Met a jour l'angle de rotation du champ de texte et cree un objet d'annulation
void TextFieldEditor::updateTextFieldRotationAngle() { addChangePartCommand(tr("angle de rotation"), part, "rotation angle", rotation_angle_ -> value()); }
/**
Met a jour le formulaire d'edition
*/
void TextFieldEditor::updateForm() {
if (!part) return;
activeConnections(false);
qle_x -> setText(part -> property("x").toString());
qle_y -> setText(part -> property("y").toString());
qle_text -> setText(part -> property("text").toString());
font_size -> setValue(part -> property("size").toInt());
rotate -> setChecked(!part -> property("rotate").toBool());
rotation_angle_ -> setValue(part -> property("rotation angle").toDouble());
activeConnections(true);
}
@@ -160,13 +116,11 @@ void TextFieldEditor::activeConnections(bool active) {
connect(qle_text, SIGNAL(editingFinished()), this, SLOT(updateTextFieldT()));
connect(font_size, SIGNAL(editingFinished()), this, SLOT(updateTextFieldS()));
connect(rotate, SIGNAL(stateChanged(int)), this, SLOT(updateTextFieldR()));
connect(rotation_angle_, SIGNAL(editingFinished()), this, SLOT(updateTextFieldRotationAngle()));
} else {
disconnect(qle_x, SIGNAL(editingFinished()), this, SLOT(updateTextFieldX()));
disconnect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTextFieldY()));
disconnect(qle_text, SIGNAL(editingFinished()), this, SLOT(updateTextFieldT()));
disconnect(font_size, SIGNAL(editingFinished()), this, SLOT(updateTextFieldS()));
disconnect(rotate, SIGNAL(stateChanged(int)), this, SLOT(updateTextFieldR()));
disconnect(rotation_angle_, SIGNAL(editingFinished()), this, SLOT(updateTextFieldRotationAngle()));
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -20,32 +20,29 @@
#include <QtGui>
#include "elementitemeditor.h"
class PartTextField;
class QTextOrientationSpinBoxWidget;
/**
This class provides a widget to edit text fields within the element editor.
Cette classe represente un editeur de champ de texte
Elle permet d'editer a travers une interface graphique les
proprietes d'un champ de texte : taille de la police, texte par
defaut et position.
*/
class TextFieldEditor : public ElementItemEditor {
Q_OBJECT
// Constructors, destructor
// Constructeurs, destructeur
public:
TextFieldEditor(QETElementEditor *, PartTextField * = 0, QWidget * = 0);
TextFieldEditor(QETElementEditor *, PartTextField *, QWidget * = 0);
virtual ~TextFieldEditor();
private:
TextFieldEditor(const TextFieldEditor &);
// attributes
// attributs
private:
PartTextField *part;
QLineEdit *qle_x, *qle_y, *qle_text;
QSpinBox *font_size;
QCheckBox *rotate;
QTextOrientationSpinBoxWidget *rotation_angle_;
// methods
public:
virtual bool setPart(CustomElementPart *);
virtual CustomElementPart *currentPart() const;
// methodes
public slots:
void updateTextField();
void updateTextFieldX();
@@ -53,7 +50,6 @@ class TextFieldEditor : public ElementItemEditor {
void updateTextFieldT();
void updateTextFieldS();
void updateTextFieldR();
void updateTextFieldRotationAngle();
void updateForm();
private:

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -27,11 +27,8 @@
Constructeur pour un element sans scene ni parent
*/
Element::Element(QGraphicsItem *parent, Diagram *scene) :
QObject(),
QGraphicsItem(parent, scene),
internal_connections_(false),
must_highlight_(false),
first_move_(true)
internal_connections(false)
{
setZValue(10);
}
@@ -42,21 +39,6 @@ Element::Element(QGraphicsItem *parent, Diagram *scene) :
Element::~Element() {
}
/**
@return true si l'element est mis en evidence
*/
bool Element::isHighlighted() const {
return(must_highlight_);
}
/**
@param hl true pour mettre l'element en evidence, false sinon
*/
void Element::setHighlighted(bool hl) {
must_highlight_ = hl;
update();
}
/**
Methode principale de dessin de l'element
@param painter Le QPainter utilise pour dessiner l'elment
@@ -65,9 +47,9 @@ void Element::setHighlighted(bool hl) {
*/
void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) {
#ifndef Q_WS_WIN
#ifdef Q_WS_X11
// corrige un bug de rendu ne se produisant que lors du rendu sur QGraphicsScene sous X11 au zoom par defaut
static bool must_correct_rendering_bug = QETApp::settings().value("correct-rendering", false).toBool();
static bool must_correct_rendering_bug = !QString(qVersion()).startsWith("4.4");
if (must_correct_rendering_bug) {
Diagram *dia = diagram();
if (dia && options -> levelOfDetail == 1.0 && widget) {
@@ -81,8 +63,6 @@ void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options,
}
}
#endif
if (must_highlight_) drawHighlight(painter, options);
// Dessin de l'element lui-meme
paint(painter, options);
@@ -114,13 +94,6 @@ QSize Element::setSize(int wid, int hei) {
return(dimensions = QSize(wid, hei));
}
/**
@return la taille de l'element sur le schema
*/
QSize Element::size() const {
return(dimensions);
}
/**
Definit le hotspot de l'element par rapport au coin superieur gauche de son rectangle delimitant.
Necessite que la taille ait deja ete definie
@@ -164,8 +137,8 @@ void Element::deselect() {
@return La pixmap de l'element
*/
QPixmap Element::pixmap() {
if (preview.isNull()) updatePixmap(); // on genere la pixmap si ce n'est deja fait
return(preview);
if (apercu.isNull()) updatePixmap(); // on genere la pixmap si ce n'est deja fait
return(apercu);
}
/**
@@ -182,9 +155,19 @@ bool Element::setOrientation(QET::Orientation o) {
rotate(rotation_value);
ori.setCurrent(o);
update();
foreach(QGraphicsItem *qgi, childItems()) {
if (Terminal *p = qgraphicsitem_cast<Terminal *>(qgi)) {
p -> updateConductor();
foreach(QGraphicsItem *qgi, children()) {
if (Terminal *p = qgraphicsitem_cast<Terminal *>(qgi)) p -> updateConductor();
else if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(qgi)) {
// applique une rotation contraire si besoin
if (!eti -> followParentRotations()) {
QMatrix new_matrix = eti -> matrix();
qreal dx = eti -> boundingRect().width() / 2.0;
qreal dy = eti -> boundingRect().height() / 2.0;
new_matrix.translate(dx, dy);
new_matrix.rotate(-rotation_value);
new_matrix.translate(-dx, -dy);
eti -> setMatrix(new_matrix);
}
}
}
return(true);
@@ -197,8 +180,7 @@ bool Element::setOrientation(QET::Orientation o) {
@param painter Le QPainter a utiliser pour dessiner les axes
@param options Les options de style a prendre en compte
*/
void Element::drawAxes(QPainter *painter, const QStyleOptionGraphicsItem *options) {
Q_UNUSED(options);
void Element::drawAxes(QPainter *painter, const QStyleOptionGraphicsItem *) {
painter -> setPen(Qt::blue);
painter -> drawLine(0, 0, 10, 0);
painter -> drawLine(7,-3, 10, 0);
@@ -213,11 +195,10 @@ void Element::drawAxes(QPainter *painter, const QStyleOptionGraphicsItem *option
/**
Dessine le cadre de selection de l'element de maniere systematiquement non antialiasee.
@param painter Le QPainter a utiliser pour dessiner les bornes.
@param qp Le QPainter a utiliser pour dessiner les bornes.
@param options Les options de style a prendre en compte
*/
void Element::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *options) {
Q_UNUSED(options);
void Element::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *) {
painter -> save();
// Annulation des renderhints
painter -> setRenderHint(QPainter::Antialiasing, false);
@@ -233,41 +214,15 @@ void Element::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *o
painter -> restore();
}
/**
Dessine le cadre de selection de l'element de maniere systematiquement non antialiasee.
@param painter Le QPainter a utiliser pour dessiner les bornes.
@param options Les options de style a prendre en compte
*/
void Element::drawHighlight(QPainter *painter, const QStyleOptionGraphicsItem *options) {
Q_UNUSED(options);
painter -> save();
qreal gradient_radius = qMin(boundingRect().width(), boundingRect().height()) / 2.0;
QRadialGradient gradient(
boundingRect().center(),
gradient_radius,
boundingRect().center()
);
gradient.setColorAt(0.0, QColor::fromRgb(69, 137, 255, 255));
gradient.setColorAt(1.0, QColor::fromRgb(69, 137, 255, 0));
QBrush brush(gradient);
painter -> setPen(Qt::NoPen);
painter -> setBrush(brush);
// Le dessin se fait a partir du rectangle delimitant
painter -> drawRoundRect(boundingRect().adjusted(1, 1, -1, -1), 10, 10);
painter -> restore();
}
/**
Fonction initialisant et dessinant la pixmap de l'element.
*/
void Element::updatePixmap() {
// Pixmap transparente faisant la taille de base de l'element
preview = QPixmap(dimensions);
preview.fill(QColor(255, 255, 255, 0));
apercu = QPixmap(dimensions);
apercu.fill(QColor(255, 255, 255, 0));
// QPainter sur la pixmap, avec antialiasing
QPainter p(&preview);
QPainter p(&apercu);
p.setRenderHint(QPainter::Antialiasing, true);
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
// Translation de l'origine du repere de la pixmap
@@ -303,51 +258,17 @@ void Element::setPos(qreal x, qreal y) {
setPos(QPointF(x, y));
}
/**
Gere le clic sur l'element
@param e Objet decrivant l'evenement souris
*/
void Element::mousePressEvent(QGraphicsSceneMouseEvent *e) {
first_move_ = true;
if (e -> modifiers() & Qt::ControlModifier) {
setSelected(!isSelected());
}
QGraphicsItem::mousePressEvent(e);
}
/**
Gere les mouvements de souris lies a l'element
@param e Objet decrivant l'evenement souris
*/
void Element::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
if (isSelected() && e -> buttons() & Qt::LeftButton) {
// l'element est en train d'etre deplace
Diagram *diagram_ptr = diagram();
if (diagram_ptr) {
if (first_move_) {
// il s'agit du premier mouvement du deplacement, on le signale
// au schema parent
diagram_ptr -> beginMoveElements(this);
}
}
// on applique le mouvement impose par la souris
QPointF old_pos = pos();
if (e -> buttons() & Qt::LeftButton) {
QPointF oldPos = pos();
setPos(mapToParent(e -> pos()) - matrix().map(e -> buttonDownPos(Qt::LeftButton)));
// on calcule le mouvement reellement applique par setPos()
QPointF effective_movement = pos() - old_pos;
if (diagram_ptr) {
// on signale le mouvement ainsi applique au schema parent, qui
// l'appliquera aux autres items selectionnes selon son bon vouloir
diagram_ptr -> continueMoveElements(effective_movement);
if (Diagram *diagram_ptr = diagram()) {
diagram_ptr -> moveElements(pos() - oldPos, this);
}
} else e -> ignore();
if (first_move_) {
first_move_ = false;
}
}
/**
@@ -356,13 +277,21 @@ void Element::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
et conducteurs a deplacer au niveau du schema.
*/
void Element::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
if (Diagram *diagram_ptr = diagram()) {
diagram_ptr -> endMoveElements();
}
if (!(e -> modifiers() & Qt::ControlModifier)) {
QGraphicsItem::mouseReleaseEvent(e);
Diagram *diagram_ptr = diagram();
if (diagram_ptr) {
if (!diagram_ptr -> current_movement.isNull()) {
diagram_ptr -> undoStack().push(
new MoveElementsCommand(
diagram_ptr,
diagram_ptr -> selectedContent(),
diagram_ptr -> current_movement
)
);
diagram_ptr -> current_movement = QPointF();
}
diagram_ptr -> invalidateMovedElements();
}
QGraphicsItem::mouseReleaseEvent(e);
}
/**
@@ -403,7 +332,7 @@ bool Element::valideXml(QDomElement &e) {
@return true si l'import a reussi, false sinon
*/
bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr, bool handle_inputs_rotation) {
bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr) {
/*
les bornes vont maintenant etre recensees pour associer leurs id a leur adresse reelle
ce recensement servira lors de la mise en place des fils
@@ -415,16 +344,14 @@ bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr, bool
QHash<int, Terminal *> priv_id_adr;
int terminals_non_trouvees = 0;
foreach(QGraphicsItem *qgi, childItems()) {
foreach(QGraphicsItem *qgi, children()) {
if (Terminal *p = qgraphicsitem_cast<Terminal *>(qgi)) {
bool terminal_trouvee = false;
foreach(QDomElement qde, liste_terminals) {
if (p -> fromXml(qde)) {
priv_id_adr.insert(qde.attribute("id").toInt(), p);
terminal_trouvee = true;
// We used to break here, because we did not expect
// several terminals to share the same position.
// Of course, it finally happened.
break;
}
}
if (!terminal_trouvee) ++ terminals_non_trouvees;
@@ -449,25 +376,20 @@ bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr, bool
// importe les valeurs des champs de texte
QList<QDomElement> inputs = QET::findInDomElement(e, "inputs", "input");
foreach(QGraphicsItem *qgi, childItems()) {
foreach(QGraphicsItem *qgi, children()) {
if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(qgi)) {
foreach(QDomElement input, inputs) eti -> fromXml(input);
}
}
// position, selection
// position, selection et orientation
setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble());
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
// orientation
bool conv_ok;
int read_ori = e.attribute("orientation").toInt(&conv_ok);
if (!conv_ok || read_ori < 0 || read_ori > 3) read_ori = ori.defaultOrientation();
if (handle_inputs_rotation) {
RotateElementsCommand::rotateElement(this, (QET::Orientation)read_ori);
} else {
setOrientation((QET::Orientation)read_ori);
}
setOrientation((QET::Orientation)read_ori);
return(true);
}
@@ -483,11 +405,13 @@ QDomElement Element::toXml(QDomDocument &document, QHash<Terminal *, int> &table
QDomElement element = document.createElement("element");
// type
element.setAttribute("type", typeId());
QString chemin_elmt = typeId();
QString type_elmt = QETApp::symbolicPath(chemin_elmt);
element.setAttribute("type", type_elmt);
// position, selection et orientation
element.setAttribute("x", QString("%1").arg(pos().x()));
element.setAttribute("y", QString("%1").arg(pos().y()));
element.setAttribute("x", pos().x());
element.setAttribute("y", pos().y());
element.setAttribute("orientation", QString("%1").arg(ori.current()));
/* recupere le premier id a utiliser pour les bornes de cet element */
@@ -502,21 +426,29 @@ QDomElement Element::toXml(QDomDocument &document, QHash<Terminal *, int> &table
}
// enregistrement des bornes de l'appareil
QDomElement xml_terminals = document.createElement("terminals");
QDomElement terminals = document.createElement("terminals");
// pour chaque enfant de l'element
foreach(Terminal *t, terminals()) {
// alors on enregistre la borne
QDomElement terminal = t -> toXml(document);
terminal.setAttribute("id", id_terminal);
table_adr_id.insert(t, id_terminal ++);
xml_terminals.appendChild(terminal);
foreach(QGraphicsItem *child, children()) {
// si cet enfant est une borne
if (Terminal *t = qgraphicsitem_cast<Terminal *>(child)) {
// alors on enregistre la borne
QDomElement terminal = t -> toXml(document);
terminal.setAttribute("id", id_terminal);
table_adr_id.insert(t, id_terminal ++);
terminals.appendChild(terminal);
}
}
element.appendChild(xml_terminals);
element.appendChild(terminals);
// enregistrement des champ de texte de l'appareil
QDomElement inputs = document.createElement("inputs");
foreach(ElementTextItem *eti, texts()) {
inputs.appendChild(eti -> toXml(document));
// pour chaque enfant de l'element
foreach(QGraphicsItem *child, children()) {
// si cet enfant est un champ de texte
if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(child)) {
// alors on enregistre le champ de texte
inputs.appendChild(eti -> toXml(document));
}
}
element.appendChild(inputs);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -21,16 +21,12 @@
#include "terminal.h"
#include "orientationset.h"
class Diagram;
class ElementTextItem;
/**
This is the base class for electrical elements.
Cette classe abstraite represente un element electrique.
*/
class Element : public QObject, public QGraphicsItem {
class Element : public QGraphicsItem {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
// constructors, destructor
// constructeurs, destructeur
public:
Element(QGraphicsItem * = 0, Diagram * = 0);
virtual ~Element();
@@ -38,16 +34,16 @@ class Element : public QObject, public QGraphicsItem {
private:
Element(const Element &);
// attributes
// attributs
public:
enum { Type = UserType + 1000 };
protected:
/**
Hold orientations for the element :
* allowed orientations
* current orientation
* default orientation
orientations de l'element :
* autorisations
* orientation en cours
* orientation par defaut
@see OrientationSet
*/
OrientationSet ori;
@@ -55,109 +51,100 @@ class Element : public QObject, public QGraphicsItem {
private:
QSize dimensions;
QPoint hotspot_coord;
QPixmap preview;
QPixmap apercu;
// methods
// methodes
public:
/**
Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into an
Element.
@return the QGraphicsItem type
permet de caster un QGraphicsItem en Element avec qgraphicsitem_cast
@return le type de QGraphicsItem
*/
virtual int type() const { return Type; }
// pure virtual methods to be defined in derived classes
/// @return the list of terminals for this element
// methodes virtuelles pures a definir dans les classes enfants
/// @return la liste des bornes de cet element
virtual QList<Terminal *> terminals() const = 0;
/// @return the list of conductors attached to this element
/// @return la liste des conducteurs relies a cet element
virtual QList<Conductor *> conductors() const = 0;
/// @return the list of text items attached to this element
virtual QList<ElementTextItem *> texts() const = 0;
/// @return the current number of terminals of this element
virtual int terminalsCount() const = 0;
/// @return the minimum number of terminals for this element
virtual int minTerminalsCount() const = 0;
/// @return the maximum number of terminals for this element
virtual int maxTerminalsCount() const = 0;
/// @return le nombre de bornes actuel de cet element
virtual int nbTerminals() const = 0;
/// @return le nombre de bornes minimum de cet element
virtual int nbTerminalsMin() const = 0;
/// @return le nombre de bornes maximum de cet element
virtual int nbTerminalsMax() const = 0;
/**
Draw this element
Dessine l'element
*/
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0;
/// @return This element type ID
/// @return L'ID du type de l'element
virtual QString typeId() const = 0;
/// @return the human name for this element
virtual QString name() const = 0;
/// @return Le nom de l'element
virtual QString nom() const = 0;
Diagram *diagram() const;
virtual bool isHighlighted() const;
virtual void setHighlighted(bool);
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
QRectF boundingRect() const;
QSize setSize(int, int);
QSize size() const;
QPixmap pixmap();
// methods related to the hotspot
// methodes relatives au point de saisie
QPoint setHotspot(QPoint);
QPoint hotspot() const;
// selection-related methods
// methodes relatives a la selection
void select();
void deselect();
// position-related methods
// methodes relatives a la position
void setPos(const QPointF &);
void setPos(qreal, qreal);
// methods related to internal connections
// methodes relatives aux connexions internes
bool internalConnections();
void setInternalConnections(bool);
// methods related to XML import/export
// methodes relatives aux fichiers XML
static bool valideXml(QDomElement &);
virtual bool fromXml(QDomElement &, QHash<int, Terminal *> &, bool = false);
virtual bool fromXml(QDomElement &, QHash<int, Terminal *> &);
virtual QDomElement toXml(QDomDocument &, QHash<Terminal *, int> &) const;
// orientation-related methods
// methodes d'acces aux possibilites d'orientation
bool setOrientation(QET::Orientation o);
const OrientationSet &orientation() const;
protected:
void drawAxes(QPainter *, const QStyleOptionGraphicsItem *);
void mousePressEvent(QGraphicsSceneMouseEvent *);
void mouseMoveEvent(QGraphicsSceneMouseEvent *);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
private:
bool internal_connections_;
bool must_highlight_;
bool first_move_;
bool internal_connections;
void drawSelection(QPainter *, const QStyleOptionGraphicsItem *);
void drawHighlight(QPainter *, const QStyleOptionGraphicsItem *);
void updatePixmap();
};
/**
Indicate whether this element allows internal connections, i.e. whether its
terminals can be linked together using a conductor.
@return true if internal connections are accepted, false otherwise
Permet de savoir si l'element accepte les connexions internes,
c'est-a-dire que ses bornes peuvent etre reliees entre elles
@return true si l'element accepte les connexions internes, false sinon
*/
inline bool Element::internalConnections() {
return(internal_connections_);
return(internal_connections);
}
/**
Specify whether this element allows internal connections, i.e. whether its
terminals can be linked together using a conductor.
@return true for internal connections to be accepted, false otherwise
Permet de specifier si l'element accepte les connexions internes,
c'est-a-dire que ses bornes peuvent etre reliees entre elles
@param ic true pour que l'element accepte les connexions internes, false pour
qu'il les interdise
*/
inline void Element::setInternalConnections(bool ic) {
internal_connections_ = ic;
internal_connections = ic;
}
/**
Indicate the current orientation of this element
@return the current orientation of this element
Permet de connaitre l'orientation actuelle de l'element
@return L'orientation actuelle de l'element
*/
inline const OrientationSet & Element::orientation() const {
return(ori);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -16,26 +16,16 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "elementdeleter.h"
#include "qetapp.h"
#include "qetmessagebox.h"
/**
Constructeur
@param elmt_path Chemin virtuel du fichier representant l'element a supprimer
@param elmt_path Chemin du fichier representant l'element a supprimer
@param parent QWidget parent
*/
ElementDeleter::ElementDeleter(const ElementsLocation &elmt_path, QWidget *parent) :
ElementDeleter::ElementDeleter(const QString &elmt_path, QWidget *parent) :
QWidget(parent),
element(0)
element_path(elmt_path)
{
// recupere l'element a supprimer
ElementsCollectionItem *element_item = QETApp::collectionItem(elmt_path);
if (!element_item) return;
// on exige un element
if (!element_item -> isElement()) return;
element = element_item;
}
/// Destructeur
@@ -46,31 +36,27 @@ ElementDeleter::~ElementDeleter() {
Supprime l'element : verifie l'existence du fichier, demande confirmation a
l'utilisateur et avertit ce dernier si la suppression a echoue.
*/
bool ElementDeleter::exec() {
void ElementDeleter::exec() {
// verifie l'existence de l'element
if (!element || !element -> isElement()) return(false);
QFile elmt_file(element_path);
if (!elmt_file.exists()) return;
// confirmation #1
QMessageBox::StandardButton answer_1 = QET::MessageBox::question(
QMessageBox::StandardButton answer_1 = QMessageBox::question(
this,
tr("Supprimer l'\351l\351ment ?", "message box title"),
tr("\312tes-vous s\373r de vouloir supprimer cet \351l\351ment ?\n", "message box content"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel
tr("Supprimer l'\351l\351ment ?"),
tr("\312tes-vous s\373r de vouloir supprimer cet \351l\351ment ?\n"),
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel
);
if (answer_1 != QMessageBox::Yes) return(false);
/**
@todo Regression : rafficher le chemin de l'element
*/
if (answer_1 != QMessageBox::Yes) return;
// supprime l'element
if (!element -> remove()) {
QET::MessageBox::warning(
if (!elmt_file.remove()) {
QMessageBox::warning(
this,
tr("Suppression de l'\351l\351ment", "message box title"),
tr("La suppression de l'\351l\351ment a \351chou\351.", "message box content")
tr("Suppression de l'\351l\351ment"),
tr("La suppression de l'\351l\351ment a \351chou\351.\n"
"V\351rifiez vos droits sur le fichier ") + element_path + tr(".")
);
return(false);
}
return(true);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2006-2013 The QElectroTech Team
Copyright 2006-2007 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
@@ -18,27 +18,27 @@
#ifndef ELEMENT_DELETER_H
#define ELEMENT_DELETER_H
#include "elementscategory.h"
#include "elementslocation.h"
#include <QtGui>
/**
This class provides an abstract way to delete an element from its parent
collection. Especially, it requires a confirmation from users.
Cette classe represente une couche d'abstraction pour supprimer
un element de la collection d'elements.
Elle demande notamment confirmation a l'utilisateur
*/
class ElementDeleter : public QWidget {
Q_OBJECT
// constructors, destructor
// constructeurs, destructeur
public:
ElementDeleter(const ElementsLocation &, QWidget * = 0);
ElementDeleter(const QString &, QWidget * = 0);
virtual ~ElementDeleter();
private:
ElementDeleter(const ElementsCategory &);
// methods
// methodes
public slots:
bool exec();
void exec();
// attributes
// attributs
private:
ElementsCollectionItem *element;
QString element_path;
};
#endif

View File

@@ -1,26 +0,0 @@
<definition width="50" version="0.3" hotspot_x="25" hotspot_y="15" height="30" type="element" orientation="dnnn">
<names>
<name lang="ar">أمبيرمتر أفقي</name>
<name lang="de">Amperemeter horizontal</name>
<name lang="ru">Амперметр (горизонтальный)</name>
<name lang="pt">Amperímetro horizontal</name>
<name lang="el">Αμπερόμετρο οριζόντιο</name>
<name lang="en">Horizontal ammeter</name>
<name lang="it">Amperometro orizzontale</name>
<name lang="fr">Ampèremètre horizontal</name>
<name lang="pl">Amperomierz (poziomo)</name>
<name lang="es">Amperímetro horizontal</name>
<name lang="cs">Vodorovný ampérmetr</name>
</names>
<informations>Author: The QElectroTech team
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
<description>
<line length1="1.5" length2="1.5" antialias="false" end1="none" end2="none" style="line-style:normal;line-weight:normal;filling:none;color:black" y1="0" x1="-1.75" y2="0" x2="1.75"/>
<line length1="1.5" length2="1.5" antialias="false" end1="none" end2="none" style="line-style:normal;line-weight:normal;filling:none;color:black" y1="0" x1="10" y2="0" x2="21"/>
<line length1="1.5" length2="1.5" antialias="false" end1="none" end2="none" style="line-style:normal;line-weight:normal;filling:none;color:black" y1="0" x1="-21" y2="0" x2="-10"/>
<polygon antialias="true" style="line-style:normal;line-weight:normal;filling:none;color:black" closed="false" y1="6" x1="-5" y2="-6" x2="0" y3="6" x3="5"/>
<circle x="-10" y="-10" antialias="true" style="line-style:normal;line-weight:normal;filling:none;color:black" diameter="20"/>
<terminal x="-21" y="0" orientation="w"/>
<terminal x="21" y="0" orientation="e"/>
</description>
</definition>

View File

@@ -1,26 +0,0 @@
<definition width="30" version="0.3" hotspot_x="15" hotspot_y="25" height="50" type="element" orientation="dnnn">
<names>
<name lang="ar">أمبيرمتر عمودي</name>
<name lang="de">Amperemeter vertikal</name>
<name lang="ru">Амперметр (вертикальный)</name>
<name lang="pt">Amperímetro vertical</name>
<name lang="el">Αμπερόμετρο κατακόρυφο</name>
<name lang="en">Vertical ammeter</name>
<name lang="it">Amperometro verticale</name>
<name lang="fr">Ampèremètre vertical</name>
<name lang="pl">Amperomierz (pionowo)</name>
<name lang="es">Amperímetro vertical</name>
<name lang="cs">Svislý ampérmetr</name>
</names>
<informations>Author: The QElectroTech team
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
<description>
<line length1="1.5" length2="1.5" antialias="false" end1="none" end2="none" style="line-style:normal;line-weight:normal;filling:none;color:black" y1="0" x1="-1.75" y2="0" x2="1.75"/>
<line length1="1.5" length2="1.5" antialias="false" end1="none" end2="none" style="line-style:normal;line-weight:normal;filling:none;color:black" y1="10" x1="0" y2="21" x2="0"/>
<line length1="1.5" length2="1.5" antialias="false" end1="none" end2="none" style="line-style:normal;line-weight:normal;filling:none;color:black" y1="-21" x1="0" y2="-10" x2="0"/>
<polygon antialias="true" style="line-style:normal;line-weight:normal;filling:none;color:black" closed="false" y1="6" x1="-5" y2="-6" x2="0" y3="6" x3="5"/>
<circle x="-10" y="-10" antialias="true" style="line-style:normal;line-weight:normal;filling:none;color:black" diameter="20"/>
<terminal x="0" y="-21" orientation="n"/>
<terminal x="0" y="21" orientation="s"/>
</description>
</definition>

View File

@@ -1,24 +0,0 @@
<definition width="50" version="0.3" hotspot_x="25" hotspot_y="15" height="30" type="element" orientation="dnnn">
<names>
<name lang="ar">مقياس تردد أفقي</name>
<name lang="de">Frequenzmeßgerät, anzeigend</name>
<name lang="pt">Frequenciómetro horizontal</name>
<name lang="el">Συχνόμετρο οριζόντιο</name>
<name lang="en">Frequency meter h</name>
<name lang="it">Frequenzimetro orizzontale</name>
<name lang="fr">Fréquencemètre horizontal</name>
<name lang="pl">Częstotliwościomierz (poziomo)</name>
<name lang="es">Frecuencímetro horizontal</name>
<name lang="cs">Měřič kmitočtu, vodorovný</name>
</names>
<informations>Author: The QElectroTech team
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
<description>
<text x="-8" y="2.3333" size="9" text="Hz"/>
<line length1="1.5" length2="1.5" antialias="false" end1="none" end2="none" style="line-style:normal;line-weight:normal;filling:none;color:black" y1="0" x1="10" y2="0" x2="21"/>
<line length1="1.5" length2="1.5" antialias="false" end1="none" end2="none" style="line-style:normal;line-weight:normal;filling:none;color:black" y1="0" x1="-21" y2="0" x2="-10"/>
<circle x="-10" y="-10" antialias="true" style="line-style:normal;line-weight:normal;filling:none;color:black" diameter="20"/>
<terminal x="-21" y="0" orientation="w"/>
<terminal x="21" y="0" orientation="e"/>
</description>
</definition>

Some files were not shown because too many files have changed in this diff Show More