summaryrefslogtreecommitdiffstats
path: root/kpovmodeler
diff options
context:
space:
mode:
Diffstat (limited to 'kpovmodeler')
-rw-r--r--kpovmodeler/AUTHORS13
-rw-r--r--kpovmodeler/BUGS5
-rw-r--r--kpovmodeler/COPYING341
-rw-r--r--kpovmodeler/ChangeLog83
-rw-r--r--kpovmodeler/INSTALL167
-rw-r--r--kpovmodeler/Makefile.am251
-rw-r--r--kpovmodeler/README3
-rw-r--r--kpovmodeler/REQUIREMENTS19
-rw-r--r--kpovmodeler/StyleConvention225
-rw-r--r--kpovmodeler/TODO52
-rw-r--r--kpovmodeler/baseinsertrules.xml1039
-rw-r--r--kpovmodeler/configure.in.bot37
-rw-r--r--kpovmodeler/configure.in.in60
-rw-r--r--kpovmodeler/cr16-mime-kpovmodeler_doc.pngbin0 -> 684 bytes
-rw-r--r--kpovmodeler/cr32-mime-kpovmodeler_doc.pngbin0 -> 1464 bytes
-rw-r--r--kpovmodeler/cr48-mime-kpovmodeler_doc.pngbin0 -> 2258 bytes
-rw-r--r--kpovmodeler/examples/Makefile.am1
-rw-r--r--kpovmodeler/examples/includes/Makefile.am1
-rw-r--r--kpovmodeler/examples/includes/inlined/Makefile.am4
-rw-r--r--kpovmodeler/examples/includes/inlined/chars.kpmbin0 -> 3354 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/finish.kpmbin0 -> 937 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/glass.kpm141
-rw-r--r--kpovmodeler/examples/includes/inlined/golds.kpmbin0 -> 1140 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/metals.kpmbin0 -> 2748 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/shapes.kpmbin0 -> 1462 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/shapes2.kpmbin0 -> 1541 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/shapesq.kpmbin0 -> 3039 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/skies.kpmbin0 -> 2229 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/stars.kpmbin0 -> 1285 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/stones1.kpmbin0 -> 9383 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/stones2.kpmbin0 -> 3659 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/textures.kpmbin0 -> 7361 bytes
-rw-r--r--kpovmodeler/examples/includes/inlined/woods.kpmbin0 -> 7129 bytes
-rw-r--r--kpovmodeler/examples/includes/original/Makefile.am4
-rw-r--r--kpovmodeler/examples/includes/original/chars.kpmbin0 -> 3083 bytes
-rw-r--r--kpovmodeler/examples/includes/original/finish.kpmbin0 -> 937 bytes
-rw-r--r--kpovmodeler/examples/includes/original/glass.kpmbin0 -> 1237 bytes
-rw-r--r--kpovmodeler/examples/includes/original/golds.kpmbin0 -> 1166 bytes
-rw-r--r--kpovmodeler/examples/includes/original/metals.kpmbin0 -> 3359 bytes
-rw-r--r--kpovmodeler/examples/includes/original/shapes.kpmbin0 -> 1462 bytes
-rw-r--r--kpovmodeler/examples/includes/original/shapes2.kpmbin0 -> 1541 bytes
-rw-r--r--kpovmodeler/examples/includes/original/shapesq.kpmbin0 -> 3045 bytes
-rw-r--r--kpovmodeler/examples/includes/original/skies.kpmbin0 -> 1981 bytes
-rw-r--r--kpovmodeler/examples/includes/original/stars.kpmbin0 -> 1285 bytes
-rw-r--r--kpovmodeler/examples/includes/original/stones1.kpmbin0 -> 7777 bytes
-rw-r--r--kpovmodeler/examples/includes/original/stones2.kpmbin0 -> 3659 bytes
-rw-r--r--kpovmodeler/examples/includes/original/textures.kpmbin0 -> 7317 bytes
-rw-r--r--kpovmodeler/examples/includes/original/woods.kpmbin0 -> 5539 bytes
-rw-r--r--kpovmodeler/examples/scenes/Makefile.am1
-rw-r--r--kpovmodeler/examples/scenes/advanced/Makefile.am2
-rw-r--r--kpovmodeler/examples/scenes/advanced/ants.kpmbin0 -> 5229 bytes
-rw-r--r--kpovmodeler/examples/scenes/advanced/bee.kpmbin0 -> 3052 bytes
-rw-r--r--kpovmodeler/examples/scenes/advanced/ink.kpmbin0 -> 3251 bytes
-rw-r--r--kpovmodeler/examples/scenes/advanced/table.kpmbin0 -> 4961 bytes
-rw-r--r--kpovmodeler/examples/scenes/csg/Makefile.am2
-rw-r--r--kpovmodeler/examples/scenes/csg/cheese.kpmbin0 -> 2642 bytes
-rw-r--r--kpovmodeler/examples/scenes/csg/emptybox.kpmbin0 -> 1952 bytes
-rw-r--r--kpovmodeler/examples/scenes/csg/heightfield.kpmbin0 -> 1321 bytes
-rw-r--r--kpovmodeler/examples/scenes/interior/Makefile.am2
-rw-r--r--kpovmodeler/examples/scenes/interior/cubes.kpmbin0 -> 1273 bytes
-rw-r--r--kpovmodeler/examples/scenes/interior/media1.kpmbin0 -> 1151 bytes
-rw-r--r--kpovmodeler/examples/scenes/interior/media2.kpmbin0 -> 1467 bytes
-rw-r--r--kpovmodeler/examples/scenes/interior/media3.kpmbin0 -> 1737 bytes
-rw-r--r--kpovmodeler/examples/scenes/interior/spheres.kpmbin0 -> 1247 bytes
-rw-r--r--kpovmodeler/examples/scenes/lights/Makefile.am2
-rw-r--r--kpovmodeler/examples/scenes/lights/arealight.kpmbin0 -> 1142 bytes
-rw-r--r--kpovmodeler/examples/scenes/lights/arealight2.kpmbin0 -> 1148 bytes
-rw-r--r--kpovmodeler/examples/scenes/lights/spotlight.kpmbin0 -> 1117 bytes
-rw-r--r--kpovmodeler/examples/scenes/objects/Makefile.am3
-rw-r--r--kpovmodeler/examples/scenes/objects/allobjects.kpmbin0 -> 2413 bytes
-rw-r--r--kpovmodeler/examples/scenes/objects/fractals.kpmbin0 -> 1143 bytes
-rw-r--r--kpovmodeler/examples/scenes/objects/lathe.kpmbin0 -> 1122 bytes
-rw-r--r--kpovmodeler/examples/scenes/objects/prism.kpmbin0 -> 1359 bytes
-rw-r--r--kpovmodeler/examples/scenes/objects/sor.kpmbin0 -> 1764 bytes
-rw-r--r--kpovmodeler/examples/scenes/objects/superellipsoid.kpmbin0 -> 1242 bytes
-rw-r--r--kpovmodeler/examples/scenes/objects/text.kpmbin0 -> 1124 bytes
-rw-r--r--kpovmodeler/hi16-app-kpovmodeler.pngbin0 -> 815 bytes
-rw-r--r--kpovmodeler/hi22-app-kpovmodeler.pngbin0 -> 1149 bytes
-rw-r--r--kpovmodeler/hi32-app-kpovmodeler.pngbin0 -> 1891 bytes
-rw-r--r--kpovmodeler/hi48-app-kpovmodeler.pngbin0 -> 3163 bytes
-rw-r--r--kpovmodeler/kdoc.rules10
-rw-r--r--kpovmodeler/kpovmodeler.desktop59
-rw-r--r--kpovmodeler/kpovmodelerbrowser.rc21
-rw-r--r--kpovmodeler/kpovmodelershell.rc58
-rw-r--r--kpovmodeler/kpovmodelerui.rc303
-rw-r--r--kpovmodeler/main.cpp69
-rw-r--r--kpovmodeler/pics/Makefile.am1
-rw-r--r--kpovmodeler/pics/crystalsvg/Makefile.am2
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmaddpoint.pngbin0 -> 262 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmaddpointabove.pngbin0 -> 226 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmaddsubprism.pngbin0 -> 260 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmbicubicpatch.pngbin0 -> 398 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmblendmapmodifiers.pngbin0 -> 608 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmblob.pngbin0 -> 514 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmblobcylinder.pngbin0 -> 474 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmblobsphere.pngbin0 -> 443 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmboundedby.pngbin0 -> 398 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmbox.pngbin0 -> 270 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmbumpmap.pngbin0 -> 681 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmcamera.pngbin0 -> 244 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmclippedby.pngbin0 -> 387 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmcolorlist.pngbin0 -> 169 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmcolormap.pngbin0 -> 360 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmcolormapdeclare.pngbin0 -> 350 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmcomment.pngbin0 -> 209 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmcone.pngbin0 -> 374 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmcylinder.pngbin0 -> 337 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdeclare.pngbin0 -> 451 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdensity.pngbin0 -> 530 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdensitydeclare.pngbin0 -> 485 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdensitylist.pngbin0 -> 544 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdensitymap.pngbin0 -> 586 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdensitymapdeclare.pngbin0 -> 519 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdialogview.pngbin0 -> 576 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdifference.pngbin0 -> 271 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdisc.pngbin0 -> 355 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmdrag.pngbin0 -> 276 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmfinish.pngbin0 -> 240 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmfinishdeclare.pngbin0 -> 265 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmfog.pngbin0 -> 524 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmfogdeclare.pngbin0 -> 477 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmglobalphotons.pngbin0 -> 589 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmglobalsettings.pngbin0 -> 736 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmglview.pngbin0 -> 549 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmheightfield.pngbin0 -> 385 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmimagemap.pngbin0 -> 758 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pminserterrors.pngbin0 -> 246 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pminsertfirstchild.pngbin0 -> 226 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pminsertlastchild.pngbin0 -> 229 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pminsertsibling.pngbin0 -> 233 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pminterior.pngbin0 -> 279 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pminteriordeclare.pngbin0 -> 253 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pminteriortexture.pngbin0 -> 449 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pminteriortexturedeclare.pngbin0 -> 376 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmintersection.pngbin0 -> 269 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmisosurface.pngbin0 -> 411 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmjuliafractal.pngbin0 -> 468 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmlathe.pngbin0 -> 445 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmlight.pngbin0 -> 419 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmlightgroup.pngbin0 -> 440 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmlistpattern.pngbin0 -> 405 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmlookslike.pngbin0 -> 385 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmmaterial.pngbin0 -> 461 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmmaterialdeclare.pngbin0 -> 407 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmmaterialmap.pngbin0 -> 699 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmmatrix.pngbin0 -> 565 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmmedia.pngbin0 -> 388 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmmediadeclare.pngbin0 -> 376 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmmerge.pngbin0 -> 281 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmmesh.pngbin0 -> 360 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmnormal.pngbin0 -> 539 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmnormaldeclare.pngbin0 -> 481 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmnormallist.pngbin0 -> 556 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmnormalmap.pngbin0 -> 516 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmnormalmapdeclare.pngbin0 -> 456 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmobjectdeclare.pngbin0 -> 420 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmobjectlink.pngbin0 -> 476 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmpattern.pngbin0 -> 710 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmphotons.pngbin0 -> 513 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmpigment.pngbin0 -> 334 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentdeclare.pngbin0 -> 361 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentlist.pngbin0 -> 442 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentmap.pngbin0 -> 487 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentmapdeclare.pngbin0 -> 454 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmplane.pngbin0 -> 483 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmpolynom.pngbin0 -> 371 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmprism.pngbin0 -> 322 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmprojectedthrough.pngbin0 -> 422 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmquickcolor.pngbin0 -> 220 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmradiosity.pngbin0 -> 534 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmrainbow.pngbin0 -> 318 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmrainbowdeclare.pngbin0 -> 307 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmraw.pngbin0 -> 193 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmremovepoint.pngbin0 -> 170 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmrender.pngbin0 -> 442 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmrenderpreview.pngbin0 -> 451 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmrendersettings.pngbin0 -> 595 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmrotate.pngbin0 -> 282 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmscale.pngbin0 -> 209 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmscene.pngbin0 -> 725 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmskysphere.pngbin0 -> 614 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmskyspheredeclare.pngbin0 -> 560 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmslope.pngbin0 -> 364 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmslopemap.pngbin0 -> 396 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmslopemapdeclare.pngbin0 -> 342 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmsolidcolor.pngbin0 -> 178 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmsor.pngbin0 -> 425 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmsphere.pngbin0 -> 467 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmspheresweep.pngbin0 -> 540 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmsqe.pngbin0 -> 495 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtext.pngbin0 -> 248 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtexture.pngbin0 -> 610 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtexturedeclare.pngbin0 -> 544 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtexturelist.pngbin0 -> 617 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtexturemap.pngbin0 -> 603 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtexturemapdeclare.pngbin0 -> 546 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtorus.pngbin0 -> 498 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtranslate.pngbin0 -> 231 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtreeview.pngbin0 -> 539 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmtriangle.pngbin0 -> 252 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmunion.pngbin0 -> 312 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr16-action-pmwarp.pngbin0 -> 686 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmbicubicpatch.pngbin0 -> 521 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmblendmapmodifiers.pngbin0 -> 975 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmblob.pngbin0 -> 845 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmblobcylinder.pngbin0 -> 796 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmblobsphere.pngbin0 -> 617 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmboundedby.pngbin0 -> 432 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmbox.pngbin0 -> 302 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmbumpmap.pngbin0 -> 1206 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmcamera.pngbin0 -> 525 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmclippedby.pngbin0 -> 477 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmcolorlist.pngbin0 -> 218 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmcolormap.pngbin0 -> 573 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmcolormapdeclare.pngbin0 -> 518 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmcomment.pngbin0 -> 343 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmcone.pngbin0 -> 396 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfigurecolors.pngbin0 -> 883 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguredialogview.pngbin0 -> 392 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguregraphicalview.pngbin0 -> 652 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguregrid.pngbin0 -> 553 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureobjectlibrary.pngbin0 -> 500 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureobjects.pngbin0 -> 710 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureopengl.pngbin0 -> 519 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfigurepovray.pngbin0 -> 1080 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguretexturepreview.pngbin0 -> 765 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureviewlayout.pngbin0 -> 410 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmcylinder.pngbin0 -> 384 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdeclare.pngbin0 -> 702 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdensity.pngbin0 -> 1147 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdensitydeclare.pngbin0 -> 683 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdensitylist.pngbin0 -> 809 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdensitymap.pngbin0 -> 900 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdensitymapdeclare.pngbin0 -> 764 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdifference.pngbin0 -> 430 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdisc.pngbin0 -> 527 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmdrag.pngbin0 -> 369 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmfinish.pngbin0 -> 299 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmfinishdeclare.pngbin0 -> 338 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmfog.pngbin0 -> 827 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmfogdeclare.pngbin0 -> 725 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmglobalphotons.pngbin0 -> 962 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmglobalsettings.pngbin0 -> 904 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmheightfield.pngbin0 -> 487 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmimagemap.pngbin0 -> 1344 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pminserterrors.pngbin0 -> 483 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pminterior.pngbin0 -> 277 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pminteriordeclare.pngbin0 -> 255 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pminteriortexture.pngbin0 -> 656 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pminteriortexturedeclare.pngbin0 -> 535 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmintersection.pngbin0 -> 372 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmisosurface.pngbin0 -> 730 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmjuliafractal.pngbin0 -> 718 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmlathe.pngbin0 -> 654 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmlight.pngbin0 -> 438 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmlightgroup.pngbin0 -> 709 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmlistpattern.pngbin0 -> 367 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmlookslike.pngbin0 -> 347 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmmaterial.pngbin0 -> 675 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmmaterialdeclare.pngbin0 -> 563 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmmaterialmap.pngbin0 -> 1243 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmmatrix.pngbin0 -> 290 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmmedia.pngbin0 -> 416 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmmediadeclare.pngbin0 -> 405 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmmerge.pngbin0 -> 489 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmmesh.pngbin0 -> 576 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmnormal.pngbin0 -> 844 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmnormaldeclare.pngbin0 -> 741 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmnormallist.pngbin0 -> 845 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmnormalmap.pngbin0 -> 804 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmnormalmapdeclare.pngbin0 -> 700 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmobjectdeclare.pngbin0 -> 643 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmobjectlink.pngbin0 -> 806 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmpattern.pngbin0 -> 1246 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmphotons.pngbin0 -> 631 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmpigment.pngbin0 -> 305 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentdeclare.pngbin0 -> 377 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentlist.pngbin0 -> 492 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentmap.pngbin0 -> 737 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentmapdeclare.pngbin0 -> 660 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmplane.pngbin0 -> 495 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmpolynom.pngbin0 -> 498 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmprism.pngbin0 -> 423 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmprojectedthrough.pngbin0 -> 420 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmquickcolor.pngbin0 -> 225 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmradiosity.pngbin0 -> 428 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmrainbow.pngbin0 -> 576 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmrainbowdeclare.pngbin0 -> 558 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmraw.pngbin0 -> 271 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmrender.pngbin0 -> 637 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmrenderpreview.pngbin0 -> 648 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmrendersettings.pngbin0 -> 693 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmrotate.pngbin0 -> 272 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmscale.pngbin0 -> 383 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmscene.pngbin0 -> 791 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmskysphere.pngbin0 -> 914 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmskyspheredeclare.pngbin0 -> 768 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmslope.pngbin0 -> 312 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmslopemap.pngbin0 -> 555 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmslopemapdeclare.pngbin0 -> 493 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmsolidcolor.pngbin0 -> 255 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmsor.pngbin0 -> 629 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmsphere.pngbin0 -> 592 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmspheresweep.pngbin0 -> 618 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmsqe.pngbin0 -> 713 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtext.pngbin0 -> 284 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtexture.pngbin0 -> 977 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtexturedeclare.pngbin0 -> 852 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtexturelist.pngbin0 -> 960 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtexturemap.pngbin0 -> 939 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtexturemapdeclare.pngbin0 -> 800 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtorus.pngbin0 -> 677 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtranslate.pngbin0 -> 463 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmtriangle.pngbin0 -> 455 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmunion.pngbin0 -> 554 bytes
-rw-r--r--kpovmodeler/pics/crystalsvg/cr22-action-pmwarp.pngbin0 -> 1011 bytes
-rw-r--r--kpovmodeler/pics/locolor/Makefile.am2
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmaddpoint.pngbin0 -> 262 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmaddpointabove.pngbin0 -> 226 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmaddsubprism.pngbin0 -> 186 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmbicubicpatch.pngbin0 -> 373 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmblendmapmodifiers.pngbin0 -> 520 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmblob.pngbin0 -> 396 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmblobcylinder.pngbin0 -> 212 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmblobsphere.pngbin0 -> 436 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmboundedby.pngbin0 -> 296 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmbox.pngbin0 -> 251 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmbumpmap.pngbin0 -> 299 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmcamera.pngbin0 -> 244 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmclippedby.pngbin0 -> 277 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmcomment.pngbin0 -> 209 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmcone.pngbin0 -> 466 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmcylinder.pngbin0 -> 341 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdeclare.pngbin0 -> 327 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdensity.pngbin0 -> 398 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdensitydeclare.pngbin0 -> 354 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdensitylist.pngbin0 -> 376 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdensitymap.pngbin0 -> 379 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdensitymapdeclare.pngbin0 -> 373 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdifference.pngbin0 -> 271 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdisc.pngbin0 -> 394 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmdrag.pngbin0 -> 276 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmfog.pngbin0 -> 329 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmfogdeclare.pngbin0 -> 384 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmglobalsettings.pngbin0 -> 509 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmheightfield.pngbin0 -> 288 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmimagemap.pngbin0 -> 458 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pminserterrors.pngbin0 -> 246 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pminsertfirstchild.pngbin0 -> 226 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pminsertlastchild.pngbin0 -> 229 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pminsertsibling.pngbin0 -> 233 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmintersection.pngbin0 -> 269 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmjuliafractal.pngbin0 -> 313 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmlathe.pngbin0 -> 237 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmlight.pngbin0 -> 297 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmlistpattern.pngbin0 -> 359 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmlookslike.pngbin0 -> 203 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmmaterialmap.pngbin0 -> 341 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmmatrix.pngbin0 -> 200 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmmerge.pngbin0 -> 281 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmobjectdeclare.pngbin0 -> 420 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmobjectlink.pngbin0 -> 476 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmpigment.pngbin0 -> 344 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmpigmentdeclare.pngbin0 -> 364 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmplane.pngbin0 -> 427 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmpolynom.pngbin0 -> 233 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmprism.pngbin0 -> 217 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmquickcolor.pngbin0 -> 205 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmrainbow.pngbin0 -> 354 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmrainbowdeclare.pngbin0 -> 337 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmraw.pngbin0 -> 193 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmremovepoint.pngbin0 -> 170 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmrender.pngbin0 -> 363 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmrenderpreview.pngbin0 -> 382 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmrendersettings.pngbin0 -> 501 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmrotate.pngbin0 -> 282 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmscale.pngbin0 -> 209 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmscene.pngbin0 -> 559 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmskysphere.pngbin0 -> 384 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmskyspheredeclare.pngbin0 -> 368 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmsolidcolor.pngbin0 -> 382 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmsor.pngbin0 -> 311 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmsphere.pngbin0 -> 363 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmsqr.pngbin0 -> 289 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmtext.pngbin0 -> 208 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmtexture.pngbin0 -> 502 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmtexturedeclare.pngbin0 -> 464 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmtorus.pngbin0 -> 399 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmtranslate.pngbin0 -> 231 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmtriangle.pngbin0 -> 324 bytes
-rw-r--r--kpovmodeler/pics/locolor/lo16-action-pmunion.pngbin0 -> 312 bytes
-rw-r--r--kpovmodeler/pm2dcontrolpoint.cpp207
-rw-r--r--kpovmodeler/pm2dcontrolpoint.h135
-rw-r--r--kpovmodeler/pm3dcontrolpoint.cpp49
-rw-r--r--kpovmodeler/pm3dcontrolpoint.h68
-rw-r--r--kpovmodeler/pmactions.cpp254
-rw-r--r--kpovmodeler/pmactions.h106
-rw-r--r--kpovmodeler/pmaddcommand.cpp233
-rw-r--r--kpovmodeler/pmaddcommand.h87
-rw-r--r--kpovmodeler/pmallcommands.h27
-rw-r--r--kpovmodeler/pmalledits.h25
-rw-r--r--kpovmodeler/pmallobjects.h106
-rw-r--r--kpovmodeler/pmbicubicpatch.cpp544
-rw-r--r--kpovmodeler/pmbicubicpatch.h188
-rw-r--r--kpovmodeler/pmbicubicpatchedit.cpp218
-rw-r--r--kpovmodeler/pmbicubicpatchedit.h80
-rw-r--r--kpovmodeler/pmblendmapmodifiers.cpp284
-rw-r--r--kpovmodeler/pmblendmapmodifiers.h129
-rw-r--r--kpovmodeler/pmblendmapmodifiersedit.cpp261
-rw-r--r--kpovmodeler/pmblendmapmodifiersedit.h100
-rw-r--r--kpovmodeler/pmblob.cpp175
-rw-r--r--kpovmodeler/pmblob.h113
-rw-r--r--kpovmodeler/pmblobcylinder.cpp468
-rw-r--r--kpovmodeler/pmblobcylinder.h181
-rw-r--r--kpovmodeler/pmblobcylinderedit.cpp114
-rw-r--r--kpovmodeler/pmblobcylinderedit.h61
-rw-r--r--kpovmodeler/pmblobedit.cpp96
-rw-r--r--kpovmodeler/pmblobedit.h65
-rw-r--r--kpovmodeler/pmblobsphere.cpp391
-rw-r--r--kpovmodeler/pmblobsphere.h168
-rw-r--r--kpovmodeler/pmblobsphereedit.cpp102
-rw-r--r--kpovmodeler/pmblobsphereedit.h63
-rw-r--r--kpovmodeler/pmboundedby.cpp114
-rw-r--r--kpovmodeler/pmboundedby.h89
-rw-r--r--kpovmodeler/pmboundedbyedit.cpp65
-rw-r--r--kpovmodeler/pmboundedbyedit.h59
-rw-r--r--kpovmodeler/pmbox.cpp276
-rw-r--r--kpovmodeler/pmbox.h123
-rw-r--r--kpovmodeler/pmboxedit.cpp86
-rw-r--r--kpovmodeler/pmboxedit.h63
-rw-r--r--kpovmodeler/pmbumpmap.cpp384
-rw-r--r--kpovmodeler/pmbumpmap.h172
-rw-r--r--kpovmodeler/pmbumpmapedit.cpp319
-rw-r--r--kpovmodeler/pmbumpmapedit.h86
-rw-r--r--kpovmodeler/pmcamera.cpp769
-rw-r--r--kpovmodeler/pmcamera.h292
-rw-r--r--kpovmodeler/pmcameraedit.cpp439
-rw-r--r--kpovmodeler/pmcameraedit.h99
-rw-r--r--kpovmodeler/pmclippedby.cpp114
-rw-r--r--kpovmodeler/pmclippedby.h88
-rw-r--r--kpovmodeler/pmclippedbyedit.cpp65
-rw-r--r--kpovmodeler/pmclippedbyedit.h59
-rw-r--r--kpovmodeler/pmcolor.cpp196
-rw-r--r--kpovmodeler/pmcolor.h130
-rw-r--r--kpovmodeler/pmcoloredit.cpp201
-rw-r--r--kpovmodeler/pmcoloredit.h83
-rw-r--r--kpovmodeler/pmcolorsettings.cpp163
-rw-r--r--kpovmodeler/pmcolorsettings.h58
-rw-r--r--kpovmodeler/pmcommand.h146
-rw-r--r--kpovmodeler/pmcommandmanager.cpp99
-rw-r--r--kpovmodeler/pmcommandmanager.h118
-rw-r--r--kpovmodeler/pmcomment.cpp174
-rw-r--r--kpovmodeler/pmcomment.h92
-rw-r--r--kpovmodeler/pmcommentedit.cpp75
-rw-r--r--kpovmodeler/pmcommentedit.h62
-rw-r--r--kpovmodeler/pmcompositeobject.cpp396
-rw-r--r--kpovmodeler/pmcompositeobject.h198
-rw-r--r--kpovmodeler/pmcone.cpp451
-rw-r--r--kpovmodeler/pmcone.h188
-rw-r--r--kpovmodeler/pmconeedit.cpp119
-rw-r--r--kpovmodeler/pmconeedit.h64
-rw-r--r--kpovmodeler/pmcontrolpoint.cpp99
-rw-r--r--kpovmodeler/pmcontrolpoint.h190
-rw-r--r--kpovmodeler/pmcsg.cpp200
-rw-r--r--kpovmodeler/pmcsg.h105
-rw-r--r--kpovmodeler/pmcsgedit.cpp118
-rw-r--r--kpovmodeler/pmcsgedit.h63
-rw-r--r--kpovmodeler/pmcylinder.cpp407
-rw-r--r--kpovmodeler/pmcylinder.h176
-rw-r--r--kpovmodeler/pmcylinderedit.cpp113
-rw-r--r--kpovmodeler/pmcylinderedit.h63
-rw-r--r--kpovmodeler/pmdatachangecommand.cpp111
-rw-r--r--kpovmodeler/pmdatachangecommand.h68
-rw-r--r--kpovmodeler/pmdebug.h26
-rw-r--r--kpovmodeler/pmdeclare.cpp238
-rw-r--r--kpovmodeler/pmdeclare.h147
-rw-r--r--kpovmodeler/pmdeclareedit.cpp206
-rw-r--r--kpovmodeler/pmdeclareedit.h74
-rw-r--r--kpovmodeler/pmdefaults.h131
-rw-r--r--kpovmodeler/pmdeletecommand.cpp281
-rw-r--r--kpovmodeler/pmdeletecommand.h126
-rw-r--r--kpovmodeler/pmdensity.cpp76
-rw-r--r--kpovmodeler/pmdensity.h76
-rw-r--r--kpovmodeler/pmdensityedit.cpp44
-rw-r--r--kpovmodeler/pmdensityedit.h58
-rw-r--r--kpovmodeler/pmdetailobject.cpp151
-rw-r--r--kpovmodeler/pmdetailobject.h115
-rw-r--r--kpovmodeler/pmdetailobjectedit.cpp122
-rw-r--r--kpovmodeler/pmdetailobjectedit.h68
-rw-r--r--kpovmodeler/pmdialogeditbase.cpp558
-rw-r--r--kpovmodeler/pmdialogeditbase.h356
-rw-r--r--kpovmodeler/pmdialogview.cpp441
-rw-r--r--kpovmodeler/pmdialogview.h163
-rw-r--r--kpovmodeler/pmdisc.cpp440
-rw-r--r--kpovmodeler/pmdisc.h180
-rw-r--r--kpovmodeler/pmdiscedit.cpp147
-rw-r--r--kpovmodeler/pmdiscedit.h67
-rw-r--r--kpovmodeler/pmdistancecontrolpoint.cpp92
-rw-r--r--kpovmodeler/pmdistancecontrolpoint.h110
-rw-r--r--kpovmodeler/pmdockwidget.cpp2549
-rw-r--r--kpovmodeler/pmdockwidget.h1478
-rw-r--r--kpovmodeler/pmdockwidget_private.cpp372
-rw-r--r--kpovmodeler/pmdockwidget_private.h142
-rw-r--r--kpovmodeler/pmdocumentationmap.cpp193
-rw-r--r--kpovmodeler/pmdocumentationmap.h138
-rw-r--r--kpovmodeler/pmdocumentformat.h26
-rw-r--r--kpovmodeler/pmdragwidget.cpp49
-rw-r--r--kpovmodeler/pmdragwidget.h51
-rw-r--r--kpovmodeler/pmenumproperty.cpp57
-rw-r--r--kpovmodeler/pmenumproperty.h110
-rw-r--r--kpovmodeler/pmerrordialog.cpp136
-rw-r--r--kpovmodeler/pmerrordialog.h73
-rw-r--r--kpovmodeler/pmerrorflags.h31
-rw-r--r--kpovmodeler/pmface.cpp119
-rw-r--r--kpovmodeler/pmface.h130
-rw-r--r--kpovmodeler/pmfactory.cpp102
-rw-r--r--kpovmodeler/pmfactory.h48
-rw-r--r--kpovmodeler/pmfiledialog.cpp104
-rw-r--r--kpovmodeler/pmfiledialog.h60
-rw-r--r--kpovmodeler/pmfinish.cpp765
-rw-r--r--kpovmodeler/pmfinish.h208
-rw-r--r--kpovmodeler/pmfinishedit.cpp474
-rw-r--r--kpovmodeler/pmfinishedit.h122
-rw-r--r--kpovmodeler/pmfog.cpp347
-rw-r--r--kpovmodeler/pmfog.h129
-rw-r--r--kpovmodeler/pmfogedit.cpp240
-rw-r--r--kpovmodeler/pmfogedit.h95
-rw-r--r--kpovmodeler/pmformulalabel.cpp190
-rw-r--r--kpovmodeler/pmformulalabel.h69
-rw-r--r--kpovmodeler/pmglobalphotons.cpp521
-rw-r--r--kpovmodeler/pmglobalphotons.h284
-rw-r--r--kpovmodeler/pmglobalphotonsedit.cpp328
-rw-r--r--kpovmodeler/pmglobalphotonsedit.h98
-rw-r--r--kpovmodeler/pmglobals.h29
-rw-r--r--kpovmodeler/pmglobalsettings.cpp516
-rw-r--r--kpovmodeler/pmglobalsettings.h268
-rw-r--r--kpovmodeler/pmglobalsettingsedit.cpp317
-rw-r--r--kpovmodeler/pmglobalsettingsedit.h93
-rw-r--r--kpovmodeler/pmglview.cpp1853
-rw-r--r--kpovmodeler/pmglview.h589
-rw-r--r--kpovmodeler/pmgraphicalobject.cpp248
-rw-r--r--kpovmodeler/pmgraphicalobject.h141
-rw-r--r--kpovmodeler/pmgraphicalobjectedit.cpp168
-rw-r--r--kpovmodeler/pmgraphicalobjectedit.h78
-rw-r--r--kpovmodeler/pmgridsettings.cpp155
-rw-r--r--kpovmodeler/pmgridsettings.h60
-rw-r--r--kpovmodeler/pmheightfield.cpp469
-rw-r--r--kpovmodeler/pmheightfield.h180
-rw-r--r--kpovmodeler/pmheightfieldedit.cpp201
-rw-r--r--kpovmodeler/pmheightfieldedit.h87
-rw-r--r--kpovmodeler/pmheightfieldroam.cpp422
-rw-r--r--kpovmodeler/pmheightfieldroam.h283
-rw-r--r--kpovmodeler/pmimagemap.cpp522
-rw-r--r--kpovmodeler/pmimagemap.h209
-rw-r--r--kpovmodeler/pmimagemapedit.cpp625
-rw-r--r--kpovmodeler/pmimagemapedit.h121
-rw-r--r--kpovmodeler/pminserterrordialog.cpp51
-rw-r--r--kpovmodeler/pminserterrordialog.h54
-rw-r--r--kpovmodeler/pminsertpopup.cpp90
-rw-r--r--kpovmodeler/pminsertpopup.h81
-rw-r--r--kpovmodeler/pminsertrules.dtd97
-rw-r--r--kpovmodeler/pminsertrulesystem.cpp1061
-rw-r--r--kpovmodeler/pminsertrulesystem.h678
-rw-r--r--kpovmodeler/pminterior.cpp343
-rw-r--r--kpovmodeler/pminterior.h128
-rw-r--r--kpovmodeler/pminterioredit.cpp212
-rw-r--r--kpovmodeler/pminterioredit.h85
-rw-r--r--kpovmodeler/pminteriortexture.cpp75
-rw-r--r--kpovmodeler/pminteriortexture.h71
-rw-r--r--kpovmodeler/pminteriortextureedit.cpp44
-rw-r--r--kpovmodeler/pminteriortextureedit.h58
-rw-r--r--kpovmodeler/pmiomanager.cpp96
-rw-r--r--kpovmodeler/pmiomanager.h184
-rw-r--r--kpovmodeler/pmisosurface.cpp419
-rw-r--r--kpovmodeler/pmisosurface.h234
-rw-r--r--kpovmodeler/pmisosurfaceedit.cpp326
-rw-r--r--kpovmodeler/pmisosurfaceedit.h92
-rw-r--r--kpovmodeler/pmjuliafractal.cpp449
-rw-r--r--kpovmodeler/pmjuliafractal.h174
-rw-r--r--kpovmodeler/pmjuliafractaledit.cpp380
-rw-r--r--kpovmodeler/pmjuliafractaledit.h79
-rw-r--r--kpovmodeler/pmlathe.cpp948
-rw-r--r--kpovmodeler/pmlathe.h193
-rw-r--r--kpovmodeler/pmlatheedit.cpp333
-rw-r--r--kpovmodeler/pmlatheedit.h89
-rw-r--r--kpovmodeler/pmlayoutsettings.cpp774
-rw-r--r--kpovmodeler/pmlayoutsettings.h174
-rw-r--r--kpovmodeler/pmlibrarybrowser.cpp304
-rw-r--r--kpovmodeler/pmlibrarybrowser.h119
-rw-r--r--kpovmodeler/pmlibraryentrypreview.cpp344
-rw-r--r--kpovmodeler/pmlibraryentrypreview.h119
-rw-r--r--kpovmodeler/pmlibraryhandle.cpp395
-rw-r--r--kpovmodeler/pmlibraryhandle.h210
-rw-r--r--kpovmodeler/pmlibraryhandleedit.cpp131
-rw-r--r--kpovmodeler/pmlibraryhandleedit.h66
-rw-r--r--kpovmodeler/pmlibraryiconview.cpp328
-rw-r--r--kpovmodeler/pmlibraryiconview.h123
-rw-r--r--kpovmodeler/pmlibrarymanager.cpp121
-rw-r--r--kpovmodeler/pmlibrarymanager.h97
-rw-r--r--kpovmodeler/pmlibraryobject.cpp331
-rw-r--r--kpovmodeler/pmlibraryobject.h136
-rw-r--r--kpovmodeler/pmlibraryobjectsearch.cpp86
-rw-r--r--kpovmodeler/pmlibraryobjectsearch.h55
-rw-r--r--kpovmodeler/pmlight.cpp1064
-rw-r--r--kpovmodeler/pmlight.h372
-rw-r--r--kpovmodeler/pmlightedit.cpp450
-rw-r--r--kpovmodeler/pmlightedit.h115
-rw-r--r--kpovmodeler/pmlightgroup.cpp134
-rw-r--r--kpovmodeler/pmlightgroup.h98
-rw-r--r--kpovmodeler/pmlightgroupedit.cpp78
-rw-r--r--kpovmodeler/pmlightgroupedit.h64
-rw-r--r--kpovmodeler/pmline.cpp22
-rw-r--r--kpovmodeler/pmline.h102
-rw-r--r--kpovmodeler/pmlineedits.cpp229
-rw-r--r--kpovmodeler/pmlineedits.h133
-rw-r--r--kpovmodeler/pmlinkedit.cpp146
-rw-r--r--kpovmodeler/pmlinkedit.h105
-rw-r--r--kpovmodeler/pmlistpattern.cpp469
-rw-r--r--kpovmodeler/pmlistpattern.h351
-rw-r--r--kpovmodeler/pmlistpatternedit.cpp225
-rw-r--r--kpovmodeler/pmlistpatternedit.h78
-rw-r--r--kpovmodeler/pmlookslike.cpp92
-rw-r--r--kpovmodeler/pmlookslike.h82
-rw-r--r--kpovmodeler/pmmapmemento.cpp51
-rw-r--r--kpovmodeler/pmmapmemento.h81
-rw-r--r--kpovmodeler/pmmaterial.cpp75
-rw-r--r--kpovmodeler/pmmaterial.h75
-rw-r--r--kpovmodeler/pmmaterialedit.cpp44
-rw-r--r--kpovmodeler/pmmaterialedit.h58
-rw-r--r--kpovmodeler/pmmaterialmap.cpp338
-rw-r--r--kpovmodeler/pmmaterialmap.h153
-rw-r--r--kpovmodeler/pmmaterialmapedit.cpp299
-rw-r--r--kpovmodeler/pmmaterialmapedit.h81
-rw-r--r--kpovmodeler/pmmath.cpp67
-rw-r--r--kpovmodeler/pmmath.h48
-rw-r--r--kpovmodeler/pmmatrix.cpp442
-rw-r--r--kpovmodeler/pmmatrix.h188
-rw-r--r--kpovmodeler/pmmedia.cpp480
-rw-r--r--kpovmodeler/pmmedia.h149
-rw-r--r--kpovmodeler/pmmediaedit.cpp370
-rw-r--r--kpovmodeler/pmmediaedit.h102
-rw-r--r--kpovmodeler/pmmemento.cpp220
-rw-r--r--kpovmodeler/pmmemento.h318
-rw-r--r--kpovmodeler/pmmesh.cpp557
-rw-r--r--kpovmodeler/pmmesh.h142
-rw-r--r--kpovmodeler/pmmeshedit.cpp100
-rw-r--r--kpovmodeler/pmmeshedit.h67
-rw-r--r--kpovmodeler/pmmessage.cpp43
-rw-r--r--kpovmodeler/pmmessage.h79
-rw-r--r--kpovmodeler/pmmetaobject.cpp95
-rw-r--r--kpovmodeler/pmmetaobject.h416
-rw-r--r--kpovmodeler/pmmovecommand.cpp478
-rw-r--r--kpovmodeler/pmmovecommand.h88
-rw-r--r--kpovmodeler/pmnamedobject.cpp111
-rw-r--r--kpovmodeler/pmnamedobject.h89
-rw-r--r--kpovmodeler/pmnamedobjectedit.cpp81
-rw-r--r--kpovmodeler/pmnamedobjectedit.h64
-rw-r--r--kpovmodeler/pmnormal.cpp189
-rw-r--r--kpovmodeler/pmnormal.h122
-rw-r--r--kpovmodeler/pmnormaledit.cpp118
-rw-r--r--kpovmodeler/pmnormaledit.h70
-rw-r--r--kpovmodeler/pmobject.cpp283
-rw-r--r--kpovmodeler/pmobject.h511
-rw-r--r--kpovmodeler/pmobjectaction.h100
-rw-r--r--kpovmodeler/pmobjectdrag.cpp230
-rw-r--r--kpovmodeler/pmobjectdrag.h81
-rw-r--r--kpovmodeler/pmobjectlibrarysettings.cpp189
-rw-r--r--kpovmodeler/pmobjectlibrarysettings.h78
-rw-r--r--kpovmodeler/pmobjectlink.cpp197
-rw-r--r--kpovmodeler/pmobjectlink.h99
-rw-r--r--kpovmodeler/pmobjectlinkedit.cpp74
-rw-r--r--kpovmodeler/pmobjectlinkedit.h62
-rw-r--r--kpovmodeler/pmobjectselect.cpp361
-rw-r--r--kpovmodeler/pmobjectselect.h132
-rw-r--r--kpovmodeler/pmobjectsettings.cpp550
-rw-r--r--kpovmodeler/pmobjectsettings.h78
-rw-r--r--kpovmodeler/pmopenglsettings.cpp59
-rw-r--r--kpovmodeler/pmopenglsettings.h54
-rw-r--r--kpovmodeler/pmoutputdevice.cpp203
-rw-r--r--kpovmodeler/pmoutputdevice.h159
-rw-r--r--kpovmodeler/pmpalettevalue.cpp81
-rw-r--r--kpovmodeler/pmpalettevalue.h78
-rw-r--r--kpovmodeler/pmpalettevalueedit.cpp99
-rw-r--r--kpovmodeler/pmpalettevalueedit.h67
-rw-r--r--kpovmodeler/pmpalettevaluememento.cpp84
-rw-r--r--kpovmodeler/pmpalettevaluememento.h85
-rw-r--r--kpovmodeler/pmparser.cpp433
-rw-r--r--kpovmodeler/pmparser.h299
-rw-r--r--kpovmodeler/pmpart.cpp2884
-rw-r--r--kpovmodeler/pmpart.h1041
-rw-r--r--kpovmodeler/pmpartiface.h119
-rw-r--r--kpovmodeler/pmpattern.cpp1126
-rw-r--r--kpovmodeler/pmpattern.h449
-rw-r--r--kpovmodeler/pmpatternedit.cpp1073
-rw-r--r--kpovmodeler/pmpatternedit.h164
-rw-r--r--kpovmodeler/pmphotons.cpp240
-rw-r--r--kpovmodeler/pmphotons.h160
-rw-r--r--kpovmodeler/pmphotonsedit.cpp160
-rw-r--r--kpovmodeler/pmphotonsedit.h79
-rw-r--r--kpovmodeler/pmpigment.cpp124
-rw-r--r--kpovmodeler/pmpigment.h95
-rw-r--r--kpovmodeler/pmpigmentedit.cpp68
-rw-r--r--kpovmodeler/pmpigmentedit.h60
-rw-r--r--kpovmodeler/pmplane.cpp276
-rw-r--r--kpovmodeler/pmplane.h148
-rw-r--r--kpovmodeler/pmplaneedit.cpp124
-rw-r--r--kpovmodeler/pmplaneedit.h66
-rw-r--r--kpovmodeler/pmplanenormalcontrolpoint.cpp93
-rw-r--r--kpovmodeler/pmplanenormalcontrolpoint.h92
-rw-r--r--kpovmodeler/pmpluginmanager.cpp115
-rw-r--r--kpovmodeler/pmpluginmanager.h113
-rw-r--r--kpovmodeler/pmpluginsettings.cpp150
-rw-r--r--kpovmodeler/pmpluginsettings.h62
-rw-r--r--kpovmodeler/pmpoint.cpp98
-rw-r--r--kpovmodeler/pmpoint.h122
-rw-r--r--kpovmodeler/pmpolynom.cpp238
-rw-r--r--kpovmodeler/pmpolynom.h105
-rw-r--r--kpovmodeler/pmpolynomedit.cpp255
-rw-r--r--kpovmodeler/pmpolynomedit.h80
-rw-r--r--kpovmodeler/pmpolynomexponents.cpp71
-rw-r--r--kpovmodeler/pmpolynomexponents.h129
-rw-r--r--kpovmodeler/pmpovray31format.cpp153
-rw-r--r--kpovmodeler/pmpovray31format.h64
-rw-r--r--kpovmodeler/pmpovray31serialization.cpp2199
-rw-r--r--kpovmodeler/pmpovray31serialization.h103
-rw-r--r--kpovmodeler/pmpovray35format.cpp100
-rw-r--r--kpovmodeler/pmpovray35format.h64
-rw-r--r--kpovmodeler/pmpovray35serialization.cpp1471
-rw-r--r--kpovmodeler/pmpovray35serialization.h49
-rw-r--r--kpovmodeler/pmpovrayformat.cpp52
-rw-r--r--kpovmodeler/pmpovrayformat.h94
-rw-r--r--kpovmodeler/pmpovraymatrix.cpp152
-rw-r--r--kpovmodeler/pmpovraymatrix.h97
-rw-r--r--kpovmodeler/pmpovraymatrixedit.cpp102
-rw-r--r--kpovmodeler/pmpovraymatrixedit.h62
-rw-r--r--kpovmodeler/pmpovrayoutputwidget.cpp115
-rw-r--r--kpovmodeler/pmpovrayoutputwidget.h77
-rw-r--r--kpovmodeler/pmpovrayparser.cpp7213
-rw-r--r--kpovmodeler/pmpovrayparser.h534
-rw-r--r--kpovmodeler/pmpovrayrenderwidget.cpp437
-rw-r--r--kpovmodeler/pmpovrayrenderwidget.h177
-rw-r--r--kpovmodeler/pmpovraysettings.cpp308
-rw-r--r--kpovmodeler/pmpovraysettings.h98
-rw-r--r--kpovmodeler/pmpovraywidget.cpp411
-rw-r--r--kpovmodeler/pmpovraywidget.h103
-rw-r--r--kpovmodeler/pmpreviewsettings.cpp207
-rw-r--r--kpovmodeler/pmpreviewsettings.h69
-rw-r--r--kpovmodeler/pmprism.cpp1187
-rw-r--r--kpovmodeler/pmprism.h224
-rw-r--r--kpovmodeler/pmprismedit.cpp696
-rw-r--r--kpovmodeler/pmprismedit.h122
-rw-r--r--kpovmodeler/pmprismmemento.cpp55
-rw-r--r--kpovmodeler/pmprismmemento.h71
-rw-r--r--kpovmodeler/pmprojectedthrough.cpp92
-rw-r--r--kpovmodeler/pmprojectedthrough.h82
-rw-r--r--kpovmodeler/pmprototypemanager.cpp243
-rw-r--r--kpovmodeler/pmprototypemanager.h149
-rw-r--r--kpovmodeler/pmquickcolor.cpp132
-rw-r--r--kpovmodeler/pmquickcolor.h100
-rw-r--r--kpovmodeler/pmquickcoloredit.cpp77
-rw-r--r--kpovmodeler/pmquickcoloredit.h65
-rw-r--r--kpovmodeler/pmradiosity.cpp428
-rw-r--r--kpovmodeler/pmradiosity.h241
-rw-r--r--kpovmodeler/pmradiosityedit.cpp233
-rw-r--r--kpovmodeler/pmradiosityedit.h81
-rw-r--r--kpovmodeler/pmrainbow.cpp422
-rw-r--r--kpovmodeler/pmrainbow.h139
-rw-r--r--kpovmodeler/pmrainbowedit.cpp278
-rw-r--r--kpovmodeler/pmrainbowedit.h90
-rw-r--r--kpovmodeler/pmraw.cpp135
-rw-r--r--kpovmodeler/pmraw.h90
-rw-r--r--kpovmodeler/pmrawedit.cpp79
-rw-r--r--kpovmodeler/pmrawedit.h62
-rw-r--r--kpovmodeler/pmrecursiveobjectiterator.cpp62
-rw-r--r--kpovmodeler/pmrecursiveobjectiterator.h49
-rw-r--r--kpovmodeler/pmrendermanager.cpp1647
-rw-r--r--kpovmodeler/pmrendermanager.h435
-rw-r--r--kpovmodeler/pmrendermode.cpp220
-rw-r--r--kpovmodeler/pmrendermode.h128
-rw-r--r--kpovmodeler/pmrendermodesdialog.cpp611
-rw-r--r--kpovmodeler/pmrendermodesdialog.h179
-rw-r--r--kpovmodeler/pmresourcelocator.cpp103
-rw-r--r--kpovmodeler/pmresourcelocator.h65
-rw-r--r--kpovmodeler/pmrotate.cpp164
-rw-r--r--kpovmodeler/pmrotate.h102
-rw-r--r--kpovmodeler/pmrotatecontrolpoint.cpp78
-rw-r--r--kpovmodeler/pmrotatecontrolpoint.h73
-rw-r--r--kpovmodeler/pmrotateedit.cpp74
-rw-r--r--kpovmodeler/pmrotateedit.h62
-rw-r--r--kpovmodeler/pmscale.cpp163
-rw-r--r--kpovmodeler/pmscale.h103
-rw-r--r--kpovmodeler/pmscalecontrolpoint.cpp58
-rw-r--r--kpovmodeler/pmscalecontrolpoint.h71
-rw-r--r--kpovmodeler/pmscaleedit.cpp74
-rw-r--r--kpovmodeler/pmscaleedit.h62
-rw-r--r--kpovmodeler/pmscanner.cpp1353
-rw-r--r--kpovmodeler/pmscanner.h191
-rw-r--r--kpovmodeler/pmscene.cpp119
-rw-r--r--kpovmodeler/pmscene.h92
-rw-r--r--kpovmodeler/pmserializer.cpp93
-rw-r--r--kpovmodeler/pmserializer.h179
-rw-r--r--kpovmodeler/pmsettingsdialog.cpp263
-rw-r--r--kpovmodeler/pmsettingsdialog.h187
-rw-r--r--kpovmodeler/pmshell.cpp676
-rw-r--r--kpovmodeler/pmshell.h172
-rw-r--r--kpovmodeler/pmskysphere.cpp76
-rw-r--r--kpovmodeler/pmskysphere.h75
-rw-r--r--kpovmodeler/pmskysphereedit.cpp44
-rw-r--r--kpovmodeler/pmskysphereedit.h58
-rw-r--r--kpovmodeler/pmslope.cpp146
-rw-r--r--kpovmodeler/pmslope.h94
-rw-r--r--kpovmodeler/pmslopeedit.cpp95
-rw-r--r--kpovmodeler/pmslopeedit.h68
-rw-r--r--kpovmodeler/pmsolidcolor.cpp127
-rw-r--r--kpovmodeler/pmsolidcolor.h97
-rw-r--r--kpovmodeler/pmsolidcoloredit.cpp79
-rw-r--r--kpovmodeler/pmsolidcoloredit.h62
-rw-r--r--kpovmodeler/pmsolidobject.cpp140
-rw-r--r--kpovmodeler/pmsolidobject.h94
-rw-r--r--kpovmodeler/pmsolidobjectedit.cpp82
-rw-r--r--kpovmodeler/pmsolidobjectedit.h63
-rw-r--r--kpovmodeler/pmsor.cpp708
-rw-r--r--kpovmodeler/pmsor.h191
-rw-r--r--kpovmodeler/pmsorcontrolpoint.cpp228
-rw-r--r--kpovmodeler/pmsorcontrolpoint.h99
-rw-r--r--kpovmodeler/pmsoredit.cpp282
-rw-r--r--kpovmodeler/pmsoredit.h86
-rw-r--r--kpovmodeler/pmsorsegment.cpp97
-rw-r--r--kpovmodeler/pmsorsegment.h77
-rw-r--r--kpovmodeler/pmsphere.cpp411
-rw-r--r--kpovmodeler/pmsphere.h165
-rw-r--r--kpovmodeler/pmsphereedit.cpp95
-rw-r--r--kpovmodeler/pmsphereedit.h64
-rw-r--r--kpovmodeler/pmspheresweep.cpp894
-rw-r--r--kpovmodeler/pmspheresweep.h245
-rw-r--r--kpovmodeler/pmspheresweepedit.cpp354
-rw-r--r--kpovmodeler/pmspheresweepedit.h90
-rw-r--r--kpovmodeler/pmsplinememento.cpp58
-rw-r--r--kpovmodeler/pmsplinememento.h68
-rw-r--r--kpovmodeler/pmsplinesegment.cpp107
-rw-r--r--kpovmodeler/pmsplinesegment.h122
-rw-r--r--kpovmodeler/pmsqe.cpp413
-rw-r--r--kpovmodeler/pmsqe.h155
-rw-r--r--kpovmodeler/pmsqeedit.cpp93
-rw-r--r--kpovmodeler/pmsqeedit.h63
-rw-r--r--kpovmodeler/pmsymboltable.cpp121
-rw-r--r--kpovmodeler/pmsymboltable.h128
-rw-r--r--kpovmodeler/pmtext.cpp339
-rw-r--r--kpovmodeler/pmtext.h147
-rw-r--r--kpovmodeler/pmtextedit.cpp138
-rw-r--r--kpovmodeler/pmtextedit.h74
-rw-r--r--kpovmodeler/pmtexture.cpp124
-rw-r--r--kpovmodeler/pmtexture.h95
-rw-r--r--kpovmodeler/pmtexturebase.cpp180
-rw-r--r--kpovmodeler/pmtexturebase.h96
-rw-r--r--kpovmodeler/pmtexturebaseedit.cpp72
-rw-r--r--kpovmodeler/pmtexturebaseedit.h64
-rw-r--r--kpovmodeler/pmtextureedit.cpp67
-rw-r--r--kpovmodeler/pmtextureedit.h60
-rw-r--r--kpovmodeler/pmtexturemap.cpp601
-rw-r--r--kpovmodeler/pmtexturemap.h368
-rw-r--r--kpovmodeler/pmtexturemapedit.cpp152
-rw-r--r--kpovmodeler/pmtexturemapedit.h70
-rw-r--r--kpovmodeler/pmthreestate.h26
-rw-r--r--kpovmodeler/pmtokens.h463
-rw-r--r--kpovmodeler/pmtorus.cpp379
-rw-r--r--kpovmodeler/pmtorus.h172
-rw-r--r--kpovmodeler/pmtorusedit.cpp105
-rw-r--r--kpovmodeler/pmtorusedit.h65
-rw-r--r--kpovmodeler/pmtranslate.cpp162
-rw-r--r--kpovmodeler/pmtranslate.h102
-rw-r--r--kpovmodeler/pmtranslatecontrolpoint.cpp50
-rw-r--r--kpovmodeler/pmtranslatecontrolpoint.h71
-rw-r--r--kpovmodeler/pmtranslateedit.cpp74
-rw-r--r--kpovmodeler/pmtranslateedit.h62
-rw-r--r--kpovmodeler/pmtreeview.cpp820
-rw-r--r--kpovmodeler/pmtreeview.h182
-rw-r--r--kpovmodeler/pmtreeviewitem.cpp117
-rw-r--r--kpovmodeler/pmtreeviewitem.h88
-rw-r--r--kpovmodeler/pmtriangle.cpp621
-rw-r--r--kpovmodeler/pmtriangle.h158
-rw-r--r--kpovmodeler/pmtriangleedit.cpp273
-rw-r--r--kpovmodeler/pmtriangleedit.h77
-rw-r--r--kpovmodeler/pmtruetypecache.cpp395
-rw-r--r--kpovmodeler/pmtruetypecache.h194
-rw-r--r--kpovmodeler/pmunknownview.cpp37
-rw-r--r--kpovmodeler/pmunknownview.h47
-rw-r--r--kpovmodeler/pmvalue.h102
-rw-r--r--kpovmodeler/pmvariant.cpp920
-rw-r--r--kpovmodeler/pmvariant.h221
-rw-r--r--kpovmodeler/pmvector.cpp593
-rw-r--r--kpovmodeler/pmvector.h275
-rw-r--r--kpovmodeler/pmvectorcontrolpoint.cpp89
-rw-r--r--kpovmodeler/pmvectorcontrolpoint.h101
-rw-r--r--kpovmodeler/pmvectoredit.cpp235
-rw-r--r--kpovmodeler/pmvectoredit.h100
-rw-r--r--kpovmodeler/pmvectorlistedit.cpp357
-rw-r--r--kpovmodeler/pmvectorlistedit.h174
-rw-r--r--kpovmodeler/pmview.cpp108
-rw-r--r--kpovmodeler/pmview.h76
-rw-r--r--kpovmodeler/pmviewbase.cpp20
-rw-r--r--kpovmodeler/pmviewbase.h128
-rw-r--r--kpovmodeler/pmviewfactory.cpp94
-rw-r--r--kpovmodeler/pmviewfactory.h145
-rw-r--r--kpovmodeler/pmviewlayoutmanager.cpp935
-rw-r--r--kpovmodeler/pmviewlayoutmanager.h306
-rw-r--r--kpovmodeler/pmviewstructure.cpp127
-rw-r--r--kpovmodeler/pmviewstructure.h222
-rw-r--r--kpovmodeler/pmwarp.cpp548
-rw-r--r--kpovmodeler/pmwarp.h162
-rw-r--r--kpovmodeler/pmwarpedit.cpp407
-rw-r--r--kpovmodeler/pmwarpedit.h110
-rw-r--r--kpovmodeler/pmxmlhelper.cpp160
-rw-r--r--kpovmodeler/pmxmlhelper.h121
-rw-r--r--kpovmodeler/pmxmlparser.cpp177
-rw-r--r--kpovmodeler/pmxmlparser.h84
-rw-r--r--kpovmodeler/povraydocmap.xml174
-rw-r--r--kpovmodeler/questionmark.pngbin0 -> 12749 bytes
-rw-r--r--kpovmodeler/version.h18
919 files changed, 124914 insertions, 0 deletions
diff --git a/kpovmodeler/AUTHORS b/kpovmodeler/AUTHORS
new file mode 100644
index 00000000..5afc7760
--- /dev/null
+++ b/kpovmodeler/AUTHORS
@@ -0,0 +1,13 @@
+Maintainer, framework, everything:
+Andreas Zehender <zehender@kde.org>
+
+Textures:
+Luis Passos Carvalho <lpassos@oninetspeed.pt>
+
+Povray 3.5 Objects:
+Leon Pennington <leon@leonscape.co.uk>
+
+Some graphical objects:
+Philippe Van Hecke <lephiloux@tiscalinet.be>
+Leonardo Skorianez <lsk@if.ufrj.br>
+
diff --git a/kpovmodeler/BUGS b/kpovmodeler/BUGS
new file mode 100644
index 00000000..7cecd8b3
--- /dev/null
+++ b/kpovmodeler/BUGS
@@ -0,0 +1,5 @@
+Known bugs in kpovmodeler in version 0.2
+--------
+
+None at the moment
+
diff --git a/kpovmodeler/COPYING b/kpovmodeler/COPYING
new file mode 100644
index 00000000..54754ab4
--- /dev/null
+++ b/kpovmodeler/COPYING
@@ -0,0 +1,341 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/kpovmodeler/ChangeLog b/kpovmodeler/ChangeLog
new file mode 100644
index 00000000..9ad06f1f
--- /dev/null
+++ b/kpovmodeler/ChangeLog
@@ -0,0 +1,83 @@
+Version 0.0.1:
+ - Development release
+ - Framework is finished
+ - Some basic objects and textures
+
+Version 0.1
+ - First release for the public
+ - Most textures are supported
+ - All simple objects are supported
+ - Rendering the scene with povray inside the program
+ - Textures can be previewed inside the dialog view
+ - The camera supports now focal blur and all complex projections
+ - The camera view can render all projections except the omnimax projection
+
+Version 0.1.1
+ - Bugfix release
+ - Fixed bugs:
+ - A bug that causes the program to crash during rendering
+ - A bug that causes the program to hang during auto scroll
+ - "Revert file" now works
+
+Version 0.2
+ - Ported to Qt 3.0 / KDE 3.0, moved to the kdegraphics package
+ - Dock widgets
+ - Qt OpenGL extension removed
+ - Key navigation in the tree view
+ - Compressed document format
+ - Fixed bugs:
+ - Validation check for the depth edit in the pattern edit
+ - Texture preview didn't serialize all needed declares
+ - "File close" follows the style guide
+
+Version 1.0
+ - View layouts
+ - User documentation
+
+Version 1.1
+ - Plugin framework (work in progress)
+ - Object and texture library (work in progress)
+ - new --no-dri command line option and configuration dialog to
+ disable direct rendering
+ - First characters of comments are used as description in the tree view
+ - The user is asked if pending changes should be saved before rendering
+ - Nicer render speed values
+ - Empty line before comments in povray output
+ - Control point selection in the properties view for bicubic patch,
+ sor, lathe and prism
+ - Export flag for graphical objects and the camera
+ - Removed the glut dependency
+ - Added Heightfield Viewstructure
+ - Light object gained, parallel, circular and orient options
+ - Dispersion options added to interior
+ - Added Noise generator options to global settings and patterns
+ - New warp types added
+ - Added accuracy setting to normals
+ - Added new finish options
+ - New objects:
+ - Isosurface
+ - Sphere sweep
+ - Projected through
+ - Radiosity
+ - Global photons
+ - Photons
+ - Light groups
+ - Interior textures
+ - Mesh
+
+Version 1.1.1
+ - Added graphical editing to Mesh object
+ - Updated Media too handle new methods and options
+ - Added new patterns cells, additional crackle options, julia,
+ additional mandel options, and slope
+ - Added keywords no_image, no_reflection, and double_illuminate to
+ graphical objects
+ - Added uv mapping and uv vectors
+
+Version 1.1.2
+ - Added local and global detail levels too:
+ Sphere, Cylinder, Cone, Torus, Disc, Blob Sphere, Blob Cylinder, Lathe,
+ SOR, Prism, SQE, Sphere sweep and Heightfield.
+
+Version 1.2
+ - The user is asked if pending changes should be saved before saving or exporting
diff --git a/kpovmodeler/INSTALL b/kpovmodeler/INSTALL
new file mode 100644
index 00000000..02a4a074
--- /dev/null
+++ b/kpovmodeler/INSTALL
@@ -0,0 +1,167 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 4. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/kpovmodeler/Makefile.am b/kpovmodeler/Makefile.am
new file mode 100644
index 00000000..4e1f3ef9
--- /dev/null
+++ b/kpovmodeler/Makefile.am
@@ -0,0 +1,251 @@
+
+INCLUDES = $(LIBFREETYPE_CFLAGS) $(all_includes)
+
+SUBDIRS = pics examples
+
+KDE_OPTIONS = nofinal
+
+####
+# common lib
+
+lib_LTLIBRARIES = libkpovmodeler.la
+libkpovmodeler_la_SOURCES = pmpart.cpp pmfactory.cpp \
+ pmview.cpp pmshell.cpp pmobjectdrag.cpp \
+ pmtreeview.cpp pmmessage.cpp pmtreeviewitem.cpp \
+ pmerrordialog.cpp pminsertpopup.cpp pminserterrordialog.cpp \
+ pmglview.cpp pmrendermanager.cpp pmobjectselect.cpp \
+ pmrendermodesdialog.cpp pmpovrayrenderwidget.cpp pmpovraywidget.cpp \
+ pmpovrayoutputwidget.cpp pmsettingsdialog.cpp \
+ pmcolorsettings.cpp pmgridsettings.cpp pmlayoutsettings.cpp \
+ pmobjectlibrarysettings.cpp pmobjectsettings.cpp pmpluginsettings.cpp \
+ pmpovraysettings.cpp pmpreviewsettings.cpp pmopenglsettings.cpp \
+ pmdockwidget.cpp pmdockwidget_private.cpp pmviewlayoutmanager.cpp \
+ pmviewbase.cpp pmviewfactory.cpp pmunknownview.cpp pmdragwidget.cpp \
+ \
+ pmprototypemanager.cpp \
+ pmobject.cpp pmcompositeobject.cpp \
+ pmgraphicalobject.cpp pmsolidobject.cpp \
+ pmscene.cpp pmglobalsettings.cpp pmskysphere.cpp pmrainbow.cpp \
+ pmfog.cpp pmbox.cpp pmsphere.cpp pmblob.cpp pmblobsphere.cpp \
+ pmblobcylinder.cpp pmtext.cpp pmjuliafractal.cpp \
+ pmcylinder.cpp pmcone.cpp pmtorus.cpp pmplane.cpp pmpolynom.cpp \
+ pmdisc.cpp pmbicubicpatch.cpp pmtriangle.cpp \
+ pmlathe.cpp pmprism.cpp pmsor.cpp pmsqe.cpp pmheightfield.cpp \
+ pmheightfieldroam.cpp pmcomment.cpp pmraw.cpp pmnamedobject.cpp \
+ pmtranslate.cpp pmscale.cpp pmrotate.cpp pmpovraymatrix.cpp \
+ pmcsg.cpp pmcamera.cpp pmboundedby.cpp pmclippedby.cpp \
+ pmlight.cpp pmlookslike.cpp pmprojectedthrough.cpp\
+ pmtexturebase.cpp pmtexture.cpp pmpigment.cpp \
+ pmsolidcolor.cpp pmlistpattern.cpp pmquickcolor.cpp \
+ pmpattern.cpp pmblendmapmodifiers.cpp pmtexturemap.cpp \
+ pmnormal.cpp pmslope.cpp pmwarp.cpp pmfinish.cpp \
+ pminterior.cpp pmmedia.cpp pmmaterial.cpp pmmaterialmap.cpp \
+ pmdensity.cpp pmimagemap.cpp pmbumpmap.cpp \
+ \
+ pmisosurface.cpp pmradiosity.cpp pmglobalphotons.cpp \
+ pmphotons.cpp pmlightgroup.cpp pminteriortexture.cpp \
+ pmspheresweep.cpp pmmesh.cpp pmdetailobject.cpp \
+ \
+ pmdeclare.cpp pmobjectlink.cpp \
+ pmrecursiveobjectiterator.cpp \
+ \
+ pmaddcommand.cpp pmcommandmanager.cpp pmdatachangecommand.cpp \
+ pmdeletecommand.cpp pmmovecommand.cpp \
+ \
+ pmdialogview.cpp pmdialogeditbase.cpp pmgraphicalobjectedit.cpp \
+ pmnamedobjectedit.cpp pmsolidobjectedit.cpp pmskysphereedit.cpp \
+ pmglobalsettingsedit.cpp pmrainbowedit.cpp pmfogedit.cpp \
+ pmboxedit.cpp pmsphereedit.cpp pmblobedit.cpp pmblobsphereedit.cpp \
+ pmblobcylinderedit.cpp pmtextedit.cpp pmjuliafractaledit.cpp \
+ pmcylinderedit.cpp pmconeedit.cpp pmtorusedit.cpp pmplaneedit.cpp \
+ pmpolynomedit.cpp pmheightfieldedit.cpp \
+ pmlatheedit.cpp pmprismedit.cpp pmsoredit.cpp pmsqeedit.cpp \
+ pmdiscedit.cpp pmbicubicpatchedit.cpp pmtriangleedit.cpp \
+ pmcommentedit.cpp pmrawedit.cpp \
+ pmrotateedit.cpp pmscaleedit.cpp pmtranslateedit.cpp \
+ pmpovraymatrixedit.cpp \
+ pmcsgedit.cpp pmcameraedit.cpp pmlightedit.cpp pmboundedbyedit.cpp \
+ pmclippedbyedit.cpp \
+ pmlineedits.cpp pmvectorlistedit.cpp pmcoloredit.cpp pmlinkedit.cpp \
+ pmvectoredit.cpp pmpalettevalueedit.cpp pmformulalabel.cpp \
+ pmtexturebaseedit.cpp pmtextureedit.cpp pmpigmentedit.cpp \
+ pmsolidcoloredit.cpp pmlistpatternedit.cpp pmquickcoloredit.cpp \
+ pmpatternedit.cpp pmblendmapmodifiersedit.cpp pmimagemapedit.cpp \
+ pmtexturemapedit.cpp pmbumpmapedit.cpp pmmaterialmapedit.cpp \
+ pmnormaledit.cpp pmslopeedit.cpp pmfinishedit.cpp pmwarpedit.cpp \
+ pminterioredit.cpp pmmediaedit.cpp pmmaterialedit.cpp \
+ pmdensityedit.cpp pmdeclareedit.cpp pmobjectlinkedit.cpp \
+ \
+ pmisosurfaceedit.cpp pmradiosityedit.cpp pmglobalphotonsedit.cpp \
+ pmphotonsedit.cpp pmlightgroupedit.cpp pminteriortextureedit.cpp \
+ pmspheresweepedit.cpp pmmeshedit.cpp pmdetailobjectedit.cpp \
+ \
+ pmcontrolpoint.cpp pm3dcontrolpoint.cpp pm2dcontrolpoint.cpp \
+ pmsorcontrolpoint.cpp pmtranslatecontrolpoint.cpp \
+ pmrotatecontrolpoint.cpp pmscalecontrolpoint.cpp \
+ pmvectorcontrolpoint.cpp pmdistancecontrolpoint.cpp \
+ pmplanenormalcontrolpoint.cpp \
+ \
+ pmmemento.cpp pmmapmemento.cpp pmsplinememento.cpp pmprismmemento.cpp \
+ pmpalettevaluememento.cpp \
+ \
+ pmiomanager.cpp pmpovrayformat.cpp pmpovray31format.cpp pmpovray35format.cpp \
+ pmpovray31serialization.cpp pmpovray35serialization.cpp \
+ pmscanner.cpp pmparser.cpp pmxmlparser.cpp pmpovrayparser.cpp \
+ pmserializer.cpp pmoutputdevice.cpp pmxmlhelper.cpp \
+ pmfiledialog.cpp \
+ \
+ pmpalettevalue.cpp \
+ pmvector.cpp pmmath.cpp pmmatrix.cpp pmviewstructure.cpp pmline.cpp \
+ pmcolor.cpp pmpoint.cpp pmsymboltable.cpp pmactions.cpp \
+ pmsplinesegment.cpp pmsorsegment.cpp pmpolynomexponents.cpp \
+ pmvariant.cpp pmmetaobject.cpp pmenumproperty.cpp pmface.cpp \
+ \
+ pmrendermode.cpp pmresourcelocator.cpp pmtruetypecache.cpp \
+ pmdocumentationmap.cpp pminsertrulesystem.cpp pmlibrarymanager.cpp \
+ pmlibraryhandle.cpp pmlibraryhandleedit.cpp pmlibraryobject.cpp \
+ pmlibraryentrypreview.cpp\
+ pmlibrarybrowser.cpp pmlibraryiconview.cpp pmlibraryobjectsearch.cpp \
+ pmpluginmanager.cpp \
+ pmpartiface.skel
+
+libkpovmodeler_la_LDFLAGS = $(all_libraries) -version-info 0:0:0 -no-undefined $(LIBFREETYPE_RPATH)
+libkpovmodeler_la_LIBADD = $(LIBFREETYPE_LIBS) $(LIB_KPARTS) $(GLLIB) -lXmu -lXi
+METASOURCES = AUTO
+
+noinst_HEADERS = pmpart.h pmfactory.h pmview.h pmshell.h pmobjectdrag.h \
+ pmtreeview.h pmtreeviewitem.h pmmessage.h \
+ pmerrordialog.h pminsertpopup.h pminserterrordialog.h \
+ pmglview.h pmrendermanager.h pmobjectselect.h \
+ pmrendermodesdialog.h pmpovrayrenderwidget.h pmpovraywidget.h \
+ pmpovrayoutputwidget.h pmsettingsdialog.h \
+ pmcolorsettings.h pmgridsettings.h pmlayoutsettings.h \
+ pmobjectlibrarysettings.h pmobjectsettings.h pmpluginsettings.h \
+ pmpovraysettings.h pmpreviewsettings.h pmopenglsettings.h \
+ pmdockwidget.h pmdockwidget_private.h pmviewlayoutmanager.h \
+ pmviewbase.h pmviewfactory.h pmunknownview.h pmdragwidget.h \
+ \
+ pmprototypemanager.h pmallobjects.h \
+ pmobject.h pmcompositeobject.h \
+ pmgraphicalobject.h pmsolidobject.h \
+ pmscene.h pmglobalsettings.h pmskysphere.h pmrainbow.h \
+ pmfog.h pmbox.h pmsphere.h pmblob.h pmblobsphere.h \
+ pmblobcylinder.h pmtext.h pmjuliafractal.h \
+ pmcylinder.h pmcone.h pmtorus.h pmplane.h pmpolynom.h \
+ pmdisc.h pmbicubicpatch.h pmtriangle.h \
+ pmlathe.h pmprism.h pmsor.h pmsqe.h pmheightfield.h \
+ pmheightfieldroam.h pmcomment.h pmraw.h pmnamedobject.h \
+ pmtranslate.h pmscale.h pmrotate.h pmpovraymatrix.h \
+ pmcsg.h pmcamera.h pmboundedby.h pmclippedby.h \
+ pmlight.h pmlookslike.h pmprojectedthrough.h\
+ pmtexturebase.h pmtexture.h pmpigment.h \
+ pmsolidcolor.h pmlistpattern.h pmquickcolor.h pmmaterialmap.h \
+ pmpattern.h pmblendmapmodifiers.h pmtexturemap.h pmnormal.h \
+ pmslope.h pmfinish.h pmwarp.h pminterior.h pmmedia.h pmmaterial.h \
+ pmdensity.h pmimagemap.h pmbumpmap.h pmdeclare.h pmobjectlink.h \
+ pmrecursiveobjectiterator.h \
+ \
+ pmisosurface.h pmradiosity.h pmglobalphotons.h \
+ pmphotons.h pmlightgroup.h pminteriortexture.h \
+ pmspheresweep.h pmmesh.h pmdetailobject.h \
+ \
+ pmcommand.h pmaddcommand.h pmcommandmanager.h pmdatachangecommand.h \
+ pmallcommands.h pmdeletecommand.h pmmovecommand.h \
+ \
+ pmdialogview.h pmdialogeditbase.h pmgraphicalobjectedit.h \
+ pmnamedobjectedit.h pmsolidobjectedit.h pmskysphereedit.h \
+ pmglobalsettingsedit.h pmrainbowedit.h pmfogedit.h \
+ pmboxedit.h pmsphereedit.h pmblobedit.h pmblobsphereedit.h \
+ pmblobcylinderedit.h pmtextedit.h pmjuliafractaledit.h \
+ pmcylinderedit.h pmconeedit.h pmtorusedit.h pmplaneedit.h \
+ pmpolynomedit.h pmheightfieldedit.h \
+ pmdiscedit.h pmbicubicpatchedit.h pmtriangleedit.h \
+ pmlatheedit.h pmprismedit.h pmsoredit.h pmsqeedit.h \
+ pmcommentedit.h pmrawedit.h \
+ pmrotateedit.h pmscaleedit.h pmtranslateedit.h \
+ pmpovraymatrixedit.h \
+ pmcsgedit.h pmcameraedit.h pmlightedit.h pmboundedbyedit.h \
+ pmclippedbyedit.h \
+ pmlineedits.h pmvectorlistedit.h pmcoloredit.h pmlinkedit.h \
+ pmvectoredit.h pmpalettevalueedit.h pmformulalabel.h \
+ pmtexturebaseedit.h pmtextureedit.h pmpigmentedit.h \
+ pmsolidcoloredit.h pmlistpatternedit.h pmquickcoloredit.h \
+ pmpatternedit.h pmblendmapmodifiersedit.h pmimagemapedit.h \
+ pmtexturemapedit.h pmbumpmapedit.h pmmaterialmapedit.h \
+ pmnormaledit.h pmslopeedit.h pmfinishedit.h pmwarpedit.h \
+ pminterioredit.h pmmediaedit.h pmmaterialedit.h pmdensityedit.h \
+ pmdeclareedit.h pmobjectlinkedit.h \
+ \
+ pmisosurfaceedit.h pmradiosityedit.h pmglobalphotonsedit.h \
+ pmphotonsedit.h pmlightgroupedit.h pminteriortextureedit.h \
+ pmspheresweepedit.h pmmeshedit.h pmdetailobjectedit.h \
+ \
+ pmcontrolpoint.h pm3dcontrolpoint.h pm2dcontrolpoint.h \
+ pmsorcontrolpoint.h pmtranslatecontrolpoint.h \
+ pmrotatecontrolpoint.h pmscalecontrolpoint.h \
+ pmvectorcontrolpoint.h pmdistancecontrolpoint.h \
+ pmplanenormalcontrolpoint.h \
+ \
+ pmmemento.h pmmapmemento.h pmsplinememento.h pmprismmemento.h \
+ pmpalettevaluememento.h \
+ \
+ pmiomanager.h pmpovrayformat.h pmpovray31format.h pmpovray35format.h \
+ pmpovray31serialization.h pmpovray35serialization.h \
+ pmtokens.h pmscanner.h \
+ pmparser.h pmxmlparser.h pmpovrayparser.h \
+ pmserializer.h pmoutputdevice.h pmxmlhelper.h \
+ pmfiledialog.h \
+ \
+ pmerrorflags.h pmpalettevalue.h \
+ pmvector.h pmmath.h pmmatrix.h pmviewstructure.h pmline.h \
+ pmcolor.h pmpoint.h pmvalue.h pmsymboltable.h pmactions.h \
+ pmobjectaction.h pmsplinesegment.h pmsorsegment.h pmpolynomexponents.h \
+ pmface.h \
+ \
+ pmrendermode.h pmglobals.h pmdefaults.h pmresourcelocator.h \
+ pmtruetypecache.h pmdocumentationmap.h pminsertrulesystem.h \
+ pmlibrarymanager.h pmlibraryhandle.h pmlibraryhandleedit.h \
+ pmlibraryobject.h pmlibrarybrowser.h pmlibraryiconview.h \
+ pmlibraryentrypreview.h\
+ pmlibraryobjectsearch.h \
+ pmpluginmanager.h \
+ \
+ version.h pmdocumentformat.h pmdebug.h pmpartiface.h
+
+####
+# the part
+
+kde_module_LTLIBRARIES = libkpovmodelerpart.la
+
+libkpovmodelerpart_la_SOURCES = dummy.cpp
+libkpovmodelerpart_la_LIBADD = libkpovmodeler.la
+libkpovmodelerpart_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+
+####
+# the executable
+
+bin_PROGRAMS = kpovmodeler
+
+kpovmodeler_SOURCES = main.cpp
+kpovmodeler_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+kpovmodeler_LDADD = libkpovmodeler.la
+
+dummy.cpp:
+ echo > dummy.cpp
+
+rcdir = $(kde_datadir)/kpovmodeler
+rc_DATA = kpovmodelershell.rc kpovmodelerui.rc kpovmodelerbrowser.rc \
+ povraydocmap.xml baseinsertrules.xml questionmark.png
+
+
+EXTRA_DIST = kpovmodeler.desktop
+
+
+# make messages.po. Move this one to ../po/ and "make merge" in po
+# the -x is for skipping messages already translated in kdelibs
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kpovmodeler.pot
+
+KDE_ICON = kpovmodeler_doc kpovmodeler
+
+xdg_apps_DATA = kpovmodeler.desktop
diff --git a/kpovmodeler/README b/kpovmodeler/README
new file mode 100644
index 00000000..209fde03
--- /dev/null
+++ b/kpovmodeler/README
@@ -0,0 +1,3 @@
+KPovModeler: A graphical editor for povray scenes
+
+See http://www.kpovmodeler.org
diff --git a/kpovmodeler/REQUIREMENTS b/kpovmodeler/REQUIREMENTS
new file mode 100644
index 00000000..17987faa
--- /dev/null
+++ b/kpovmodeler/REQUIREMENTS
@@ -0,0 +1,19 @@
+Requirements for KPovModeler 1.0
+--------------------------------
+
+The program requires:
+
+- KDE-3.0 with header files
+
+- Qt-3.0.2 with header files
+
+- Freetype2 (Text view structures will be disabled otherwise)
+
+- OpenGL, glut, glu, glx libraries and header files
+
+- The Qt OpenGL extension is _NOT_ required any more!
+
+If you still have problems compiling the application,
+visit http://www.kpovmodeler.org/install.html
+or contact the KPovModeler developers
+http://www.kpovmodeler.org/contact.html
diff --git a/kpovmodeler/StyleConvention b/kpovmodeler/StyleConvention
new file mode 100644
index 00000000..eddc404f
--- /dev/null
+++ b/kpovmodeler/StyleConvention
@@ -0,0 +1,225 @@
+ Coding Style Convention
+ -------------------------
+
+This document describes the coding style convention
+used in KPovModeler.
+
+Author: Andreas Zehender <zehender@kde.org>
+Date: 16 June 2001
+
+If you edit existing files or create new ones, please follow this convention.
+This ensures that the code is consistent and clear.
+
+1) Indentation
+--------------
+
+- Use 3 spaces as basic offset. Do not use tabs for indentation.
+- Do not indent access keywords (public, protected, private) as
+ well as signal/slot keywords.
+- Do not indent braces.
+- Put braces in separate lines.
+- Indent case statements.
+
+Example:
+class abcd
+{
+public:
+ void someMethod( );
+};
+
+void abcd::someMethod( )
+{
+ if( 1 == 2 )
+ {
+ }
+ else
+ {
+ switch( x )
+ {
+ case 1:
+ y = 2;
+ break;
+ default:
+ y = -2;
+ }
+ }
+}
+
+
+2) Spacing
+----------
+
+Use many spaces.
+Use it
+- before and after brackets
+- before and after operators
+- after commas
+
+Examples:
+
+a = someMethod( ); // Notice the space between the brackets!
+b = anotherMethod( ( a + b ) / 2, 3 ) || 23456;
+if( ( a == 2 ) && !b )
+
+
+3) Type Modifiers (Pointers and References)
+-------------------------------------------
+
+Put type modifiers behind the type, not before the variable name.
+
+Example:
+
+const QString& type;
+PMObject* obj;
+
+
+4) Names
+--------
+
+Variables:
+----------
+Member variables begin with "m_".
+Static variables begin with "s_".
+Member pointers begin with "m_p".
+
+All variables begin with a lower case (member variables after the "m_").
+Use upper case character to separate different words.
+
+Examples:
+
+class abcd
+{
+ int m_firstMember;
+ char* m_pFirstMember;
+ static const char* s_pAStaticPointerToConstCharThatMeansItIsAString;
+};
+
+void abcd::efgh( )
+{
+ int aLocalVariable;
+}
+
+Classes:
+--------
+All classes start with "PM" and a upper case character.
+
+Methods:
+--------
+All methods start with a lower case character.
+
+Set methods begin with "set".
+Get methods do NOT begin with "get".
+
+Examples:
+
+int PMSPhere::centre( ) const;
+void PMSphere::setCentre( );
+
+5) KDoc Comments
+----------------
+
+Use KDoc comments to document classes.
+
+Don't add a description if you just overload a virtual function
+that doesn't add some functionality.
+
+Example:
+
+/** Returns the internal object name (not i18n'ed) */
+virtual PMObject::className( ) const;
+
+/** */
+virtual PMSphere::className( ) const;
+
+KDoc will then generate the following output:
+
+<documentation>
+PMObject* newObject ( )
+
+[const virtual]
+
+Reimplemented from PMObject.
+</documentation>
+
+
+6) Long Lines
+--------------
+Try to use only 80 characters per line.
+
+
+7) Sample .emacs File
+---------------------
+
+Here is a sample .emacs file. It is a mix of several files, so some
+things are set multiple times. But it works :-)
+
+<.emacs>
+(defconst my-c-style
+ '((c-tab-always-indent . t)
+ (c-comment-only-line-offset . 0)
+ (c-hanging-braces-alist . ((substatement-open after)
+ (brace-list-open)))
+ (c-hanging-colons-alist . ((member-init-intro before)
+ (inher-intro)
+ (case-label after)
+ (label after)
+ (access-label after)))
+ (c-cleanup-list . (scope-operator
+ empty-defun-braces
+ defun-close-semi))
+ (c-offsets-alist . ((arglist-close . c-lineup-arglist)
+ (substatement-open . 0)
+ (case-label . +)
+ (block-open . 0)
+ (knr-argdecl-intro . -)
+ (inline-open . 0)))
+ (c-echo-syntactic-information-p . t)
+ )
+ "My C Programming Style")
+
+;; Customizations for all of c-mode, c++-mode, and objc-mode
+(defun my-c-mode-common-hook ()
+ ;; add my personal style and set it for the current buffer
+ (c-add-style "PERSONAL" my-c-style t)
+ ;; offset customizations not in my-c-style
+ (c-set-offset 'member-init-intro '++)
+ ;; other customizations
+ (setq tab-width 8
+ ;; this will make sure spaces are used instead of tabs
+ indent-tabs-mode nil)
+ (setq c-basic-offset 3)
+ ;; we like auto-newline and hungry-delete
+ (c-toggle-hungry-state 1)
+ ;; keybindings for C, C++, and Objective-C. We can put these in
+ ;; c-mode-map because c++-mode-map and objc-mode-map inherit it
+ (define-key c-mode-map [f9] 'compile)
+ (define-key c-mode-map [return] 'newline-and-indent)
+ (define-key c++-mode-map [f9] 'compile)
+ (define-key c++-mode-map [return] 'newline-and-indent)
+ (define-key java-mode-map [f9] 'compile)
+ (define-key java-mode-map [return] 'newline-and-indent)
+ (load-library "vc")
+
+ ;;for QT
+ (setq c-C++-access-key "\\<\\(signals\\|public\\|protected\\|private
+ \\|public slots\\|protected slots\\|private slots\\)\\>[ \t]*:")
+ ;; modify the colour of slots to match public, private, etc ...
+ (font-lock-add-keywords 'c++-mode
+ '(("\\<\\(slots\\|signals\\)\\>" . font-lock-type-face)))
+ ;; make new font for rest of qt keywords
+ (make-face 'qt-keywords-face)
+ (set-face-foreground 'qt-keywords-face "green")
+ ;; qt keywords
+ (font-lock-add-keywords 'c++-mode
+ '(("\\<Q_OBJECT\\>" . 'qt-keywords-face)))
+ (font-lock-add-keywords 'c++-mode
+ '(("\\<SIGNAL\\|SLOT\\>" . 'qt-keywords-face)))
+ (font-lock-add-keywords 'c++-mode
+ '(("\\<Q[A-Z][A-Za-z]*" . 'qt-keywords-face)))
+ )
+
+(setq auto-mode-alist
+ (append '(("\\.h$" . c++-mode)) auto-mode-alist))
+
+</.emacs>
+
diff --git a/kpovmodeler/TODO b/kpovmodeler/TODO
new file mode 100644
index 00000000..565d19d1
--- /dev/null
+++ b/kpovmodeler/TODO
@@ -0,0 +1,52 @@
+TODO/Wishlist for kpovmodeler
+-----------------------------
+
+Tree View
+---------
+- Leave insert errors at their original position
+- Add an option to the configuration whether transformations and maybe
+ a simple pigment should be added to new graphical objects
+
+Object Properties View
+----------------------
+
+Graphical View
+--------------
+- Zoom to object short cut
+- Invert mouse wheel option
+- Remove GLUT dependency
+- Do hidden views use CPU time?
+- Heightfield wire frame
+
+Povray Render Window
+--------------------
+
+Includes
+--------
+- Finish the library
+ * Maintain the object index in PMLibraryHandle and library_index.html
+ * Eliminate crashes when modifying a library object
+ * Implement delete in the library object preview tree
+- Build an example objects library
+
+Povray Export
+-------------
+
+General
+-------
+- All not implemented objects
+- New POV-Ray 3.5 objects and textures
+- BREP modeling with the patch object (triangles and polygons, extrusion etc.)
+- Umlauts in the truetype text object
+- Scene templates
+- Add some basic render modes to a new scenes
+- Sync the recent files list between multiple windows
+- Multiplication of objects with simple transformations
+
+Long Term
+---------
+- Support for animations
+- Shaded views, csg results
+- The whole povray syntax (macros, includes, ...)
+- Support for povray variants (megapov, pvmpov)
+- Support for more renderers
diff --git a/kpovmodeler/baseinsertrules.xml b/kpovmodeler/baseinsertrules.xml
new file mode 100644
index 00000000..24aa7dd5
--- /dev/null
+++ b/kpovmodeler/baseinsertrules.xml
@@ -0,0 +1,1039 @@
+<!DOCTYPE insertrules SYSTEM "pminsertrules.dtd">
+<insertrules format="1.0">
+
+ <definegroup name="Transformations">
+ <class name="Translate"/>
+ <class name="Scale"/>
+ <class name="Rotate"/>
+ <class name="PovrayMatrix"/>
+ </definegroup>
+
+ <definegroup name="Textures">
+ <class name="Pigment"/>
+ <class name="Normal"/>
+ <class name="Finish"/>
+ <class name="Texture"/>
+ <class name="InteriorTexture"/>
+ <class name="Interior"/>
+ <class name="Material"/>
+ </definegroup>
+
+ <definegroup name="ObjectModifier">
+ <group name="Transformations"/>
+ <group name="Textures"/>
+ <class name="BoundedBy"/>
+ <class name="ClippedBy"/>
+ <class name="Photons"/>
+ </definegroup>
+
+ <targetclass name="Blob">
+ <definegroup name="ObjectModifier">
+ <group name="Transformations"/>
+ <group name="Textures"/>
+ </definegroup>
+ <definegroup name="BlobComponents">
+ <class name="BlobCylinder"/>
+ <class name="BlobSphere"/>
+ </definegroup>
+
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <group name="ObjectModifier"/>
+ <not><before><group name="BlobComponents"/></before></not>
+ </rule>
+ <rule>
+ <group name="BlobComponents"/>
+ <not><after><group name="ObjectModifier"/></after></not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="BlobCylinder">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ <group name="Transformations"/>
+ <class name="Texture"/>
+ <class name="InteriorTexture"/>
+ <class name="Pigment"/>
+ <class name="Normal"/>
+ <class name="Finish"/>
+ </rule>
+ </targetclass>
+ <targetclass name="BlobSphere">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ <group name="Transformations"/>
+ <class name="Texture"/>
+ <class name="InteriorTexture"/>
+ <class name="Pigment"/>
+ <class name="Normal"/>
+ <class name="Finish"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="BoundedBy">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ <class name="SolidObject"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Camera">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ <group name="Transformations"/>
+ <class name="Normal"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="ClippedBy">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ <class name="SolidObject"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="CSG">
+ <definegroup name="CSGObjects">
+ <class name="GraphicalObject"/>
+ <class name="Light"/>
+ </definegroup>
+
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <group name="ObjectModifier"/>
+ <not><before><group name="CSGObjects"/></before></not>
+ </rule>
+ <rule>
+ <group name="CSGObjects"/>
+ <not><after><group name="ObjectModifier"/></after></not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="LightGroup">
+ <definegroup name="LightGroupObjects">
+ <class name="GraphicalObject"/>
+ <class name="Light"/>
+ </definegroup>
+
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <group name="ObjectModifier"/>
+ <not><before><group name="LightGroupObjects"/></before></not>
+ </rule>
+ <rule>
+ <group name="LightGroupObjects"/>
+ <not><after><group name="ObjectModifier"/></after></not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Mesh">
+ <definegroup name="MeshObjects">
+ <class name="Triangle"/>
+ </definegroup>
+
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <group name="ObjectModifier"/>
+ <not><before><group name="MeshObjects"/></before></not>
+ </rule>
+ <rule>
+ <group name="MeshObjects"/>
+ <not><after><group name="ObjectModifier"/></after></not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Triangle">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <group name="ObjectModifier"/>
+ <not><parent><class name="Mesh"/></parent></not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Declare">
+ <rule>
+ <class name="GraphicalObject"/>
+ <class name="Light"/>
+ <class name="TextureBase"/>
+ <equal>
+ <property name="numberOfChildren"/>
+ <const value="0"/>
+ </equal>
+ </rule>
+ <rule>
+ <class name="Texture"/>
+ <contains><class name="Texture"/></contains>
+ </rule>
+ <rule>
+ <class name="InteriorTexture"/>
+ <contains><class name="InteriorTexture"/></contains>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Density">
+ <definegroup name="ListPattern">
+ <class name="ColorList"/>
+ <class name="DensityList"/>
+ </definegroup>
+ <definegroup name="Map">
+ <class name="ColorMap"/>
+ <class name="DensityMap"/>
+ </definegroup>
+ <definegroup name="Sum">
+ <class name="Pattern"/>
+ <group name="Map"/>
+ <class name="Warp"/>
+ <class name="SolidColor"/>
+ <group name="ListPattern"/>
+ </definegroup>
+
+ <rule>
+ <class name="SolidColor"/>
+ <class name="ColorList"/>
+ <class name="DensityList"/>
+ <not><contains><group name="Sum"/></contains></not>
+ </rule>
+ <rule>
+ <class name="Pattern"/>
+ <and>
+ <not>
+ <contains>
+ <class name="Pattern"/>
+ <group name="ListPattern"/>
+ </contains>
+ </not>
+ <not><after><group name="Map"/></after></not>
+ <not><after><class name="Warp"/></after></not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ <not><after><group name="Transformations"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="Warp"/>
+ <after><class name="Pattern"/></after>
+ </rule>
+ <rule>
+ <group name="Map"/>
+ <and>
+ <not>
+ <contains>
+ <group name="Map"/>
+ <group name="ListPattern"/>
+ <class name="SolidColor"/>
+ </contains>
+ </not>
+ <not><before><class name="Pattern"/></before></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="QuickColor"/>
+ <group name="Transformations"/>
+ <not><before><class name="Pattern"/></before></not>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Finish">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Fog">
+ <rule>
+ <group name="Transformations"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="GraphicalObject">
+ <exception class="CSG"/>
+ <exception class="Mesh"/>
+ <rule>
+ <group name="ObjectModifier"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Interior">
+ <rule>
+ <class name="Media"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Light">
+ <rule>
+ <group name="Transformations"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="LooksLike"/>
+ <not><contains><class name="LooksLike"/></contains></not>
+ </rule>
+ <rule>
+ <class name="ProjectedThrough"/>
+ <not><contains><class name="ProjectedThrough"/></contains></not>
+ </rule>
+ <rule>
+ <class name="Photons"/>
+ <not><contains><class name="Photons"/></contains></not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="ColorList">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="SolidColor"/>
+ <or>
+ <and>
+ <equal><property name="listType"/><const value="Hexagon"/></equal>
+ <less><count><class name="SolidColor"/></count><const value="3"/></less>
+ </and>
+ <and>
+ <not><equal><property name="listType"/><const value="Hexagon"/></equal></not>
+ <less><count><class name="SolidColor"/></count><const value="2"/></less>
+ </and>
+ </or>
+ </rule>
+ </targetclass>
+
+ <targetclass name="DensityList">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="Density"/>
+ <or>
+ <and>
+ <equal><property name="listType"/><const value="Hexagon"/></equal>
+ <less><count><class name="Density"/></count><const value="3"/></less>
+ </and>
+ <and>
+ <not><equal><property name="listType"/><const value="Hexagon"/></equal></not>
+ <less><count><class name="Density"/></count><const value="2"/></less>
+ </and>
+ </or>
+ </rule>
+ </targetclass>
+
+ <targetclass name="NormalList">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="Normal"/>
+ <and>
+ <equal><property name="depth"/><const value="0.0"/></equal>
+ <or>
+ <and>
+ <equal><property name="listType"/><const value="Hexagon"/></equal>
+ <less><count><class name="Normal"/></count><const value="3"/></less>
+ </and>
+ <and>
+ <not><equal><property name="listType"/><const value="Hexagon"/></equal></not>
+ <less><count><class name="Normal"/></count><const value="2"/></less>
+ </and>
+ </or>
+ </and>
+ </rule>
+ </targetclass>
+
+ <targetclass name="PigmentList">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="Pigment"/>
+ <or>
+ <and>
+ <equal><property name="listType"/><const value="Hexagon"/></equal>
+ <less><count><class name="Pigment"/></count><const value="3"/></less>
+ </and>
+ <and>
+ <not><equal><property name="listType"/><const value="Hexagon"/></equal></not>
+ <less><count><class name="Pigment"/></count><const value="2"/></less>
+ </and>
+ </or>
+ </rule>
+ </targetclass>
+
+ <targetclass name="TextureList">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="Texture"/>
+ <or>
+ <and>
+ <equal><property name="listType"/><const value="Hexagon"/></equal>
+ <less><count><class name="Texture"/></count><const value="3"/></less>
+ </and>
+ <and>
+ <not><equal><property name="listType"/><const value="Hexagon"/></equal></not>
+ <less><count><class name="Texture"/></count><const value="2"/></less>
+ </and>
+ </or>
+ </rule>
+ </targetclass>
+
+ <targetclass name="LooksLike">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="GraphicalObject"/>
+ <not>
+ <contains>
+ <class name="GraphicalObject"/>
+ </contains>
+ </not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="ProjectedThrough">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="GraphicalObject"/>
+ <not>
+ <contains>
+ <class name="GraphicalObject"/>
+ </contains>
+ </not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="ProjectedThrough">
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ <rule>
+ <class name="GraphicalObject"/>
+ <not>
+ <contains>
+ <class name="GraphicalObject"/>
+ </contains>
+ </not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Material">
+ <rule>
+ <group name="Textures"/>
+ <group name="Transformations"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="MaterialMap">
+ <rule>
+ <class name="Comment"/>
+ <class name="Texture"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Media">
+ <rule>
+ <class name="Density"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Normal">
+ <rule>
+ <class name="BumpMap"/>
+ <not>
+ <contains>
+ <class name="BumpMap"/>
+ <class name="NormalList"/>
+ <class name="Pattern"/>
+ <class name="NormalMap"/>
+ <class name="SlopeMap"/>
+ <class name="Warp"/>
+ <class name="BlendMapModifiers"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="NormalList"/>
+ <not>
+ <contains>
+ <class name="BumpMap"/>
+ <class name="NormalList"/>
+ <class name="Pattern"/>
+ <class name="NormalMap"/>
+ <class name="SlopeMap"/>
+ <class name="Warp"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Pattern"/>
+ <and>
+ <not>
+ <contains>
+ <class name="BumpMap"/>
+ <class name="NormalList"/>
+ <class name="Pattern"/>
+ </contains>
+ </not>
+ <not><after><class name="NormalMap"/></after></not>
+ <not><after><class name="SlopeMap"/></after></not>
+ <not><after><class name="Warp"/></after></not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ <not><after><group name="Transformations"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="Warp"/>
+ <after><class name="Pattern"/></after>
+ </rule>
+ <rule>
+ <class name="NormalMap"/>
+ <and>
+ <not>
+ <contains>
+ <class name="BumpMap"/>
+ <class name="NormalMap"/>
+ <class name="NormalList"/>
+ </contains>
+ </not>
+ <not><after><class name="SlopeMap"/></after></not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ <not><before><class name="Pattern"/></before></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="SlopeMap"/>
+ <and>
+ <not>
+ <contains>
+ <class name="BumpMap"/>
+ <class name="SlopeMap"/>
+ <class name="NormalList"/>
+ </contains>
+ </not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ <not><after><group name="Transformations"/></after></not>
+ <not><before><class name="Pattern"/></before></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="BlendMapModifiers"/>
+ <and>
+ <not><contains><class name="BlendMapModifiers"/></contains></not>
+ <or>
+ <not>
+ <contains>
+ <class name="BumpMap"/>
+ <class name="NormalMap"/>
+ <class name="SlopeMap"/>
+ </contains>
+ </not>
+ <after><class name="NormalMap"/></after>
+ <after><class name="SlopeMap"/></after>
+ </or>
+ <not><before><class name="Pattern"/></before></not>
+ <not><after><group name="Transformations"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <group name="Transformations"/>
+ <not><before><class name="Pattern"/></before></not>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Pigment">
+ <definegroup name="Color">
+ <class name="SolidColor"/>
+ <class name="ImageMap"/>
+ </definegroup>
+ <definegroup name="ListPattern">
+ <class name="ColorList"/>
+ <class name="PigmentList"/>
+ </definegroup>
+ <definegroup name="Map">
+ <class name="ColorMap"/>
+ <class name="PigmentMap"/>
+ </definegroup>
+ <definegroup name="Sum">
+ <class name="Pattern"/>
+ <group name="Map"/>
+ <class name="Warp"/>
+ <group name="Color"/>
+ <group name="ListPattern"/>
+ </definegroup>
+
+ <rule>
+ <group name="Color"/>
+ <group name="ListPattern"/>
+ <not><contains><group name="Sum"/></contains></not>
+ </rule>
+ <rule>
+ <class name="Pattern"/>
+ <and>
+ <not>
+ <contains>
+ <group name="Color"/>
+ <class name="Pattern"/>
+ <group name="ListPattern"/>
+ </contains>
+ </not>
+ <not><after><group name="Map"/></after></not>
+ <not><after><class name="Warp"/></after></not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ <not><after><group name="Transformations"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="Warp"/>
+ <after><class name="Pattern"/></after>
+ </rule>
+ <rule>
+ <group name="Map"/>
+ <and>
+ <not>
+ <contains>
+ <group name="Map"/>
+ <group name="ListPattern"/>
+ <group name="Color"/>
+ </contains>
+ </not>
+ <not><before><class name="Pattern"/></before></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="BlendMapModifiers"/>
+ <and>
+ <not>
+ <contains>
+ <class name="BlendMapModifiers"/>
+ <group name="Color"/>
+ </contains>
+ </not>
+ <not><before><group name="Map"/></before></not>
+ <not><before><class name="Pattern"/></before></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="QuickColor"/>
+ <group name="Transformations"/>
+ <not><before><class name="Pattern"/></before></not>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Rainbow">
+ <rule>
+ <class name="ColorMap"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Scene">
+ <rule>
+ <class name="GraphicalObject"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ <class name="Declare"/>
+ <class name="Camera"/>
+ <class name="Light"/>
+ <class name="SkySphere"/>
+ <class name="Rainbow"/>
+ <class name="Fog"/>
+ <class name="Media"/>
+ </rule>
+ <rule>
+ <class name="GlobalSettings"/>
+ <not><contains><class name="GlobalSettings"/></contains></not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="GlobalSettings">
+ <rule>
+ <class name="Radiosity"/>
+ <not><contains><class name="Radiosity"/></contains></not>
+ </rule>
+ <rule>
+ <class name="GlobalPhotons"/>
+ <not><contains><class name="GlobalPhotons"/></contains></not>
+ </rule>
+ </targetclass>
+
+ <targetclass name="SkySphere">
+ <rule>
+ <class name="Pigment"/>
+ <group name="Transformations"/>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="Texture">
+ <definegroup name="SumMap">
+ <class name="Pattern"/>
+ <class name="TextureMap"/>
+ <class name="Warp"/>
+ </definegroup>
+ <definegroup name="SumPigment">
+ <class name="Pigment"/>
+ <class name="Normal"/>
+ <class name="Finish"/>
+ </definegroup>
+
+ <rule>
+ <class name="MaterialMap"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <group name="SumPigment"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Pigment"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <class name="Pigment"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Normal"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <class name="Normal"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Finish"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <class name="Finish"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Pattern"/>
+ <and>
+ <not>
+ <contains>
+ <class name="Pattern"/>
+ <class name="TextureList"/>
+ <group name="SumPigment"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ <not><after><class name="TextureMap"/></after></not>
+ <not><after><class name="Warp"/></after></not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ <not><after><group name="Transformations"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="TextureMap"/>
+ <and>
+ <not>
+ <contains>
+ <class name="TextureMap"/>
+ <class name="TextureList"/>
+ <group name="SumPigment"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ <not><before><class name="Pattern"/></before></not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="TextureList"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <group name="SumPigment"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Warp"/>
+ <after><class name="Pattern"/></after>
+ </rule>
+ <rule>
+ <group name="Transformations"/>
+ <not><before><class name="Pattern"/></before></not>
+ </rule>
+ <rule>
+ <class name="BlendMapModifiers"/>
+ <and>
+ <not>
+ <contains>
+ <class name="MaterialMap"/>
+ <class name="BlendMapModifiers"/>
+ </contains>
+ </not>
+ <not><before><class name="TextureMap"/></before></not>
+ <not><before><class name="Pattern"/></before></not>
+ <not><after><group name="Transformations"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="InteriorTexture">
+ <definegroup name="SumMap">
+ <class name="Pattern"/>
+ <class name="TextureMap"/>
+ <class name="Warp"/>
+ </definegroup>
+ <definegroup name="SumPigment">
+ <class name="Pigment"/>
+ <class name="Normal"/>
+ <class name="Finish"/>
+ </definegroup>
+
+ <rule>
+ <class name="MaterialMap"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <group name="SumPigment"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Pigment"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <class name="Pigment"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Normal"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <class name="Normal"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Finish"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <class name="Finish"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Pattern"/>
+ <and>
+ <not>
+ <contains>
+ <class name="Pattern"/>
+ <class name="TextureList"/>
+ <group name="SumPigment"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ <not><after><class name="TextureMap"/></after></not>
+ <not><after><class name="Warp"/></after></not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ <not><after><group name="Transformations"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="TextureMap"/>
+ <and>
+ <not>
+ <contains>
+ <class name="TextureMap"/>
+ <class name="TextureList"/>
+ <group name="SumPigment"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ <not><before><class name="Pattern"/></before></not>
+ <not><after><class name="BlendMapModifiers"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="TextureList"/>
+ <not>
+ <contains>
+ <class name="TextureList"/>
+ <group name="SumMap"/>
+ <group name="SumPigment"/>
+ <class name="MaterialMap"/>
+ </contains>
+ </not>
+ </rule>
+ <rule>
+ <class name="Warp"/>
+ <after><class name="Pattern"/></after>
+ </rule>
+ <rule>
+ <group name="Transformations"/>
+ <not><before><class name="Pattern"/></before></not>
+ </rule>
+ <rule>
+ <class name="BlendMapModifiers"/>
+ <and>
+ <not>
+ <contains>
+ <class name="MaterialMap"/>
+ <class name="BlendMapModifiers"/>
+ </contains>
+ </not>
+ <not><before><class name="TextureMap"/></before></not>
+ <not><before><class name="Pattern"/></before></not>
+ <not><after><group name="Transformations"/></after></not>
+ </and>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="TextureMap">
+ <rule>
+ <class name="Texture"/>
+ <equal><property name="hasLinkedObject"/><const value="false"/></equal>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="PigmentMap">
+ <rule>
+ <class name="Pigment"/>
+ <equal><property name="hasLinkedObject"/><const value="false"/></equal>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="ColorMap">
+ <rule>
+ <class name="SolidColor"/>
+ <equal><property name="hasLinkedObject"/><const value="false"/></equal>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="NormalMap">
+ <rule>
+ <class name="Normal"/>
+ <equal><property name="hasLinkedObject"/><const value="false"/></equal>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="SlopeMap">
+ <rule>
+ <class name="Slope"/>
+ <equal><property name="hasLinkedObject"/><const value="false"/></equal>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+
+ <targetclass name="DensityMap">
+ <rule>
+ <class name="Density"/>
+ <equal><property name="hasLinkedObject"/><const value="false"/></equal>
+ </rule>
+ <rule>
+ <class name="Comment"/>
+ <class name="Raw"/>
+ </rule>
+ </targetclass>
+</insertrules>
diff --git a/kpovmodeler/configure.in.bot b/kpovmodeler/configure.in.bot
new file mode 100644
index 00000000..da816798
--- /dev/null
+++ b/kpovmodeler/configure.in.bot
@@ -0,0 +1,37 @@
+if test "$KPOVMODELER_OPENGL" = "no"; then
+ if test "$have_gl_headers" = "no"; then
+ echo ""
+ echo "You are missing"
+ if test "$ac_cv_header_GL_gl_h" = "no"; then
+ echo " - OpenGL (mesa)"
+ fi
+ if test "$ac_cv_header_GL_glu_h" = "no"; then
+ echo " - GLU"
+ fi
+ if test "$ac_cv_header_GL_glx_h" = "no"; then
+ echo " - GLX"
+ fi
+ echo "KPovModeler will not be compiled."
+ echo "You can download them from"
+ echo "http://mesa3d.sf.net"
+ echo ""
+ else
+ echo ""
+ echo "Your system fails at linking a small OpenGL application!"
+ echo "KPovModeler will not be compiled."
+ echo "Check, if OpenGL and GLU are installed correctly on your system."
+ echo "For more details about this problem, look at config.log after"
+ echo "the line \"checking for GL\"."
+ echo ""
+ fi
+ all_tests=bad
+fi
+
+if test -z "$LIBFREETYPE_LIBS"; then
+ echo ""
+ echo "You're missing freetype2. KPovModeler will not display true type texts."
+ echo "You can download it from"
+ echo "http://www.freetype.org"
+ echo ""
+ all_tests=bad
+fi
diff --git a/kpovmodeler/configure.in.in b/kpovmodeler/configure.in.in
new file mode 100644
index 00000000..34ae508f
--- /dev/null
+++ b/kpovmodeler/configure.in.in
@@ -0,0 +1,60 @@
+have_gl_headers=yes
+can_link_gl=yes
+KPOVMODELER_OPENGL=yes;
+
+KDE_CHECK_HEADERS(GL/gl.h GL/glu.h GL/glx.h)
+if test "$ac_cv_header_GL_gl_h" = "no"; then
+ have_gl_headers=no;
+fi
+if test "$ac_cv_header_GL_glu_h" = "no"; then
+ have_gl_headers=no;
+fi
+if test "$ac_cv_header_GL_glx_h" = "no"; then
+ have_gl_headers=no;
+fi
+
+if test "$have_gl_headers" = "yes"; then
+ AC_HAVE_GL( can_link_gl=yes, can_link_gl=no )
+fi
+
+if test "$have_gl_headers" = "no"; then
+ KPOVMODELER_OPENGL=no;
+fi
+if test "$can_link_gl" = "no"; then
+ KPOVMODELER_OPENGL=no;
+fi
+
+if test "$KPOVMODELER_OPENGL" = "no"; then
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kpovmodeler"
+fi
+
+
+KDE_FIND_PATH(freetype-config, FREETYPE_CONFIG, [${prefix}/bin ${exec_prefix}/bin /usr/local/bin /opt/local/bin])
+
+if test -n "$FREETYPE_CONFIG"; then
+ vers=`$FREETYPE_CONFIG --version 2>/dev/null | sed -e 's/libfreetype //' | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+ if test -n "$vers" && test "$vers" -ge 5000000
+ then
+ LIBFREETYPE_LIBS="`$FREETYPE_CONFIG --libs`"
+ LIBFREETYPE_RPATH=
+ for args in $LIBFREETYPE_LIBS; do
+ case $args in
+ -L*)
+ LIBFREETYPE_RPATH="$LIBFREETYPE_RPATH $args"
+ ;;
+ esac
+ done
+ LIBFREETYPE_RPATH=`echo $LIBFREETYPE_RPATH | sed -e "s/-L/-R/g"`
+ LIBFREETYPE_CFLAGS="`$FREETYPE_CONFIG --cflags`"
+
+ AC_DEFINE_UNQUOTED(HAVE_FREETYPE, 1, [Defines if your system has the libfreetype library])
+ AC_MSG_RESULT([libraries $LIBFREETYPE_LIBS, headers $LIBFREETYPE_CFLAGS])
+ else
+ AC_MSG_WARN([You need at least libfreetype 5.0])
+ fi
+fi
+
+
+AC_SUBST(LIBFREETYPE_LIBS)
+AC_SUBST(LIBFREETYPE_CFLAGS)
+AC_SUBST(LIBFREETYPE_RPATH)
diff --git a/kpovmodeler/cr16-mime-kpovmodeler_doc.png b/kpovmodeler/cr16-mime-kpovmodeler_doc.png
new file mode 100644
index 00000000..7ece4cce
--- /dev/null
+++ b/kpovmodeler/cr16-mime-kpovmodeler_doc.png
Binary files differ
diff --git a/kpovmodeler/cr32-mime-kpovmodeler_doc.png b/kpovmodeler/cr32-mime-kpovmodeler_doc.png
new file mode 100644
index 00000000..32f0d2a5
--- /dev/null
+++ b/kpovmodeler/cr32-mime-kpovmodeler_doc.png
Binary files differ
diff --git a/kpovmodeler/cr48-mime-kpovmodeler_doc.png b/kpovmodeler/cr48-mime-kpovmodeler_doc.png
new file mode 100644
index 00000000..ec8bf13e
--- /dev/null
+++ b/kpovmodeler/cr48-mime-kpovmodeler_doc.png
Binary files differ
diff --git a/kpovmodeler/examples/Makefile.am b/kpovmodeler/examples/Makefile.am
new file mode 100644
index 00000000..4ad27f9a
--- /dev/null
+++ b/kpovmodeler/examples/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = scenes includes \ No newline at end of file
diff --git a/kpovmodeler/examples/includes/Makefile.am b/kpovmodeler/examples/includes/Makefile.am
new file mode 100644
index 00000000..9d7b21f2
--- /dev/null
+++ b/kpovmodeler/examples/includes/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = inlined original \ No newline at end of file
diff --git a/kpovmodeler/examples/includes/inlined/Makefile.am b/kpovmodeler/examples/includes/inlined/Makefile.am
new file mode 100644
index 00000000..f798eb8b
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/Makefile.am
@@ -0,0 +1,4 @@
+exdir = $(kde_datadir)/kpovmodeler/examples/includes/inlined
+ex_DATA = chars.kpm finish.kpm glass.kpm golds.kpm metals.kpm shapes.kpm \
+ shapes2.kpm shapesq.kpm skies.kpm stars.kpm stones1.kpm stones2.kpm \
+ textures.kpm woods.kpm \ No newline at end of file
diff --git a/kpovmodeler/examples/includes/inlined/chars.kpm b/kpovmodeler/examples/includes/inlined/chars.kpm
new file mode 100644
index 00000000..606e7db0
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/chars.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/finish.kpm b/kpovmodeler/examples/includes/inlined/finish.kpm
new file mode 100644
index 00000000..d7131c4d
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/finish.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/glass.kpm b/kpovmodeler/examples/includes/inlined/glass.kpm
new file mode 100644
index 00000000..329b68e1
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/glass.kpm
@@ -0,0 +1,141 @@
+<!DOCTYPE KPOVMODELER>
+<scene minorFormat="0" majorFormat="1" visibility_level="10" >
+ <extra_data>
+ <rendermode sampling_method="0" width="640" subsection="0" antialiasing="0" end_column="640" start_row="1" radiosity="0" height="480" alpha="0" start_column="1" end_row="480" aa_depth="2" aa_jitter="0" aa_jitter_amount="1" aa_threshold="0.3" quality="9" description="Default" />
+ </extra_data>
+ <comment>
+Persistence of Vision Raytracer Version 3.1
+Glass finishes and textures
+</comment>
+ <comment>Changes in ver. 3.1 moved refraction and ior to the interior statment.
+Use I_Glass in conjunction with each of the finish statments below.</comment>
+ <comment>Glass Interior</comment>
+ <declare id="I_Glass" >
+ <interior enable_fade_power="0" fade_power="0" fade_distance="0" caustics="0" ior="1.5" enable_ior="1" enable_fade_distance="0" enable_caustics="0" name="" />
+ </declare>
+ <comment>Glass Finishes</comment>
+ <declare id="F_Glass1" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0 0 0 0 0" reflection="0.1 0.1 0.1 0.1 0.1" diffuse="0" name="" specular="1" phongsize="40" enable_crand="0" />
+ </declare>
+ <declare id="F_Glass2" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="0" enable_specular="0" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.05" enable_phong_size="1" enable_phong="1" irid_thickness="0" phong="0.3" ambient="0 0 0 0 0" reflection="0.5 0.5 0.5 0.5 0.5" diffuse="0" name="" specular="0" phongsize="60" enable_crand="0" />
+ </declare>
+ <declare id="F_Glass3" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.003" enable_phong_size="1" enable_phong="1" irid_thickness="0" phong="1" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.1 0.1 0.1 0.1 0.1" diffuse="0.1" name="" specular="0.8" phongsize="400" enable_crand="0" />
+ </declare>
+ <declare id="F_Glass4" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ </declare>
+ <comment>Glass Textures</comment>
+ <comment>Simple clear glass</comment>
+ <declare id="T_Glass1" >
+ <texture name="" >
+ <pigment name="" >
+ <solidcolor color="1 1 1 0.7 0" />
+ </pigment>
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0 0 0 0 0" reflection="0.1 0.1 0.1 0.1 0.1" diffuse="0" name="" specular="1" phongsize="40" enable_crand="0" />
+ </texture>
+ </declare>
+ <comment>More like an acrylic plastic</comment>
+ <declare id="T_Glass2" >
+ <texture name="" >
+ <pigment name="" >
+ <solidcolor color="1 1 1 1 0" />
+ </pigment>
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="0" enable_specular="0" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.05" enable_phong_size="1" enable_phong="1" irid_thickness="0" phong="0.3" ambient="0 0 0 0 0" reflection="0.5 0.5 0.5 0.5 0.5" diffuse="0" name="" specular="0" phongsize="60" enable_crand="0" />
+ </texture>
+ </declare>
+ <comment>An excellent lead crystal glass!</comment>
+ <declare id="T_Glass3" >
+ <texture name="" >
+ <pigment name="" >
+ <solidcolor color="0.98 0.98 0.98 0.9 0" />
+ </pigment>
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.003" enable_phong_size="1" enable_phong="1" irid_thickness="0" phong="1" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.1 0.1 0.1 0.1 0.1" diffuse="0.1" name="" specular="0.8" phongsize="400" enable_crand="0" />
+ </texture>
+ </declare>
+ <declare id="T_Glass4" >
+ <texture name="" >
+ <pigment name="" >
+ <solidcolor color="0.98 1 0.99 0.75 0" />
+ </pigment>
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ </texture>
+ </declare>
+ <declare id="T_Old_Glass" >
+ <texture name="" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ <pigment name="" >
+ <solidcolor color="0.8 0.9 0.85 0.85 0" />
+ </pigment>
+ </texture>
+ </declare>
+ <declare id="T_Winebottle_Glass" >
+ <texture name="" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ <pigment name="" >
+ <solidcolor color="0.4 0.72 0.4 0.6 0" />
+ </pigment>
+ </texture>
+ </declare>
+ <declare id="T_Beerbottle_Glass" >
+ <texture name="" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ <pigment name="" >
+ <solidcolor color="0.7 0.5 0.1 0.6 0" />
+ </pigment>
+ </texture>
+ </declare>
+ <comment>A few color variations on Norm's glass
+Ruby glass</comment>
+ <declare id="T_Ruby_Glass" >
+ <texture name="" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ <pigment name="" >
+ <solidcolor color="0.9 0.1 0.2 0.8 0" />
+ </pigment>
+ </texture>
+ </declare>
+ <declare id="T_Green_Glass" >
+ <texture name="" >
+ <pigment name="" >
+ <solidcolor color="0.8 1 0.95 0.9 0" />
+ </pigment>
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.003" enable_phong_size="1" enable_phong="1" irid_thickness="0" phong="1" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.1 0.1 0.1 0.1 0.1" diffuse="0.1" name="" specular="0.8" phongsize="400" enable_crand="0" />
+ </texture>
+ </declare>
+ <declare id="T_Dark_Green_Glass" >
+ <texture name="" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ <pigment name="" >
+ <solidcolor color="0.1 0.7 0.8 0.8 0" />
+ </pigment>
+ </texture>
+ </declare>
+ <declare id="T_Yellow_Glass" >
+ <texture name="" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ <pigment name="" >
+ <solidcolor color="0.8 0.8 0.2 0.8 0" />
+ </pigment>
+ </texture>
+ </declare>
+ <comment>Orange/Amber glass</comment>
+ <declare id="T_Orange_Glass" >
+ <texture name="" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ <pigment name="" >
+ <solidcolor color="1 0.5 0 0.8 0" />
+ </pigment>
+ </texture>
+ </declare>
+ <comment>Vicks bottle, glass</comment>
+ <declare id="T_Vicksbottle_Glass" >
+ <texture name="" >
+ <finish enable_brilliance="0" enable_metallic="0" enable_exponent="0" enable_diffuse="1" metallic="1" enable_reflection="1" irid_turbulence="0" irid="0" crand="0" brilliance="1" enable_roughness="1" enable_specular="1" enable_ambient="1" irid_amount="0" reflection_exponent="1" roughness="0.001" enable_phong_size="0" enable_phong="0" irid_thickness="0" phong="0" ambient="0.1 0.1 0.1 0.1 0.1" reflection="0.25 0.25 0.25 0.25 0.25" diffuse="0.1" name="" specular="1" phongsize="40" enable_crand="0" />
+ <pigment name="" >
+ <solidcolor color="0.1 0.15 0.5 0.9 0" />
+ </pigment>
+ </texture>
+ </declare>
+</scene>
diff --git a/kpovmodeler/examples/includes/inlined/golds.kpm b/kpovmodeler/examples/includes/inlined/golds.kpm
new file mode 100644
index 00000000..91feeca0
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/golds.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/metals.kpm b/kpovmodeler/examples/includes/inlined/metals.kpm
new file mode 100644
index 00000000..80f7f432
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/metals.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/shapes.kpm b/kpovmodeler/examples/includes/inlined/shapes.kpm
new file mode 100644
index 00000000..0390613d
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/shapes.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/shapes2.kpm b/kpovmodeler/examples/includes/inlined/shapes2.kpm
new file mode 100644
index 00000000..72421aef
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/shapes2.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/shapesq.kpm b/kpovmodeler/examples/includes/inlined/shapesq.kpm
new file mode 100644
index 00000000..3aa691b6
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/shapesq.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/skies.kpm b/kpovmodeler/examples/includes/inlined/skies.kpm
new file mode 100644
index 00000000..9c4ff952
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/skies.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/stars.kpm b/kpovmodeler/examples/includes/inlined/stars.kpm
new file mode 100644
index 00000000..9ec844a6
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/stars.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/stones1.kpm b/kpovmodeler/examples/includes/inlined/stones1.kpm
new file mode 100644
index 00000000..67ddadfe
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/stones1.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/stones2.kpm b/kpovmodeler/examples/includes/inlined/stones2.kpm
new file mode 100644
index 00000000..955052e5
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/stones2.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/textures.kpm b/kpovmodeler/examples/includes/inlined/textures.kpm
new file mode 100644
index 00000000..4f5d3dc9
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/textures.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/inlined/woods.kpm b/kpovmodeler/examples/includes/inlined/woods.kpm
new file mode 100644
index 00000000..f5b12879
--- /dev/null
+++ b/kpovmodeler/examples/includes/inlined/woods.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/Makefile.am b/kpovmodeler/examples/includes/original/Makefile.am
new file mode 100644
index 00000000..544ecd09
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/Makefile.am
@@ -0,0 +1,4 @@
+exdir = $(kde_datadir)/kpovmodeler/examples/includes/original
+ex_DATA = chars.kpm finish.kpm glass.kpm golds.kpm metals.kpm shapes.kpm \
+ shapes2.kpm shapesq.kpm skies.kpm stars.kpm stones1.kpm stones2.kpm \
+ textures.kpm woods.kpm \ No newline at end of file
diff --git a/kpovmodeler/examples/includes/original/chars.kpm b/kpovmodeler/examples/includes/original/chars.kpm
new file mode 100644
index 00000000..1f16af27
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/chars.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/finish.kpm b/kpovmodeler/examples/includes/original/finish.kpm
new file mode 100644
index 00000000..57964af6
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/finish.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/glass.kpm b/kpovmodeler/examples/includes/original/glass.kpm
new file mode 100644
index 00000000..9750c57a
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/glass.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/golds.kpm b/kpovmodeler/examples/includes/original/golds.kpm
new file mode 100644
index 00000000..d11b632b
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/golds.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/metals.kpm b/kpovmodeler/examples/includes/original/metals.kpm
new file mode 100644
index 00000000..c5634789
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/metals.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/shapes.kpm b/kpovmodeler/examples/includes/original/shapes.kpm
new file mode 100644
index 00000000..e587d44b
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/shapes.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/shapes2.kpm b/kpovmodeler/examples/includes/original/shapes2.kpm
new file mode 100644
index 00000000..206f375a
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/shapes2.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/shapesq.kpm b/kpovmodeler/examples/includes/original/shapesq.kpm
new file mode 100644
index 00000000..416d190e
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/shapesq.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/skies.kpm b/kpovmodeler/examples/includes/original/skies.kpm
new file mode 100644
index 00000000..e5c65c04
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/skies.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/stars.kpm b/kpovmodeler/examples/includes/original/stars.kpm
new file mode 100644
index 00000000..b17cb306
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/stars.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/stones1.kpm b/kpovmodeler/examples/includes/original/stones1.kpm
new file mode 100644
index 00000000..0753b49e
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/stones1.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/stones2.kpm b/kpovmodeler/examples/includes/original/stones2.kpm
new file mode 100644
index 00000000..16438514
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/stones2.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/textures.kpm b/kpovmodeler/examples/includes/original/textures.kpm
new file mode 100644
index 00000000..ae6cca1f
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/textures.kpm
Binary files differ
diff --git a/kpovmodeler/examples/includes/original/woods.kpm b/kpovmodeler/examples/includes/original/woods.kpm
new file mode 100644
index 00000000..4cdca2ec
--- /dev/null
+++ b/kpovmodeler/examples/includes/original/woods.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/Makefile.am b/kpovmodeler/examples/scenes/Makefile.am
new file mode 100644
index 00000000..090e2230
--- /dev/null
+++ b/kpovmodeler/examples/scenes/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = advanced csg interior lights objects \ No newline at end of file
diff --git a/kpovmodeler/examples/scenes/advanced/Makefile.am b/kpovmodeler/examples/scenes/advanced/Makefile.am
new file mode 100644
index 00000000..42f8c53c
--- /dev/null
+++ b/kpovmodeler/examples/scenes/advanced/Makefile.am
@@ -0,0 +1,2 @@
+exdir = $(kde_datadir)/kpovmodeler/examples/scenes/advanced
+ex_DATA = ants.kpm bee.kpm ink.kpm table.kpm \ No newline at end of file
diff --git a/kpovmodeler/examples/scenes/advanced/ants.kpm b/kpovmodeler/examples/scenes/advanced/ants.kpm
new file mode 100644
index 00000000..c84bd68d
--- /dev/null
+++ b/kpovmodeler/examples/scenes/advanced/ants.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/advanced/bee.kpm b/kpovmodeler/examples/scenes/advanced/bee.kpm
new file mode 100644
index 00000000..9f594df3
--- /dev/null
+++ b/kpovmodeler/examples/scenes/advanced/bee.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/advanced/ink.kpm b/kpovmodeler/examples/scenes/advanced/ink.kpm
new file mode 100644
index 00000000..036ef168
--- /dev/null
+++ b/kpovmodeler/examples/scenes/advanced/ink.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/advanced/table.kpm b/kpovmodeler/examples/scenes/advanced/table.kpm
new file mode 100644
index 00000000..1fdddccd
--- /dev/null
+++ b/kpovmodeler/examples/scenes/advanced/table.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/csg/Makefile.am b/kpovmodeler/examples/scenes/csg/Makefile.am
new file mode 100644
index 00000000..c63d4ae8
--- /dev/null
+++ b/kpovmodeler/examples/scenes/csg/Makefile.am
@@ -0,0 +1,2 @@
+exdir = $(kde_datadir)/kpovmodeler/examples/scenes/csg
+ex_DATA = cheese.kpm emptybox.kpm heightfield.kpm \ No newline at end of file
diff --git a/kpovmodeler/examples/scenes/csg/cheese.kpm b/kpovmodeler/examples/scenes/csg/cheese.kpm
new file mode 100644
index 00000000..215ec50d
--- /dev/null
+++ b/kpovmodeler/examples/scenes/csg/cheese.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/csg/emptybox.kpm b/kpovmodeler/examples/scenes/csg/emptybox.kpm
new file mode 100644
index 00000000..e917ba21
--- /dev/null
+++ b/kpovmodeler/examples/scenes/csg/emptybox.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/csg/heightfield.kpm b/kpovmodeler/examples/scenes/csg/heightfield.kpm
new file mode 100644
index 00000000..051b25ea
--- /dev/null
+++ b/kpovmodeler/examples/scenes/csg/heightfield.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/interior/Makefile.am b/kpovmodeler/examples/scenes/interior/Makefile.am
new file mode 100644
index 00000000..7d8e4e22
--- /dev/null
+++ b/kpovmodeler/examples/scenes/interior/Makefile.am
@@ -0,0 +1,2 @@
+exdir = $(kde_datadir)/kpovmodeler/examples/scenes/interior
+ex_DATA = cubes.kpm media1.kpm media2.kpm media3.kpm spheres.kpm \ No newline at end of file
diff --git a/kpovmodeler/examples/scenes/interior/cubes.kpm b/kpovmodeler/examples/scenes/interior/cubes.kpm
new file mode 100644
index 00000000..30f516c9
--- /dev/null
+++ b/kpovmodeler/examples/scenes/interior/cubes.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/interior/media1.kpm b/kpovmodeler/examples/scenes/interior/media1.kpm
new file mode 100644
index 00000000..94938e69
--- /dev/null
+++ b/kpovmodeler/examples/scenes/interior/media1.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/interior/media2.kpm b/kpovmodeler/examples/scenes/interior/media2.kpm
new file mode 100644
index 00000000..bae2c746
--- /dev/null
+++ b/kpovmodeler/examples/scenes/interior/media2.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/interior/media3.kpm b/kpovmodeler/examples/scenes/interior/media3.kpm
new file mode 100644
index 00000000..b9215dfa
--- /dev/null
+++ b/kpovmodeler/examples/scenes/interior/media3.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/interior/spheres.kpm b/kpovmodeler/examples/scenes/interior/spheres.kpm
new file mode 100644
index 00000000..059bee3b
--- /dev/null
+++ b/kpovmodeler/examples/scenes/interior/spheres.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/lights/Makefile.am b/kpovmodeler/examples/scenes/lights/Makefile.am
new file mode 100644
index 00000000..9b1f5ad5
--- /dev/null
+++ b/kpovmodeler/examples/scenes/lights/Makefile.am
@@ -0,0 +1,2 @@
+exdir = $(kde_datadir)/kpovmodeler/examples/scenes/lights
+ex_DATA = arealight.kpm arealight2.kpm spotlight.kpm \ No newline at end of file
diff --git a/kpovmodeler/examples/scenes/lights/arealight.kpm b/kpovmodeler/examples/scenes/lights/arealight.kpm
new file mode 100644
index 00000000..d02a893d
--- /dev/null
+++ b/kpovmodeler/examples/scenes/lights/arealight.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/lights/arealight2.kpm b/kpovmodeler/examples/scenes/lights/arealight2.kpm
new file mode 100644
index 00000000..21d2e772
--- /dev/null
+++ b/kpovmodeler/examples/scenes/lights/arealight2.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/lights/spotlight.kpm b/kpovmodeler/examples/scenes/lights/spotlight.kpm
new file mode 100644
index 00000000..925fb7c3
--- /dev/null
+++ b/kpovmodeler/examples/scenes/lights/spotlight.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/objects/Makefile.am b/kpovmodeler/examples/scenes/objects/Makefile.am
new file mode 100644
index 00000000..bfa14dce
--- /dev/null
+++ b/kpovmodeler/examples/scenes/objects/Makefile.am
@@ -0,0 +1,3 @@
+exdir = $(kde_datadir)/kpovmodeler/examples/scenes/objects
+ex_DATA = allobjects.kpm fractals.kpm lathe.kpm prism.kpm sor.kpm \
+ superellipsoid.kpm text.kpm \ No newline at end of file
diff --git a/kpovmodeler/examples/scenes/objects/allobjects.kpm b/kpovmodeler/examples/scenes/objects/allobjects.kpm
new file mode 100644
index 00000000..10136a71
--- /dev/null
+++ b/kpovmodeler/examples/scenes/objects/allobjects.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/objects/fractals.kpm b/kpovmodeler/examples/scenes/objects/fractals.kpm
new file mode 100644
index 00000000..a0e83171
--- /dev/null
+++ b/kpovmodeler/examples/scenes/objects/fractals.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/objects/lathe.kpm b/kpovmodeler/examples/scenes/objects/lathe.kpm
new file mode 100644
index 00000000..64e8691a
--- /dev/null
+++ b/kpovmodeler/examples/scenes/objects/lathe.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/objects/prism.kpm b/kpovmodeler/examples/scenes/objects/prism.kpm
new file mode 100644
index 00000000..c6b5cd19
--- /dev/null
+++ b/kpovmodeler/examples/scenes/objects/prism.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/objects/sor.kpm b/kpovmodeler/examples/scenes/objects/sor.kpm
new file mode 100644
index 00000000..cddea81e
--- /dev/null
+++ b/kpovmodeler/examples/scenes/objects/sor.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/objects/superellipsoid.kpm b/kpovmodeler/examples/scenes/objects/superellipsoid.kpm
new file mode 100644
index 00000000..35810e6e
--- /dev/null
+++ b/kpovmodeler/examples/scenes/objects/superellipsoid.kpm
Binary files differ
diff --git a/kpovmodeler/examples/scenes/objects/text.kpm b/kpovmodeler/examples/scenes/objects/text.kpm
new file mode 100644
index 00000000..f7c84beb
--- /dev/null
+++ b/kpovmodeler/examples/scenes/objects/text.kpm
Binary files differ
diff --git a/kpovmodeler/hi16-app-kpovmodeler.png b/kpovmodeler/hi16-app-kpovmodeler.png
new file mode 100644
index 00000000..a6f1b945
--- /dev/null
+++ b/kpovmodeler/hi16-app-kpovmodeler.png
Binary files differ
diff --git a/kpovmodeler/hi22-app-kpovmodeler.png b/kpovmodeler/hi22-app-kpovmodeler.png
new file mode 100644
index 00000000..218417bd
--- /dev/null
+++ b/kpovmodeler/hi22-app-kpovmodeler.png
Binary files differ
diff --git a/kpovmodeler/hi32-app-kpovmodeler.png b/kpovmodeler/hi32-app-kpovmodeler.png
new file mode 100644
index 00000000..07ffa8bb
--- /dev/null
+++ b/kpovmodeler/hi32-app-kpovmodeler.png
Binary files differ
diff --git a/kpovmodeler/hi48-app-kpovmodeler.png b/kpovmodeler/hi48-app-kpovmodeler.png
new file mode 100644
index 00000000..904a39cf
--- /dev/null
+++ b/kpovmodeler/hi48-app-kpovmodeler.png
Binary files differ
diff --git a/kpovmodeler/kdoc.rules b/kpovmodeler/kdoc.rules
new file mode 100644
index 00000000..6b5d40a6
--- /dev/null
+++ b/kpovmodeler/kdoc.rules
@@ -0,0 +1,10 @@
+# These are the rules used by makekdedoc to generate the kpovmodeler
+# documentation with KDOC.
+#
+# $Id$
+
+kde_MODULES = kpovmodeler
+
+kpovmodeler_FILES = *.h
+kpovmodeler_LIBS = -lkdeui -lkparts -lkdecore -ldcop -lkfile -lkio -lqt -p
+kpovmodeler_PATH = . \ No newline at end of file
diff --git a/kpovmodeler/kpovmodeler.desktop b/kpovmodeler/kpovmodeler.desktop
new file mode 100644
index 00000000..49e0844c
--- /dev/null
+++ b/kpovmodeler/kpovmodeler.desktop
@@ -0,0 +1,59 @@
+[Desktop Entry]
+DocPath=kpovmodeler/index.html
+Exec=kpovmodeler -caption "%c" %i %m %f
+Icon=kpovmodeler
+MimeType=application/x-kpovmodeler;
+Name=KPovModeler
+Name[eo]=KPovModelilo
+Name[es]=Modelador Povray
+Name[he]=מעצב Povray
+Name[nb]=KPov-modellerer
+Name[ne]=केडीई पोभ मोडेलर
+Name[nn]=KPov-modellering
+Name[sv]=Kpovmodeler
+GenericName=Povray Modeler
+GenericName[ca]=Modelador Povray
+GenericName[cs]=Modelář Povray
+GenericName[cy]=Modelydd Povray
+GenericName[da]=Povray-modellering
+GenericName[de]=Povray-Modellierer
+GenericName[en_GB]=Povray Modeller
+GenericName[eo]=Povray-modelilo
+GenericName[es]=Modelador Povray
+GenericName[et]=Povray modelleerija
+GenericName[eu]=Povray modelatzailea
+GenericName[fa]=سازندۀ مدل Povray
+GenericName[fi]=Povray-mallintaja
+GenericName[fr]=Modeleur Povray
+GenericName[gl]=Modelador Povray
+GenericName[he]=מעצב Povray
+GenericName[hu]=Povray-modellező
+GenericName[is]=Povray hönnuður
+GenericName[it]=Modellatore per Povray
+GenericName[ja]=Povray モデラー
+GenericName[kk]=Povray үлгілеу
+GenericName[km]=កម្មវិធី​ធ្វើ​ម៉ូដែល Povray
+GenericName[ms]=Pemodel Povray
+GenericName[nb]=Povray-modellerer
+GenericName[nds]=Povray-Modellmaker
+GenericName[ne]=पोभ्रे मोडेलर
+GenericName[nn]=Povray-modellering
+GenericName[pl]=Modeler Povray
+GenericName[pt]=Modelador de Povray
+GenericName[pt_BR]=Modelador Povray
+GenericName[ro]=Modelator Povray
+GenericName[ru]=Редактор Povray
+GenericName[sl]=Modelirnik Povray
+GenericName[sr]=Моделар за Povray
+GenericName[sr@Latn]=Modelar za Povray
+GenericName[sv]=Modellering med Povray
+GenericName[ta]=பாவ்ரே மாடுல்லர்
+GenericName[tr]=Povray Modelleyici
+GenericName[zh_CN]=Povray 建模器
+GenericName[zh_HK]=Povray 建模器
+Path=
+ServiceTypes=KParts/ReadOnlyPart,KParts/ReadWritePart,Browser/View,KPovModeler/Document
+Terminal=false
+Type=Application
+X-KDE-Library=libkpovmodelerpart
+Categories=Qt;KDE;Graphics;
diff --git a/kpovmodeler/kpovmodelerbrowser.rc b/kpovmodeler/kpovmodelerbrowser.rc
new file mode 100644
index 00000000..9640121f
--- /dev/null
+++ b/kpovmodeler/kpovmodelerbrowser.rc
@@ -0,0 +1,21 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="KPovModelerPart" version="1">
+<MenuBar>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_delete"/>
+ </Menu>
+</MenuBar>
+
+<ToolBar name="mainToolBar">
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_delete"/>
+</ToolBar>
+</kpartgui>
diff --git a/kpovmodeler/kpovmodelershell.rc b/kpovmodeler/kpovmodelershell.rc
new file mode 100644
index 00000000..cea9e017
--- /dev/null
+++ b/kpovmodeler/kpovmodelershell.rc
@@ -0,0 +1,58 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="KPovModelerShell" version="7">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <DefineGroup name="file_export_actions" append="save_merge"/>
+ <DefineGroup name="file_import_actions" append="open_merge"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="insert"><text>&amp;Insert</text>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="view_new_treeview"/>
+ <Action name="view_new_dialogview"/>
+ <Action name="view_new_librarybrowser"/>
+ <DefineGroup name="view_new_views_merge"/>
+ <Separator/>
+ <Action name="view_new_topview"/>
+ <Action name="view_new_bottomview"/>
+ <Action name="view_new_leftview"/>
+ <Action name="view_new_rightview"/>
+ <Action name="view_new_frontview"/>
+ <Action name="view_new_backview"/>
+ <Action name="view_new_cameraview"/>
+ <Separator/>
+ <Action name="view_layouts_menu"/>
+ <Action name="save_view_layout"/>
+ <Separator/>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Action name="options_show_path" append="show_merge"/>
+ </Menu>
+ <Merge/>
+</MenuBar>
+
+<ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text>
+ <Action name="file_new"/>
+ <Action name="file_open"/>
+ <Action name="file_save"/>
+ <Action name="file_print"/>
+ <Action name="file_print_preview"/>
+ <Action name="file_mail"/>
+ <Separator/>
+ <Merge/>
+</ToolBar>
+
+<ToolBar name="libraryToolbar" noMerge="1"><text>Library Toolbar</text>
+ <Action name="library_up"/>
+ <Action name="library_object_new"/>
+ <Action name="library_object_edit"/>
+ <Action name="library_object_delete"/>
+</ToolBar>
+
+</kpartgui>
+
diff --git a/kpovmodeler/kpovmodelerui.rc b/kpovmodeler/kpovmodelerui.rc
new file mode 100644
index 00000000..007257b6
--- /dev/null
+++ b/kpovmodeler/kpovmodelerui.rc
@@ -0,0 +1,303 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="KPovModelerPart" version="14">
+
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="file_export" group="file_export_actions"/>
+ <Action name="file_import" group="file_import_actions"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_delete"/>
+ </Menu>
+ <Menu name="insert"><text context="Insert menu">&amp;Insert</text>
+ <Action name="new_globalsettings"/>
+ <Action name="new_radiosity"/>
+ <Action name="new_globalphotons"/>
+ <Separator/>
+ <Action name="new_declare"/>
+ <Separator/>
+ <Action name="new_clippedby"/>
+ <Action name="new_boundedby"/>
+ <Separator/>
+ <Action name="new_light"/>
+ <Action name="new_lightgroup"/>
+ <Action name="new_lookslike"/>
+ <Action name="new_projectedthrough"/>
+ <Action name="new_camera"/>
+ <Separator/>
+ <Action name="new_comment"/>
+ <Action name="new_raw"/>
+ <Separator/>
+ <Menu name="finite_solid_objects"><text>Finite Solid Primitives</text>
+ <Action name="new_box"/>
+ <Action name="new_sphere"/>
+ <Action name="new_cylinder"/>
+ <Action name="new_cone"/>
+ <Action name="new_torus"/>
+ <Action name="new_superquadricellipsoid"/>
+ <Action name="new_heightfield"/>
+ <Action name="new_text"/>
+ <Action name="new_juliafractal"/>
+ <Action name="new_isosurface"/>
+ <Separator/>
+ <Action name="new_blob"/>
+ <Action name="new_blobsphere"/>
+ <Action name="new_blobcylinder"/>
+ <Separator/>
+ <Action name="new_lathe"/>
+ <Action name="new_prism"/>
+ <Action name="new_surfaceofrevolution"/>
+ <Action name="new_spheresweep"/>
+ <Separator/>
+ <Action name="new_objectlink"/>
+ </Menu>
+ <Menu name="finite_patch_objects"><text>Finite Patch Primitives</text>
+ <Action name="new_disc"/>
+ <Action name="new_bicubicpatch"/>
+ <Action name="new_triangle"/>
+ <Action name="new_mesh"/>
+ </Menu>
+ <Menu name="infinite_solid_objects"><text>Infinite Solid Primitives</text>
+ <Action name="new_plane"/>
+ <Action name="new_polynom"/>
+ </Menu>
+ <Menu name="csg_objects"><text>Constructive Solid Geometry</text>
+ <Action name="new_union"/>
+ <Action name="new_intersection"/>
+ <Action name="new_difference"/>
+ <Action name="new_merge"/>
+ </Menu>
+ <Separator/>
+ <Menu name="material_objects"><text>Material</text>
+ <Action name="new_material"/>
+ </Menu>
+ <Menu name="interior_objects"><text>Interior</text>
+ <Action name="new_interior"/>
+ <Action name="new_media"/>
+ <Action name="new_density"/>
+ <Action name="new_densitylist"/>
+ <Action name="new_densitymap"/>
+ </Menu>
+ <Menu name="texture_objects"><text>Textures</text>
+ <Action name="new_pattern"/>
+ <Action name="new_blendmapmodifiers"/>
+ <Action name="new_warp"/>
+ <Separator/>
+ <Action name="new_texture"/>
+ <Action name="new_interiortexture"/>
+ <Action name="new_texturelist"/>
+ <Action name="new_texturemap"/>
+ <Action name="new_materialmap"/>
+ <Action name="new_pigment"/>
+ <Action name="new_pigmentlist"/>
+ <Action name="new_pigmentmap"/>
+ <Action name="new_imagemap"/>
+ <Action name="new_solidcolor"/>
+ <Action name="new_colorlist"/>
+ <Action name="new_colormap"/>
+ <Action name="new_normal"/>
+ <Action name="new_normallist"/>
+ <Action name="new_normalmap"/>
+ <Action name="new_bumpmap"/>
+ <Action name="new_slope"/>
+ <Action name="new_slopemap"/>
+ <Action name="new_finish"/>
+ <Separator/>
+ <Action name="new_quickcolor"/>
+ </Menu>
+ <Menu name="photons_objects"><text>Photons</text>
+ <Action name="new_photons"/>
+ </Menu>
+ <Menu name="atmospheric_objects"><text>Atmospheric Effects</text>
+ <Action name="new_skysphere"/>
+ <Action name="new_rainbow"/>
+ <Action name="new_fog"/>
+ </Menu>
+ <Separator/>
+ <Menu name="transformation_objects"><text>Transformations</text>
+ <Action name="new_scale"/>
+ <Action name="new_rotate"/>
+ <Action name="new_translate"/>
+ <Action name="new_povraymatrix"/>
+ </Menu>
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="view_render_settings"/>
+ <Action name="view_render"/>
+ <Action name="view_render_window"/>
+ <Separator/>
+ <Action name="global_detail_level"/>
+ </Menu>
+</MenuBar>
+
+<Menu name="viewPopup">
+ <Action name="view_redisplay"/>
+ <Separator/>
+ <Action name="view_pos_x"/>
+ <Action name="view_neg_x"/>
+ <Action name="view_pos_y"/>
+ <Action name="view_neg_y"/>
+ <Action name="view_pos_z"/>
+ <Action name="view_neg_z"/>
+ <Action name="view_cameras_menu"/>
+ <Separator/>
+ <Action name="view_translate"/>
+ <Action name="view_scale"/>
+ <Separator/>
+ <Action name="cp_snaptogrid"/>
+ <ActionList name="cp_commands"/>
+ <Separator/>
+ <Action name="view_control_points_menu"/>
+</Menu>
+
+<Menu name="treeViewPopup">
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_delete"/>
+</Menu>
+
+<ToolBar name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_delete"/>
+</ToolBar>
+
+<ToolBar name="newSolidObjectsBar"><text>Finite Solid Primitives</text>
+ <Action name="new_box"/>
+ <Action name="new_sphere"/>
+ <Action name="new_cylinder"/>
+ <Action name="new_cone"/>
+ <Action name="new_torus"/>
+ <Action name="new_superquadricellipsoid"/>
+ <Action name="new_heightfield"/>
+ <Action name="new_text"/>
+ <Action name="new_juliafractal"/>
+ <Action name="new_isosurface"/>
+ <Separator/>
+ <Action name="new_blob"/>
+ <Action name="new_blobsphere"/>
+ <Action name="new_blobcylinder"/>
+ <Separator/>
+ <Action name="new_lathe"/>
+ <Action name="new_prism"/>
+ <Action name="new_surfaceofrevolution"/>
+ <Action name="new_spheresweep"/>
+ <Separator/>
+ <Action name="new_objectlink"/>
+</ToolBar>
+
+<ToolBar name="newCSGObjectsBar"><text>Constructive Solid Geometry</text>
+ <Action name="new_union"/>
+ <Action name="new_intersection"/>
+ <Action name="new_difference"/>
+ <Action name="new_merge"/>
+</ToolBar>
+
+<ToolBar name="newInfiniteAndPatchObjectsBar"><text>Infinite and Patch Primitives</text>
+ <Action name="new_plane"/>
+ <Action name="new_polynom"/>
+ <Separator/>
+ <Action name="new_disc"/>
+ <Action name="new_bicubicpatch"/>
+ <Action name="new_triangle"/>
+ <Action name="new_mesh"/>
+</ToolBar>
+
+<ToolBar name="newAtmosphericEffectsBar"><text>Atmospheric Effects</text>
+ <Action name="new_skysphere"/>
+ <Action name="new_rainbow"/>
+ <Action name="new_fog"/>
+</ToolBar>
+
+<ToolBar name="newMiscObjectsBar"><text>Misc Objects</text>
+ <Action name="new_declare"/>
+ <Separator/>
+ <Action name="new_clippedby"/>
+ <Action name="new_boundedby"/>
+ <Separator/>
+ <Action name="new_light"/>
+ <Action name="new_lightgroup"/>
+ <Action name="new_lookslike"/>
+ <Action name="new_projectedthrough"/>
+ <Separator/>
+ <Action name="new_camera"/>
+ <Separator/>
+ <Action name="new_globalsettings"/>
+ <Action name="new_radiosity"/>
+ <Action name="new_globalphotons"/>
+ <Separator/>
+ <Action name="new_comment"/>
+ <Action name="new_raw"/>
+</ToolBar>
+
+<ToolBar name="newTransformationsBar"><text>Transformations</text>
+ <Action name="new_scale"/>
+ <Action name="new_rotate"/>
+ <Action name="new_translate"/>
+ <Action name="new_povraymatrix"/>
+</ToolBar>
+
+<ToolBar name="newTexturesBar"><text>Textures</text>
+ <Action name="new_material"/>
+ <Separator/>
+ <Action name="new_interior"/>
+ <Action name="new_media"/>
+ <Action name="new_density"/>
+ <Action name="new_densitylist"/>
+ <Action name="new_densitymap"/>
+ <Separator/>
+ <Action name="new_pattern"/>
+ <Action name="new_blendmapmodifiers"/>
+ <Action name="new_warp"/>
+ <Separator/>
+ <Action name="new_texture"/>
+ <Action name="new_interiortexture"/>
+ <Action name="new_texturelist"/>
+ <Action name="new_texturemap"/>
+ <Action name="new_materialmap"/>
+ <Action name="new_pigment"/>
+ <Action name="new_pigmentlist"/>
+ <Action name="new_pigmentmap"/>
+ <Action name="new_imagemap"/>
+ <Action name="new_solidcolor"/>
+ <Action name="new_colorlist"/>
+ <Action name="new_colormap"/>
+ <Action name="new_normal"/>
+ <Action name="new_normallist"/>
+ <Action name="new_normalmap"/>
+ <Action name="new_bumpmap"/>
+ <Action name="new_slope"/>
+ <Action name="new_slopemap"/>
+ <Action name="new_finish"/>
+ <Separator/>
+ <Action name="new_quickcolor"/>
+ <Separator/>
+ <Action name="new_photons"/>
+</ToolBar>
+
+<ToolBar name="renderBar"><text>Povray Rendering</text>
+ <Action name="view_render_combo"/>
+ <Action name="view_render_settings"/>
+ <Action name="view_render"/>
+</ToolBar>
+
+<ToolBar name="graphicalViewsBar"><text>Graphical View</text>
+ <Action name="view_visibility_label"/>
+ <Action name="view_visibility_level"/>
+ <Separator/>
+ <Action name="global_detail_label"/>
+ <Action name="global_detail_level"/>
+</ToolBar>
+
+</kpartgui>
diff --git a/kpovmodeler/main.cpp b/kpovmodeler/main.cpp
new file mode 100644
index 00000000..8bdabf8e
--- /dev/null
+++ b/kpovmodeler/main.cpp
@@ -0,0 +1,69 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include <klocale.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kapplication.h>
+
+#include "pmshell.h"
+#include "pmfactory.h"
+#include "pmrendermanager.h"
+#include "version.h"
+
+
+static KCmdLineOptions options[] =
+{
+ { "+[file]", I18N_NOOP( "File to open" ), 0 },
+ { "no-opengl", I18N_NOOP( "Disables OpenGL rendering" ), 0 },
+ { "no-dri", I18N_NOOP( "Disables direct rendering" ), 0 },
+ KCmdLineLastOption
+};
+
+int main( int argc, char* argv[] )
+{
+ PMShell* shell = 0;
+
+ KCmdLineArgs::init( argc, argv, PMFactory::aboutData( ) );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs( );
+
+ if( !args->isSet( "-opengl" ) )
+ PMRenderManager::disableOpenGL( );
+ if( !args->isSet( "-dri" ) )
+ PMGLView::enableDirectRendering( false );
+
+ if( args->count( ) > 0 )
+ {
+ for( int i = 0 ; i < args->count( ) ; i++ )
+ {
+ shell = new PMShell( args->url( i ) );
+ shell->show( );
+ }
+ }
+ else
+ {
+ shell = new PMShell;
+ shell->show( );
+ }
+ args->clear();
+ return app.exec( );
+}
diff --git a/kpovmodeler/pics/Makefile.am b/kpovmodeler/pics/Makefile.am
new file mode 100644
index 00000000..ff33151e
--- /dev/null
+++ b/kpovmodeler/pics/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = locolor crystalsvg
diff --git a/kpovmodeler/pics/crystalsvg/Makefile.am b/kpovmodeler/pics/crystalsvg/Makefile.am
new file mode 100644
index 00000000..66481ab6
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/Makefile.am
@@ -0,0 +1,2 @@
+pmtoolbardir = $(kde_datadir)/kpovmodeler/icons
+pmtoolbar_ICON = AUTO
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmaddpoint.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmaddpoint.png
new file mode 100644
index 00000000..b3c7cab4
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmaddpoint.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmaddpointabove.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmaddpointabove.png
new file mode 100644
index 00000000..4310c761
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmaddpointabove.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmaddsubprism.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmaddsubprism.png
new file mode 100644
index 00000000..ff5bca2b
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmaddsubprism.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmbicubicpatch.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmbicubicpatch.png
new file mode 100644
index 00000000..3b7baaa0
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmbicubicpatch.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmblendmapmodifiers.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmblendmapmodifiers.png
new file mode 100644
index 00000000..334867dc
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmblendmapmodifiers.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmblob.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmblob.png
new file mode 100644
index 00000000..28c7f9c4
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmblob.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmblobcylinder.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmblobcylinder.png
new file mode 100644
index 00000000..3b788ebf
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmblobcylinder.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmblobsphere.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmblobsphere.png
new file mode 100644
index 00000000..9e9e9c04
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmblobsphere.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmboundedby.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmboundedby.png
new file mode 100644
index 00000000..288769d8
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmboundedby.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmbox.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmbox.png
new file mode 100644
index 00000000..48a81471
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmbox.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmbumpmap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmbumpmap.png
new file mode 100644
index 00000000..5221c2a9
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmbumpmap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmcamera.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmcamera.png
new file mode 100644
index 00000000..264a4e9f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmcamera.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmclippedby.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmclippedby.png
new file mode 100644
index 00000000..b281ac84
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmclippedby.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmcolorlist.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmcolorlist.png
new file mode 100644
index 00000000..cc3e406d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmcolorlist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmcolormap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmcolormap.png
new file mode 100644
index 00000000..ed68e5e5
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmcolormap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmcolormapdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmcolormapdeclare.png
new file mode 100644
index 00000000..3371c27a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmcolormapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmcomment.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmcomment.png
new file mode 100644
index 00000000..78b0a3f0
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmcomment.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmcone.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmcone.png
new file mode 100644
index 00000000..0dd88efd
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmcone.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmcylinder.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmcylinder.png
new file mode 100644
index 00000000..753453b2
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmcylinder.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdeclare.png
new file mode 100644
index 00000000..36c277d5
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdensity.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensity.png
new file mode 100644
index 00000000..98b91daa
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensity.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitydeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitydeclare.png
new file mode 100644
index 00000000..87f96d9e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitydeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitylist.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitylist.png
new file mode 100644
index 00000000..a783751e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitylist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitymap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitymap.png
new file mode 100644
index 00000000..dc277d2c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitymap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitymapdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitymapdeclare.png
new file mode 100644
index 00000000..f22f525e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdensitymapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdialogview.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdialogview.png
new file mode 100644
index 00000000..e48cb253
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdialogview.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdifference.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdifference.png
new file mode 100644
index 00000000..d2551828
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdifference.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdisc.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdisc.png
new file mode 100644
index 00000000..c39115c4
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdisc.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmdrag.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmdrag.png
new file mode 100644
index 00000000..65aba8ba
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmdrag.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmfinish.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmfinish.png
new file mode 100644
index 00000000..d014f144
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmfinish.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmfinishdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmfinishdeclare.png
new file mode 100644
index 00000000..b0e77f59
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmfinishdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmfog.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmfog.png
new file mode 100644
index 00000000..5d7acae0
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmfog.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmfogdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmfogdeclare.png
new file mode 100644
index 00000000..0db954dc
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmfogdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmglobalphotons.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmglobalphotons.png
new file mode 100644
index 00000000..1e6d4144
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmglobalphotons.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmglobalsettings.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmglobalsettings.png
new file mode 100644
index 00000000..9732e0ba
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmglobalsettings.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmglview.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmglview.png
new file mode 100644
index 00000000..7b69cea1
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmglview.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmheightfield.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmheightfield.png
new file mode 100644
index 00000000..f40f3f50
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmheightfield.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmimagemap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmimagemap.png
new file mode 100644
index 00000000..01d8d9da
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmimagemap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pminserterrors.png b/kpovmodeler/pics/crystalsvg/cr16-action-pminserterrors.png
new file mode 100644
index 00000000..a8edc396
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pminserterrors.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pminsertfirstchild.png b/kpovmodeler/pics/crystalsvg/cr16-action-pminsertfirstchild.png
new file mode 100644
index 00000000..5ee47f17
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pminsertfirstchild.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pminsertlastchild.png b/kpovmodeler/pics/crystalsvg/cr16-action-pminsertlastchild.png
new file mode 100644
index 00000000..cc7193f7
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pminsertlastchild.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pminsertsibling.png b/kpovmodeler/pics/crystalsvg/cr16-action-pminsertsibling.png
new file mode 100644
index 00000000..a0bca16f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pminsertsibling.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pminterior.png b/kpovmodeler/pics/crystalsvg/cr16-action-pminterior.png
new file mode 100644
index 00000000..76a003df
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pminterior.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pminteriordeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pminteriordeclare.png
new file mode 100644
index 00000000..18781544
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pminteriordeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pminteriortexture.png b/kpovmodeler/pics/crystalsvg/cr16-action-pminteriortexture.png
new file mode 100644
index 00000000..0de1c19b
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pminteriortexture.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pminteriortexturedeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pminteriortexturedeclare.png
new file mode 100644
index 00000000..801ecda9
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pminteriortexturedeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmintersection.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmintersection.png
new file mode 100644
index 00000000..954eae50
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmintersection.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmisosurface.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmisosurface.png
new file mode 100644
index 00000000..59dbdc05
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmisosurface.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmjuliafractal.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmjuliafractal.png
new file mode 100644
index 00000000..66b6cad0
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmjuliafractal.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmlathe.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmlathe.png
new file mode 100644
index 00000000..bd316870
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmlathe.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmlight.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmlight.png
new file mode 100644
index 00000000..e6e0d098
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmlight.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmlightgroup.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmlightgroup.png
new file mode 100644
index 00000000..105ca083
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmlightgroup.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmlistpattern.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmlistpattern.png
new file mode 100644
index 00000000..cd68aa2a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmlistpattern.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmlookslike.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmlookslike.png
new file mode 100644
index 00000000..3b511673
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmlookslike.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterial.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterial.png
new file mode 100644
index 00000000..af492025
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterial.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterialdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterialdeclare.png
new file mode 100644
index 00000000..aa9ba10b
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterialdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterialmap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterialmap.png
new file mode 100644
index 00000000..f46a9fb2
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmmaterialmap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmmatrix.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmmatrix.png
new file mode 100644
index 00000000..32f4f298
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmmatrix.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmmedia.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmmedia.png
new file mode 100644
index 00000000..4b72046c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmmedia.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmmediadeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmmediadeclare.png
new file mode 100644
index 00000000..e43b3948
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmmediadeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmmerge.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmmerge.png
new file mode 100644
index 00000000..04e71ed2
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmmerge.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmmesh.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmmesh.png
new file mode 100644
index 00000000..3ab5de1a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmmesh.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmnormal.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormal.png
new file mode 100644
index 00000000..99979725
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormal.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmnormaldeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormaldeclare.png
new file mode 100644
index 00000000..e148abc3
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormaldeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmnormallist.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormallist.png
new file mode 100644
index 00000000..4f4fea88
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormallist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmnormalmap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormalmap.png
new file mode 100644
index 00000000..6d12407b
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormalmap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmnormalmapdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormalmapdeclare.png
new file mode 100644
index 00000000..09c6d28e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmnormalmapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmobjectdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmobjectdeclare.png
new file mode 100644
index 00000000..cd562250
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmobjectdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmobjectlink.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmobjectlink.png
new file mode 100644
index 00000000..479664f6
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmobjectlink.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmpattern.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmpattern.png
new file mode 100644
index 00000000..5032bb8d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmpattern.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmphotons.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmphotons.png
new file mode 100644
index 00000000..b2f64977
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmphotons.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmpigment.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigment.png
new file mode 100644
index 00000000..e1c49853
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigment.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentdeclare.png
new file mode 100644
index 00000000..15af344d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentlist.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentlist.png
new file mode 100644
index 00000000..26aa2908
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentlist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentmap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentmap.png
new file mode 100644
index 00000000..32e1c4e6
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentmap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentmapdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentmapdeclare.png
new file mode 100644
index 00000000..2ff2d59d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmpigmentmapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmplane.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmplane.png
new file mode 100644
index 00000000..8e6590b0
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmplane.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmpolynom.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmpolynom.png
new file mode 100644
index 00000000..fcaf1a15
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmpolynom.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmprism.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmprism.png
new file mode 100644
index 00000000..b58f5aa8
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmprism.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmprojectedthrough.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmprojectedthrough.png
new file mode 100644
index 00000000..94b4aa4e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmprojectedthrough.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmquickcolor.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmquickcolor.png
new file mode 100644
index 00000000..41afd2a3
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmquickcolor.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmradiosity.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmradiosity.png
new file mode 100644
index 00000000..0428f202
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmradiosity.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmrainbow.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmrainbow.png
new file mode 100644
index 00000000..271405db
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmrainbow.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmrainbowdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmrainbowdeclare.png
new file mode 100644
index 00000000..9232255c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmrainbowdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmraw.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmraw.png
new file mode 100644
index 00000000..cb0ce235
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmraw.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmremovepoint.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmremovepoint.png
new file mode 100644
index 00000000..0be182fb
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmremovepoint.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmrender.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmrender.png
new file mode 100644
index 00000000..901a283d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmrender.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmrenderpreview.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmrenderpreview.png
new file mode 100644
index 00000000..c14b2c38
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmrenderpreview.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmrendersettings.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmrendersettings.png
new file mode 100644
index 00000000..9a63e1a2
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmrendersettings.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmrotate.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmrotate.png
new file mode 100644
index 00000000..744f927c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmrotate.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmscale.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmscale.png
new file mode 100644
index 00000000..ca553a0f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmscale.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmscene.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmscene.png
new file mode 100644
index 00000000..8a4c4bd1
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmscene.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmskysphere.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmskysphere.png
new file mode 100644
index 00000000..bbfd050a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmskysphere.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmskyspheredeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmskyspheredeclare.png
new file mode 100644
index 00000000..16cd5bb3
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmskyspheredeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmslope.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmslope.png
new file mode 100644
index 00000000..e665a1bd
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmslope.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmslopemap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmslopemap.png
new file mode 100644
index 00000000..a757fc90
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmslopemap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmslopemapdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmslopemapdeclare.png
new file mode 100644
index 00000000..fe7e9969
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmslopemapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmsolidcolor.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmsolidcolor.png
new file mode 100644
index 00000000..b2f4eda7
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmsolidcolor.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmsor.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmsor.png
new file mode 100644
index 00000000..8a652ed7
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmsor.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmsphere.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmsphere.png
new file mode 100644
index 00000000..a8a38679
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmsphere.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmspheresweep.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmspheresweep.png
new file mode 100644
index 00000000..19cced4c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmspheresweep.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmsqe.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmsqe.png
new file mode 100644
index 00000000..ea2e2a14
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmsqe.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtext.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtext.png
new file mode 100644
index 00000000..4b339926
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtext.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtexture.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexture.png
new file mode 100644
index 00000000..c90031ca
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexture.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturedeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturedeclare.png
new file mode 100644
index 00000000..75a77847
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturedeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturelist.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturelist.png
new file mode 100644
index 00000000..85881a7d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturelist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturemap.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturemap.png
new file mode 100644
index 00000000..171bf68d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturemap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturemapdeclare.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturemapdeclare.png
new file mode 100644
index 00000000..ab2edae6
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtexturemapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtorus.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtorus.png
new file mode 100644
index 00000000..82f78511
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtorus.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtranslate.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtranslate.png
new file mode 100644
index 00000000..2d16dea2
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtranslate.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtreeview.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtreeview.png
new file mode 100644
index 00000000..b78f646d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtreeview.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmtriangle.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmtriangle.png
new file mode 100644
index 00000000..9592e253
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmtriangle.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmunion.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmunion.png
new file mode 100644
index 00000000..1407fe3a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmunion.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr16-action-pmwarp.png b/kpovmodeler/pics/crystalsvg/cr16-action-pmwarp.png
new file mode 100644
index 00000000..c0f294cd
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr16-action-pmwarp.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmbicubicpatch.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmbicubicpatch.png
new file mode 100644
index 00000000..4dedf979
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmbicubicpatch.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmblendmapmodifiers.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmblendmapmodifiers.png
new file mode 100644
index 00000000..15fc5700
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmblendmapmodifiers.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmblob.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmblob.png
new file mode 100644
index 00000000..a165af80
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmblob.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmblobcylinder.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmblobcylinder.png
new file mode 100644
index 00000000..5dc230f9
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmblobcylinder.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmblobsphere.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmblobsphere.png
new file mode 100644
index 00000000..a43cf351
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmblobsphere.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmboundedby.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmboundedby.png
new file mode 100644
index 00000000..a8748990
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmboundedby.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmbox.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmbox.png
new file mode 100644
index 00000000..1bbdac7c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmbox.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmbumpmap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmbumpmap.png
new file mode 100644
index 00000000..2371d104
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmbumpmap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmcamera.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmcamera.png
new file mode 100644
index 00000000..51e3079a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmcamera.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmclippedby.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmclippedby.png
new file mode 100644
index 00000000..e7653cb1
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmclippedby.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmcolorlist.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmcolorlist.png
new file mode 100644
index 00000000..b94946d3
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmcolorlist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmcolormap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmcolormap.png
new file mode 100644
index 00000000..775db294
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmcolormap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmcolormapdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmcolormapdeclare.png
new file mode 100644
index 00000000..d4033601
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmcolormapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmcomment.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmcomment.png
new file mode 100644
index 00000000..348ed6fa
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmcomment.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmcone.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmcone.png
new file mode 100644
index 00000000..8cb55a7a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmcone.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigurecolors.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigurecolors.png
new file mode 100644
index 00000000..5775bb49
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigurecolors.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguredialogview.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguredialogview.png
new file mode 100644
index 00000000..5951a63b
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguredialogview.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguregraphicalview.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguregraphicalview.png
new file mode 100644
index 00000000..87ce6705
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguregraphicalview.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguregrid.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguregrid.png
new file mode 100644
index 00000000..f378b405
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguregrid.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureobjectlibrary.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureobjectlibrary.png
new file mode 100644
index 00000000..83a72f37
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureobjectlibrary.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureobjects.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureobjects.png
new file mode 100644
index 00000000..16fc0bdf
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureobjects.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureopengl.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureopengl.png
new file mode 100644
index 00000000..03c1efca
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureopengl.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigurepovray.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigurepovray.png
new file mode 100644
index 00000000..de26c9ca
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigurepovray.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguretexturepreview.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguretexturepreview.png
new file mode 100644
index 00000000..6cd4ee02
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfiguretexturepreview.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureviewlayout.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureviewlayout.png
new file mode 100644
index 00000000..502eb876
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmconfigureviewlayout.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmcylinder.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmcylinder.png
new file mode 100644
index 00000000..7fe73163
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmcylinder.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdeclare.png
new file mode 100644
index 00000000..840d56eb
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdensity.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensity.png
new file mode 100644
index 00000000..057210fb
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensity.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitydeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitydeclare.png
new file mode 100644
index 00000000..c38fe00c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitydeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitylist.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitylist.png
new file mode 100644
index 00000000..3c260d9e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitylist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitymap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitymap.png
new file mode 100644
index 00000000..3aabb850
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitymap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitymapdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitymapdeclare.png
new file mode 100644
index 00000000..2fc8e38b
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdensitymapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdifference.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdifference.png
new file mode 100644
index 00000000..0ac4238e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdifference.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdisc.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdisc.png
new file mode 100644
index 00000000..536cc8a0
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdisc.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmdrag.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmdrag.png
new file mode 100644
index 00000000..5a5c703d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmdrag.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmfinish.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmfinish.png
new file mode 100644
index 00000000..070f16d1
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmfinish.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmfinishdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmfinishdeclare.png
new file mode 100644
index 00000000..8d8359c5
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmfinishdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmfog.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmfog.png
new file mode 100644
index 00000000..23a5e5ee
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmfog.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmfogdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmfogdeclare.png
new file mode 100644
index 00000000..df4460d1
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmfogdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmglobalphotons.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmglobalphotons.png
new file mode 100644
index 00000000..b97c1337
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmglobalphotons.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmglobalsettings.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmglobalsettings.png
new file mode 100644
index 00000000..c87764bc
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmglobalsettings.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmheightfield.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmheightfield.png
new file mode 100644
index 00000000..64b767b4
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmheightfield.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmimagemap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmimagemap.png
new file mode 100644
index 00000000..a93604e5
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmimagemap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pminserterrors.png b/kpovmodeler/pics/crystalsvg/cr22-action-pminserterrors.png
new file mode 100644
index 00000000..fab5a4eb
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pminserterrors.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pminterior.png b/kpovmodeler/pics/crystalsvg/cr22-action-pminterior.png
new file mode 100644
index 00000000..d3c3a66f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pminterior.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pminteriordeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pminteriordeclare.png
new file mode 100644
index 00000000..20c5880e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pminteriordeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pminteriortexture.png b/kpovmodeler/pics/crystalsvg/cr22-action-pminteriortexture.png
new file mode 100644
index 00000000..bf6b6d00
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pminteriortexture.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pminteriortexturedeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pminteriortexturedeclare.png
new file mode 100644
index 00000000..2566437f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pminteriortexturedeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmintersection.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmintersection.png
new file mode 100644
index 00000000..edc287ff
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmintersection.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmisosurface.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmisosurface.png
new file mode 100644
index 00000000..cbbad58f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmisosurface.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmjuliafractal.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmjuliafractal.png
new file mode 100644
index 00000000..ce90ba06
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmjuliafractal.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmlathe.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmlathe.png
new file mode 100644
index 00000000..572ca904
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmlathe.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmlight.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmlight.png
new file mode 100644
index 00000000..ebb36242
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmlight.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmlightgroup.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmlightgroup.png
new file mode 100644
index 00000000..49e1aee6
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmlightgroup.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmlistpattern.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmlistpattern.png
new file mode 100644
index 00000000..76fa8d8b
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmlistpattern.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmlookslike.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmlookslike.png
new file mode 100644
index 00000000..d70ce958
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmlookslike.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterial.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterial.png
new file mode 100644
index 00000000..9cb8498d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterial.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterialdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterialdeclare.png
new file mode 100644
index 00000000..317b793b
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterialdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterialmap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterialmap.png
new file mode 100644
index 00000000..d352f4c1
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmmaterialmap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmmatrix.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmmatrix.png
new file mode 100644
index 00000000..3b9524e5
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmmatrix.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmmedia.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmmedia.png
new file mode 100644
index 00000000..dcb93a22
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmmedia.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmmediadeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmmediadeclare.png
new file mode 100644
index 00000000..e09b71c9
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmmediadeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmmerge.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmmerge.png
new file mode 100644
index 00000000..ce93f989
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmmerge.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmmesh.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmmesh.png
new file mode 100644
index 00000000..74ffa376
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmmesh.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmnormal.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormal.png
new file mode 100644
index 00000000..c2838b98
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormal.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmnormaldeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormaldeclare.png
new file mode 100644
index 00000000..ce3841d8
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormaldeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmnormallist.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormallist.png
new file mode 100644
index 00000000..ec5d3695
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormallist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmnormalmap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormalmap.png
new file mode 100644
index 00000000..435b0b74
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormalmap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmnormalmapdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormalmapdeclare.png
new file mode 100644
index 00000000..2cabff95
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmnormalmapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmobjectdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmobjectdeclare.png
new file mode 100644
index 00000000..b1d2947f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmobjectdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmobjectlink.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmobjectlink.png
new file mode 100644
index 00000000..f6e2a32f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmobjectlink.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmpattern.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmpattern.png
new file mode 100644
index 00000000..f2620041
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmpattern.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmphotons.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmphotons.png
new file mode 100644
index 00000000..4e2f161e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmphotons.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmpigment.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigment.png
new file mode 100644
index 00000000..6a2103d0
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigment.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentdeclare.png
new file mode 100644
index 00000000..5b0e22e7
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentlist.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentlist.png
new file mode 100644
index 00000000..568beead
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentlist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentmap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentmap.png
new file mode 100644
index 00000000..36466942
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentmap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentmapdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentmapdeclare.png
new file mode 100644
index 00000000..8bbee2e9
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmpigmentmapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmplane.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmplane.png
new file mode 100644
index 00000000..f5430a72
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmplane.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmpolynom.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmpolynom.png
new file mode 100644
index 00000000..67e4b46c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmpolynom.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmprism.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmprism.png
new file mode 100644
index 00000000..ca3dd0b5
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmprism.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmprojectedthrough.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmprojectedthrough.png
new file mode 100644
index 00000000..4f7712e6
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmprojectedthrough.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmquickcolor.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmquickcolor.png
new file mode 100644
index 00000000..4a2c7c25
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmquickcolor.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmradiosity.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmradiosity.png
new file mode 100644
index 00000000..59f923cf
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmradiosity.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmrainbow.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmrainbow.png
new file mode 100644
index 00000000..3e0b1021
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmrainbow.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmrainbowdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmrainbowdeclare.png
new file mode 100644
index 00000000..f92ab03e
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmrainbowdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmraw.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmraw.png
new file mode 100644
index 00000000..d8270f7c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmraw.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmrender.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmrender.png
new file mode 100644
index 00000000..6aa2b69f
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmrender.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmrenderpreview.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmrenderpreview.png
new file mode 100644
index 00000000..0227ab0c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmrenderpreview.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmrendersettings.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmrendersettings.png
new file mode 100644
index 00000000..cb6b2e9a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmrendersettings.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmrotate.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmrotate.png
new file mode 100644
index 00000000..22a5af44
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmrotate.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmscale.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmscale.png
new file mode 100644
index 00000000..e7820f60
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmscale.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmscene.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmscene.png
new file mode 100644
index 00000000..47c9dc56
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmscene.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmskysphere.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmskysphere.png
new file mode 100644
index 00000000..cad5cdf5
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmskysphere.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmskyspheredeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmskyspheredeclare.png
new file mode 100644
index 00000000..4aaafa28
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmskyspheredeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmslope.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmslope.png
new file mode 100644
index 00000000..42abb1b4
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmslope.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmslopemap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmslopemap.png
new file mode 100644
index 00000000..4efbb6ef
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmslopemap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmslopemapdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmslopemapdeclare.png
new file mode 100644
index 00000000..19307196
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmslopemapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmsolidcolor.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmsolidcolor.png
new file mode 100644
index 00000000..e8cbfc51
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmsolidcolor.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmsor.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmsor.png
new file mode 100644
index 00000000..1a9bdf7a
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmsor.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmsphere.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmsphere.png
new file mode 100644
index 00000000..bb9b6f2d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmsphere.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmspheresweep.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmspheresweep.png
new file mode 100644
index 00000000..fe94fb83
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmspheresweep.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmsqe.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmsqe.png
new file mode 100644
index 00000000..a3d9152d
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmsqe.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtext.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtext.png
new file mode 100644
index 00000000..25fc94c3
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtext.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtexture.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexture.png
new file mode 100644
index 00000000..a2f13e15
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexture.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturedeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturedeclare.png
new file mode 100644
index 00000000..e40843f0
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturedeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturelist.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturelist.png
new file mode 100644
index 00000000..e497f164
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturelist.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturemap.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturemap.png
new file mode 100644
index 00000000..282acdf6
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturemap.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturemapdeclare.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturemapdeclare.png
new file mode 100644
index 00000000..2f046f10
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtexturemapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtorus.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtorus.png
new file mode 100644
index 00000000..ab187e64
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtorus.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtranslate.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtranslate.png
new file mode 100644
index 00000000..3234c8fe
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtranslate.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmtriangle.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmtriangle.png
new file mode 100644
index 00000000..4cae6980
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmtriangle.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmunion.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmunion.png
new file mode 100644
index 00000000..aacb8776
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmunion.png
Binary files differ
diff --git a/kpovmodeler/pics/crystalsvg/cr22-action-pmwarp.png b/kpovmodeler/pics/crystalsvg/cr22-action-pmwarp.png
new file mode 100644
index 00000000..e98e139c
--- /dev/null
+++ b/kpovmodeler/pics/crystalsvg/cr22-action-pmwarp.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/Makefile.am b/kpovmodeler/pics/locolor/Makefile.am
new file mode 100644
index 00000000..66481ab6
--- /dev/null
+++ b/kpovmodeler/pics/locolor/Makefile.am
@@ -0,0 +1,2 @@
+pmtoolbardir = $(kde_datadir)/kpovmodeler/icons
+pmtoolbar_ICON = AUTO
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmaddpoint.png b/kpovmodeler/pics/locolor/lo16-action-pmaddpoint.png
new file mode 100644
index 00000000..b3c7cab4
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmaddpoint.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmaddpointabove.png b/kpovmodeler/pics/locolor/lo16-action-pmaddpointabove.png
new file mode 100644
index 00000000..4310c761
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmaddpointabove.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmaddsubprism.png b/kpovmodeler/pics/locolor/lo16-action-pmaddsubprism.png
new file mode 100644
index 00000000..c292daab
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmaddsubprism.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmbicubicpatch.png b/kpovmodeler/pics/locolor/lo16-action-pmbicubicpatch.png
new file mode 100644
index 00000000..dd3752c9
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmbicubicpatch.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmblendmapmodifiers.png b/kpovmodeler/pics/locolor/lo16-action-pmblendmapmodifiers.png
new file mode 100644
index 00000000..c95808c9
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmblendmapmodifiers.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmblob.png b/kpovmodeler/pics/locolor/lo16-action-pmblob.png
new file mode 100644
index 00000000..f5dfe034
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmblob.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmblobcylinder.png b/kpovmodeler/pics/locolor/lo16-action-pmblobcylinder.png
new file mode 100644
index 00000000..a320ec3a
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmblobcylinder.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmblobsphere.png b/kpovmodeler/pics/locolor/lo16-action-pmblobsphere.png
new file mode 100644
index 00000000..f45f5433
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmblobsphere.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmboundedby.png b/kpovmodeler/pics/locolor/lo16-action-pmboundedby.png
new file mode 100644
index 00000000..4d167b4d
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmboundedby.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmbox.png b/kpovmodeler/pics/locolor/lo16-action-pmbox.png
new file mode 100644
index 00000000..6e8665d4
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmbox.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmbumpmap.png b/kpovmodeler/pics/locolor/lo16-action-pmbumpmap.png
new file mode 100644
index 00000000..17df5809
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmbumpmap.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmcamera.png b/kpovmodeler/pics/locolor/lo16-action-pmcamera.png
new file mode 100644
index 00000000..264a4e9f
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmcamera.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmclippedby.png b/kpovmodeler/pics/locolor/lo16-action-pmclippedby.png
new file mode 100644
index 00000000..98394ece
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmclippedby.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmcomment.png b/kpovmodeler/pics/locolor/lo16-action-pmcomment.png
new file mode 100644
index 00000000..78b0a3f0
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmcomment.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmcone.png b/kpovmodeler/pics/locolor/lo16-action-pmcone.png
new file mode 100644
index 00000000..dc369725
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmcone.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmcylinder.png b/kpovmodeler/pics/locolor/lo16-action-pmcylinder.png
new file mode 100644
index 00000000..7147b4ca
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmcylinder.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmdeclare.png
new file mode 100644
index 00000000..e56be4e9
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdensity.png b/kpovmodeler/pics/locolor/lo16-action-pmdensity.png
new file mode 100644
index 00000000..58fe3d6f
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdensity.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdensitydeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmdensitydeclare.png
new file mode 100644
index 00000000..9b826d4a
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdensitydeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdensitylist.png b/kpovmodeler/pics/locolor/lo16-action-pmdensitylist.png
new file mode 100644
index 00000000..d4d9170b
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdensitylist.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdensitymap.png b/kpovmodeler/pics/locolor/lo16-action-pmdensitymap.png
new file mode 100644
index 00000000..69f9fda7
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdensitymap.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdensitymapdeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmdensitymapdeclare.png
new file mode 100644
index 00000000..0b26c273
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdensitymapdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdifference.png b/kpovmodeler/pics/locolor/lo16-action-pmdifference.png
new file mode 100644
index 00000000..d2551828
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdifference.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdisc.png b/kpovmodeler/pics/locolor/lo16-action-pmdisc.png
new file mode 100644
index 00000000..095adf32
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdisc.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmdrag.png b/kpovmodeler/pics/locolor/lo16-action-pmdrag.png
new file mode 100644
index 00000000..65aba8ba
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmdrag.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmfog.png b/kpovmodeler/pics/locolor/lo16-action-pmfog.png
new file mode 100644
index 00000000..89346120
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmfog.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmfogdeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmfogdeclare.png
new file mode 100644
index 00000000..944720cb
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmfogdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmglobalsettings.png b/kpovmodeler/pics/locolor/lo16-action-pmglobalsettings.png
new file mode 100644
index 00000000..b8951994
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmglobalsettings.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmheightfield.png b/kpovmodeler/pics/locolor/lo16-action-pmheightfield.png
new file mode 100644
index 00000000..5f4b7871
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmheightfield.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmimagemap.png b/kpovmodeler/pics/locolor/lo16-action-pmimagemap.png
new file mode 100644
index 00000000..2ece117d
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmimagemap.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pminserterrors.png b/kpovmodeler/pics/locolor/lo16-action-pminserterrors.png
new file mode 100644
index 00000000..a8edc396
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pminserterrors.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pminsertfirstchild.png b/kpovmodeler/pics/locolor/lo16-action-pminsertfirstchild.png
new file mode 100644
index 00000000..5ee47f17
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pminsertfirstchild.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pminsertlastchild.png b/kpovmodeler/pics/locolor/lo16-action-pminsertlastchild.png
new file mode 100644
index 00000000..cc7193f7
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pminsertlastchild.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pminsertsibling.png b/kpovmodeler/pics/locolor/lo16-action-pminsertsibling.png
new file mode 100644
index 00000000..a0bca16f
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pminsertsibling.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmintersection.png b/kpovmodeler/pics/locolor/lo16-action-pmintersection.png
new file mode 100644
index 00000000..954eae50
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmintersection.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmjuliafractal.png b/kpovmodeler/pics/locolor/lo16-action-pmjuliafractal.png
new file mode 100644
index 00000000..4b88db07
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmjuliafractal.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmlathe.png b/kpovmodeler/pics/locolor/lo16-action-pmlathe.png
new file mode 100644
index 00000000..181e4446
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmlathe.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmlight.png b/kpovmodeler/pics/locolor/lo16-action-pmlight.png
new file mode 100644
index 00000000..ec9c456d
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmlight.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmlistpattern.png b/kpovmodeler/pics/locolor/lo16-action-pmlistpattern.png
new file mode 100644
index 00000000..6a85bc72
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmlistpattern.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmlookslike.png b/kpovmodeler/pics/locolor/lo16-action-pmlookslike.png
new file mode 100644
index 00000000..6f7a439f
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmlookslike.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmmaterialmap.png b/kpovmodeler/pics/locolor/lo16-action-pmmaterialmap.png
new file mode 100644
index 00000000..c964f8a4
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmmaterialmap.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmmatrix.png b/kpovmodeler/pics/locolor/lo16-action-pmmatrix.png
new file mode 100644
index 00000000..096bad00
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmmatrix.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmmerge.png b/kpovmodeler/pics/locolor/lo16-action-pmmerge.png
new file mode 100644
index 00000000..04e71ed2
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmmerge.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmobjectdeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmobjectdeclare.png
new file mode 100644
index 00000000..cd562250
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmobjectdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmobjectlink.png b/kpovmodeler/pics/locolor/lo16-action-pmobjectlink.png
new file mode 100644
index 00000000..479664f6
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmobjectlink.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmpigment.png b/kpovmodeler/pics/locolor/lo16-action-pmpigment.png
new file mode 100644
index 00000000..0f59413c
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmpigment.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmpigmentdeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmpigmentdeclare.png
new file mode 100644
index 00000000..efdada03
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmpigmentdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmplane.png b/kpovmodeler/pics/locolor/lo16-action-pmplane.png
new file mode 100644
index 00000000..7b2029d9
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmplane.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmpolynom.png b/kpovmodeler/pics/locolor/lo16-action-pmpolynom.png
new file mode 100644
index 00000000..d2858866
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmpolynom.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmprism.png b/kpovmodeler/pics/locolor/lo16-action-pmprism.png
new file mode 100644
index 00000000..ce96f3e5
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmprism.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmquickcolor.png b/kpovmodeler/pics/locolor/lo16-action-pmquickcolor.png
new file mode 100644
index 00000000..109131d8
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmquickcolor.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmrainbow.png b/kpovmodeler/pics/locolor/lo16-action-pmrainbow.png
new file mode 100644
index 00000000..ddd11480
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmrainbow.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmrainbowdeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmrainbowdeclare.png
new file mode 100644
index 00000000..47906a3a
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmrainbowdeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmraw.png b/kpovmodeler/pics/locolor/lo16-action-pmraw.png
new file mode 100644
index 00000000..cb0ce235
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmraw.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmremovepoint.png b/kpovmodeler/pics/locolor/lo16-action-pmremovepoint.png
new file mode 100644
index 00000000..0be182fb
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmremovepoint.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmrender.png b/kpovmodeler/pics/locolor/lo16-action-pmrender.png
new file mode 100644
index 00000000..a2fc7d79
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmrender.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmrenderpreview.png b/kpovmodeler/pics/locolor/lo16-action-pmrenderpreview.png
new file mode 100644
index 00000000..feb2f7b1
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmrenderpreview.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmrendersettings.png b/kpovmodeler/pics/locolor/lo16-action-pmrendersettings.png
new file mode 100644
index 00000000..f19b0eea
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmrendersettings.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmrotate.png b/kpovmodeler/pics/locolor/lo16-action-pmrotate.png
new file mode 100644
index 00000000..744f927c
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmrotate.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmscale.png b/kpovmodeler/pics/locolor/lo16-action-pmscale.png
new file mode 100644
index 00000000..ca553a0f
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmscale.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmscene.png b/kpovmodeler/pics/locolor/lo16-action-pmscene.png
new file mode 100644
index 00000000..61dfa78a
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmscene.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmskysphere.png b/kpovmodeler/pics/locolor/lo16-action-pmskysphere.png
new file mode 100644
index 00000000..aaf0f47a
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmskysphere.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmskyspheredeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmskyspheredeclare.png
new file mode 100644
index 00000000..b9d719ff
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmskyspheredeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmsolidcolor.png b/kpovmodeler/pics/locolor/lo16-action-pmsolidcolor.png
new file mode 100644
index 00000000..38840359
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmsolidcolor.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmsor.png b/kpovmodeler/pics/locolor/lo16-action-pmsor.png
new file mode 100644
index 00000000..c38eb6ae
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmsor.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmsphere.png b/kpovmodeler/pics/locolor/lo16-action-pmsphere.png
new file mode 100644
index 00000000..a7ea2461
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmsphere.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmsqr.png b/kpovmodeler/pics/locolor/lo16-action-pmsqr.png
new file mode 100644
index 00000000..cfaa5aff
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmsqr.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmtext.png b/kpovmodeler/pics/locolor/lo16-action-pmtext.png
new file mode 100644
index 00000000..04987349
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmtext.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmtexture.png b/kpovmodeler/pics/locolor/lo16-action-pmtexture.png
new file mode 100644
index 00000000..d84fcd66
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmtexture.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmtexturedeclare.png b/kpovmodeler/pics/locolor/lo16-action-pmtexturedeclare.png
new file mode 100644
index 00000000..8984df92
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmtexturedeclare.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmtorus.png b/kpovmodeler/pics/locolor/lo16-action-pmtorus.png
new file mode 100644
index 00000000..a09660ab
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmtorus.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmtranslate.png b/kpovmodeler/pics/locolor/lo16-action-pmtranslate.png
new file mode 100644
index 00000000..2d16dea2
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmtranslate.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmtriangle.png b/kpovmodeler/pics/locolor/lo16-action-pmtriangle.png
new file mode 100644
index 00000000..dfe6ed44
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmtriangle.png
Binary files differ
diff --git a/kpovmodeler/pics/locolor/lo16-action-pmunion.png b/kpovmodeler/pics/locolor/lo16-action-pmunion.png
new file mode 100644
index 00000000..1407fe3a
--- /dev/null
+++ b/kpovmodeler/pics/locolor/lo16-action-pmunion.png
Binary files differ
diff --git a/kpovmodeler/pm2dcontrolpoint.cpp b/kpovmodeler/pm2dcontrolpoint.cpp
new file mode 100644
index 00000000..66e7a85a
--- /dev/null
+++ b/kpovmodeler/pm2dcontrolpoint.cpp
@@ -0,0 +1,207 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pm2dcontrolpoint.h"
+#include "pmmath.h"
+#include <math.h>
+
+PM2DControlPoint::PM2DControlPoint( const PMVector& point,
+ PM2DControlPoint::CPType type, int id,
+ const QString& description )
+ : PMControlPoint( id, description )
+{
+ m_point = point;
+ m_type = type;
+ m_thirdCoordinate = 0;
+ m_scale = 1.0;
+ m_pBasePoint = 0;
+ m_pLatheLink = 0;
+}
+
+void PM2DControlPoint::graphicalChangeStarted( )
+{
+ QPtrListIterator<PM2DControlPoint> it( m_linkedPoints );
+ for( ; *it; ++it )
+ if( !( *it )->selected( ) )
+ ( *it )->graphicalChangeStarted( );
+
+ m_original2DPoint = m_point;
+ m_originalPoint = to3D( m_point );
+}
+
+void PM2DControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& /*viewNormal*/,
+ const PMVector& endPoint )
+{
+ if( m_pBasePoint && m_pBasePoint->selected( ) )
+ return;
+
+ m_point = to2D( m_originalPoint + endPoint - startPoint );
+
+ if( m_pLatheLink && m_pLatheLink->selected( ) )
+ {
+ PM2DControlPoint* ll = m_pLatheLink;
+ PMVector op = ll->to2D( ll->m_originalPoint + endPoint - startPoint );
+
+ m_point = to2D( m_originalPoint + endPoint - startPoint );
+ if( ( m_point - m_original2DPoint ).abs( ) <
+ ( op - ll->m_original2DPoint ).abs( ) )
+ m_point = op;
+ }
+
+ QPtrListIterator<PM2DControlPoint> it( m_linkedPoints );
+ for( ; *it; ++it )
+ {
+ ( *it )->m_point = m_point + ( *it )->m_original2DPoint
+ - m_original2DPoint;
+ ( *it )->setChanged( );
+ }
+}
+
+void PM2DControlPoint::setBasePoint( PM2DControlPoint* p )
+{
+ if( p != m_pBasePoint )
+ {
+ if( m_pBasePoint )
+ m_pBasePoint->removeLinkedPoint( this );
+ m_pBasePoint = p;
+ if( m_pBasePoint )
+ m_pBasePoint->addLinkedPoint( this );
+ }
+}
+
+void PM2DControlPoint::snapToGrid( )
+{
+ int i;
+ double d = moveGrid( );
+ bool diff = false;
+ PMVector change( 2 );
+
+ if( m_pBasePoint && m_pBasePoint->selected( ) )
+ {
+ m_point -= m_pBasePoint->m_point;
+ diff = true;
+ }
+
+ if( !approxZero( d ) )
+ {
+ for( i = 0; i < 2; i++ )
+ {
+ change[i] = -m_point[i];
+ m_point[i] = rint( m_point[i] / d ) * d;
+ change[i] += m_point[i];
+ }
+ }
+
+ if( diff )
+ m_point += m_pBasePoint->m_point;
+
+ QPtrListIterator<PM2DControlPoint> it( m_linkedPoints );
+ for( ; *it; ++it )
+ {
+ ( *it )->m_point += change;
+ ( *it )->setChanged( );
+ }
+
+ setChanged( );
+}
+
+PMVector PM2DControlPoint::to2D( const PMVector& v ) const
+{
+ PMVector result( 2 );
+ switch( m_type )
+ {
+ case PM2DXY:
+ result[0] = v[0];
+ result[1] = v[1];
+ break;
+ case PM2DXZ:
+ result[0] = v[0];
+ result[1] = v[2];
+ break;
+ case PM2DYZ:
+ result[0] = v[1];
+ result[1] = v[2];
+ break;
+ case PM2DYX:
+ result[0] = v[1];
+ result[1] = v[0];
+ break;
+ case PM2DZX:
+ result[0] = v[2];
+ result[1] = v[0];
+ break;
+ case PM2DZY:
+ result[0] = v[2];
+ result[1] = v[1];
+ break;
+ }
+ if( !approxZero( m_scale ) )
+ result /= m_scale;
+ return result;
+}
+
+PMVector PM2DControlPoint::to3D( const PMVector& v ) const
+{
+ PMVector vec( v * m_scale );
+ PMVector result( 3 );
+ switch( m_type )
+ {
+ case PM2DXY:
+ result[0] = vec[0];
+ result[1] = vec[1];
+ result[2] = m_thirdCoordinate;
+ break;
+ case PM2DXZ:
+ result[0] = vec[0];
+ result[1] = m_thirdCoordinate;
+ result[2] = vec[1];
+ break;
+ case PM2DYZ:
+ result[0] = m_thirdCoordinate;
+ result[1] = vec[0];
+ result[2] = vec[1];
+ break;
+ case PM2DYX:
+ result[1] = vec[0];
+ result[0] = vec[1];
+ result[2] = m_thirdCoordinate;
+ break;
+ case PM2DZX:
+ result[2] = vec[0];
+ result[0] = vec[1];
+ result[1] = m_thirdCoordinate;
+ break;
+ case PM2DZY:
+ result[2] = vec[0];
+ result[1] = vec[1];
+ result[0] = m_thirdCoordinate;
+ break;
+ }
+ return result;
+}
+
+void PM2DControlPoint::addLinkedPoint( PM2DControlPoint* p )
+{
+ if( !m_linkedPoints.containsRef( p ) )
+ m_linkedPoints.append( p );
+}
+
+void PM2DControlPoint::removeLinkedPoint( PM2DControlPoint* p )
+{
+ m_linkedPoints.removeRef( p );
+}
diff --git a/kpovmodeler/pm2dcontrolpoint.h b/kpovmodeler/pm2dcontrolpoint.h
new file mode 100644
index 00000000..f949570b
--- /dev/null
+++ b/kpovmodeler/pm2dcontrolpoint.h
@@ -0,0 +1,135 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PM2DCONTROLPOINT_H
+#define PM2DCONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "pmcontrolpoint.h"
+#include <qptrlist.h>
+
+/**
+ * Class for free moveable control points
+ */
+class PM2DControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Type enum
+ */
+ enum CPType { PM2DXY, PM2DYX, PM2DXZ, PM2DZX, PM2DYZ, PM2DZY };
+ /**
+ * Creates a PM2DControlPoint with id. Point has to be a 2D vector.
+ */
+ PM2DControlPoint( const PMVector& point, CPType type,
+ int id, const QString& description );
+ /**
+ * Deletes the PM2DControlPoint
+ */
+ virtual ~PM2DControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const { return to3D( m_point ); }
+ /**
+ * Sets the 2d coordinates of the control point
+ */
+ void setPoint( const PMVector& newPoint ) { m_point = newPoint; }
+ /**
+ * 2d coordinates of the control point
+ */
+ PMVector point( ) const { return m_point; }
+ /** */
+ virtual void snapToGrid( );
+ /**
+ * Returns the third coordinate
+ */
+ double thirdCoordinate( ) const { return m_thirdCoordinate; }
+ /**
+ * Sets the third coordinate
+ */
+ void setThirdCoordinate( double d ) { m_thirdCoordinate = d; }
+ /**
+ * Returns the 2d scale
+ */
+ double scale( ) const { return m_scale; }
+ /**
+ * Sets the scale
+ */
+ void setScale( double s ) { m_scale = s; }
+
+ /**
+ * Sets the base point.
+ *
+ * If a base point is set, an extra line is shown between
+ * the base point and this control point.
+ */
+ void setBasePoint( PM2DControlPoint* p );
+ /**
+ * Returns the base point
+ */
+ PM2DControlPoint* basePoint( ) const { return m_pBasePoint; }
+ /**
+ * This method is used by the lathe object to link
+ * the control points in the xy and xz plane. These points are
+ * synchronized if both are selected.
+ */
+ void setLatheLink( PM2DControlPoint* p ) { m_pLatheLink = p; }
+ /**
+ * Returns the linked control point for lathe points
+ */
+ PM2DControlPoint* latheLink( ) const { return m_pLatheLink; }
+
+ /** */
+ virtual bool hasExtraLine( ) const { return m_pBasePoint; }
+ /** */
+ virtual PMVector extraLineStart( ) const { return position( ); }
+ /** */
+ virtual PMVector extraLineEnd( ) const
+ {
+ if( m_pBasePoint )
+ return m_pBasePoint->position( );
+ return PMVector( 0, 0, 0 );
+ }
+
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ PMVector to2D( const PMVector& v ) const;
+ PMVector to3D( const PMVector& v ) const;
+ void addLinkedPoint( PM2DControlPoint* p );
+ void removeLinkedPoint( PM2DControlPoint* p );
+
+ PMVector m_point, m_originalPoint, m_original2DPoint;
+ CPType m_type;
+ double m_thirdCoordinate;
+ double m_scale;
+ PM2DControlPoint* m_pBasePoint;
+ QPtrList<PM2DControlPoint> m_linkedPoints;
+ PM2DControlPoint* m_pLatheLink;
+};
+
+#endif
diff --git a/kpovmodeler/pm3dcontrolpoint.cpp b/kpovmodeler/pm3dcontrolpoint.cpp
new file mode 100644
index 00000000..7bd4e10e
--- /dev/null
+++ b/kpovmodeler/pm3dcontrolpoint.cpp
@@ -0,0 +1,49 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pm3dcontrolpoint.h"
+#include "pmmath.h"
+#include <math.h>
+
+PM3DControlPoint::PM3DControlPoint( const PMVector& point, int id,
+ const QString& description )
+ : PMControlPoint( id, description )
+{
+ m_point = point;
+}
+
+void PM3DControlPoint::graphicalChangeStarted( )
+{
+ m_originalPoint = m_point;
+}
+
+void PM3DControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& /*viewNormal*/,
+ const PMVector& endPoint )
+{
+ m_point = m_originalPoint + endPoint - startPoint;
+}
+
+void PM3DControlPoint::snapToGrid( )
+{
+ int i;
+ double d = moveGrid( );
+ if( !approxZero( d ) )
+ for( i = 0; i < 3; i++ )
+ m_point[i] = rint( m_point[i] / d ) * d;
+ setChanged( );
+}
diff --git a/kpovmodeler/pm3dcontrolpoint.h b/kpovmodeler/pm3dcontrolpoint.h
new file mode 100644
index 00000000..765c4e43
--- /dev/null
+++ b/kpovmodeler/pm3dcontrolpoint.h
@@ -0,0 +1,68 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PM3DCONTROLPOINT_H
+#define PM3DCONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "pmcontrolpoint.h"
+
+/**
+ * Class for free moveable control points
+ */
+class PM3DControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Creates a PM3DControlPoint with id.
+ */
+ PM3DControlPoint( const PMVector& point, int id, const QString& description );
+ /**
+ * Deletes the PM3DControlPoint
+ */
+ virtual ~PM3DControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const { return m_point; }
+ /**
+ * Sets the 3d coordinates of the control point
+ */
+ void setPoint( const PMVector& newPoint ) { m_point = newPoint; }
+ /**
+ * 3d coordinates of the control point
+ */
+ PMVector point( ) const { return m_point; }
+ /** */
+ virtual void snapToGrid( );
+
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ PMVector m_point, m_originalPoint;
+};
+
+#endif
diff --git a/kpovmodeler/pmactions.cpp b/kpovmodeler/pmactions.cpp
new file mode 100644
index 00000000..b84e42da
--- /dev/null
+++ b/kpovmodeler/pmactions.cpp
@@ -0,0 +1,254 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmactions.h"
+
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <qstyle.h>
+#include <qpainter.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+
+#include "pmdebug.h"
+
+// Fixed widths are calculated wrong in a toolbar.
+// Fixed sizeHint for the combo box to return
+// at least the minimum size
+class PMComboBox : public QComboBox
+{
+public:
+ PMComboBox( QWidget* parent, const char* name = 0 )
+ : QComboBox( parent, name )
+ {
+ }
+
+ virtual QSize minimumSizeHint( ) const
+ {
+ QSize s = QComboBox::minimumSizeHint( );
+ return s.expandedTo( minimumSize( ) );
+ }
+ virtual QSize sizeHint( ) const
+ {
+ QSize s = QComboBox::sizeHint( );
+ return s.expandedTo( minimumSize( ) );
+ }
+};
+
+PMComboAction::PMComboAction( const QString& text, int accel, const QObject* receiver, const char* member,
+ QObject* parent, const char* name )
+ : KAction( text, accel, parent, name )
+{
+ m_receiver = receiver;
+ m_member = member;
+ m_minWidth = 0;
+ m_maxWidth = 0;
+}
+
+PMComboAction::~PMComboAction( )
+{
+}
+
+int PMComboAction::plug( QWidget* w, int index )
+{
+ if( !w->inherits( "KToolBar" ) )
+ return -1;
+
+ KToolBar* toolBar = ( KToolBar* ) w;
+
+ int id = KAction::getToolButtonID( );
+
+ QComboBox* comboBox = new PMComboBox( toolBar );
+ if( m_minWidth > 0 )
+ comboBox->setMinimumWidth( m_minWidth );
+ if( m_maxWidth > 0 )
+ comboBox->setMaximumWidth( m_maxWidth );
+
+ toolBar->insertWidget( id, m_minWidth > 0 ? m_minWidth : 300,
+ comboBox, index );
+ connect( comboBox, SIGNAL( activated( int ) ), m_receiver, m_member );
+
+ addContainer( toolBar, id );
+
+ connect( toolBar, SIGNAL( destroyed( ) ), this, SLOT( slotDestroyed( ) ) );
+
+ //toolBar->setItemAutoSized( id, true );
+
+ m_combo = comboBox;
+
+ emit plugged( );
+
+ QWhatsThis::add( comboBox, whatsThis( ) );
+
+ return containerCount( ) - 1;
+}
+
+void PMComboAction::unplug( QWidget *w )
+{
+ if( !w->inherits( "KToolBar" ) )
+ return;
+
+ KToolBar *toolBar = ( KToolBar* ) w;
+
+ int idx = findContainer( w );
+
+ toolBar->removeItem( itemId( idx ) );
+
+ removeContainer( idx );
+ m_combo = 0L;
+}
+
+
+// Use a toolbutton instead of a label so it is styled correctly.
+// copied from konq_actions.cc
+class PMToolBarLabel : public QToolButton
+{
+public:
+ PMToolBarLabel( const QString& text, QWidget* parent = 0, const char* name = 0 )
+ : QToolButton( parent, name )
+ {
+ setText( text );
+ }
+protected:
+ QSize sizeHint( ) const
+ {
+ int w = fontMetrics( ).width( text( ) );
+ int h = fontMetrics( ).height( );
+ return QSize( w, h );
+ }
+ void drawButton( QPainter* p )
+ {
+#if ( QT_VERSION >= 300 )
+ // Draw the background
+ style( ).drawComplexControl( QStyle::CC_ToolButton, p, this, rect( ), colorGroup( ),
+ QStyle::Style_Enabled, QStyle::SC_ToolButton );
+ // Draw the label
+ style( ).drawControl( QStyle::CE_ToolButtonLabel, p, this, rect( ), colorGroup( ),
+ QStyle::Style_Enabled );
+#else
+ p->drawText( rect( ), Qt::AlignVCenter | Qt::AlignLeft, text( ) );
+#endif
+ }
+};
+
+PMLabelAction::PMLabelAction( const QString &text, QObject *parent, const char *name )
+ : KAction( text, 0, parent, name )
+{
+ m_button = 0;
+}
+
+int PMLabelAction::plug( QWidget *widget, int index )
+{
+ //do not call the previous implementation here
+
+ if( widget->inherits( "KToolBar" ) )
+ {
+ KToolBar* tb = ( KToolBar* ) widget;
+
+ int id = KAction::getToolButtonID( );
+
+ m_button = new PMToolBarLabel( text( ), widget );
+ tb->insertWidget( id, m_button->width( ), m_button, index );
+
+ addContainer( tb, id );
+
+ connect( tb, SIGNAL( destroyed( ) ), this, SLOT( slotDestroyed( ) ) );
+
+ return containerCount( ) - 1;
+ }
+
+ return -1;
+}
+
+void PMLabelAction::unplug( QWidget *widget )
+{
+ if( widget->inherits( "KToolBar" ) )
+ {
+ KToolBar* bar = ( KToolBar* ) widget;
+
+ int idx = findContainer( bar );
+
+ if( idx != -1 )
+ {
+ bar->removeItem( itemId( idx ) );
+ removeContainer( idx );
+ }
+
+ m_button = 0;
+ return;
+ }
+}
+
+
+PMSpinBoxAction::PMSpinBoxAction( const QString& text, int accel, const QObject* receiver, const char* member,
+ QObject* parent, const char* name )
+ : KAction( text, accel, parent, name )
+{
+ m_receiver = receiver;
+ m_member = member;
+}
+
+PMSpinBoxAction::~PMSpinBoxAction( )
+{
+}
+
+int PMSpinBoxAction::plug( QWidget* w, int index )
+{
+ if( !w->inherits( "KToolBar" ) )
+ return -1;
+
+ KToolBar* toolBar = ( KToolBar* ) w;
+
+ int id = KAction::getToolButtonID( );
+
+ QSpinBox* spinBox = new QSpinBox( -1000, 1000, 1, w );
+ toolBar->insertWidget( id, 70, spinBox, index );
+
+ connect( spinBox, SIGNAL( valueChanged( int ) ), m_receiver, m_member );
+
+ addContainer( toolBar, id );
+
+ connect( toolBar, SIGNAL( destroyed( ) ), this, SLOT( slotDestroyed( ) ) );
+ //toolBar->setItemAutoSized( id, false );
+
+ m_spinBox = spinBox;
+
+ emit plugged( );
+
+ QWhatsThis::add( spinBox, whatsThis( ) );
+
+ return containerCount( ) - 1;
+}
+
+void PMSpinBoxAction::unplug( QWidget *w )
+{
+ if( !w->inherits( "KToolBar" ) )
+ return;
+
+ KToolBar *toolBar = (KToolBar *)w;
+
+ int idx = findContainer( w );
+
+ toolBar->removeItem( itemId( idx ) );
+
+ removeContainer( idx );
+ m_spinBox = 0L;
+}
+
+#include "pmactions.moc"
diff --git a/kpovmodeler/pmactions.h b/kpovmodeler/pmactions.h
new file mode 100644
index 00000000..f4f8e9e4
--- /dev/null
+++ b/kpovmodeler/pmactions.h
@@ -0,0 +1,106 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMACTIONS_H
+#define PMACTIONS_H
+
+#include <qguardedptr.h>
+#include <kaction.h>
+
+class QComboBox;
+class QSpinBox;
+class QLabel;
+class QToolButton;
+
+/**
+ * Combobox action for the toolbar.
+ *
+ * Copied from konq_actions.h, author: Simon Hausmann <hausmann@kde.org>
+ */
+class PMComboAction : public KAction
+{
+ Q_OBJECT
+public:
+ PMComboAction( const QString& text, int accel, const QObject* receiver, const char* member, QObject* parent, const char* name );
+ ~PMComboAction( );
+
+ virtual int plug( QWidget* w, int index = -1 );
+
+ virtual void unplug( QWidget* w );
+
+ QGuardedPtr<QComboBox> combo( ) { return m_combo; }
+
+ void setMaximumWidth( int w ) { m_maxWidth = w; }
+ void setMinimumWidth( int w ) { m_minWidth = w; }
+
+signals:
+ void plugged( );
+
+private:
+ QGuardedPtr<QComboBox> m_combo;
+ const QObject* m_receiver;
+ const char* m_member;
+ int m_minWidth, m_maxWidth;
+};
+
+/**
+ * Label action for the toolbar.
+ *
+ * Copied from konq_actions.h, author: Simon Hausmann <hausmann@kde.org>
+ */
+class PMLabelAction : public KAction
+{
+ Q_OBJECT
+public:
+ PMLabelAction( const QString &text, QObject *parent = 0, const char *name = 0 );
+
+ virtual int plug( QWidget *widget, int index = -1 );
+ virtual void unplug( QWidget *widget );
+ QToolButton* button( ) { return m_button; }
+
+private:
+ QToolButton* m_button;
+};
+
+/**
+ * Spinbox action for the toolbar.
+ */
+class PMSpinBoxAction : public KAction
+{
+ Q_OBJECT
+public:
+ PMSpinBoxAction( const QString& text, int accel, const QObject* receiver, const char* member, QObject* parent, const char* name );
+ ~PMSpinBoxAction( );
+
+ virtual int plug( QWidget* w, int index = -1 );
+ virtual void unplug( QWidget* w );
+
+ QGuardedPtr<QSpinBox> spinBox( ) { return m_spinBox; }
+
+signals:
+ void plugged( );
+
+private:
+ QGuardedPtr<QSpinBox> m_spinBox;
+ const QObject* m_receiver;
+ const char* m_member;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmaddcommand.cpp b/kpovmodeler/pmaddcommand.cpp
new file mode 100644
index 00000000..b8d4ea49
--- /dev/null
+++ b/kpovmodeler/pmaddcommand.cpp
@@ -0,0 +1,233 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmaddcommand.h"
+#include "pmcommandmanager.h"
+#include "pmpart.h"
+#include "pmdeclare.h"
+#include "pmerrorflags.h"
+#include "pmrecursiveobjectiterator.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+PMAddCommand::PMAddCommand( PMObject* obj, PMObject* parent, PMObject* after )
+ : PMCommand( i18n( "Add New %1" ).arg( obj->description( ) ) )
+{
+ m_objects.append( obj );
+ m_pParent = parent;
+ m_pAfter = after;
+ m_executed = false;
+ m_firstExecution = true;
+ m_linksCreated = false;
+ m_pParentChangeMemento = 0;
+}
+
+PMAddCommand::PMAddCommand( const PMObjectList& list, PMObject* parent,
+ PMObject* after )
+ : PMCommand( i18n( "Add Objects" ) )
+{
+ m_objects = list;
+ m_pParent = parent;
+ m_pAfter = after;
+ m_executed = false;
+ m_firstExecution = true;
+ m_linksCreated = false;
+ m_pParentChangeMemento = 0;
+}
+
+PMAddCommand::~PMAddCommand( )
+{
+ if( !m_executed )
+ {
+ m_objects.setAutoDelete( true );
+ m_objects.clear( );
+ }
+
+ m_insertErrors.setAutoDelete( true );
+ m_insertErrors.clear( );
+}
+
+void PMAddCommand::execute( PMCommandManager* theManager )
+{
+ if( !m_executed )
+ {
+ PMObjectListIterator it( m_objects );
+ PMObject* prev = m_pAfter;
+ PMObjectList errors;
+ PMObject* current;
+ bool error = false;
+
+ if( m_firstExecution )
+ if( m_pParent->dataChangeOnInsertRemove( ) )
+ m_pParent->createMemento( );
+
+ for( ; it.current( ); ++it )
+ {
+ current = it.current( );
+ if( !prev )
+ {
+ if( m_pParent->canInsert( current, 0 ) )
+ {
+ m_pParent->insertChild( current, 0 );
+ prev = current;
+ theManager->cmdObjectChanged( current, PMCAdd );
+ }
+ else
+ error = true;
+ }
+ else
+ {
+ if( m_pParent->canInsert( current, prev ) )
+ {
+ m_pParent->insertChildAfter( current, prev );
+ prev = current;
+ theManager->cmdObjectChanged( current, PMCAdd );
+ }
+ else
+ error = true;
+ }
+
+ if( error )
+ {
+ errors.append( current );
+ theManager->cmdObjectChanged( current, PMCAdd | PMCInsertError );
+ if( current->isA( "Declare" ) )
+ {
+ // the object, that couldn't be inserted was a declare,
+ // remove all links
+ PMObjectListIterator links =
+ ( ( PMDeclare* ) current )->linkedObjects( );
+ for( ; links.current( ); ++links )
+ {
+ PMObject* l = links.current( );
+ if( l->parent( ) )
+ l->parent( )->takeChild( l );
+ else
+ m_objects.removeRef( l );
+ m_insertErrors.append( l );
+ }
+ }
+ if( current->linkedObject( ) )
+ current->linkedObject( )->removeLinkedObject( current );
+ error = false;
+ }
+ }
+
+ if( m_pParent->mementoCreated( ) )
+ m_pParentChangeMemento = m_pParent->takeMemento( );
+
+ if( m_pParentChangeMemento )
+ {
+ PMObjectChangeListIterator c = m_pParentChangeMemento->changedObjects( );
+ for( ; c.current( ); ++c )
+ theManager->cmdObjectChanged( c.current( )->object( ),
+ c.current( )->mode( ) );
+ }
+
+ if( m_linksCreated )
+ {
+ PMObjectListIterator rit( m_links );
+ for( ; rit.current( ); ++rit )
+ rit.current( )->linkedObject( )->addLinkedObject( rit.current( ) );
+ PMObjectListIterator dit( m_linkedDeclares );
+ for( ; dit.current( ); ++dit )
+ theManager->cmdObjectChanged( dit.current( ), PMCData );
+ }
+
+ PMObjectListIterator errorit( errors );
+ for( ; errorit.current( ); ++errorit )
+ {
+ m_objects.removeRef( errorit.current( ) );
+ m_insertErrors.append( errorit.current( ) );
+
+ PMRecursiveObjectIterator lit( errorit.current( ) );
+ for( ; lit.current( ); ++lit )
+ if( lit.current( )->linkedObject( ) )
+ lit.current( )->linkedObject( )->removeLinkedObject( lit.current( ) );
+ }
+
+ m_executed = true;
+ m_firstExecution = false;
+ }
+}
+
+void PMAddCommand::undo( PMCommandManager* theManager )
+{
+ if( m_executed )
+ {
+ PMObjectListIterator it( m_objects );
+ PMObject* obj;
+ PMDeclare* decl;
+
+ if( !m_linksCreated )
+ {
+ for( ; it.current( ); ++it )
+ {
+ PMRecursiveObjectIterator lit( it.current( ) );
+ for( ; lit.current( ); ++lit )
+ {
+ decl = lit.current( )->linkedObject( );
+ if( decl )
+ {
+ m_links.append( lit.current( ) );
+ if( !m_linkedDeclares.containsRef( decl ) )
+ m_linkedDeclares.append( decl );
+ }
+ }
+ }
+ m_linksCreated = true;
+ }
+
+ PMObjectListIterator rit( m_links );
+ for( ; rit.current( ); ++rit )
+ rit.current( )->linkedObject( )->removeLinkedObject( rit.current( ) );
+
+ for( it.toLast( ) ; it.current( ); --it )
+ {
+ obj = it.current( );
+ // signal has to be emitted before the item is removed
+ theManager->cmdObjectChanged( obj, PMCRemove );
+
+ if( obj->parent( ) )
+ obj->parent( )->takeChild( obj );
+ }
+
+ if( m_pParentChangeMemento )
+ {
+ m_pParent->restoreMemento( m_pParentChangeMemento );
+ PMObjectChangeListIterator c = m_pParentChangeMemento->changedObjects( );
+ for( ; c.current( ); ++c )
+ {
+ theManager->cmdObjectChanged( c.current( )->object( ),
+ c.current( )->mode( ) );
+ }
+ }
+
+ PMObjectListIterator dit( m_linkedDeclares );
+ for( ; dit.current( ); ++dit )
+ theManager->cmdObjectChanged( dit.current( ), PMCData );
+
+ m_executed = false;
+ }
+}
+
+int PMAddCommand::errorFlags( PMPart* )
+{
+ return PMENone;
+}
diff --git a/kpovmodeler/pmaddcommand.h b/kpovmodeler/pmaddcommand.h
new file mode 100644
index 00000000..97793d03
--- /dev/null
+++ b/kpovmodeler/pmaddcommand.h
@@ -0,0 +1,87 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMADDCOMMAND_H
+#define PMADDCOMMAND_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcommand.h"
+#include "pmobject.h"
+
+class PMMemento;
+
+/**
+ * Command class for adding a new PMObject
+ */
+class PMAddCommand : public PMCommand
+{
+public:
+ /**
+ * Command that adds a new PMObject.
+ *
+ * The object obj will be inserted as child of parent after
+ * the object after.
+ *
+ * If after is 0, the object becomes the first child.
+ */
+ PMAddCommand( PMObject* obj, PMObject* parent, PMObject* after );
+
+ /**
+ * Command that adds a list of new PMObjects.
+ *
+ * The object in the list will be inserted as children of parent after
+ * the object after.
+ *
+ * If after is 0, the objects will be inserted as first children.
+ */
+ PMAddCommand( const PMObjectList& list, PMObject* parent, PMObject* after );
+ /**
+ * Deletes the command. The inserted object will be deleted, if
+ the command was not executed (or undo-ed) */
+ virtual ~PMAddCommand( );
+
+ /** */
+ virtual int errorFlags( PMPart* );
+
+protected:
+ /**
+ * Executes the command and stores undo information
+ */
+ virtual void execute( PMCommandManager* theManager );
+ /**
+ * Undo the command
+ */
+ virtual void undo( PMCommandManager* theManager );
+
+private:
+ PMObject* m_pParent;
+ PMObjectList m_objects;
+ PMObject* m_pAfter;
+ bool m_executed, m_firstExecution;
+ PMObjectList m_insertErrors;
+ PMObjectList m_links;
+ PMObjectList m_linkedDeclares;
+ bool m_linksCreated;
+ PMMemento* m_pParentChangeMemento;
+};
+
+#endif
diff --git a/kpovmodeler/pmallcommands.h b/kpovmodeler/pmallcommands.h
new file mode 100644
index 00000000..014b5a04
--- /dev/null
+++ b/kpovmodeler/pmallcommands.h
@@ -0,0 +1,27 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMALLCOMMANDS_H
+#define PMALLCOMMANDS_H
+
+#include "pmaddcommand.h"
+#include "pmdeletecommand.h"
+#include "pmmovecommand.h"
+
+#endif
diff --git a/kpovmodeler/pmalledits.h b/kpovmodeler/pmalledits.h
new file mode 100644
index 00000000..e1ee4a5a
--- /dev/null
+++ b/kpovmodeler/pmalledits.h
@@ -0,0 +1,25 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMALLEDITS_H
+#define PMALLEDITS_H
+
+#include "pmboxedit.h"
+
+#endif
diff --git a/kpovmodeler/pmallobjects.h b/kpovmodeler/pmallobjects.h
new file mode 100644
index 00000000..3a02107c
--- /dev/null
+++ b/kpovmodeler/pmallobjects.h
@@ -0,0 +1,106 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMALLOBJECTS_H
+#define PMALLOBJECTS_H
+
+#include "pmscene.h"
+#include "pmglobalsettings.h"
+
+#include "pmbox.h"
+#include "pmsphere.h"
+#include "pmcylinder.h"
+#include "pmcone.h"
+#include "pmtorus.h"
+#include "pmlathe.h"
+#include "pmprism.h"
+#include "pmsor.h"
+#include "pmsqe.h"
+#include "pmheightfield.h"
+#include "pmtext.h"
+#include "pmjuliafractal.h"
+
+#include "pmblob.h"
+#include "pmblobsphere.h"
+#include "pmblobcylinder.h"
+
+#include "pmplane.h"
+#include "pmpolynom.h"
+
+#include "pmdeclare.h"
+#include "pmobjectlink.h"
+
+#include "pmcsg.h"
+
+#include "pmdisc.h"
+#include "pmbicubicpatch.h"
+#include "pmtriangle.h"
+
+#include "pmboundedby.h"
+#include "pmclippedby.h"
+
+#include "pmcamera.h"
+
+#include "pmtranslate.h"
+#include "pmscale.h"
+#include "pmrotate.h"
+#include "pmpovraymatrix.h"
+
+#include "pmlight.h"
+#include "pmlookslike.h"
+#include "pmprojectedthrough.h"
+
+#include "pmtexture.h"
+#include "pmpigment.h"
+#include "pmsolidcolor.h"
+#include "pmlistpattern.h"
+#include "pmquickcolor.h"
+#include "pmnormal.h"
+#include "pmfinish.h"
+#include "pmpattern.h"
+#include "pmblendmapmodifiers.h"
+#include "pmimagemap.h"
+#include "pmbumpmap.h"
+#include "pmtexturemap.h"
+#include "pmmaterialmap.h"
+#include "pmwarp.h"
+#include "pmslope.h"
+#include "pmdensity.h"
+
+#include "pmskysphere.h"
+#include "pmrainbow.h"
+#include "pmfog.h"
+#include "pminterior.h"
+#include "pmmedia.h"
+#include "pmmaterial.h"
+
+#include "pmcomment.h"
+#include "pmraw.h"
+
+// POV-Ray 3.5 objects
+#include "pmisosurface.h"
+#include "pmradiosity.h"
+#include "pmglobalphotons.h"
+#include "pmphotons.h"
+#include "pmlightgroup.h"
+#include "pminteriortexture.h"
+#include "pmspheresweep.h"
+#include "pmmesh.h"
+
+#endif
diff --git a/kpovmodeler/pmbicubicpatch.cpp b/kpovmodeler/pmbicubicpatch.cpp
new file mode 100644
index 00000000..cbc633a9
--- /dev/null
+++ b/kpovmodeler/pmbicubicpatch.cpp
@@ -0,0 +1,544 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmbicubicpatch.h"
+
+#include "pmxmlhelper.h"
+#include "pmbicubicpatchedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm3dcontrolpoint.h"
+#include "pmmath.h"
+
+#include <klocale.h>
+
+const double c_defaultPatchSize = 6.0;
+const int c_defaultPatchType = 0;
+const int c_defaultPatchUSteps = 3;
+const int c_defaultPatchVSteps = 3;
+const double c_defaultPatchFlatness = 0;
+const PMVector c_defaultUVVector0 = PMVector( 0.0, 0.0 );
+const PMVector c_defaultUVVector1 = PMVector( 1.0, 0.0 );
+const PMVector c_defaultUVVector2 = PMVector( 1.0, 1.0 );
+const PMVector c_defaultUVVector3 = PMVector( 0.0, 1.0 );
+
+PMDefinePropertyClass( PMBicubicPatch, PMBicubicPatchProperty );
+
+class PMPointProperty : public PMPropertyBase
+{
+public:
+ PMPointProperty( )
+ : PMPropertyBase( "controlPoints", PMVariant::Vector )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ if( index < 0 || index > 15 )
+ kdError( PMArea ) << "Illegal index in PMBicubicPatch::PointProperty::setIndex" << endl;
+ else
+ m_index = index;
+ }
+ virtual int size( PMObject* /*object*/, int /*dimension*/ ) const
+ {
+ return 16;
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& v )
+ {
+ PMBicubicPatch* p = ( PMBicubicPatch* ) obj;
+ p->setControlPoint( m_index, v.vectorData( ) );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ const PMBicubicPatch* p = ( const PMBicubicPatch* ) obj;
+ return PMVariant( p->controlPoint( m_index ) );
+ }
+
+private:
+ int m_index;
+};
+
+class PMUVVectorProperty : public PMPropertyBase
+{
+public:
+ PMUVVectorProperty( )
+ : PMPropertyBase( "uvVectors", PMVariant::Vector )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ if( index < 0 || index > 3 )
+ kdError( PMArea ) << "Illegal index in PMBicubicPatch::UVVectorProperty::setIndex" << endl;
+ else
+ m_index = index;
+ }
+ virtual int size( PMObject* /*object*/, int /*dimension*/ ) const
+ {
+ return 3;
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& v )
+ {
+ PMBicubicPatch* p = ( PMBicubicPatch* ) obj;
+ p->setUVVector( m_index, v.vectorData( ) );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ const PMBicubicPatch* p = ( const PMBicubicPatch* ) obj;
+ return PMVariant( p->uvVector( m_index ) );
+ }
+
+private:
+ int m_index;
+};
+
+PMMetaObject* PMBicubicPatch::s_pMetaObject = 0;
+PMObject* createNewBicubicPatch( PMPart* part )
+{
+ return new PMBicubicPatch( part );
+}
+
+PMBicubicPatch::PMBicubicPatch( PMPart* part )
+ : Base( part )
+{
+ int x, z;
+ double o = -c_defaultPatchSize / 2.0, s = c_defaultPatchSize / 3.0;
+ m_patchType = c_defaultPatchType;
+ m_numUSteps = c_defaultPatchUSteps;
+ m_numVSteps = c_defaultPatchVSteps;
+ m_flatness = c_defaultPatchFlatness;
+ for( x = 0; x < 4; x++ )
+ for( z = 0; z < 4; z++ )
+ m_point[x+z*4] = PMVector( o + s * x, 0, o + s * z );
+ m_vsUSteps = 0;
+ m_vsVSteps = 0;
+ m_uvEnabled = false;
+ m_uvVectors[0] = c_defaultUVVector0;
+ m_uvVectors[1] = c_defaultUVVector1;
+ m_uvVectors[2] = c_defaultUVVector2;
+ m_uvVectors[3] = c_defaultUVVector3;
+}
+
+PMBicubicPatch::PMBicubicPatch( const PMBicubicPatch& p )
+ : Base( p )
+{
+ int i;
+ m_patchType = p.m_patchType;
+ m_numUSteps = p.m_numUSteps;
+ m_numVSteps = p.m_numVSteps;
+ m_flatness = p.m_flatness;
+ for( i = 0; i < 16; i++ )
+ m_point[i] = p.m_point[i];
+ m_vsUSteps = 0;
+ m_vsVSteps = 0;
+ m_uvEnabled = p.m_uvEnabled;
+ for( i = 0; i < 4; ++i )
+ m_uvVectors[i] = p.m_uvVectors[i];
+}
+
+PMBicubicPatch::~PMBicubicPatch( )
+{
+}
+
+QString PMBicubicPatch::description( ) const
+{
+ return i18n( "bicubic patch" );
+}
+
+void PMBicubicPatch::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ int i;
+
+ e.setAttribute( "type", m_patchType );
+ e.setAttribute( "flatness", m_flatness );
+ e.setAttribute( "uSteps", m_numUSteps );
+ e.setAttribute( "vSteps", m_numVSteps );
+ e.setAttribute( "uvEnabled", m_uvEnabled );
+
+ for( i = 0; i < 16; i++ )
+ e.setAttribute( QString( "cp%1" ).arg( i ), m_point[i].serializeXML( ) );
+
+ for( i = 0; i < 4; ++i )
+ e.setAttribute( QString( "uv%1" ).arg( i ), m_uvVectors[i].serializeXML( ) );
+
+ Base::serialize( e, doc );
+}
+
+void PMBicubicPatch::readAttributes( const PMXMLHelper& h )
+{
+ int u, v;
+ double o = -c_defaultPatchSize / 2.0, s = c_defaultPatchSize / 3.0;
+
+ m_patchType = h.intAttribute( "type", c_defaultPatchType );
+ m_flatness = h.doubleAttribute( "flatness", c_defaultPatchFlatness );
+ m_numUSteps = h.intAttribute( "uSteps", c_defaultPatchUSteps );
+ m_numVSteps = h.intAttribute( "vSteps", c_defaultPatchVSteps );
+ m_uvEnabled = h.boolAttribute( "uvEnabled", m_uvEnabled );
+
+ for( v = 0; v < 4; v++ )
+ for( u = 0; u < 4; u++ )
+ m_point[u+v*4] = h.vectorAttribute( QString( "cp%1" ).arg( u+v*4 ),
+ PMVector( o + s * u, 0, o + s * v ) );
+
+ m_uvVectors[0] = h.vectorAttribute( "uv0", c_defaultUVVector0 );
+ m_uvVectors[1] = h.vectorAttribute( "uv1", c_defaultUVVector1 );
+ m_uvVectors[2] = h.vectorAttribute( "uv2", c_defaultUVVector2 );
+ m_uvVectors[3] = h.vectorAttribute( "uv3", c_defaultUVVector3 );
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMBicubicPatch::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "BicubicPatch", Base::metaObject( ),
+ createNewBicubicPatch );
+ s_pMetaObject->addProperty(
+ new PMBicubicPatchProperty( "patchType", &PMBicubicPatch::setPatchType,
+ &PMBicubicPatch::patchType ) );
+ s_pMetaObject->addProperty(
+ new PMBicubicPatchProperty( "uSteps", &PMBicubicPatch::setUSteps,
+ &PMBicubicPatch::uSteps ) );
+ s_pMetaObject->addProperty(
+ new PMBicubicPatchProperty( "vSteps", &PMBicubicPatch::setVSteps,
+ &PMBicubicPatch::vSteps ) );
+ s_pMetaObject->addProperty(
+ new PMBicubicPatchProperty( "flatness", &PMBicubicPatch::setFlatness,
+ &PMBicubicPatch::flatness ) );
+ s_pMetaObject->addProperty(
+ new PMBicubicPatchProperty( "uvEnabled", &PMBicubicPatch::enableUV,
+ &PMBicubicPatch::isUVEnabled ) );
+ s_pMetaObject->addProperty( new PMPointProperty( ) );
+ s_pMetaObject->addProperty( new PMUVVectorProperty( ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMBicubicPatch::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMBicubicPatch::setPatchType( int patchType )
+{
+ if( ( patchType == 0 ) || ( patchType == 1 ) )
+ {
+ if( patchType != m_patchType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMTypeID, m_patchType );
+ m_patchType = patchType;
+ }
+ }
+ else
+ kdError( PMArea ) << "Wrong type in PMBicubicPatch::setPatchType( )\n";
+}
+
+void PMBicubicPatch::setFlatness( double flatness )
+{
+ if( flatness >= 0.0 )
+ {
+ if( flatness != m_flatness )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFlatnessID, m_flatness );
+ m_flatness = flatness;
+ }
+ }
+ else
+ kdError( PMArea ) << "Flatness has to be >= 0 in PMBicubicPatch::setFlatness( )\n";
+}
+
+void PMBicubicPatch::setUSteps( int steps )
+{
+ if( steps >= 0 )
+ {
+ if( steps != m_numUSteps )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUStepsID, m_numUSteps );
+ m_numUSteps = steps;
+ setViewStructureChanged( );
+ }
+ }
+ else
+ kdError( PMArea ) << "uSteps has to be >= 0 in PMBicubicPatch::setUSteps( )\n";
+}
+
+void PMBicubicPatch::setVSteps( int steps )
+{
+ if( steps >= 0 )
+ {
+ if( steps != m_numVSteps )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMVStepsID, m_numVSteps );
+ m_numVSteps = steps;
+ setViewStructureChanged( );
+ }
+ }
+ else
+ kdError( PMArea ) << "vSteps has to be >= 0 in PMBicubicPatch::setVSteps( )\n";
+}
+
+void PMBicubicPatch::setControlPoint( int i, const PMVector& p )
+{
+ if( ( i >= 0 ) && ( i <= 15 ) )
+ {
+ if( p != m_point[i] )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCP0ID + i, m_point[i] );
+ m_point[i] = p;
+ setViewStructureChanged( );
+ }
+ }
+ else
+ kdError( PMArea ) << "Wrong index in PMBicubicPatch::setControlPoint( )\n";
+}
+
+PMVector PMBicubicPatch::controlPoint( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 15 ) )
+ return m_point[i];
+ else
+ kdError( PMArea ) << "Wrong index in PMBicubicPatch::controlPoint( )\n";
+ return PMVector( 0, 0, 0 );
+}
+
+void PMBicubicPatch::enableUV( bool yes )
+{
+ if( yes != m_uvEnabled )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUVEnabledID, m_uvEnabled );
+ m_uvEnabled = yes;
+ }
+}
+
+void PMBicubicPatch::setUVVector( int i, const PMVector& v )
+{
+ if ( i >= 0 && i < 4 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUV0ID + i, m_uvVectors[i] );
+ m_uvVectors[i] = v;
+ m_uvVectors[i].resize( 2 );
+ }
+ else
+ kdError( PMArea ) << "Wrong index in PMBicubicPatch::setUVVector\n";
+}
+
+PMVector PMBicubicPatch::uvVector( int i ) const
+{
+ if( i >= 0 && i < 4 )
+ return m_uvVectors[i];
+ else
+ kdError( PMArea ) << "Wrong index in PMBicubicPatch::uvVector\n";
+ return PMVector( 0.0, 0.0 );
+}
+
+PMDialogEditBase* PMBicubicPatch::editWidget( QWidget* parent ) const
+{
+ return new PMBicubicPatchEdit( parent );
+}
+
+void PMBicubicPatch::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMTypeID:
+ setPatchType( data->intData( ) );
+ break;
+ case PMFlatnessID:
+ setFlatness( data->doubleData( ) );
+ break;
+ case PMUStepsID:
+ setUSteps( data->intData( ) );
+ break;
+ case PMVStepsID:
+ setVSteps( data->intData( ) );
+ break;
+ case PMUVEnabledID:
+ enableUV( data->boolData( ) );
+ break;
+ default:
+ if( ( data->valueID( ) >= PMCP0ID ) && ( data->valueID( ) <= PMCP15ID ) )
+ setControlPoint( data->valueID( ) - PMCP0ID, data->vectorData( ) );
+ else if ( data->valueID( ) >= PMUV0ID && data->valueID( ) <= PMUV3ID )
+ setUVVector( data->valueID( ) - PMUV0ID, data->vectorData( ) );
+ else
+ kdError( PMArea ) << "Wrong ID in PMBicubicPatch::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+void PMBicubicPatch::createViewStructure( )
+{
+ int u, v, i, j;
+ int uSteps = m_numUSteps, vSteps = m_numVSteps;
+ if( uSteps > 5 ) uSteps = 5;
+ if( vSteps > 5 ) vSteps = 5;
+ if( uSteps < 0 ) uSteps = 0;
+ if( vSteps < 0 ) vSteps = 0;
+
+ // bugfix: Swap u and v
+ int segmentsU = pmpot( 2, vSteps );
+ int segmentsV = pmpot( 2, uSteps );
+
+ int np = ( segmentsU + 1 ) * ( segmentsV + 1 );
+ int nl = segmentsU * ( segmentsV + 1 ) + ( segmentsU + 1 ) * segmentsV;
+
+ int offset = 0;
+
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( np, nl );
+ m_vsUSteps = uSteps + 1;
+ }
+ else
+ {
+ if( m_pViewStructure->points( ).size( ) != ( unsigned ) np )
+ m_pViewStructure->points( ).resize( np );
+ if( m_pViewStructure->lines( ).size( ) != ( unsigned ) nl )
+ m_pViewStructure->lines( ).resize( nl );
+ }
+
+ if( ( m_vsUSteps != uSteps ) || ( m_vsVSteps != vSteps ) )
+ {
+ PMLineArray& lines = m_pViewStructure->lines( );
+ int poffset = 0;
+ for( v = 0; v < ( segmentsV + 1 ); v++ )
+ {
+ for( u = 0; u < segmentsU; u++ )
+ {
+ lines[offset + u] = PMLine( poffset, poffset + 1 );
+ poffset++;
+ }
+ poffset++;
+ offset += segmentsU;
+ }
+ poffset = 0;
+ for( v = 0; v < segmentsV; v++ )
+ {
+ for( u = 0; u < ( segmentsU + 1 ); u++ )
+ {
+ lines[offset + u] = PMLine( poffset, poffset + segmentsU + 1 );
+ poffset++;
+ }
+ offset += segmentsU + 1;
+ }
+ m_vsUSteps = uSteps;
+ m_vsVSteps = vSteps;
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+
+ offset = 0;
+ double incU = 1.0 / segmentsU;
+ double incV = 1.0 / segmentsV;
+
+ PMVector* hp[4];
+ for( v = 0; v < 4; v++ )
+ hp[v] = new PMVector[segmentsU+1];
+
+ PMVector tp[4];
+
+ double cu, cv;
+
+ // points in u direction
+ for( v = 0; v < 4; v++ )
+ {
+ for( u = 1; u < segmentsU; u++ )
+ {
+ cu = u * incU;
+
+ for( i = 0; i < 4; i++ )
+ tp[i] = m_point[v*4+i];
+ for( i = 3; i > 0; i-- )
+ for( j = 0; j < i; j++ )
+ tp[j] = tp[j] * ( 1 - cu ) + tp[j+1] * cu;
+ hp[v][u] = tp[0];
+ }
+ hp[v][0] = m_point[v*4];
+ hp[v][segmentsU] = m_point[v*4+3];
+ }
+
+ for( v = 0; v <= segmentsV; v++ )
+ {
+ cv = v * incV;
+ for( u = 0; u <= segmentsU; u++ )
+ {
+ for( i = 0; i < 4; i++ )
+ tp[i] = hp[i][u];
+ for( i = 3; i > 0; i-- )
+ for( j = 0; j < i; j++ )
+ tp[j] = tp[j] * ( 1 - cv ) + tp[j+1] * cv;
+ points[offset] = tp[0];
+ offset++;
+ }
+ }
+
+ for( v = 0; v < 4; v++ )
+ delete[] hp[v];
+}
+
+void PMBicubicPatch::controlPoints( PMControlPointList& list )
+{
+ int u, v;
+ for( v = 0; v < 4; v++ )
+ for( u = 0; u < 4; u++ )
+ list.append( new PM3DControlPoint( m_point[u+v*4], u+v*4,
+ i18n( "Point (%1, %2)" ).arg( u ).arg( v ) ) );
+}
+
+void PMBicubicPatch::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ setControlPoint( p->id( ), p->position( ) );
+ }
+ }
+}
diff --git a/kpovmodeler/pmbicubicpatch.h b/kpovmodeler/pmbicubicpatch.h
new file mode 100644
index 00000000..c7ca6b3b
--- /dev/null
+++ b/kpovmodeler/pmbicubicpatch.h
@@ -0,0 +1,188 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBICUBICPATCH_H
+#define PMBICUBICPATCH_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmgraphicalobject.h"
+#include "pmvector.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray bicubic patches (bezier patches).
+ */
+
+class PMBicubicPatch : public PMGraphicalObject
+{
+ typedef PMGraphicalObject Base;
+public:
+ /**
+ * Creates an empty PMBicubicPatch
+ */
+ PMBicubicPatch( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMBicubicPatch( const PMBicubicPatch& p );
+ /**
+ * deletes the PMBicubicPatch
+ */
+ virtual ~PMBicubicPatch( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMBicubicPatch( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMBicubicPatchEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmbicubicpatch" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool multipleSelectControlPoints( ) const { return true; }
+
+ /**
+ * Sets the type. Type must be 0 or 1
+ */
+ void setPatchType( int type );
+ /**
+ * Returns the type
+ */
+ int patchType( ) const { return m_patchType; }
+ /**
+ * Sets the number of u steps
+ */
+ void setUSteps( int steps );
+ /**
+ * Returns the number of u steps
+ */
+ int uSteps( ) const { return m_numUSteps; }
+ /**
+ * Sets the number of v steps
+ */
+ void setVSteps( int steps );
+ /**
+ * Returns the number of v steps
+ */
+ int vSteps( ) const { return m_numVSteps; }
+ /**
+ * Sets the flatness
+ */
+ void setFlatness( double f );
+ /**
+ * Returns the flatness
+ */
+ double flatness( ) const { return m_flatness; }
+
+ /**
+ * Sets the ith patch control point
+ */
+ void setControlPoint( int i, const PMVector& p );
+ /**
+ * Returns the ith patch control point
+ */
+ PMVector controlPoint( int i ) const;
+
+ /**
+ * Sets the uv vectors flag
+ */
+ void enableUV( bool yes );
+ /**
+ * Returns the uv vectors flag
+ */
+ bool isUVEnabled( ) const { return m_uvEnabled; }
+ /**
+ * Sets the ith uv vector
+ */
+ void setUVVector( int i, const PMVector& v );
+ /**
+ * Returns the ith uv vector
+ */
+ PMVector uvVector( int i ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( ) { return false; }
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const { return 0; }
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMBicubicPatchMementoID { PMTypeID, PMFlatnessID, PMUStepsID,
+ PMVStepsID,
+ PMCP0ID, PMCP1ID, PMCP2ID, PMCP3ID,
+ PMCP4ID, PMCP5ID, PMCP6ID, PMCP7ID,
+ PMCP8ID, PMCP9ID, PMCP10ID, PMCP11ID,
+ PMCP12ID, PMCP13ID, PMCP14ID, PMCP15ID,
+ PMUVEnabledID,
+ PMUV0ID, PMUV1ID, PMUV2ID, PMUV3ID };
+
+ /**
+ * The patch type
+ */
+ int m_patchType;
+ /**
+ * Number of subdivisions
+ */
+ int m_numUSteps, m_numVSteps;
+ /**
+ * Flatness of the patch
+ */
+ double m_flatness;
+ /**
+ * The control points
+ */
+ PMVector m_point[16];
+ int m_vsUSteps, m_vsVSteps;
+ bool m_uvEnabled;
+ PMVector m_uvVectors[4];
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmbicubicpatchedit.cpp b/kpovmodeler/pmbicubicpatchedit.cpp
new file mode 100644
index 00000000..6ead96ae
--- /dev/null
+++ b/kpovmodeler/pmbicubicpatchedit.cpp
@@ -0,0 +1,218 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmbicubicpatchedit.h"
+#include "pmbicubicpatch.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmvectorlistedit.h"
+#include "pmpart.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+PMBicubicPatchEdit::PMBicubicPatchEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMBicubicPatchEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+
+ m_pType = new QComboBox( false, this );
+ m_pType->insertItem( i18n( "Normal (type 0)" ) );
+ m_pType->insertItem( i18n( "Preprocessed (type 1)" ) );
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Type:" ), this ) );
+ layout->addWidget( m_pType );
+ layout->addStretch( 1 );
+
+ m_pUSteps = new PMIntEdit( this );
+ m_pUSteps->setValidation( true, 0, false, 0 );
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Steps:" ) + " u", this ) );
+ layout->addWidget( m_pUSteps );
+ m_pVSteps = new PMIntEdit( this );
+ m_pVSteps->setValidation( true, 0, false, 0 );
+ layout->addWidget( new QLabel( "v", this ) );
+ layout->addWidget( m_pVSteps );
+
+ m_pFlatness = new PMFloatEdit( this );
+ m_pFlatness->setValidation( true, 0.0, false, 0.0 );
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Flatness:" ), this ) );
+ layout->addWidget( m_pFlatness );
+ layout->addStretch( 1 );
+
+ topLayout( )->addWidget( new QLabel( i18n( "Points:" ), this ) );
+
+ m_pPoints = new PMVectorListEdit( "x", "y", "z", this );
+ m_pPoints->setSize( 16 );
+ topLayout( )->addWidget( m_pPoints );
+
+ m_pUVEnabled = new QCheckBox( i18n( "UV vectors" ), this );
+ topLayout( )->addWidget( m_pUVEnabled );
+ m_pUVVectors = new PMVectorListEdit( "u", "v", this );
+ m_pUVVectors->setSize( 4 );
+ topLayout( )->addWidget( m_pUVVectors );
+
+ connect( m_pType, SIGNAL( highlighted( int ) ), SLOT( slotTypeSelected( int ) ) );
+ connect( m_pUSteps, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pVSteps, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFlatness, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPoints, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPoints, SIGNAL( selectionChanged( ) ),
+ SLOT( slotSelectionChanged( ) ) );
+ connect( m_pUVEnabled, SIGNAL( clicked( ) ), SLOT( slotUVEnabledClicked( ) ) );
+ connect( m_pUVVectors, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMBicubicPatchEdit::displayObject( PMObject* o )
+{
+ int i;
+ if( o->isA( "BicubicPatch" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMBicubicPatch* ) o;
+
+ m_pType->setCurrentItem( m_pDisplayedObject->patchType( ) );
+ m_pType->setEnabled( !readOnly );
+ m_pUSteps->setValue( m_pDisplayedObject->uSteps( ) );
+ m_pUSteps->setReadOnly( readOnly );
+ m_pVSteps->setValue( m_pDisplayedObject->vSteps( ) );
+ m_pVSteps->setReadOnly( readOnly );
+ m_pFlatness->setValue( m_pDisplayedObject->flatness( ) );
+ m_pFlatness->setReadOnly( readOnly );
+
+ for( i = 0; i < 16; i++ )
+ m_pPoints->setVector( i, m_pDisplayedObject->controlPoint( i ) );
+ m_pPoints->setReadOnly( readOnly );
+ updateControlPointSelection( );
+
+ m_pUVEnabled->setChecked( m_pDisplayedObject->isUVEnabled( ) );
+ m_pUVEnabled->setEnabled( !readOnly );
+ for( i = 0; i < 4; ++i )
+ m_pUVVectors->setVector( i, m_pDisplayedObject->uvVector( i ) );
+ m_pUVVectors->setReadOnly( readOnly );
+ slotUVEnabledClicked( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMBicubicPatchEdit: Can't display object\n";
+}
+
+void PMBicubicPatchEdit::updateControlPointSelection( )
+{
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp );
+ int s = 0, e = 0;
+
+ m_pPoints->blockSelectionUpdates( true );
+ bool sb = m_pPoints->signalsBlocked( );
+ m_pPoints->blockSignals( true );
+
+ m_pPoints->clearSelection( );
+ while( s < 16 )
+ {
+ if( ( *it )->selected( ) )
+ {
+ for( e = s; e < 16 && ( *it )->selected( ); e++ )
+ ++it;
+ m_pPoints->select( s, e - 1 );
+ s = e;
+ }
+ else
+ {
+ s++;
+ ++it;
+ }
+ }
+
+ m_pPoints->blockSignals( sb );
+ m_pPoints->blockSelectionUpdates( false );
+}
+
+void PMBicubicPatchEdit::saveContents( )
+{
+ int i;
+
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setPatchType( m_pType->currentItem( ) );
+ m_pDisplayedObject->setUSteps( m_pUSteps->value( ) );
+ m_pDisplayedObject->setVSteps( m_pVSteps->value( ) );
+ m_pDisplayedObject->setFlatness( m_pFlatness->value( ) );
+ for( i = 0; i < 16; i++ )
+ m_pDisplayedObject->setControlPoint( i, m_pPoints->vector( i ) );
+ m_pDisplayedObject->enableUV( m_pUVEnabled->isChecked( ) );
+ for( i = 0; i < 4; ++i )
+ m_pDisplayedObject->setUVVector( i, m_pUVVectors->vector( i ) );
+ }
+}
+
+bool PMBicubicPatchEdit::isDataValid( )
+{
+ bool ok = false;
+ if( m_pUSteps->isDataValid( ) )
+ if( m_pVSteps->isDataValid( ) )
+ if( m_pFlatness->isDataValid( ) )
+ ok = true;
+ if( ok )
+ ok = m_pPoints->isDataValid( );
+ if( ok && m_pUVEnabled->isChecked( ) )
+ ok = m_pUVVectors->isDataValid( );
+ if( ok )
+ return Base::isDataValid( );
+ return false;
+}
+
+void PMBicubicPatchEdit::slotTypeSelected( int )
+{
+ emit dataChanged( );
+}
+
+void PMBicubicPatchEdit::slotSelectionChanged( )
+{
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp );
+ int i;
+ for( i = 0; i < 16; i++, ++it )
+ ( *it )->setSelected( m_pPoints->isSelected( i ) );
+ emit controlPointSelectionChanged( );
+}
+
+void PMBicubicPatchEdit::slotUVEnabledClicked( )
+{
+ if( m_pUVEnabled->isChecked( ) )
+ m_pUVVectors->show( );
+ else
+ m_pUVVectors->hide( );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+#include "pmbicubicpatchedit.moc"
diff --git a/kpovmodeler/pmbicubicpatchedit.h b/kpovmodeler/pmbicubicpatchedit.h
new file mode 100644
index 00000000..41d173c1
--- /dev/null
+++ b/kpovmodeler/pmbicubicpatchedit.h
@@ -0,0 +1,80 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBICUBICPATCHEDIT_H
+#define PMBICUBICPATCHEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmgraphicalobjectedit.h"
+
+class PMBicubicPatch;
+class PMIntEdit;
+class PMFloatEdit;
+class PMVectorListEdit;
+class QComboBox;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMBicubicPatch
+ */
+class PMBicubicPatchEdit : public PMGraphicalObjectEdit
+{
+ Q_OBJECT
+ typedef PMGraphicalObjectEdit Base;
+public:
+ /**
+ * Creates a PMBicubicPatchEdit with parent and name
+ */
+ PMBicubicPatchEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+ /** */
+ virtual void updateControlPointSelection( );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected slots:
+ void slotTypeSelected( int i );
+ void slotSelectionChanged( );
+ void slotUVEnabledClicked( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ QComboBox* m_pType;
+ PMIntEdit* m_pUSteps;
+ PMIntEdit* m_pVSteps;
+ PMFloatEdit* m_pFlatness;
+ PMVectorListEdit* m_pPoints;
+ QCheckBox* m_pUVEnabled;
+ PMVectorListEdit* m_pUVVectors;
+
+ PMBicubicPatch* m_pDisplayedObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmblendmapmodifiers.cpp b/kpovmodeler/pmblendmapmodifiers.cpp
new file mode 100644
index 00000000..0259fb90
--- /dev/null
+++ b/kpovmodeler/pmblendmapmodifiers.cpp
@@ -0,0 +1,284 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmblendmapmodifiers.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmblendmapmodifiersedit.h"
+#include "pmvector.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMBlendMapModifiers, PMBlendMapModifiersProperty );
+PMDefineEnumPropertyClass( PMBlendMapModifiers,
+ PMBlendMapModifiers::PMWaveFormType,
+ PMWaveFormProperty );
+
+PMMetaObject* PMBlendMapModifiers::s_pMetaObject = 0;
+PMObject* createBlendMapModifiers( PMPart* part )
+{
+ return new PMBlendMapModifiers( part );
+}
+
+const double frequencyDefault = 1.0;
+const double phaseDefault = 0.0;
+const PMBlendMapModifiers::PMWaveFormType waveFormTypeDefault = PMBlendMapModifiers::RampWave;
+const double waveFormExponentDefault = 1.0;
+
+
+PMBlendMapModifiers::PMBlendMapModifiers( PMPart* part )
+ : Base( part )
+{
+ m_enableFrequency = false;
+ m_frequency = frequencyDefault;
+ m_enablePhase = false;
+ m_phase = phaseDefault;
+ m_enableWaveForm = false;
+ m_waveFormType = waveFormTypeDefault;
+ m_waveFormExponent = waveFormExponentDefault;
+}
+
+PMBlendMapModifiers::~PMBlendMapModifiers( )
+{
+}
+
+PMMetaObject* PMBlendMapModifiers::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "BlendMapModifiers", Base::metaObject( ),
+ createBlendMapModifiers );
+ s_pMetaObject->addProperty(
+ new PMBlendMapModifiersProperty( "frequencyEnabled", &PMBlendMapModifiers::enableFrequency,
+ &PMBlendMapModifiers::isFrequencyEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMBlendMapModifiersProperty( "frequency", &PMBlendMapModifiers::setFrequency,
+ &PMBlendMapModifiers::frequency ) );
+ s_pMetaObject->addProperty(
+ new PMBlendMapModifiersProperty( "phaseEnabled", &PMBlendMapModifiers::enablePhase,
+ &PMBlendMapModifiers::isPhaseEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMBlendMapModifiersProperty( "phase", &PMBlendMapModifiers::setPhase,
+ &PMBlendMapModifiers::phase ) );
+ s_pMetaObject->addProperty(
+ new PMBlendMapModifiersProperty( "waveFormEnabled", &PMBlendMapModifiers::enableWaveForm,
+ &PMBlendMapModifiers::isWaveFormEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMBlendMapModifiersProperty( "waveFormExponent", &PMBlendMapModifiers::setWaveFormExponent,
+ &PMBlendMapModifiers::waveFormExponent ) );
+
+ PMWaveFormProperty* p = new PMWaveFormProperty(
+ "waveForm", &PMBlendMapModifiers::setWaveFormType,
+ &PMBlendMapModifiers::waveFormType );
+ p->addEnumValue( QString( "RampWave" ), RampWave );
+ p->addEnumValue( QString( "TriangleWave" ), TriangleWave );
+ p->addEnumValue( QString( "SineWave" ), SineWave );
+ p->addEnumValue( QString( "ScallopWave" ), ScallopWave );
+ p->addEnumValue( QString( "CubicWave" ), CubicWave );
+ p->addEnumValue( QString( "PolyWave" ), PolyWave );
+ s_pMetaObject->addProperty( p );
+ }
+ return s_pMetaObject;
+}
+
+void PMBlendMapModifiers::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMBlendMapModifiers::description( ) const
+{
+ return i18n( "blend map modifiers" );
+}
+
+void PMBlendMapModifiers::serialize( QDomElement& e, QDomDocument& ) const
+{
+ e.setAttribute( "frequency", m_frequency );
+ e.setAttribute( "phase", m_phase );
+ e.setAttribute( "enable_frequency", m_enableFrequency );
+ e.setAttribute( "enable_phase", m_enablePhase );
+ e.setAttribute( "wave_exponent", m_waveFormExponent );
+ e.setAttribute( "enable_wave", m_enableWaveForm );
+ switch( m_waveFormType )
+ {
+ case RampWave:
+ e.setAttribute( "waveform_type", "ramp" );
+ break;
+ case TriangleWave:
+ e.setAttribute( "waveform_type", "triangle" );
+ break;
+ case SineWave:
+ e.setAttribute( "waveform_type", "sine" );
+ break;
+ case ScallopWave:
+ e.setAttribute( "waveform_type", "scallop" );
+ break;
+ case CubicWave:
+ e.setAttribute( "waveform_type", "cubic" );
+ break;
+ case PolyWave:
+ e.setAttribute( "waveform_type", "poly" );
+ break;
+ }
+}
+
+void PMBlendMapModifiers::readAttributes( const PMXMLHelper& h )
+{
+ QString str = h.stringAttribute( "waveform_type", "ramp" );
+
+ if( str == "ramp" )
+ m_waveFormType = RampWave;
+ else if( str == "triangle" )
+ m_waveFormType = TriangleWave;
+ else if( str == "sine" )
+ m_waveFormType = SineWave;
+ else if( str == "scallop" )
+ m_waveFormType = ScallopWave;
+ else if( str == "cubic" )
+ m_waveFormType = CubicWave;
+ else if( str == "poly" )
+ m_waveFormType = PolyWave;
+ m_frequency = h.doubleAttribute( "frequency", frequencyDefault );
+ m_enableFrequency = h.boolAttribute( "enable_frequency", false );
+ m_phase = h.doubleAttribute( "phase", phaseDefault );
+ m_enablePhase = h.boolAttribute( "enable_phase", false );
+ m_enableWaveForm = h.boolAttribute( "enable_wave", false );
+ m_waveFormExponent = h.doubleAttribute( "wave_exponent", waveFormExponentDefault );
+}
+
+void PMBlendMapModifiers::setFrequency( double c )
+{
+ if( c != m_frequency )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFrequencyID, m_frequency );
+ m_frequency = c;
+ }
+}
+
+void PMBlendMapModifiers::enableFrequency( bool c )
+{
+ if( c != m_enableFrequency )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableFrequencyID, m_enableFrequency );
+ m_enableFrequency = c;
+ }
+}
+
+void PMBlendMapModifiers::setPhase( double c )
+{
+ if( c != m_phase )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPhaseID, m_phase );
+ m_phase = c;
+ }
+}
+
+void PMBlendMapModifiers::enablePhase( bool c )
+{
+ if( c != m_enablePhase )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnablePhaseID, m_enablePhase );
+ m_enablePhase = c;
+ }
+}
+
+void PMBlendMapModifiers::enableWaveForm( bool c )
+{
+ if( c != m_enableWaveForm )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableWaveFormID, m_enableWaveForm );
+ m_enableWaveForm = c;
+ }
+}
+
+void PMBlendMapModifiers::setWaveFormExponent( double c )
+{
+ if( c != m_waveFormExponent )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMWaveFormExponentID, m_waveFormExponent );
+ m_waveFormExponent = c;
+ }
+}
+
+void PMBlendMapModifiers::setWaveFormType( PMWaveFormType c )
+{
+ if( c != m_waveFormType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMWaveFormTypeID, m_waveFormType );
+ m_waveFormType = c;
+ }
+}
+
+PMDialogEditBase* PMBlendMapModifiers::editWidget( QWidget* parent ) const
+{
+ return new PMBlendMapModifiersEdit( parent );
+}
+
+void PMBlendMapModifiers::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMFrequencyID:
+ setFrequency( data->doubleData( ) );
+ break;
+ case PMEnableFrequencyID:
+ enableFrequency( data->boolData( ) );
+ break;
+ case PMPhaseID:
+ setPhase( data->doubleData( ) );
+ break;
+ case PMEnablePhaseID:
+ enablePhase( data->boolData( ) );
+ break;
+ case PMWaveFormTypeID:
+ setWaveFormType( ( PMWaveFormType )data->intData( ) );
+ break;
+ case PMEnableWaveFormID:
+ enableWaveForm( data->boolData( ) );
+ break;
+ case PMWaveFormExponentID:
+ setWaveFormExponent( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMBlendMapModifiers::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmblendmapmodifiers.h b/kpovmodeler/pmblendmapmodifiers.h
new file mode 100644
index 00000000..1fa45528
--- /dev/null
+++ b/kpovmodeler/pmblendmapmodifiers.h
@@ -0,0 +1,129 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBLENDMAPMODIFIERS_H
+#define PMBLENDMAPMODIFIERS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+#include "pmcolor.h"
+#include "pmvector.h"
+
+/**
+ * Class for povray blendmapmodifierss
+ */
+class PMBlendMapModifiers : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * The type of the wave form
+ */
+ enum PMWaveFormType { RampWave, TriangleWave, SineWave, ScallopWave,
+ CubicWave, PolyWave };
+
+ /**
+ * Creates an PMBlendMapModifiers
+ */
+ PMBlendMapModifiers( PMPart* part );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMBlendMapModifiers( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMBlendMapModifiers( *this ); }
+
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMBlendMapModifiersEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmblendmapmodifiers" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ /** */
+ bool isFrequencyEnabled( ) const { return m_enableFrequency; }
+ /** */
+ double frequency( ) const { return m_frequency; }
+ /** */
+ bool isPhaseEnabled( ) const { return m_enablePhase; }
+ /** */
+ double phase( ) const { return m_phase; }
+ /** */
+ bool isWaveFormEnabled( ) const { return m_enableWaveForm; }
+ /** */
+ PMWaveFormType waveFormType( ) const { return m_waveFormType; }
+ /** */
+ double waveFormExponent( ) const { return m_waveFormExponent; }
+
+ /** */
+ void enableFrequency( bool c );
+ /** */
+ void setFrequency( double c );
+ /** */
+ void enablePhase( bool c );
+ /** */
+ void setPhase( double c );
+ /** */
+ void enableWaveForm( bool c );
+ /** */
+ void setWaveFormType( PMWaveFormType c );
+ /** */
+ void setWaveFormExponent( double c );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMBlendMapModifiersMementoID { PMEnableFrequencyID, PMFrequencyID,
+ PMEnablePhaseID, PMPhaseID, PMEnableWaveFormID,
+ PMWaveFormTypeID, PMWaveFormExponentID };
+
+ bool m_enableFrequency;
+ double m_frequency;
+ bool m_enablePhase;
+ double m_phase;
+ bool m_enableWaveForm;
+ PMWaveFormType m_waveFormType;
+ double m_waveFormExponent;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmblendmapmodifiersedit.cpp b/kpovmodeler/pmblendmapmodifiersedit.cpp
new file mode 100644
index 00000000..8e8ff150
--- /dev/null
+++ b/kpovmodeler/pmblendmapmodifiersedit.cpp
@@ -0,0 +1,261 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmblendmapmodifiersedit.h"
+#include "pmblendmapmodifiers.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmvector.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <ktabctl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+
+PMBlendMapModifiersEdit::PMBlendMapModifiersEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMBlendMapModifiersEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pEnableFrequencyEdit = new QCheckBox( i18n( "Frequency:" ), this );
+ m_pFrequencyEdit = new PMFloatEdit( this );
+ hl->addWidget( m_pEnableFrequencyEdit );
+ hl->addWidget( m_pFrequencyEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pEnablePhaseEdit = new QCheckBox( i18n( "Phase:" ), this );
+ m_pPhaseEdit = new PMFloatEdit( this );
+ hl->addWidget( m_pEnablePhaseEdit );
+ hl->addWidget( m_pPhaseEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pEnableWaveFormEdit = new QCheckBox( i18n( "Wave form:" ), this );
+ m_pWaveTypeCombo = new QComboBox( this );
+ m_pWaveTypeCombo->insertItem( i18n( "Ramp" ) );
+ m_pWaveTypeCombo->insertItem( i18n( "Triangle" ) );
+ m_pWaveTypeCombo->insertItem( i18n( "Sine" ) );
+ m_pWaveTypeCombo->insertItem( i18n( "Scallop" ) );
+ m_pWaveTypeCombo->insertItem( i18n( "Cubic" ) );
+ m_pWaveTypeCombo->insertItem( i18n( "Poly" ) );
+ hl->addWidget( m_pEnableWaveFormEdit );
+ hl->addWidget( m_pWaveTypeCombo );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pWaveExponentLabel = new QLabel( i18n( "Exponent:" ), this );
+ m_pWaveExponentEdit = new PMFloatEdit( this );
+ hl->addWidget( m_pWaveExponentLabel );
+ hl->addWidget( m_pWaveExponentEdit );
+ hl->addStretch( 1 );
+
+ connect( m_pEnableFrequencyEdit, SIGNAL( clicked( ) ), SLOT( slotFrequencyClicked( ) ) );
+ connect( m_pFrequencyEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnablePhaseEdit, SIGNAL( clicked( ) ), SLOT( slotPhaseClicked( ) ) );
+ connect( m_pPhaseEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnableWaveFormEdit, SIGNAL( clicked( ) ), SLOT( slotWaveFormClicked( ) ) );
+ connect( m_pWaveExponentEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pWaveTypeCombo, SIGNAL( activated( int ) ), SLOT( slotTypeComboChanged( int ) ) );
+}
+
+void PMBlendMapModifiersEdit::displayObject( PMObject* o )
+{
+ QString str;
+
+ if( o->isA( "BlendMapModifiers" ) )
+ {
+ m_pDisplayedObject = ( PMBlendMapModifiers* ) o;
+
+ m_pEnableFrequencyEdit->setChecked( m_pDisplayedObject->isFrequencyEnabled( ) );
+ m_pEnablePhaseEdit->setChecked( m_pDisplayedObject->isPhaseEnabled( ) );
+ m_pEnableWaveFormEdit->setChecked( m_pDisplayedObject->isWaveFormEnabled( ) );
+
+ m_pFrequencyEdit->setValue( m_pDisplayedObject->frequency( ) );
+ m_pPhaseEdit->setValue( m_pDisplayedObject->phase( ) );
+ m_pWaveExponentEdit->setValue( m_pDisplayedObject->waveFormExponent( ) );
+
+ switch( m_pDisplayedObject->waveFormType( ) )
+ {
+ case PMBlendMapModifiers::RampWave:
+ m_pWaveTypeCombo->setCurrentItem( 0 );
+ break;
+ case PMBlendMapModifiers::TriangleWave:
+ m_pWaveTypeCombo->setCurrentItem( 1 );
+ break;
+ case PMBlendMapModifiers::SineWave:
+ m_pWaveTypeCombo->setCurrentItem( 2 );
+ break;
+ case PMBlendMapModifiers::ScallopWave:
+ m_pWaveTypeCombo->setCurrentItem( 3 );
+ break;
+ case PMBlendMapModifiers::CubicWave:
+ m_pWaveTypeCombo->setCurrentItem( 4 );
+ break;
+ case PMBlendMapModifiers::PolyWave:
+ m_pWaveTypeCombo->setCurrentItem( 5 );
+ break;
+ }
+
+ slotFrequencyClicked( );
+ slotPhaseClicked( );
+ slotWaveFormClicked( );
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMBlendMapModifiersEdit: Can't display object\n";
+}
+
+void PMBlendMapModifiersEdit::setBlendMapModifiersType( int i )
+{
+ m_pWaveTypeCombo->setCurrentItem( i );
+ slotTypeComboChanged( i );
+}
+
+void PMBlendMapModifiersEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+
+ m_pDisplayedObject->enableFrequency( m_pEnableFrequencyEdit->isChecked( ) );
+ m_pDisplayedObject->enablePhase( m_pEnablePhaseEdit->isChecked( ) );
+ m_pDisplayedObject->enableWaveForm( m_pEnableWaveFormEdit->isChecked( ) );
+
+ if( m_pEnableFrequencyEdit->isChecked( ) )
+ m_pDisplayedObject->setFrequency( m_pFrequencyEdit->value( ) );
+
+ if( m_pEnablePhaseEdit->isChecked( ) )
+ m_pDisplayedObject->setPhase( m_pPhaseEdit->value( ) );
+
+ if( m_pEnableWaveFormEdit->isChecked( ) )
+ {
+ switch( m_pWaveTypeCombo->currentItem( ) )
+ {
+ case 0: /* Ramp Wave */
+ m_pDisplayedObject->setWaveFormType( PMBlendMapModifiers::RampWave );
+ break;
+ case 1: /* Triangle Wave */
+ m_pDisplayedObject->setWaveFormType( PMBlendMapModifiers::TriangleWave );
+ break;
+ case 2: /* Sine Wave */
+ m_pDisplayedObject->setWaveFormType( PMBlendMapModifiers::SineWave );
+ break;
+ case 3: /* Scallop Wave */
+ m_pDisplayedObject->setWaveFormType( PMBlendMapModifiers::ScallopWave );
+ break;
+ case 4: /* Cubic Wave */
+ m_pDisplayedObject->setWaveFormType( PMBlendMapModifiers::CubicWave );
+ break;
+ case 5: /* Poly Wave */
+ m_pDisplayedObject->setWaveFormType( PMBlendMapModifiers::PolyWave );
+ m_pDisplayedObject->setWaveFormExponent( m_pWaveExponentEdit->value( ) );
+ break;
+ }
+ }
+ }
+}
+
+bool PMBlendMapModifiersEdit::isDataValid( )
+{
+ if( !m_pFrequencyEdit->isDataValid( ) ) return false;
+ if( !m_pPhaseEdit->isDataValid( ) ) return false;
+
+ switch( m_pWaveTypeCombo->currentItem( ) )
+ {
+ case 5: /* Poly Wave */
+ if( !m_pWaveExponentEdit->isDataValid( ) ) return false;
+ break;
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMBlendMapModifiersEdit::slotTypeComboChanged( int c )
+{
+ switch( c )
+ {
+ case 5: /* Poly Wave */
+ m_pWaveExponentLabel->show( );
+ m_pWaveExponentEdit->show( );
+ break;
+ default:
+ m_pWaveExponentLabel->hide( );
+ m_pWaveExponentEdit->hide( );
+ break;
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMBlendMapModifiersEdit::slotFrequencyClicked( )
+{
+ if( m_pEnableFrequencyEdit->isChecked( ) )
+ m_pFrequencyEdit->setEnabled( true );
+ else
+ m_pFrequencyEdit->setEnabled( false );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMBlendMapModifiersEdit::slotPhaseClicked( )
+{
+ if(m_pEnablePhaseEdit->isChecked( ) )
+ m_pPhaseEdit->setEnabled( true );
+ else
+ m_pPhaseEdit->setEnabled( false );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMBlendMapModifiersEdit::slotWaveFormClicked( )
+{
+ if(m_pEnableWaveFormEdit->isChecked( ) )
+ {
+ m_pWaveTypeCombo->setEnabled( true );
+ slotTypeComboChanged( m_pWaveTypeCombo->currentItem( ) );
+ }
+ else
+ {
+ m_pWaveTypeCombo->setEnabled( false );
+ m_pWaveExponentLabel->hide( );
+ m_pWaveExponentEdit->hide( );
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+#include "pmblendmapmodifiersedit.moc"
diff --git a/kpovmodeler/pmblendmapmodifiersedit.h b/kpovmodeler/pmblendmapmodifiersedit.h
new file mode 100644
index 00000000..eb4e40b5
--- /dev/null
+++ b/kpovmodeler/pmblendmapmodifiersedit.h
@@ -0,0 +1,100 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBLENDMAPMODIFIERSEDIT_H
+#define PMBLENDMAPMODIFIERSEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMBlendMapModifiers;
+class PMVectorEdit;
+class QComboBox;
+class PMFloatEdit;
+class PMIntEdit;
+class QLabel;
+class QCheckBox;
+class QWidget;
+class QLineEdit;
+class QPushButton;
+
+/**
+ * Dialog edit class for @ref PMBlendMapModifiers.
+ */
+class PMBlendMapModifiersEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMBlendMapModifiersEdit with parent and name
+ */
+ PMBlendMapModifiersEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * Slot called whenever a new Wave Form type is selected.
+ */
+ void slotTypeComboChanged( int c );
+ /**
+ * Slot called when frequency is activated/deactivated.
+ */
+ void slotFrequencyClicked( );
+ /**
+ * Slot called when phase is activated/deactivated.
+ */
+ void slotPhaseClicked( );
+ /**
+ * Slot called when wave form is activated/deactivated.
+ */
+ void slotWaveFormClicked( );
+
+private:
+ /**
+ * Set's the combo box and enables/disables widgets.
+ */
+ void setBlendMapModifiersType( int i );
+ PMBlendMapModifiers* m_pDisplayedObject;
+
+ QComboBox* m_pWaveTypeCombo;
+ PMFloatEdit* m_pFrequencyEdit;
+ PMFloatEdit* m_pPhaseEdit;
+ PMFloatEdit* m_pWaveExponentEdit;
+ QLabel* m_pWaveExponentLabel;
+ QCheckBox* m_pEnableFrequencyEdit;
+ QCheckBox* m_pEnablePhaseEdit;
+ QCheckBox* m_pEnableWaveFormEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmblob.cpp b/kpovmodeler/pmblob.cpp
new file mode 100644
index 00000000..800c3b5a
--- /dev/null
+++ b/kpovmodeler/pmblob.cpp
@@ -0,0 +1,175 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmblob.h"
+
+#include "pmxmlhelper.h"
+#include "pmblobedit.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+const double c_defaultThreshold = 0.5;
+bool c_defaultSturm = false;
+bool c_defaultHierarchy = false;
+
+PMDefinePropertyClass( PMBlob, PMBlobProperty );
+
+PMMetaObject* PMBlob::s_pMetaObject = 0;
+PMObject* createNewBlob( PMPart* part )
+{
+ return new PMBlob( part );
+}
+
+PMBlob::PMBlob( PMPart* part )
+ : Base( part )
+{
+ m_threshold = c_defaultThreshold;
+ m_sturm = c_defaultSturm;
+ m_hierarchy = c_defaultHierarchy;
+}
+
+PMBlob::PMBlob( const PMBlob& b )
+ : Base( b )
+{
+ m_threshold = b.m_threshold;
+ m_sturm = b.m_sturm;
+ m_hierarchy = b.m_hierarchy;
+}
+
+PMBlob::~PMBlob( )
+{
+}
+
+QString PMBlob::description( ) const
+{
+ return i18n( "blob" );
+}
+
+void PMBlob::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "threshold", m_threshold );
+ e.setAttribute( "sturm", m_sturm );
+ e.setAttribute( "hierarchy", m_hierarchy );
+ Base::serialize( e, doc );
+}
+
+void PMBlob::readAttributes( const PMXMLHelper& h )
+{
+ m_threshold = h.doubleAttribute( "threshold", c_defaultThreshold );
+ m_sturm = h.boolAttribute( "sturm", c_defaultSturm );
+ m_hierarchy = h.boolAttribute( "hierarchy", c_defaultHierarchy );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMBlob::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Blob", Base::metaObject( ),
+ createNewBlob );
+ s_pMetaObject->addProperty(
+ new PMBlobProperty( "threshold", &PMBlob::setThreshold, &PMBlob::threshold ) );
+ s_pMetaObject->addProperty(
+ new PMBlobProperty( "hierarchy", &PMBlob::setHierarchy, &PMBlob::hierarchy ) );
+ s_pMetaObject->addProperty(
+ new PMBlobProperty( "sturm", &PMBlob::setSturm, &PMBlob::sturm ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMBlob::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMBlob::setThreshold( double t )
+{
+ if( t <= 0.0 )
+ {
+ kdError( PMArea ) << "Threshold is not positive in PMBlob::setThreshold\n";
+ t = 1.0;
+ }
+
+ if( t != m_threshold )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMThresholdID, m_threshold );
+ m_threshold = t;
+ }
+}
+
+void PMBlob::setSturm( bool s )
+{
+ if( s != m_sturm )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSturmID, m_sturm );
+ m_sturm = s;
+ }
+}
+
+void PMBlob::setHierarchy( bool h )
+{
+ if( h != m_hierarchy )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHierarchyID, m_hierarchy );
+ m_hierarchy = h;
+ }
+}
+
+PMDialogEditBase* PMBlob::editWidget( QWidget* parent ) const
+{
+ return new PMBlobEdit( parent );
+}
+
+void PMBlob::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMThresholdID:
+ setThreshold( data->doubleData( ) );
+ break;
+ case PMSturmID:
+ setSturm( data->boolData( ) );
+ break;
+ case PMHierarchyID:
+ setHierarchy( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMBlob::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmblob.h b/kpovmodeler/pmblob.h
new file mode 100644
index 00000000..986cec8c
--- /dev/null
+++ b/kpovmodeler/pmblob.h
@@ -0,0 +1,113 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBLOB_H
+#define PMBLOB_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+
+/**
+ * Class for povray blobs.
+ */
+
+class PMBlob : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMBlob
+ */
+ PMBlob( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMBlob( const PMBlob& b );
+ /**
+ * deletes the PMBlob
+ */
+ virtual ~PMBlob( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMBlob( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMBlobEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmblob" ); }
+
+ /**
+ * Returns the threshold
+ */
+ double threshold( ) const { return m_threshold; }
+ /**
+ * Sets the threshold
+ */
+ void setThreshold( double t );
+ /**
+ * Returns the hierarchy flag
+ */
+ bool hierarchy( ) const { return m_hierarchy; }
+ /**
+ * Sets the hierarchy flag
+ */
+ void setHierarchy( bool h );
+ /**
+ * Returns the sturm flag
+ */
+ bool sturm( ) const { return m_sturm; }
+ /**
+ * Sets the sturm flag
+ */
+ void setSturm( bool s );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMBlobMementoID { PMThresholdID, PMHierarchyID, PMSturmID };
+ double m_threshold;
+ bool m_hierarchy;
+ bool m_sturm;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmblobcylinder.cpp b/kpovmodeler/pmblobcylinder.cpp
new file mode 100644
index 00000000..687ce132
--- /dev/null
+++ b/kpovmodeler/pmblobcylinder.cpp
@@ -0,0 +1,468 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmblobcylinder.h"
+
+#include "pmxmlhelper.h"
+#include "pmboxedit.h"
+#include "pmmemento.h"
+#include "pm3dcontrolpoint.h"
+#include "pmdefaults.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmblobcylinderedit.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMBlobCylinder, PMBlobCylinderProperty );
+
+PMMetaObject* PMBlobCylinder::s_pMetaObject = 0;
+PMObject* createNewBlobCylinder( PMPart* part )
+{
+ return new PMBlobCylinder( part );
+}
+
+const double c_defaultRadius = 0.5;
+const PMVector c_defaultEnd1 = PMVector ( 0, 0.5, 0 );
+const PMVector c_defaultEnd2 = PMVector ( 0, -0.5, 0 );
+const double c_defaultStrength = 1.0;
+
+/** default cylinder structure */
+PMViewStructure* PMBlobCylinder::s_pDefaultViewStructure = 0;
+int PMBlobCylinder::s_vStep = c_defaultBlobCylinderVSteps;
+int PMBlobCylinder::s_uStep = c_defaultBlobCylinderUSteps;
+int PMBlobCylinder::s_parameterKey = 0;
+
+
+PMBlobCylinder::PMBlobCylinder( PMPart* part )
+ : Base( part )
+{
+ m_end1 = c_defaultEnd1;
+ m_end2 = c_defaultEnd2;
+ m_radius = c_defaultRadius;
+ m_strength = c_defaultStrength;
+}
+
+PMBlobCylinder::PMBlobCylinder( const PMBlobCylinder& c )
+ : Base( c )
+{
+ m_end1 = c.m_end1;
+ m_end2 = c.m_end2;
+ m_radius = c.m_radius;
+ m_strength = c.m_strength;
+}
+
+PMBlobCylinder::~PMBlobCylinder( )
+{
+}
+
+QString PMBlobCylinder::description( ) const
+{
+ return i18n( "blob cylinder" );
+}
+
+void PMBlobCylinder::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "end_a", m_end1.serializeXML( ) );
+ e.setAttribute( "end_b", m_end2.serializeXML( ) );
+ e.setAttribute( "radius", m_radius );
+ e.setAttribute( "strength", m_strength );
+ Base::serialize( e, doc );
+}
+
+void PMBlobCylinder::readAttributes( const PMXMLHelper& h )
+{
+ m_end1 = h.vectorAttribute( "end_a", c_defaultEnd1 );
+ m_end2 = h.vectorAttribute( "end_b", c_defaultEnd2 );
+ m_radius = h.doubleAttribute( "radius", c_defaultRadius );
+ m_strength = h.doubleAttribute( "strength", c_defaultStrength );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMBlobCylinder::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "BlobCylinder", Base::metaObject( ),
+ createNewBlobCylinder );
+ s_pMetaObject->addProperty(
+ new PMBlobCylinderProperty( "end1", &PMBlobCylinder::setEnd1,
+ &PMBlobCylinder::end1 ) );
+ s_pMetaObject->addProperty(
+ new PMBlobCylinderProperty( "end2", &PMBlobCylinder::setEnd2,
+ &PMBlobCylinder::end2 ) );
+ s_pMetaObject->addProperty(
+ new PMBlobCylinderProperty( "radius", &PMBlobCylinder::setRadius,
+ &PMBlobCylinder::radius ) );
+ s_pMetaObject->addProperty(
+ new PMBlobCylinderProperty( "strength", &PMBlobCylinder::setStrength,
+ &PMBlobCylinder::strength ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMBlobCylinder::setEnd1( const PMVector& p )
+{
+ if( p != m_end1 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnd1ID, m_end1 );
+ m_end1 = p;
+ m_end1.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMBlobCylinder::setEnd2( const PMVector& p )
+{
+ if( p != m_end2 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnd2ID, m_end2 );
+ m_end2 = p;
+ m_end2.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMBlobCylinder::setRadius( double radius )
+{
+ if( m_radius != radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusID, m_radius );
+ m_radius = radius;
+ setViewStructureChanged( );
+ }
+}
+
+void PMBlobCylinder::setStrength( double s )
+{
+ if( s != m_strength )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMStrengthID, m_strength );
+ m_strength = s;
+ }
+}
+
+PMDialogEditBase* PMBlobCylinder::editWidget( QWidget* parent ) const
+{
+ return new PMBlobCylinderEdit( parent );
+}
+
+void PMBlobCylinder::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMEnd1ID:
+ setEnd1( data->vectorData( ) );
+ break;
+ case PMEnd2ID:
+ setEnd2( data->vectorData( ) );
+ break;
+ case PMRadiusID:
+ setRadius( data->doubleData( ) );
+ break;
+ case PMStrengthID:
+ setStrength( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMBlobCylinder::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+bool PMBlobCylinder::isDefault( )
+{
+ if( ( m_end1 == c_defaultEnd1 ) && ( m_end2 == c_defaultEnd2 )
+ && ( m_radius == c_defaultRadius )
+ && globalDetail( ) )
+ return true;
+ return false;
+}
+
+void PMBlobCylinder::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure ( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( displayDetail( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( displayDetail( ) + 1 ) );
+ unsigned ptsSize = vStep * uStep * 2 + 2;
+ unsigned lineSize = vStep * uStep * 4 + vStep;
+
+ if( ptsSize != m_pViewStructure->points( ).size( ) )
+ m_pViewStructure->points( ).resize( ptsSize );
+
+ createPoints( m_pViewStructure->points( ), m_end1, m_end2, m_radius, uStep, vStep );
+
+ if( lineSize != m_pViewStructure->lines( ).size( ) )
+ {
+ m_pViewStructure->lines( ).detach( );
+ m_pViewStructure->lines( ).resize( lineSize );
+ createLines( m_pViewStructure->lines( ), uStep, vStep );
+ }
+}
+
+PMViewStructure* PMBlobCylinder::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( displayDetail( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( displayDetail( ) + 1 ) );
+
+ s_pDefaultViewStructure =
+ new PMViewStructure( vStep * uStep * 2 + 2,
+ vStep * uStep * 4 + vStep );
+
+ createPoints( s_pDefaultViewStructure->points( ), c_defaultEnd1,
+ c_defaultEnd2, c_defaultRadius, uStep, vStep );
+
+ createLines( s_pDefaultViewStructure->lines( ), uStep, vStep );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMBlobCylinder::createLines( PMLineArray& lines, int uStep, int vStep )
+{
+ int u, v;
+ int offset = 0;
+
+ // horizontal lines
+ for( u = 0; u < ( uStep * 2 ); u++ )
+ {
+ for( v = 0; v < ( vStep - 1 ); v++ )
+ lines[offset + v] =
+ PMLine( u * vStep + v + 1, u * vStep + v + 2 );
+ lines[offset + vStep - 1] =
+ PMLine( u * vStep + 1, u * vStep + vStep );
+
+ offset += vStep;
+ }
+
+ // vertical lines
+ // lines at the "north pole"
+ for( v = 0; v < vStep; v++ )
+ lines[offset + v] = PMLine( 0, v + 1 );
+ offset += vStep;
+
+ for( v = 0; v < vStep; v++ )
+ {
+ for( u = 0; u < ( 2 * uStep - 1 ); u++ )
+ {
+ lines[offset + u] =
+ PMLine( u * vStep + v + 1, ( u + 1 ) * vStep + v + 1 );
+ }
+ offset += ( 2 * uStep - 1 );
+ }
+ // lines at the "south pole"
+ for( v = 0; v < vStep; v++ )
+ lines[offset + v] = PMLine( ( 2 * uStep - 1 ) * vStep + v + 1,
+ 2 * uStep * vStep + 1 );
+ // offset += vStep;
+}
+
+void PMBlobCylinder::createPoints( PMPointArray& points, const PMVector& end1,
+ const PMVector& end2, double radius, int uStep, int vStep )
+{
+ double uRadStep = M_PI / uStep / 2.0;
+ double vRadStep = 2 * M_PI / vStep;
+ double du = uRadStep;
+
+ if( radius < 0 )
+ radius = -radius;
+
+ PMVector pointAt = end2 - end1;
+ double pl = pointAt.abs( );
+ if( approxZero( pl ) )
+ pointAt = PMVector( 0.0, 0.0, 1.0 );
+ else
+ pointAt /= pl;
+
+ PMMatrix rotation = PMMatrix::rotation( pointAt, vRadStep );
+ PMVector ortho = pointAt.orthogonal( );
+ ortho /= ortho.abs( );
+
+ points[0] = PMPoint( end1 - pointAt * radius );
+ points[vStep * uStep * 2 + 1] = PMPoint( end2 + pointAt * radius );
+
+ int u, v;
+ for( u = 0; u < uStep; u++ )
+ {
+ PMVector end = ortho * radius * sin( du );
+ PMVector pv = pointAt * radius * cos( du );
+ PMVector e1 = end1 - pv;
+ PMVector e2 = end2 + pv;
+
+ for( v = 0; v < vStep; v++ )
+ {
+ points[u * vStep + v + 1] = PMPoint( e1 + end );
+ points[vStep * uStep * 2 - ( u + 1 ) * vStep + v + 1]
+ = PMPoint( e2 + end );
+ end = rotation * end;
+ }
+ du += uRadStep;
+ }
+}
+
+void PMBlobCylinder::controlPoints( PMControlPointList & list )
+{
+ PMVector center, angle1, angle2;
+ center = m_end1 - m_end2;
+ double pl = center.abs( );
+ if( approxZero( pl ) )
+ center = PMVector( 0.0, 1.0, 0.0 );
+ else
+ center /= pl;
+
+ angle1 = center.orthogonal( );
+ angle2 = PMVector::cross( center, angle1 );
+
+ PM3DControlPoint* pb = new PM3DControlPoint( m_end1, PMEnd1ID, i18n( "End 1" ) );
+ list.append( pb );
+ list.append( new PM3DControlPoint( m_end2, PMEnd2ID, i18n( "End 2" ) ) );
+ list.append( new PMDistanceControlPoint( pb, angle1, m_radius, PMRadiusID, i18n( "Radius (1)" ) ) );
+ list.append( new PMDistanceControlPoint( pb, angle2, m_radius, PMRadiusID, i18n( "Radius (2)" ) ) );
+}
+
+
+void PMBlobCylinder::controlPointsChanged( PMControlPointList & list )
+{
+ PMControlPoint* p;
+ bool pointChanged = false;
+ bool radiusChanged = false;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMEnd1ID:
+ setEnd1( ( ( PM3DControlPoint *) p)->point( ) );
+ pointChanged = true;
+ break;
+ case PMEnd2ID:
+ setEnd2( ( ( PM3DControlPoint *) p)->point( ) );
+ pointChanged = true;
+ break;
+ case PMRadiusID:
+ setRadius( ( ( PMDistanceControlPoint *) p)->distance( ) );
+ radiusChanged = true;
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMBlobCylinder::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+
+ if( pointChanged )
+ {
+ PMVector center, angle1, angle2;
+ bool firstPoint = true;
+
+ center = m_end1 - m_end2;
+ double pl = center.abs( );
+ if( approxZero( pl ) )
+ center = PMVector( 0.0, 1.0, 0.0 );
+ else
+ center /= pl;
+
+ angle1 = center.orthogonal( );
+ angle2 = PMVector::cross( center, angle1 );
+
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMRadiusID )
+ {
+ if( firstPoint )
+ {
+ ( ( PMDistanceControlPoint *) p)->setDirection( angle1 );
+ firstPoint = false;
+ }
+ else
+ ( ( PMDistanceControlPoint *) p)->setDirection( angle2 );
+ }
+ }
+
+ if( radiusChanged )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMRadiusID )
+ ( ( PMDistanceControlPoint *) p)->setDistance( m_radius );
+}
+
+void PMBlobCylinder::setUSteps( int u )
+{
+ if( u >= 2 )
+ {
+ s_uStep = u;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMBlobCylinder::setUSteps: U must be greater than 1\n";
+ s_parameterKey++;
+}
+
+void PMBlobCylinder::setVSteps( int v )
+{
+ if( v >= 4 )
+ {
+ s_vStep = v;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMBlobCylinder::setVSteps: V must be greater than 3\n";
+ s_parameterKey++;
+}
+
+void PMBlobCylinder::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmblobcylinder.h b/kpovmodeler/pmblobcylinder.h
new file mode 100644
index 00000000..80986cfe
--- /dev/null
+++ b/kpovmodeler/pmblobcylinder.h
@@ -0,0 +1,181 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBLOBCYLINDER_H
+#define PMBLOBCYLINDER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdetailobject.h"
+#include "pmvector.h"
+#include "pmviewstructure.h"
+
+/**
+ * Class for povray blob cylinder
+ */
+
+class PMBlobCylinder : public PMDetailObject
+{
+ typedef PMDetailObject Base;
+public:
+ /**
+ * Creates a cylinder
+ */
+ PMBlobCylinder( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMBlobCylinder( const PMBlobCylinder& c );
+
+ /**
+ * Deletes the cylinder
+ */
+ virtual ~PMBlobCylinder( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMBlobCylinder( *this ); }
+
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMBlobCylinderEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmblobcylinder" ); }
+
+ /**
+ * Return the end_1
+ */
+ PMVector end1( ) const { return m_end1; }
+ /**
+ * Sets end_1
+ */
+ void setEnd1( const PMVector& p );
+ /**
+ * Return the end_2
+ */
+ PMVector end2( ) const { return m_end2; }
+ /**
+ * Sets end_2
+ */
+ void setEnd2( const PMVector& p );
+ /**
+ * return the radius of the cylinder
+ */
+ double radius( ) const { return m_radius; }
+ /**
+ * Sets the radius of the cylinder
+ */
+ void setRadius( double radius );
+ /**
+ * Returns the strength
+ */
+ double strength( ) const { return m_strength; }
+ /**
+ * Sets the strength
+ */
+ void setStrength( double s );
+
+ /**
+ * Sets the number of latitutes
+ */
+ static void setUSteps( int u );
+ /**
+ * Sets the number of longitudes
+ */
+ static void setVSteps( int v );
+ /**
+ * Returns the number or latitutes
+ */
+ static int uSteps( ) { return s_uStep; }
+ /**
+ * Returns the number or longitudes
+ */
+ static int vSteps( ) { return s_vStep; }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure *defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey(); }
+
+private:
+ /**
+ * Creates the lines for the view structure
+ */
+ static void createLines( PMLineArray& lines, int uStep, int vStep );
+ /**
+ * Creates the points for the view structure
+ */
+ static void createPoints( PMPointArray& points, const PMVector& end1,
+ const PMVector& end2, double radius, int uStep, int vStep );
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMBlobCylinderMementoID { PMEnd1ID, PMEnd2ID, PMRadiusID, PMStrengthID };
+ /**
+ * ends of cylinder
+ */
+ PMVector m_end1, m_end2;
+ /**
+ * radius of cylinder
+ */
+ double m_radius;
+ double m_strength;
+ /**
+ * The default view structure. It can be shared between cylinders
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_vStep;
+ static int s_uStep;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmblobcylinderedit.cpp b/kpovmodeler/pmblobcylinderedit.cpp
new file mode 100644
index 00000000..9313b8af
--- /dev/null
+++ b/kpovmodeler/pmblobcylinderedit.cpp
@@ -0,0 +1,114 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmblobcylinderedit.h"
+#include "pmblobcylinder.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <qcheckbox.h>
+
+PMBlobCylinderEdit::PMBlobCylinderEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMBlobCylinderEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+ QGridLayout* gl;
+
+ m_pEnd1 = new PMVectorEdit( "x", "y", "z", this );
+ m_pEnd2 = new PMVectorEdit( "x", "y", "z", this );
+ m_pRadius = new PMFloatEdit( this );
+ m_pStrength = new PMFloatEdit( this );
+
+ gl = new QGridLayout( topLayout( ), 2, 2 );
+ gl->addWidget( new QLabel( i18n( "End 1:" ), this ), 0, 0 );
+ gl->addWidget( m_pEnd1, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "End 2:" ), this ), 1, 0 );
+ gl->addWidget( m_pEnd2, 1, 1 );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( layout, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Radius:" ), this ), 0, 0 );
+ gl->addWidget( m_pRadius, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Strength:" ), this ), 1, 0 );
+ gl->addWidget( m_pStrength, 1, 1 );
+ layout->addStretch( 1 );
+
+ connect( m_pEnd1, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnd2, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pStrength, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMBlobCylinderEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "BlobCylinder" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMBlobCylinder* ) o;
+
+ m_pEnd1->setVector( m_pDisplayedObject->end1( ) );
+ m_pEnd2->setVector( m_pDisplayedObject->end2( ) );
+ m_pRadius->setValue( m_pDisplayedObject->radius( ) );
+ m_pStrength->setValue( m_pDisplayedObject->strength( ) );
+
+ m_pEnd1->setReadOnly( readOnly );
+ m_pEnd2->setReadOnly( readOnly );
+ m_pRadius->setReadOnly( readOnly );
+ m_pStrength->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMBlobCylinderEdit: Can't display object\n";
+}
+
+void PMBlobCylinderEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setEnd1( m_pEnd1->vector( ) );
+ m_pDisplayedObject->setEnd2( m_pEnd2->vector( ) );
+ m_pDisplayedObject->setRadius( m_pRadius->value( ) );
+ m_pDisplayedObject->setStrength( m_pStrength->value( ) );
+ }
+}
+
+bool PMBlobCylinderEdit::isDataValid( )
+{
+ if( m_pEnd1->isDataValid( ) )
+ if( m_pEnd2->isDataValid( ) )
+ if( m_pRadius->isDataValid( ) )
+ if( m_pStrength->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+#include "pmblobcylinderedit.moc"
+
+
diff --git a/kpovmodeler/pmblobcylinderedit.h b/kpovmodeler/pmblobcylinderedit.h
new file mode 100644
index 00000000..d156e412
--- /dev/null
+++ b/kpovmodeler/pmblobcylinderedit.h
@@ -0,0 +1,61 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBLOBCYLINDEREDIT_H
+#define PMBLOBCYLINDEREDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdetailobjectedit.h"
+
+class PMVectorEdit;
+class PMFloatEdit;
+class PMBlobCylinder;
+
+class PMBlobCylinderEdit : public PMDetailObjectEdit
+{
+ Q_OBJECT
+ typedef PMDetailObjectEdit Base;
+public:
+ /**
+ * Creates a PMBlobCylinderEdit with parent and name
+ */
+ PMBlobCylinderEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMBlobCylinder* m_pDisplayedObject;
+ PMVectorEdit* m_pEnd1;
+ PMVectorEdit* m_pEnd2;
+ PMFloatEdit* m_pRadius;
+ PMFloatEdit* m_pStrength;
+};
+#endif
diff --git a/kpovmodeler/pmblobedit.cpp b/kpovmodeler/pmblobedit.cpp
new file mode 100644
index 00000000..80ebd510
--- /dev/null
+++ b/kpovmodeler/pmblobedit.cpp
@@ -0,0 +1,96 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmblobedit.h"
+#include "pmblob.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+PMBlobEdit::PMBlobEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMBlobEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Threshold:" ), this ) );
+ m_pThreshold = new PMFloatEdit( this );
+ hl->addWidget( m_pThreshold );
+ m_pThreshold->setValidation( true, 0.0, false, 0 );
+ m_pThreshold->setValidationOperator( PMFloatEdit::OpGreater,
+ PMFloatEdit::OpLess );
+ hl->addStretch( 1 );
+
+ m_pSturm = new QCheckBox( i18n( "Sturm" ), this );
+ topLayout( )->addWidget( m_pSturm );
+ m_pHierarchy = new QCheckBox( i18n( "Hierarchy" ), this );
+ topLayout( )->addWidget( m_pHierarchy );
+
+ connect( m_pThreshold, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pHierarchy, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSturm, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMBlobEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Blob" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMBlob* ) o;
+
+ m_pThreshold->setValue( m_pDisplayedObject->threshold( ) );
+ m_pSturm->setChecked( m_pDisplayedObject->sturm( ) );
+ m_pHierarchy->setChecked( m_pDisplayedObject->hierarchy( ) );
+
+ m_pThreshold->setReadOnly( readOnly );
+ m_pSturm->setEnabled( !readOnly );
+ m_pHierarchy->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMBlobEdit: Can't display object\n";
+}
+
+void PMBlobEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setThreshold( m_pThreshold->value( ) );
+ m_pDisplayedObject->setSturm( m_pSturm->isChecked( ) );
+ m_pDisplayedObject->setHierarchy( m_pHierarchy->isChecked( ) );
+ }
+}
+
+bool PMBlobEdit::isDataValid( )
+{
+ if( m_pThreshold->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+#include "pmblobedit.moc"
diff --git a/kpovmodeler/pmblobedit.h b/kpovmodeler/pmblobedit.h
new file mode 100644
index 00000000..df07ba30
--- /dev/null
+++ b/kpovmodeler/pmblobedit.h
@@ -0,0 +1,65 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBLOBEDIT_H
+#define PMBLOBEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMBlob;
+class PMFloatEdit;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMBlob
+ */
+class PMBlobEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMBlobEdit with parent and name
+ */
+ PMBlobEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMBlob* m_pDisplayedObject;
+ PMFloatEdit* m_pThreshold;
+ QCheckBox* m_pSturm;
+ QCheckBox* m_pHierarchy;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmblobsphere.cpp b/kpovmodeler/pmblobsphere.cpp
new file mode 100644
index 00000000..6ca96769
--- /dev/null
+++ b/kpovmodeler/pmblobsphere.cpp
@@ -0,0 +1,391 @@
+/*
+**************************************************************************
+ description
+ -------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmblobsphere.h"
+
+#include "pmxmlhelper.h"
+#include "pmblobsphereedit.h"
+#include "pmmemento.h"
+#include "pm3dcontrolpoint.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmdefaults.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMBlobSphere, PMBlobSphereProperty );
+
+PMMetaObject* PMBlobSphere::s_pMetaObject = 0;
+PMObject* createNewBlobSphere( PMPart* part )
+{
+ return new PMBlobSphere( part );
+}
+
+/** default param for the sphere */
+const double c_defaultRadius = 0.5;
+const PMVector c_defaultCentre = PMVector( 0, 0, 0 );
+const double c_defaultStrength = 1.0;
+
+/** default sphere structure */
+PMViewStructure* PMBlobSphere::s_pDefaultViewStructure = 0;
+
+int PMBlobSphere::s_vStep = c_defaultBlobSphereVSteps;
+int PMBlobSphere::s_uStep = c_defaultBlobSphereUSteps;
+int PMBlobSphere::s_parameterKey = 0;
+
+PMBlobSphere::PMBlobSphere( PMPart* part )
+ : Base( part )
+{
+ m_radius = c_defaultRadius;
+ m_centre = c_defaultCentre;
+ m_strength = c_defaultStrength;
+}
+
+PMBlobSphere::PMBlobSphere( const PMBlobSphere& s )
+ : Base( s )
+{
+ m_radius = s.m_radius;
+ m_centre = s.m_centre;
+ m_strength = s.m_strength;
+}
+
+PMBlobSphere::~PMBlobSphere( )
+{
+}
+
+
+QString PMBlobSphere::description( ) const
+{
+ return i18n( "blob sphere" );
+}
+
+PMMetaObject* PMBlobSphere::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "BlobSphere", Base::metaObject( ),
+ createNewBlobSphere );
+ s_pMetaObject->addProperty(
+ new PMBlobSphereProperty( "center", &PMBlobSphere::setCentre,
+ &PMBlobSphere::centre ) );
+ s_pMetaObject->addProperty(
+ new PMBlobSphereProperty( "radius", &PMBlobSphere::setRadius,
+ &PMBlobSphere::radius ) );
+ s_pMetaObject->addProperty(
+ new PMBlobSphereProperty( "strength", &PMBlobSphere::setStrength,
+ &PMBlobSphere::strength ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMBlobSphere::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "centre", m_centre.serializeXML( ) );
+ e.setAttribute( "radius", m_radius );
+ e.setAttribute( "strength", m_strength );
+ Base::serialize( e, doc );
+}
+
+void PMBlobSphere::readAttributes( const PMXMLHelper& h )
+{
+ m_centre = h.vectorAttribute( "centre", c_defaultCentre );
+ m_radius = h.doubleAttribute( "radius", c_defaultRadius );
+ m_strength = h.doubleAttribute( "strength", c_defaultStrength );
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMBlobSphere::editWidget( QWidget* parent ) const
+{
+ return new PMBlobSphereEdit( parent );
+}
+
+void PMBlobSphere::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMRadiusID:
+ setRadius( data->doubleData( ) );
+ break;
+ case PMCentreID:
+ setCentre( data->vectorData( ) );
+ break;
+ case PMStrengthID:
+ setStrength( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PBlobSphere::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+
+}
+
+void PMBlobSphere::controlPoints( PMControlPointList& list )
+{
+ PM3DControlPoint* p = new PM3DControlPoint( m_centre, PMCentreID,
+ i18n( "Center" ) );
+ list.append( p );
+ list.append( new PMDistanceControlPoint( p, PMVector( 1.0, 0.0, 0.0 ),
+ m_radius, PMRadiusID,
+ i18n( "Radius (x)" ) ) );
+ list.append( new PMDistanceControlPoint( p, PMVector( 0.0, 1.0, 0.0 ),
+ m_radius, PMRadiusID,
+ i18n( "Radius (y)" ) ) );
+ list.append( new PMDistanceControlPoint( p, PMVector( 0.0, 0.0, 1.0 ),
+ m_radius, PMRadiusID,
+ i18n( "Radius (z)" ) ) );
+}
+
+void PMBlobSphere::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+ bool radiusChanged = false;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMCentreID:
+ setCentre( ( ( PM3DControlPoint* ) p )->point( ) );
+ break;
+ case PMRadiusID:
+ setRadius( ( ( PMDistanceControlPoint* ) p )->distance( ) );
+ radiusChanged = true;
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMBlobSphere::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+
+ if( radiusChanged )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMRadiusID )
+ ( ( PMDistanceControlPoint* ) p )->setDistance( m_radius );
+}
+
+bool PMBlobSphere::isDefault( )
+{
+ if( ( m_radius == c_defaultRadius ) && ( m_centre == c_defaultCentre ) && globalDetail( ) )
+ return true;
+ return false;
+}
+
+void PMBlobSphere::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( displayDetail( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( displayDetail( ) + 1 ) );
+ unsigned ptsSize = vStep * ( uStep - 1 ) + 2;
+ unsigned lineSize = vStep * ( uStep - 1 ) * 2 + vStep;
+
+ if( ptsSize != m_pViewStructure->points( ).size( ) )
+ m_pViewStructure->points( ).resize( ptsSize );
+
+ createPoints( m_pViewStructure->points( ), m_centre, m_radius, uStep, vStep );
+
+ if( lineSize != m_pViewStructure->lines( ).size( ) )
+ {
+ m_pViewStructure->lines( ).detach( );
+ m_pViewStructure->lines( ).resize( lineSize );
+ createLines( m_pViewStructure->lines( ), uStep, vStep );
+ }
+}
+
+PMViewStructure* PMBlobSphere::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
+
+ s_pDefaultViewStructure =
+ new PMViewStructure( vStep * ( uStep - 1 ) + 2,
+ vStep * ( uStep - 1 ) * 2 + vStep );
+
+ createPoints( s_pDefaultViewStructure->points( ), c_defaultCentre,
+ c_defaultRadius, uStep, vStep );
+
+ createLines( s_pDefaultViewStructure->lines( ), uStep, vStep );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMBlobSphere::createLines( PMLineArray& lines, int uStep, int vStep )
+{
+ int u, v;
+ int offset = 0;
+
+ // horizontal lines
+ for( u = 0; u < ( uStep - 1 ); u++ )
+ {
+ for( v = 0; v < ( vStep - 1 ); v++ )
+ lines[offset + v] =
+ PMLine( u * vStep + v + 1, u * vStep + v + 2 );
+ lines[offset + vStep - 1] =
+ PMLine( u * vStep + 1, u * vStep + vStep );
+
+ offset += vStep;
+ }
+
+ // vertical lines
+ // lines at the "north pole"
+ for( v = 0; v < vStep; v++ )
+ lines[offset + v] = PMLine( 0, v + 1 );
+ offset += vStep;
+
+ for( v = 0; v < vStep; v++ )
+ {
+ for( u = 0; u < ( uStep - 2 ); u++ )
+ {
+ lines[offset + u] =
+ PMLine( u * vStep + v + 1, ( u + 1 ) * vStep + v + 1 );
+ }
+ offset += ( uStep - 2 );
+ }
+ // lines at the "south pole"
+ for( v = 0; v < vStep; v++ )
+ lines[offset + v] = PMLine( ( uStep - 2 ) * vStep + v + 1,
+ ( uStep - 1 ) * vStep + 1 );
+ // offset += vStep;
+}
+
+void PMBlobSphere::createPoints( PMPointArray& points, const PMVector& centre,
+ double radius, int uStep, int vStep )
+{
+ double l_UradStep = M_PI / uStep;
+ double l_VradStep = ( 2.0 * M_PI ) / vStep;
+ double l_u = l_UradStep;
+ int u, v;
+
+ points[0] = PMPoint( centre + PMVector( 0, radius, 0 ) );
+ points[vStep * ( uStep - 1 ) + 1] =
+ PMPoint( centre - PMVector( 0, radius, 0 ) );
+
+ for( u = 0; u < ( uStep - 1 ); u++ )
+ {
+ double l_v = 0.0;
+ double l_rcosu = radius * sin( l_u );
+ double y = ( radius * cos( l_u ) ) + centre[1];
+ for( v = 0; v < vStep ; v++ )
+ {
+
+ double x = ( l_rcosu * cos( l_v ) ) + centre[0];
+ double z = ( l_rcosu * sin( l_v ) ) + centre[2];
+
+ points[u * vStep + v + 1] = PMPoint( x, y, z );
+ l_v = l_v + l_VradStep;
+ }
+ l_u = l_u + l_UradStep;
+ }
+}
+
+void PMBlobSphere::setRadius( double radius )
+{
+ if( m_radius != radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusID, m_radius );
+ m_radius = radius;
+ setViewStructureChanged( );
+ }
+}
+
+void PMBlobSphere::setCentre( const PMVector& centre )
+{
+ if( m_centre != centre )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCentreID, m_centre );
+ m_centre = centre;
+ setViewStructureChanged( );
+ }
+}
+
+void PMBlobSphere::setStrength( double s )
+{
+ if( m_strength != s )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMStrengthID, m_strength );
+ m_strength = s;
+ }
+}
+
+void PMBlobSphere::setUSteps( int u )
+{
+ if( u >= 2 )
+ {
+ s_uStep = u;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMBlobSphere::setUSteps: U must be greater than 1\n";
+ s_parameterKey++;
+}
+
+void PMBlobSphere::setVSteps( int v )
+{
+ if( v >= 4 )
+ {
+ s_vStep = v;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMBlobSphere::setVSteps: V must be greater than 3\n";
+ s_parameterKey++;
+}
+
+void PMBlobSphere::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmblobsphere.h b/kpovmodeler/pmblobsphere.h
new file mode 100644
index 00000000..bb75b856
--- /dev/null
+++ b/kpovmodeler/pmblobsphere.h
@@ -0,0 +1,168 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ -------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBLOBSPHERE_H
+#define PMBLOBSPHERE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdetailobject.h"
+#include "pmvector.h"
+#include "pmviewstructure.h"
+
+/**
+ * Class for povray sphere.
+ */
+class PMBlobSphere : public PMDetailObject
+{
+ typedef PMDetailObject Base;
+
+public:
+ /**
+ * Create an empty BlobSphere
+ */
+ PMBlobSphere( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMBlobSphere( const PMBlobSphere& s );
+ /**
+ * Delete the PMBlobSphere
+ */
+ virtual ~PMBlobSphere( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMBlobSphere( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMBlobSphereEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmblobsphere" ); }
+
+ /**
+ * Returns the centre of the sphere
+ */
+ PMVector centre( ) const { return m_centre; }
+ /**
+ * Set the centre of the sphere
+ */
+ void setCentre( const PMVector& centre );
+ /**
+ * returns the radius of the sphere
+ */
+ double radius( ) const { return m_radius; }
+ /**
+ * Sets the radius of the sphere
+ */
+ void setRadius( double radius );
+ /**
+ * Returns the components strength
+ */
+ double strength( ) const { return m_strength; }
+ /**
+ * Sets the strength
+ */
+ void setStrength( double s );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+
+ /**
+ * Sets the number of latitutes
+ */
+ static void setUSteps( int u );
+ /**
+ * Sets the number of longitudes
+ */
+ static void setVSteps( int v );
+ /**
+ * Returns the number or latitutes
+ */
+ static int uSteps( ) { return s_uStep; }
+ /**
+ * Returns the number or longitudes
+ */
+ static int vSteps( ) { return s_vStep; }
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey(); }
+
+private:
+ /**
+ * Creates the lines for the view structure
+ */
+ static void createLines( PMLineArray& lines, int uStep, int vStep );
+ /**
+ * Creates the points for the view structure
+ */
+ static void createPoints( PMPointArray& points, const PMVector& centre,
+ double radius, int uStep, int vStep );
+
+ enum PMBlobSphereMementoID { PMRadiusID, PMCentreID, PMStrengthID };
+ /**
+ * Radius of the sphere
+ */
+ double m_radius;
+ /**
+ * centre of the sphere
+ */
+ PMVector m_centre;
+ double m_strength;
+
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_vStep;
+ static int s_uStep;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmblobsphereedit.cpp b/kpovmodeler/pmblobsphereedit.cpp
new file mode 100644
index 00000000..26291248
--- /dev/null
+++ b/kpovmodeler/pmblobsphereedit.cpp
@@ -0,0 +1,102 @@
+/*
+**************************************************************************
+ description
+ -------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmblobsphereedit.h"
+#include "pmblobsphere.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+PMBlobSphereEdit::PMBlobSphereEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMBlobSphereEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+
+ m_pCentre = new PMVectorEdit( "x", "y", "z", this );
+ m_pRadius = new PMFloatEdit( this );
+ m_pStrength = new PMFloatEdit( this );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Center:" ), this ) );
+ layout->addWidget( m_pCentre );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ QGridLayout* gl = new QGridLayout( layout, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Radius:" ), this ), 0, 0 );
+ gl->addWidget( m_pRadius, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Strength:" ), this ), 1, 0 );
+ gl->addWidget( m_pStrength, 1, 1 );
+ layout->addStretch( 1 );
+
+ connect( m_pCentre, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pStrength, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMBlobSphereEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "BlobSphere" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMBlobSphere* ) o;
+
+ m_pCentre->setVector( m_pDisplayedObject->centre( ) );
+ m_pRadius->setValue( m_pDisplayedObject->radius( ) );
+ m_pStrength->setValue( m_pDisplayedObject->strength( ) );
+
+ m_pCentre->setReadOnly( readOnly );
+ m_pRadius->setReadOnly( readOnly );
+ m_pStrength->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMBlobSphereEdit: Can't display object\n";
+}
+
+void PMBlobSphereEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setCentre( m_pCentre->vector( ) );
+ m_pDisplayedObject->setRadius( m_pRadius->value( ) );
+ m_pDisplayedObject->setStrength( m_pStrength->value( ) );
+ }
+}
+
+bool PMBlobSphereEdit::isDataValid( )
+{
+ if( m_pCentre->isDataValid( ) )
+ if( m_pRadius->isDataValid( ) )
+ if( m_pStrength->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+
+#include "pmblobsphereedit.moc"
diff --git a/kpovmodeler/pmblobsphereedit.h b/kpovmodeler/pmblobsphereedit.h
new file mode 100644
index 00000000..08f0f1d4
--- /dev/null
+++ b/kpovmodeler/pmblobsphereedit.h
@@ -0,0 +1,63 @@
+/*
+**************************************************************************
+ description
+ -------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMBLOBSPHEREEDIT_H
+#define PMBLOBSPHEREEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdetailobjectedit.h"
+
+class PMBlobSphere;
+class PMVectorEdit;
+class PMFloatEdit ;
+
+/**
+ * Dialog edit class for @ref PMBlobSphere
+ */
+class PMBlobSphereEdit : public PMDetailObjectEdit
+{
+ Q_OBJECT
+ typedef PMDetailObjectEdit Base;
+public:
+ /**
+ * Creates a PMBlobSphereEdit with parent and name
+ */
+ PMBlobSphereEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMBlobSphere* m_pDisplayedObject;
+ PMVectorEdit* m_pCentre;
+ PMFloatEdit* m_pRadius;
+ PMFloatEdit* m_pStrength;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmboundedby.cpp b/kpovmodeler/pmboundedby.cpp
new file mode 100644
index 00000000..127a05f8
--- /dev/null
+++ b/kpovmodeler/pmboundedby.cpp
@@ -0,0 +1,114 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmboundedby.h"
+#include "pmboundedbyedit.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMBoundedBy, PMBoundedByProperty );
+
+PMMetaObject* PMBoundedBy::s_pMetaObject = 0;
+PMObject* createNewBoundedBy( PMPart* part )
+{
+ return new PMBoundedBy( part );
+}
+
+PMBoundedBy::PMBoundedBy( PMPart* part )
+ : Base( part )
+{
+}
+
+PMBoundedBy::~PMBoundedBy( )
+{
+}
+
+PMMetaObject* PMBoundedBy::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "BoundedBy", Base::metaObject( ),
+ createNewBoundedBy );
+ s_pMetaObject->addProperty(
+ new PMBoundedByProperty( "clippedBy", 0, &PMBoundedBy::clippedBy ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMBoundedBy::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMBoundedBy::description( ) const
+{
+ return i18n( "bounded by" );
+}
+
+bool PMBoundedBy::clippedBy( ) const
+{
+ bool cb = true;
+ PMObject* o = firstChild( );
+
+ for( ; o && cb; o = o->nextSibling( ) )
+ if( o->type( ) != "Comment" )
+ cb = false;
+
+ return cb;
+}
+
+void PMBoundedBy::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ // no extra data at the moment
+ Base::serialize( e, doc );
+}
+
+void PMBoundedBy::readAttributes( const PMXMLHelper& h )
+{
+ // no extra data at the moment
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMBoundedBy::editWidget( QWidget* parent ) const
+{
+ return new PMBoundedByEdit( parent );
+}
+
+void PMBoundedBy::childRemoved( PMObject* o )
+{
+ Base::childRemoved( o );
+
+ // add a dummy change
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMClippedByID, true );
+}
+
+void PMBoundedBy::childAdded( PMObject* o )
+{
+ Base::childAdded( o );
+
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMClippedByID, true );
+}
diff --git a/kpovmodeler/pmboundedby.h b/kpovmodeler/pmboundedby.h
new file mode 100644
index 00000000..22ac3fb4
--- /dev/null
+++ b/kpovmodeler/pmboundedby.h
@@ -0,0 +1,89 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMBOUNDEDBY_H
+#define PMBOUNDEDBY_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcompositeobject.h"
+
+/**
+ * class for bounded_by povray statements
+ */
+
+class PMBoundedBy : public PMCompositeObject
+{
+ typedef PMCompositeObject Base;
+public:
+ /**
+ * Creates an empty PMBoundedBy
+ */
+ PMBoundedBy( PMPart* part );
+ /**
+ * Deletes the object
+ */
+ ~PMBoundedBy( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMBoundedBy( *this ); }
+
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual bool dataChangeOnInsertRemove( ) const { return true; }
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMBoundedByEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmboundedby" ); }
+
+ /** */
+ virtual void childRemoved( PMObject* );
+ /** */
+ virtual void childAdded( PMObject* );
+
+ /**
+ * Returns true if the object contains no child objects (exmbumcept comments)
+ */
+ bool clippedBy( ) const;
+
+private:
+ enum PMBoundedByMementoID { PMClippedByID };
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmboundedbyedit.cpp b/kpovmodeler/pmboundedbyedit.cpp
new file mode 100644
index 00000000..2bf1409e
--- /dev/null
+++ b/kpovmodeler/pmboundedbyedit.cpp
@@ -0,0 +1,65 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmboundedbyedit.h"
+#include "pmboundedby.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+PMBoundedByEdit::PMBoundedByEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMBoundedByEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pChildLabel = new QLabel( i18n( "No child objects" ), this );
+ topLayout( )->addWidget( m_pChildLabel );
+ m_pClippedByLabel = new QLabel( i18n( "(= clipped by)" ), this );
+ topLayout( )->addWidget( m_pClippedByLabel );
+}
+
+void PMBoundedByEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "BoundedBy" ) )
+ {
+ m_pDisplayedObject = ( PMBoundedBy* ) o;
+
+ if( m_pDisplayedObject->clippedBy( ) )
+ {
+ m_pChildLabel->show( );
+ m_pClippedByLabel->show( );
+ }
+ else
+ {
+ m_pChildLabel->hide( );
+ m_pClippedByLabel->hide( );
+ }
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMBoundedByEdit: Can't display object\n";
+}
+
+#include "pmboundedbyedit.moc"
diff --git a/kpovmodeler/pmboundedbyedit.h b/kpovmodeler/pmboundedbyedit.h
new file mode 100644
index 00000000..f4d24a41
--- /dev/null
+++ b/kpovmodeler/pmboundedbyedit.h
@@ -0,0 +1,59 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBOUNDEDBYEDIT_H
+#define PMBOUNDEDBYEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMBoundedBy;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMBoundedBy
+ */
+class PMBoundedByEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMBoundedByEdit with parent and name
+ */
+ PMBoundedByEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+
+private:
+ PMBoundedBy* m_pDisplayedObject;
+ QLabel* m_pChildLabel;
+ QLabel* m_pClippedByLabel;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmbox.cpp b/kpovmodeler/pmbox.cpp
new file mode 100644
index 00000000..045389bb
--- /dev/null
+++ b/kpovmodeler/pmbox.cpp
@@ -0,0 +1,276 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmbox.h"
+
+#include "pmxmlhelper.h"
+#include "pmboxedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm3dcontrolpoint.h"
+
+#include <klocale.h>
+
+const double defaultBoxSize = 0.5;
+const PMVector corner1Default = PMVector( -defaultBoxSize, -defaultBoxSize, -defaultBoxSize );
+const PMVector corner2Default = PMVector( defaultBoxSize, defaultBoxSize, defaultBoxSize );
+
+PMDefinePropertyClass( PMBox, PMBoxProperty );
+
+PMViewStructure* PMBox::s_pDefaultViewStructure = 0;
+PMMetaObject* PMBox::s_pMetaObject = 0;
+PMObject* createNewBox( PMPart* part )
+{
+ return new PMBox( part );
+}
+
+PMBox::PMBox( PMPart* part )
+ : Base( part )
+{
+ m_corner1 = corner1Default;
+ m_corner2 = corner2Default;
+}
+
+PMBox::PMBox( const PMBox& b )
+ : Base( b )
+{
+ m_corner1 = b.m_corner1;
+ m_corner2 = b.m_corner2;
+}
+
+PMBox::~PMBox( )
+{
+}
+
+QString PMBox::description( ) const
+{
+ return i18n( "box" );
+}
+
+void PMBox::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "corner_a", m_corner1.serializeXML( ) );
+ e.setAttribute( "corner_b", m_corner2.serializeXML( ) );
+ Base::serialize( e, doc );
+}
+
+void PMBox::readAttributes( const PMXMLHelper& h )
+{
+ m_corner1 = h.vectorAttribute( "corner_a", corner1Default );
+ m_corner2 = h.vectorAttribute( "corner_b", corner2Default );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMBox::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Box", Base::metaObject( ),
+ createNewBox );
+ s_pMetaObject->addProperty(
+ new PMBoxProperty( "corner1", &PMBox::setCorner1, &PMBox::corner1 ) );
+ s_pMetaObject->addProperty(
+ new PMBoxProperty( "corner2", &PMBox::setCorner2, &PMBox::corner2 ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMBox::setCorner1( const PMVector& p )
+{
+ if( p != m_corner1 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCorner1ID, m_corner1 );
+ m_corner1 = p;
+ m_corner1.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMBox::setCorner2( const PMVector& p )
+{
+ if( p != m_corner2 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCorner2ID, m_corner2 );
+ m_corner2 = p;
+ m_corner2.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+PMDialogEditBase* PMBox::editWidget( QWidget* parent ) const
+{
+ return new PMBoxEdit( parent );
+}
+
+void PMBox::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMCorner1ID:
+ setCorner1( data->vectorData( ) );
+ break;
+ case PMCorner2ID:
+ setCorner2( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMBox::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+
+bool PMBox::isDefault( )
+{
+ if( ( m_corner1 == corner1Default ) && ( m_corner2 == corner2Default ) )
+ return true;
+ return false;
+}
+
+void PMBox::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+
+ points[0][0] = m_corner1[0];
+ points[0][1] = m_corner1[1];
+ points[0][2] = m_corner1[2];
+
+ points[1][0] = m_corner2[0];
+ points[1][1] = m_corner1[1];
+ points[1][2] = m_corner1[2];
+
+ points[2][0] = m_corner2[0];
+ points[2][1] = m_corner1[1];
+ points[2][2] = m_corner2[2];
+
+ points[3][0] = m_corner1[0];
+ points[3][1] = m_corner1[1];
+ points[3][2] = m_corner2[2];
+
+ points[4][0] = m_corner1[0];
+ points[4][1] = m_corner2[1];
+ points[4][2] = m_corner1[2];
+
+ points[5][0] = m_corner2[0];
+ points[5][1] = m_corner2[1];
+ points[5][2] = m_corner1[2];
+
+ points[6][0] = m_corner2[0];
+ points[6][1] = m_corner2[1];
+ points[6][2] = m_corner2[2];
+
+ points[7][0] = m_corner1[0];
+ points[7][1] = m_corner2[1];
+ points[7][2] = m_corner2[2];
+}
+
+PMViewStructure* PMBox::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure )
+ {
+ s_pDefaultViewStructure = new PMViewStructure( 8, 12 );
+ PMPointArray& points = s_pDefaultViewStructure->points( );
+ PMLineArray& lines = s_pDefaultViewStructure->lines( );
+
+ points[0] = PMPoint( -defaultBoxSize, -defaultBoxSize, -defaultBoxSize );
+ points[1] = PMPoint( defaultBoxSize, -defaultBoxSize, -defaultBoxSize );
+ points[2] = PMPoint( defaultBoxSize, -defaultBoxSize, defaultBoxSize );
+ points[3] = PMPoint( -defaultBoxSize, -defaultBoxSize, defaultBoxSize );
+ points[4] = PMPoint( -defaultBoxSize, defaultBoxSize, -defaultBoxSize );
+ points[5] = PMPoint( defaultBoxSize, defaultBoxSize, -defaultBoxSize );
+ points[6] = PMPoint( defaultBoxSize, defaultBoxSize, defaultBoxSize );
+ points[7] = PMPoint( -defaultBoxSize, defaultBoxSize, defaultBoxSize );
+
+ lines[ 0] = PMLine( 0, 1 );
+ lines[ 1] = PMLine( 0, 3 );
+ lines[ 2] = PMLine( 0, 4 );
+ lines[ 3] = PMLine( 1, 2 );
+ lines[ 4] = PMLine( 1, 5 );
+ lines[ 5] = PMLine( 2, 3 );
+ lines[ 6] = PMLine( 2, 6 );
+ lines[ 7] = PMLine( 3, 7 );
+ lines[ 8] = PMLine( 4, 5 );
+ lines[ 9] = PMLine( 4, 7 );
+ lines[10] = PMLine( 5, 6 );
+ lines[11] = PMLine( 6, 7 );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMBox::controlPoints( PMControlPointList& list )
+{
+ list.append( new PM3DControlPoint( m_corner1, PMCorner1ID,
+ i18n( "Corner 1" ) ) );
+ list.append( new PM3DControlPoint( m_corner2, PMCorner2ID,
+ i18n( "Corner 2" ) ) );
+}
+
+void PMBox::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMCorner1ID:
+ setCorner1( ( ( PM3DControlPoint* ) p )->point( ) );
+ break;
+ case PMCorner2ID:
+ setCorner2( ( ( PM3DControlPoint* ) p )->point( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMBox::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+}
+
+void PMBox::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmbox.h b/kpovmodeler/pmbox.h
new file mode 100644
index 00000000..d6627ffe
--- /dev/null
+++ b/kpovmodeler/pmbox.h
@@ -0,0 +1,123 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBOX_H
+#define PMBOX_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray boxes.
+ */
+
+class PMBox : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMBox
+ */
+ PMBox( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMBox( const PMBox& b );
+ /**
+ * deletes the PMBox
+ */
+ virtual ~PMBox( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMBox( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMBoxEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmbox" ); }
+
+ /**
+ * Returns Corner_1
+ */
+ PMVector corner1( ) const { return m_corner1; }
+ /**
+ * Sets Corner_1
+ */
+ void setCorner1( const PMVector& p );
+ /**
+ * Returns Corner_2
+ */
+ PMVector corner2( ) const { return m_corner2; }
+ /**
+ * Sets Corner_2
+ */
+ void setCorner2( const PMVector& p );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMBoxMementoID { PMCorner1ID, PMCorner2ID };
+ PMVector m_corner1, m_corner2;
+
+ /**
+ * The default view structure. It can be shared between boxes
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmboxedit.cpp b/kpovmodeler/pmboxedit.cpp
new file mode 100644
index 00000000..2db1eb79
--- /dev/null
+++ b/kpovmodeler/pmboxedit.cpp
@@ -0,0 +1,86 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmboxedit.h"
+#include "pmbox.h"
+#include "pmvectoredit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+PMBoxEdit::PMBoxEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMBoxEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pCorner1 = new PMVectorEdit( "x", "y", "z", this );
+ m_pCorner2 = new PMVectorEdit( "x", "y", "z", this );
+
+ QGridLayout* gl = new QGridLayout( topLayout( ), 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Corner 1:" ), this ), 0, 0 );
+ gl->addWidget( m_pCorner1, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Corner 2:" ), this ), 1, 0 );
+ gl->addWidget( m_pCorner2, 1, 1 );
+
+ connect( m_pCorner1, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCorner2, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMBoxEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Box" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMBox* ) o;
+
+ m_pCorner1->setVector( m_pDisplayedObject->corner1( ) );
+ m_pCorner2->setVector( m_pDisplayedObject->corner2( ) );
+
+ m_pCorner1->setReadOnly( readOnly );
+ m_pCorner2->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMBoxEdit: Can't display object\n";
+}
+
+void PMBoxEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setCorner1( m_pCorner1->vector( ) );
+ m_pDisplayedObject->setCorner2( m_pCorner2->vector( ) );
+ }
+}
+
+bool PMBoxEdit::isDataValid( )
+{
+ if( m_pCorner1->isDataValid( ) )
+ if( m_pCorner2->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+#include "pmboxedit.moc"
diff --git a/kpovmodeler/pmboxedit.h b/kpovmodeler/pmboxedit.h
new file mode 100644
index 00000000..4f87ceac
--- /dev/null
+++ b/kpovmodeler/pmboxedit.h
@@ -0,0 +1,63 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBOXEDIT_H
+#define PMBOXEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMBox;
+class PMVectorEdit;
+
+/**
+ * Dialog edit class for @ref PMBox
+ */
+class PMBoxEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMBoxEdit with parent and name
+ */
+ PMBoxEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMBox* m_pDisplayedObject;
+ PMVectorEdit* m_pCorner1;
+ PMVectorEdit* m_pCorner2;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmbumpmap.cpp b/kpovmodeler/pmbumpmap.cpp
new file mode 100644
index 00000000..e9549bd9
--- /dev/null
+++ b/kpovmodeler/pmbumpmap.cpp
@@ -0,0 +1,384 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmbumpmapedit.h"
+#include "pmbumpmap.h"
+#include "pmpalettevalue.h"
+#include "pmpalettevaluememento.h"
+
+#include "pmxmlhelper.h"
+#include "pmcompositeobject.h"
+#include "pmmemento.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+const PMBumpMap::PMBitmapType bitmapTypeDefault = PMBumpMap::BitmapSys;
+const char *const bitmapFileDefault = 0;
+const bool enableFilterAllDefault = false;
+const bool enableTransmitAllDefault = false;
+const double filterAllDefault = 0.0;
+const double transmitAllDefault = 0.0;
+const bool onceDefault = false;
+const PMBumpMap::PMMapType mapTypeDefault = PMBumpMap::MapPlanar;
+const PMBumpMap::PMInterpolateType interpolateTypeDefault = PMBumpMap::InterpolateNone;
+const bool useIndexDefault = false;
+const double bumpSizeDefault = 0.0;
+
+PMDefinePropertyClass( PMBumpMap, PMBumpMapProperty );
+PMDefineEnumPropertyClass( PMBumpMap, PMBumpMap::PMBitmapType,
+ PMBitmapTypeProperty );
+PMDefineEnumPropertyClass( PMBumpMap, PMBumpMap::PMInterpolateType,
+ PMInterpolateTypeProperty );
+PMDefineEnumPropertyClass( PMBumpMap, PMBumpMap::PMMapType,
+ PMMapTypeProperty );
+
+PMMetaObject* PMBumpMap::s_pMetaObject = 0;
+PMObject* createNewBumpMap( PMPart* part )
+{
+ return new PMBumpMap( part );
+}
+
+PMBumpMap::PMBumpMap( PMPart* part )
+ : Base( part )
+{
+ m_bitmapType = bitmapTypeDefault;
+ m_bitmapFile = bitmapFileDefault;
+ m_once = onceDefault;
+ m_mapType = mapTypeDefault;
+ m_interpolateType = interpolateTypeDefault;
+ m_useIndex = useIndexDefault;
+ m_bumpSize = bumpSizeDefault;
+}
+
+PMBumpMap::PMBumpMap( const PMBumpMap& m )
+ : Base( m )
+{
+ m_bitmapType = m.m_bitmapType;
+ m_bitmapFile = m.m_bitmapFile;
+ m_once = m.m_once;
+ m_mapType = m.m_mapType;
+ m_interpolateType = m.m_interpolateType;
+ m_useIndex = m.m_useIndex;
+ m_bumpSize = m.m_bumpSize;
+}
+
+PMBumpMap::~PMBumpMap( )
+{
+}
+
+void PMBumpMap::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ switch( m_bitmapType )
+ {
+ case BitmapGif:
+ e.setAttribute( "bitmap_type", "gif" );
+ break;
+ case BitmapTga:
+ e.setAttribute( "bitmap_type", "tga" );
+ break;
+ case BitmapIff:
+ e.setAttribute( "bitmap_type", "iff" );
+ break;
+ case BitmapPpm:
+ e.setAttribute( "bitmap_type", "ppm" );
+ break;
+ case BitmapPgm:
+ e.setAttribute( "bitmap_type", "pgm" );
+ break;
+ case BitmapPng:
+ e.setAttribute( "bitmap_type", "png" );
+ break;
+ case BitmapJpeg:
+ e.setAttribute( "bitmap_type", "jpeg" );
+ break;
+ case BitmapTiff:
+ e.setAttribute( "bitmap_type", "tiff" );
+ break;
+ case BitmapSys:
+ e.setAttribute( "bitmap_type", "sys" );
+ break;
+ }
+ e.setAttribute( "file_name", m_bitmapFile );
+ e.setAttribute( "once", m_once );
+ switch( m_mapType )
+ {
+ case MapPlanar:
+ e.setAttribute( "map_type", "planar" );
+ break;
+ case MapSpherical:
+ e.setAttribute( "map_type", "spherical" );
+ break;
+ case MapCylindrical:
+ e.setAttribute( "map_type", "cylindrical" );
+ break;
+ case MapToroidal:
+ e.setAttribute( "map_type", "toroidal" );
+ break;
+ }
+ switch( m_interpolateType )
+ {
+ case InterpolateNone:
+ e.setAttribute( "interpolate", "none" );
+ break;
+ case InterpolateBilinear:
+ e.setAttribute( "interpolate", "bilinear" );
+ break;
+ case InterpolateNormalized:
+ e.setAttribute( "interpolate", "normalized" );
+ break;
+ }
+ e.setAttribute( "use_index", m_useIndex );
+ e.setAttribute( "bump_size", m_bumpSize );
+
+ Base::serialize( e, doc );
+}
+
+void PMBumpMap::readAttributes( const PMXMLHelper& h )
+{
+ QString str;
+
+ str = h.stringAttribute( "bitmap_type", "sys" );
+ if( str == "gif" )
+ m_bitmapType = BitmapGif;
+ else if( str == "tga" )
+ m_bitmapType = BitmapTga;
+ else if( str == "iff" )
+ m_bitmapType = BitmapIff;
+ else if( str == "ppm" )
+ m_bitmapType = BitmapPpm;
+ else if( str == "pgm" )
+ m_bitmapType = BitmapPgm;
+ else if( str == "png" )
+ m_bitmapType = BitmapPng;
+ else if( str == "jpeg" )
+ m_bitmapType = BitmapJpeg;
+ else if( str == "tiff" )
+ m_bitmapType = BitmapTiff;
+ else if( str == "sys" )
+ m_bitmapType = BitmapSys;
+
+ m_bitmapFile = h.stringAttribute( "file_name", bitmapFileDefault );
+ m_once = h.boolAttribute( "once", onceDefault );
+
+ str = h.stringAttribute( "map_type", "planar" );
+ if( str == "planar" )
+ m_mapType = MapPlanar;
+ else if( str == "spherical" )
+ m_mapType = MapSpherical;
+ else if( str == "cylindrical" )
+ m_mapType = MapCylindrical;
+ else if( str == "toroidal" )
+ m_mapType = MapToroidal;
+
+ str = h.stringAttribute( "interpolate", "none" );
+ if( str == "none" )
+ m_interpolateType = InterpolateNone;
+ else if( str == "bilinear" )
+ m_interpolateType = InterpolateBilinear;
+ else if( str == "normalized" )
+ m_interpolateType = InterpolateNormalized;
+
+ m_useIndex = h.boolAttribute( "use_index", useIndexDefault );
+ m_bumpSize = h.doubleAttribute( "bump_size", bumpSizeDefault );
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMBumpMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "BumpMap", Base::metaObject( ),
+ createNewBumpMap );
+
+ PMBitmapTypeProperty* bp = new PMBitmapTypeProperty(
+ "bitmapType", &PMBumpMap::setBitmapType,
+ &PMBumpMap::bitmapType );
+ bp->addEnumValue( "Gif", BitmapGif );
+ bp->addEnumValue( "Tga", BitmapTga );
+ bp->addEnumValue( "Iff", BitmapIff );
+ bp->addEnumValue( "Ppm", BitmapPpm );
+ bp->addEnumValue( "Pgm", BitmapPgm );
+ bp->addEnumValue( "Png", BitmapPng );
+ bp->addEnumValue( "Jpeg", BitmapJpeg );
+ bp->addEnumValue( "Tiff", BitmapTiff );
+ bp->addEnumValue( "Sys", BitmapSys );
+ s_pMetaObject->addProperty( bp );
+
+ PMInterpolateTypeProperty* ip = new PMInterpolateTypeProperty(
+ "interpolateType", &PMBumpMap::setInterpolateType,
+ &PMBumpMap::interpolateType );
+ ip->addEnumValue( "None", InterpolateNone );
+ ip->addEnumValue( "Bilinear", InterpolateBilinear );
+ ip->addEnumValue( "Normalized", InterpolateNormalized );
+ s_pMetaObject->addProperty( ip );
+
+ PMMapTypeProperty* mp = new PMMapTypeProperty(
+ "mapType", &PMBumpMap::setMapType, &PMBumpMap::mapType );
+ mp->addEnumValue( "Planar", MapPlanar );
+ mp->addEnumValue( "Spherical", MapSpherical );
+ mp->addEnumValue( "Cylindrical", MapCylindrical );
+ mp->addEnumValue( "Toroidal", MapToroidal );
+ s_pMetaObject->addProperty( mp );
+
+ s_pMetaObject->addProperty(
+ new PMBumpMapProperty( "bitmapFile", &PMBumpMap::setBitmapFileName,
+ &PMBumpMap::bitmapFile ) );
+ s_pMetaObject->addProperty(
+ new PMBumpMapProperty( "useIndex", &PMBumpMap::enableUseIndex,
+ &PMBumpMap::isUseIndexEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMBumpMapProperty( "once", &PMBumpMap::enableOnce,
+ &PMBumpMap::isOnceEnabled ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMBumpMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+
+QString PMBumpMap::description( ) const
+{
+ return i18n( "bump map" );
+}
+
+void PMBumpMap::setBitmapType( PMBitmapType c )
+{
+ if( c != m_bitmapType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBitmapTypeID, m_bitmapType );
+ m_bitmapType = c;
+ }
+}
+
+void PMBumpMap::setBitmapFileName( const QString& c )
+{
+ if( c != m_bitmapFile )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBitmapFileID, m_bitmapFile );
+ m_bitmapFile = c;
+ }
+}
+
+void PMBumpMap::enableUseIndex( bool c )
+{
+ if( c != m_useIndex )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUseIndexID, m_useIndex );
+ m_useIndex = c;
+ }
+}
+
+void PMBumpMap::setMapType( PMMapType c )
+{
+ if( c != m_mapType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMapTypeID, m_mapType );
+ m_mapType = c;
+ }
+}
+
+void PMBumpMap::setInterpolateType( PMInterpolateType c )
+{
+ if( c != m_interpolateType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMInterpolateID, m_interpolateType );
+ m_interpolateType = c;
+ }
+}
+
+void PMBumpMap::enableOnce( bool c )
+{
+ if( c != m_once )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOnceID, m_once );
+ m_once = c;
+ }
+}
+
+void PMBumpMap::setBumpSize( double c )
+{
+ if( c != m_bumpSize )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBumpSizeID, m_bumpSize );
+ m_bumpSize = c;
+ }
+}
+
+PMDialogEditBase* PMBumpMap::editWidget( QWidget* parent ) const
+{
+ return new PMBumpMapEdit( parent );
+}
+
+void PMBumpMap::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMBitmapTypeID:
+ setBitmapType( ( PMBitmapType )data->intData( ) );
+ break;
+ case PMBitmapFileID:
+ setBitmapFileName( data->stringData( ) );
+ break;
+ case PMOnceID:
+ enableOnce( data->boolData( ) );
+ break;
+ case PMMapTypeID:
+ setMapType( ( PMMapType )data->intData( ) );
+ break;
+ case PMInterpolateID:
+ setInterpolateType( ( PMInterpolateType )data->intData( ) );
+ break;
+ case PMUseIndexID:
+ enableUseIndex( data->boolData( ) );
+ break;
+ case PMBumpSizeID:
+ setBumpSize( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMBumpMap::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmbumpmap.h b/kpovmodeler/pmbumpmap.h
new file mode 100644
index 00000000..69bf53a3
--- /dev/null
+++ b/kpovmodeler/pmbumpmap.h
@@ -0,0 +1,172 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBUMPMAP_H
+#define PMBUMPMAP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+#include "pmpalettevalue.h"
+
+/**
+ * Class for povray bumpmaps.
+ */
+
+class PMBumpMap : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+public:
+ /**
+ * The bitmap type
+ */
+ enum PMBitmapType { BitmapGif, BitmapTga, BitmapIff, BitmapPpm,
+ BitmapPgm, BitmapPng, BitmapJpeg, BitmapTiff,
+ BitmapSys };
+ /**
+ * The interpolate method
+ */
+ enum PMInterpolateType { InterpolateNone, InterpolateBilinear,
+ InterpolateNormalized };
+ /**
+ * The mapping method
+ */
+ enum PMMapType { MapPlanar, MapSpherical, MapCylindrical,
+ MapToroidal };
+
+
+ /**
+ * Creates a PMBumpMap
+ */
+ PMBumpMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMBumpMap( const PMBumpMap& m );
+ /**
+ * deletes the PMBumpMap
+ */
+ virtual ~PMBumpMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMBumpMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmbumpmap" ); }
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMBumpMapEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+
+ /**
+ * Gets the bitmap type
+ */
+ PMBitmapType bitmapType( ) const { return m_bitmapType; }
+ /**
+ * Gets the bitmap file name
+ */
+ QString bitmapFile( ) const { return m_bitmapFile; }
+ /**
+ * Returns true if use_index is enabled
+ */
+ bool isUseIndexEnabled( ) const { return m_useIndex; }
+ /**
+ * Returns the bump size
+ */
+ double bumpSize( ) const { return m_bumpSize; }
+ /**
+ * Returns true if once is enabled
+ */
+ bool isOnceEnabled( ) const { return m_once; }
+ /**
+ * Gets the bitmap file type
+ */
+ PMMapType mapType( ) const { return m_mapType; }
+ /**
+ * Gets the interpolate method type
+ */
+ PMInterpolateType interpolateType( ) const { return m_interpolateType; }
+
+
+ /**
+ * Sets the bumpmap type
+ */
+ void setBitmapType( PMBitmapType c );
+ /**
+ * Sets the bitmap file name*/
+ void setBitmapFileName( const QString& c );
+ /**
+ * Sets if use_index is enabled
+ */
+ void enableUseIndex( bool c );
+ /**
+ * Set the bump size
+ */
+ void setBumpSize( double c );
+ /**
+ * Sets if the bitmap should be mapped once
+ */
+ void enableOnce( bool c );
+ /**
+ * Sets the mapping method
+ */
+ void setMapType( const PMMapType c );
+ /**
+ * Sets the interpolating method
+ */
+ void setInterpolateType( PMInterpolateType c );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMBumpMapMementoID { PMBitmapTypeID, PMBitmapFileID,
+ PMOnceID, PMMapTypeID, PMInterpolateID,
+ PMUseIndexID, PMBumpSizeID };
+ /**
+ * BumpMap type
+ */
+ PMBitmapType m_bitmapType;
+ QString m_bitmapFile;
+ bool m_once;
+ PMMapType m_mapType;
+ PMInterpolateType m_interpolateType;
+ bool m_useIndex;
+ double m_bumpSize;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmbumpmapedit.cpp b/kpovmodeler/pmbumpmapedit.cpp
new file mode 100644
index 00000000..d792cec2
--- /dev/null
+++ b/kpovmodeler/pmbumpmapedit.cpp
@@ -0,0 +1,319 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmbumpmapedit.h"
+#include "pmbumpmap.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmpalettevalueedit.h"
+#include "pmvector.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <ktabctl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+
+PMBumpMapEdit::PMBumpMapEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMBumpMapEdit::createTopWidgets( )
+{
+ QLabel* lbl;
+ QHBoxLayout* hl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "File type:" ), this );
+ m_pImageFileTypeEdit = new QComboBox( this );
+ m_pImageFileTypeEdit->insertItem( "gif" );
+ m_pImageFileTypeEdit->insertItem( "tga" );
+ m_pImageFileTypeEdit->insertItem( "iff" );
+ m_pImageFileTypeEdit->insertItem( "ppm" );
+ m_pImageFileTypeEdit->insertItem( "pgm" );
+ m_pImageFileTypeEdit->insertItem( "png" );
+ m_pImageFileTypeEdit->insertItem( "jpeg" );
+ m_pImageFileTypeEdit->insertItem( "tiff" );
+ m_pImageFileTypeEdit->insertItem( "sys" );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pImageFileTypeEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "File name:" ), this );
+ m_pImageFileNameEdit = new QLineEdit( this );
+ m_pImageFileNameBrowse = new QPushButton( this );
+ m_pImageFileNameBrowse->setPixmap( SmallIcon( "fileopen" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pImageFileNameEdit );
+ hl->addWidget( m_pImageFileNameBrowse );
+ hl->addStretch( 1 );
+
+ m_pOnceEdit = new QCheckBox( i18n( "Once" ), this );
+ topLayout( )->addWidget( m_pOnceEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Interpolate:" ), this );
+ m_pInterpolateTypeEdit = new QComboBox( this );
+ m_pInterpolateTypeEdit->insertItem( i18n( "None" ) );
+ m_pInterpolateTypeEdit->insertItem( i18n( "Bilinear" ) );
+ m_pInterpolateTypeEdit->insertItem( i18n( "Normalized" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pInterpolateTypeEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Map type:" ), this );
+ m_pMapTypeEdit = new QComboBox( this );
+ m_pMapTypeEdit->insertItem( i18n( "Planar" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Spherical" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Cylindrical" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Toroidal" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pMapTypeEdit );
+ hl->addStretch( 1 );
+
+ m_pUseIndexEdit = new QCheckBox( i18n( "Use index" ), this );
+ topLayout( )->addWidget( m_pUseIndexEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Bump size:" ), this );
+ m_pBumpSizeEdit = new PMFloatEdit( this );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pBumpSizeEdit );
+ hl->addStretch( 1 );
+
+ connect( m_pImageFileTypeEdit, SIGNAL( activated( int ) ), SLOT( slotImageFileTypeChanged( int ) ) );
+ connect( m_pMapTypeEdit, SIGNAL( activated( int ) ), SLOT( slotMapTypeChanged( int ) ) );
+ connect( m_pInterpolateTypeEdit, SIGNAL( activated( int ) ), SLOT( slotInterpolateTypeChanged( int ) ) );
+ connect( m_pImageFileNameBrowse, SIGNAL( clicked( ) ), SLOT( slotImageFileBrowseClicked( ) ) );
+ connect( m_pImageFileNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotImageFileNameChanged( const QString& ) ) );
+ connect( m_pOnceEdit, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pUseIndexEdit, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pBumpSizeEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMBumpMapEdit::displayObject( PMObject* o )
+{
+ bool readOnly;
+
+ if( o->isA( "BumpMap" ) )
+ {
+ m_pDisplayedObject = ( PMBumpMap* ) o;
+ readOnly = m_pDisplayedObject->isReadOnly( );
+
+ switch( m_pDisplayedObject->bitmapType( ) )
+ {
+ case PMBumpMap::BitmapGif:
+ m_pImageFileTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMBumpMap::BitmapTga:
+ m_pImageFileTypeEdit->setCurrentItem( 1 );
+ break;
+ case PMBumpMap::BitmapIff:
+ m_pImageFileTypeEdit->setCurrentItem( 2 );
+ break;
+ case PMBumpMap::BitmapPpm:
+ m_pImageFileTypeEdit->setCurrentItem( 3 );
+ break;
+ case PMBumpMap::BitmapPgm:
+ m_pImageFileTypeEdit->setCurrentItem( 4 );
+ break;
+ case PMBumpMap::BitmapPng:
+ m_pImageFileTypeEdit->setCurrentItem( 5 );
+ break;
+ case PMBumpMap::BitmapJpeg:
+ m_pImageFileTypeEdit->setCurrentItem( 6 );
+ break;
+ case PMBumpMap::BitmapTiff:
+ m_pImageFileTypeEdit->setCurrentItem( 7 );
+ break;
+ case PMBumpMap::BitmapSys:
+ m_pImageFileTypeEdit->setCurrentItem( 8 );
+ break;
+ }
+ m_pImageFileTypeEdit->setEnabled( !readOnly );
+
+ switch( m_pDisplayedObject->interpolateType( ) )
+ {
+ case PMBumpMap::InterpolateNone:
+ m_pInterpolateTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMBumpMap::InterpolateBilinear:
+ m_pInterpolateTypeEdit->setCurrentItem( 1);
+ break;
+ case PMBumpMap::InterpolateNormalized:
+ m_pInterpolateTypeEdit->setCurrentItem( 2 );
+ break;
+ }
+ m_pInterpolateTypeEdit->setEnabled( !readOnly );
+
+ switch( m_pDisplayedObject->mapType( ) )
+ {
+ case PMBumpMap::MapPlanar:
+ m_pMapTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMBumpMap::MapSpherical:
+ m_pMapTypeEdit->setCurrentItem( 1 );
+ break;
+ case PMBumpMap::MapCylindrical:
+ m_pMapTypeEdit->setCurrentItem( 2 );
+ break;
+ case PMBumpMap::MapToroidal:
+ m_pMapTypeEdit->setCurrentItem( 3 );
+ break;
+ }
+ m_pMapTypeEdit->setEnabled( !readOnly );
+
+ m_pImageFileNameEdit->setText( m_pDisplayedObject->bitmapFile( ) );
+ m_pImageFileNameEdit->setEnabled( !readOnly );
+ m_pOnceEdit->setChecked( m_pDisplayedObject->isOnceEnabled( ) );
+ m_pOnceEdit->setEnabled( !readOnly );
+ m_pUseIndexEdit->setChecked( m_pDisplayedObject->isUseIndexEnabled( ) );
+ m_pUseIndexEdit->setEnabled( !readOnly );
+ m_pBumpSizeEdit->setValue( m_pDisplayedObject->bumpSize( ) );
+ m_pBumpSizeEdit->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+
+}
+
+void PMBumpMapEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ switch( m_pImageFileTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapGif );
+ break;
+ case 1:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapTga );
+ break;
+ case 2:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapIff );
+ break;
+ case 3:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapPpm );
+ break;
+ case 4:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapPgm );
+ break;
+ case 5:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapPng );
+ break;
+ case 6:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapJpeg );
+ break;
+ case 7:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapTiff );
+ break;
+ case 8:
+ m_pDisplayedObject->setBitmapType( PMBumpMap::BitmapSys );
+ break;
+ }
+
+ switch( m_pInterpolateTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setInterpolateType( PMBumpMap::InterpolateNone );
+ break;
+ case 1:
+ m_pDisplayedObject->setInterpolateType( PMBumpMap::InterpolateBilinear );
+ break;
+ case 2:
+ m_pDisplayedObject->setInterpolateType( PMBumpMap::InterpolateNormalized );
+ break;
+ }
+
+ switch( m_pMapTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setMapType( PMBumpMap::MapPlanar );
+ break;
+ case 1:
+ m_pDisplayedObject->setMapType( PMBumpMap::MapSpherical );
+ break;
+ case 2:
+ m_pDisplayedObject->setMapType( PMBumpMap::MapCylindrical );
+ break;
+ case 3:
+ m_pDisplayedObject->setMapType( PMBumpMap::MapToroidal );
+ break;
+ }
+
+ m_pDisplayedObject->setBitmapFileName( m_pImageFileNameEdit->text( ) );
+ m_pDisplayedObject->enableOnce( m_pOnceEdit->isChecked( ) );
+ m_pDisplayedObject->enableUseIndex( m_pUseIndexEdit->isChecked( ) );
+ m_pDisplayedObject->setBumpSize( m_pBumpSizeEdit->value( ) );
+ }
+}
+
+bool PMBumpMapEdit::isDataValid( )
+{
+ if( !m_pBumpSizeEdit->isDataValid( ) ) return false;
+
+ return Base::isDataValid( );
+}
+
+void PMBumpMapEdit::slotInterpolateTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMBumpMapEdit::slotImageFileTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMBumpMapEdit::slotMapTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMBumpMapEdit::slotImageFileNameChanged( const QString& /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMBumpMapEdit::slotImageFileBrowseClicked( )
+{
+ QString str = KFileDialog::getOpenFileName( QString::null, QString::null );
+
+ if( !str.isEmpty() )
+ {
+ m_pImageFileNameEdit->setText( str );
+ emit dataChanged( );
+ }
+}
+
+#include "pmbumpmapedit.moc"
diff --git a/kpovmodeler/pmbumpmapedit.h b/kpovmodeler/pmbumpmapedit.h
new file mode 100644
index 00000000..cceb2b84
--- /dev/null
+++ b/kpovmodeler/pmbumpmapedit.h
@@ -0,0 +1,86 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMBUMPMAPEDIT_H
+#define PMBUMPMAPEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmpalettevalueedit.h"
+#include "pmdialogeditbase.h"
+
+class PMBumpMap;
+class PMPaletteValue;
+class PMVectorEdit;
+class QComboBox;
+class PMFloatEdit;
+class PMIntEdit;
+class QLabel;
+class QCheckBox;
+class QWidget;
+class QLineEdit;
+class QPushButton;
+
+/**
+ * Dialog edit class for @ref PMBumpMap.
+ */
+class PMBumpMapEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMBumpMapEdit with parent and name
+ */
+ PMBumpMapEdit( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displayObject( PMObject* o );
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+private slots:
+ /** */
+ void slotImageFileTypeChanged( int a );
+ /** */
+ void slotMapTypeChanged( int a );
+ /** */
+ void slotInterpolateTypeChanged( int a );
+ /** */
+ void slotImageFileNameChanged( const QString& a );
+ /** */
+ void slotImageFileBrowseClicked( );
+private:
+ PMBumpMap* m_pDisplayedObject;
+ QComboBox* m_pImageFileTypeEdit;
+ QLineEdit* m_pImageFileNameEdit;
+ QPushButton* m_pImageFileNameBrowse;
+ QCheckBox* m_pOnceEdit;
+ QComboBox* m_pMapTypeEdit;
+ QComboBox* m_pInterpolateTypeEdit;
+ QCheckBox* m_pUseIndexEdit;
+ PMFloatEdit* m_pBumpSizeEdit;
+};
+
+#endif
diff --git a/kpovmodeler/pmcamera.cpp b/kpovmodeler/pmcamera.cpp
new file mode 100644
index 00000000..b224f340
--- /dev/null
+++ b/kpovmodeler/pmcamera.cpp
@@ -0,0 +1,769 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcamera.h"
+
+#include "pmxmlhelper.h"
+#include "pmcameraedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm3dcontrolpoint.h"
+#include "pmvectorcontrolpoint.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMCamera, PMCameraProperty );
+PMDefineEnumPropertyClass( PMCamera, PMCamera::CameraType,
+ PMCameraTypeProperty );
+
+PMViewStructure* PMCamera::s_pDefaultViewStructure = 0;
+PMMetaObject* PMCamera::s_pMetaObject = 0;
+PMObject* createNewCamera( PMPart* part )
+{
+ return new PMCamera( part );
+}
+
+const PMVector locationDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector lookAtDefault = PMVector( 0.0, 0.0, 1.0 );
+const PMVector directionDefault = PMVector( 0.0, 0.0, 1.0 );
+const PMVector upDefault = PMVector( 0.0, 1.0, 0.0 );
+const PMVector rightDefault = PMVector( 4.0/3.0, 0.0, 0.0 );
+const PMVector skyDefault = PMVector( 0.0, 1.0, 0.0 );
+//const double aspectDefault = 1.0;
+const bool angleEnabledDefault = false;
+const double angleDefault = 90.0;
+const PMCamera::CameraType cameraTypeDefault = PMCamera::Perspective;
+const int cylinderTypeDefault = 1;
+const bool focalBlurDefault = false;
+const double apertureDefault = 0.4;
+const int blurSamplesDefault = 10;
+const PMVector focalPointDefault = PMVector( 0.0, 0.0, 0.0 );
+const double confidenceDefault = 0.9;
+const double varianceDefault = 0.008;
+const bool c_defaultExport = true;
+
+PMCamera::PMCamera( PMPart* part )
+ : Base( part )
+{
+ m_location = locationDefault;
+ m_lookAt = lookAtDefault;
+ m_direction = directionDefault;
+
+ m_up = upDefault;
+ m_right = rightDefault;
+
+ m_sky = skyDefault;
+ m_angle = angleDefault;
+ m_angleEnabled = angleEnabledDefault;
+
+ m_cameraType = cameraTypeDefault;
+ m_cylinderType = cylinderTypeDefault;
+
+ m_focalBlurEnabled = focalBlurDefault;
+ m_aperture = apertureDefault;
+ m_blurSamples = blurSamplesDefault;
+ m_focalPoint = focalPointDefault;
+ m_confidence = confidenceDefault;
+ m_variance = varianceDefault;
+ m_export = c_defaultExport;
+}
+
+PMCamera::PMCamera( const PMCamera& c )
+ : Base( c )
+{
+ m_location = c.m_location;
+ m_lookAt = c.m_lookAt;
+ m_direction = c.m_direction;
+
+ m_up = c.m_up;
+ m_right = c.m_right;
+
+ m_sky = c.m_sky;
+ m_angle = c.m_angle;
+ m_angleEnabled = c.m_angleEnabled;
+
+ m_cameraType = c.m_cameraType;
+ m_cylinderType = c.m_cylinderType;
+
+ m_focalBlurEnabled = c.m_focalBlurEnabled;
+ m_aperture = c.m_aperture;
+ m_blurSamples = c.m_blurSamples;
+ m_focalPoint = c.m_focalPoint;
+ m_confidence = c.m_confidence;
+ m_variance = c.m_variance;
+ m_export = c.m_export;
+}
+
+PMCamera::~PMCamera( )
+{
+}
+
+QString PMCamera::description( ) const
+{
+ return i18n( "camera" );
+}
+
+void PMCamera::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "camera_type", cameraTypeToString( m_cameraType ) );
+ e.setAttribute( "cylinder_type", m_cylinderType );
+ e.setAttribute( "location", m_location.serializeXML( ) );
+ e.setAttribute( "sky", m_sky.serializeXML( ) );
+ e.setAttribute( "direction", m_direction.serializeXML( ) );
+ e.setAttribute( "right", m_right.serializeXML( ) );
+ e.setAttribute( "up", m_up.serializeXML( ) );
+ e.setAttribute( "look_at", m_lookAt.serializeXML( ) );
+ e.setAttribute( "angle_enabled", m_angleEnabled );
+ e.setAttribute( "angle", m_angle );
+ e.setAttribute( "focal_blur", m_focalBlurEnabled );
+ e.setAttribute( "aperture", m_aperture );
+ e.setAttribute( "blur_samples", m_blurSamples );
+ e.setAttribute( "focal_point", m_focalPoint.serializeXML( ) );
+ e.setAttribute( "confidence", m_confidence );
+ e.setAttribute( "variance", m_variance );
+ e.setAttribute( "export", m_export );
+
+ Base::serialize( e, doc );
+}
+
+void PMCamera::readAttributes( const PMXMLHelper& h )
+{
+ m_cameraType = stringToCameraType( h.stringAttribute( "camera_type",
+ "perspective" ) );
+ m_cylinderType = h.intAttribute( "cylinder_type", cylinderTypeDefault );
+ m_location = h.vectorAttribute( "location", locationDefault );
+ m_sky = h.vectorAttribute( "sky", skyDefault );
+ m_direction = h.vectorAttribute( "direction", directionDefault );
+ m_right = h.vectorAttribute( "right", rightDefault );
+ m_up = h.vectorAttribute( "up", upDefault );
+ m_lookAt = h.vectorAttribute( "look_at", lookAtDefault );
+ m_angleEnabled = h.boolAttribute( "angle_enabled", angleEnabledDefault );
+ m_angle = h.doubleAttribute( "angle", angleDefault );
+ m_focalBlurEnabled = h.boolAttribute( "focal_blur", focalBlurDefault );
+ m_aperture = h.doubleAttribute( "aperture", apertureDefault );
+ m_blurSamples = h.intAttribute( "blur_samples", blurSamplesDefault );
+ m_focalPoint = h.vectorAttribute( "focal_point", focalPointDefault );
+ m_confidence = h.doubleAttribute( "confidence", confidenceDefault );
+ m_variance = h.doubleAttribute( "variance", varianceDefault );
+ m_export = h.boolAttribute( "export", c_defaultExport );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMCamera::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Camera", Base::metaObject( ),
+ createNewCamera );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "location", &PMCamera::setLocation,
+ &PMCamera::location ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "lookAt", &PMCamera::setLookAt,
+ &PMCamera::lookAt ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "up", &PMCamera::setUp,
+ &PMCamera::up ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "right", &PMCamera::setRight,
+ &PMCamera::right ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "direction", &PMCamera::setDirection,
+ &PMCamera::direction ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "sky", &PMCamera::setSky,
+ &PMCamera::sky ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "aspect", 0, &PMCamera::aspect ) );
+
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "angleEnabled", &PMCamera::enableAngle,
+ &PMCamera::isAngleEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "angle", &PMCamera::setAngle,
+ &PMCamera::angle ) );
+
+ PMCameraTypeProperty* p = new PMCameraTypeProperty(
+ "cameraType", &PMCamera::setCameraType,
+ &PMCamera::cameraType );
+ p->addEnumValue( "Perspective", Perspective );
+ p->addEnumValue( "Orthographic", Orthographic );
+ p->addEnumValue( "FishEye", FishEye );
+ p->addEnumValue( "UltraWideAngle", UltraWideAngle );
+ p->addEnumValue( "Omnimax", Omnimax );
+ p->addEnumValue( "Panoramic", Panoramic );
+ p->addEnumValue( "Cylinder", Cylinder );
+ s_pMetaObject->addProperty( p );
+
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "cylinderType", &PMCamera::setCylinderType,
+ &PMCamera::cylinderType ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "focalBlurEnabled", &PMCamera::enableFocalBlur,
+ &PMCamera::isFocalBlurEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "aperture", &PMCamera::setAperture,
+ &PMCamera::aperture ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "blurSamples", &PMCamera::setBlurSamples,
+ &PMCamera::blurSamples ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "focalPoint", &PMCamera::setFocalPoint,
+ &PMCamera::focalPoint ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "confidence", &PMCamera::setConfidence,
+ &PMCamera::confidence ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "variance", &PMCamera::setVariance,
+ &PMCamera::variance ) );
+ s_pMetaObject->addProperty(
+ new PMCameraProperty( "export", &PMCamera::setExportPovray,
+ &PMCamera::exportPovray ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMCamera::setLocation( const PMVector& p )
+{
+ if( p != m_location )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLocationID, m_location );
+ m_location = p;
+ m_location.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::setLookAt( const PMVector& p )
+{
+ if( p != m_lookAt )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLookAtID, m_lookAt );
+ m_lookAt = p;
+ m_lookAt.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::setUp( const PMVector& v )
+{
+ if( v != m_up )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUpID, m_up );
+ m_up = v;
+ m_up.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::setRight( const PMVector& v )
+{
+ if( v != m_right )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRightID, m_right );
+ m_right = v;
+ m_right.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::setDirection( const PMVector& v )
+{
+ if( v != m_direction )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDirectionID, m_direction );
+ m_direction = v;
+ m_direction.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::setSky( const PMVector& v )
+{
+ if( v != m_sky )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSkyID, m_sky );
+ m_sky = v;
+ m_sky.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+double PMCamera::aspect( ) const
+{
+ double d = m_up.abs( );
+ if( approxZero( d ) )
+ return 1.0;
+ return m_right.abs( ) / d;
+}
+
+void PMCamera::enableAngle( bool yes )
+{
+ if( yes != m_angleEnabled )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAngleEnabledID, m_angleEnabled );
+ m_angleEnabled = yes;
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::setAngle( double a )
+{
+ if( a != m_angle )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAngleID, m_angle );
+ m_angle = a;
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::setCameraType( PMCamera::CameraType t )
+{
+ if( t != m_cameraType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCameraTypeID, m_cameraType );
+ m_cameraType = t;
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::setCylinderType( int t )
+{
+ if( ( t < 1 ) || ( t > 4 ) )
+ kdError( PMArea ) << "Invalid type in PMCylinder::setCylinderType\n";
+ else if( t != m_cylinderType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCylinderTypeID, m_cylinderType );
+ m_cylinderType = t;
+ setViewStructureChanged( );
+ }
+}
+
+void PMCamera::enableFocalBlur( bool yes )
+{
+ if( yes != m_focalBlurEnabled )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFocalBlurID, m_focalBlurEnabled );
+ m_focalBlurEnabled = yes;
+ }
+}
+
+void PMCamera::setAperture( double a )
+{
+ if( a < 0 )
+ kdError( PMArea ) << "Aperture < 0 in PMCylinder::setAperture\n";
+ else if( a != m_aperture )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMApertureID, m_aperture );
+ m_aperture = a;
+ }
+}
+
+void PMCamera::setBlurSamples( int s )
+{
+ if( s < 0 )
+ kdError( PMArea ) << "Samples < 0 in PMCylinder::setBlutSamples\n";
+ else if( s != m_blurSamples )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBlurSamplesID, m_blurSamples );
+ m_blurSamples = s;
+ }
+}
+
+void PMCamera::setFocalPoint( const PMVector& v )
+{
+ if( v != m_focalPoint )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFocalPointID, m_focalPoint );
+ m_focalPoint = v;
+ }
+}
+
+void PMCamera::setConfidence( double c )
+{
+ if( ( c < 0.0 ) || ( c > 1.0 ) )
+ kdError( PMArea ) << "Confidence not in [0.0 1.0] in PMCylinder::setConfidence\n";
+ else if( c != m_confidence )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMConfidenceID, m_confidence );
+ m_confidence = c;
+ }
+}
+
+void PMCamera::setVariance( double v )
+{
+ if( v < 0 )
+ kdError( PMArea ) << "Variance < 0 in PMCylinder::setVariance\n";
+ else if( v != m_variance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMVarianceID, m_variance );
+ m_variance = v;
+ }
+}
+
+void PMCamera::setExportPovray( bool ex )
+{
+ if( m_export != ex )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMExportID, m_export );
+ m_export = ex;
+ }
+}
+
+PMDialogEditBase* PMCamera::editWidget( QWidget* parent ) const
+{
+ return new PMCameraEdit( parent );
+}
+
+void PMCamera::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMLocationID:
+ setLocation( data->vectorData( ) );
+ break;
+ case PMLookAtID:
+ setLookAt( data->vectorData( ) );
+ break;
+ case PMUpID:
+ setUp( data->vectorData( ) );
+ break;
+ case PMRightID:
+ setRight( data->vectorData( ) );
+ break;
+ case PMDirectionID:
+ setDirection( data->vectorData( ) );
+ break;
+ case PMSkyID:
+ setSky( data->vectorData( ) );
+ break;
+ case PMAngleEnabledID:
+ enableAngle( data->boolData( ) );
+ break;
+ case PMAngleID:
+ setAngle( data->doubleData( ) );
+ break;
+ case PMCameraTypeID:
+ setCameraType( ( CameraType ) data->intData( ) );
+ break;
+ case PMCylinderTypeID:
+ setCylinderType( data->intData( ) );
+ break;
+ case PMFocalBlurID:
+ enableFocalBlur( data->boolData( ) );
+ break;
+ case PMBlurSamplesID:
+ setBlurSamples( data->intData( ) );
+ break;
+ case PMFocalPointID:
+ setFocalPoint( data->vectorData( ) );
+ break;
+ case PMConfidenceID:
+ setConfidence( data->doubleData( ) );
+ break;
+ case PMVarianceID:
+ setVariance( data->doubleData( ) );
+ break;
+ case PMApertureID:
+ setAperture( data->doubleData( ) );
+ break;
+ case PMExportID:
+ setExportPovray( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMCamera::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+void PMCamera::createViewStructure( )
+{
+ PMVector newUp, newRight, newDirection, tmp;
+ double upLen, rightLen;
+
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+ calculateLookAtAngle( newRight, newUp, newDirection );
+
+ points[0] = m_lookAt;
+ points[1] = m_location;
+
+ upLen = newUp.abs( );
+ rightLen = newRight.abs( );
+ if( rightLen > upLen )
+ {
+ newUp /= rightLen;
+ newRight /= rightLen;
+ newDirection /= rightLen;
+ }
+ else
+ {
+ newUp /= upLen;
+ newRight /= upLen;
+ newDirection /= upLen;
+ }
+
+ newRight /= 2.0;
+ newUp /= 2.0;
+ tmp = m_location + newDirection;
+ points[2] = tmp - newRight + newUp;
+ points[3] = tmp - newRight - newUp;
+ points[4] = tmp + newRight - newUp;
+ points[5] = tmp + newRight + newUp;
+// points[6] = m_location + m_sky;
+}
+
+PMViewStructure* PMCamera::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure )
+ {
+ s_pDefaultViewStructure = new PMViewStructure( 6, 9 );
+ PMLineArray& lines = s_pDefaultViewStructure->lines( );
+
+ lines[0] = PMLine( 0, 1 );
+ lines[1] = PMLine( 1, 2 );
+ lines[2] = PMLine( 1, 3 );
+ lines[3] = PMLine( 1, 4 );
+ lines[4] = PMLine( 1, 5 );
+ lines[5] = PMLine( 2, 3 );
+ lines[6] = PMLine( 2, 5 );
+ lines[7] = PMLine( 3, 4 );
+ lines[8] = PMLine( 4, 5 );
+// lines[9] = PMLine( 1, 6 );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMCamera::controlPoints( PMControlPointList& list )
+{
+ PMControlPoint* p;
+ p = new PM3DControlPoint( m_location, PMLocationID, i18n( "Location" ) );
+ list.append( p );
+ list.append( new PM3DControlPoint( m_lookAt, PMLookAtID, i18n( "Look at" ) ) );
+}
+
+void PMCamera::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMLocationID:
+ setLocation( ( ( PM3DControlPoint* ) p )->point( ) );
+ break;
+ case PMLookAtID:
+ setLookAt( ( ( PM3DControlPoint* ) p )->point( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMCamera::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+}
+
+void PMCamera::calculateLookAtAngle( PMVector& right, PMVector& up, PMVector& direction )
+{
+ PMVector tmpVector;
+ double directionLen, upLen, rightLen, handedness, angle;
+
+ angle = m_angle;
+ if( m_cameraType == Perspective )
+ {
+ if( angle < 0.0 )
+ angle = angleDefault;
+ if( angle >= 180.0 )
+ angle = angleDefault;
+ }
+ else
+ angle = 90.0;
+
+ directionLen = m_direction.abs( );
+ upLen = m_up.abs( );
+ rightLen = m_right.abs( );
+
+ // for safety: if vector is null vector, use the default one
+ if( approxZero( directionLen ) )
+ {
+ direction = directionDefault;
+ directionLen = direction.abs( );
+ }
+ else
+ direction = m_direction;
+
+ if( approxZero( upLen ) )
+ {
+ up = upDefault;
+ upLen = up.abs( );
+ }
+ else
+ up = m_up;
+
+ if( approxZero( rightLen ) )
+ {
+ right = rightDefault;
+ rightLen = right.abs( );
+ }
+ else
+ right = m_right;
+
+ if( m_angleEnabled )
+ {
+ // calculate angle
+ direction /= directionLen;
+ directionLen = 0.5 * rightLen / tan( angle * M_PI / 360.0 );
+ direction *= directionLen;
+ }
+
+ // calculate handedness
+ tmpVector = PMVector::cross( up, direction );
+ handedness = PMVector::dot( tmpVector, right );
+
+ direction = m_lookAt - m_location;
+ if( approxZero( direction.abs( ) ) )
+ {
+ // Camera location and look_at point are the same
+ direction = directionDefault;
+ }
+
+ // normalize new direction
+ direction /= direction.abs( );
+
+ tmpVector = right;
+ right = PMVector::cross( m_sky, direction );
+
+ if( approxZero( right.abs( ) ) )
+ right = tmpVector;
+
+ right /= right.abs( );
+ up = PMVector::cross( direction, right );
+ direction *= directionLen;
+
+ if( handedness > 0.0 )
+ right *= rightLen;
+ else
+ right *= -rightLen;
+ up *= upLen;
+}
+
+QString PMCamera::cameraTypeToString( PMCamera::CameraType t )
+{
+ QString str( "perspective" );
+ switch( t )
+ {
+ case Perspective:
+ break;
+ case Orthographic:
+ str = "orthographic";
+ break;
+ case FishEye:
+ str = "fisheye";
+ break;
+ case UltraWideAngle:
+ str = "ultra_wide_angle";
+ break;
+ case Omnimax:
+ str = "omnimax";
+ break;
+ case Panoramic:
+ str = "panoramic";
+ break;
+ case Cylinder:
+ str = "cylinder";
+ break;
+ }
+ return str;
+}
+
+PMCamera::CameraType PMCamera::stringToCameraType( const QString& str )
+{
+ CameraType t = Perspective;
+
+ if( str == "perspective" )
+ t = Perspective;
+ else if( str == "orthographic" )
+ t = Orthographic;
+ else if( str == "fisheye" )
+ t = FishEye;
+ else if( str == "ultra_wide_angle" )
+ t = UltraWideAngle;
+ else if( str == "omnimax" )
+ t = Omnimax;
+ else if( str == "panoramic" )
+ t = Panoramic;
+ else if( str == "cylinder" )
+ t = Cylinder;
+ else
+ kdDebug( PMArea ) << "Unknown camera type\n";
+
+ return t;
+}
+
+void PMCamera::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmcamera.h b/kpovmodeler/pmcamera.h
new file mode 100644
index 00000000..9f09ee58
--- /dev/null
+++ b/kpovmodeler/pmcamera.h
@@ -0,0 +1,292 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMCAMERA_H
+#define PMCAMERA_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+#include "pmvector.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray cameras
+ */
+
+class PMCamera : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+public:
+ /**
+ * Type of the camera
+ */
+ enum CameraType { Perspective, Orthographic, FishEye, UltraWideAngle,
+ Omnimax, Panoramic, Cylinder };
+ /**
+ * Creates a default povray camera
+ */
+ PMCamera( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMCamera( const PMCamera& c );
+ /**
+ * deletes the camera
+ */
+ virtual ~PMCamera( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMCamera( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMCameraEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmcamera" ); }
+
+ /**
+ * Returns the location
+ */
+ PMVector location( ) const { return m_location; }
+ /**
+ * Sets the location
+ */
+ void setLocation( const PMVector& p );
+
+ /**
+ * Returns the look_at point
+ */
+ PMVector lookAt( ) const { return m_lookAt; }
+ /**
+ * Sets the look_at point
+ */
+ void setLookAt( const PMVector& p );
+
+ /**
+ * Returns the up vector
+ */
+ PMVector up( ) const { return m_up; }
+ /**
+ * Sets the up vector
+ */
+ void setUp( const PMVector& v );
+
+ /**
+ * Returns the right vector
+ */
+ PMVector right( ) const { return m_right; }
+ /**
+ * Sets the right vector
+ */
+ void setRight( const PMVector& v );
+
+ /**
+ * Returns the direction vector
+ */
+ PMVector direction( ) const { return m_direction; }
+ /**
+ * Sets the direction vector
+ */
+ void setDirection( const PMVector& v );
+
+ /**
+ * Returns the sky vector
+ */
+ PMVector sky( ) const { return m_sky; }
+ /**
+ * Sets the sky vector
+ */
+ void setSky( const PMVector& v );
+
+ /**
+ * Returns the aspect ratio
+ */
+ double aspect( ) const;
+
+ /**
+ * Returns true if angle is enabled
+ */
+ bool isAngleEnabled( ) const { return m_angleEnabled; }
+ /**
+ * Enables/Disables the use of angle
+ */
+ void enableAngle( bool yes );
+
+ /**
+ * Returns the angle
+ */
+ double angle( ) const { return m_angle; }
+ /**
+ * Sets the angle
+ */
+ void setAngle( double a );
+
+ /**
+ * Returns the camera type
+ */
+ CameraType cameraType( ) const { return m_cameraType; }
+ /**
+ * Sets the camera type
+ */
+ void setCameraType( CameraType t );
+
+ /**
+ * Returns the cylinder type
+ */
+ int cylinderType( ) const { return m_cylinderType; }
+ /**
+ * Sets the cylinder type. Valid values are 1-4
+ */
+ void setCylinderType( int t );
+
+ /**
+ * Returns true if focal blur is enabled
+ */
+ bool isFocalBlurEnabled( ) const { return m_focalBlurEnabled; }
+ /**
+ * Enables/Disables the focal blur
+ */
+ void enableFocalBlur( bool yes );
+ /**
+ * Returns the aperture
+ */
+ double aperture( ) const { return m_aperture; }
+ /**
+ * Sets the aperture. Has to be greater or equal 0
+ */
+ void setAperture( double d );
+ /**
+ * Returns the number of blur samples
+ */
+ int blurSamples( ) const { return m_blurSamples; }
+ /**
+ * Sets the number of blur samples
+ */
+ void setBlurSamples( int s );
+ /**
+ * Returns the focal point
+ */
+ PMVector focalPoint( ) const { return m_focalPoint; }
+ /**
+ * Sets the focal point
+ */
+ void setFocalPoint( const PMVector& v );
+ /**
+ * Returns the confidence
+ */
+ double confidence( ) const { return m_confidence;}
+ /**
+ * Sets the confidence
+ */
+ void setConfidence( double c );
+ /**
+ * Returns the variance
+ */
+ double variance( ) const { return m_variance; }
+ /**
+ * Sets the variance
+ */
+ void setVariance( double v );
+
+ /**
+ * Returns the export flag
+ */
+ virtual bool exportPovray( ) const { return m_export; }
+ /**
+ * Sets the export flag
+ */
+ void setExportPovray( bool ex );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+
+ /**
+ * Calculates the new right, up and direction vector with the
+ * look_at vector.
+ */
+ void calculateLookAtAngle( PMVector& right, PMVector& up, PMVector& direction );
+
+ /**
+ * Converts the camera type to a string
+ */
+ static QString cameraTypeToString( CameraType t );
+ /**
+ * Converts a string to the camera type
+ */
+ static CameraType stringToCameraType( const QString& s );
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( ) { return false; }
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMCameraMementoID { PMLocationID, PMLookAtID, PMDirectionID,
+ PMUpID, PMRightID, PMAngleID, PMSkyID,
+ PMCameraTypeID, PMCylinderTypeID,
+ PMFocalBlurID, PMBlurSamplesID, PMFocalPointID,
+ PMConfidenceID, PMVarianceID, PMApertureID,
+ PMAngleEnabledID, PMExportID };
+ PMVector m_location, m_lookAt, m_up, m_right, m_direction, m_sky;
+ bool m_angleEnabled;
+ double m_angle;
+ CameraType m_cameraType;
+ int m_cylinderType;
+ bool m_focalBlurEnabled;
+ double m_aperture;
+ int m_blurSamples;
+ PMVector m_focalPoint;
+ double m_confidence, m_variance;
+ bool m_export;
+
+ /**
+ * The default view structure. It can be shared between cameras
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmcameraedit.cpp b/kpovmodeler/pmcameraedit.cpp
new file mode 100644
index 00000000..676c9f8b
--- /dev/null
+++ b/kpovmodeler/pmcameraedit.cpp
@@ -0,0 +1,439 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcameraedit.h"
+#include "pmcamera.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+
+
+PMCameraEdit::PMCameraEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMCameraEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QGridLayout* layout;
+ QLabel* label;
+
+ m_pCameraType = new QComboBox( false, this );
+ m_pCameraType->insertItem( i18n( "Perspective" ) );
+ m_pCameraType->insertItem( i18n( "Orthographic" ) );
+ m_pCameraType->insertItem( i18n( "Fish Eye" ) );
+ m_pCameraType->insertItem( i18n( "Ultra Wide Angle" ) );
+ m_pCameraType->insertItem( i18n( "Omnimax" ) );
+ m_pCameraType->insertItem( i18n( "Panoramic" ) );
+ m_pCameraType->insertItem( i18n( "Cylinder" ) );
+
+ m_pCylinderType = new QComboBox( false, this );
+ m_pCylinderType->insertItem( i18n( "1: Vertical, Fixed Viewpoint" ) );
+ m_pCylinderType->insertItem( i18n( "2: Horizontal, Fixed Viewpoint" ) );
+ m_pCylinderType->insertItem( i18n( "3: Vertical, Variable Viewpoint" ) );
+ m_pCylinderType->insertItem( i18n( "4: Horizontal, Variable Viewpoint" ) );
+
+ m_pLocation = new PMVectorEdit( "x", "y", "z", this );
+ m_pSky = new PMVectorEdit( "x", "y", "z", this );
+ m_pDirection = new PMVectorEdit( "x", "y", "z", this );
+ m_pRight = new PMVectorEdit( "x", "y", "z", this );
+ m_pUp = new PMVectorEdit( "x", "y", "z", this );
+ m_pLookAt = new PMVectorEdit( "x", "y", "z", this );
+ m_pAngle = new PMFloatEdit( this );
+ m_pAngle->setValidation( true, 0.0, true, 360.0 );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Camera type:" ), this ) );
+ hl->addWidget( m_pCameraType );
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pCylinderTypeLabel = new QLabel( i18n( "Cylinder type:" ), this );
+ hl->addWidget( m_pCylinderTypeLabel );
+ hl->addWidget( m_pCylinderType );
+
+ layout = new QGridLayout( topLayout( ), 7, 2 );
+ layout->addWidget( new QLabel( i18n( "Location:" ), this ), 0, 0 );
+ layout->addWidget( m_pLocation, 0, 1 );
+
+ layout->addWidget( new QLabel( i18n( "Sky:" ), this ), 1, 0 );
+ layout->addWidget( m_pSky, 1, 1 );
+
+ layout->addWidget( new QLabel( i18n( "Direction:" ), this ), 2, 0 );
+ layout->addWidget( m_pDirection, 2, 1 );
+
+ layout->addWidget( new QLabel( i18n( "Right:" ), this ), 3, 0 );
+ layout->addWidget( m_pRight, 3, 1 );
+
+ layout->addWidget( new QLabel( i18n( "Up:" ), this ), 4, 0 );
+ layout->addWidget( m_pUp, 4, 1 );
+
+ layout->addWidget( new QLabel( i18n( "Look at:" ), this ), 5, 0 );
+ layout->addWidget( m_pLookAt, 5, 1 );
+
+ m_pEnableAngle = new QCheckBox( i18n( "Angle:" ), this );
+ layout->addWidget( m_pEnableAngle, 6, 0 );
+ layout->addWidget( m_pAngle, 6, 1, AlignLeft );
+
+ m_pFocalBlur = new QCheckBox( i18n( "Focal blur" ), this );
+ topLayout( )->addWidget( m_pFocalBlur );
+
+ m_pAperture = new PMFloatEdit( this );
+ m_pAperture->setValidation( true, 0, false, 0 );
+ m_focalWidgets.append( m_pAperture );
+ m_pBlurSamples = new PMIntEdit( this );
+ m_pBlurSamples->setValidation( true, 0, false, 0 );
+ m_focalWidgets.append( m_pBlurSamples );
+ m_pFocalPoint = new PMVectorEdit( "x", "y", "z", this );
+ m_focalWidgets.append( m_pFocalPoint );
+ m_pConfidence = new PMFloatEdit( this );
+ m_pConfidence->setValidation( true, 0, true, 1 );
+ m_focalWidgets.append( m_pConfidence );
+ m_pVariance = new PMFloatEdit( this );
+ m_pVariance->setValidation( true, 0, false, 0 );
+ m_focalWidgets.append( m_pVariance );
+
+ layout = new QGridLayout( topLayout( ), 5, 2 );
+ label = new QLabel( i18n( "Aperture:" ), this );
+ m_focalWidgets.append( label );
+ layout->addWidget( label, 0, 0 );
+ layout->addWidget( m_pAperture, 0, 1 );
+ label = new QLabel( i18n( "Blur samples:" ), this );
+ m_focalWidgets.append( label );
+ layout->addWidget( label, 1, 0 );
+ layout->addWidget( m_pBlurSamples, 1, 1 );
+ label = new QLabel( i18n( "Focal point:" ), this );
+ m_focalWidgets.append( label );
+ layout->addWidget( label, 2, 0 );
+ layout->addWidget( m_pFocalPoint, 2, 1 );
+ label = new QLabel( i18n( "Confidence:" ), this );
+ m_focalWidgets.append( label );
+ layout->addWidget( label, 3, 0 );
+ layout->addWidget( m_pConfidence, 3, 1 );
+ label = new QLabel( i18n( "Variance:" ), this );
+ m_focalWidgets.append( label );
+ layout->addWidget( label, 4, 0 );
+ layout->addWidget( m_pVariance, 4, 1 );
+
+ m_pExport = new QCheckBox( i18n( "Export to renderer" ), this );
+ topLayout( )->addWidget( m_pExport );
+
+ connect( m_pLocation, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDirection, SIGNAL( dataChanged( ) ), SLOT( slotDirectionChanged( ) ) );
+ connect( m_pRight, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRight, SIGNAL( dataChanged( ) ), SLOT( slotRightChanged( ) ) );
+ connect( m_pUp, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSky, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pLookAt, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnableAngle, SIGNAL( toggled( bool ) ),
+ SLOT( slotAngleToggled( bool ) ) );
+ connect( m_pAngle, SIGNAL( dataChanged( ) ), SLOT( slotAngleChanged( ) ) );
+ connect( m_pCameraType, SIGNAL( activated( int ) ),
+ SLOT( slotCameraTypeActivated( int ) ) );
+ connect( m_pCylinderType, SIGNAL( activated( int ) ),
+ SLOT( slotCylinderTypeActivated( int ) ) );
+
+ connect( m_pFocalBlur, SIGNAL( toggled( bool ) ),
+ SLOT( slotFocalBlurToggled( bool ) ) );
+ connect( m_pAperture, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pBlurSamples, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFocalPoint, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pVariance, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pConfidence, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pExport, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMCameraEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Camera" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMCamera* ) o;
+
+ m_pCameraType->setCurrentItem( m_pDisplayedObject->cameraType( ) );
+ m_pCameraType->setEnabled( !readOnly );
+ slotCameraTypeActivated( m_pDisplayedObject->cameraType( ) );
+ m_pCylinderType->setCurrentItem( m_pDisplayedObject->cylinderType( ) - 1 );
+ m_pCylinderType->setEnabled( !readOnly );
+ m_pLocation->setVector( m_pDisplayedObject->location( ) );
+ m_pLocation->setReadOnly( readOnly );
+ m_pSky->setVector( m_pDisplayedObject->sky( ) );
+ m_pSky->setReadOnly( readOnly );
+ m_pDirection->setVector( m_pDisplayedObject->direction( ) );
+ m_pDirection->setReadOnly( readOnly );
+ m_pRight->setVector( m_pDisplayedObject->right( ) );
+ m_pRight->setReadOnly( readOnly );
+ m_pUp->setVector( m_pDisplayedObject->up( ) );
+ m_pUp->setReadOnly( readOnly );
+ m_pLookAt->setVector( m_pDisplayedObject->lookAt( ) );
+ m_pLookAt->setReadOnly( readOnly );
+
+ m_pEnableAngle->setChecked( m_pDisplayedObject->isAngleEnabled( ) );
+ m_pEnableAngle->setEnabled( !readOnly );
+ m_pAngle->setValue( m_pDisplayedObject->angle( ) );
+ m_pAngle->setReadOnly( readOnly );
+ slotAngleToggled( m_pDisplayedObject->isAngleEnabled( ) );
+ slotRightChanged( );
+ m_pFocalBlur->setChecked( m_pDisplayedObject->isFocalBlurEnabled( ) );
+ slotFocalBlurToggled( m_pDisplayedObject->isFocalBlurEnabled( ) );
+ m_pFocalBlur->setEnabled( !readOnly );
+
+ m_pAperture->setValue( m_pDisplayedObject->aperture( ) );
+ m_pAperture->setReadOnly( readOnly );
+ m_pBlurSamples->setValue( m_pDisplayedObject->blurSamples( ) );
+ m_pBlurSamples->setReadOnly( readOnly );
+ m_pFocalPoint->setVector( m_pDisplayedObject->focalPoint( ) );
+ m_pFocalPoint->setReadOnly( readOnly );
+ m_pConfidence->setValue( m_pDisplayedObject->confidence( ) );
+ m_pConfidence->setReadOnly( readOnly );
+ m_pVariance->setValue( m_pDisplayedObject->variance( ) );
+ m_pVariance->setReadOnly( readOnly );
+
+ m_pExport->setChecked( m_pDisplayedObject->exportPovray( ) );
+ m_pExport->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMCameraEdit: Can't display object\n";
+}
+
+void PMCameraEdit::saveContents( )
+{
+ int index;
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ index = m_pCameraType->currentItem( );
+ m_pDisplayedObject->setCameraType( ( PMCamera::CameraType ) index );
+ if( index == 6 )
+ m_pDisplayedObject->setCylinderType( m_pCylinderType->currentItem( ) + 1 );
+ m_pDisplayedObject->setLocation( m_pLocation->vector( ) );
+ m_pDisplayedObject->setDirection( m_pDirection->vector( ) );
+ m_pDisplayedObject->setRight( m_pRight->vector( ) );
+ m_pDisplayedObject->setUp( m_pUp->vector( ) );
+ m_pDisplayedObject->setSky( m_pSky->vector( ) );
+ m_pDisplayedObject->setLookAt( m_pLookAt->vector( ) );
+ m_pDisplayedObject->enableAngle( m_pEnableAngle->isChecked( ) );
+ if( m_pEnableAngle->isChecked( ) )
+ m_pDisplayedObject->setAngle( m_pAngle->value( ) );
+
+ m_pDisplayedObject->enableFocalBlur( m_pFocalBlur->isChecked( ) );
+ if( m_pFocalBlur->isChecked( ) )
+ {
+ m_pDisplayedObject->setAperture( m_pAperture->value( ) );
+ m_pDisplayedObject->setBlurSamples( m_pBlurSamples->value( ) );
+ m_pDisplayedObject->setFocalPoint( m_pFocalPoint->vector( ) );
+ m_pDisplayedObject->setConfidence( m_pConfidence->value( ) );
+ m_pDisplayedObject->setVariance( m_pVariance->value( ) );
+ }
+ m_pDisplayedObject->setExportPovray( m_pExport->isChecked( ) );
+ }
+}
+
+bool PMCameraEdit::isDataValid( )
+{
+ if( !m_pLocation->isDataValid( ) )
+ return false;
+ if( !m_pSky->isDataValid( ) )
+ return false;
+ if( approxZero( m_pSky->vector( ).abs( ) ) )
+ {
+ KMessageBox::error( this, i18n( "The sky vector may not be a null vector." ),
+ i18n( "Error" ) );
+ m_pSky->setFocus( );
+ return false;
+ }
+ if( !m_pDirection->isDataValid( ) )
+ return false;
+ if( approxZero( m_pDirection->vector( ).abs( ) ) )
+ {
+ KMessageBox::error( this, i18n( "The direction vector may not be a null vector." ),
+ i18n( "Error" ) );
+ m_pDirection->setFocus( );
+ return false;
+ }
+ if( !m_pRight->isDataValid( ) )
+ return false;
+ if( approxZero( m_pRight->vector( ).abs( ) ) )
+ {
+ KMessageBox::error( this, i18n( "The right vector may not be a null vector." ),
+ i18n( "Error" ) );
+ m_pRight->setFocus( );
+ return false;
+ }
+ if( !m_pUp->isDataValid( ) )
+ return false;
+ if( approxZero( m_pUp->vector( ).abs( ) ) )
+ {
+ KMessageBox::error( this, i18n( "The up vector may not be a null vector." ),
+ i18n( "Error" ) );
+ m_pDirection->setFocus( );
+ return false;
+ }
+ if( !m_pLookAt->isDataValid( ) )
+ return false;
+ if( m_pEnableAngle->isChecked( ) && !m_pAngle->isDataValid( ) )
+ return false;
+
+ if( ( m_pCameraType->currentItem( ) == 0 ) && m_pEnableAngle->isChecked( ) )
+ {
+ double angle = m_pAngle->value( );
+ if( angle >= 180.0 )
+ {
+ KMessageBox::error( this, i18n( "Angle has to be smaller than 180"
+ " degrees for that camera type." ),
+ i18n( "Error" ) );
+ m_pAngle->setFocus( );
+ return false;
+ }
+ }
+
+ if( m_pFocalBlur->isChecked( ) )
+ {
+ if( !m_pAperture->isDataValid( ) )
+ return false;
+ if( !m_pBlurSamples->isDataValid( ) )
+ return false;
+ if( !m_pFocalPoint->isDataValid( ) )
+ return false;
+ if( !m_pConfidence->isDataValid( ) )
+ return false;
+ if( !m_pVariance->isDataValid( ) )
+ return false;
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMCameraEdit::slotCameraTypeActivated( int index )
+{
+ if( index == 6 )
+ {
+ m_pCylinderType->show( );
+ m_pCylinderTypeLabel->show( );
+ }
+ else
+ {
+ m_pCylinderType->hide( );
+ m_pCylinderTypeLabel->hide( );
+ }
+
+ if( ( index == 1 ) || ( index == 4 ) || ( index == 5 ) )
+ {
+ m_pAngle->hide( );
+ m_pEnableAngle->hide( );
+ }
+ else
+ {
+ m_pAngle->show( );
+ m_pEnableAngle->show( );
+ }
+
+ if( index == 0 )
+ m_pFocalBlur->show( );
+ else
+ m_pFocalBlur->hide( );
+ enableFocalWidgets( m_pFocalBlur->isChecked( ) && ( index == 0 ) );
+ emit sizeChanged( );
+ emit dataChanged( );
+}
+
+void PMCameraEdit::slotCylinderTypeActivated( int )
+{
+ emit dataChanged( );
+}
+
+void PMCameraEdit::slotFocalBlurToggled( bool on )
+{
+ enableFocalWidgets( on && ( m_pCameraType->currentItem( ) == 0 ) );
+ emit dataChanged( );
+}
+
+void PMCameraEdit::slotAngleToggled( bool on )
+{
+ m_pAngle->setEnabled( on );
+ emit dataChanged( );
+}
+
+void PMCameraEdit::slotAngleChanged( )
+{
+ /*
+ if( ( m_pCameraType->currentItem( ) == 0 ) && m_pEnableAngle->isChecked( ) )
+ {
+ // Only change direction's value in perspective and with an enabled angle
+ disconnect( m_pDirection, SIGNAL( dataChanged( ) ), 0, 0 );
+ m_pDirection->setVector( 0.5 * m_pRight->vector( ) / tan( 2 * deg2Rad( m_pAngle->value( ) ) ) );
+ connect( m_pDirection, SIGNAL( dataChanged( ) ), SLOT( slotDirectionChanged( ) ) );
+ }
+ */
+ emit dataChanged( );
+}
+
+void PMCameraEdit::slotDirectionChanged( )
+{
+ calculateCameraAngle( );
+ emit dataChanged( );
+}
+
+void PMCameraEdit::slotRightChanged( )
+{
+ calculateCameraAngle( );
+ emit dataChanged( );
+}
+
+void PMCameraEdit::calculateCameraAngle( )
+{
+ if( ( m_pCameraType->currentItem( ) == 0 ) && !m_pEnableAngle->isChecked( ) )
+ {
+ // Only change angle's value in perspective and with a disabled angle
+ double rl = m_pRight->vector( ).abs( );
+ double dl = m_pDirection->vector( ).abs( );
+ if( ( rl > 0 ) && ( dl > 0 ) )
+ {
+ bool sb = m_pAngle->signalsBlocked( );
+ m_pAngle->blockSignals( true );
+ m_pAngle->setValue( rad2Deg( 2 * atan2( 0.5 * rl, dl ) ) );
+ m_pAngle->blockSignals( sb );
+ }
+ }
+}
+
+void PMCameraEdit::enableFocalWidgets( bool on )
+{
+ QPtrListIterator<QWidget> it( m_focalWidgets );
+
+ for( ; it.current( ); ++it )
+ {
+ if( on )
+ it.current( )->show( );
+ else
+ it.current( )->hide( );
+ }
+ emit sizeChanged( );
+}
+
+#include "pmcameraedit.moc"
diff --git a/kpovmodeler/pmcameraedit.h b/kpovmodeler/pmcameraedit.h
new file mode 100644
index 00000000..7b787683
--- /dev/null
+++ b/kpovmodeler/pmcameraedit.h
@@ -0,0 +1,99 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCAMERAEDIT_H
+#define PMCAMERAEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobjectedit.h"
+#include <qptrlist.h>
+
+class PMCamera;
+class PMVectorEdit;
+class PMFloatEdit;
+class PMIntEdit;
+class QComboBox;
+class QLabel;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMCamera
+ */
+class PMCameraEdit : public PMNamedObjectEdit
+{
+ Q_OBJECT
+ typedef PMNamedObjectEdit Base;
+public:
+ /**
+ * Creates a PMCameraEdit with parent and name
+ */
+ PMCameraEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotCameraTypeActivated( int index );
+ void slotCylinderTypeActivated( int index );
+ void slotFocalBlurToggled( bool on );
+ void slotAngleToggled( bool on );
+ void slotAngleChanged( );
+ void slotDirectionChanged( );
+ void slotRightChanged( );
+
+private:
+ void enableFocalWidgets( bool yes );
+ void calculateCameraAngle( );
+
+ PMCamera* m_pDisplayedObject;
+ PMVectorEdit* m_pLocation;
+ PMVectorEdit* m_pDirection;
+ PMVectorEdit* m_pRight;
+ PMVectorEdit* m_pUp;
+ PMVectorEdit* m_pSky;
+ PMVectorEdit* m_pLookAt;
+ QCheckBox* m_pEnableAngle;
+ PMFloatEdit* m_pAngle;
+ QComboBox* m_pCameraType;
+ QComboBox* m_pCylinderType;
+ QLabel* m_pCylinderTypeLabel;
+ QCheckBox* m_pFocalBlur;
+ PMFloatEdit* m_pAperture;
+ PMIntEdit* m_pBlurSamples;
+ PMVectorEdit* m_pFocalPoint;
+ PMFloatEdit* m_pConfidence;
+ PMFloatEdit* m_pVariance;
+ QPtrList<QWidget> m_focalWidgets;
+ QCheckBox* m_pExport;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmclippedby.cpp b/kpovmodeler/pmclippedby.cpp
new file mode 100644
index 00000000..fc00bc51
--- /dev/null
+++ b/kpovmodeler/pmclippedby.cpp
@@ -0,0 +1,114 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmclippedby.h"
+#include "pmclippedbyedit.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMClippedBy, PMClippedByProperty );
+
+PMMetaObject* PMClippedBy::s_pMetaObject = 0;
+PMObject* createNewClippedBy( PMPart* part )
+{
+ return new PMClippedBy( part );
+}
+
+PMClippedBy::PMClippedBy( PMPart* part )
+ : Base( part )
+{
+}
+
+PMClippedBy::~PMClippedBy( )
+{
+}
+
+PMMetaObject* PMClippedBy::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "ClippedBy", Base::metaObject( ),
+ createNewClippedBy );
+ s_pMetaObject->addProperty(
+ new PMClippedByProperty( "boundedBy", 0, &PMClippedBy::boundedBy ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMClippedBy::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMClippedBy::description( ) const
+{
+ return i18n( "clipped by" );
+}
+
+bool PMClippedBy::boundedBy( ) const
+{
+ bool cb = true;
+ PMObject* o = firstChild( );
+
+ for( ; o && cb; o = o->nextSibling( ) )
+ if( o->type( ) != "Comment" )
+ cb = false;
+
+ return cb;
+}
+
+void PMClippedBy::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ // no extra data at the moment
+ Base::serialize( e, doc );
+}
+
+void PMClippedBy::readAttributes( const PMXMLHelper& h )
+{
+ // no extra data at the moment
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMClippedBy::editWidget( QWidget* parent ) const
+{
+ return new PMClippedByEdit( parent );
+}
+
+void PMClippedBy::childRemoved( PMObject* o )
+{
+ Base::childRemoved( o );
+
+ // add a dummy change
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBoundedByID, true );
+}
+
+void PMClippedBy::childAdded( PMObject* o )
+{
+ Base::childAdded( o );
+
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBoundedByID, true );
+}
diff --git a/kpovmodeler/pmclippedby.h b/kpovmodeler/pmclippedby.h
new file mode 100644
index 00000000..39c5081a
--- /dev/null
+++ b/kpovmodeler/pmclippedby.h
@@ -0,0 +1,88 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMCLIPPEDBY_H
+#define PMCLIPPEDBY_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcompositeobject.h"
+
+/**
+ * class for clipped_by povray statements
+ */
+
+class PMClippedBy : public PMCompositeObject
+{
+ typedef PMCompositeObject Base;
+public:
+ /**
+ * Creates an empty PMClippedBy
+ */
+ PMClippedBy( PMPart* part );
+ /**
+ * Deletes the object
+ */
+ ~PMClippedBy( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMClippedBy( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual bool dataChangeOnInsertRemove( ) const { return true; }
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMClippedByEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmclippedby" ); }
+
+ /** */
+ virtual void childRemoved( PMObject* );
+ /** */
+ virtual void childAdded( PMObject* );
+
+ /**
+ * Returns true if the object contains no child objects (except comments)
+ */
+ bool boundedBy( ) const;
+
+private:
+ enum PMClippedByMementoID { PMBoundedByID };
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmclippedbyedit.cpp b/kpovmodeler/pmclippedbyedit.cpp
new file mode 100644
index 00000000..18a9d4db
--- /dev/null
+++ b/kpovmodeler/pmclippedbyedit.cpp
@@ -0,0 +1,65 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmclippedbyedit.h"
+#include "pmclippedby.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+PMClippedByEdit::PMClippedByEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMClippedByEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pChildLabel = new QLabel( i18n( "No child objects" ), this );
+ topLayout( )->addWidget( m_pChildLabel );
+ m_pBoundedByLabel = new QLabel( i18n( "(= bounded by)" ), this );
+ topLayout( )->addWidget( m_pBoundedByLabel );
+}
+
+void PMClippedByEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "ClippedBy" ) )
+ {
+ m_pDisplayedObject = ( PMClippedBy* ) o;
+
+ if( m_pDisplayedObject->boundedBy( ) )
+ {
+ m_pChildLabel->show( );
+ m_pBoundedByLabel->show( );
+ }
+ else
+ {
+ m_pChildLabel->hide( );
+ m_pBoundedByLabel->hide( );
+ }
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMClippedByEdit: Can't display object\n";
+}
+
+#include "pmclippedbyedit.moc"
diff --git a/kpovmodeler/pmclippedbyedit.h b/kpovmodeler/pmclippedbyedit.h
new file mode 100644
index 00000000..3dc0c38f
--- /dev/null
+++ b/kpovmodeler/pmclippedbyedit.h
@@ -0,0 +1,59 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCLIPPEDBYEDIT_H
+#define PMCLIPPEDBYEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMClippedBy;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMClippedBy
+ */
+class PMClippedByEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMClippedByEdit with parent and name
+ */
+ PMClippedByEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+
+private:
+ PMClippedBy* m_pDisplayedObject;
+ QLabel* m_pChildLabel;
+ QLabel* m_pBoundedByLabel;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmcolor.cpp b/kpovmodeler/pmcolor.cpp
new file mode 100644
index 00000000..0eb38b79
--- /dev/null
+++ b/kpovmodeler/pmcolor.cpp
@@ -0,0 +1,196 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcolor.h"
+#include "pmvector.h"
+#include "pmmath.h"
+
+#include "pmdebug.h"
+
+#include <qtextstream.h>
+#include <qstring.h>
+
+PMColor::PMColor( )
+{
+ int i;
+ for( i = 0; i < 5; i++ )
+ m_colorValue[i] = 0;
+}
+
+PMColor::PMColor( const double red, const double green, const double blue,
+ const double filter, const double transmit )
+{
+ m_colorValue[0] = red;
+ m_colorValue[1] = green;
+ m_colorValue[2] = blue;
+ m_colorValue[3] = filter;
+ m_colorValue[4] = transmit;
+}
+
+PMColor::PMColor( const double red, const double green, const double blue )
+{
+ m_colorValue[0] = red;
+ m_colorValue[1] = green;
+ m_colorValue[2] = blue;
+ m_colorValue[3] = 0;
+ m_colorValue[4] = 0;
+}
+
+PMColor::PMColor( const PMVector& v )
+{
+ int i;
+ if( v.size( ) != 5 )
+ {
+ kdError( PMArea ) << "Vector has wrong size in PMColor::PMColor( const PMVector& v )\n";
+ for( i = 0; i < 5; i++ )
+ m_colorValue[i] = 0;
+ }
+ else
+ {
+ for( i = 0; i < 5; i++ )
+ m_colorValue[i] = v[i];
+ }
+}
+
+PMColor::PMColor( const QColor& c )
+{
+ m_colorValue[0] = c.red( ) / 255.0;
+ m_colorValue[1] = c.green( ) / 255.0;
+ m_colorValue[2] = c.blue( ) / 255.0;
+ m_colorValue[3] = 0.0;
+ m_colorValue[4] = 0.0;
+}
+
+QColor PMColor::toQColor( ) const
+{
+ double r, g, b, max = 0;
+ r = red( );
+ g = green( );
+ b = blue( );
+
+ if( r < 0 ) r = 0;
+ if( g < 0 ) g = 0;
+ if( b < 0 ) b = 0;
+
+ if( r > max )
+ max = r;
+ if( g > max )
+ max = g;
+ if( b > max )
+ max = b;
+ if( max > 1 )
+ {
+ r /= max;
+ g /= max;
+ b /= max;
+ }
+ return QColor( ( int ) ( r * 255 + 0.5 ), ( int ) ( g * 255 + 0.5 ),
+ ( int ) ( b * 255 + 0.5 ) );
+}
+
+QString PMColor::serialize( bool addColorKeyword ) const
+{
+ QString result;
+ QTextStream str( &result, IO_WriteOnly );
+
+ if( addColorKeyword )
+ str << "color ";
+
+ if( approxZero( m_colorValue[4] ) )
+ {
+ if( approxZero( m_colorValue[3] ) )
+ {
+ // rgb
+ str << "rgb <" << m_colorValue[0] << ", " << m_colorValue[1] << ", "
+ << m_colorValue[2] << '>';
+ }
+ else
+ {
+ // rgbf
+ str << "rgbf <" << m_colorValue[0] << ", " << m_colorValue[1] << ", "
+ << m_colorValue[2] << ", " << m_colorValue[3] << '>';
+ }
+ }
+ else
+ {
+ if( approxZero( m_colorValue[3] ) )
+ {
+ // rgbt
+ str << "rgbt <" << m_colorValue[0] << ", " << m_colorValue[1] << ", "
+ << m_colorValue[2] << ", " << m_colorValue[4] << '>';
+ }
+ else
+ {
+ // rgbft
+ str << "rgbft <" << m_colorValue[0] << ", " << m_colorValue[1] << ", "
+ << m_colorValue[2] << ", " << m_colorValue[3]
+ << ", " << m_colorValue[4] << '>';
+ }
+ }
+
+ return result;
+}
+
+QString PMColor::serializeXML( ) const
+{
+ QString result;
+ QTextStream str( &result, IO_WriteOnly );
+ int i;
+
+ for( i = 0; i < 5; i++ )
+ {
+ if( i != 0 )
+ str << ' ';
+ str << m_colorValue[i];
+ }
+
+ return result;
+}
+
+bool PMColor::operator!= ( const PMColor& c ) const
+{
+ return !( *this == c );
+}
+
+bool PMColor::operator== ( const PMColor& c ) const
+{
+ unsigned int i;
+
+ for( i = 0; i < 5; i++ )
+ if( c.m_colorValue[i] != m_colorValue[i] )
+ return false;
+ return true;
+}
+
+bool PMColor::loadXML( const QString& str )
+{
+ QString tmp( str );
+ QTextStream s( &tmp, IO_ReadOnly );
+ QString val;
+ bool ok;
+ int i;
+
+ for( i = 0; i < 5; i++ )
+ {
+ s >> val;
+ m_colorValue[i] = val.toDouble( &ok );
+ if( !ok )
+ return false;
+ }
+ return true;
+}
diff --git a/kpovmodeler/pmcolor.h b/kpovmodeler/pmcolor.h
new file mode 100644
index 00000000..7ae0eeab
--- /dev/null
+++ b/kpovmodeler/pmcolor.h
@@ -0,0 +1,130 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMCOLOR_H
+#define PMCOLOR_H
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class PMVector;
+
+/**
+ * Class for povray colors (red, green, blue, filter and transmit amount)
+ */
+class PMColor
+{
+public:
+ /**
+ * Creates a color with all values set to 0.0
+ */
+ PMColor( );
+ /**
+ * Creates a color
+ */
+ PMColor( const double red, const double green, const double blue,
+ const double filter, const double transmit );
+ /**
+ * Creates a color with filter and transmit set to 0
+ */
+ PMColor( const double red, const double green, const double blue );
+ /**
+ * Creates a color from a @ref PMVector. The vector has to be of size 5
+ */
+ PMColor( const PMVector& v );
+ /**
+ * Creates a color from a @ref QColor object.
+ * filter and transmit are set to 0
+ */
+ PMColor( const QColor& c );
+
+ /**
+ * Sets the red value
+ */
+ void setRed( double d ) { m_colorValue[0] = d; }
+ /**
+ * Returns the red value
+ */
+ double red( ) const { return m_colorValue[0]; }
+ /**
+ * Sets the green value
+ */
+ void setGreen( double d ) { m_colorValue[1] = d; }
+ /**
+ * Returns the green value
+ */
+ double green( ) const { return m_colorValue[1]; }
+ /**
+ * Sets the blue value
+ */
+ void setBlue( double d ) { m_colorValue[2] = d; }
+ /**
+ * Returns the red value
+ */
+ double blue( ) const { return m_colorValue[2]; }
+ /**
+ * Sets the filter value
+ */
+ void setFilter( double d ) { m_colorValue[3] = d; }
+ /**
+ * Returns the filter value
+ */
+ double filter( ) const { return m_colorValue[3]; }
+ /**
+ * Sets the transmit value
+ */
+ void setTransmit( double d ) { m_colorValue[4] = d; }
+ /**
+ * Returns the transmit value
+ */
+ double transmit( ) const { return m_colorValue[4]; }
+
+ /**
+ * Returns the rgb value as QColor
+ */
+ QColor toQColor( ) const;
+
+ /**
+ * Returns a string for serialization
+ */
+ QString serialize( bool addColorKeyword = false ) const;
+ /**
+ * Returns a string for xml output
+ */
+ QString serializeXML( ) const;
+ /**
+ * loads the color data from the xml string
+ */
+ bool loadXML( const QString& str );
+
+ /**
+ * Returns true if the colors are equal*/
+ bool operator== ( const PMColor& p ) const;
+ /**
+ * Returns false if the colors are equal
+ */
+ bool operator!= ( const PMColor& p ) const;
+private:
+ /**
+ * The color values. Index 0 is red, 1 green, 2 blue, 3 filter, 4 transmit
+ */
+ double m_colorValue[5];
+
+};
+
+#endif
diff --git a/kpovmodeler/pmcoloredit.cpp b/kpovmodeler/pmcoloredit.cpp
new file mode 100644
index 00000000..06ac4d0f
--- /dev/null
+++ b/kpovmodeler/pmcoloredit.cpp
@@ -0,0 +1,201 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmcoloredit.h"
+#include "pmlineedits.h"
+#include <kcolorbutton.h>
+#include <klocale.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qcolor.h>
+#include <kdialog.h>
+
+PMColorEdit::PMColorEdit( bool filterAndTransmit, QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ m_bFilterAndTransmit = filterAndTransmit;
+
+ m_edits[0] = new PMFloatEdit( this );
+ m_edits[1] = new PMFloatEdit( this );
+ m_edits[2] = new PMFloatEdit( this );
+ if( filterAndTransmit )
+ {
+ m_edits[3] = new PMFloatEdit( this );
+ m_edits[4] = new PMFloatEdit( this );
+ }
+ else
+ {
+ m_edits[3] = 0;
+ m_edits[4] = 0;
+ }
+ m_pButton = new KColorButton( this );
+
+ QVBoxLayout* topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+ QHBoxLayout* l = new QHBoxLayout( topLayout );
+ l->addWidget( m_pButton );
+ l = new QHBoxLayout( topLayout );
+ l->addWidget( new QLabel( i18n( "red:" ), this ) );
+ l->addWidget( m_edits[0] );
+ l->addWidget( new QLabel( i18n( "green:" ), this ) );
+ l->addWidget( m_edits[1] );
+ l->addWidget( new QLabel( i18n( "blue:" ), this ) );
+ l->addWidget( m_edits[2] );
+ if( filterAndTransmit )
+ {
+ l = new QHBoxLayout( topLayout );
+ l->addWidget( new QLabel( i18n( "filter" ), this ) );
+ l->addWidget( m_edits[3] );
+ l->addWidget( new QLabel( i18n( "transmit" ), this ) );
+ l->addWidget( m_edits[4] );
+ }
+
+ connect( m_edits[0], SIGNAL( dataChanged( ) ), SLOT( slotEditChanged( ) ) );
+ connect( m_edits[1], SIGNAL( dataChanged( ) ), SLOT( slotEditChanged( ) ) );
+ connect( m_edits[2], SIGNAL( dataChanged( ) ), SLOT( slotEditChanged( ) ) );
+ if( filterAndTransmit )
+ {
+ connect( m_edits[3], SIGNAL( dataChanged( ) ), SLOT( slotEditChanged( ) ) );
+ connect( m_edits[4], SIGNAL( dataChanged( ) ), SLOT( slotEditChanged( ) ) );
+ }
+ connect( m_pButton, SIGNAL( changed( const QColor& ) ),
+ SLOT( slotColorChanged( const QColor& ) ) );
+}
+
+void PMColorEdit::setColor( const PMColor& c )
+{
+ bool blocked[5];
+ int i;
+ int num = m_bFilterAndTransmit ? 5 : 3;
+
+ for( i = 0; i < num; i++ )
+ {
+ blocked[i] = m_edits[i]->signalsBlocked( );
+ m_edits[i]->blockSignals( true );
+ }
+
+ m_color = c;
+ m_edits[0]->setValue( c.red( ) );
+ m_edits[1]->setValue( c.green( ) );
+ m_edits[2]->setValue( c.blue( ) );
+ if( m_bFilterAndTransmit )
+ {
+ m_edits[3]->setValue( c.filter( ) );
+ m_edits[4]->setValue( c.transmit( ) );
+ }
+ updateButton( );
+
+ for( i = 0; i < num; i++ )
+ m_edits[i]->blockSignals( blocked[i] );
+}
+
+void PMColorEdit::updateButton( )
+{
+ bool b = m_pButton->signalsBlocked( );
+ m_pButton->blockSignals( true );
+ m_pButton->setColor( m_color.toQColor( ) );
+ m_pButton->blockSignals( b );
+}
+
+bool PMColorEdit::isDataValid( )
+{
+ if( !m_edits[0]->isDataValid( ) )
+ return false;
+ if( !m_edits[1]->isDataValid( ) )
+ return false;
+ if( !m_edits[2]->isDataValid( ) )
+ return false;
+ if( m_bFilterAndTransmit )
+ {
+ if( !m_edits[3]->isDataValid( ) )
+ return false;
+ if( !m_edits[4]->isDataValid( ) )
+ return false;
+ }
+ return true;
+}
+
+void PMColorEdit::setReadOnly( bool yes )
+{
+ m_edits[0]->setReadOnly( yes );
+ m_edits[1]->setReadOnly( yes );
+ m_edits[2]->setReadOnly( yes );
+ if( m_bFilterAndTransmit )
+ {
+ m_edits[3]->setReadOnly( yes );
+ m_edits[4]->setReadOnly( yes );
+ }
+ m_pButton->setEnabled( !yes );
+}
+
+void PMColorEdit::slotColorChanged( const QColor& c )
+{
+ int i;
+ bool blocked[3];
+
+ for( i = 0; i < 3; i++ )
+ {
+ blocked[i] = m_edits[i]->signalsBlocked( );
+ m_edits[i]->blockSignals( true );
+ }
+
+ m_color.setRed( c.red( ) / 255.0 );
+ m_color.setGreen( c.green( ) / 255.0 );
+ m_color.setBlue( c.blue( ) / 255.0 );
+
+ m_edits[0]->setValue( m_color.red( ) );
+ m_edits[1]->setValue( m_color.green( ) );
+ m_edits[2]->setValue( m_color.blue( ) );
+
+ for( i = 0; i < 3; i++ )
+ m_edits[i]->blockSignals( blocked[i] );
+
+ emit dataChanged( );
+}
+
+void PMColorEdit::slotEditChanged( )
+{
+ bool ok;
+
+ m_edits[0]->text( ).toDouble( &ok );
+ if( ok )
+ m_edits[1]->text( ).toDouble( &ok );
+ if( ok )
+ m_edits[2]->text( ).toDouble( &ok );
+ if( m_bFilterAndTransmit )
+ {
+ if( ok )
+ m_edits[3]->text( ).toDouble( &ok );
+ if( ok )
+ m_edits[4]->text( ).toDouble( &ok );
+ }
+
+ if( ok )
+ {
+ m_color.setRed( m_edits[0]->value( ) );
+ m_color.setGreen( m_edits[1]->value( ) );
+ m_color.setBlue( m_edits[2]->value( ) );
+ if( m_bFilterAndTransmit )
+ {
+ m_color.setFilter( m_edits[3]->value( ) );
+ m_color.setTransmit( m_edits[4]->value( ) );
+ }
+ updateButton( );
+ }
+ emit dataChanged( );
+}
+
+#include "pmcoloredit.moc"
diff --git a/kpovmodeler/pmcoloredit.h b/kpovmodeler/pmcoloredit.h
new file mode 100644
index 00000000..4b581a0f
--- /dev/null
+++ b/kpovmodeler/pmcoloredit.h
@@ -0,0 +1,83 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCOLOREDIT_H
+#define PMCOLOREDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include "pmcolor.h"
+
+class KColorButton;
+class PMFloatEdit;
+class QColor;
+
+/**
+ * Edit widget for @ref PMColor
+ */
+class PMColorEdit : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates an edit widget for rgbft colors.
+ */
+ PMColorEdit( bool filterAndTransmit, QWidget* parent, const char* name = 0 );
+
+ /**
+ * Sets the displayed color
+ */
+ void setColor( const PMColor& c );
+ /**
+ * Returns the color
+ */
+ PMColor color( ) const { return m_color; }
+
+ /**
+ * Returns true if the input is a valid
+ * color value. Otherwise an error message is shown.
+ */
+ bool isDataValid( );
+
+ /**
+ * Enables or disables read only mode
+ */
+ void setReadOnly( bool yes = true );
+signals:
+ /**
+ * Emitted when the color is changed
+ */
+ void dataChanged( );
+
+protected slots:
+ void slotColorChanged( const QColor& c );
+ void slotEditChanged( );
+private:
+ void updateButton( );
+private:
+ PMFloatEdit* m_edits[5];
+ KColorButton* m_pButton;
+ bool m_bFilterAndTransmit;
+ PMColor m_color;
+};
+
+#endif
diff --git a/kpovmodeler/pmcolorsettings.cpp b/kpovmodeler/pmcolorsettings.cpp
new file mode 100644
index 00000000..d5924d4b
--- /dev/null
+++ b/kpovmodeler/pmcolorsettings.cpp
@@ -0,0 +1,163 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmcolorsettings.h"
+
+#include "pmrendermanager.h"
+#include "pmdefaults.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <kcolorbutton.h>
+#include <klocale.h>
+
+PMColorSettings::PMColorSettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ QHBoxLayout* hlayout;
+ QVBoxLayout* vlayout;
+ QGridLayout* grid;
+
+ vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+ grid = new QGridLayout( vlayout, 6, 3 );
+
+ grid->addWidget( new QLabel( i18n( "Background:" ), this ), 0, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 0, 2 );
+ m_pBackgroundColor = new KColorButton( this );
+ hlayout->addWidget( m_pBackgroundColor );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Wire frame:" ), this ), 1, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 1, 2 );
+ m_pGraphicalObjectsColor[0] = new KColorButton( this );
+ hlayout->addWidget( m_pGraphicalObjectsColor[0] );
+ hlayout->addWidget( new QLabel( i18n( "Selected:" ), this ) );
+ m_pGraphicalObjectsColor[1] = new KColorButton( this );
+ hlayout->addWidget( m_pGraphicalObjectsColor[1] );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Control points:" ), this ), 2, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 2, 2 );
+ m_pControlPointsColor[0] = new KColorButton( this );
+ hlayout->addWidget( m_pControlPointsColor[0] );
+ hlayout->addWidget( new QLabel( i18n( "Selected:" ), this ) );
+ m_pControlPointsColor[1] = new KColorButton( this );
+ hlayout->addWidget( m_pControlPointsColor[1] );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Axes:" ), this ), 3, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 3, 2 );
+ grid->addWidget( new QLabel( "x", this ), 3, 1 );
+ m_pAxesColor[0] = new KColorButton( this );
+ hlayout->addWidget( m_pAxesColor[0] );
+ hlayout->addWidget( new QLabel( "y", this ) );
+ m_pAxesColor[1] = new KColorButton( this );
+ hlayout->addWidget( m_pAxesColor[1] );
+ hlayout->addWidget( new QLabel( "z", this ) );
+ m_pAxesColor[2] = new KColorButton( this );
+ hlayout->addWidget( m_pAxesColor[2] );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Field of view:" ), this ), 4, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 4, 2 );
+ m_pFieldOfViewColor = new KColorButton( this );
+ hlayout->addWidget( m_pFieldOfViewColor );
+ hlayout->addStretch( 1 );
+}
+
+void PMColorSettings::displaySettings( )
+{
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ m_pBackgroundColor->setColor( rm->backgroundColor( ) );
+ m_pGraphicalObjectsColor[0]->setColor( rm->graphicalObjectColor( 0 ) );
+ m_pGraphicalObjectsColor[1]->setColor( rm->graphicalObjectColor( 1 ) );
+ m_pControlPointsColor[0]->setColor( rm->controlPointColor( 0 ) );
+ m_pControlPointsColor[1]->setColor( rm->controlPointColor( 1 ) );
+ m_pAxesColor[0]->setColor( rm->axesColor( 0 ) );
+ m_pAxesColor[1]->setColor( rm->axesColor( 1 ) );
+ m_pAxesColor[2]->setColor( rm->axesColor( 2 ) );
+ m_pFieldOfViewColor->setColor( rm->fieldOfViewColor( ) );
+}
+
+void PMColorSettings::displayDefaults( )
+{
+ m_pBackgroundColor->setColor( c_defaultBackgroundColor );
+ m_pGraphicalObjectsColor[0]->setColor( c_defaultGraphicalObjectColor0 );
+ m_pGraphicalObjectsColor[1]->setColor( c_defaultGraphicalObjectColor1 );
+ m_pControlPointsColor[0]->setColor( c_defaultControlPointColor0 );
+ m_pControlPointsColor[1]->setColor( c_defaultControlPointColor1 );
+ m_pAxesColor[0]->setColor( c_defaultAxesColorX );
+ m_pAxesColor[1]->setColor( c_defaultAxesColorY );
+ m_pAxesColor[2]->setColor( c_defaultAxesColorZ );
+ m_pFieldOfViewColor->setColor( c_defaultFieldOfViewColor );
+}
+
+bool PMColorSettings::validateData( )
+{
+ return true;
+}
+
+void PMColorSettings::applySettings( )
+{
+ bool repaint = false;
+ int i;
+
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ if( rm->backgroundColor( ) != m_pBackgroundColor->color( ) )
+ {
+ rm->setBackgroundColor( m_pBackgroundColor->color( ) );
+ repaint = true;
+ }
+ for( i = 0; i < 2; i++ )
+ {
+ if( rm->graphicalObjectColor( i ) != m_pGraphicalObjectsColor[i]->color( ) )
+ {
+ rm->setGraphicalObjectColor( i, m_pGraphicalObjectsColor[i]->color( ) );
+ repaint = true;
+ }
+ }
+ for( i = 0; i < 2; i++ )
+ {
+ if( rm->controlPointColor( i ) != m_pControlPointsColor[i]->color( ) )
+ {
+ rm->setControlPointColor( i, m_pControlPointsColor[i]->color( ) );
+ repaint = true;
+ }
+ }
+ for( i = 0; i < 3; i++ )
+ {
+ if( rm->axesColor( i ) != m_pAxesColor[i]->color( ) )
+ {
+ rm->setAxesColor( i, m_pAxesColor[i]->color( ) );
+ repaint = true;
+ }
+ }
+ if( rm->fieldOfViewColor( ) != m_pFieldOfViewColor->color( ) )
+ {
+ rm->setFieldOfViewColor( m_pFieldOfViewColor->color( ) );
+ repaint = true;
+ }
+ if( repaint )
+ emit repaintViews( );
+}
+
+#include "pmcolorsettings.moc"
diff --git a/kpovmodeler/pmcolorsettings.h b/kpovmodeler/pmcolorsettings.h
new file mode 100644
index 00000000..9ad628e0
--- /dev/null
+++ b/kpovmodeler/pmcolorsettings.h
@@ -0,0 +1,58 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMCOLORSETTINGS_H
+#define PMCOLORSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+
+class KColorButton;
+
+/**
+ * Colors configuration dialog page
+ */
+class PMColorSettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMColorSettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual void displayDefaults( );
+
+private:
+ KColorButton* m_pBackgroundColor;
+ KColorButton* m_pGraphicalObjectsColor[2];
+ KColorButton* m_pControlPointsColor[2];
+ KColorButton* m_pAxesColor[3];
+ KColorButton* m_pFieldOfViewColor;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmcommand.h b/kpovmodeler/pmcommand.h
new file mode 100644
index 00000000..9bdca16f
--- /dev/null
+++ b/kpovmodeler/pmcommand.h
@@ -0,0 +1,146 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCOMMAND_H
+#define PMCOMMAND_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qptrlist.h>
+
+#include "pmmessage.h"
+#include "pmerrorflags.h"
+
+class PMCommandManager;
+class PMObject;
+class PMPart;
+
+/**
+ * Constants for object changes
+ *
+ * PMCAdd: An object was added
+ *
+ * PMCRemove: An object was removed. A signal with this constant has
+ * to be emitted _before_ the object is removed.
+ *
+ * PMCChildren: Some children are added or removed. Do not use. Use PMCAdd and
+ * PMCRemove for all childrens.
+ *
+ * PMCData: Data (for dialog views) is changed
+ *
+ * PMCDescription: The name or pixmap of the object has changed. Always
+ * together with PMCData.
+ *
+ * PMCViewStructure: The rendering has changed
+ *
+ * PMCNewSelection: The object was selected and all other deleselected.
+ * If the changed object is 0, all objects are deselected!
+ *
+ * PMCSelected: The object was selected.
+ *
+ * PMCDeselected: The object was deselected.
+ *
+ * PMCNewControlPoints: The list of control points has changed.
+ *
+ * PMCControlPointSelection: The control point selection has changed.
+ *
+ * PMCInsertError: The added object couldn't be inserted and was appended
+ * to the insert errors. Always together with PMCAdd.
+ *
+ * PMCNothing: Nothing was changed
+ */
+enum PMChange
+{
+ PMCNothing = 0, PMCAdd = 1, PMCRemove = 2, PMCChildren = 4,
+ PMCData = 8, PMCDescription = 16, PMCViewStructure = 32,
+ PMCGraphicalChange = 64,
+ PMCNewSelection = 128, PMCSelected = 256,
+ PMCDeselected = 512,
+ PMCNewControlPoints = 1024, PMCControlPointSelection = 2048,
+ PMCInsertError = 4096
+};
+
+/**
+ * Base class for all commands, that support undo/redo.
+ */
+class PMCommand
+{
+ friend class PMCommandManager; // only PMCommandManager can execute commands
+public:
+ /**
+ * Creates an empty command object.
+ */
+ PMCommand( ) { }
+ /**
+ * Creates a command with command text text
+ */
+ PMCommand( const QString &text )
+ { m_text = text; }
+ /**
+ * Deletes the command.
+ */
+ virtual ~PMCommand( ) { }
+
+ /**
+ * Command text shown in the undo/redo menues
+ */
+ QString text( ) const { return m_text; }
+ /**
+ * Sets the command text
+ */
+ void setText( const QString& s ) { m_text = s; }
+
+ /**
+ * Checks if the command is valid and sets the error message
+ *
+ * Returns a bitwise combination of @ref PMErrorFlags flags
+ */
+ virtual int errorFlags( PMPart* ) { return PMENone; }
+ /**
+ * Returns the error message
+ */
+ PMMessageList messages( ) { return m_errors; }
+
+protected:
+ /**
+ * Executes the command and stores undo information.
+ */
+ virtual void execute( PMCommandManager* theManager ) = 0;
+ /**
+ * Undoes the command
+ */
+ virtual void undo( PMCommandManager* theManager ) = 0;
+ /**
+ * The error messages
+ */
+ PMMessageList m_errors;
+
+private:
+ /**
+ * The command text.
+ */
+ QString m_text;
+};
+
+typedef QPtrList<PMCommand> PMCommandList;
+
+#endif
diff --git a/kpovmodeler/pmcommandmanager.cpp b/kpovmodeler/pmcommandmanager.cpp
new file mode 100644
index 00000000..333468e3
--- /dev/null
+++ b/kpovmodeler/pmcommandmanager.cpp
@@ -0,0 +1,99 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcommandmanager.h"
+#include "pmpart.h"
+
+PMCommandManager::PMCommandManager( PMPart* thePart )
+{
+ m_commands.setAutoDelete( true );
+ m_redoCommands.setAutoDelete( true );
+ m_maxUndoRedo = 50;
+ m_pPart = thePart;
+}
+
+PMCommandManager::~PMCommandManager( )
+{
+ m_commands.clear( );
+ m_redoCommands.clear( );
+}
+
+void PMCommandManager::execute( PMCommand* cmd )
+{
+ // some commands (like control point commands) can be executed
+ // multiple times.
+ cmd->execute( this );
+
+ if( m_commands.last( ) != cmd )
+ m_commands.append( cmd );
+ while( m_commands.count( ) > m_maxUndoRedo )
+ m_commands.removeFirst( );
+ m_redoCommands.clear( );
+
+ emit updateUndoRedo( cmd->text( ), QString::null );
+}
+
+void PMCommandManager::undo( )
+{
+ if( !m_commands.isEmpty( ) )
+ {
+ PMCommand* last = m_commands.last( );
+ last->undo( this );
+
+ m_redoCommands.append( m_commands.take( ) );
+
+ if( m_commands.isEmpty( ) )
+ emit updateUndoRedo( QString::null, last->text( ) );
+ else
+ emit updateUndoRedo( m_commands.last( )->text( ), last->text( ) );
+ }
+}
+
+void PMCommandManager::redo( )
+{
+ if( !m_redoCommands.isEmpty( ) )
+ {
+ PMCommand* last = m_redoCommands.last( );
+ last->execute( this );
+
+ m_commands.append( m_redoCommands.take( ) );
+
+ if( m_redoCommands.isEmpty( ) )
+ emit updateUndoRedo( last->text( ), QString::null );
+ else
+ emit updateUndoRedo( last->text( ), m_redoCommands.last( )->text( ) );
+ }
+}
+
+void PMCommandManager::clear( )
+{
+ m_redoCommands.clear( );
+ m_commands.clear( );
+ emit updateUndoRedo( QString::null, QString::null );
+}
+
+void PMCommandManager::cmdObjectChanged( PMObject* obj, const int mode )
+{
+ emit objectChanged( obj, mode, this );
+}
+
+void PMCommandManager::cmdIDChanged( PMObject* obj, const QString& oldID )
+{
+ emit idChanged( obj, oldID );
+}
+#include "pmcommandmanager.moc"
diff --git a/kpovmodeler/pmcommandmanager.h b/kpovmodeler/pmcommandmanager.h
new file mode 100644
index 00000000..2ef2fbbc
--- /dev/null
+++ b/kpovmodeler/pmcommandmanager.h
@@ -0,0 +1,118 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCOMMANDMANAGER_H
+#define PMCOMMANDMANAGER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcommand.h"
+#include <qptrstack.h>
+#include <qobject.h>
+
+class PMPart;
+
+/**
+ * Manager for PMCommand objects.
+ *
+ * The class PMCommandManager stores stacks of commands for undo/redo
+ * operations.
+ */
+class PMCommandManager : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a new PMCommandManager
+ */
+ PMCommandManager( PMPart* thepart );
+ /**
+ * Deletes the command manager. All commands are deleted as well.
+ */
+ ~PMCommandManager( );
+ /**
+ * Adds the @ref PMCommand to the command stack.
+ * All commands in the m_redoCommands stack are deleted.
+ */
+ void execute( PMCommand* cmd );
+ /**
+ * Moves the last command to the m_redoCommands stack.
+ */
+ void undo( );
+ /**
+ * Moves the last redo command to the command stack.
+ */
+ void redo( );
+ /**
+ * Deletes the commands
+ */
+ void clear( );
+ /**
+ * Returns the maximal number of items that can be undone/redone.
+ */
+ unsigned int maxUndoRedo( ) const { return m_maxUndoRedo; }
+ /**
+ * Sets the maximal number of items that can be undone/redone.
+ */
+ void setMaxUndoRedo( unsigned int n ) { m_maxUndoRedo = n; }
+ /**
+ * Called by an executed command. Will emit objectChanged( )
+ */
+ void cmdObjectChanged( PMObject* obj, const int mode );
+ /**
+ * Called by an executed command. Will emit idChanged( )
+ */
+ void cmdIDChanged( PMObject* obj, const QString& oldID );
+ /**
+ * Returns a pointer to the part. For commands that need to access the
+ * part directly.
+ */
+ PMPart* part( ) const { return m_pPart; }
+signals:
+ /**
+ * emmited, when the undo and redo command texts change
+ */
+ void updateUndoRedo( const QString& undo, const QString& redo );
+ /**
+ * Signal that is emitted when an object is changed.
+ * Mode is a bit combination of @ref PMChange constants.
+ */
+ void objectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Signal that is emitted when the id of the object is changed
+ */
+ void idChanged( PMObject* obj, const QString& oldID );
+private:
+ /**
+ * The executed commands.
+ */
+ PMCommandList m_commands;
+ /**
+ * The undone commands.
+ */
+ PMCommandList m_redoCommands;
+ // the maximal number of items that can be undone/redone.
+ unsigned int m_maxUndoRedo;
+ PMObject* m_pLastChangedObject;
+ PMPart* m_pPart;
+};
+
+#endif
diff --git a/kpovmodeler/pmcomment.cpp b/kpovmodeler/pmcomment.cpp
new file mode 100644
index 00000000..e4783ae5
--- /dev/null
+++ b/kpovmodeler/pmcomment.cpp
@@ -0,0 +1,174 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcomment.h"
+#include "pmxmlhelper.h"
+
+#include "pmcommentedit.h"
+#include "pmmemento.h"
+
+#include <qtextstream.h>
+#include <klocale.h>
+
+PMDefinePropertyClass( PMComment, PMCommentProperty );
+
+PMMetaObject* PMComment::s_pMetaObject = 0;
+PMObject* createNewComment( PMPart* part )
+{
+ return new PMComment( part );
+}
+
+const unsigned int c_maxDescriptionLength = 25;
+
+PMComment::PMComment( PMPart* part )
+ : Base( part )
+{
+}
+
+PMComment::PMComment( PMPart* part, const QString& t )
+ : Base( part )
+{
+ m_text = t;
+}
+
+PMComment::PMComment( const PMComment& c )
+ : Base( c )
+{
+ m_text = c.m_text;
+}
+
+PMComment::~PMComment( )
+{
+}
+
+QString PMComment::description( ) const
+{
+ if( !m_text.isEmpty( ) )
+ {
+ QString copy = m_text;
+ QTextStream str( &copy, IO_ReadOnly );
+ QString tmp, desc;
+ bool stop = false;
+ bool truncated = false;
+
+ while( !str.atEnd( ) && !stop )
+ {
+ str >> tmp;
+ if( desc.length( ) + tmp.length( ) + 1 <= c_maxDescriptionLength )
+ {
+ if( !desc.isEmpty( ) )
+ desc += " ";
+ desc += tmp;
+ }
+ else
+ {
+ if( desc.isEmpty( ) )
+ {
+ desc = tmp.left( c_maxDescriptionLength );
+ if( tmp.length( ) > c_maxDescriptionLength )
+ truncated = true;
+ }
+ else
+ truncated = true;
+ stop = true;
+ }
+ }
+ if( truncated )
+ desc += "...";
+ return desc;
+ }
+ return i18n( "comment" );
+}
+
+void PMComment::setText( const QString& text )
+{
+ if( text != m_text )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMTextID, m_text );
+ m_pMemento->setDescriptionChanged( );
+ }
+ m_text = text;
+ }
+}
+
+PMMetaObject* PMComment::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Comment", Base::metaObject( ),
+ createNewComment );
+ s_pMetaObject->addProperty(
+ new PMCommentProperty( "text", &PMComment::setText, &PMComment::text ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMComment::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMComment::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ QDomText t = doc.createTextNode( m_text );
+ e.appendChild( t );
+}
+
+void PMComment::readAttributes( const PMXMLHelper& h )
+{
+ QDomNode e = h.element( ).firstChild( );
+ if( e.isText( ) )
+ m_text = e.toText( ).data( );
+}
+
+PMDialogEditBase* PMComment::editWidget( QWidget* parent ) const
+{
+ return new PMCommentEdit( parent );
+}
+
+void PMComment::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMTextID:
+ setText( data->stringData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMComment::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmcomment.h b/kpovmodeler/pmcomment.h
new file mode 100644
index 00000000..82c62fa8
--- /dev/null
+++ b/kpovmodeler/pmcomment.h
@@ -0,0 +1,92 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCOMMENT_H
+#define PMCOMMENT_H
+
+#include "pmobject.h"
+#include <qstring.h>
+
+
+/**
+ * Class for povray comments
+ */
+
+class PMComment : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates an enpty comment
+ */
+ PMComment( PMPart* part );
+ /**
+ * Creates a comment with text t
+ */
+ PMComment( PMPart* part, const QString& t );
+ /**
+ * Copy constructor
+ */
+ PMComment( const PMComment& c );
+ /**
+ * Deletes the comment
+ */
+ ~PMComment( );
+
+ /**
+ * Sets the comment text
+ */
+ void setText( const QString& text );
+ /**
+ * Returns the comment text
+ */
+ QString text( ) const { return m_text; }
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMComment( *this ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /** */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmcomment" ); }
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMCommentMementoID { PMTextID };
+ QString m_text;
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmcommentedit.cpp b/kpovmodeler/pmcommentedit.cpp
new file mode 100644
index 00000000..6fa5ba9e
--- /dev/null
+++ b/kpovmodeler/pmcommentedit.cpp
@@ -0,0 +1,75 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcommentedit.h"
+#include "pmcomment.h"
+
+#include <qlayout.h>
+#include <qmultilineedit.h>
+#include <kglobalsettings.h>
+
+PMCommentEdit::PMCommentEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMCommentEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pEdit = new QMultiLineEdit( this );
+#if ( QT_VERSION >= 300 )
+ m_pEdit->setTextFormat( Qt::PlainText );
+ m_pEdit->setWordWrap( QTextEdit::NoWrap );
+#endif
+ m_pEdit->setFont( KGlobalSettings::fixedFont( ) );
+ topLayout( )->addWidget( m_pEdit, 2 );
+
+ connect( m_pEdit, SIGNAL( textChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMCommentEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Comment" ) )
+ {
+ m_pDisplayedObject = ( PMComment* ) o;
+ m_pEdit->setText( m_pDisplayedObject->text( ) );
+
+ m_pEdit->setReadOnly( o->isReadOnly( ) );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMCommentEdit: Can't display object\n";
+}
+
+void PMCommentEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setText( m_pEdit->text( ) );
+ }
+}
+
+bool PMCommentEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+#include "pmcommentedit.moc"
diff --git a/kpovmodeler/pmcommentedit.h b/kpovmodeler/pmcommentedit.h
new file mode 100644
index 00000000..b3dc1d25
--- /dev/null
+++ b/kpovmodeler/pmcommentedit.h
@@ -0,0 +1,62 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCOMMENTEDIT_H
+#define PMCOMMENTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMComment;
+class QMultiLineEdit;
+
+/**
+ * Dialog edit class for @ref PMComment.
+ */
+class PMCommentEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMCommentEdit with parent and name
+ */
+ PMCommentEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMComment* m_pDisplayedObject;
+ QMultiLineEdit* m_pEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmcompositeobject.cpp b/kpovmodeler/pmcompositeobject.cpp
new file mode 100644
index 00000000..c1ab704d
--- /dev/null
+++ b/kpovmodeler/pmcompositeobject.cpp
@@ -0,0 +1,396 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcompositeobject.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+
+#include <qdom.h>
+
+PMMetaObject* PMCompositeObject::s_pMetaObject = 0;
+
+PMCompositeObject::PMCompositeObject( PMPart* part )
+ : Base( part )
+{
+ m_pFirstChild = 0;
+ m_pLastChild = 0;
+ m_selectedChildren = 0;
+ m_bViewStructureChanged = true;
+ m_pViewStructure = 0;
+}
+
+PMCompositeObject::PMCompositeObject( const PMCompositeObject& c )
+ : Base( c )
+{
+ m_pFirstChild = 0;
+ m_pLastChild = 0;
+ m_selectedChildren = 0;
+ m_bViewStructureChanged = true;
+ m_pViewStructure = 0;
+
+ PMObject* o = c.m_pFirstChild;
+ for( ; o; o = o->nextSibling( ) )
+ appendChild( o->copy( ) );
+}
+
+PMCompositeObject::~PMCompositeObject( )
+{
+ PMObject* tmp;
+ PMObject* next;
+
+ tmp = m_pFirstChild;
+
+ while( tmp )
+ {
+ next = tmp->m_pNextSibling;
+ delete tmp;
+ tmp = next;
+ }
+
+ if( m_pViewStructure )
+ delete m_pViewStructure;
+}
+
+PMMetaObject* PMCompositeObject::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ s_pMetaObject = new PMMetaObject( "CompositeObject", Base::metaObject( ) );
+ return s_pMetaObject;
+}
+
+void PMCompositeObject::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+PMObject* PMCompositeObject::childAt( uint index ) const
+{
+ PMObject* tmp;
+ uint i = 0;
+
+ for( tmp = m_pFirstChild; tmp && ( i < index ); tmp = tmp->nextSibling( ) )
+ i++;
+ return tmp;
+}
+
+int PMCompositeObject::findChild( PMObject* o )
+{
+ if( o->parent( ) != this )
+ return -1;
+
+ PMObject* tmp;
+ int index = 0;
+
+ for( tmp = m_pFirstChild; tmp; tmp = tmp->nextSibling( ) )
+ {
+ if( tmp == o )
+ return index;
+ else
+ index++;
+ }
+ return -1;
+}
+
+bool PMCompositeObject::insertChild( PMObject* o, int i )
+{
+ if( i < 0 )
+ return appendChild( o );
+ else
+ {
+ if( i == 0 )
+ {
+ if( canInsert( o, 0 ) )
+ {
+ o->m_pNextSibling = m_pFirstChild;
+ o->m_pPrevSibling = 0;
+ if( m_pFirstChild )
+ m_pFirstChild->m_pPrevSibling = o;
+ m_pFirstChild = o;
+ if( !m_pLastChild )
+ m_pLastChild = o;
+ o->m_pParent = this;
+ }
+ else
+ return false;
+ }
+ else
+ {
+ PMObject* tmp = childAt( ( uint ) ( i - 1 ) );
+ if( !tmp )
+ {
+ kdError( PMArea ) << "Index too big" << "\n";
+ return false;
+ }
+
+ if( canInsert( o, tmp ) )
+ {
+ o->m_pPrevSibling = tmp;
+ o->m_pNextSibling = tmp->m_pNextSibling;
+ if( tmp->m_pNextSibling )
+ tmp->m_pNextSibling->m_pPrevSibling = o;
+ else
+ m_pLastChild = o;
+ tmp->m_pNextSibling = o;
+ o->m_pParent = this;
+ }
+ else
+ return false;
+ }
+ childAdded( o );
+ return true;
+ }
+ return false;
+}
+
+bool PMCompositeObject::appendChild( PMObject* o )
+{
+ if( canInsert( o, m_pLastChild ) )
+ {
+ o->m_pParent = this;
+ o->m_pPrevSibling = m_pLastChild;
+ o->m_pNextSibling = 0;
+ if( m_pLastChild )
+ m_pLastChild->m_pNextSibling = o;
+ else
+ m_pFirstChild = o;
+ m_pLastChild = o;
+
+ childAdded( o );
+ return true;
+ }
+ return false;
+}
+
+bool PMCompositeObject::insertChildAfter( PMObject* obj, PMObject* after )
+{
+ if( canInsert( obj, after ) )
+ {
+ if( after->m_pParent == this )
+ {
+ obj->m_pParent = this;
+ obj->m_pPrevSibling = after;
+ obj->m_pNextSibling = after->m_pNextSibling;
+ if( after->m_pNextSibling )
+ after->m_pNextSibling->m_pPrevSibling = obj;
+ else
+ m_pLastChild = obj;
+ after->m_pNextSibling = obj;
+
+ childAdded( obj );
+ return true;
+ }
+ else
+ {
+ kdError( PMArea ) << "Object after is no child" << "\n";
+ return false;
+ }
+ }
+ return false;
+}
+
+bool PMCompositeObject::insertChildBefore( PMObject* obj, PMObject* before )
+{
+ if( before )
+ {
+ if( canInsert( obj, before->m_pPrevSibling ) )
+ {
+ if( before->m_pParent == this )
+ {
+ obj->m_pParent = this;
+ obj->m_pPrevSibling = before->m_pPrevSibling;
+ obj->m_pNextSibling = before;
+ if( before->m_pPrevSibling )
+ before->m_pPrevSibling->m_pNextSibling = obj;
+ else
+ m_pFirstChild = obj;
+ before->m_pPrevSibling = obj;
+
+ childAdded( obj );
+ return true;
+ }
+ else
+ {
+ kdError( PMArea ) << "Object before is no child" << "\n";
+ return false;
+ }
+ }
+ }
+ return false;
+}
+
+bool PMCompositeObject::takeChild( PMObject* o )
+{
+ if( ( PMObject* ) this == o->m_pParent )
+ {
+ // deselect the object and all child objects of o
+ if( o->isSelected( ) )
+ o->setSelected( false );
+ else if( o->selectedChildren( ) > 0 )
+ o->deselectChildren( );
+
+ // remove it, but do NOT delete it.
+ if( o->m_pPrevSibling )
+ o->m_pPrevSibling->m_pNextSibling = o->m_pNextSibling;
+ else
+ m_pFirstChild = o->m_pNextSibling;
+ if( o->m_pNextSibling )
+ o->m_pNextSibling->m_pPrevSibling = o->m_pPrevSibling;
+ else
+ m_pLastChild = o->m_pPrevSibling;
+
+ o->m_pParent = 0;
+ o->m_pPrevSibling = 0;
+ o->m_pNextSibling = 0;
+
+ childRemoved( o );
+ return true;
+ }
+ kdError( PMArea ) << "o is no child" << "\n";
+ return false;
+}
+
+bool PMCompositeObject::takeChild( uint i )
+{
+ PMObject* tmp = childAt( i );
+ if( tmp )
+ return takeChild( tmp );
+ kdError( PMArea ) << "Index too big";
+ return false;
+}
+
+void PMCompositeObject::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ PMObject* tmp;
+
+ for( tmp = m_pFirstChild; tmp; tmp = tmp->m_pNextSibling )
+ e.appendChild( tmp->serialize( doc ) );
+}
+
+int PMCompositeObject::countChildren( ) const
+{
+ int num = 0;
+ PMObject* tmp;
+
+ for( tmp = m_pFirstChild; tmp; tmp = tmp->m_pNextSibling )
+ num++;
+ return num;
+}
+
+void PMCompositeObject::adjustSelectedChildren( int num )
+{
+ m_selectedChildren += num;
+ if( m_selectedChildren < 0 )
+ {
+ kdError( PMArea ) << "num too big in PMCompositeObject::adjustSelectedChildren( )\n";
+ m_selectedChildren = 0;
+ }
+ if( m_pParent )
+ m_pParent->adjustSelectedChildren( num );
+}
+
+void PMCompositeObject::deselectChildren( )
+{
+ PMObject* tmp;
+ if( m_selectedChildren > 0 )
+ {
+ tmp = m_pFirstChild;
+ while( tmp && ( m_selectedChildren > 0 ) )
+ {
+ if( tmp->isSelected( ) )
+ tmp->setSelected( false );
+ else if( tmp->selectedChildren( ) > 0 )
+ tmp->deselectChildren( );
+
+ tmp = tmp->m_pNextSibling;
+ }
+ }
+}
+
+
+PMViewStructure* PMCompositeObject::viewStructure( )
+{
+ if( m_pViewStructure )
+ {
+ if( m_pViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ // the default view structure or the parameters (detail level)
+ // have changed
+ m_bViewStructureChanged = true;
+ delete m_pViewStructure;
+ m_pViewStructure = 0;
+ }
+ }
+
+ if( m_bViewStructureChanged )
+ {
+ PMViewStructure* dvs = defaultViewStructure( );
+ if( dvs )
+ if( dvs->parameterKey( ) == -1 ) // newly created view structure
+ dvs->setParameterKey( viewStructureParameterKey( ) );
+
+ if( isDefault( ) )
+ {
+ if( dvs )
+ {
+ if( m_pViewStructure )
+ {
+ if( *m_pViewStructure != *dvs )
+ {
+ delete m_pViewStructure;
+ m_pViewStructure = new PMViewStructure( dvs );
+ }
+ }
+ else
+ m_pViewStructure = new PMViewStructure( dvs );
+ }
+
+ if( !m_pViewStructure )
+ kdError( PMArea ) << "isDefault( ) returned true, but no default view structure is provided\n";
+ }
+ else
+ {
+ if( dvs )
+ {
+ if( m_pViewStructure && ( *m_pViewStructure == *dvs ) )
+ {
+ delete m_pViewStructure;
+ m_pViewStructure = 0;
+ }
+ }
+ createViewStructure( );
+ if( m_pViewStructure )
+ m_pViewStructure->setParameterKey( viewStructureParameterKey( ) );
+ }
+ m_bViewStructureChanged = false;
+ }
+ return m_pViewStructure;
+}
+
+void PMCompositeObject::setViewStructureChanged( )
+{
+ m_bViewStructureChanged = true;
+ if( m_pMemento )
+ m_pMemento->setViewStructureChanged( );
+}
+
diff --git a/kpovmodeler/pmcompositeobject.h b/kpovmodeler/pmcompositeobject.h
new file mode 100644
index 00000000..c2e2da58
--- /dev/null
+++ b/kpovmodeler/pmcompositeobject.h
@@ -0,0 +1,198 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCOMPOBJECT_H
+#define PMCOMPOBJECT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+/**
+ * Base class for all povray objects that can have child objects.
+ *
+ * Used pattern: Composite
+ */
+class PMCompositeObject : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates an empty PMCompositeObject
+ */
+ PMCompositeObject( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMCompositeObject( const PMCompositeObject& o );
+ /**
+ * Deletes the object and all children.
+ */
+ virtual ~PMCompositeObject( );
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /**
+ * Returns a pointer to the first child.
+ */
+ virtual PMObject* firstChild( ) const { return m_pFirstChild; }
+ /**
+ * Returns a pointer to the last child.
+ */
+ virtual PMObject* lastChild( ) const { return m_pLastChild; }
+ /**
+ * Returns a pointer to the child object at position index,
+ * or null if the index is out of range.
+ */
+ virtual PMObject* childAt( uint index ) const;
+
+ /**
+ * Returns true if the object contains the child object o
+ */
+ virtual bool containsChild( PMObject* o ) const
+ { return ( ( PMObject* )this == o->parent( ) ); }
+ /**
+ * Returns the index of the object or -1 if not found
+ */
+ virtual int findChild( PMObject* o );
+
+ /**
+ * Inserts the object as child at index i.
+ * If i is -1, the object is appended.
+ * Returns true if successful.
+ */
+ virtual bool insertChild( PMObject* o, int i );
+ /**
+ * Inserts the object as child after the child object after
+ */
+ virtual bool insertChildAfter( PMObject* object, PMObject* after );
+ /**
+ * Inserts the object as child before the child object before
+ */
+ virtual bool insertChildBefore( PMObject* object, PMObject* before );
+ /**
+ * Appends the object as child. Returns true if successful.
+ */
+ virtual bool appendChild( PMObject* );
+ /**
+ * Returns the number of children.
+ */
+ virtual int countChildren( ) const;
+ /**
+ * Removes a child object. Does not delete it!
+ * Returns true if successful.*/
+ virtual bool takeChild( PMObject* o );
+ /**
+ * Removes a child object at index i. Does not delete it!
+ */
+ virtual bool takeChild( uint i );
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+
+ /**
+ * Returns the number of selected child items. All selected items in
+ * any depth are counted
+ */
+ virtual int selectedChildren( ) const { return m_selectedChildren; }
+ /**
+ * Deselects recursively all child objects
+ */
+ virtual void deselectChildren( );
+
+ /**
+ * Returns the view structure of the object.
+ *
+ * If the view structure has changed since the last call, the
+ * structure is created or updated, or the default view structure
+ * is used.
+ *
+ * If the default view structure can't be used, this function calls
+ * createViewStructure, which has to create a non default view structure.
+ */
+ virtual PMViewStructure* viewStructure( );
+protected:
+ /**
+ * Adds num to the number of selected objects in this object and all
+ * parent objects. num can be negative.
+ */
+ virtual void adjustSelectedChildren( int num );
+
+ /**
+ * Returns the default view structure for the object. This view
+ * structure can be shared between all objects of this type.
+ *
+ * Only the data can be shared, NOT the pointer!!!
+ *
+ * The default view structure has to be created when this function
+ * is called first.
+ */
+ virtual PMViewStructure* defaultViewStructure( ) const { return 0; }
+ /**
+ * Returns a key that represents the view structure parameter.
+ *
+ * Each time a view structure parameter is changed (=detail level),
+ * this key has to be incremented.
+ */
+ virtual int viewStructureParameterKey( ) const { return 0; }
+
+ /**
+ * Returns true if the objects attributes are default and the default
+ * view structure can be used
+ */
+ virtual bool isDefault( ) { return false; }
+ /**
+ * The object has to create or update a non default view structure
+ */
+ virtual void createViewStructure( ) { };
+ /**
+ * Calls setViewStructureChanged( ) for the memento (if one has been created)
+ * and marks the current view structure as outdated.
+ */
+ void setViewStructureChanged( );
+ /**
+ * The view structure.
+ */
+ PMViewStructure* m_pViewStructure;
+private:
+ /**
+ * Pointer to the first child
+ */
+ PMObject* m_pFirstChild;
+ /**
+ * Pointer to the last child
+ */
+ PMObject* m_pLastChild;
+ /**
+ * number of selected child items.
+ */
+ int m_selectedChildren;
+ /**
+ * The modify flag for the view structure
+ */
+ bool m_bViewStructureChanged;
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmcone.cpp b/kpovmodeler/pmcone.cpp
new file mode 100644
index 00000000..2772eda5
--- /dev/null
+++ b/kpovmodeler/pmcone.cpp
@@ -0,0 +1,451 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcone.h"
+
+#include "pmxmlhelper.h"
+#include "pmboxedit.h"
+#include "pmmemento.h"
+#include "pm3dcontrolpoint.h"
+#include "pmdefaults.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmconeedit.h"
+
+#include <klocale.h>
+
+
+const double defaultConeRadius1 = 0.0;
+const double defaultConeRadius2 = 0.5;
+const double defaultHalfConeSize = 0.5;
+const PMVector defaultEnd1 = PMVector ( 0, defaultHalfConeSize, 0 );
+const PMVector defaultEnd2 = PMVector ( 0, -defaultHalfConeSize, 0 );
+const bool defaultOpen = false;
+
+/** default cone structure */
+PMViewStructure* PMCone::s_pDefaultViewStructure = 0;
+int PMCone::s_numSteps = c_defaultConeSteps;
+int PMCone::s_parameterKey = 0;
+
+PMDefinePropertyClass( PMCone, PMConeProperty );
+
+PMMetaObject* PMCone::s_pMetaObject = 0;
+PMObject* createNewCone( PMPart* part )
+{
+ return new PMCone( part );
+}
+
+PMCone::PMCone( PMPart* part )
+ :Base( part )
+{
+ m_end1 = defaultEnd1;
+ m_end2 = defaultEnd2;
+ m_radius1 = defaultConeRadius1;
+ m_radius2 = defaultConeRadius2;
+ m_open = defaultOpen;
+}
+
+PMCone::PMCone( const PMCone& c )
+ : Base( c )
+{
+ m_end1 = c.m_end1;
+ m_end2 = c.m_end2;
+ m_radius1 = c.m_radius1;
+ m_radius2 = c.m_radius2;
+ m_open = c.m_open;
+}
+
+PMCone::~PMCone( )
+{
+}
+
+QString PMCone::description( ) const
+{
+ return i18n( "cone" );
+}
+
+void PMCone::serialize( QDomElement & e, QDomDocument & doc ) const
+{
+ e.setAttribute( "end_a", m_end1.serializeXML( ) );
+ e.setAttribute( "end_b", m_end2.serializeXML( ) );
+ e.setAttribute( "radius_a", m_radius1 );
+ e.setAttribute( "radius_b", m_radius2 );
+ e.setAttribute( "open", m_open );
+ Base::serialize( e, doc );
+}
+
+void PMCone::readAttributes( const PMXMLHelper & h )
+{
+ m_end1 = h.vectorAttribute( "end_a", defaultEnd1 );
+ m_end2 = h.vectorAttribute( "end_b", defaultEnd2 );
+ m_radius1 = h.doubleAttribute( "radius_a", defaultConeRadius1 );
+ m_radius2 = h.doubleAttribute( "radius_b", defaultConeRadius2 );
+ m_open = h.boolAttribute( "open", defaultOpen );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMCone::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Cone", Base::metaObject( ),
+ createNewCone );
+ s_pMetaObject->addProperty(
+ new PMConeProperty( "end1", &PMCone::setEnd1, &PMCone::end1 ) );
+ s_pMetaObject->addProperty(
+ new PMConeProperty( "end2", &PMCone::setEnd2, &PMCone::end2 ) );
+ s_pMetaObject->addProperty(
+ new PMConeProperty( "radius1", &PMCone::setRadius1, &PMCone::radius1 ) );
+ s_pMetaObject->addProperty(
+ new PMConeProperty( "radius2", &PMCone::setRadius2, &PMCone::radius2 ) );
+ s_pMetaObject->addProperty(
+ new PMConeProperty( "open", &PMCone::setOpen, &PMCone::open ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMCone::setEnd1( const PMVector & p )
+{
+ if( p != m_end1 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnd1ID, m_end1 );
+ m_end1 = p;
+ m_end1.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCone::setEnd2( const PMVector & p )
+{
+ if( p != m_end2 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnd2ID, m_end2 );
+ m_end2 = p;
+ m_end2.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCone::setRadius1( double radius )
+{
+ if( m_radius1 != radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadius1ID, m_radius1 );
+ m_radius1 = radius;
+ setViewStructureChanged( );
+ }
+}
+
+void PMCone::setRadius2( double radius )
+{
+ if( m_radius2 != radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadius2ID, m_radius2 );
+ m_radius2 = radius;
+ setViewStructureChanged( );
+ }
+}
+
+void PMCone::setOpen( bool op )
+{
+ if( op != m_open )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOpenID, m_open );
+ m_open = op;
+ }
+}
+
+PMDialogEditBase* PMCone::editWidget( QWidget * parent ) const
+{
+ return new PMConeEdit( parent );
+}
+
+void PMCone::restoreMemento( PMMemento * s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMEnd1ID:
+ setEnd1( data->vectorData( ) );
+ break;
+ case PMEnd2ID:
+ setEnd2( data->vectorData( ) );
+ break;
+ case PMRadius1ID:
+ setRadius1( data->doubleData( ) );
+ break;
+ case PMRadius2ID:
+ setRadius2( data->doubleData( ) );
+ break;
+ case PMOpenID:
+ setOpen( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMCone::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento (s);
+}
+
+bool PMCone::isDefault( )
+{
+ if( ( m_end1 == defaultEnd1 ) && ( m_radius1 == defaultConeRadius1 )
+ && ( m_end2 == defaultEnd2 ) && ( m_radius2 == defaultConeRadius2 ) && ( m_open == defaultOpen )
+ && globalDetail( ) )
+ return true;
+ return false;
+}
+
+void PMCone::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure(defaultViewStructure ( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ int steps = (int)( ( (float)s_numSteps / 2 ) * ( displayDetail( ) + 1 ) );
+ unsigned ptsSize = steps * 2;
+ unsigned lineSize = steps * 3;
+
+ if( ptsSize != m_pViewStructure->points( ).size( ) )
+ m_pViewStructure->points( ).resize( ptsSize );
+
+ createPoints( m_pViewStructure->points( ), m_end1, m_end2, m_radius1, m_radius2, steps );
+
+ if( lineSize != m_pViewStructure->lines( ).size( ) )
+ {
+ m_pViewStructure->lines( ).detach( );
+ m_pViewStructure->lines( ).resize( lineSize );
+ createLines( m_pViewStructure->lines( ), steps );
+ }
+}
+
+PMViewStructure* PMCone::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ int steps = (int)( ( (float)s_numSteps / 2 ) * ( globalDetailLevel( ) + 1 ) );
+ s_pDefaultViewStructure = new PMViewStructure( steps * 2, steps * 3 );
+
+ createPoints( s_pDefaultViewStructure->points( ), defaultEnd1,
+ defaultEnd2,defaultConeRadius1,defaultConeRadius2, steps );
+
+ createLines( s_pDefaultViewStructure->lines( ), steps );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMCone::createLines( PMLineArray& lines, int steps )
+{
+ int i;
+ for( i = 0; i < ( steps - 1 ); i++ )
+ {
+ lines[i] = PMLine( i, i + 1 );
+ lines[i + steps] = PMLine( i + steps, i + steps+ 1 );
+ }
+ lines[steps - 1] = PMLine( steps - 1, 0 );
+ lines[steps * 2 - 1] = PMLine( steps * 2 - 1, steps );
+
+ for( i = 0; i < steps; i++ )
+ {
+ lines[i + 2 * steps] = PMLine( i, i + steps );
+ }
+}
+
+void PMCone::createPoints( PMPointArray& points, const PMVector& end1,
+ const PMVector& end2, double radius1, double radius2, int steps )
+{
+
+ double angle = ( 2.0 * M_PI ) / (double) steps;
+
+ PMVector pointAt = end2 - end1;
+ double pl = pointAt.abs( );
+ if( approxZero( pl ) )
+ pointAt = PMVector( 0.0, 1.0, 0.0 );
+ else
+ pointAt /= pl;
+
+ PMMatrix rotation = PMMatrix::rotation( pointAt, angle );
+ PMVector endPoint1 = pointAt.orthogonal( );
+ endPoint1 *= radius1;
+ PMVector endPoint2 = pointAt.orthogonal( );
+ endPoint2 *= radius2;
+
+ int i;
+ for( i = 0; i < steps; i++ )
+ {
+ points[i] = PMPoint( endPoint1 + end1 );
+ points[i + steps] = PMPoint( endPoint2 + end2 );
+ endPoint1 = rotation * endPoint1;
+ endPoint2 = rotation * endPoint2;
+ }
+}
+
+void PMCone::controlPoints( PMControlPointList & list )
+{
+ PMVector center, angle1, angle2;
+ center = m_end1 - m_end2;
+ double pl = center.abs( );
+ if( approxZero( pl ) )
+ center = PMVector( 0.0, 1.0, 0.0 );
+ else
+ center /= pl;
+
+ angle1 = center.orthogonal( );
+ angle2 = PMVector::cross( center, angle1 );
+
+ PM3DControlPoint* pb1 = new PM3DControlPoint( m_end1, PMEnd1ID, i18n( "End 1" ) );
+ list.append( pb1 );
+ PM3DControlPoint* pb2 = new PM3DControlPoint( m_end2, PMEnd2ID, i18n( "End 2" ) );
+ list.append( pb2 );
+
+ list.append( new PMDistanceControlPoint( pb1, angle1, m_radius1, PMRadius1ID, i18n( "Radius 1 (1)" ) ) );
+ list.append( new PMDistanceControlPoint( pb1, angle2, m_radius1, PMRadius1ID, i18n( "Radius 1 (2)" ) ) );
+ list.append( new PMDistanceControlPoint( pb2, angle1, m_radius2, PMRadius2ID, i18n( "Radius 2 (1)" ) ) );
+ list.append( new PMDistanceControlPoint( pb2, angle2, m_radius2, PMRadius2ID, i18n( "Radius 2 (2)" ) ) );
+}
+
+void PMCone::controlPointsChanged( PMControlPointList & list )
+{
+ PMControlPoint* p;
+ bool pointChanged = false;
+ bool radiusChanged = false;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMEnd1ID:
+ setEnd1( ( ( PM3DControlPoint *) p)->point( ) );
+ pointChanged = true;
+ break;
+ case PMEnd2ID:
+ setEnd2( ( ( PM3DControlPoint *) p)->point( ) );
+ pointChanged = true;
+ break;
+ case PMRadius1ID:
+ setRadius1( ( ( PMDistanceControlPoint *) p)->distance( ) );
+ radiusChanged = true;
+ break;
+ case PMRadius2ID:
+ setRadius2( ( ( PMDistanceControlPoint *) p)->distance( ) );
+ radiusChanged = true;
+ break;
+ default:
+ kdError (PMArea) << "Wrong ID in PMCone::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+
+ if( pointChanged )
+ {
+ PMVector center, angle1, angle2;
+ bool firstPoint1 = true;
+ bool firstPoint2 = true;
+
+ center = m_end1 - m_end2;
+ double pl = center.abs( );
+ if( approxZero( pl ) )
+ center = PMVector( 0.0, 1.0, 0.0 );
+ else
+ center /= pl;
+
+ angle1 = center.orthogonal( );
+ angle2 = PMVector::cross( center, angle1 );
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->id( ) == PMRadius1ID )
+ {
+ if( firstPoint1 )
+ {
+ ( ( PMDistanceControlPoint *) p)->setDirection( angle1 );
+ firstPoint1 = false;
+ }
+ else
+ ( ( PMDistanceControlPoint *) p)->setDirection( angle2 );
+ }else if( p->id( ) == PMRadius2ID )
+ {
+ if( firstPoint2 )
+ {
+ ( ( PMDistanceControlPoint *) p)->setDirection( angle1 );
+ firstPoint2 = false;
+ }
+ else
+ ( ( PMDistanceControlPoint *) p)->setDirection( angle2 );
+ }
+ }
+ }
+
+ if( radiusChanged )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMRadius1ID )
+ ( ( PMDistanceControlPoint *) p)->setDistance( m_radius1 );
+ else if( p->id( ) == PMRadius2ID )
+ ( ( PMDistanceControlPoint *) p)->setDistance( m_radius2 );
+}
+
+void PMCone::setSteps( int s )
+{
+ if( s >= 4 )
+ {
+ s_numSteps = s;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMCone::setSteps: S must be greater than 4\n";
+ s_parameterKey++;
+}
+
+void PMCone::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmcone.h b/kpovmodeler/pmcone.h
new file mode 100644
index 00000000..445846f3
--- /dev/null
+++ b/kpovmodeler/pmcone.h
@@ -0,0 +1,188 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCONE_H
+#define PMCONE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include "pmviewstructure.h"
+
+class PMViewStructure;
+
+/**
+ * Class for Povray Cone
+ *
+ */
+
+class PMCone : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Create a Cone
+ */
+ PMCone( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMCone( const PMCone& c );
+
+ /**
+ * delete the Cone
+ */
+ virtual ~PMCone( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMCone( *this ); }
+
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMConeEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmcone" ); }
+
+ /**
+ * Return the end_1
+ */
+ PMVector end1( ) const { return m_end1; }
+ /**
+ * Sets end_1
+ */
+ void setEnd1( const PMVector & p );
+ /**
+ * Return the end_2
+ */
+ PMVector end2( ) const { return m_end2; }
+ /**
+ * Sets end_2
+ */
+ void setEnd2( const PMVector & p );
+ /**
+ * return the first radius of the cone
+ */
+ double radius1( ) const { return m_radius1; }
+ /**
+ * Sets the first radius of the cone
+ */
+ void setRadius1( double radius );
+ /**
+ * return the second radius of the cone
+ */
+ double radius2( ) const { return m_radius2; }
+ /**
+ * Sets the second radius of the cone
+ */
+ void setRadius2( double radius );
+ /**
+ * Return open = 1 or close = 0
+ */
+ bool open( ) const { return m_open; }
+ /**
+ * Sets open cylinder
+ */
+ void setOpen( bool op );
+
+ /**
+ * Returns the number of lines for rendering
+ */
+ static int steps( ) { return s_numSteps; }
+ /**
+ * Sets the number of lines for rendering
+ */
+ static void setSteps( int s );
+
+ /** */
+ virtual void restoreMemento( PMMemento * s );
+ /** */
+ virtual void controlPoints( PMControlPointList & list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList & list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey(); }
+
+private:
+ /**
+ * Creates the lines for the view structure
+ */
+ static void createLines( PMLineArray& lines, int steps );
+ /**
+ * Creates the points for the view structure
+ */
+ static void createPoints( PMPointArray& points, const PMVector& end1,
+ const PMVector& end2, double radius1, double radius2, int steps );
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMConeMementoID { PMEnd1ID, PMEnd2ID, PMRadius1ID, PMRadius2ID, PMOpenID };
+ /**
+ * ends of cone
+ */
+ PMVector m_end1, m_end2;
+ /**
+ * radius of cone
+ */
+ double m_radius1,m_radius2;
+ /**
+ * open
+ */
+ bool m_open;
+ /**
+ * The default view structure. It can be shared between cones
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_numSteps;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmconeedit.cpp b/kpovmodeler/pmconeedit.cpp
new file mode 100644
index 00000000..2dbcfc7c
--- /dev/null
+++ b/kpovmodeler/pmconeedit.cpp
@@ -0,0 +1,119 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmconeedit.h"
+#include "pmcone.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <qcheckbox.h>
+
+PMConeEdit::PMConeEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMConeEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+ QGridLayout* gl;
+
+ m_pEnd1 = new PMVectorEdit( "x", "y", "z", this );
+ m_pEnd2 = new PMVectorEdit( "x", "y", "z", this );
+ m_pRadius1 = new PMFloatEdit( this );
+ m_pRadius2 = new PMFloatEdit( this );
+ m_pOpen = new QCheckBox( i18n( "type of the object", "Open" ), this );
+
+ gl = new QGridLayout( topLayout( ), 2, 2 );
+ gl->addWidget( new QLabel( i18n( "End 1:" ), this ), 0, 0 );
+ gl->addWidget( m_pEnd1, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "End 2:" ), this ), 1, 0 );
+ gl->addWidget( m_pEnd2, 1, 1 );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( layout, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Radius 1:" ), this ), 0, 0 );
+ gl->addWidget( m_pRadius1, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Radius 2:" ), this ), 1, 0 );
+ gl->addWidget( m_pRadius2, 1, 1 );
+ layout->addStretch( 1 );
+
+ topLayout( )->addWidget( m_pOpen );
+
+ connect( m_pEnd1, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnd2, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadius1, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadius2, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOpen, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMConeEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Cone" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMCone* ) o;
+
+ m_pEnd1->setVector( m_pDisplayedObject->end1( ) );
+ m_pEnd2->setVector( m_pDisplayedObject->end2( ) );
+ m_pRadius1->setValue( m_pDisplayedObject->radius1( ) );
+ m_pRadius2->setValue( m_pDisplayedObject->radius2( ) );
+ m_pOpen->setChecked( m_pDisplayedObject->open( ) );
+
+ m_pEnd1->setReadOnly( readOnly );
+ m_pEnd2->setReadOnly( readOnly );
+ m_pRadius1->setReadOnly( readOnly );
+ m_pRadius2->setReadOnly( readOnly );
+ m_pOpen->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMConeEdit: Can't display object\n";
+}
+
+void PMConeEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setEnd1( m_pEnd1->vector( ) );
+ m_pDisplayedObject->setEnd2( m_pEnd2->vector( ) );
+ m_pDisplayedObject->setRadius1( m_pRadius1->value( ) );
+ m_pDisplayedObject->setRadius2( m_pRadius2->value( ) );
+ m_pDisplayedObject->setOpen( m_pOpen->isChecked( ) );
+ }
+}
+
+bool PMConeEdit::isDataValid( )
+{
+ if( m_pEnd1->isDataValid( ) )
+ if( m_pEnd2->isDataValid( ) )
+ if( m_pRadius1->isDataValid( ) )
+ if( m_pRadius2->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+#include "pmconeedit.moc"
diff --git a/kpovmodeler/pmconeedit.h b/kpovmodeler/pmconeedit.h
new file mode 100644
index 00000000..f39f95c6
--- /dev/null
+++ b/kpovmodeler/pmconeedit.h
@@ -0,0 +1,64 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorinaez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCONEEDIT_H
+#define PMCONEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class QCheckBox;
+
+class PMVectorEdit;
+class PMFloatEdit;
+class PMCone;
+
+class PMConeEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMConeEdit with parent and name
+ */
+ PMConeEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMCone* m_pDisplayedObject;
+ PMVectorEdit* m_pEnd1;
+ PMVectorEdit* m_pEnd2;
+ PMFloatEdit* m_pRadius1;
+ PMFloatEdit* m_pRadius2;
+ QCheckBox* m_pOpen;
+};
+#endif
diff --git a/kpovmodeler/pmcontrolpoint.cpp b/kpovmodeler/pmcontrolpoint.cpp
new file mode 100644
index 00000000..8617ae27
--- /dev/null
+++ b/kpovmodeler/pmcontrolpoint.cpp
@@ -0,0 +1,99 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmcontrolpoint.h"
+#include "pmdefaults.h"
+#include "pmdebug.h"
+
+#include <kconfig.h>
+
+double PMControlPoint::s_moveGrid = c_defaultMoveGrid;
+double PMControlPoint::s_scaleGrid = c_defaultScaleGrid;
+double PMControlPoint::s_rotateGrid = c_defaultRotateGrid;
+
+PMControlPoint::PMControlPoint( int id, const QString& description )
+{
+ m_id = id;
+ m_bChanged = false;
+ m_description = description;
+ m_bSelected = false;
+}
+
+PMControlPoint::~PMControlPoint( )
+{
+}
+
+void PMControlPoint::startChange( const PMVector& s, const PMVector& n )
+{
+ m_startPoint = s;
+ m_normalVector = n;
+ graphicalChangeStarted( );
+}
+
+void PMControlPoint::change( const PMVector& endPoint )
+{
+ m_bChanged = true;
+ graphicalChange( m_startPoint, m_normalVector, endPoint );
+}
+
+bool PMControlPoint::changed( )
+{
+ bool h = m_bChanged;
+ m_bChanged = false;
+
+ return h;
+}
+
+void PMControlPoint::setMoveGrid( double d )
+{
+ if( d > 0 )
+ s_moveGrid = d;
+ else
+ kdError( PMArea ) << "Grid has to be greater than 0\n";
+}
+
+void PMControlPoint::setScaleGrid( double d )
+{
+ if( d > 0 )
+ s_scaleGrid = d;
+ else
+ kdError( PMArea ) << "Grid has to be greater than 0\n";
+}
+
+void PMControlPoint::setRotateGrid( double d )
+{
+ if( d > 0 )
+ s_rotateGrid = d;
+ else
+ kdError( PMArea ) << "Grid has to be greater than 0\n";
+}
+
+void PMControlPoint::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Grid" );
+ cfg->writeEntry( "MoveGrid", s_moveGrid );
+ cfg->writeEntry( "RotateGrid", s_rotateGrid );
+ cfg->writeEntry( "ScaleGrid", s_scaleGrid );
+}
+
+void PMControlPoint::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Grid" );
+ s_moveGrid = cfg->readDoubleNumEntry( "MoveGrid", c_defaultMoveGrid );
+ s_rotateGrid = cfg->readDoubleNumEntry( "RotateGrid", c_defaultRotateGrid );
+ s_scaleGrid = cfg->readDoubleNumEntry( "ScaleGrid", c_defaultScaleGrid );
+}
diff --git a/kpovmodeler/pmcontrolpoint.h b/kpovmodeler/pmcontrolpoint.h
new file mode 100644
index 00000000..8d3e9e66
--- /dev/null
+++ b/kpovmodeler/pmcontrolpoint.h
@@ -0,0 +1,190 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCONTROLPOINT_H
+#define PMCONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmvector.h"
+#include <qptrlist.h>
+#include <qstring.h>
+
+class KConfig;
+
+/**
+ * Interface between the graphical views and the PMObject.
+ *
+ * PMControlPoint is the interface between graphical view and PMObjects that
+ * can be changed graphically with the mouse. A @ref PMObject has a
+ * PMControlPoint for each changeable attribute.
+ *
+ * There is one subclass for each change behavior like 3dpoint, normal vector,
+ * radius, rotation ...
+ *
+ * Each control point has an id to be indentified by the PMObject. The id has
+ * to be unique within a PMObject.
+ */
+
+class PMControlPoint
+{
+public:
+ /**
+ * Creates a PMControlPoint with an id and a description.
+ */
+ PMControlPoint( int id, const QString& description );
+ /**
+ * Deletes the PMControlPoint
+ */
+ virtual ~PMControlPoint( );
+
+ /**
+ * Starts a graphical change at 3d cursor position startPoint. viewNormal
+ * is the normal vector of the view
+ */
+ void startChange( const PMVector& startPoint, const PMVector& viewNormal );
+ /**
+ * Graphical change with 3d end cursor position endPoint
+ */
+ void change( const PMVector& endPoint );
+ /**
+ * Snaps the control point to the grid
+ */
+ virtual void snapToGrid( ) = 0;
+
+ /**
+ * 3d coordinates of the control point for rendering*/
+ virtual PMVector position( ) const { return PMVector( ); }
+ /**
+ * Returns true if the point should be displayed (rendered)
+ */
+ virtual bool display( ) const { return true; }
+ /**
+ * Returns the id of the control point
+ */
+ int id( ) const { return m_id; }
+ /**
+ * Type of the control point
+ *
+ * CPPoint: The control point is displayed as point, the mouse cursor
+ * has to be over the control point to be active (e.g. 3DControlPoint)
+ *
+ * CPCross: The control point is displayed as cross, the control point
+ * can be changed with the mouse in the whole view (e.g. Translation)
+ */
+ enum PMCPDisplayType { CPPoint = 0, CPCross = 1 };
+ /**
+ * Returns the type of the control point (see @ref PMCPDisplayType)
+ */
+ virtual PMCPDisplayType displayType( ) const { return CPPoint; };
+ /**
+ * Returns the description
+ */
+ QString description( ) const { return m_description; }
+ /**
+ * Selects/deselects the control point
+ */
+ void setSelected( bool yes ) { m_bSelected = yes; }
+ /**
+ * Returns true if the control point is selected
+ */
+ bool selected( ) const { return m_bSelected; }
+
+ /**
+ * Returns true, if the control point was changed and sets the
+ * changed flag to false.
+ */
+ bool changed( );
+
+ /**
+ * Returns true if an extra line should be displayed in addition to
+ * the view structure
+ */
+ virtual bool hasExtraLine( ) const { return false; }
+ /**
+ * Returns the start point of the extra line
+ */
+ virtual PMVector extraLineStart( ) const { return PMVector( 0, 0, 0 ); }
+ /**
+ * Returns the end point of the extra line
+ */
+ virtual PMVector extraLineEnd( ) const { return PMVector( 0, 0, 0 ); }
+
+ /**
+ * Returns the grid distance for 3d points, vectors and movements
+ */
+ static double moveGrid( ) { return s_moveGrid; }
+ /**
+ * Sets the grid distance
+ */
+ static void setMoveGrid( double d );
+ /**
+ * Returns the grid distance rotations
+ */
+ static double rotateGrid( ) { return s_rotateGrid; }
+ /**
+ * Sets the grid distance
+ */
+ static void setRotateGrid( double d );
+ /**
+ * Returns the grid distance for scales
+ */
+ static double scaleGrid( ) { return s_scaleGrid; }
+ /**
+ * Sets the grid distance
+ */
+ static void setScaleGrid( double d );
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+
+protected:
+ /**
+ * Called when a graphical change was started
+ */
+ virtual void graphicalChangeStarted( ) = 0;
+ /**
+ * Called when the control point was changed
+ */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint ) = 0;
+ /**
+ * Sets the changed flag
+ */
+ void setChanged( ) { m_bChanged = true; }
+private:
+ int m_id;
+ PMVector m_startPoint;
+ PMVector m_normalVector;
+ bool m_bChanged;
+ bool m_bSelected;
+ QString m_description;
+
+ static double s_moveGrid;
+ static double s_rotateGrid;
+ static double s_scaleGrid;
+};
+
+typedef QPtrList<PMControlPoint> PMControlPointList;
+typedef QPtrListIterator<PMControlPoint> PMControlPointListIterator;
+
+#endif
diff --git a/kpovmodeler/pmcsg.cpp b/kpovmodeler/pmcsg.cpp
new file mode 100644
index 00000000..3af76740
--- /dev/null
+++ b/kpovmodeler/pmcsg.cpp
@@ -0,0 +1,200 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcsg.h"
+
+#include <klocale.h>
+#include "pmxmlhelper.h"
+#include "pmcsgedit.h"
+#include "pmmemento.h"
+#include "pmenumproperty.h"
+
+PMDefineEnumPropertyClass( PMCSG, PMCSG::PMCSGType, PMCSGTypeProperty );
+
+PMMetaObject* PMCSG::s_pMetaObject = 0;
+PMObject* createNewCSG( PMPart* part )
+{
+ return new PMCSG( part );
+}
+
+PMCSG::PMCSG( PMPart* part )
+ : Base( part )
+{
+ m_type = CSGUnion;
+}
+
+PMCSG::PMCSG( PMPart* part, const PMCSGType t )
+ : Base( part )
+{
+ m_type = t;
+}
+
+PMCSG::PMCSG( const PMCSG& c )
+ : Base( c )
+{
+ m_type = c.m_type;
+}
+
+PMCSG::~PMCSG( )
+{
+}
+
+QString PMCSG::description( ) const
+{
+ switch( m_type )
+ {
+ case CSGUnion:
+ return i18n( "union" );
+ break;
+ case CSGIntersection:
+ return i18n( "intersection" );
+ break;
+ case CSGDifference:
+ return i18n( "difference" );
+ break;
+ case CSGMerge:
+ return i18n( "merge" );
+ break;
+ }
+ return QString( "" );
+}
+
+QString PMCSG::pixmap( ) const
+{
+ switch( m_type )
+ {
+ case CSGUnion:
+ return QString( "pmunion" );
+ break;
+ case CSGIntersection:
+ return QString( "pmintersection" );
+ break;
+ case CSGDifference:
+ return QString( "pmdifference" );
+ break;
+ case CSGMerge:
+ return QString( "pmmerge" );
+ break;
+ }
+ return QString( "" );
+}
+
+void PMCSG::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ switch( m_type )
+ {
+ case CSGUnion:
+ e.setAttribute( "csgtype", "union" );
+ break;
+ case CSGIntersection:
+ e.setAttribute( "csgtype", "intersection" );
+ break;
+ case CSGDifference:
+ e.setAttribute( "csgtype", "difference" );
+ break;
+ case CSGMerge:
+ e.setAttribute( "csgtype", "merge" );
+ break;
+ }
+
+ Base::serialize( e, doc );
+}
+
+void PMCSG::readAttributes( const PMXMLHelper& h )
+{
+ QString str = h.stringAttribute( "csgtype", "union" );
+ if( str == "union" )
+ m_type = CSGUnion;
+ else if( str == "intersection" )
+ m_type = CSGIntersection;
+ else if( str == "difference" )
+ m_type = CSGDifference;
+ else
+ m_type = CSGMerge;
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMCSG::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "CSG", Base::metaObject( ),
+ createNewCSG );
+ PMCSGTypeProperty* p = new PMCSGTypeProperty( "csgType", &PMCSG::setCSGType, &PMCSG::csgType );
+ p->addEnumValue( "union", CSGUnion );
+ p->addEnumValue( "intersection", CSGIntersection );
+ p->addEnumValue( "difference", CSGDifference );
+ p->addEnumValue( "merge", CSGMerge );
+ s_pMetaObject->addProperty( p );
+ }
+ return s_pMetaObject;
+}
+
+void PMCSG::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMCSG::setCSGType( const PMCSGType t )
+{
+ if( t != m_type )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMTypeID, ( int ) m_type );
+ m_pMemento->setDescriptionChanged( );
+ }
+ m_type = t;
+ }
+}
+
+PMDialogEditBase* PMCSG::editWidget( QWidget* parent ) const
+{
+ return new PMCSGEdit( parent );
+}
+
+void PMCSG::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMTypeID:
+ setCSGType( ( PMCSGType ) data->intData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMCSG::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmcsg.h b/kpovmodeler/pmcsg.h
new file mode 100644
index 00000000..e8ce741e
--- /dev/null
+++ b/kpovmodeler/pmcsg.h
@@ -0,0 +1,105 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCSG_H
+#define PMCSG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+
+/**
+ * Class for povray csg objects.
+ */
+
+class PMCSG : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * The type of the csg object
+ */
+ enum PMCSGType { CSGUnion, CSGIntersection, CSGDifference, CSGMerge };
+ /**
+ * Creates an empty PMCSG union
+ */
+ PMCSG( PMPart* part );
+ /**
+ * Creates an empty PMCSG object with type t
+ */
+ PMCSG( PMPart* part, const PMCSGType t );
+ /**
+ * Copy constructor
+ */
+ PMCSG( const PMCSG& c );
+
+ /**
+ * deletes the PMCSG object
+ */
+ virtual ~PMCSG( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMCSG( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMCSGEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const;
+
+ /**
+ * Returns the type of the csg
+ */
+ PMCSGType csgType( ) const { return m_type; }
+ /**
+ * Sets the type of the csg
+ */
+ void setCSGType( const PMCSGType t );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMCSGMementoID { PMTypeID };
+ PMCSGType m_type;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmcsgedit.cpp b/kpovmodeler/pmcsgedit.cpp
new file mode 100644
index 00000000..9a6e0a39
--- /dev/null
+++ b/kpovmodeler/pmcsgedit.cpp
@@ -0,0 +1,118 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcsgedit.h"
+#include "pmcsg.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <klocale.h>
+
+PMCSGEdit::PMCSGEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMCSGEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+ m_pTypeCombo = new QComboBox( false, this );
+ m_pTypeCombo->insertItem( i18n( "Union" ) );
+ m_pTypeCombo->insertItem( i18n( "Intersection" ) );
+ m_pTypeCombo->insertItem( i18n( "Difference" ) );
+ m_pTypeCombo->insertItem( i18n( "Merge" ) );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Type:" ), this ) );
+ layout->addWidget( m_pTypeCombo );
+ layout->addStretch( 1 );
+
+ connect( m_pTypeCombo, SIGNAL( activated( int ) ), SLOT( slotTypeSelected( int ) ) );
+}
+
+void PMCSGEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "CSG" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMCSG* ) o;
+
+ switch( m_pDisplayedObject->csgType( ) )
+ {
+ case PMCSG::CSGUnion:
+ m_pTypeCombo->setCurrentItem( 0 );
+ break;
+ case PMCSG::CSGIntersection:
+ m_pTypeCombo->setCurrentItem( 1 );
+ break;
+ case PMCSG::CSGDifference:
+ m_pTypeCombo->setCurrentItem( 2 );
+ break;
+ case PMCSG::CSGMerge:
+ m_pTypeCombo->setCurrentItem( 3 );
+ break;
+ }
+
+ m_pTypeCombo->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMCSGEdit: Can't display object\n";
+}
+
+void PMCSGEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ switch( m_pTypeCombo->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setCSGType( PMCSG::CSGUnion );
+ break;
+ case 1:
+ m_pDisplayedObject->setCSGType( PMCSG::CSGIntersection );
+ break;
+ case 2:
+ m_pDisplayedObject->setCSGType( PMCSG::CSGDifference );
+ break;
+ case 3:
+ m_pDisplayedObject->setCSGType( PMCSG::CSGMerge );
+ break;
+ default:
+ m_pDisplayedObject->setCSGType( PMCSG::CSGUnion );
+ break;
+ }
+ }
+}
+
+bool PMCSGEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+void PMCSGEdit::slotTypeSelected( int )
+{
+ emit dataChanged( );
+}
+#include "pmcsgedit.moc"
diff --git a/kpovmodeler/pmcsgedit.h b/kpovmodeler/pmcsgedit.h
new file mode 100644
index 00000000..8aeaddc6
--- /dev/null
+++ b/kpovmodeler/pmcsgedit.h
@@ -0,0 +1,63 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCSGEDIT_H
+#define PMCSGEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMCSG;
+class QComboBox;
+
+/**
+ * Dialog edit class for @ref PMCSG
+ */
+class PMCSGEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMCSGEdit with parent and name
+ */
+ PMCSGEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+protected slots:
+ void slotTypeSelected( int index );
+private:
+ PMCSG* m_pDisplayedObject;
+ QComboBox* m_pTypeCombo;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmcylinder.cpp b/kpovmodeler/pmcylinder.cpp
new file mode 100644
index 00000000..1a119004
--- /dev/null
+++ b/kpovmodeler/pmcylinder.cpp
@@ -0,0 +1,407 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcylinder.h"
+
+#include "pmxmlhelper.h"
+#include "pmboxedit.h"
+#include "pmmemento.h"
+#include "pm3dcontrolpoint.h"
+#include "pmdefaults.h"
+
+#include <klocale.h>
+
+#include "pmdistancecontrolpoint.h"
+
+#include "pmcylinderedit.h"
+
+const double defaultCylRadius = 0.5;
+const double defaultHalfCylSize = 0.5;
+const PMVector defaultEnd1 = PMVector ( 0, defaultHalfCylSize, 0 );
+const PMVector defaultEnd2 = PMVector ( 0, -defaultHalfCylSize, 0 );
+const bool defaultOpen = false;
+
+/** default cylinder structure */
+PMViewStructure* PMCylinder::s_pDefaultViewStructure = 0;
+int PMCylinder::s_numSteps = c_defaultCylinderSteps;
+int PMCylinder::s_parameterKey = 0;
+
+PMDefinePropertyClass( PMCylinder, PMCylinderProperty );
+
+PMMetaObject* PMCylinder::s_pMetaObject = 0;
+PMObject* createNewCylinder( PMPart* part )
+{
+ return new PMCylinder( part );
+}
+
+
+PMCylinder::PMCylinder( PMPart* part )
+ : Base( part )
+{
+ m_end1 = defaultEnd1;
+ m_end2 = defaultEnd2;
+ m_radius = defaultCylRadius;
+ m_open = defaultOpen;
+}
+
+PMCylinder::PMCylinder( const PMCylinder& c )
+ : Base( c )
+{
+ m_end1 = c.m_end1;
+ m_end2 = c.m_end2;
+ m_radius = c.m_radius;
+ m_open = c.m_open;
+}
+
+PMCylinder::~PMCylinder( )
+{
+}
+
+QString PMCylinder::description( ) const
+{
+ return i18n( "cylinder" );
+}
+
+void PMCylinder::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "end_a", m_end1.serializeXML( ) );
+ e.setAttribute( "end_b", m_end2.serializeXML( ) );
+ e.setAttribute( "radius", m_radius );
+ e.setAttribute( "open", m_open );
+ Base::serialize( e, doc );
+}
+
+void PMCylinder::readAttributes( const PMXMLHelper& h )
+{
+ m_end1 = h.vectorAttribute( "end_a", defaultEnd1 );
+ m_end2 = h.vectorAttribute( "end_b", defaultEnd2 );
+ m_radius = h.doubleAttribute( "radius", defaultCylRadius );
+ m_open = h.boolAttribute( "open", defaultOpen );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMCylinder::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Cylinder", Base::metaObject( ),
+ createNewCylinder );
+ s_pMetaObject->addProperty(
+ new PMCylinderProperty( "end1", &PMCylinder::setEnd1, &PMCylinder::end1 ) );
+ s_pMetaObject->addProperty(
+ new PMCylinderProperty( "end2", &PMCylinder::setEnd2, &PMCylinder::end2 ) );
+ s_pMetaObject->addProperty(
+ new PMCylinderProperty( "radius", &PMCylinder::setRadius, &PMCylinder::radius ) );
+ s_pMetaObject->addProperty(
+ new PMCylinderProperty( "open", &PMCylinder::setOpen, &PMCylinder::open ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMCylinder::setEnd1( const PMVector& p )
+{
+ if( p != m_end1 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnd1ID, m_end1 );
+ m_end1 = p;
+ m_end1.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCylinder::setEnd2( const PMVector& p )
+{
+ if( p != m_end2 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnd2ID, m_end2 );
+ m_end2 = p;
+ m_end2.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMCylinder::setRadius( double radius )
+{
+ if( m_radius != radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusID, m_radius );
+ m_radius = radius;
+ setViewStructureChanged( );
+ }
+}
+
+void PMCylinder::setOpen( bool op )
+{
+ if( op != m_open )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOpenID, m_open );
+ m_open = op;
+ }
+}
+
+PMDialogEditBase* PMCylinder::editWidget( QWidget* parent ) const
+{
+ return new PMCylinderEdit( parent );
+}
+
+void PMCylinder::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMEnd1ID:
+ setEnd1( data->vectorData( ) );
+ break;
+ case PMEnd2ID:
+ setEnd2( data->vectorData( ) );
+ break;
+ case PMRadiusID:
+ setRadius( data->doubleData( ) );
+ break;
+ case PMOpenID:
+ setOpen( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMCylinder::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+bool PMCylinder::isDefault( )
+{
+ if( ( m_end1 == defaultEnd1 ) && ( m_end2 == defaultEnd2 )
+ && ( m_radius == defaultCylRadius ) && ( m_open == defaultOpen )
+ && globalDetail( ) )
+ return true;
+ return false;
+}
+
+void PMCylinder::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure ( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ int steps = (int)( ( (float)s_numSteps / 2 ) * ( displayDetail( ) + 1 ) );
+ unsigned ptsSize = steps * 2;
+ unsigned lineSize = steps * 3;
+
+ if( ptsSize != m_pViewStructure->points( ).size( ) )
+ m_pViewStructure->points( ).resize( ptsSize );
+
+ createPoints( m_pViewStructure->points( ), m_end1, m_end2, m_radius, steps );
+
+ if( ( lineSize ) != m_pViewStructure->lines( ).size( ) )
+ {
+ m_pViewStructure->lines( ).detach( );
+ m_pViewStructure->lines( ).resize( lineSize );
+ createLines( m_pViewStructure->lines( ), steps );
+ }
+}
+
+PMViewStructure* PMCylinder::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ int steps = (int)( ( (float)s_numSteps / 2 ) * ( globalDetailLevel( ) + 1 ) );
+ s_pDefaultViewStructure = new PMViewStructure( steps * 2, steps * 3 );
+
+ createPoints( s_pDefaultViewStructure->points( ), defaultEnd1,
+ defaultEnd2, defaultCylRadius, steps );
+
+ createLines( s_pDefaultViewStructure->lines( ), steps );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMCylinder::createLines( PMLineArray& lines, int steps )
+{
+ int i;
+ for( i = 0; i < ( steps - 1 ); i++ )
+ {
+ lines[i] = PMLine( i, i + 1 );
+ lines[i + steps] = PMLine( i + steps, i + steps + 1 );
+ }
+ lines[steps - 1] = PMLine( steps - 1, 0 );
+ lines[steps * 2 - 1] = PMLine( steps * 2 - 1, steps );
+
+ for( i = 0; i < steps; i++ )
+ {
+ lines[i + 2 * steps] = PMLine( i, i + steps );
+ }
+}
+
+void PMCylinder::createPoints( PMPointArray& points, const PMVector& end1,
+ const PMVector& end2, double radius, int steps )
+{
+ double angle = ( 2.0 * M_PI ) / ( double ) steps;
+
+ PMVector pointAt = end2 - end1;
+ double pl = pointAt.abs( );
+ if( approxZero( pl ) )
+ pointAt = PMVector( 0.0, 0.0, 1.0 );
+ else
+ pointAt /= pl;
+
+ PMMatrix rotation = PMMatrix::rotation( pointAt, angle );
+ PMVector endPoint = pointAt.orthogonal( );
+ endPoint *= radius;
+
+ int i;
+ for( i = 0; i < steps; i++ )
+ {
+ points[i] = PMPoint( endPoint + end1 );
+ points[i + steps] = PMPoint( endPoint + end2 );
+ endPoint = rotation * endPoint;
+ }
+}
+
+void PMCylinder::controlPoints( PMControlPointList & list )
+{
+ PMVector center, angle1, angle2;
+ center = m_end1 - m_end2;
+ double pl = center.abs( );
+ if( approxZero( pl ) )
+ center = PMVector( 0.0, 1.0, 0.0 );
+ else
+ center /= pl;
+
+ angle1 = center.orthogonal( );
+ angle2 = PMVector::cross( center, angle1 );
+
+ PM3DControlPoint* pb = new PM3DControlPoint( m_end1, PMEnd1ID, i18n( "End 1" ) );
+ list.append( pb );
+ list.append( new PM3DControlPoint( m_end2, PMEnd2ID, i18n( "End 2" ) ) );
+ list.append( new PMDistanceControlPoint( pb, angle1, m_radius, PMRadiusID, i18n( "Radius (1)" ) ) );
+ list.append( new PMDistanceControlPoint( pb, angle2, m_radius, PMRadiusID, i18n( "Radius (2)" ) ) );
+}
+
+
+void PMCylinder::controlPointsChanged( PMControlPointList & list )
+{
+ PMControlPoint* p;
+ bool pointChanged = false;
+ bool radiusChanged = false;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMEnd1ID:
+ setEnd1( ( ( PM3DControlPoint *) p)->point( ) );
+ pointChanged = true;
+ break;
+ case PMEnd2ID:
+ setEnd2( ( ( PM3DControlPoint *) p)->point( ) );
+ pointChanged = true;
+ break;
+ case PMRadiusID:
+ setRadius( ( ( PMDistanceControlPoint *) p)->distance( ) );
+ radiusChanged = true;
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMCylinder::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+
+ if( pointChanged )
+ {
+ PMVector center, angle1, angle2;
+ bool firstPoint = true;
+
+ center = m_end1 - m_end2;
+ double pl = center.abs( );
+ if( approxZero( pl ) )
+ center = PMVector( 0.0, 1.0, 0.0 );
+ else
+ center /= pl;
+
+ angle1 = center.orthogonal( );
+ angle2 = PMVector::cross( center, angle1 );
+
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMRadiusID )
+ {
+ if( firstPoint )
+ {
+ ( ( PMDistanceControlPoint *) p)->setDirection( angle1 );
+ firstPoint = false;
+ }
+ else
+ ( ( PMDistanceControlPoint *) p)->setDirection( angle2 );
+ }
+ }
+
+ if( radiusChanged )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMRadiusID )
+ ( ( PMDistanceControlPoint *) p)->setDistance( m_radius );
+}
+
+void PMCylinder::setSteps( int s )
+{
+ if( s >= 4 )
+ {
+ s_numSteps = s;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMCylinder::setSteps: S must be greater than 3\n";
+ s_parameterKey++;
+}
+
+void PMCylinder::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmcylinder.h b/kpovmodeler/pmcylinder.h
new file mode 100644
index 00000000..ba98ae40
--- /dev/null
+++ b/kpovmodeler/pmcylinder.h
@@ -0,0 +1,176 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCYLINDER_H
+#define PMCYLINDER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include "pmviewstructure.h"
+
+/**
+ * Class for povray cylinder
+ */
+
+class PMCylinder : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates a cylinder
+ */
+ PMCylinder( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMCylinder( const PMCylinder& c );
+
+ /**
+ * Deletes the cylinder
+ */
+ virtual ~PMCylinder( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMCylinder( *this ); }
+
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMCylinderEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmcylinder" ); }
+
+ /**
+ * Return the end_1
+ */
+ PMVector end1( ) const { return m_end1; }
+ /**
+ * Sets end_1
+ */
+ void setEnd1( const PMVector& p );
+ /**
+ * Return the end_2
+ */
+ PMVector end2( ) const { return m_end2; }
+ /**
+ * Sets end_2
+ */
+ void setEnd2( const PMVector& p );
+ /**
+ * return the radius of the cylinder
+ */
+ double radius( ) const { return m_radius; }
+ /**
+ * Sets the radius of the cylinder
+ */
+ void setRadius( double radius );
+ /**
+ * Return open = 1 or close = 0
+ */
+ bool open( ) const { return m_open; }
+ /**
+ * Sets open cylinder
+ */
+ void setOpen( bool op );
+
+ /**
+ * Returns the number of lines for rendering
+ */
+ static int steps( ) { return s_numSteps; }
+ /**
+ * Sets the number of lines for rendering
+ */
+ static void setSteps( int s );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey(); }
+
+private:
+ /**
+ * Creates the lines for the view structure
+ */
+ static void createLines( PMLineArray& lines, int steps );
+ /**
+ * Creates the points for the view structure
+ */
+ static void createPoints( PMPointArray& points, const PMVector& end1,
+ const PMVector& end2, double radius, int steps );
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMCylinderMementoID { PMEnd1ID, PMEnd2ID, PMRadiusID, PMOpenID };
+ /**
+ * ends of cylinder
+ */
+ PMVector m_end1, m_end2;
+ /**
+ * radius of cylinder
+ */
+ double m_radius;
+ /**
+ * open
+ */
+ bool m_open;
+ /**
+ * The default view structure. It can be shared between cylinders
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_numSteps;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmcylinderedit.cpp b/kpovmodeler/pmcylinderedit.cpp
new file mode 100644
index 00000000..623b2b4f
--- /dev/null
+++ b/kpovmodeler/pmcylinderedit.cpp
@@ -0,0 +1,113 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : skoriane@nce.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmcylinderedit.h"
+#include "pmcylinder.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <qcheckbox.h>
+
+PMCylinderEdit::PMCylinderEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMCylinderEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+ QGridLayout* gl;
+
+ m_pEnd1 = new PMVectorEdit( "x", "y", "z", this );
+ m_pEnd2 = new PMVectorEdit( "x", "y", "z", this );
+ m_pRadius = new PMFloatEdit( this );
+ m_pOpen = new QCheckBox( i18n( "type of the object", "Open" ), this );
+
+ gl = new QGridLayout( topLayout( ), 2, 2 );
+ gl->addWidget( new QLabel( i18n( "End 1:" ), this ), 0, 0 );
+ gl->addWidget( m_pEnd1, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "End 2:" ), this ), 1, 0 );
+ gl->addWidget( m_pEnd2, 1, 1 );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Radius:" ), this ) );
+ layout->addWidget( m_pRadius );
+ layout->addStretch( 1 );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( m_pOpen );
+
+ connect( m_pEnd1, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnd2, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOpen, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMCylinderEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Cylinder" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMCylinder* ) o;
+
+ m_pEnd1->setVector( m_pDisplayedObject->end1( ) );
+ m_pEnd2->setVector( m_pDisplayedObject->end2( ) );
+ m_pRadius->setValue( m_pDisplayedObject->radius( ) );
+ m_pOpen->setChecked( m_pDisplayedObject->open( ) );
+
+ m_pEnd1->setReadOnly( readOnly );
+ m_pEnd2->setReadOnly( readOnly );
+ m_pRadius->setReadOnly( readOnly );
+ m_pOpen->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMCylinderEdit: Can't display object\n";
+}
+
+void PMCylinderEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setEnd1( m_pEnd1->vector( ) );
+ m_pDisplayedObject->setEnd2( m_pEnd2->vector( ) );
+ m_pDisplayedObject->setRadius( m_pRadius->value( ) );
+ m_pDisplayedObject->setOpen( m_pOpen->isChecked( ) );
+ }
+}
+
+bool PMCylinderEdit::isDataValid( )
+{
+ if( m_pEnd1->isDataValid( ) )
+ if( m_pEnd2->isDataValid( ) )
+ if( m_pRadius->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+#include "pmcylinderedit.moc"
+
+
diff --git a/kpovmodeler/pmcylinderedit.h b/kpovmodeler/pmcylinderedit.h
new file mode 100644
index 00000000..aec05df5
--- /dev/null
+++ b/kpovmodeler/pmcylinderedit.h
@@ -0,0 +1,63 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorinaez
+ email : skoriane@nce.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMCYLINDEREDIT_H
+#define PMCYLINDEREDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMVectorEdit;
+class PMFloatEdit;
+class PMCylinder;
+class QCheckBox;
+
+class PMCylinderEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMCylinderEdit with parent and name
+ */
+ PMCylinderEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMCylinder* m_pDisplayedObject;
+ PMVectorEdit* m_pEnd1;
+ PMVectorEdit* m_pEnd2;
+ PMFloatEdit* m_pRadius;
+ QCheckBox* m_pOpen;
+
+};
+#endif
diff --git a/kpovmodeler/pmdatachangecommand.cpp b/kpovmodeler/pmdatachangecommand.cpp
new file mode 100644
index 00000000..0793986e
--- /dev/null
+++ b/kpovmodeler/pmdatachangecommand.cpp
@@ -0,0 +1,111 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdatachangecommand.h"
+#include "pmcommandmanager.h"
+#include "pmmemento.h"
+#include "pmobject.h"
+#include <klocale.h>
+
+PMDataChangeCommand::PMDataChangeCommand( PMMemento* memento )
+ : PMCommand( )
+{
+ QString text = memento->originator( )->name( );
+ if( text.isEmpty( ) )
+ text = memento->originator( )->description( );
+ setText( i18n( "Change %1" ).arg( text ) );
+
+ // the data is already changed when the command is created
+ m_executed = true;
+ m_unexecuted = false;
+ m_pOldState = memento;
+ m_pNewState = 0;
+}
+
+PMDataChangeCommand::~PMDataChangeCommand( )
+{
+ if( m_pOldState )
+ delete m_pOldState;
+ if( m_pNewState )
+ delete m_pNewState;
+}
+
+void PMDataChangeCommand::execute( PMCommandManager* theManager )
+{
+ PMObject* obj = m_pOldState->originator( );
+ if( !m_executed )
+ {
+ // if the command is not executed
+ // restore the memento
+ if( m_pNewState )
+ {
+ if( m_pNewState->containsChanges( ) )
+ {
+ obj->restoreMemento( m_pNewState );
+
+ if( m_pOldState->idChanged( ) )
+ theManager->cmdIDChanged( obj, m_pOldState->oldID( ) );
+ signalChanges( theManager, m_pNewState );
+ }
+ }
+ m_executed = true;
+ }
+ else if( !m_unexecuted )
+ {
+ // the data can be changed multiple times
+ // if the command was never unexecuted, emit the signal
+ // ( the data was already changed, so this is not necessary here )
+ if( m_pOldState->idChanged( ) )
+ theManager->cmdIDChanged( obj, m_pOldState->oldID( ) );
+ signalChanges( theManager, m_pOldState );
+ }
+}
+
+void PMDataChangeCommand::undo( PMCommandManager* theManager )
+{
+ if( m_executed )
+ {
+ if( m_pOldState->containsChanges( ) )
+ {
+ PMObject* obj = m_pOldState->originator( );
+ if( !m_pNewState )
+ obj->createMemento( );
+
+ obj->restoreMemento( m_pOldState );
+
+ if( !m_pNewState )
+ m_pNewState = obj->takeMemento( );
+
+ if( m_pNewState->idChanged( ) )
+ theManager->cmdIDChanged( obj, m_pNewState->oldID( ) );
+ signalChanges( theManager, m_pOldState );
+ }
+ m_executed = false;
+ m_unexecuted = true;
+ }
+}
+
+void PMDataChangeCommand::signalChanges( PMCommandManager* theManager,
+ PMMemento* memento )
+{
+ PMObjectChangeListIterator it( memento->changedObjects( ) );
+
+ for( ; it.current( ); ++it )
+ theManager->cmdObjectChanged( it.current( )->object( ),
+ it.current( )->mode( ) );
+}
diff --git a/kpovmodeler/pmdatachangecommand.h b/kpovmodeler/pmdatachangecommand.h
new file mode 100644
index 00000000..878e0f4f
--- /dev/null
+++ b/kpovmodeler/pmdatachangecommand.h
@@ -0,0 +1,68 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMDATACHANGECOMMAND_H
+#define PMDATACHANGECOMMAND_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcommand.h"
+
+class PMMemento;
+
+/**
+ * Command that stores undo information for object changes
+ *
+ * Let an object create a @ref PMMemento, change the objects data, take the
+ * memento and create a PMDataChangeCommand with this memento.
+ *
+ * Then execute the command. The object will not be changed again!
+ */
+class PMDataChangeCommand : public PMCommand
+{
+public:
+ /**
+ * Creates a PMDataChangeCommand for the memento
+ */
+ PMDataChangeCommand( PMMemento* memento );
+ /**
+ * Deletes the command. The memento will be deleted.
+ */
+ virtual ~PMDataChangeCommand( );
+protected:
+ /**
+ * Executes the command
+ */
+ virtual void execute( PMCommandManager* theManager );
+ /**
+ * Undo the command
+ */
+ virtual void undo( PMCommandManager* theManager );
+
+private:
+ void signalChanges( PMCommandManager* theManager, PMMemento* memento );
+ PMMemento* m_pNewState;
+ PMMemento* m_pOldState;
+ bool m_executed;
+ bool m_unexecuted;
+};
+
+#endif
diff --git a/kpovmodeler/pmdebug.h b/kpovmodeler/pmdebug.h
new file mode 100644
index 00000000..692bcd60
--- /dev/null
+++ b/kpovmodeler/pmdebug.h
@@ -0,0 +1,26 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDEBUG_H
+#define PMDEBUG_H
+
+#define PMArea 0 // no area for debug messages yet
+
+#include <kdebug.h>
+
+#endif
diff --git a/kpovmodeler/pmdeclare.cpp b/kpovmodeler/pmdeclare.cpp
new file mode 100644
index 00000000..2b698f0e
--- /dev/null
+++ b/kpovmodeler/pmdeclare.cpp
@@ -0,0 +1,238 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmdeclare.h"
+#include "pmdeclareedit.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmprototypemanager.h"
+#include "pmpart.h"
+
+#include <qvaluelist.h>
+#include <klocale.h>
+
+PMDefinePropertyClass( PMDeclare, PMDeclareProperty );
+
+PMMetaObject* PMDeclare::s_pMetaObject;
+PMObject* createNewDeclare( PMPart* part )
+{
+ return new PMDeclare( part );
+}
+
+PMDeclare::PMDeclare( PMPart* part )
+ : Base( part )
+{
+ m_pDeclareType = 0;
+}
+
+PMDeclare::PMDeclare( const PMDeclare& d )
+ : Base( d )
+{
+ m_id = d.m_id; // CAUTION! Duplication of the id which has to be unique
+ m_pDeclareType = 0; // will be set automatically in the
+ // base constuctor when the children are copied
+}
+
+PMMetaObject* PMDeclare::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Declare", Base::metaObject( ),
+ createNewDeclare );
+ s_pMetaObject->addProperty(
+ new PMDeclareProperty( "id", &PMDeclare::setID, &PMDeclare::id ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMDeclare::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+PMDeclare::~PMDeclare( )
+{
+}
+
+QString PMDeclare::description( ) const
+{
+ PMPart* pPart = part( );
+ QString d = i18n( "declaration" );
+
+ if( m_pDeclareType && pPart )
+ {
+ const QValueList<PMDeclareDescription>& descriptions
+ = pPart->prototypeManager( )->declarationTypes( );
+ QValueList<PMDeclareDescription>::const_iterator it;
+ bool found = false;
+ for( it = descriptions.begin( ); it != descriptions.end( ) && !found; ++it )
+ {
+ if( ( *it ).type == m_pDeclareType )
+ {
+ d = ( *it ).description;
+ found = true;
+ }
+ }
+ }
+ return d;
+}
+
+QString PMDeclare::pixmap( ) const
+{
+ PMPart* pPart = part( );
+ QString d = "pmdeclare";
+
+ if( m_pDeclareType && pPart )
+ {
+ const QValueList<PMDeclareDescription>& descriptions
+ = pPart->prototypeManager( )->declarationTypes( );
+ QValueList<PMDeclareDescription>::const_iterator it;
+ bool found = false;
+ for( it = descriptions.begin( ); it != descriptions.end( ) && !found; ++it )
+ {
+ if( ( *it ).type == m_pDeclareType )
+ {
+ d = ( *it ).pixmap;
+ found = true;
+ }
+ }
+ }
+ return d;
+}
+
+void PMDeclare::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "id", m_id );
+ Base::serialize( e, doc );
+}
+
+void PMDeclare::readAttributes( const PMXMLHelper& h )
+{
+ m_id = h.stringAttribute( "id", "object" );
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMDeclare::editWidget( QWidget* parent ) const
+{
+ return new PMDeclareEdit( parent );
+}
+
+void PMDeclare::setID( const QString& newID )
+{
+ if( newID != m_id )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addIDChange( s_pMetaObject, PMIDID, m_id );
+ m_pMemento->setDescriptionChanged( );
+ }
+
+ m_id = newID;
+ }
+}
+
+QString PMDeclare::declareType( ) const
+{
+ if( !m_pDeclareType )
+ return QString( "None" );
+ return m_pDeclareType->className( );
+}
+
+void PMDeclare::setDeclareType( PMMetaObject* t )
+{
+ if( m_pDeclareType != t )
+ {
+ if( m_pMemento )
+ m_pMemento->setDescriptionChanged( );
+
+ m_pDeclareType = t;
+ }
+}
+
+void PMDeclare::updateDeclareType( )
+{
+ PMPart* pPart = part( );
+ if( !pPart )
+ return;
+
+ PMMetaObject* type = 0;
+ PMObject* o = firstChild( );
+ PMPrototypeManager* m = pPart->prototypeManager( );
+ if( o )
+ {
+ if( o->isA( "GraphicalObject" ) )
+ type = m->metaObject( "GraphicalObject" );
+ else
+ type = o->metaObject( );
+ }
+ setDeclareType( type );
+}
+
+void PMDeclare::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMIDID:
+ setID( data->stringData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMDeclare::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+void PMDeclare::addLinkedObject( PMObject* o )
+{
+ m_linkedObjects.append( o );
+}
+
+void PMDeclare::removeLinkedObject( PMObject* o )
+{
+ m_linkedObjects.removeRef( o );
+}
+
+void PMDeclare::childAdded( PMObject* o )
+{
+ if( !m_pDeclareType )
+ updateDeclareType( );
+
+ Base::childAdded( o );
+}
+
+void PMDeclare::childRemoved( PMObject* o )
+{
+ if( !firstChild( ) )
+ setDeclareType( 0 );
+
+ Base::childRemoved( o );
+}
diff --git a/kpovmodeler/pmdeclare.h b/kpovmodeler/pmdeclare.h
new file mode 100644
index 00000000..d466e60e
--- /dev/null
+++ b/kpovmodeler/pmdeclare.h
@@ -0,0 +1,147 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDECLARE_H
+#define PMDECLARE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcompositeobject.h"
+#include "pmsymboltable.h"
+
+/**
+ * Class for all povray declares
+ */
+class PMDeclare : public PMCompositeObject
+{
+ typedef PMCompositeObject Base;
+public:
+ /**
+ * Constructor
+ */
+ PMDeclare( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMDeclare( const PMDeclare& d );
+ /**
+ * Deletes the object
+ */
+ ~PMDeclare( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMDeclare( *this ); }
+
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString pixmap( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual bool dataChangeOnInsertRemove( ) const { return true; }
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMDeclareEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the id of the declare
+ */
+ virtual QString name( ) const { return m_id; }
+ /**
+ * Returns the id of the declare
+ */
+ QString id( ) const { return m_id; }
+ /**
+ * Returns the declare type
+ */
+ QString declareType( ) const;
+
+ /**
+ * Sets the id of the object.
+ */
+ void setID( const QString& id );
+ /** */
+ virtual bool canHaveName( ) const { return true; }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /**
+ * Returns an iterator to the list of objects, that are linked to that
+ * declare
+ */
+ PMObjectListIterator linkedObjects( ) const
+ {
+ return PMObjectListIterator( m_linkedObjects );
+ }
+ /**
+ * Adds the object to the list of linked objects
+ */
+ void addLinkedObject( PMObject* o );
+ /**
+ * Removes the object from the list of linked objects
+ */
+ void removeLinkedObject( PMObject* o );
+
+ /** */
+ virtual void childAdded( PMObject* o );
+ /** */
+ virtual void childRemoved( PMObject* o );
+
+private:
+ /**
+ * Sets the declare type
+ */
+ void setDeclareType( PMMetaObject* o );
+ /**
+ * Recalculates the declaration type
+ */
+ void updateDeclareType( );
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMDeclareMementoID { PMIDID };
+
+ /**
+ * id of the declare
+ */
+ QString m_id;
+ /**
+ * The linked objects
+ */
+ PMObjectList m_linkedObjects;
+ /**
+ * The declare type
+ */
+ PMMetaObject* m_pDeclareType;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmdeclareedit.cpp b/kpovmodeler/pmdeclareedit.cpp
new file mode 100644
index 00000000..5f9e9c67
--- /dev/null
+++ b/kpovmodeler/pmdeclareedit.cpp
@@ -0,0 +1,206 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdeclareedit.h"
+#include "pmdeclare.h"
+#include "pmpart.h"
+#include "pmsymboltable.h"
+#include "pmscanner.h"
+#include "pmobjectselect.h"
+
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qtextstream.h>
+#include <qpushbutton.h>
+#include <qlistbox.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+
+PMDeclareEdit::PMDeclareEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+ m_pSelectedObject = 0;
+}
+
+void PMDeclareEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout = new QHBoxLayout( topLayout( ) );
+ m_pNameEdit = new QLineEdit( this );
+ m_pNameEdit->setMaxLength( 40 );
+ QLabel* label = new QLabel( i18n( "Identifier:" ), this );
+
+ layout->addWidget( label );
+ layout->addWidget( m_pNameEdit );
+
+ connect( m_pNameEdit, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotNameChanged( const QString& ) ) );
+}
+
+void PMDeclareEdit::createBottomWidgets( )
+{
+ QLabel* l = new QLabel( i18n( "Linked objects:" ), this );
+ topLayout( )->addWidget( l );
+
+ m_pLinkedObjects = new QListBox( this );
+ m_pLinkedObjects->setMinimumHeight( 100 );
+ connect( m_pLinkedObjects, SIGNAL( highlighted( QListBoxItem* ) ),
+ SLOT( slotItemSelected( QListBoxItem* ) ) );
+ topLayout( )->addWidget( m_pLinkedObjects, 1 );
+
+ QHBoxLayout* layout = new QHBoxLayout( topLayout( ) );
+ m_pSelectButton = new QPushButton( i18n( "Select..." ), this );
+ m_pSelectButton->setEnabled( false );
+
+ connect( m_pSelectButton, SIGNAL( clicked( ) ), SLOT( slotSelect( ) ) );
+ layout->addStretch( );
+ layout->addWidget( m_pSelectButton );
+
+ Base::createBottomWidgets( );
+}
+
+void PMDeclareEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Declare" ) )
+ {
+ m_pDisplayedObject = ( PMDeclare* ) o;
+ m_pNameEdit->setText( QString( m_pDisplayedObject->id( ) ) );
+
+ m_pNameEdit->setReadOnly( m_pDisplayedObject->isReadOnly( ) );
+
+ PMObjectListIterator it( m_pDisplayedObject->linkedObjects( ) );
+ m_pLinkedObjects->clear( );
+
+ for( ; it.current( ); ++it )
+ m_pLinkedObjects->insertItem(
+ new PMListBoxObject( it.current( ) ) );
+
+ m_pSelectButton->setEnabled( false );
+ m_pSelectedObject = 0;
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMDeclareEdit: Can't display object\n";
+}
+
+void PMDeclareEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setID( m_pNameEdit->text( ) );
+ }
+}
+
+bool PMDeclareEdit::isDataValid( )
+{
+ if( !Base::isDataValid( ) )
+ return false;
+
+ QString text = m_pNameEdit->text( );
+ if( text.length( ) == 0 )
+ {
+ KMessageBox::error( this, i18n( "Please enter an identifier!" ),
+ i18n( "Error" ) );
+ return false;
+ }
+
+ if( text == m_pDisplayedObject->id( ) )
+ return true;
+
+ QTextStream str( &text, IO_ReadOnly );
+ QChar c;
+ int ac;
+ bool ok = true;
+ int i = 0;
+ while( !str.atEnd( ) && ok )
+ {
+ str >> c;
+ ac = c.latin1( );
+ // QChar::category can't be used because umlauts are not allowed
+ if( i == 0 )
+ ok = ( ( ( ac >= 'a' ) && ( ac <= 'z' ) ) ||
+ ( ( ac >= 'A' ) && ( ac <= 'Z' ) ) ||
+ ( ac == '_' ) );
+ else
+ ok = ( ( ( ac >= 'a' ) && ( ac <= 'z' ) ) ||
+ ( ( ac >= 'A' ) && ( ac <= 'Z' ) ) ||
+ ( ( ac >= '0' ) && ( ac <= '9' ) ) ||
+ ( ac == '_' ) );
+ i++;
+ }
+ if( !ok )
+ {
+ KMessageBox::error( this, i18n( "An identifier may consist of letters,"
+ " digits and the underscore character"
+ " ('_').\n"
+ "The first character must be a letter"
+ " or the underscore character!" ),
+ i18n( "Error" ) );
+ return false;
+ }
+ // valid identifer!
+
+ PMReservedWordDict* dict = PMScanner::reservedWords( );
+ if( dict->find( text.latin1( ) ) != -1 )
+ {
+ KMessageBox::error( this, i18n( "You can't use a povray reserved word"
+ " as an identifier!" ), i18n( "Error" ) );
+ return false;
+ }
+ dict = PMScanner::directives( );
+ if( dict->find( text.latin1( ) ) != -1 )
+ {
+ KMessageBox::error( this, i18n( "You can't use a povray directive"
+ " as an identifier!" ), i18n( "Error" ) );
+ return false;
+ }
+
+ // no reserved word
+ PMSymbolTable* st = part( )->symbolTable( );
+ if( st->find( text ) )
+ {
+ KMessageBox::error( this, i18n( "Please enter a unique identifier!" ),
+ i18n( "Error" ) );
+ return false;
+ }
+ return true;
+}
+
+void PMDeclareEdit::slotNameChanged( const QString& )
+{
+ emit dataChanged( );
+}
+
+void PMDeclareEdit::slotItemSelected( QListBoxItem* item )
+{
+ m_pSelectedObject = ( ( PMListBoxObject* ) item )->object( );
+ m_pSelectButton->setEnabled( true );
+}
+
+void PMDeclareEdit::slotSelect( )
+{
+ if( m_pSelectedObject )
+ part( )->slotObjectChanged( m_pSelectedObject, PMCNewSelection, this );
+}
+#include "pmdeclareedit.moc"
diff --git a/kpovmodeler/pmdeclareedit.h b/kpovmodeler/pmdeclareedit.h
new file mode 100644
index 00000000..9ee2fc83
--- /dev/null
+++ b/kpovmodeler/pmdeclareedit.h
@@ -0,0 +1,74 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMDECLAREEDIT_H
+#define PMDECLAREEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMDeclare;
+class QLineEdit;
+class QListBox;
+class QPushButton;
+class QListBoxItem;
+
+/**
+ * Dialog edit class for @ref PMDeclare.
+ */
+class PMDeclareEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMDeclareEdit with parent and name
+ */
+ PMDeclareEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void createBottomWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private slots:
+ void slotNameChanged( const QString& );
+ void slotItemSelected( QListBoxItem* );
+ void slotSelect( );
+private:
+ PMDeclare* m_pDisplayedObject;
+ QLineEdit* m_pNameEdit;
+ QListBox* m_pLinkedObjects;
+ QPushButton* m_pSelectButton;
+ PMObject* m_pSelectedObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmdefaults.h b/kpovmodeler/pmdefaults.h
new file mode 100644
index 00000000..32c9675c
--- /dev/null
+++ b/kpovmodeler/pmdefaults.h
@@ -0,0 +1,131 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDEFAULTS_H
+#define PMDEFAULTS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qcolor.h>
+#include <math.h>
+
+// PMRenderManager
+const QColor c_defaultGraphicalObjectColor0 = QColor( 148, 148, 148 );
+const QColor c_defaultGraphicalObjectColor1 = QColor( 255, 255, 128 );
+const QColor c_defaultTextureColor0 = QColor( 64, 192, 64 );
+const QColor c_defaultTextureColor1 = QColor( 192, 255, 128 );
+const QColor c_defaultAxesColorX = QColor( 255, 0, 0 );
+const QColor c_defaultAxesColorY = QColor( 0, 255, 0 );
+const QColor c_defaultAxesColorZ = QColor( 0, 0, 255 );
+const QColor c_defaultControlPointColor0 = QColor( 255, 255, 148 );
+const QColor c_defaultControlPointColor1 = QColor( 92, 255, 92 );
+const QColor c_defaultBackgroundColor = QColor( 0, 0, 0 );
+const QColor c_defaultFieldOfViewColor = QColor( 128, 128, 255 );
+const bool c_defaultHighDetailCameraView = true;
+
+// PMGLView
+const int c_defaultGridDistance = 50;
+const QColor c_defaultGridColor = QColor( 40, 120, 40 );
+
+// PovrayRenderWidget
+const QString c_defaultPovrayCommand = QString( "povray" );
+
+// PMDetailObject
+const int c_defaultDetailObjectGlobalDetailLevel = 1;
+
+// PMSphere
+const int c_defaultSphereUSteps = 8;
+const int c_defaultSphereVSteps = 16;
+
+// PMBlobSphere
+const int c_defaultBlobSphereUSteps = 8;
+const int c_defaultBlobSphereVSteps = 16;
+
+// PMBlobCylinder
+const int c_defaultBlobCylinderUSteps = 4;
+const int c_defaultBlobCylinderVSteps = 16;
+
+// PMCylinder
+const int c_defaultCylinderSteps = 16;
+
+// PMCone
+const int c_defaultConeSteps = 16;
+
+// PMTorus
+const int c_defaultTorusVSteps = 16;
+const int c_defaultTorusUSteps = 9;
+
+// PMPlane
+const double c_defaultPlaneSize = 2.0;
+
+// PMDisc
+const int c_defaultDiscSteps = 16;
+
+// PMText
+const int c_defaultTextSteps = 3;
+
+// PMLathe
+const int c_defaultLatheRSteps = 16;
+const int c_defaultLatheSSteps = 4;
+
+// PMPrism
+const int c_defaultPrismSSteps = 4;
+
+// PMSurfaceOfRevolution
+const int c_defaultSurfaceOfRevolutionRSteps = 16;
+const int c_defaultSurfaceOfRevolutionSSteps = 4;
+
+// PMSuperquadricEllipsoid
+const int c_defaultSuperquadricEllipsoidUSteps = 3;
+const int c_defaultSuperquadricEllipsoidVSteps = 3;
+
+// PMSphereSweep
+const int c_defaultSphereSweepRSteps = 8;
+const int c_defaultSphereSweepSSteps = 4;
+
+// PMHeightField
+const int c_defaultHeightFieldVariance = 16;
+
+// PMDialogEditBase, texture preview
+const int c_defaultTPSize = 160;
+const bool c_defaultTPShowSphere = true;
+const bool c_defaultTPShowCylinder = false;
+const bool c_defaultTPShowBox = true;
+const bool c_defaultTPAA = false;
+const int c_defaultTPAADepth = 2;
+const double c_defaultTPAAThreshold = 0.3;
+const bool c_defaultTPShowFloor = true;
+const bool c_defaultTPShowWall = true;
+const QColor c_defaultTPWallColor1 = QColor( 255, 255, 255 );
+const QColor c_defaultTPWallColor2 = QColor( 0, 0, 0 );
+const QColor c_defaultTPFloorColor1 = QColor( 192, 0, 0 );
+const QColor c_defaultTPFloorColor2 = QColor( 255, 255, 255 );
+const double c_defaultTPGamma = 1.5;
+
+// PM3DControlPoint
+const double c_defaultMoveGrid = 0.1;
+const double c_defaultScaleGrid = 0.1;
+const double c_defaultRotateGrid = 1.0;
+
+// PMShell
+const bool c_defaultTreeViewTabbed = false;
+const bool c_defaultTreeViewRight = false;
+const bool c_defaultTreeViewBelow = false;
+
+#endif
diff --git a/kpovmodeler/pmdeletecommand.cpp b/kpovmodeler/pmdeletecommand.cpp
new file mode 100644
index 00000000..fa5ff47b
--- /dev/null
+++ b/kpovmodeler/pmdeletecommand.cpp
@@ -0,0 +1,281 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdeletecommand.h"
+#include "pmcommandmanager.h"
+#include "pmdeclare.h"
+#include "pmrecursiveobjectiterator.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qptrdict.h>
+
+PMDeleteCommand::PMDeleteCommand( PMObject* obj )
+ : PMCommand( i18n( "Delete %1" ).arg( obj->name( ) ) )
+{
+ // the scene can not be deleted!
+ if( obj->parent( ) )
+ m_infoList.append( new PMDeleteInfo( obj ) );
+ else
+ {
+ // object has no parent!
+ // top level objects can't be moved, move all child items
+ PMObject* tmp;
+ for( tmp = obj->firstChild( ); tmp; tmp = tmp->nextSibling( ) )
+ m_infoList.append( new PMDeleteInfo( tmp ) );
+ }
+ m_executed = false;
+ m_firstExecution = true;
+ m_linksCreated = false;
+}
+
+PMDeleteCommand::PMDeleteCommand( const PMObjectList& list )
+ : PMCommand( i18n( "Delete Objects" ) )
+{
+ PMObjectListIterator it( list );
+ PMObject* obj;
+
+ for( ; it.current( ); ++it )
+ {
+ obj = it.current( );
+
+ if( obj->parent( ) )
+ m_infoList.append( new PMDeleteInfo( obj ) );
+ else
+ {
+ // object has no parent!
+ // top level objects can't be moved, move all child items
+ PMObject* tmp;
+ for( tmp = obj->firstChild( ); tmp; tmp = tmp->nextSibling( ) )
+ m_infoList.append( new PMDeleteInfo( tmp ) );
+ }
+ }
+
+ m_infoList.setAutoDelete( true );
+ m_executed = false;
+ m_firstExecution = true;
+ m_linksCreated = false;
+}
+
+PMDeleteCommand::~PMDeleteCommand( )
+{
+ if( m_executed )
+ {
+ PMDeleteInfoListIterator it( m_infoList );
+ for( ; it.current( ); ++it )
+ delete ( it.current( )->deletedObject( ) );
+ }
+
+ m_infoList.clear( );
+}
+
+void PMDeleteCommand::execute( PMCommandManager* theManager )
+{
+ if( !m_executed )
+ {
+ PMDeleteInfoListIterator it( m_infoList );
+ PMDeleteInfo* info = 0;
+ PMObject* parent;
+
+ if( !m_linksCreated )
+ {
+ PMDeclare* decl;
+ for( ; it.current( ); ++it )
+ {
+ PMRecursiveObjectIterator oit( it.current( )->deletedObject( ) );
+ for( ; oit.current( ); ++oit )
+ {
+ decl = oit.current( )->linkedObject( );
+ if( decl )
+ {
+ m_links.append( oit.current( ) );
+ if( !m_linkedDeclares.containsRef( decl ) )
+ m_linkedDeclares.append( decl );
+ }
+ }
+ }
+ m_linksCreated = true;
+ }
+
+ PMObjectListIterator lit( m_links );
+ for( ; lit.current( ); ++lit )
+ lit.current( )->linkedObject( )->removeLinkedObject( lit.current( ) );
+
+ for( it.toLast( ); it.current( ); --it )
+ {
+ info = it.current( );
+ parent = info->parent( );
+ // signal has to be emitted before the item is removed
+ theManager->cmdObjectChanged( info->deletedObject( ), PMCRemove );
+ if( m_firstExecution )
+ if( parent->dataChangeOnInsertRemove( )
+ && !parent->mementoCreated( ) )
+ parent->createMemento( );
+ parent->takeChild( info->deletedObject( ) );
+ }
+
+ if( m_firstExecution )
+ {
+ for( it.toLast( ); it.current( ); --it )
+ {
+ parent = it.current( )->parent( );
+ if( parent->mementoCreated( ) )
+ m_dataChanges.append( parent->takeMemento( ) );
+ }
+ }
+
+ QPtrListIterator<PMMemento> mit( m_dataChanges );
+ for( ; mit.current( ); ++mit )
+ {
+ PMObjectChangeListIterator change = mit.current( )->changedObjects( );
+ for( ; change.current( ); ++change )
+ theManager->cmdObjectChanged( change.current( )->object( ),
+ change.current( )->mode( ) );
+ }
+
+ PMObjectListIterator dit( m_linkedDeclares );
+ for( ; dit.current( ); ++dit )
+ theManager->cmdObjectChanged( dit.current( ), PMCData );
+
+ m_executed = true;
+ m_firstExecution = false;
+ }
+}
+
+void PMDeleteCommand::undo( PMCommandManager* theManager )
+{
+ if( m_executed )
+ {
+ PMDeleteInfoListIterator it( m_infoList );
+ for( ; it.current( ); ++it )
+ {
+ if( it.current( )->prevSibling( ) )
+ it.current( )->parent( )
+ ->insertChildAfter( it.current( )->deletedObject( ),
+ it.current( )->prevSibling( ) );
+ else
+ it.current( )->parent( )
+ ->insertChild( it.current( )->deletedObject( ), 0 );
+ theManager->cmdObjectChanged( it.current( )->deletedObject( ), PMCAdd );
+ }
+
+ PMObjectListIterator lit( m_links );
+ for( ; lit.current( ); ++lit )
+ lit.current( )->linkedObject( )->addLinkedObject( lit.current( ) );
+ PMObjectListIterator dit( m_linkedDeclares );
+ for( ; dit.current( ); ++dit )
+ theManager->cmdObjectChanged( dit.current( ), PMCData );
+
+ QPtrListIterator<PMMemento> mit( m_dataChanges );
+ for( ; mit.current( ); ++mit )
+ {
+ mit.current( )->originator( )->restoreMemento( mit.current( ) );
+ PMObjectChangeListIterator change = mit.current( )->changedObjects( );
+ for( ; change.current( ); ++change )
+ theManager->cmdObjectChanged( change.current( )->object( ),
+ change.current( )->mode( ) );
+ }
+
+ m_executed = false;
+ }
+}
+
+int PMDeleteCommand::errorFlags( PMPart* )
+{
+ PMDeleteInfo* info;
+ PMDeclare* decl = 0;
+ PMObject* obj;
+ bool insideSelection;
+ bool ok = true;
+ bool error = false;
+
+ // dictionary of deleted objects
+ QPtrDict<bool> m_deletedObjects( 1009 );
+ m_deletedObjects.setAutoDelete( true );
+ PMDeleteInfoListIterator it( m_infoList );
+ for( ; it.current( ); ++it )
+ m_deletedObjects.insert( it.current( )->deletedObject( ),
+ new bool( true ) );
+
+ // declares can only be deleted, if all linked
+ // objects are deleted as well
+
+ info = m_infoList.last( );
+
+ while( info )
+ {
+ ok = true;
+ if( info->deletedObject( )->isA( "Declare" ) )
+ {
+ decl = ( PMDeclare* ) ( info->deletedObject( ) );
+ PMObjectListIterator links = decl->linkedObjects( );
+
+ for( ; links.current( ) && ok; ++links )
+ {
+ insideSelection = false;
+ for( obj = links.current( ); obj && !insideSelection;
+ obj = obj->parent( ) )
+ {
+ if( m_deletedObjects.find( obj ) )
+ insideSelection = true;
+ }
+
+ if( insideSelection )
+ {
+ bool stop = false;
+ for( obj = links.current( ); obj && !stop; obj = obj->parent( ) )
+ {
+ if( m_deletedObjects.find( obj ) )
+ stop = true;
+ else
+ m_deletedObjects.insert( obj, new bool( true ) );
+ }
+ }
+ else
+ ok = false;
+ }
+ }
+
+ if( !ok )
+ {
+ m_errors.prepend( i18n( "The declare \"%1\" can't be removed "
+ "because of some remaining links." )
+ .arg( decl->id( ) ) );
+
+ PMDeleteInfo* tmp = info;
+ info = m_infoList.prev( );
+ m_deletedObjects.remove( decl );
+ m_infoList.removeRef( tmp );
+
+ error = true;
+ }
+ else
+ info = m_infoList.prev( );
+ }
+
+ if( error )
+ {
+ if( m_infoList.count( ) == 0 )
+ return PMEError | PMEFatal;
+ else
+ return PMEError;
+ }
+
+ return PMENone;
+}
diff --git a/kpovmodeler/pmdeletecommand.h b/kpovmodeler/pmdeletecommand.h
new file mode 100644
index 00000000..ff67c0bc
--- /dev/null
+++ b/kpovmodeler/pmdeletecommand.h
@@ -0,0 +1,126 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMDELETECOMMAND_H
+#define PMDELETECOMMAND_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcommand.h"
+#include <qstring.h>
+
+#include "pmobject.h"
+
+class PMMemento;
+
+/**
+ * Class that stores undo information for the @ref PMDeleteCommand
+ */
+class PMDeleteInfo
+{
+public:
+ /**
+ * Creates undo information for the object deletedObject.
+ * The object has to have a parent!
+ */
+ PMDeleteInfo( PMObject* deletedObject )
+ {
+ m_pDeletedObject = deletedObject;
+ m_pParent = deletedObject->parent( );
+ m_pPrevSibling = deletedObject->prevSibling( );
+ m_insertError = false;
+ }
+ /**
+ * Deletes the object. The object deletedObject will not be deleted!
+ */
+ ~PMDeleteInfo( ) { };
+ /**
+ * Returns a pointer to the deleted object
+ */
+ PMObject* deletedObject( ) const { return m_pDeletedObject; }
+ /**
+ * Returns a pointer to the parent of the deleted object
+ */
+ PMObject* parent( ) const { return m_pParent; }
+ /**
+ * Returns the previous sibling of the deleted object
+ */
+ PMObject* prevSibling( ) const { return m_pPrevSibling; }
+ /**
+ * Returns true if this object could not be inserted in a move command
+ */
+ bool insertError( ) const { return m_insertError; }
+ /**
+ * Sets the insert error flag
+ */
+ void setInsertError( ) { m_insertError = true; }
+private:
+ PMObject* m_pDeletedObject;
+ PMObject* m_pParent;
+ PMObject* m_pPrevSibling;
+ bool m_insertError;
+};
+
+typedef QPtrList<PMDeleteInfo> PMDeleteInfoList;
+typedef QPtrListIterator<PMDeleteInfo> PMDeleteInfoListIterator;
+
+/**
+ * Command class for removing PMObjects
+ */
+class PMDeleteCommand : public PMCommand
+{
+public:
+ /**
+ * Delete Command that removes the object obj.
+ */
+ PMDeleteCommand( PMObject* obj );
+ /**
+ * Command that deletes a list of PMObjects. The list has to be sorted!
+ */
+ PMDeleteCommand( const PMObjectList& list );
+ /**
+ * Deletes the command. The deleted object will be deleted, if removed
+ */
+ virtual ~PMDeleteCommand( );
+
+ /** */
+ virtual int errorFlags( PMPart* );
+
+protected:
+ /**
+ * Executes the command and stores undo information
+ */
+ virtual void execute( PMCommandManager* theManager );
+ /**
+ * Undo the command
+ */
+ virtual void undo( PMCommandManager* theManager );
+
+private:
+ PMDeleteInfoList m_infoList;
+ bool m_executed, m_firstExecution;
+ PMObjectList m_links;
+ PMObjectList m_linkedDeclares;
+ bool m_linksCreated;
+ QPtrList<PMMemento> m_dataChanges;
+};
+
+#endif
diff --git a/kpovmodeler/pmdensity.cpp b/kpovmodeler/pmdensity.cpp
new file mode 100644
index 00000000..1cc1d638
--- /dev/null
+++ b/kpovmodeler/pmdensity.cpp
@@ -0,0 +1,76 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.tp
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdensity.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmdensityedit.h"
+
+#include <klocale.h>
+
+PMMetaObject* PMDensity::s_pMetaObject = 0;
+PMObject* createNewDensity( PMPart* part )
+{
+ return new PMDensity( part );
+}
+
+PMDensity::PMDensity( PMPart* part )
+ : Base( part )
+{
+}
+
+PMDensity::PMDensity( const PMDensity& d )
+ : Base( d )
+{
+}
+
+PMDensity::~PMDensity( )
+{
+}
+
+PMMetaObject* PMDensity::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Density", Base::metaObject( ),
+ createNewDensity );
+ }
+ return s_pMetaObject;
+}
+
+void PMDensity::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMDensity::description( ) const
+{
+ return i18n( "density" );
+}
+
+
+PMDialogEditBase* PMDensity::editWidget( QWidget* parent ) const
+{
+ return new PMDensityEdit( parent );
+}
+
diff --git a/kpovmodeler/pmdensity.h b/kpovmodeler/pmdensity.h
new file mode 100644
index 00000000..72a76bb7
--- /dev/null
+++ b/kpovmodeler/pmdensity.h
@@ -0,0 +1,76 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMDENSITY_H
+#define PMDENSITY_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+
+/**
+ * Class for povray densities
+ */
+class PMDensity : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMDensity
+ */
+ PMDensity( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMDensity( const PMDensity& d );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMDensity( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMDensity( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /**
+ * Returns a new @ref PMDensityEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmdensity" ); }
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+// enum PMDensityMementoID { };
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmdensityedit.cpp b/kpovmodeler/pmdensityedit.cpp
new file mode 100644
index 00000000..9c7ff732
--- /dev/null
+++ b/kpovmodeler/pmdensityedit.cpp
@@ -0,0 +1,44 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdensityedit.h"
+#include "pmdensity.h"
+#include "pmlinkedit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMDensityEdit::PMDensityEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMDensityEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Density" ) )
+ {
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMDensityEdit: Can't display object\n";
+}
+
+#include "pmdensityedit.moc"
diff --git a/kpovmodeler/pmdensityedit.h b/kpovmodeler/pmdensityedit.h
new file mode 100644
index 00000000..093a750c
--- /dev/null
+++ b/kpovmodeler/pmdensityedit.h
@@ -0,0 +1,58 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMDENSITYEDIT_H
+#define PMDENSITYEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMDensity;
+
+/**
+ * Dialog edit class for @ref PMDensity
+ */
+class PMDensityEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMDensityEdit with parent and name
+ */
+ PMDensityEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+// virtual void createTopWidgets( );
+ /** */
+// virtual void saveContents( );
+
+private:
+ PMDensity* m_pDisplayedObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmdetailobject.cpp b/kpovmodeler/pmdetailobject.cpp
new file mode 100644
index 00000000..eae526cb
--- /dev/null
+++ b/kpovmodeler/pmdetailobject.cpp
@@ -0,0 +1,151 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+#include "pmdetailobject.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmdefaults.h"
+
+/** Default local detail value*/
+const bool c_defaulGlobalDetail = true;
+const int c_defaultLocalDetailLevel = 1;
+
+/** Static global detail */
+int PMDetailObject::s_globalDetailLevel = c_defaultDetailObjectGlobalDetailLevel;
+int PMDetailObject::s_globalDetailKey = 0;
+
+PMMetaObject* PMDetailObject::s_pMetaObject = 0;
+
+PMDefinePropertyClass( PMDetailObject, PMDetailObjectProperty );
+
+PMDetailObject::PMDetailObject( PMPart *part ) : Base( part )
+{
+ m_globalDetail = c_defaulGlobalDetail;
+ m_localDetailLevel = c_defaultLocalDetailLevel;
+}
+
+PMDetailObject::PMDetailObject( const PMDetailObject& o ) : Base( o )
+{
+ m_globalDetail = o.m_globalDetail;
+ m_localDetailLevel = o.m_localDetailLevel;
+}
+
+PMDetailObject::~PMDetailObject()
+{
+}
+
+PMMetaObject* PMDetailObject::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "DetailObject", Base::metaObject( ) );
+ s_pMetaObject->addProperty(
+ new PMDetailObjectProperty( "globalDetail", &PMDetailObject::setGlobalDetail, &PMDetailObject::globalDetail ) );
+ s_pMetaObject->addProperty(
+ new PMDetailObjectProperty( "localDetailLevel", &PMDetailObject::setLocalDetailLevel, &PMDetailObject::localDetailLevel ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMDetailObject::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMDetailObject::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "global_detail", m_globalDetail );
+ e.setAttribute( "local_detail_level", m_localDetailLevel );
+ Base::serialize( e, doc );
+}
+
+void PMDetailObject::readAttributes( const PMXMLHelper& h )
+{
+ m_globalDetail = h.boolAttribute( "global_detail", c_defaulGlobalDetail );
+ m_localDetailLevel = h.intAttribute( "local_detail_level", c_defaultLocalDetailLevel );
+ Base::readAttributes( h );
+}
+
+int PMDetailObject::displayDetail( ) const
+{
+ if( m_globalDetail )
+ return s_globalDetailLevel;
+ else
+ return m_localDetailLevel;
+}
+
+void PMDetailObject::setGlobalDetail( bool yes )
+{
+ if( m_globalDetail != yes )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMGlobalDetailID, m_globalDetail );
+ m_globalDetail = yes;
+ setViewStructureChanged( );
+ }
+}
+
+void PMDetailObject::setLocalDetailLevel( int level )
+{
+ if( m_localDetailLevel != level )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLocalDetailLevelID, m_localDetailLevel );
+ m_localDetailLevel = level;
+ setViewStructureChanged( );
+ }
+}
+
+void PMDetailObject::setGlobalDetailLevel( int level )
+{
+ if( s_globalDetailLevel != level )
+ {
+ ++s_globalDetailKey;
+ s_globalDetailLevel = level;
+ }
+}
+
+void PMDetailObject::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMGlobalDetailID:
+ setGlobalDetail( data->boolData( ) );
+ break;
+ case PMLocalDetailLevelID:
+ setLocalDetailLevel( data->intData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMDetailObject::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmdetailobject.h b/kpovmodeler/pmdetailobject.h
new file mode 100644
index 00000000..7994cdff
--- /dev/null
+++ b/kpovmodeler/pmdetailobject.h
@@ -0,0 +1,115 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDETAILOBJECT_H
+#define PMDETAILOBJECT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+
+class PMDetailObject : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+public:
+ /**
+ * Creates an empty PMDetailObject
+ */
+ PMDetailObject( PMPart* part );
+ /**
+ * Copy constrctor
+ */
+ PMDetailObject( const PMDetailObject& o );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMDetailObject();
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns true if the object has detail settings
+ */
+ virtual bool hasDisplayDetail( ) const { return false; }
+
+ /**
+ * Returns the current display detail
+ */
+ int displayDetail( ) const;
+
+ /**
+ * Sets the global detail flag
+ */
+ void setGlobalDetail( bool yes );
+ /**
+ * Returns the global detail flag
+ */
+ bool globalDetail( ) const { return m_globalDetail; }
+
+ /**
+ * Sets the local detail level
+ */
+ void setLocalDetailLevel( int level );
+ /**
+ * Returns the local detail level
+ */
+ int localDetailLevel( ) const { return m_localDetailLevel; }
+
+ /**
+ * Sets the global detail level
+ */
+ static void setGlobalDetailLevel( int level );
+ /**
+ * Returns the global detail level
+ */
+ static int globalDetailLevel( ) { return s_globalDetailLevel; }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+protected:
+ /**
+ * Global parameter key
+ */
+ static int globalDetailKey( ) { return s_globalDetailKey; }
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMNamedObjectMementoID { PMGlobalDetailID, PMLocalDetailLevelID };
+
+ bool m_globalDetail;
+ int m_localDetailLevel;
+
+ static int s_globalDetailKey;
+ static int s_globalDetailLevel;
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmdetailobjectedit.cpp b/kpovmodeler/pmdetailobjectedit.cpp
new file mode 100644
index 00000000..d42c668c
--- /dev/null
+++ b/kpovmodeler/pmdetailobjectedit.cpp
@@ -0,0 +1,122 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+#include "pmdetailobjectedit.h"
+#include "pmdetailobject.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <klocale.h>
+
+PMDetailObjectEdit::PMDetailObjectEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMDetailObjectEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout = new QHBoxLayout( topLayout( ) );
+ m_pGlobalDetail = new QCheckBox( i18n( "Global detail" ), this );
+ m_pLocalDetailLevelLabel = new QLabel( i18n( "Detail level:" ), this );
+ m_pLocalDetailLevel = new QComboBox( this );
+ m_pLocalDetailLevel->insertItem( i18n( "Very Low" ) );
+ m_pLocalDetailLevel->insertItem( i18n( "Low" ) );
+ m_pLocalDetailLevel->insertItem( i18n( "Medium" ) );
+ m_pLocalDetailLevel->insertItem( i18n( "High" ) );
+ m_pLocalDetailLevel->insertItem( i18n( "Very High" ) );
+
+ layout->addWidget( m_pGlobalDetail );
+ layout->addWidget( m_pLocalDetailLevelLabel );
+ layout->addWidget( m_pLocalDetailLevel );
+ layout->addStretch( );
+
+ connect( m_pGlobalDetail, SIGNAL( clicked( ) ), SLOT( slotGlobalDetailClicked( ) ) );
+ connect( m_pLocalDetailLevel, SIGNAL( activated( int ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMDetailObjectEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "DetailObject" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMDetailObject* ) o;
+
+ if( !m_pDisplayedObject->hasDisplayDetail( ) )
+ {
+ m_pGlobalDetail->hide( );
+ m_pLocalDetailLevelLabel->hide( );
+ m_pLocalDetailLevel->hide( );
+ }
+
+ if( m_pDisplayedObject->globalDetail( ) )
+ {
+ m_pGlobalDetail->setChecked( true );
+ m_pLocalDetailLevelLabel->setEnabled( false );
+ m_pLocalDetailLevel->setEnabled( false );
+ }
+ else
+ {
+ m_pGlobalDetail->setChecked( false );
+ m_pLocalDetailLevelLabel->setEnabled( !readOnly );
+ m_pLocalDetailLevel->setEnabled( !readOnly );
+ }
+ m_pGlobalDetail->setEnabled( !readOnly );
+
+ m_pLocalDetailLevel->setCurrentItem( m_pDisplayedObject->localDetailLevel( ) - 1 );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMNamedObjectEdit: Can't display object\n";
+}
+
+void PMDetailObjectEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setGlobalDetail( m_pGlobalDetail->isChecked( ) );
+ m_pDisplayedObject->setLocalDetailLevel( m_pLocalDetailLevel->currentItem( ) + 1 );
+ }
+}
+
+bool PMDetailObjectEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+void PMDetailObjectEdit::slotGlobalDetailClicked( )
+{
+ if( m_pGlobalDetail->isChecked( ) )
+ {
+ m_pLocalDetailLevelLabel->setEnabled( false );
+ m_pLocalDetailLevel->setEnabled( false );
+ }
+ else
+ {
+ bool readOnly = m_pDisplayedObject->isReadOnly( );
+ m_pLocalDetailLevelLabel->setEnabled( !readOnly );
+ m_pLocalDetailLevel->setEnabled( !readOnly );
+ }
+ emit dataChanged( );
+}
+
+#include "pmdetailobjectedit.moc"
diff --git a/kpovmodeler/pmdetailobjectedit.h b/kpovmodeler/pmdetailobjectedit.h
new file mode 100644
index 00000000..7a585034
--- /dev/null
+++ b/kpovmodeler/pmdetailobjectedit.h
@@ -0,0 +1,68 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+#ifndef PMDETAILOBJECTEDIT_H
+#define PMDETAILOBJECTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobjectedit.h"
+
+class PMDetailObject;
+class QCheckBox;
+class QLabel;
+class QComboBox;
+
+/**
+ * Dialog edit class for @ref PMNamedObject.
+ */
+class PMDetailObjectEdit : public PMNamedObjectEdit
+{
+ Q_OBJECT
+ typedef PMNamedObjectEdit Base;
+public:
+ /**
+ * Creates a PMNamedObjectEdit with parent and name
+ */
+ PMDetailObjectEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private slots:
+ void slotGlobalDetailClicked( );
+
+private:
+ PMDetailObject* m_pDisplayedObject;
+ QCheckBox* m_pGlobalDetail;
+ QLabel* m_pLocalDetailLevelLabel;
+ QComboBox* m_pLocalDetailLevel;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmdialogeditbase.cpp b/kpovmodeler/pmdialogeditbase.cpp
new file mode 100644
index 00000000..9defd762
--- /dev/null
+++ b/kpovmodeler/pmdialogeditbase.cpp
@@ -0,0 +1,558 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdialogeditbase.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qvbox.h>
+#include <qbuffer.h>
+#include <qptrdict.h>
+#include <kdialog.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "pmpart.h"
+#include "pmdefaults.h"
+#include "pmpovrayrenderwidget.h"
+#include "pmpovrayoutputwidget.h"
+#include "pmpovray31format.h"
+#include "pmserializer.h"
+#include "pmcolor.h"
+#include "pmrecursiveobjectiterator.h"
+#include "pmdeclare.h"
+
+#include "pmdebug.h"
+
+int PMDialogEditBase::s_previewSize = c_defaultTPSize;
+bool PMDialogEditBase::s_showSphere = c_defaultTPShowSphere;
+bool PMDialogEditBase::s_showCylinder = c_defaultTPShowCylinder;
+bool PMDialogEditBase::s_showBox = c_defaultTPShowBox;
+bool PMDialogEditBase::s_previewAA = c_defaultTPAA;
+int PMDialogEditBase::s_previewAADepth = c_defaultTPAADepth;
+double PMDialogEditBase::s_previewAAThreshold = c_defaultTPAAThreshold;
+bool PMDialogEditBase::s_showFloor = c_defaultTPShowFloor;
+bool PMDialogEditBase::s_showWall = c_defaultTPShowWall;
+QColor PMDialogEditBase::s_wallColor1 = c_defaultTPWallColor1;
+QColor PMDialogEditBase::s_wallColor2 = c_defaultTPWallColor2;
+QColor PMDialogEditBase::s_floorColor1 = c_defaultTPFloorColor1;
+QColor PMDialogEditBase::s_floorColor2 = c_defaultTPFloorColor2;
+bool PMDialogEditBase::s_previewLocal = false;
+double PMDialogEditBase::s_previewGamma = c_defaultTPGamma;
+
+
+/** Constants for texture preview */
+const QString c_wallCode = QString(
+ "plane { <0, 0, -1>, -2\n"
+ " pigment { checker %1 %2\n"
+ " scale <0.5, 0.5, 0.5>\n"
+ " translate <0.5, 0, 0>\n"
+ " }\n"
+ "}\n" );
+const QString c_floorCode = QString(
+ "plane { <0, 1, 0>, 0\n"
+ " pigment { checker %1 %2\n"
+ " scale <0.5, 0.5, 0.5>\n"
+ " }\n"
+ "}\n" );
+const QString c_lightCode = QString(
+ "light_source { <-2.5, 3, -1.5>, rgb <1, 1, 1> }\n"
+ "light_source { <3, 3, -3>, rgb <0.6, 0.6, 0.6> shadowless }\n" );
+
+
+const QString c_cameraCode[3] = {
+ QString( "camera { location <-1, 1.25, -2> right <1, 0, 0>\n"
+ " look_at <0.0, 0.5, 0> angle 45 }\n" ),
+ QString( "camera { location <-1, 2, -3> right <1, 0, 0>\n"
+ " look_at <0.0, 1, 0> angle 45 }\n" ),
+ QString( "camera { location <-2, 2.5, -4> right <1, 0, 0>\n"
+ " look_at <0.0, 1.5, 0> angle 45 }\n" )
+};
+const QString c_sphereCode = QString(
+ "sphere { <0, 0.5, 0>, 0.5 translate <0, %1, 0> }\n" );
+const QString c_cylinderCode = QString(
+ "cylinder { <0, 0, 0>, <0, 1, 0>, 0.5 translate <0, %1, 0> }\n" );
+const QString c_boxCode = QString(
+ "box { <-0.5, 0, -0.5>, <0.5, 1, 0.5> translate <0, %1, 0> }\n" );
+const QString c_globalSettingsCode = QString(
+ "global_settings { assumed_gamma %1 }\n" );
+
+PMDialogEditBase::PMDialogEditBase( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ m_pDisplayedObject = 0;
+ m_pPart = 0;
+
+ m_pTexturePreviewWidget = 0;
+ m_pOutputWidget = 0;
+ m_pRenderWidget = 0;
+ m_pRenderFrame = 0;
+ m_pPreviewLocalBox = 0;
+ m_pPreviewButton = 0;
+ m_pOutputButton = 0;
+}
+
+PMDialogEditBase::~PMDialogEditBase( )
+{
+ if( m_pOutputWidget )
+ delete m_pOutputWidget;
+}
+
+void PMDialogEditBase::createWidgets( )
+{
+ m_pTopLayout = new QBoxLayout( this, QBoxLayout::TopToBottom,
+ KDialog::spacingHint( ) );
+
+ createTopWidgets( );
+ createBottomWidgets( );
+
+ m_pTopLayout->addStretch( );
+ m_pTopLayout->activate( );
+}
+
+void PMDialogEditBase::createBottomWidgets( )
+{
+ m_pTexturePreviewWidget = new QWidget( this );
+ m_pTexturePreviewWidget->hide( );
+ m_pTopLayout->addWidget( m_pTexturePreviewWidget );
+}
+
+bool PMDialogEditBase::saveData( )
+{
+ if( isDataValid( ) )
+ {
+ saveContents( );
+ return true;
+ }
+ return false;
+}
+
+void PMDialogEditBase::saveContents( )
+{
+}
+
+void PMDialogEditBase::displayObject( PMObject* o )
+{
+ bool newObject = ( m_pDisplayedObject != o );
+ m_pDisplayedObject = o;
+ PMObject* global;
+ PMObject* local;
+
+ // Is object a full texture or inside a full texture
+ findTextures( global, local );
+ if( global )
+ {
+ // is the preview widget created?
+ if( !m_pRenderWidget )
+ {
+ QVBoxLayout* vl = new QVBoxLayout( m_pTexturePreviewWidget, 0,
+ KDialog::spacingHint( ) );
+ vl->addSpacing( 10 );
+ QFrame* hline = new QFrame( m_pTexturePreviewWidget );
+ hline->setFrameStyle( QFrame::HLine | QFrame::Plain );
+ hline->setLineWidth( 1 );
+ vl->addWidget( hline );
+ vl->addWidget( new QLabel( i18n( "Texture preview:" ), m_pTexturePreviewWidget ) );
+ m_pRenderFrame = new QVBox( m_pTexturePreviewWidget );
+ m_pRenderFrame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
+ m_pRenderFrame->setLineWidth( 2 );
+ m_pRenderFrame->hide( );
+ vl->addWidget( m_pRenderFrame );
+
+ m_pRenderWidget = new PMPovrayRenderWidget( m_pRenderFrame );
+ connect( m_pRenderWidget, SIGNAL( finished( int ) ),
+ SLOT( slotPreviewFinished( int ) ) );
+ m_pPreviewLocalBox = new QCheckBox( i18n( "local" ), m_pTexturePreviewWidget );
+ m_pPreviewLocalBox->setChecked( s_previewLocal );
+ connect( m_pPreviewLocalBox, SIGNAL( toggled( bool ) ),
+ SLOT( slotPreviewLocal( bool ) ) );
+ vl->addWidget( m_pPreviewLocalBox );
+
+ QHBoxLayout* hl = new QHBoxLayout( vl );
+ m_pPreviewButton = new QPushButton( i18n( "&Preview" ), m_pTexturePreviewWidget );
+ hl->addWidget( m_pPreviewButton );
+ connect( m_pPreviewButton, SIGNAL( clicked( ) ),
+ SLOT( slotTexturePreview( ) ) );
+ m_pOutputButton = new QPushButton( i18n( "Povray Output" ), m_pTexturePreviewWidget );
+ hl->addWidget( m_pOutputButton );
+ connect( m_pOutputButton, SIGNAL( clicked( ) ),
+ SLOT( slotPovrayOutput( ) ) );
+ hl->addStretch( 1 );
+
+ m_pOutputWidget = new PMPovrayOutputWidget( );
+ connect( m_pRenderWidget, SIGNAL( povrayMessage( const QString& ) ),
+ m_pOutputWidget, SLOT( slotText( const QString& ) ) );
+ }
+
+ m_pTexturePreviewWidget->show( );
+ if( newObject )
+ m_pRenderFrame->hide( );
+ m_pPreviewLocalBox->setEnabled( local != global );
+ m_pPreviewButton->setEnabled( true );
+ }
+ else
+ {
+ // is the preview widget created?
+ if( m_pPreviewButton )
+ m_pPreviewButton->setEnabled( false );
+ m_pTexturePreviewWidget->hide( );
+ }
+}
+
+void PMDialogEditBase::setHelp( const QString& anchor )
+{
+ m_helpTopic = anchor;
+}
+
+void PMDialogEditBase::redisplay( )
+{
+ if( m_pDisplayedObject )
+ displayObject( m_pDisplayedObject );
+}
+
+void PMDialogEditBase::setCheckBox( QCheckBox* box, PMThreeState state )
+{
+ switch( state )
+ {
+ case PMTrue:
+ box->setChecked( true );
+ break;
+ case PMFalse:
+ box->setChecked( false );
+ break;
+ case PMUnspecified:
+ box->setNoChange( );
+ break;
+ }
+}
+
+PMThreeState PMDialogEditBase::checkBoxState( QCheckBox* box )
+{
+ PMThreeState st = PMTrue;
+ switch( box->state( ) )
+ {
+ case QCheckBox::On:
+ st = PMTrue;
+ break;
+ case QCheckBox::Off:
+ st = PMFalse;
+ break;
+ case QCheckBox::NoChange:
+ st = PMUnspecified;
+ break;
+ }
+ return st;
+}
+
+void PMDialogEditBase::setPreviewSize( int size )
+{
+ if( ( size >= 10 ) && ( size <= 400 ) )
+ s_previewSize = size;
+}
+
+void PMDialogEditBase::setPreviewAADepth( int d )
+{
+ if( ( d >= 1 ) && ( d <= 9 ) )
+ s_previewAADepth = d;
+}
+
+void PMDialogEditBase::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "TexturePreview" );
+ cfg->writeEntry( "Size", s_previewSize );
+ cfg->writeEntry( "showSphere", s_showSphere );
+ cfg->writeEntry( "showCylinder", s_showCylinder );
+ cfg->writeEntry( "showBox", s_showBox );
+ cfg->writeEntry( "AA", s_previewAA );
+ cfg->writeEntry( "AADepth", s_previewAADepth );
+ cfg->writeEntry( "AAThreshold", s_previewAAThreshold );
+ cfg->writeEntry( "showWall", s_showWall );
+ cfg->writeEntry( "showFloor", s_showFloor );
+ cfg->writeEntry( "WallColor1", s_wallColor1 );
+ cfg->writeEntry( "WallColor2", s_wallColor2 );
+ cfg->writeEntry( "FloorColor1", s_floorColor1 );
+ cfg->writeEntry( "FloorColor2", s_floorColor2 );
+ cfg->writeEntry( "Gamma", s_previewGamma );
+}
+
+void PMDialogEditBase::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "TexturePreview" );
+ setPreviewSize( cfg->readNumEntry( "Size", s_previewSize ) );
+ s_showSphere = cfg->readBoolEntry( "showSphere", s_showSphere );
+ s_showCylinder = cfg->readBoolEntry( "showCylinder", s_showCylinder );
+ s_showBox = cfg->readBoolEntry( "showBox", s_showBox );
+ s_previewAA = cfg->readBoolEntry( "AA", s_previewAA );
+ setPreviewAADepth( cfg->readNumEntry( "AADepth", s_previewAADepth ) );
+ s_previewAAThreshold = cfg->readDoubleNumEntry( "AAThreshold", s_previewAAThreshold );
+ s_showWall = cfg->readBoolEntry( "showWall", s_showWall );
+ s_showFloor = cfg->readBoolEntry( "showFloor", s_showFloor );
+ s_wallColor1 = cfg->readColorEntry( "WallColor1", &s_wallColor1 );
+ s_wallColor2 = cfg->readColorEntry( "WallColor2", &s_wallColor2 );
+ s_floorColor1 = cfg->readColorEntry( "FloorColor1", &s_floorColor1 );
+ s_floorColor2 = cfg->readColorEntry( "FloorColor2", &s_floorColor2 );
+ s_previewGamma = cfg->readDoubleNumEntry( "Gamma", s_previewGamma );
+}
+
+void PMDialogEditBase::findTextures( PMObject*& global, PMObject*& local ) const
+{
+ PMObject* o;
+ global = 0;
+ local = 0;
+
+ for( o = m_pDisplayedObject; o; o = o->parent( ) )
+ {
+ if( o->type( ) == "Material" || o->type( ) == "Interior" ||
+ o->type( ) == "Texture" || o->type( ) == "Pigment" ||
+ o->type( ) == "InteriorTexture" )
+ {
+ if( !local )
+ local = o;
+ global = o;
+ }
+ else if( o->type( ) == "Declare" )
+ {
+ PMDeclare* d = ( PMDeclare* ) o;
+ if( d->declareType( ) == "Interior" ||
+ d->declareType( ) == "Pigment" ||
+ d->declareType( ) == "Material" )
+ {
+ if( !local || ( local == global ) )
+ local = o;
+ global = o;
+ }
+ else if( d->declareType( ) == "Texture" ||
+ d->declareType( ) == "InteriorTexture" )
+ {
+ if( o->countChildren( ) > 1 )
+ {
+ if( !local )
+ local = o;
+ }
+ else
+ if( !local || ( local == global ) )
+ local = o;
+ global = o;
+ }
+ }
+ }
+}
+
+void PMDialogEditBase::slotTexturePreview( )
+{
+ PMObject* o;
+ PMObject* local = 0;
+ PMObject* global = 0;
+
+ if( !m_pRenderWidget )
+ return;
+
+ findTextures( global, local );
+ if( local )
+ {
+ emit aboutToRender( );
+
+ if( global == local )
+ o = global;
+ else
+ {
+ if( m_pPreviewLocalBox->isChecked( ) )
+ o = local;
+ else
+ o = global;
+ }
+
+ // ensure at least one object will be rendered.
+ if( !( s_showSphere || s_showCylinder || s_showBox ) )
+ s_showSphere = true;
+
+ int numObjects = 0;
+ QByteArray scene;
+ QBuffer buffer( scene );
+ buffer.open( IO_WriteOnly );
+ QTextStream str( &buffer );
+ PMPovray31Format format;
+ PMSerializer* dev = format.newSerializer( &buffer );
+ PMRenderMode mode;
+ PMObjectList neededDeclares, objectsToCheck;
+ QPtrDict<PMObject> objectsToSerialize( 101 );
+ PMObject* link;
+
+ // find needed declares
+ objectsToCheck.append( o );
+ do
+ {
+ PMObjectListIterator it( objectsToCheck );
+ for( ; it.current( ); ++it )
+ {
+ PMRecursiveObjectIterator rit( it.current( ) );
+ for( ; rit.current( ); ++rit )
+ {
+ link = rit.current( )->linkedObject( );
+ if( link )
+ if( !neededDeclares.containsRef( link ) )
+ if( !objectsToSerialize.find( link ) )
+ neededDeclares.append( link );
+ }
+ objectsToSerialize.insert( it.current( ), it.current( ) );
+ }
+
+ objectsToCheck = neededDeclares;
+ neededDeclares.clear( );
+ }
+ while( objectsToCheck.count( ) > 0 );
+
+ // serialize all needed declares in the right order
+ int numDeclares = objectsToSerialize.count( );
+ if( numDeclares > 0 )
+ {
+ PMObject* otr = o;
+
+ // find the scene
+ while( otr->parent( ) ) otr = otr->parent( );
+
+ for( otr = otr->firstChild( ); otr && ( numDeclares > 0 );
+ otr = otr->nextSibling( ) )
+ {
+ if( otr->type( ) == "Declare" )
+ {
+ if( objectsToSerialize.find( otr ) )
+ {
+ dev->serialize( otr );
+ numDeclares--;
+ }
+ }
+ }
+ str << "\n\n";
+ }
+ // if the previewed texture is a declare, serialize it
+ if( o->type( ) == "Declare" )
+ dev->serialize( o );
+
+ // build the preview scene
+ str << "union {\n";
+ if( s_showBox )
+ {
+ str << c_boxCode.arg( numObjects );
+ numObjects++;
+ }
+ if( s_showCylinder )
+ {
+ str << c_cylinderCode.arg( numObjects );
+ numObjects++;
+ }
+ if( s_showSphere )
+ {
+ str << c_sphereCode.arg( numObjects );
+ numObjects++;
+ }
+
+ // serialize the texture
+ if( o->type( ) == "Declare" )
+ {
+ PMDeclare* dec = ( PMDeclare* ) o;
+ if( dec->declareType( ) == "Interior" )
+ str << "interior { ";
+ else if( dec->declareType( ) == "Texture" )
+ str << "texture { ";
+ else if( dec->declareType( ) == "Pigment" )
+ str << "pigment { ";
+ else if( dec->declareType( ) == "InteriorTexture" )
+ str << "interior_texture { ";
+ else if( dec->declareType( ) == "Material" )
+ str << "material { ";
+ else
+ kdError( PMArea ) << "Unhandled declare type in "
+ "PMDialogEditBase::slotTexturePreview\n";
+
+ str << dec->id( );
+ str << " }\n";
+ }
+ else
+ dev->serialize( o );
+ str << "}\n";
+
+ PMColor c1, c2;
+ if( s_showWall )
+ {
+ c1 = PMColor( s_wallColor1 );
+ c2 = PMColor( s_wallColor2 );
+ str << c_wallCode.arg( c1.serialize( true ) ).arg( c2.serialize( true ) );
+ }
+ if( s_showFloor )
+ {
+ c1 = PMColor( s_floorColor1 );
+ c2 = PMColor( s_floorColor2 );
+ str << c_floorCode.arg( c1.serialize( true ) ).arg( c2.serialize( true ) );
+ }
+
+ str << c_lightCode;
+ str << c_cameraCode[numObjects-1];
+ str << c_globalSettingsCode.arg( s_previewGamma );
+
+ // Set the render mode
+ mode.setHeight( s_previewSize );
+ mode.setWidth( s_previewSize );
+ mode.setAntialiasing( s_previewAA );
+ mode.setAntialiasingThreshold( s_previewAAThreshold );
+ mode.setAntialiasingDepth( s_previewAADepth );
+
+ m_pRenderFrame->show( );
+ m_pRenderFrame->setFixedSize( s_previewSize + m_pRenderFrame->frameWidth( ) * 2,
+ s_previewSize + m_pRenderFrame->frameWidth( ) * 2 );
+ m_pRenderFrame->updateGeometry( );
+ m_pTexturePreviewWidget->layout( )->activate( );
+ emit sizeChanged( );
+ m_pOutputWidget->slotClear( );
+ m_pRenderWidget->render( scene, mode, m_pPart->url( ) );
+
+ delete dev;
+ }
+}
+
+void PMDialogEditBase::slotPreviewLocal( bool on )
+{
+ s_previewLocal = on;
+}
+
+void PMDialogEditBase::slotPreviewFinished( int exitStatus )
+{
+ if( exitStatus != 0 )
+ {
+ KMessageBox::error( this, i18n( "Povray exited abnormally with "
+ "exit code %1.\n"
+ "See the povray output for details." )
+ .arg( exitStatus ) );
+ }
+ else if( m_pRenderWidget->povrayOutput( ).contains( "ERROR" ) )
+ {
+ KMessageBox::error( this, i18n( "There were errors while rendering.\n"
+ "See the povray output for details." ) );
+ }
+}
+
+void PMDialogEditBase::slotPovrayOutput( )
+{
+ if( m_pOutputWidget )
+ m_pOutputWidget->show( );
+}
+
+#include "pmdialogeditbase.moc"
diff --git a/kpovmodeler/pmdialogeditbase.h b/kpovmodeler/pmdialogeditbase.h
new file mode 100644
index 00000000..547946f5
--- /dev/null
+++ b/kpovmodeler/pmdialogeditbase.h
@@ -0,0 +1,356 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMDIALOGEDITBASE_H
+#define PMDIALOGEDITBASE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qstring.h>
+
+#include "pmobject.h"
+
+class QBoxLayout;
+class QCheckBox;
+class QLayout;
+class QPushButton;
+class QVBox;
+class KConfig;
+class PMPart;
+class PMPovrayRenderWidget;
+class PMPovrayOutputWidget;
+
+/**
+ * Base class for all widgets for editing object attributes.
+ *
+ * Ensures a consistent layout for all widgets. Widgets should not
+ * created within the constructor, but with the functions @ref createTopWidgets
+ * and @ref createBottomWidgets.
+ *
+ * Each subclass uses the functionality of the base class. For example all
+ * widgets for solid objects have the same base class that shows attributes
+ * of solid objects. Subclasses like the widget for the box object add their
+ * object specific controls.
+ */
+class PMDialogEditBase : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a new PMDialogEditBase widget objectType is
+ * @ref PMObject->description( ).
+ *
+ * No widgets are created within the constructor! You have to call
+ * @ref createWidgets after creating a new edit widget.
+ */
+ PMDialogEditBase( QWidget* parent, const char* name = 0 );
+ /**
+ * Destructor
+ */
+ virtual ~PMDialogEditBase( );
+
+ /**
+ * Creates child widgets.
+ *
+ * This function is necessary because virtual functions do not work
+ * properly inside the constructor.
+ *
+ * Calls @ref createTopWidgets and @ref createBottomWidgets
+ */
+ void createWidgets( );
+
+ /**
+ * Displays the object o.
+ * Always call displayObject( ) of the base class after displaying the
+ * objects data
+ */
+ virtual void displayObject( PMObject* o );
+
+ /**
+ * returns a pointer to the displayed object
+ */
+ PMObject* displayedObject( ) const { return m_pDisplayedObject; }
+
+ /**
+ * Function that is called, when the "Apply" button is pressed.
+ *
+ * Returns true if successful
+ */
+ bool saveData( );
+
+ /**
+ * Called, when the contents have to be checked.
+ *
+ * Display an error message and return false, if the data is invalid.
+ * Otherwise return isDataValid( ) of the base class.
+ */
+ virtual bool isDataValid( ) { return true; }
+
+ /**
+ * Returns the help topic
+ */
+ const QString& helpTopic( ) { return m_helpTopic; }
+
+ /**
+ * Discards changes and redisplays the object
+ */
+ void redisplay( );
+
+ /**
+ * Called when the control point selection has changed
+ */
+ virtual void updateControlPointSelection( ) { };
+
+ /**
+ * Sets the check box to state s
+ */
+ static void setCheckBox( QCheckBox* box, PMThreeState s );
+ /**
+ * Gets the state of the checkbox
+ */
+ static PMThreeState checkBoxState( QCheckBox* box );
+
+ /**
+ * Sets the part
+ */
+ void setPart( PMPart* p ) { m_pPart = p; }
+ /**
+ * Returns the part
+ */
+ PMPart* part( ) const { return m_pPart; }
+
+ /**
+ * Returns the size of the texture preview widget
+ */
+ static int previewSize( ) { return s_previewSize; }
+ /**
+ * Sets the texture preview size
+ */
+ static void setPreviewSize( int size );
+ /**
+ * Returns true if a sphere should be renderend
+ */
+ static bool previewShowSphere( ) { return s_showSphere; }
+ /**
+ * Enable/disable the sphere in the texture preview widget
+ */
+ static void previewShowSphere( bool show ) { s_showSphere = show; }
+ /**
+ * Returns true if a cylinder should be renderend
+ */
+ static bool previewShowCylinder( ) { return s_showCylinder; }
+ /**
+ * Enable/disable the cylinder in the texture preview widget
+ */
+ static void previewShowCylinder( bool show ) { s_showCylinder = show; }
+ /**
+ * Returns true if a box should be renderend
+ */
+ static bool previewShowBox( ) { return s_showBox; }
+ /**
+ * Enable/disable the box in the texture preview widget
+ */
+ static void previewShowBox( bool show ) { s_showBox = show; }
+
+ /**
+ * Returns true if AA is enabled
+ */
+ static bool isPreviewAAEnabled( ) { return s_previewAA; }
+ /**
+ * Enables/disables AA
+ */
+ static void setPreviewAAEnabled( bool enable ) { s_previewAA = enable; }
+ /**
+ * Returns the AA depth
+ */
+ static int previewAADepth( ) { return s_previewAADepth; }
+ /**
+ * Sets the AA depth
+ */
+ static void setPreviewAADepth( int d );
+ /**
+ * Returns the AA threshold
+ */
+ static double previewAAThreshold( ) { return s_previewAAThreshold; }
+ /**
+ * Sets the AA threshold
+ */
+ static void setPreviewAAThreshold( double t ) { s_previewAAThreshold = t; }
+
+ /**
+ * Returns true if the floor should be rendered
+ */
+ static bool previewShowFloor( ) { return s_showFloor; }
+ /**
+ * Enables/disables the floor
+ */
+ static void previewShowFloor( bool show ) { s_showFloor = show; }
+ /**
+ * Returns true if the wall should be rendered
+ */
+ static bool previewShowWall( ) { return s_showWall; }
+ /**
+ * Enables/disables the wall
+ */
+ static void previewShowWall( bool show ) { s_showWall = show; }
+ /**
+ * Returns the first wall color
+ */
+ static QColor previewWallColor1( ) { return s_wallColor1; }
+ /**
+ * Sets the first wall color
+ */
+ static void setPreviewWallColor1( const QColor& c ) { s_wallColor1 = c; }
+ /**
+ * Returns the second wall color
+ */
+ static QColor previewWallColor2( ) { return s_wallColor2; }
+ /**
+ * Sets the second wall color
+ */
+ static void setPreviewWallColor2( const QColor& c ) { s_wallColor2 = c; }
+ /**
+ * Returns the first floor color
+ */
+ static QColor previewFloorColor1( ) { return s_floorColor1; }
+ /**
+ * Sets the first floor color
+ */
+ static void setPreviewFloorColor1( const QColor& c ) { s_floorColor1 = c; }
+ /**
+ * Returns the second floor color
+ */
+ static QColor previewFloorColor2( ) { return s_floorColor2; }
+ /**
+ * Sets the second floor color
+ */
+ static void setPreviewFloorColor2( const QColor& c ) { s_floorColor2 = c; }
+ /**
+ * Returns the local flag for texture preview
+ */
+ static bool previewLocal( ) { return s_previewLocal; }
+ /**
+ * Sets the local flag
+ */
+ static void setPreviewLocal( bool l ) { s_previewLocal = l; }
+ /**
+ * Returns the gamma value for the texture preview
+ */
+ static double previewGamma( ) { return s_previewGamma; }
+ /**
+ * Sets the gamma value for the texture preview
+ */
+ static void setPreviewGamma( double g ) { s_previewGamma = g; }
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+protected:
+ /**
+ * Sets the help topic
+ * @param anchor Defined anchor in your docbook sources
+ */
+ void setHelp( const QString& anchor );
+
+ /**
+ * Create widgets here, that should be placed on top of the widgets
+ * of the sub class.
+ *
+ * First call the function of the base class, then create and append
+ * the widgets to the top layout.
+ */
+ virtual void createTopWidgets( ) { };
+
+ /**
+ * Create widgets here, that should be placed under the widgets
+ * of the sub class.
+ *
+ * First create and append the widgets to the top layout, then
+ * call the function of the base class
+ */
+ virtual void createBottomWidgets( );
+
+ /**
+ * Save here the class specific data and call saveContents( )
+ * of the base class
+ */
+ virtual void saveContents( );
+
+ /**
+ * Returns a pointer to the top layout
+ */
+ QBoxLayout* topLayout( ) const { return m_pTopLayout; }
+
+protected slots:
+ void slotTexturePreview( );
+ void slotPreviewLocal( bool on );
+ void slotPreviewFinished( int exitStatus );
+ void slotPovrayOutput( );
+
+signals:
+ /**
+ * Emit this, if data has changed
+ */
+ void dataChanged( );
+ /**
+ * Emit this, if the size of the widget has changed
+ */
+ void sizeChanged( );
+ /**
+ * Emit this, if the control point selection has changed
+ */
+ void controlPointSelectionChanged( );
+ /**
+ * Emit this signal, before the displayed object or texture is rendered
+ */
+ void aboutToRender( );
+private:
+ void findTextures( PMObject*& global, PMObject*& local ) const;
+
+ PMObject* m_pDisplayedObject;
+ QBoxLayout* m_pTopLayout;
+ QString m_helpTopic;
+ PMPart* m_pPart;
+ QWidget* m_pTexturePreviewWidget;
+ PMPovrayRenderWidget* m_pRenderWidget;
+ PMPovrayOutputWidget* m_pOutputWidget;
+ QVBox* m_pRenderFrame;
+ QCheckBox* m_pPreviewLocalBox;
+ QPushButton* m_pPreviewButton;
+ QPushButton* m_pOutputButton;
+
+ static int s_previewSize;
+ static bool s_showSphere;
+ static bool s_showCylinder;
+ static bool s_showBox;
+ static bool s_previewAA;
+ static int s_previewAADepth;
+ static double s_previewAAThreshold;
+ static bool s_showFloor;
+ static bool s_showWall;
+ static QColor s_wallColor1, s_wallColor2;
+ static QColor s_floorColor1, s_floorColor2;
+ static bool s_previewLocal;
+ static double s_previewGamma;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmdialogview.cpp b/kpovmodeler/pmdialogview.cpp
new file mode 100644
index 00000000..f88a0272
--- /dev/null
+++ b/kpovmodeler/pmdialogview.cpp
@@ -0,0 +1,441 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdialogview.h"
+#include "pmdialogeditbase.h"
+#include "pmallobjects.h"
+#include "pmdebug.h"
+#include "pmfactory.h"
+#include "pmdatachangecommand.h"
+#include "pmpart.h"
+#include "pmdocumentationmap.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kprocess.h>
+#include <kiconloader.h>
+#include <krun.h>
+#include <kstdguiitem.h>
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qscrollview.h>
+#include <qlabel.h>
+
+PMDialogEditContent::PMDialogEditContent( QWidget* parent, const char* name )
+ : QScrollView( parent, name )
+{
+ m_pContents = 0;
+ setVScrollBarMode( AlwaysOff );
+ setHScrollBarMode( AlwaysOff );
+ setFrameStyle( Panel | Sunken );
+ setLineWidth( 1 );
+ setResizePolicy( Manual );
+}
+
+void PMDialogEditContent::setContents( QWidget* wid )
+{
+ if( m_pContents )
+ removeChild( m_pContents );
+
+ m_pContents = wid;
+
+ if( m_pContents )
+ {
+ addChild( m_pContents );
+ calculateSize( );
+ }
+}
+
+void PMDialogEditContent::calculateSize( )
+{
+ int fw = lineWidth( ) * 2;
+ if( m_pContents )
+ {
+ QSize newSize = m_pContents->minimumSizeHint( );
+
+ setVScrollBarMode( AlwaysOff );
+ setHScrollBarMode( AlwaysOff );
+ setMargins( 0, 0, 0, 0 );
+
+ if( width( ) - fw < newSize.width( ) )
+ {
+ setHScrollBarMode( AlwaysOn );
+
+ if( ( height( ) - horizontalScrollBar( )->height( ) - fw )
+ < newSize.height( ) )
+ setVScrollBarMode( AlwaysOn );
+ else
+ newSize.setHeight( height( ) - horizontalScrollBar( )->height( ) - 2 );
+ }
+ else if( height( ) - fw < newSize.height( ) )
+ {
+ setVScrollBarMode( AlwaysOn );
+
+ if( ( width( ) - verticalScrollBar( )->width( ) - fw )
+ < newSize.width( ) )
+ setHScrollBarMode( AlwaysOn );
+ else
+ newSize.setWidth( width( ) - verticalScrollBar( )->width( ) - fw );
+ }
+ else
+ {
+ newSize.setWidth( width( ) - fw );
+ newSize.setHeight( height( ) - fw );
+ }
+
+ resizeContents( newSize.width( ), newSize.height( ) );
+ m_pContents->resize( newSize );
+ }
+}
+
+void PMDialogEditContent::resizeEvent( QResizeEvent* /* ev */ )
+{
+ calculateSize( );
+}
+
+PMDialogView::PMDialogView( PMPart* part, QWidget* parent, const char* name )
+ : PMViewBase( parent, name )
+{
+ m_pDisplayedWidget = 0;
+ m_unsavedData = false;
+ m_pHelper = new PMDialogEditContent( this );
+ m_pHelper->show( );
+ m_pPart = part;
+
+ m_pLayout = new QVBoxLayout( this, KDialog::marginHint( ),
+ KDialog::spacingHint( ) );
+
+ QHBoxLayout* labelLayout = new QHBoxLayout( m_pLayout );
+ m_pPixmapLabel = new QLabel( this );
+ m_pObjectTypeLabel = new QLabel( this );
+ labelLayout->addWidget( m_pPixmapLabel );
+ labelLayout->addWidget( m_pObjectTypeLabel );
+ labelLayout->addStretch( );
+
+ m_pLayout->addWidget( m_pHelper, 2 );
+ m_pLayout->addStretch( );
+
+ QHBoxLayout* buttonLayout = new QHBoxLayout( m_pLayout );
+ m_pHelpButton = new KPushButton( KStdGuiItem::help(), this );
+ buttonLayout->addWidget( m_pHelpButton );
+ connect( m_pHelpButton, SIGNAL( clicked( ) ), this, SLOT( slotHelp( ) ) );
+ m_pHelpButton->setEnabled( false );
+
+ m_pApplyButton = new KPushButton( KStdGuiItem::apply(), this );
+ buttonLayout->addWidget( m_pApplyButton );
+ connect( m_pApplyButton, SIGNAL( clicked( ) ), this, SLOT( slotApply( ) ) );
+ m_pApplyButton->setEnabled( false );
+
+ buttonLayout->addStretch( );
+
+ m_pCancelButton = new KPushButton( KStdGuiItem::cancel(), this );
+ buttonLayout->addWidget( m_pCancelButton );
+ connect( m_pCancelButton, SIGNAL( clicked( ) ), this, SLOT( slotCancel( ) ) );
+ m_pCancelButton->setEnabled( false );
+
+ m_pLayout->activate( );
+
+ connect( part, SIGNAL( refresh( ) ), SLOT( slotRefresh( ) ) );
+ connect( part, SIGNAL( objectChanged( PMObject*, const int, QObject* ) ),
+ SLOT( slotObjectChanged( PMObject*, const int, QObject* ) ) );
+ connect( part, SIGNAL( clear( ) ), SLOT( slotClear( ) ) );
+ connect( part, SIGNAL( aboutToRender( ) ), SLOT( slotAboutToRender( ) ) );
+ connect( part, SIGNAL( aboutToSave( ) ), SLOT( slotAboutToRender( ) ) );
+ connect( this, SIGNAL( objectChanged( PMObject*, const int, QObject* ) ),
+ part, SLOT( slotObjectChanged( PMObject*, const int, QObject* ) ) );
+
+ displayObject( m_pPart->activeObject( ) );
+}
+
+
+
+PMDialogView::~PMDialogView( )
+{
+ emit destroyed( this );
+}
+
+void PMDialogView::slotObjectChanged( PMObject* obj, const int mode, QObject* sender )
+{
+ if( sender == this )
+ return;
+ if( mode & PMCNewSelection )
+ {
+ if( m_pDisplayedWidget )
+ if( m_pDisplayedWidget->displayedObject( ) )
+ if( m_unsavedData )
+ if( shouldSaveData( ) )
+ slotApply( );
+
+ displayObject( obj );
+ }
+ if( mode & ( PMCSelected | PMCDeselected ) )
+ {
+ if( m_pDisplayedWidget )
+ if( m_pDisplayedWidget->displayedObject( ) )
+ if( m_unsavedData )
+ if( shouldSaveData( ) )
+ slotApply( );
+
+ displayObject( 0 );
+ }
+ if( mode & PMCRemove )
+ {
+ if( m_pDisplayedWidget )
+ {
+ if( m_pDisplayedWidget->displayedObject( ) == obj )
+ {
+ displayObject( 0 );
+ }
+ }
+ }
+ if( mode & ( PMCData | PMCDescription ) )
+ {
+ if( m_pDisplayedWidget )
+ {
+ if( m_pDisplayedWidget->displayedObject( ) )
+ {
+ if( m_pDisplayedWidget->displayedObject( ) == obj )
+ {
+ displayObject( obj, mode & PMCDescription );
+ m_unsavedData = false;
+ m_pApplyButton->setEnabled( false );
+ m_pCancelButton->setEnabled( false );
+ }
+ }
+ }
+ }
+ if( mode & PMCControlPointSelection )
+ {
+ if( m_pDisplayedWidget )
+ m_pDisplayedWidget->updateControlPointSelection( );
+ }
+}
+
+bool PMDialogView::shouldSaveData( )
+{
+ return ( KMessageBox::questionYesNo(
+ this, i18n( "This object was modified.\n\nSave changes?" ),
+ i18n( "Unsaved Changes" ), KStdGuiItem::save(), KStdGuiItem::discard() ) == KMessageBox::Yes );
+}
+
+void PMDialogView::slotRefresh( )
+{
+ if( m_pDisplayedWidget )
+ m_pDisplayedWidget->redisplay( );
+}
+
+void PMDialogView::slotClear( )
+{
+ displayObject( 0 );
+}
+
+void PMDialogView::slotApply( )
+{
+ if( m_pDisplayedWidget )
+ {
+ PMObject* obj = m_pDisplayedWidget->displayedObject( );
+ if( obj )
+ {
+ if( m_pDisplayedWidget->isDataValid( ) )
+ {
+ PMDataChangeCommand* cmd;
+
+ obj->createMemento( );
+ m_pDisplayedWidget->saveData( );
+ cmd = new PMDataChangeCommand( obj->takeMemento( ) );
+ m_pPart->executeCommand( cmd );
+
+ m_pApplyButton->setEnabled( false );
+ m_pCancelButton->setEnabled( false );
+ m_unsavedData = false;
+ }
+ }
+ }
+}
+
+void PMDialogView::slotHelp( )
+{
+ if( m_pDisplayedWidget && m_pDisplayedWidget->displayedObject( ) )
+ {
+ QString url = PMDocumentationMap::theMap( )->documentation(
+ m_pDisplayedWidget->displayedObject( )->className( ) );
+ if( !url.isEmpty( ) )
+ {
+ // Instead of calling invokeBrowser run konqueror directly.
+ // invokeBrowser was ignoring html anchors.
+ url = "konqueror " + KProcess::quote(url);
+ KRun::runCommand( url );
+ }
+ }
+}
+
+void PMDialogView::slotCancel( )
+{
+ m_pCancelButton->setEnabled( false );
+ m_pApplyButton->setEnabled( false );
+ m_unsavedData = false;
+
+ if( m_pDisplayedWidget )
+ {
+ bool b = m_pDisplayedWidget->signalsBlocked( );
+ m_pDisplayedWidget->blockSignals( true );
+ m_pDisplayedWidget->redisplay( );
+ m_pDisplayedWidget->blockSignals( b );
+ slotSizeChanged( );
+ }
+}
+
+void PMDialogView::slotDataChanged( )
+{
+// kdDebug( PMArea ) << "PMDialogView::slotDataChanged\n";
+ m_pApplyButton->setEnabled( true ) ;
+ m_pCancelButton->setEnabled( true );
+
+ m_unsavedData = true;
+}
+
+void PMDialogView::slotSizeChanged( )
+{
+ // force recalculating of the layout
+ if( m_pDisplayedWidget )
+ if( m_pDisplayedWidget->layout( ) )
+ m_pDisplayedWidget->layout( )->activate( );
+ m_pHelper->calculateSize( );
+}
+
+void PMDialogView::slotControlPointSelectionChanged( )
+{
+ if( m_pDisplayedWidget && m_pDisplayedWidget->displayedObject( ) )
+ emit objectChanged( m_pDisplayedWidget->displayedObject( ),
+ PMCControlPointSelection, this );
+}
+
+void PMDialogView::displayObject( PMObject* obj, bool updateDescription )
+{
+ PMDialogEditBase* old = 0;
+
+ if( !obj )
+ {
+ if( m_pDisplayedWidget )
+ old = m_pDisplayedWidget;
+
+ m_pDisplayedWidget = new PMDialogEditBase( m_pHelper->viewport( ) );
+ m_pDisplayedWidget->createWidgets( );
+ m_pHelper->setContents( m_pDisplayedWidget );
+ m_pPixmapLabel->setText( "" );
+ m_pObjectTypeLabel->setText( "" );
+ }
+ else
+ {
+ bool newWidget = true;
+ if( m_pDisplayedWidget )
+ {
+ if( m_pDisplayedWidget->displayedObject( ) )
+ {
+ if( obj->type( ) == m_pDisplayedWidget->displayedObject( )->type( ) )
+ {
+ // current widget displays object of the same type
+ // reuse the widget
+ newWidget = false;
+ }
+ }
+ }
+
+ if( newWidget )
+ {
+ // first create the new widget, then delete the old one.
+ if( m_pDisplayedWidget )
+ old = m_pDisplayedWidget;
+ m_pDisplayedWidget = obj->editWidget( m_pHelper->viewport( ) );
+ m_pDisplayedWidget->setPart( m_pPart );
+ m_pDisplayedWidget->createWidgets( );
+ m_pHelper->setContents( m_pDisplayedWidget );
+
+ if( m_pDisplayedWidget )
+ {
+ connect( m_pDisplayedWidget, SIGNAL( dataChanged( ) ),
+ this, SLOT( slotDataChanged( ) ) );
+ connect( m_pDisplayedWidget, SIGNAL( sizeChanged( ) ),
+ this, SLOT( slotSizeChanged( ) ) );
+ connect( m_pDisplayedWidget, SIGNAL( aboutToRender( ) ),
+ this, SLOT( slotAboutToRender( ) ) );
+ connect( m_pDisplayedWidget,
+ SIGNAL( controlPointSelectionChanged( ) ),
+ SLOT( slotControlPointSelectionChanged( ) ) );
+
+ }
+ }
+ }
+
+ if( m_pDisplayedWidget )
+ {
+ bool b = m_pDisplayedWidget->signalsBlocked( );
+ m_pDisplayedWidget->blockSignals( true );
+ m_pDisplayedWidget->displayObject( obj );
+ m_pDisplayedWidget->blockSignals( b );
+
+ m_pHelpButton->setEnabled( !m_pDisplayedWidget->helpTopic( ).isNull() );
+
+ if( !m_pDisplayedWidget->isVisible( ) )
+ m_pDisplayedWidget->show( );
+ if( obj && updateDescription )
+ {
+ m_pPixmapLabel->setPixmap( SmallIcon( obj->pixmap( ), PMFactory::instance( ) ) );
+ m_pObjectTypeLabel->setText( obj->description( ) );
+ }
+ slotSizeChanged( );
+ }
+
+ if( old )
+ delete old;
+
+ m_pApplyButton->setEnabled( false );
+ m_pCancelButton->setEnabled( false );
+ m_pHelpButton->setEnabled( !PMDocumentationMap::theMap( )
+ ->povrayDocumentationPath( ).isEmpty( ) );
+
+ m_unsavedData = false;
+}
+
+void PMDialogView::keyPressEvent( QKeyEvent* ev )
+{
+ if( ( ev->key( ) == Key_Return ) || ( ev->key( ) == Key_Enter ) )
+ slotApply( );
+}
+
+void PMDialogView::slotAboutToRender( )
+{
+ if( m_unsavedData )
+ if( shouldSaveData( ) )
+ slotApply( );
+}
+
+QString PMDialogView::description( ) const
+{
+ return i18n( "Object Properties" );
+}
+
+QString PMDialogViewFactory::description( ) const
+{
+ return i18n( "Object Properties" );
+}
+
+#include "pmdialogview.moc"
diff --git a/kpovmodeler/pmdialogview.h b/kpovmodeler/pmdialogview.h
new file mode 100644
index 00000000..aef224eb
--- /dev/null
+++ b/kpovmodeler/pmdialogview.h
@@ -0,0 +1,163 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDIALOGEDITVIEW_H
+#define PMDIALOGEDITVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qscrollview.h>
+#include <kpushbutton.h>
+
+#include "pmviewbase.h"
+#include "pmviewfactory.h"
+
+class PMDialogEditBase;
+class PMObject;
+class PMPart;
+class QGroupBox;
+class QBoxLayout;
+class QLabel;
+
+/**
+ * Helper class for @ref PMDialogView
+ */
+class PMDialogEditContent : public QScrollView
+{
+ Q_OBJECT
+public:
+ PMDialogEditContent( QWidget* parent, const char* name = 0 );
+ void setContents( QWidget* wid );
+ void calculateSize( );
+protected:
+ void resizeEvent( QResizeEvent* );
+private:
+ QWidget* m_pContents;
+};
+
+/**
+ * View to display and modify attributes of objects.
+ *
+ * This class creates the corresponding widget
+ * (subclass of @ref PMDialogEditBase) for the active object and
+ * displays it.
+ */
+class PMDialogView : public PMViewBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a new PMDialogView widget
+ */
+ PMDialogView( PMPart* part, QWidget* parent, const char* name = 0 );
+ /**
+ * Deletes the widget
+ */
+ ~PMDialogView( );
+
+ /** */
+ virtual QString viewType( ) const { return QString( "dialogview" ); }
+ /** */
+ virtual QString description( ) const;
+
+public slots:
+ /**
+ * Called when an object is changed.
+ * Mode is a bit combination of @ref PMChange constants
+ */
+ void slotObjectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Called before the scene is rendered
+ */
+ void slotAboutToRender( );
+ /**
+ * Called when the whole documents contents have changed
+ */
+ void slotRefresh( );
+ /**
+ * Clears all data
+ */
+ void slotClear( );
+signals:
+ /**
+ * Signal that is emitted when an object is changed.
+ * Mode is a bit combination of @ref PMChange constants.
+ */
+ void objectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Emitted in the destructor
+ */
+ void destroyed( PMDialogView* v );
+
+protected:
+ virtual void keyPressEvent( QKeyEvent* );
+
+private slots:
+ void slotApply( );
+ void slotHelp( );
+ void slotCancel( );
+ void slotDataChanged( );
+ void slotSizeChanged( );
+ void slotControlPointSelectionChanged( );
+
+private:
+ /**
+ * Asks the user to save unsaved data in the displayed widget
+ */
+ bool shouldSaveData( );
+ /**
+ * Displays the object
+ */
+ void displayObject( PMObject* obj, bool updateDescription = true );
+
+ PMDialogEditBase* m_pDisplayedWidget;
+ QBoxLayout* m_pLayout;
+
+ KPushButton* m_pApplyButton;
+ KPushButton* m_pCancelButton;
+ KPushButton* m_pHelpButton;
+
+ QLabel* m_pPixmapLabel;
+ QLabel* m_pObjectTypeLabel;
+
+ PMDialogEditContent* m_pHelper;
+
+ bool m_unsavedData;
+ PMPart* m_pPart;
+};
+
+/**
+ * Factory class for dialog views
+ */
+class PMDialogViewFactory : public PMViewTypeFactory
+{
+public:
+ PMDialogViewFactory( ) { }
+ virtual QString viewType( ) const { return QString( "dialogview" ); }
+ virtual QString description( ) const;
+ virtual QString iconName( ) const { return QString( "pmdialogview" ); }
+ virtual PMViewBase* newInstance( QWidget* parent, PMPart* part ) const
+ {
+ return new PMDialogView( part, parent );
+ }
+};
+
+#endif
diff --git a/kpovmodeler/pmdisc.cpp b/kpovmodeler/pmdisc.cpp
new file mode 100644
index 00000000..d276e541
--- /dev/null
+++ b/kpovmodeler/pmdisc.cpp
@@ -0,0 +1,440 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdisc.h"
+
+#include "pmxmlhelper.h"
+#include "pmboxedit.h"
+#include "pmmemento.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmvectorcontrolpoint.h"
+#include "pm3dcontrolpoint.h"
+#include "pmdefaults.h"
+
+#include <klocale.h>
+
+#include "pmdiscedit.h"
+
+const double defaultDiscRadius = 1.0;
+const double defaultDiscHoleRadius = 0.0;
+const PMVector defaultDiscCenter = PMVector ( 0.0, 0.0, 0.0 );
+const PMVector defaultDiscNormal = PMVector ( 0.0, 1.0, 0.0 );
+
+/** default disc structure */
+PMViewStructure* PMDisc::s_pDefaultViewStructure = 0;
+int PMDisc::s_numSteps = c_defaultDiscSteps;
+int PMDisc::s_parameterKey = 0;
+
+PMDefinePropertyClass( PMDisc, PMDiscProperty );
+
+PMMetaObject* PMDisc::s_pMetaObject = 0;
+PMObject* createNewDisc( PMPart* part )
+{
+ return new PMDisc( part );
+}
+
+PMDisc::PMDisc( PMPart* part )
+ : Base( part )
+{
+ m_center = defaultDiscCenter;
+ m_normal = defaultDiscNormal;
+ m_radius = defaultDiscRadius;
+ m_hradius = defaultDiscHoleRadius;
+}
+
+PMDisc::PMDisc( const PMDisc& d )
+ : Base( d )
+{
+ m_center = d.m_center;
+ m_normal = d.m_normal;
+ m_radius = d.m_radius;
+ m_hradius = d.m_hradius;
+}
+
+
+PMDisc::~PMDisc( )
+{
+}
+
+QString PMDisc::description( ) const
+{
+ return i18n( "disc" );
+}
+
+void PMDisc::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "center", m_center.serializeXML( ) );
+ e.setAttribute( "normal", m_normal.serializeXML( ) );
+ e.setAttribute( "radius", m_radius );
+ e.setAttribute( "hole_radius", m_hradius );
+ Base::serialize( e, doc );
+}
+
+void PMDisc::readAttributes( const PMXMLHelper& h )
+{
+ m_center = h.vectorAttribute( "center", defaultDiscCenter );
+ m_normal = h.vectorAttribute( "normal", defaultDiscNormal );
+ m_radius = h.doubleAttribute( "radius", defaultDiscRadius );
+ m_hradius = h.doubleAttribute( "hole_radius", defaultDiscHoleRadius );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMDisc::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Disc", Base::metaObject( ),
+ createNewDisc );
+ s_pMetaObject->addProperty(
+ new PMDiscProperty( "center", &PMDisc::setCenter, &PMDisc::center ) );
+ s_pMetaObject->addProperty(
+ new PMDiscProperty( "normal", &PMDisc::setNormal, &PMDisc::normal ) );
+ s_pMetaObject->addProperty(
+ new PMDiscProperty( "radius", &PMDisc::setRadius, &PMDisc::radius ) );
+ s_pMetaObject->addProperty(
+ new PMDiscProperty( "holeRadius", &PMDisc::setHoleRadius, &PMDisc::holeRadius ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMDisc::setCenter( const PMVector& c )
+{
+ if( c != m_center )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCenterID, m_center );
+
+ m_center = c;
+ m_center.resize( 3 );
+
+ setViewStructureChanged( );
+ }
+}
+
+void PMDisc::setNormal( const PMVector& p )
+{
+ if( p != m_normal )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNormalID, m_normal );
+
+ m_normal = p;
+ m_normal.resize( 3 );
+
+ setViewStructureChanged( );
+ }
+}
+
+void PMDisc::setRadius( double radius )
+{
+ if( m_radius != radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusID, m_radius );
+
+ if( radius <= m_hradius )
+ m_radius = m_hradius;
+ else
+ m_radius = radius;
+
+ setViewStructureChanged( );
+ }
+}
+
+void PMDisc::setHoleRadius( double hradius )
+{
+ if( m_hradius != hradius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHRadiusID, m_hradius );
+
+ if( hradius >= m_radius )
+ m_hradius = m_radius;
+ else if( hradius <= 0.0 )
+ m_hradius = 0.0;
+ else
+ m_hradius = hradius;
+
+ setViewStructureChanged( );
+ }
+}
+
+PMDialogEditBase* PMDisc::editWidget( QWidget* parent ) const
+{
+ return new PMDiscEdit( parent );
+}
+
+void PMDisc::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMCenterID:
+ setCenter( data->vectorData( ) );
+ break;
+ case PMNormalID:
+ setNormal( data->vectorData( ) );
+ break;
+ case PMRadiusID:
+ setRadius( data->doubleData( ) );
+ break;
+ case PMHRadiusID:
+ setHoleRadius( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMDisc::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+bool PMDisc::isDefault( )
+{
+ if( ( m_center == defaultDiscCenter ) && ( m_normal == defaultDiscNormal )
+ && ( m_radius == defaultDiscRadius ) && ( m_hradius == defaultDiscHoleRadius )
+ && globalDetail( ) )
+ return true;
+ return false;
+}
+
+void PMDisc::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure ( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ int steps = (int)( ( (float)s_numSteps / 2 ) * ( displayDetail( ) + 1 ) );
+ unsigned size = steps * 2;
+
+ if( size != m_pViewStructure->points( ).size( ) )
+ {
+ m_pViewStructure->points( ).resize( size );
+ m_pViewStructure->lines( ).detach( );
+ m_pViewStructure->lines( ).resize( size );
+ createLines( m_pViewStructure->lines( ), steps );
+ }
+ createPoints( m_pViewStructure->points( ), m_center, m_normal, m_radius, m_hradius, steps );
+}
+
+PMViewStructure* PMDisc::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ int steps = (int)( ( (float)s_numSteps / 2 ) * ( globalDetailLevel( ) + 1 ) );
+ s_pDefaultViewStructure = new PMViewStructure( steps * 2 , steps * 2 );
+
+ createPoints( s_pDefaultViewStructure->points( ), defaultDiscCenter, defaultDiscNormal,
+ defaultDiscRadius, defaultDiscHoleRadius, steps );
+
+ createLines( s_pDefaultViewStructure->lines( ), steps );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMDisc::createLines( PMLineArray& lines, int steps )
+{
+ int i;
+ for( i = 0; i < ( steps - 1) ; i++ )
+ {
+ lines[ i ] = PMLine( i, i + 1 );
+ lines[ i + steps ] = PMLine( i + steps, i + steps + 1 );
+ }
+ lines[ i ] = PMLine( i , 0 );
+ lines[i + steps] = PMLine( i + steps, steps );
+}
+
+void PMDisc::createPoints( PMPointArray& points, const PMVector& center,
+ const PMVector& normal, double radius , double hradius, int steps )
+{
+ PMVector pv = normal;
+ double pl = pv.abs( );
+ if( approxZero( pl ) )
+ pv = PMVector( 0.0 , 1.0 , 0.0 );
+ else
+ pv /= pl;
+
+ double angle = ( 2.0 * M_PI ) / ( double ) steps;
+ PMMatrix rotation = PMMatrix::rotation( pv , angle );
+ PMVector endP = pv.orthogonal( );
+
+ for( int i = 0 ; i < steps ; i++ )
+ {
+ points[ i ] = PMPoint( ( endP * radius ) + center );
+ points[ i + steps ] = PMPoint( ( endP * hradius ) + center );
+ endP = rotation * endP;
+ }
+}
+
+void setVectorBase( PMVector pn , PMVector& vn , PMVector& v1, PMVector& v2 )
+{
+ double pl = pn.abs( );
+ if( approxZero( pl ) )
+ vn = PMVector( 0.0 , 1.0 , 0.0 );
+ else
+ vn = ( pn / pl );
+
+ v1 = vn.orthogonal( );
+ v2 = PMVector::cross( vn, v1 );
+}
+
+void PMDisc::controlPoints( PMControlPointList & list )
+{
+ PMVector vetN , vet1 , vet2 ;
+ setVectorBase( m_normal , vetN , vet1 , vet2 );
+
+ PM3DControlPoint* pb = new PM3DControlPoint( m_center, PMCenterID, i18n( "Center" ) );
+ list.append( pb );
+
+ PMDistanceControlPoint* d;
+ d = new PMDistanceControlPoint( pb , vet1, m_radius, PMRadiusID, i18n( "Radius (1)" ) );
+ list.append( d );
+ d = new PMDistanceControlPoint( pb , vet2, m_radius, PMRadiusID, i18n( "Radius (2)" ) );
+ list.append( d );
+ d = new PMDistanceControlPoint( pb , vet1, m_hradius, PMHRadiusID, i18n( "Hole Radius (1)" ) );
+ list.append( d );
+ d = new PMDistanceControlPoint( pb , vet2, m_hradius, PMHRadiusID, i18n( "Hole Radius (2)" ) );
+ list.append( d );
+
+ list.append( new PMVectorControlPoint( pb, m_normal, PMNormalID, i18n( "Normal" ) ) );
+}
+
+void PMDisc::controlPointsChanged( PMControlPointList & list )
+{
+ PMControlPoint* p;
+ bool radius1Changed = false;
+ bool radius2Changed = false;
+ bool pointChanged = false;
+ PMVector pt;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMCenterID:
+ pt =( (PM3DControlPoint* ) p)->point( ) ;
+ setCenter( pt );
+ pointChanged = true;
+ break;
+ case PMNormalID:
+ setNormal( ( ( (PM3DControlPoint* ) p)->point( ) ) );
+ pointChanged = true;
+ break;
+ case PMRadiusID:
+ setRadius( ( ( PMDistanceControlPoint *) p )->distance( ) );
+ radius1Changed = true;
+ break;
+ case PMHRadiusID:
+ setHoleRadius( ( ( PMDistanceControlPoint *) p )->distance( ) );
+ radius2Changed = true;
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMDisc::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+
+ if( radius1Changed )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMRadiusID )
+ ( ( PMDistanceControlPoint *) p)->setDistance( m_radius );
+
+ if( radius2Changed )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMHRadiusID )
+ ( ( PMDistanceControlPoint *) p)->setDistance( m_hradius );
+
+ if( pointChanged )
+ {
+ PMVector vetN, vet1, vet2;
+ setVectorBase( m_normal , vetN, vet1, vet2 );
+
+ bool firstPoint1 = true;
+ bool firstPoint2 = true;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->id( ) == PMRadiusID )
+ {
+ if( firstPoint1 )
+ {
+ ( ( PMDistanceControlPoint *) p)->setDirection( vet1 );
+ firstPoint1 = false;
+ }
+ else
+ ( ( PMDistanceControlPoint *) p)->setDirection( vet2 );
+ }
+ if( p->id( ) == PMHRadiusID )
+ {
+ if( firstPoint2 )
+ {
+ ( ( PMDistanceControlPoint *) p)->setDirection( vet1 );
+ firstPoint2 = false;
+ }
+ else
+ ( ( PMDistanceControlPoint *) p)->setDirection( vet2 );
+ }
+ }
+ }
+}
+
+void PMDisc::setSteps( int s )
+{
+ if( s >= 4 )
+ {
+ s_numSteps = s;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMDisc::setSteps: S must be greater than 3\n";
+ s_parameterKey++;
+}
+
+void PMDisc::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmdisc.h b/kpovmodeler/pmdisc.h
new file mode 100644
index 00000000..35cb0081
--- /dev/null
+++ b/kpovmodeler/pmdisc.h
@@ -0,0 +1,180 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMDISC_H
+#define PMDISC_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmgraphicalobject.h"
+#include "pmvector.h"
+#include "pmviewstructure.h"
+
+/**
+ * Class for povray disc
+ */
+
+class PMDisc : public PMGraphicalObject
+{
+ typedef PMGraphicalObject Base;
+public:
+ /**
+ * Creates a disc
+ */
+ PMDisc( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMDisc( const PMDisc& d );
+
+ /**
+ * Deletes the disc
+ */
+ virtual ~PMDisc( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMDisc( *this ); }
+
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMDiscEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmdisc" ); }
+
+ /**
+ * Return the center
+ */
+ PMVector center( ) const { return m_center; }
+ /**
+ * Sets center
+ */
+ void setCenter( const PMVector& c );
+ /**
+ * Return the normal
+ */
+ PMVector normal( ) const { return m_normal; }
+ /**
+ * Sets normal
+ */
+ void setNormal( const PMVector& p );
+ /**
+ * Return the radius
+ */
+ double radius( ) const { return m_radius; }
+ /**
+ * Sets the radius
+ */
+ void setRadius( double radius );
+ /**
+ * Return the hole radius
+ */
+ double holeRadius( ) const { return m_hradius; }
+ /**
+ * Sets the hole radius
+ */
+ void setHoleRadius( double hradius );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+
+ /**
+ * Returns the number of lines for rendering
+ */
+ static int steps( ) { return s_numSteps; }
+ /**
+ * Sets the number of lines for rendering
+ */
+ static void setSteps( int s );
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey+ globalDetailKey(); }
+
+private:
+ /**
+ * Creates the lines for the view structure
+ */
+ static void createLines( PMLineArray& lines, int steps );
+ /**
+ * Creates the points for the view structure
+ */
+ static void createPoints( PMPointArray& points, const PMVector& center,
+ const PMVector& normal, double radius , double hradius, int steps );
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMPlaneMementoID { PMCenterID, PMNormalID, PMRadiusID, PMHRadiusID };
+ /**
+ * center of disc
+ */
+ PMVector m_center;
+ /**
+ * normal of disc
+ */
+ PMVector m_normal;
+ /**
+ * radius of disc
+ */
+ double m_radius;
+ /**
+ * hole radius of disc
+ */
+ double m_hradius;
+ /**
+ * The default view structure. It can be shared between planes
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_numSteps;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmdiscedit.cpp b/kpovmodeler/pmdiscedit.cpp
new file mode 100644
index 00000000..109c3d66
--- /dev/null
+++ b/kpovmodeler/pmdiscedit.cpp
@@ -0,0 +1,147 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmdiscedit.h"
+#include "pmdisc.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+PMDiscEdit::PMDiscEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMDiscEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+ QGridLayout* gl;
+
+ m_pCenter = new PMVectorEdit( "x", "y", "z", this );
+ m_pNormal = new PMVectorEdit( "x", "y", "z", this );
+ m_pHRadius = new PMFloatEdit( this );
+ m_pHRadius->setValidation( true, 0.0, false, 0.0 );
+ m_pRadius = new PMFloatEdit( this );
+ m_pRadius->setValidation( true, 0.0, false, 0.0 );
+
+ gl = new QGridLayout( topLayout( ), 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Center:" ), this ), 0, 0 );
+ gl->addWidget( m_pCenter, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Normal:" ), this ), 1, 0 );
+ gl->addWidget( m_pNormal, 1, 1 );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( layout, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Radius:" ), this ), 0, 0 );
+ gl->addWidget( m_pRadius, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Hole radius:" ), this ), 1, 0 );
+ gl->addWidget( m_pHRadius, 1, 1 );
+ layout->addStretch( 1 );
+
+ QPushButton* nb = new QPushButton( i18n( "Normalize" ), this );
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( nb );
+ layout->addStretch( 1 );
+
+ connect( m_pCenter, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pNormal, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pHRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( nb, SIGNAL( clicked( ) ), SLOT( slotNormalize( ) ) );
+}
+
+void PMDiscEdit::slotNormalize( )
+{
+ PMVector normal = m_pNormal->vector( );
+ double l = normal.abs( );
+ if( !approxZero( l ) )
+ m_pNormal->setVector( normal / l );
+}
+
+
+void PMDiscEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Disc" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMDisc* ) o;
+
+ m_pCenter->setVector( m_pDisplayedObject->center( ) );
+ m_pNormal->setVector( m_pDisplayedObject->normal( ) );
+ m_pRadius->setValue( m_pDisplayedObject->radius( ) );
+ m_pHRadius->setValue( m_pDisplayedObject->holeRadius( ) );
+
+ m_pCenter->setReadOnly( readOnly );
+ m_pNormal->setReadOnly( readOnly );
+ m_pRadius->setReadOnly( readOnly );
+ m_pHRadius->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMDiscEdit: Can't display object\n";
+}
+
+void PMDiscEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setCenter( m_pCenter->vector( ) );
+ m_pDisplayedObject->setNormal( m_pNormal->vector( ) );
+ m_pDisplayedObject->setRadius( m_pRadius->value( ) );
+ m_pDisplayedObject->setHoleRadius( m_pHRadius->value( ) );
+ }
+}
+
+bool PMDiscEdit::isDataValid( )
+{
+ if( m_pNormal->isDataValid( ) )
+ {
+ if( approxZero( m_pNormal->vector( ).abs( ) ) )
+ {
+ KMessageBox::error( this, i18n( "The normal vector may not be a "
+ "null vector." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ if( m_pCenter->isDataValid( ) )
+ if( m_pRadius->isDataValid( ) )
+ if( m_pHRadius->isDataValid( ) )
+ if( m_pRadius->value( ) >= m_pHRadius->value( ) )
+ return Base::isDataValid( );
+ else
+ {
+ KMessageBox::error( this, i18n( "The radius may not be smaller "
+ "than the hole radius." ),
+ i18n( "Error" ) );
+ m_pRadius->setFocus( );
+ }
+ }
+ return false;
+}
+
+#include "pmdiscedit.moc"
diff --git a/kpovmodeler/pmdiscedit.h b/kpovmodeler/pmdiscedit.h
new file mode 100644
index 00000000..bc603ddc
--- /dev/null
+++ b/kpovmodeler/pmdiscedit.h
@@ -0,0 +1,67 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorinaez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMDISCEDIT_H
+#define PMDISCEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmgraphicalobjectedit.h"
+
+class PMVectorEdit;
+class PMFloatEdit;
+class PMDisc;
+
+class PMDiscEdit : public PMGraphicalObjectEdit
+{
+ Q_OBJECT
+ typedef PMGraphicalObjectEdit Base;
+public:
+ /**
+ * Creates a PMPlaneEdit with parent and name
+ */
+ PMDiscEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * Normalizes the vector
+ */
+ void slotNormalize( );
+
+private:
+ PMDisc* m_pDisplayedObject;
+ PMVectorEdit* m_pCenter;
+ PMVectorEdit* m_pNormal;
+ PMFloatEdit* m_pRadius;
+ PMFloatEdit* m_pHRadius;
+};
+#endif
diff --git a/kpovmodeler/pmdistancecontrolpoint.cpp b/kpovmodeler/pmdistancecontrolpoint.cpp
new file mode 100644
index 00000000..dbd8b881
--- /dev/null
+++ b/kpovmodeler/pmdistancecontrolpoint.cpp
@@ -0,0 +1,92 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmdistancecontrolpoint.h"
+#include "pmmath.h"
+#include "pmdebug.h"
+#include <math.h>
+
+
+PMDistanceControlPoint::PMDistanceControlPoint( PMControlPoint* base,
+ const PMVector& direction, double distance,
+ int id, const QString& description,
+ bool showExtraLine )
+ : PMControlPoint( id, description )
+{
+ m_distance = distance;
+ m_pBasePoint = base;
+ m_direction = direction;
+ m_directionLength = direction.abs( );
+ m_extraLine = showExtraLine;
+}
+
+PMDistanceControlPoint::PMDistanceControlPoint( const PMVector& base,
+ const PMVector& direction, double distance,
+ int id, const QString& description,
+ bool showExtraLine )
+ : PMControlPoint( id, description )
+{
+ m_distance = distance;
+ m_constBasePoint = base;
+ m_pBasePoint = 0;
+ m_direction = direction;
+ m_directionLength = direction.abs( );
+ m_extraLine = showExtraLine;
+}
+
+PMVector PMDistanceControlPoint::position( ) const
+{
+ if( m_pBasePoint )
+ return m_pBasePoint->position( ) + m_direction * m_distance;
+ return m_constBasePoint + m_direction * m_distance;
+}
+
+PMVector PMDistanceControlPoint::basePoint( ) const
+{
+ if( m_pBasePoint )
+ return m_pBasePoint->position( );
+ return m_constBasePoint;
+}
+
+void PMDistanceControlPoint::setDirection( const PMVector& direction )
+{
+ m_direction = direction;
+ m_directionLength = direction.abs( );
+}
+
+void PMDistanceControlPoint::graphicalChangeStarted( )
+{
+ m_originalDistance = m_distance;
+}
+
+void PMDistanceControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& /*viewNormal*/,
+ const PMVector& endPoint )
+{
+ if( !approxZero( m_directionLength ) )
+ m_distance = m_originalDistance +
+ PMVector::dot( endPoint - startPoint, m_direction )
+ / ( m_directionLength * m_directionLength );
+}
+
+void PMDistanceControlPoint::snapToGrid( )
+{
+ double d = moveGrid( );
+ if( !approxZero( d ) )
+ m_distance = rint( m_distance / d ) * d;
+ setChanged( );
+}
diff --git a/kpovmodeler/pmdistancecontrolpoint.h b/kpovmodeler/pmdistancecontrolpoint.h
new file mode 100644
index 00000000..f5e28fff
--- /dev/null
+++ b/kpovmodeler/pmdistancecontrolpoint.h
@@ -0,0 +1,110 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDISTANCECONTROLPOINT_H
+#define PMDISTANCECONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "pmcontrolpoint.h"
+
+/**
+ * Class for distance control points
+ */
+class PMDistanceControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Creates a PMDistanceControlPoint with id.
+ *
+ * The base point of the vector is given by the control point location.
+ */
+ PMDistanceControlPoint( PMControlPoint* location, const PMVector& direction,
+ double distance, int id, const QString& description,
+ bool extraLine = false );
+ /**
+ * Creates a PMDistanceControlPoint with id.
+ *
+ * The base point of the vector is given by the vector p.
+ */
+ PMDistanceControlPoint( const PMVector& location, const PMVector& direction,
+ double distance, int id, const QString& description,
+ bool extraLine = false );
+
+ /**
+ * Deletes the PMDistanceControlPoint
+ */
+ virtual ~PMDistanceControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const;
+
+ /**
+ * Sets the distance
+ */
+ void setDistance( double distance ) { m_distance = distance; }
+ /**
+ * returns the distance
+ */
+ double distance( ) const { return m_distance; }
+ /**
+ * Sets the direction
+ */
+ void setDirection( const PMVector& d );
+ /**
+ * Returns the direction
+ */
+ PMVector direction( ) const { return m_direction; }
+ /**
+ * Returns the base point
+ */
+ PMVector basePoint( ) const;
+
+ /** */
+ virtual bool hasExtraLine( ) const { return m_extraLine; }
+ /**
+ * Returns the start point of the extra line
+ */
+ virtual PMVector extraLineStart( ) const { return basePoint( ); }
+ /**
+ * Returns the end point of the extra line
+ */
+ virtual PMVector extraLineEnd( ) const { return position( ); }
+
+ /** */
+ virtual void snapToGrid( );
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ double m_distance, m_originalDistance;
+ PMControlPoint* m_pBasePoint;
+ PMVector m_constBasePoint;
+ PMVector m_direction;
+ double m_directionLength;
+ bool m_extraLine;
+};
+
+#endif
diff --git a/kpovmodeler/pmdockwidget.cpp b/kpovmodeler/pmdockwidget.cpp
new file mode 100644
index 00000000..625ea6bc
--- /dev/null
+++ b/kpovmodeler/pmdockwidget.cpp
@@ -0,0 +1,2549 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Modified 2002 Andreas Zehender <zehender@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "pmdockwidget.h"
+#include "pmdockwidget_private.h"
+
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qobjectlist.h>
+#include <qstrlist.h>
+#include <qcursor.h>
+#include <qwidgetlist.h>
+#include <qtabwidget.h>
+#include <qstyle.h>
+
+#ifndef NO_KDE2
+#include <kconfig.h>
+#include <kglobal.h>
+#include <ktoolbar.h>
+#include <kpopupmenu.h>
+#include <kwin.h>
+#include <kdebug.h>
+#ifdef Q_WS_X11
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#endif
+#else
+#include <qapplication.h>
+#include <qtoolbar.h>
+#include <qpopupmenu.h>
+#endif
+
+#include "pmdebug.h"
+
+#include <kparts/event.h>
+#include <kparts/part.h>
+#include <kaccel.h>
+#include <kparts/plugin.h>
+#include <kstatusbar.h>
+#include <kinstance.h>
+#include <khelpmenu.h>
+#include <kstandarddirs.h>
+#include <qapplication.h>
+#include <kdebug.h>
+#include <kxmlguifactory.h>
+
+#include <assert.h>
+
+#define DOCK_CONFIG_VERSION "0.0.5"
+
+static const char* const close_xpm[]={
+"7 7 2 1",
+"# c black",
+". c None",
+".......",
+"##..##.",
+".####..",
+"..##...",
+".####..",
+"##..##.",
+"......."};
+
+static const char* const todesktop_xpm[]={
+"5 5 2 1",
+"# c black",
+". c None",
+"####.",
+"##...",
+"#.#..",
+"#..#.",
+"....#"};
+
+static const char* const dockback_xpm[]={
+"5 5 2 1",
+"# c black",
+". c None",
+"#....",
+".#..#",
+"..#.#",
+"...##",
+".####"};
+
+static const char* const not_close_xpm[]={
+"5 5 2 1",
+"# c black",
+". c None",
+"#####",
+"#...#",
+"#...#",
+"#...#",
+"#####"};
+
+class PMDockMainWindowPrivate
+{
+public:
+ PMDockMainWindowPrivate()
+ {
+ m_activePart = 0;
+ m_bShellGUIActivated = false;
+ m_helpMenu = 0;
+ }
+ ~PMDockMainWindowPrivate()
+ {
+ }
+
+ QGuardedPtr<Part> m_activePart;
+ bool m_bShellGUIActivated;
+ KHelpMenu *m_helpMenu;
+};
+
+
+/**
+ * A special kind of KMainWindow that is able to have dockwidget child widgets.
+ *
+ * The main widget should be a dockwidget where other dockwidgets can be docked to
+ * the left, right, top, bottom or to the middle.
+ * Furthermore, the PMDockMainWindow has got the KDocManager and some data about the dock states.
+ *
+ * @author Max Judin.
+*/
+PMDockMainWindow::PMDockMainWindow( QWidget* parent, const char *name, WFlags f)
+:KMainWindow( parent, name, f )
+{
+ QString new_name = QString(name) + QString("_DockManager");
+ dockManager = new PMDockManager( this, new_name.latin1() );
+ mainDockWidget = 0L;
+
+ d = new PMDockMainWindowPrivate( );
+ PartBase::setPartObject( this );
+}
+
+PMDockMainWindow::~PMDockMainWindow()
+{
+ delete dockManager;
+ delete d;
+}
+
+// kparts/dockmainwindow stuff
+void PMDockMainWindow::createGUI( Part * part )
+{
+ kdDebug(1000) << QString("DockMainWindow::createGUI for %1").arg(part?part->name():"0L") << endl;
+
+ KXMLGUIFactory *factory = guiFactory();
+
+ setUpdatesEnabled( false );
+
+ QPtrList<Plugin> plugins;
+
+ if ( d->m_activePart )
+ {
+ kdDebug(1000) << QString("deactivating GUI for %1").arg(d->m_activePart->name()) << endl;
+
+ GUIActivateEvent ev( false );
+ QApplication::sendEvent( d->m_activePart, &ev );
+
+ factory->removeClient( d->m_activePart );
+
+ disconnect( d->m_activePart, SIGNAL( setWindowCaption( const QString & ) ),
+ this, SLOT( setCaption( const QString & ) ) );
+ disconnect( d->m_activePart, SIGNAL( setStatusBarText( const QString & ) ),
+ this, SLOT( slotSetStatusBarText( const QString & ) ) );
+ }
+
+ if( !d->m_bShellGUIActivated )
+ {
+ loadPlugins( this, this, KGlobal::instance() );
+ createShellGUI();
+ d->m_bShellGUIActivated = true;
+ }
+
+ if ( part )
+ {
+ // do this before sending the activate event
+ connect( part, SIGNAL( setWindowCaption( const QString & ) ),
+ this, SLOT( setCaption( const QString & ) ) );
+ connect( part, SIGNAL( setStatusBarText( const QString & ) ),
+ this, SLOT( slotSetStatusBarText( const QString & ) ) );
+
+ factory->addClient( part );
+
+ GUIActivateEvent ev( true );
+ QApplication::sendEvent( part, &ev );
+
+ }
+
+ setUpdatesEnabled( true );
+
+ d->m_activePart = part;
+}
+
+void PMDockMainWindow::slotSetStatusBarText( const QString & text )
+{
+ statusBar()->message( text );
+}
+
+void PMDockMainWindow::createShellGUI( bool create )
+{
+ bool bAccelAutoUpdate = accel()->setAutoUpdate( false );
+ assert( d->m_bShellGUIActivated != create );
+ d->m_bShellGUIActivated = create;
+
+ if ( create )
+ {
+ if ( isHelpMenuEnabled() && !d->m_helpMenu )
+ d->m_helpMenu = new KHelpMenu( this, instance()->aboutData(), true, actionCollection() );
+
+ QString f = xmlFile();
+ setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) );
+ if ( !f.isEmpty() )
+ setXMLFile( f, true );
+ else
+ {
+ QString auto_file( instance()->instanceName() + "ui.rc" );
+ setXMLFile( auto_file, true );
+ }
+
+ GUIActivateEvent ev( true );
+ QApplication::sendEvent( this, &ev );
+
+ guiFactory()->addClient( this );
+
+ }
+ else
+ {
+ GUIActivateEvent ev( false );
+ QApplication::sendEvent( this, &ev );
+
+ guiFactory()->removeClient( this );
+ }
+ accel()->setAutoUpdate( bAccelAutoUpdate );
+}
+// end kparts/dockmainwindow
+
+void PMDockMainWindow::setMainDockWidget( PMDockWidget* mdw )
+{
+ if ( mainDockWidget == mdw ) return;
+ mainDockWidget = mdw;
+}
+
+void PMDockMainWindow::setView( QWidget *view )
+{
+ if ( view->isA("PMDockWidget") ){
+ if ( view->parent() != this ) ((PMDockWidget*)view)->applyToWidget( this );
+ }
+
+#ifndef NO_KDE2
+ KMainWindow::setCentralWidget(view);
+#else
+ QMainWindow::setCentralWidget(view);
+#endif
+}
+
+PMDockWidget* PMDockMainWindow::createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel)
+{
+ return new PMDockWidget( dockManager, name.latin1(), pixmap, parent, strCaption, strTabPageLabel );
+}
+
+void PMDockMainWindow::makeDockVisible( PMDockWidget* dock )
+{
+ if ( dock != 0L)
+ dock->makeDockVisible();
+}
+
+void PMDockMainWindow::makeDockInvisible( PMDockWidget* dock )
+{
+ if ( dock != 0L)
+ dock->undock();
+}
+
+void PMDockMainWindow::makeWidgetDockVisible( QWidget* widget )
+{
+ makeDockVisible( dockManager->findWidgetParentDock(widget) );
+}
+
+void PMDockMainWindow::writeDockConfig(QDomElement &base)
+{
+ dockManager->writeConfig(base);
+}
+
+void PMDockMainWindow::readDockConfig(QDomElement &base)
+{
+ dockManager->readConfig(base);
+}
+
+#ifndef NO_KDE2
+void PMDockMainWindow::writeDockConfig( KConfig* c, QString group )
+{
+ dockManager->writeConfig( c, group );
+}
+
+void PMDockMainWindow::readDockConfig( KConfig* c, QString group )
+{
+ dockManager->readConfig( c, group );
+}
+#endif
+
+void PMDockMainWindow::slotDockWidgetUndocked()
+{
+ QObject* pSender = (QObject*) sender();
+ if (!pSender->inherits("PMDockWidget")) return;
+ PMDockWidget* pDW = (PMDockWidget*) pSender;
+ emit dockWidgetHasUndocked( pDW);
+}
+
+/*************************************************************************/
+PMDockWidgetAbstractHeaderDrag::PMDockWidgetAbstractHeaderDrag( PMDockWidgetAbstractHeader* parent, PMDockWidget* dock, const char* name )
+:QFrame( parent, name )
+{
+ dw = dock;
+ installEventFilter( dock->dockManager() );
+}
+/*************************************************************************/
+PMDockWidgetHeaderDrag::PMDockWidgetHeaderDrag( PMDockWidgetAbstractHeader* parent, PMDockWidget* dock, const char* name )
+:PMDockWidgetAbstractHeaderDrag( parent, dock, name )
+{
+}
+
+void PMDockWidgetHeaderDrag::paintEvent( QPaintEvent* )
+{
+ QPainter paint;
+
+ paint.begin( this );
+
+ style().drawPrimitive (QStyle::PE_DockWindowHandle, &paint, QRect(0,0,width(), height()), colorGroup());
+
+ paint.end();
+}
+/*************************************************************************/
+PMDockWidgetAbstractHeader::PMDockWidgetAbstractHeader( PMDockWidget* parent, const char* name )
+:QFrame( parent, name )
+{
+}
+/*************************************************************************/
+PMDockWidgetHeader::PMDockWidgetHeader( PMDockWidget* parent, const char* name )
+:PMDockWidgetAbstractHeader( parent, name )
+{
+ layout = new QHBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ drag = new PMDockWidgetHeaderDrag( this, parent );
+
+ closeButton = new PMDockButton_Private( this, "DockCloseButton" );
+ closeButton->setPixmap( const_cast< const char** >(close_xpm) );
+ int buttonWidth = 9, buttonHeight = 9;
+ closeButton->setFixedSize(buttonWidth,buttonHeight);
+ connect( closeButton, SIGNAL(clicked()), parent, SIGNAL(headerCloseButtonClicked()));
+ // MODIFICATION (zehender)
+ // The shell will delete the widget
+ // undock is unnecessary
+ // connect( closeButton, SIGNAL(clicked()), parent, SLOT(undock()));
+
+ stayButton = new PMDockButton_Private( this, "DockStayButton" );
+ stayButton->setToggleButton( true );
+ stayButton->setPixmap( const_cast< const char** >(not_close_xpm) );
+ stayButton->setFixedSize(buttonWidth,buttonHeight);
+ connect( stayButton, SIGNAL(clicked()), this, SLOT(slotStayClicked()));
+ stayButton->hide( );
+
+ dockbackButton = new PMDockButton_Private( this, "DockbackButton" );
+ dockbackButton->setPixmap( const_cast< const char** >(dockback_xpm));
+ dockbackButton->setFixedSize(buttonWidth,buttonHeight);
+ connect( dockbackButton, SIGNAL(clicked()), parent, SIGNAL(headerDockbackButtonClicked()));
+ connect( dockbackButton, SIGNAL(clicked()), parent, SLOT(dockBack()));
+
+ // MODIFICATION (zehender)
+ // Add a button to undock the widget and dock it as top level
+ // widget to the desktop
+ toDesktopButton = new PMDockButton_Private( this, "ToDesktopButton" );
+ toDesktopButton->setPixmap( const_cast< const char** >(todesktop_xpm));
+ toDesktopButton->setFixedSize(buttonWidth,buttonHeight);
+ connect( toDesktopButton, SIGNAL(clicked()), parent, SLOT(toDesktop()));
+
+ layout->addWidget( drag );
+ layout->addWidget( dockbackButton );
+ layout->addWidget( toDesktopButton );
+ layout->addWidget( stayButton );
+ layout->addWidget( closeButton );
+ layout->activate();
+ drag->setFixedHeight( layout->minimumSize().height() );
+}
+
+void PMDockWidgetHeader::setTopLevel( bool isTopLevel )
+{
+ if ( isTopLevel ){
+ PMDockWidget* par = (PMDockWidget*)parent();
+ if( par) {
+ if( par->isDockBackPossible())
+ dockbackButton->show();
+ else
+ dockbackButton->hide();
+ }
+ stayButton->hide();
+ closeButton->hide();
+ toDesktopButton->hide();
+ drag->setEnabled( true );
+ } else {
+ dockbackButton->hide();
+ stayButton->hide();
+ closeButton->show();
+ toDesktopButton->show();
+ }
+ layout->activate();
+ updateGeometry();
+}
+
+void PMDockWidgetHeader::setDragPanel( PMDockWidgetHeaderDrag* nd )
+{
+ if ( !nd ) return;
+
+ delete layout;
+ layout = new QHBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ delete drag;
+ drag = nd;
+
+ layout->addWidget( drag );
+ layout->addWidget( dockbackButton );
+ layout->addWidget( toDesktopButton );
+ layout->addWidget( stayButton );
+ layout->addWidget( closeButton );
+ layout->activate();
+ drag->setFixedHeight( layout->minimumSize().height() );
+}
+
+void PMDockWidgetHeader::slotStayClicked()
+{
+ setDragEnabled(!stayButton->isOn());
+}
+
+bool PMDockWidgetHeader::dragEnabled() const
+{
+ return drag->isEnabled();
+}
+
+void PMDockWidgetHeader::setDragEnabled(bool b)
+{
+ stayButton->setOn(!b);
+ closeButton->setEnabled(b);
+ drag->setEnabled(b);
+}
+
+#ifndef NO_KDE2
+void PMDockWidgetHeader::saveConfig( KConfig* c )
+{
+ c->writeEntry( QString("%1%2").arg(parent()->name()).arg(":stayButton"), stayButton->isOn() );
+}
+
+void PMDockWidgetHeader::loadConfig( KConfig* c )
+{
+ setDragEnabled( !c->readBoolEntry( QString("%1%2").arg(parent()->name()).arg(":stayButton"), false ) );
+}
+#endif
+
+/*************************************************************************/
+PMDockWidget::PMDockWidget( PMDockManager* dockManager, const char* name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel, WFlags f)
+: QWidget( parent, name, f )
+ ,formerBrotherDockWidget(0L)
+ ,currentDockPos(DockNone)
+ ,formerDockPos(DockNone)
+ ,pix(new QPixmap(pixmap))
+ ,prevSideDockPosBeforeDrag(DockNone)
+{
+ d = new PMDockWidgetPrivate(); // create private data
+
+ d->_parent = parent;
+
+ layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ manager = dockManager;
+ manager->childDock->append( this );
+ installEventFilter( manager );
+
+ header = 0L;
+ setHeader( new PMDockWidgetHeader( this, "AutoCreatedDockHeader" ) );
+ if( strCaption == 0L)
+ setCaption( name );
+ else
+ setCaption( strCaption);
+
+ if( strTabPageLabel == " ")
+ setTabPageLabel( caption());
+ else
+ setTabPageLabel( strTabPageLabel);
+
+ eDocking = DockFullDocking;
+ sDocking = DockFullSite;
+
+ isGroup = false;
+ isTabGroup = false;
+
+ setIcon( pixmap);
+ widget = 0L;
+
+ QObject::connect(this, SIGNAL(hasUndocked()), manager->main, SLOT(slotDockWidgetUndocked()) );
+ applyToWidget( parent, QPoint(0,0) );
+}
+
+void PMDockWidget::slotSetCaption( const QString& str )
+{
+ setTabPageLabel( str );
+ setCaption( str );
+}
+
+PMDockWidget::~PMDockWidget()
+{
+ if ( !manager->undockProcess ){
+ d->blockHasUndockedSignal = true;
+ undock();
+ d->blockHasUndockedSignal = false;
+ }
+ emit iMBeingClosed();
+ manager->childDock->remove( this );
+ delete pix;
+ delete d; // destroy private data
+}
+
+void PMDockWidget::setHeader( PMDockWidgetAbstractHeader* h )
+{
+ if ( !h ) return;
+
+ if ( header ){
+ delete header;
+ delete layout;
+ header = h;
+ layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+ layout->addWidget( header );
+ setWidget( widget );
+ } else {
+ header = h;
+ layout->addWidget( header );
+ }
+}
+
+void PMDockWidget::setEnableDocking( int pos )
+{
+ eDocking = pos;
+ updateHeader();
+}
+
+void PMDockWidget::updateHeader()
+{
+ if ( parent() ){
+ if ( (parent() == manager->main) || isGroup || (eDocking == PMDockWidget::DockNone) ){
+ header->hide();
+ } else {
+ header->setTopLevel( false );
+ header->show();
+ }
+ } else {
+ header->setTopLevel( true );
+ header->show();
+ }
+}
+
+void PMDockWidget::applyToWidget( QWidget* s, const QPoint& p )
+{
+ if ( parent() != s )
+ {
+ hide();
+ reparent(s, 0, QPoint(0,0), false);
+ }
+
+ if ( s && s->inherits("PMDockMainWindow") ){
+ ((PMDockMainWindow*)s)->setView( this );
+ }
+
+ if ( s == manager->main ){
+ setGeometry( QRect(QPoint(0,0), manager->main->geometry().size()) );
+ }
+
+ if ( !s )
+ {
+ move(p);
+
+#ifndef NO_KDE2
+#ifdef Q_WS_X11
+ if (d->transient && d->_parent)
+ XSetTransientForHint( qt_xdisplay(), winId(), d->_parent->winId() );
+
+ KWin::setType( winId(), d->windowType );
+#endif
+#endif
+
+ }
+ updateHeader();
+
+ setIcon(*pix);
+}
+
+void PMDockWidget::show()
+{
+ if ( parent() || manager->main->isVisible() )
+ if ( !parent() ){
+ emit manager->setDockDefaultPos( this );
+ emit setDockDefaultPos();
+ if ( parent() ){
+ makeDockVisible();
+ } else {
+ QWidget::show();
+ }
+ } else {
+ QWidget::show();
+ }
+}
+
+#ifndef NO_KDE2
+
+void PMDockWidget::setDockWindowType (NET::WindowType windowType)
+{
+ d->windowType = windowType;
+ applyToWidget( parentWidget(), QPoint(0,0) );
+}
+
+#endif
+
+void PMDockWidget::setDockWindowTransient (QWidget *parent, bool transientEnabled)
+{
+ d->_parent = parent;
+ d->transient = transientEnabled;
+ applyToWidget( parentWidget(), QPoint(0,0) );
+}
+
+bool PMDockWidget::event( QEvent* pevent )
+{
+ switch ( pevent->type() )
+ {
+ #undef FocusIn
+ case QEvent::FocusIn:
+ if (widget && !d->pendingFocusInEvent) {
+ d->pendingFocusInEvent = true;
+ widget->setFocus();
+ }
+ d->pendingFocusInEvent = false;
+ break;
+ case QEvent::ChildRemoved:
+ if ( widget == ((QChildEvent*)pevent)->child() ) widget = 0L;
+ break;
+ case QEvent::Show:
+ if ( widget ) widget->show();
+ emit manager->change();
+ break;
+ case QEvent::Hide:
+ if ( widget ) widget->hide();
+ emit manager->change();
+ break;
+ case QEvent::CaptionChange:
+ if ( parentWidget() ){
+ if ( parent()->inherits("PMDockSplitter") ){
+ ((PMDockSplitter*)(parent()))->updateName();
+ }
+ if ( parentDockTabGroup() ){
+ setDockTabName( parentDockTabGroup() );
+ parentDockTabGroup()->setTabLabel( this, tabPageLabel() );
+ }
+ }
+ break;
+ case QEvent::Close:
+ // MODIFICATION (zehender)
+ // Top level widget is closed
+ // emit same signal as if the widget is docked and closed with
+ // the header button
+ emit headerCloseButtonClicked( );
+ // emit iMBeingClosed();
+ break;
+ default:
+ break;
+ }
+ #undef KeyPress
+ bool processed = QWidget::event( pevent );
+ if( pevent->type( ) == QEvent::AccelOverride && !processed && !parent( ) ){
+ // MODIFICATION (zehender)
+ // floating widget, post event to main window
+ processed = qApp->sendEvent( manager->dockMainWidget( ), pevent );
+ }
+ return processed;
+}
+
+PMDockWidget* PMDockWidget::manualDock( PMDockWidget* target, DockPosition dockPos, int spliPos, QPoint pos, bool check, int tabIndex )
+{
+ if (this == target)
+ return 0L; // docking to itself not possible
+
+ bool succes = true; // tested flag
+
+ // do not dock into a floating widget
+ if( target && !target->parent( ) )
+ target = 0;
+
+ // check allowed this dock submit this operations
+ if ( !(eDocking & (int)dockPos) ){
+ succes = false;
+ }
+
+ // check allowed target submit this operations
+ if ( target && !(target->dockSite( ) & (int)dockPos) ){
+ succes = false;
+ }
+
+ if ( parent() && !parent()->inherits("PMDockSplitter") && !parentDockTabGroup() ){
+ succes = false;
+ }
+
+ // if docking to a tab group, and position is not center
+ // dock to the parent of the tab group
+ if( target && ( dockPos != PMDockWidget::DockCenter )
+ && ( dockPos != PMDockWidget::DockNone ) )
+ {
+ QWidget* pdt = target->parentDockTabGroup( );
+ if( pdt )
+ return manualDock( ( PMDockWidget* ) ( pdt->parent( ) ),
+ dockPos, spliPos, pos, check, tabIndex );
+ }
+
+ if ( !succes ){
+ // try to make another manualDock
+ PMDockWidget* dock_result = 0L;
+ if ( target && !check ){
+ PMDockWidget::DockPosition another__dockPos = PMDockWidget::DockNone;
+ switch ( dockPos ){
+ case PMDockWidget::DockLeft : another__dockPos = PMDockWidget::DockRight ; break;
+ case PMDockWidget::DockRight : another__dockPos = PMDockWidget::DockLeft ; break;
+ case PMDockWidget::DockTop : another__dockPos = PMDockWidget::DockBottom; break;
+ case PMDockWidget::DockBottom: another__dockPos = PMDockWidget::DockTop ; break;
+ default: break;
+ }
+ dock_result = target->manualDock( this, another__dockPos, spliPos, pos, true, tabIndex );
+ }
+ return dock_result;
+ }
+ // end check block
+
+ d->blockHasUndockedSignal = true;
+ undock();
+ d->blockHasUndockedSignal = false;
+
+ if ( !target ){
+ move( pos );
+ show();
+ emit manager->change();
+ return this;
+ }
+
+ PMDockTabGroup* parentTab = target->parentDockTabGroup();
+ if ( parentTab ){
+ // add to existing TabGroup
+ applyToWidget( parentTab );
+ parentTab->insertTab( this, icon() ? *icon() : QPixmap(),
+ tabPageLabel(), tabIndex );
+ setDockTabName( parentTab );
+ if( !toolTipStr.isEmpty())
+ parentTab->setTabToolTip( this, toolTipStr);
+
+ currentDockPos = PMDockWidget::DockCenter;
+ emit manager->change();
+ return (PMDockWidget*)parentTab->parent();
+ }
+
+ // MODIFICATION (Zehender):
+ // If DockPosition is DockLeft or DockRight, add the widget
+ // left or right of the target, so that a new vertical splitter
+ // (a splitter with horizontal widget layout :-) is created
+ // that spawns the full height of the main view
+
+ if( ( dockPos == PMDockWidget::DockLeft ) ||
+ ( dockPos == PMDockWidget::DockRight ) )
+ {
+ PMDockWidget* newTarget = target;
+ bool found = false;
+ QWidget* wtarget = target;
+ while( wtarget && !found )
+ {
+ if( wtarget->inherits( "PMDockWidget" ) )
+ {
+ PMDockWidget* dw = ( PMDockWidget* ) wtarget;
+ newTarget = dw;
+ QWidget* pw = wtarget->parentWidget( );
+ if( pw )
+ {
+ if( pw->inherits( "PMDockSplitter" ) )
+ {
+ PMDockSplitter* ds = ( PMDockSplitter* ) pw;
+ if( ds->splitterOrientation( ) == Vertical )
+ found = true;
+ }
+ }
+ }
+ wtarget = wtarget->parentWidget( );
+ }
+
+ if( newTarget != target )
+ return manualDock( newTarget, dockPos, spliPos, pos, check, tabIndex );
+ }
+
+ // END MODIFICATION
+
+ // create a new dockwidget that will contain the target and this
+ QWidget* parentDock = target->parentWidget();
+ PMDockWidget* newDock = new PMDockWidget( manager, "tempName", QPixmap(""), parentDock );
+ newDock->currentDockPos = target->currentDockPos;
+
+ if ( dockPos == PMDockWidget::DockCenter ){
+ newDock->isTabGroup = true;
+ } else {
+ newDock->isGroup = true;
+ }
+ newDock->eDocking = (target->eDocking & eDocking) & (~(int)PMDockWidget::DockCenter);
+
+ newDock->applyToWidget( parentDock );
+
+ if ( !parentDock ){
+ // dock to a toplevel dockwidget means newDock is toplevel now
+ newDock->move( target->frameGeometry().topLeft() );
+ newDock->resize( target->geometry().size() );
+ if ( target->isVisibleToTLW() ) newDock->show();
+ }
+
+ // redirect the dockback button to the new dockwidget
+ if( target->formerBrotherDockWidget != 0L) {
+ newDock->formerBrotherDockWidget = target->formerBrotherDockWidget;
+ if( formerBrotherDockWidget != 0L)
+ QObject::connect( newDock->formerBrotherDockWidget, SIGNAL(iMBeingClosed()),
+ newDock, SLOT(loseFormerBrotherDockWidget()) );
+ target->loseFormerBrotherDockWidget();
+ }
+ newDock->formerDockPos = target->formerDockPos;
+
+ if ( dockPos == PMDockWidget::DockCenter )
+ {
+ PMDockTabGroup* tab = new PMDockTabGroup( newDock, "_dock_tab");
+ QObject::connect(tab, SIGNAL(currentChanged(QWidget*)), d, SLOT(slotFocusEmbeddedWidget(QWidget*)));
+ newDock->setWidget( tab );
+
+ target->applyToWidget( tab );
+ applyToWidget( tab );
+
+
+ tab->insertTab( target, target->icon() ? *(target->icon()) : QPixmap(),
+ target->tabPageLabel() );
+ if( !target->toolTipString().isEmpty())
+ tab->setTabToolTip( target, target->toolTipString());
+
+ tab->insertTab( this, icon() ? *icon() : QPixmap(),
+ tabPageLabel(), tabIndex );
+ if( !toolTipString().isEmpty())
+ tab->setTabToolTip( this, toolTipString());
+
+ setDockTabName( tab );
+ tab->show();
+
+ currentDockPos = DockCenter;
+ target->formerDockPos = target->currentDockPos;
+ target->currentDockPos = DockCenter;
+ }
+ else {
+ // if to dock not to the center of the target dockwidget,
+ // dock to newDock
+ PMDockSplitter* panner = 0L;
+ if ( dockPos == PMDockWidget::DockTop || dockPos == PMDockWidget::DockBottom ) panner = new PMDockSplitter( newDock, "_dock_split_", Horizontal, spliPos, manager->splitterHighResolution() );
+ if ( dockPos == PMDockWidget::DockLeft || dockPos == PMDockWidget::DockRight ) panner = new PMDockSplitter( newDock, "_dock_split_", Vertical , spliPos, manager->splitterHighResolution() );
+ newDock->setWidget( panner );
+
+ panner->setOpaqueResize(manager->splitterOpaqueResize());
+ panner->setKeepSize(manager->splitterKeepSize());
+ panner->setFocusPolicy( NoFocus );
+ target->applyToWidget( panner );
+ applyToWidget( panner );
+ target->formerDockPos = target->currentDockPos;
+ if ( dockPos == PMDockWidget::DockRight) {
+ panner->activate( target, this );
+ currentDockPos = PMDockWidget::DockRight;
+ target->currentDockPos = PMDockWidget::DockLeft;
+ }
+ else if( dockPos == PMDockWidget::DockBottom) {
+ panner->activate( target, this );
+ currentDockPos = PMDockWidget::DockBottom;
+ target->currentDockPos = PMDockWidget::DockTop;
+ }
+ else if( dockPos == PMDockWidget::DockTop) {
+ panner->activate( this, target );
+ currentDockPos = PMDockWidget::DockTop;
+ target->currentDockPos = PMDockWidget::DockBottom;
+ }
+ else if( dockPos == PMDockWidget::DockLeft) {
+ panner->activate( this, target );
+ currentDockPos = PMDockWidget::DockLeft;
+ target->currentDockPos = PMDockWidget::DockRight;
+ }
+ target->show();
+ show();
+ panner->show();
+ }
+
+ if ( parentDock ){
+ if ( parentDock->inherits("PMDockSplitter") ){
+ PMDockSplitter* sp = (PMDockSplitter*)parentDock;
+ sp->deactivate();
+ if ( sp->getFirst() == target )
+ sp->activate( newDock, 0L );
+ else
+ sp->activate( 0L, newDock );
+ }
+ }
+
+ newDock->show();
+ emit target->docking( this, dockPos );
+ emit manager->replaceDock( target, newDock );
+ emit manager->change();
+
+ return newDock;
+}
+
+PMDockTabGroup* PMDockWidget::parentDockTabGroup() const
+{
+ if ( !parent() ) return 0L;
+ QWidget* candidate = parentWidget()->parentWidget();
+ if ( candidate && candidate->inherits("PMDockTabGroup") ) return (PMDockTabGroup*)candidate;
+ return 0L;
+}
+
+void PMDockWidget::toDesktop()
+{
+ QPoint p = mapToGlobal( QPoint( -30, -30 ) );
+ if( p.x( ) < 0 )
+ p.setX( 0 );
+ if( p.y( ) < 0 )
+ p.setY( 0 );
+ manualDock( 0, DockDesktop, 50, p );
+}
+
+void PMDockWidget::undock()
+{
+ QWidget* parentW = parentWidget();
+ if ( !parentW ){
+ hide();
+ if (!d->blockHasUndockedSignal)
+ emit hasUndocked();
+ return;
+ }
+
+ formerDockPos = currentDockPos;
+ currentDockPos = PMDockWidget::DockDesktop;
+
+ manager->blockSignals(true);
+ manager->undockProcess = true;
+
+ bool isV = parentW->isVisibleToTLW();
+
+ PMDockTabGroup* parentTab = parentDockTabGroup();
+ if ( parentTab ){
+ d->index = parentTab->indexOf( this); // memorize the page position in the tab widget
+ parentTab->removePage( this );
+ formerBrotherDockWidget = (PMDockWidget*)parentTab->page(0);
+ QObject::connect( formerBrotherDockWidget, SIGNAL(iMBeingClosed()),
+ this, SLOT(loseFormerBrotherDockWidget()) );
+ applyToWidget( 0L );
+ if ( parentTab->count() == 1 ){
+
+ // last subdock widget in the tab control
+ PMDockWidget* lastTab = (PMDockWidget*)parentTab->page(0);
+ parentTab->removePage( lastTab );
+ lastTab->applyToWidget( 0L );
+ lastTab->move( parentTab->mapToGlobal(parentTab->frameGeometry().topLeft()) );
+
+ // PMDockTabGroup always have a parent that is a PMDockWidget
+ PMDockWidget* parentOfTab = (PMDockWidget*)parentTab->parent();
+ delete parentTab; // PMDockTabGroup
+
+ QWidget* parentOfDockWidget = parentOfTab->parentWidget();
+ if ( parentOfDockWidget == 0L ){
+ if ( isV ) lastTab->show();
+ } else {
+ if ( parentOfDockWidget->inherits("PMDockSplitter") ){
+ PMDockSplitter* split = (PMDockSplitter*)parentOfDockWidget;
+ lastTab->applyToWidget( split );
+ split->deactivate();
+ if ( split->getFirst() == parentOfTab ){
+ split->activate( lastTab );
+ if ( ((PMDockWidget*)split->parent())->splitterOrientation == Vertical )
+ emit ((PMDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, PMDockWidget::DockLeft );
+ else
+ emit ((PMDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, PMDockWidget::DockTop );
+ } else {
+ split->activate( 0L, lastTab );
+ if ( ((PMDockWidget*)split->parent())->splitterOrientation == Vertical )
+ emit ((PMDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, PMDockWidget::DockRight );
+ else
+ emit ((PMDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, PMDockWidget::DockBottom );
+ }
+ split->show();
+ } else {
+ lastTab->applyToWidget( parentOfDockWidget );
+ }
+ lastTab->show();
+ }
+ manager->blockSignals(false);
+ emit manager->replaceDock( parentOfTab, lastTab );
+ lastTab->currentDockPos = parentOfTab->currentDockPos;
+ emit parentOfTab->iMBeingClosed();
+ manager->blockSignals(true);
+ delete parentOfTab;
+
+ } else {
+ setDockTabName( parentTab );
+ }
+ } else {
+/*********************************************************************************************/
+ if ( parentW->inherits("PMDockSplitter") ){
+ PMDockSplitter* parentSplitterOfDockWidget = (PMDockSplitter*)parentW;
+ d->splitPosInPercent = parentSplitterOfDockWidget->separatorPos();
+
+ PMDockWidget* secondWidget = (PMDockWidget*)parentSplitterOfDockWidget->getAnother( this );
+ PMDockWidget* group = (PMDockWidget*)parentSplitterOfDockWidget->parentWidget();
+ formerBrotherDockWidget = secondWidget;
+ applyToWidget( 0L );
+ group->hide();
+
+ if( formerBrotherDockWidget != 0L)
+ QObject::connect( formerBrotherDockWidget, SIGNAL(iMBeingClosed()),
+ this, SLOT(loseFormerBrotherDockWidget()) );
+
+ if ( !group->parentWidget() ){
+ secondWidget->applyToWidget( 0L, group->frameGeometry().topLeft() );
+ secondWidget->resize( group->width(), group->height() );
+ } else {
+ QWidget* obj = group->parentWidget();
+ secondWidget->applyToWidget( obj );
+ if ( obj->inherits("PMDockSplitter") ){
+ PMDockSplitter* parentOfGroup = (PMDockSplitter*)obj;
+ parentOfGroup->deactivate();
+
+ if ( parentOfGroup->getFirst() == group )
+ parentOfGroup->activate( secondWidget );
+ else
+ parentOfGroup->activate( 0L, secondWidget );
+ }
+ }
+ secondWidget->currentDockPos = group->currentDockPos;
+ secondWidget->formerDockPos = group->formerDockPos;
+ delete parentSplitterOfDockWidget;
+ manager->blockSignals(false);
+ emit manager->replaceDock( group, secondWidget );
+ emit group->iMBeingClosed();
+ manager->blockSignals(true);
+ delete group;
+
+ if ( isV ) secondWidget->show();
+ } else {
+ applyToWidget( 0L );
+ }
+/*********************************************************************************************/
+ }
+ manager->blockSignals(false);
+ if (!d->blockHasUndockedSignal)
+ emit manager->change();
+ manager->undockProcess = false;
+
+ if (!d->blockHasUndockedSignal)
+ emit hasUndocked();
+}
+
+void PMDockWidget::setWidget( QWidget* mw )
+{
+ if ( !mw ) return;
+
+ if ( mw->parent() != this ){
+ mw->reparent(this, 0, QPoint(0,0), false);
+ }
+
+ widget = mw;
+ delete layout;
+
+ layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ layout->addWidget( header );
+ layout->addWidget( widget,1 );
+}
+
+void PMDockWidget::setDockTabName( PMDockTabGroup* tab )
+{
+ QString listOfName;
+ QString listOfCaption;
+ for ( int i = 0; i < tab->count(); ++i ) {
+ QWidget *w = tab->page( i );
+ listOfCaption.append( w->caption() ).append(",");
+ listOfName.append( w->name() ).append(",");
+ }
+ listOfCaption.remove( listOfCaption.length()-1, 1 );
+ listOfName.remove( listOfName.length()-1, 1 );
+
+ tab->parentWidget()->setName( listOfName.utf8() );
+ tab->parentWidget()->setCaption( listOfCaption );
+
+ tab->parentWidget()->repaint( false ); // PMDockWidget->repaint
+ if ( tab->parentWidget()->parent() )
+ if ( tab->parentWidget()->parent()->inherits("PMDockSplitter") )
+ ((PMDockSplitter*)(tab->parentWidget()->parent()))->updateName();
+}
+
+bool PMDockWidget::mayBeHide() const
+{
+ bool f = (parent() != manager->main);
+ return ( !isGroup && !isTabGroup && f && isVisible() && ( eDocking != (int)PMDockWidget::DockNone ) );
+}
+
+bool PMDockWidget::mayBeShow() const
+{
+ bool f = (parent() != manager->main);
+ return ( !isGroup && !isTabGroup && f && !isVisible() );
+}
+
+void PMDockWidget::changeHideShowState()
+{
+ if ( mayBeHide() ){
+ undock();
+ return;
+ }
+
+ if ( mayBeShow() ){
+ if ( manager->main->inherits("PMDockMainWindow") ){
+ ((PMDockMainWindow*)manager->main)->makeDockVisible(this);
+ } else {
+ makeDockVisible();
+ }
+ }
+}
+
+void PMDockWidget::makeDockVisible()
+{
+ if ( parentDockTabGroup() ){
+ parentDockTabGroup()->showPage( this );
+ }
+ if ( isVisible() ) return;
+
+ QWidget* p = parentWidget();
+ while ( p ){
+ if ( !p->isVisible() )
+ p->show();
+ p = p->parentWidget();
+ }
+ if( parent() == 0L) // is undocked
+ dockBack();
+ show();
+}
+
+void PMDockWidget::loseFormerBrotherDockWidget()
+{
+ if( formerBrotherDockWidget != 0L)
+ QObject::disconnect( formerBrotherDockWidget, SIGNAL(iMBeingClosed()),
+ this, SLOT(loseFormerBrotherDockWidget()) );
+ formerBrotherDockWidget = 0L;
+ repaint();
+}
+
+void PMDockWidget::dockBack()
+{
+ if( formerBrotherDockWidget) {
+ // search all children if it tries to dock back to a child
+ bool found = false;
+ QObjectList* cl = queryList("PMDockWidget");
+ QObjectListIt it( *cl );
+ QObject * obj;
+ while ( !found && (obj=it.current()) != 0 ) {
+ ++it;
+ QWidget* widg = (QWidget*)obj;
+ if( widg == formerBrotherDockWidget)
+ found = true;
+ }
+ delete cl;
+
+ if( !found) {
+ // can dock back to the former brother dockwidget
+ manualDock( formerBrotherDockWidget, formerDockPos, d->splitPosInPercent, QPoint(0,0), false, d->index);
+ formerBrotherDockWidget = 0L;
+ makeDockVisible();
+ return;
+ }
+ }
+
+ // else dockback to the dockmainwindow (default behaviour)
+ manualDock( ((PMDockMainWindow*)manager->main)->getMainDockWidget(), formerDockPos, d->splitPosInPercent, QPoint(0,0), false, d->index);
+ formerBrotherDockWidget = 0L;
+ if (parent())
+ makeDockVisible();
+}
+
+bool PMDockWidget::isDockBackPossible() const
+{
+ if( (formerBrotherDockWidget == 0L) || !(formerBrotherDockWidget->dockSite() & formerDockPos))
+ return false;
+ else
+ return true;
+}
+
+/**************************************************************************************/
+
+class PMDockManager::PMDockManagerPrivate
+{
+public:
+ /**
+ * This rectangle is used to highlight the current dockposition. It stores global screen coordinates.
+ */
+ QRect dragRect;
+
+ /**
+ * This rectangle is used to erase the previously highlighted dockposition. It stores global screen coordinates.
+ */
+ QRect oldDragRect;
+
+ /**
+ * This flag stores the information if dragging is ready to start. Used between mousePress and mouseMove event.
+ */
+ bool readyToDrag;
+
+ /**
+ * This variable stores the offset of the mouse cursor to the upper left edge of the current drag widget.
+ */
+ QPoint dragOffset;
+
+ /**
+ * These flags store information about the splitter behaviour
+ */
+ bool splitterOpaqueResize;
+ bool splitterKeepSize;
+ bool splitterHighResolution;
+};
+
+PMDockManager::PMDockManager( QWidget* mainWindow , const char* name )
+:QObject( mainWindow, name )
+ ,main(mainWindow)
+ ,currentDragWidget(0L)
+ ,currentMoveWidget(0L)
+ ,childDockWidgetList(0L)
+ ,autoCreateDock(0L)
+ ,storeW(0)
+ ,storeH(0)
+ ,draging(false)
+ ,undockProcess(false)
+ ,dropCancel(true)
+{
+ d = new PMDockManagerPrivate;
+ d->splitterOpaqueResize = false;
+ d->splitterKeepSize = false;
+ d->splitterHighResolution = false;
+
+ main->installEventFilter( this );
+
+ undockProcess = false;
+
+ menuData = new QPtrList<MenuDockData>;
+ menuData->setAutoDelete( true );
+ menuData->setAutoDelete( true );
+
+#ifndef NO_KDE2
+ menu = new KPopupMenu();
+#else
+ menu = new QPopupMenu();
+#endif
+
+ connect( menu, SIGNAL(aboutToShow()), SLOT(slotMenuPopup()) );
+ connect( menu, SIGNAL(activated(int)), SLOT(slotMenuActivated(int)) );
+
+ childDock = new QObjectList();
+ childDock->setAutoDelete( false );
+}
+
+PMDockManager::~PMDockManager()
+{
+ delete menuData;
+ delete menu;
+
+ QObjectListIt it( *childDock );
+ PMDockWidget * obj;
+
+ while ( (obj=(PMDockWidget*)it.current()) ) {
+ delete obj;
+ }
+ delete childDock;
+ delete d;
+}
+
+void PMDockManager::activate()
+{
+ QObjectListIt it( *childDock );
+ PMDockWidget * obj;
+
+ while ( (obj=(PMDockWidget*)it.current()) ) {
+ ++it;
+ if ( obj->widget ) obj->widget->show();
+ if ( !obj->parentDockTabGroup() ){
+ obj->show();
+ }
+ }
+ if ( !main->inherits("QDialog") ) main->show();
+}
+
+bool PMDockManager::eventFilter( QObject *obj, QEvent *event )
+{
+/* This doesn't seem to fullfill any sense, other than breaking
+ QMainWindow's layout all over the place
+ The first child of the mainwindow is not necessarily a meaningful
+ content widget but in Qt3's QMainWindow it can easily be a QToolBar.
+ In short: QMainWindow knows how to layout its children, no need to
+ mess that up.
+
+ >>>>>I need this in the PMDockArea at the moment (JoWenn)
+
+ if ( obj == main && event->type() == QEvent::Resize && dynamic_cast<PMDockArea*>(main) && main->children() ){
+#ifndef NO_KDE2
+ kdDebug()<<"PMDockManager::eventFilter(): main is a PMDockArea and there are children"<<endl;
+#endif
+ QWidget* fc = (QWidget*)main->children()->getFirst();
+ if ( fc )
+ fc->setGeometry( QRect(QPoint(0,0), main->geometry().size()) );
+ }
+*/
+
+ if ( obj->inherits("PMDockWidgetAbstractHeaderDrag") ){
+ PMDockWidget* pDockWdgAtCursor = 0L;
+ PMDockWidget* curdw = ((PMDockWidgetAbstractHeaderDrag*)obj)->dockWidget();
+ switch ( event->type() ){
+ case QEvent::MouseButtonDblClick:
+ if (curdw->currentDockPos == PMDockWidget::DockDesktop) curdw->dockBack();
+ else curdw->toDesktop( );
+ break;
+ case QEvent::MouseButtonPress:
+ if ( ((QMouseEvent*)event)->button() == LeftButton ){
+ if ( curdw->eDocking != (int)PMDockWidget::DockNone ){
+ dropCancel = true;
+ curdw->setFocus();
+ qApp->processOneEvent();
+
+ currentDragWidget = curdw;
+ currentMoveWidget = 0L;
+ childDockWidgetList = new QWidgetList();
+ childDockWidgetList->append( curdw );
+ findChildDockWidget( curdw, *childDockWidgetList );
+
+ d->oldDragRect = QRect();
+ d->dragRect = QRect(curdw->geometry());
+ QPoint p = curdw->mapToGlobal(QPoint(0,0));
+ d->dragRect.moveTopLeft(p);
+ drawDragRectangle();
+ d->readyToDrag = true;
+
+ d->dragOffset = QCursor::pos()-currentDragWidget->mapToGlobal(QPoint(0,0));
+ }
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ if ( ((QMouseEvent*)event)->button() == LeftButton ){
+ if ( draging ){
+ if ( !dropCancel )
+ drop();
+ else
+ cancelDrop();
+ }
+ if (d->readyToDrag) {
+ d->readyToDrag = false;
+ d->oldDragRect = QRect();
+ d->dragRect = QRect(curdw->geometry());
+ QPoint p = curdw->mapToGlobal(QPoint(0,0));
+ d->dragRect.moveTopLeft(p);
+ drawDragRectangle();
+ currentDragWidget = 0L;
+ delete childDockWidgetList;
+ childDockWidgetList = 0L;
+ }
+ draging = false;
+ dropCancel = true;
+ }
+ break;
+ case QEvent::MouseMove:
+ if ( draging ) {
+ pDockWdgAtCursor = findDockWidgetAt( QCursor::pos() );
+ PMDockWidget* oldMoveWidget = currentMoveWidget;
+ if ( currentMoveWidget && pDockWdgAtCursor == currentMoveWidget ) { //move
+ dragMove( currentMoveWidget, currentMoveWidget->mapFromGlobal( QCursor::pos() ) );
+ break;
+ } else {
+ if (dropCancel && curdw) {
+ d->dragRect = QRect(curdw->geometry());
+ QPoint p = curdw->mapToGlobal(QPoint(0,0));
+ d->dragRect.moveTopLeft(p);
+ }else
+ d->dragRect = QRect();
+
+ drawDragRectangle();
+ }
+
+ if ( !pDockWdgAtCursor && (curdw->eDocking & (int)PMDockWidget::DockDesktop) == 0 ){
+ // just moving at the desktop
+ currentMoveWidget = pDockWdgAtCursor;
+ curPos = PMDockWidget::DockDesktop;
+ } else {
+ if ( oldMoveWidget && pDockWdgAtCursor != currentMoveWidget ) { //leave
+ currentMoveWidget = pDockWdgAtCursor;
+ curPos = PMDockWidget::DockDesktop;
+ }
+ }
+
+ if ( oldMoveWidget != pDockWdgAtCursor && pDockWdgAtCursor ) { //enter pDockWdgAtCursor
+ currentMoveWidget = pDockWdgAtCursor;
+ curPos = PMDockWidget::DockDesktop;
+ }
+ } else {
+ if (d->readyToDrag) {
+ d->readyToDrag = false;
+ }
+ if ( (((QMouseEvent*)event)->state() == LeftButton) &&
+ (curdw->eDocking != (int)PMDockWidget::DockNone) ) {
+ startDrag( curdw);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return QObject::eventFilter( obj, event );
+}
+
+PMDockWidget* PMDockManager::findDockWidgetAt( const QPoint& pos )
+{
+ dropCancel = true;
+
+ if (!currentDragWidget)
+ return 0L; // pointer access safety
+
+ if (currentDragWidget->eDocking == (int)PMDockWidget::DockNone ) return 0L;
+
+ QWidget* p = QApplication::widgetAt( pos );
+ if ( !p ) {
+ dropCancel = false;
+ return 0L;
+ }
+#if defined(_OS_WIN32_) || defined(Q_OS_WIN32)
+ p = p->topLevelWidget();
+#endif
+ QWidget* w = 0L;
+ findChildDockWidget( w, p, p->mapFromGlobal(pos) );
+ if ( !w ){
+ if ( !p->inherits("PMDockWidget") ) {
+ return 0L;
+ }
+ w = p;
+ }
+ if ( qt_find_obj_child( w, "PMDockSplitter", "_dock_split_" ) ) return 0L;
+ if ( qt_find_obj_child( w, "PMDockTabGroup", "_dock_tab" ) ) return 0L;
+ if (!childDockWidgetList) return 0L;
+ if ( childDockWidgetList->find(w) != -1 ) return 0L;
+ if ( currentDragWidget->isGroup && ((PMDockWidget*)w)->parentDockTabGroup() ) return 0L;
+
+ PMDockWidget* www = (PMDockWidget*)w;
+ if ( www->dockSite( ) == (int)PMDockWidget::DockNone ) return 0L;
+
+ PMDockWidget::DockPosition curPos = PMDockWidget::DockDesktop;
+ QPoint cpos = www->mapFromGlobal( pos );
+
+ int ww = www->widget->width() / 3;
+ int hh = www->widget->height() / 3;
+
+ if ( cpos.y() <= hh ){
+ curPos = PMDockWidget::DockTop;
+ } else
+ if ( cpos.y() >= 2*hh ){
+ curPos = PMDockWidget::DockBottom;
+ } else
+ if ( cpos.x() <= ww ){
+ curPos = PMDockWidget::DockLeft;
+ } else
+ if ( cpos.x() >= 2*ww ){
+ curPos = PMDockWidget::DockRight;
+ } else
+ curPos = PMDockWidget::DockCenter;
+
+ if ( !(www->dockSite( ) & (int)curPos) ) return 0L;
+ if ( !(currentDragWidget->eDocking & (int)curPos) ) return 0L;
+ if ( www->manager != this ) return 0L;
+
+ dropCancel = false;
+ return www;
+}
+
+void PMDockManager::findChildDockWidget( QWidget*& ww, const QWidget* p, const QPoint& pos )
+{
+ if ( p->children() ) {
+ QWidget *w;
+ QObjectListIt it( *p->children() );
+ it.toLast();
+ while ( it.current() ) {
+ if ( it.current()->isWidgetType() ) {
+ w = (QWidget*)it.current();
+ if ( w->isVisible() && w->geometry().contains(pos) ) {
+ if ( w->inherits("PMDockWidget") ) ww = w;
+ findChildDockWidget( ww, w, w->mapFromParent(pos) );
+ return;
+ }
+ }
+ --it;
+ }
+ }
+ return;
+}
+
+void PMDockManager::findChildDockWidget( const QWidget* p, QWidgetList& list )
+{
+ if ( p->children() ) {
+ QWidget *w;
+ QObjectListIt it( *p->children() );
+ it.toLast();
+ while ( it.current() ) {
+ if ( it.current()->isWidgetType() ) {
+ w = (QWidget*)it.current();
+ if ( w->isVisible() ) {
+ if ( w->inherits("PMDockWidget") ) list.append( w );
+ findChildDockWidget( w, list );
+ }
+ }
+ --it;
+ }
+ }
+ return;
+}
+
+void PMDockManager::findFloatingWidgets( QPtrList<PMDockWidget>& l )
+{
+ QObjectListIt it( *childDock );
+ for( ; it.current( ); ++it )
+ if( it.current( )->inherits( "PMDockWidget" ) &&
+ !it.current( )->parent( ) )
+ l.append( ( PMDockWidget* ) it.current( ) );
+}
+
+void PMDockManager::startDrag( PMDockWidget* w )
+{
+ if(( w->currentDockPos == PMDockWidget::DockLeft) || ( w->currentDockPos == PMDockWidget::DockRight)
+ || ( w->currentDockPos == PMDockWidget::DockTop) || ( w->currentDockPos == PMDockWidget::DockBottom)) {
+ w->prevSideDockPosBeforeDrag = w->currentDockPos;
+
+ if ( w->parentWidget()->inherits("PMDockSplitter") ){
+ PMDockSplitter* parentSplitterOfDockWidget = (PMDockSplitter*)(w->parentWidget());
+ w->d->splitPosInPercent = parentSplitterOfDockWidget->separatorPos();
+ }
+ }
+
+ curPos = PMDockWidget::DockDesktop;
+ draging = true;
+
+ QApplication::setOverrideCursor(QCursor(sizeAllCursor));
+}
+
+void PMDockManager::dragMove( PMDockWidget* dw, QPoint pos )
+{
+ QPoint p = dw->mapToGlobal( dw->widget->pos() );
+ PMDockWidget::DockPosition oldPos = curPos;
+
+ QSize r = dw->widget->size();
+ if ( dw->parentDockTabGroup() ){
+ curPos = PMDockWidget::DockCenter;
+ if ( oldPos != curPos ) {
+ d->dragRect.setRect( p.x()+2, p.y()+2, r.width()-4, r.height()-4 );
+ }
+ return;
+ }
+
+ int w = r.width() / 3;
+ int h = r.height() / 3;
+
+ PMDockMainWindow* mw = ( PMDockMainWindow* ) parent( );
+ QWidget* cw = mw->centralWidget( );
+ QPoint cwp = cw->mapToGlobal( QPoint( 0, 0 ) );
+ int cwh = cw->height( );
+
+ if ( pos.y() <= h )
+ {
+ curPos = PMDockWidget::DockTop;
+ w = r.width();
+ }
+ else if ( pos.y() >= 2*h )
+ {
+ curPos = PMDockWidget::DockBottom;
+ p.setY( p.y() + 2*h );
+ w = r.width();
+ }
+ else if ( pos.x() <= w )
+ {
+ curPos = PMDockWidget::DockLeft;
+ h = r.height();
+ p.setY( cwp.y( ) );
+ h = cwh;
+ }
+ else if ( pos.x() >= 2*w )
+ {
+ curPos = PMDockWidget::DockRight;
+ p.setX( p.x() + 2*w );
+ p.setY( cwp.y( ) );
+ h = cwh;
+ }
+ else
+ {
+ curPos = PMDockWidget::DockCenter;
+ p.setX( p.x() + w );
+ p.setY( p.y() + h );
+ }
+
+ if ( oldPos != curPos ) {
+ d->dragRect.setRect( p.x(), p.y(), w, h );
+ drawDragRectangle();
+ }
+}
+
+
+void PMDockManager::cancelDrop()
+{
+ QApplication::restoreOverrideCursor();
+
+ delete childDockWidgetList;
+ childDockWidgetList = 0L;
+
+ d->dragRect = QRect(); // cancel drawing
+ drawDragRectangle(); // only the old rect will be deleted
+}
+
+
+void PMDockManager::drop()
+{
+ d->dragRect = QRect(); // cancel drawing
+ drawDragRectangle(); // only the old rect will be deleted
+
+ QApplication::restoreOverrideCursor();
+
+ delete childDockWidgetList;
+ childDockWidgetList = 0L;
+
+ if ( dropCancel ) return;
+ if ( !currentMoveWidget && ((currentDragWidget->eDocking & (int)PMDockWidget::DockDesktop) == 0) ) {
+ d->dragRect = QRect(); // cancel drawing
+ drawDragRectangle(); // only the old rect will be deleted
+ return;
+ }
+ if ( !currentMoveWidget && !currentDragWidget->parent() ) {
+ currentDragWidget->move( QCursor::pos() - d->dragOffset );
+ }
+ else {
+ int splitPos = currentDragWidget->d->splitPosInPercent;
+ // do we have to calculate 100%-splitPosInPercent?
+ if( (curPos != currentDragWidget->prevSideDockPosBeforeDrag) && (curPos != PMDockWidget::DockCenter) && (curPos != PMDockWidget::DockDesktop)) {
+ switch( currentDragWidget->prevSideDockPosBeforeDrag) {
+ case PMDockWidget::DockLeft: if(curPos != PMDockWidget::DockTop) splitPos = 100-splitPos; break;
+ case PMDockWidget::DockRight: if(curPos != PMDockWidget::DockBottom) splitPos = 100-splitPos; break;
+ case PMDockWidget::DockTop: if(curPos != PMDockWidget::DockLeft) splitPos = 100-splitPos; break;
+ case PMDockWidget::DockBottom: if(curPos != PMDockWidget::DockRight) splitPos = 100-splitPos; break;
+ default: break;
+ }
+ }
+ currentDragWidget->manualDock( currentMoveWidget, curPos , splitPos, QCursor::pos() - d->dragOffset );
+ currentDragWidget->makeDockVisible();
+ }
+}
+
+
+static QDomElement createStringEntry(QDomDocument &doc, const QString &tagName, const QString &str)
+{
+ QDomElement el = doc.createElement(tagName);
+
+ el.appendChild(doc.createTextNode(str));
+ return el;
+}
+
+
+static QDomElement createBoolEntry(QDomDocument &doc, const QString &tagName, bool b)
+{
+ return createStringEntry(doc, tagName, QString::fromLatin1(b? "true" : "false"));
+}
+
+
+static QDomElement createNumberEntry(QDomDocument &doc, const QString &tagName, int n)
+{
+ return createStringEntry(doc, tagName, QString::number(n));
+}
+
+
+static QDomElement createRectEntry(QDomDocument &doc, const QString &tagName, const QRect &rect)
+{
+ QDomElement el = doc.createElement(tagName);
+
+ QDomElement xel = doc.createElement("x");
+ xel.appendChild(doc.createTextNode(QString::number(rect.x())));
+ el.appendChild(xel);
+ QDomElement yel = doc.createElement("y");
+ yel.appendChild(doc.createTextNode(QString::number(rect.y())));
+ el.appendChild(yel);
+ QDomElement wel = doc.createElement("width");
+ wel.appendChild(doc.createTextNode(QString::number(rect.width())));
+ el.appendChild(wel);
+ QDomElement hel = doc.createElement("height");
+ hel.appendChild(doc.createTextNode(QString::number(rect.height())));
+ el.appendChild(hel);
+
+ return el;
+}
+
+
+static QDomElement createListEntry(QDomDocument &doc, const QString &tagName,
+ const QString &subTagName, const QStrList &list)
+{
+ QDomElement el = doc.createElement(tagName);
+
+ QStrListIterator it(list);
+ for (; it.current(); ++it) {
+ QDomElement subel = doc.createElement(subTagName);
+ subel.appendChild(doc.createTextNode(QString::fromLatin1(it.current())));
+ el.appendChild(subel);
+ }
+
+ return el;
+}
+
+
+static QString stringEntry(QDomElement &base, const QString &tagName)
+{
+ return base.namedItem(tagName).firstChild().toText().data();
+}
+
+
+static bool boolEntry(QDomElement &base, const QString &tagName)
+{
+ return base.namedItem(tagName).firstChild().toText().data() == "true";
+}
+
+
+static int numberEntry(QDomElement &base, const QString &tagName)
+{
+ return stringEntry(base, tagName).toInt();
+}
+
+
+static QRect rectEntry(QDomElement &base, const QString &tagName)
+{
+ QDomElement el = base.namedItem(tagName).toElement();
+
+ int x = numberEntry(el, "x");
+ int y = numberEntry(el, "y");
+ int width = numberEntry(el, "width");
+ int height = numberEntry(el, "height");
+
+ return QRect(x, y, width, height);
+}
+
+
+static QStrList listEntry(QDomElement &base, const QString &tagName, const QString &subTagName)
+{
+ QStrList list;
+
+ QDomElement subel = base.namedItem(tagName).firstChild().toElement();
+ while (!subel.isNull()) {
+ if (subel.tagName() == subTagName)
+ list.append(subel.firstChild().toText().data().latin1());
+ subel = subel.nextSibling().toElement();
+ }
+
+ return list;
+}
+
+
+void PMDockManager::writeConfig(QDomElement &base)
+{
+ // First of all, clear the tree under base
+ while (!base.firstChild().isNull())
+ base.removeChild(base.firstChild());
+ QDomDocument doc = base.ownerDocument();
+
+ QStrList nameList;
+ QString mainWidgetStr;
+
+ // collect widget names
+ QStrList nList;
+ QObjectListIt it(*childDock);
+ PMDockWidget *obj1;
+ while ( (obj1=(PMDockWidget*)it.current()) ) {
+ if ( obj1->parent() == main )
+ mainWidgetStr = QString::fromLatin1(obj1->name());
+ nList.append(obj1->name());
+ ++it;
+ }
+
+ nList.first();
+ while ( nList.current() ) {
+ PMDockWidget *obj = getDockWidgetFromName( nList.current() );
+ if (obj->isGroup && (nameList.find( obj->firstName.latin1() ) == -1
+ || nameList.find(obj->lastName.latin1()) == -1)) {
+ // Skip until children are saved (why?)
+ nList.next();
+ if ( !nList.current() ) nList.first();
+ continue;
+ }
+
+ QDomElement groupEl;
+
+ if (obj->isGroup) {
+ //// Save a group
+ groupEl = doc.createElement("splitGroup");
+
+ groupEl.appendChild(createStringEntry(doc, "firstName", obj->firstName));
+ groupEl.appendChild(createStringEntry(doc, "secondName", obj->lastName));
+ groupEl.appendChild(createNumberEntry(doc, "orientation", (int)obj->splitterOrientation));
+ groupEl.appendChild(createNumberEntry(doc, "separatorPos", ((PMDockSplitter*)obj->widget)->separatorPos()));
+ } else if (obj->isTabGroup) {
+ //// Save a tab group
+ groupEl = doc.createElement("tabGroup");
+
+ QStrList list;
+ for ( int i = 0; i < ((PMDockTabGroup*)obj->widget)->count(); ++i )
+ list.append( ((PMDockTabGroup*)obj->widget)->page( i )->name() );
+ groupEl.appendChild(createListEntry(doc, "tabs", "tab", list));
+ groupEl.appendChild(createNumberEntry(doc, "currentTab", ((PMDockTabGroup*)obj->widget)->currentPageIndex()));
+ } else {
+ //// Save an ordinary dock widget
+ groupEl = doc.createElement("dock");
+ }
+
+ groupEl.appendChild(createStringEntry(doc, "name", QString::fromLatin1(obj->name())));
+ groupEl.appendChild(createBoolEntry(doc, "hasParent", obj->parent()));
+ if ( !obj->parent() ) {
+ groupEl.appendChild(createRectEntry(doc, "geometry", QRect(main->frameGeometry().topLeft(), main->size())));
+ groupEl.appendChild(createBoolEntry(doc, "visible", obj->isVisible()));
+ }
+ if (obj->header && obj->header->inherits("PMDockWidgetHeader")) {
+ PMDockWidgetHeader *h = static_cast<PMDockWidgetHeader*>(obj->header);
+ groupEl.appendChild(createBoolEntry(doc, "dragEnabled", h->dragEnabled()));
+ }
+
+ base.appendChild(groupEl);
+ nameList.append(obj->name());
+ nList.remove();
+ nList.first();
+ }
+
+ if (main->inherits("PMDockMainWindow")) {
+ PMDockMainWindow *dmain = (PMDockMainWindow*)main;
+ QString centralWidgetStr = QString(dmain->centralWidget()? dmain->centralWidget()->name() : "");
+ base.appendChild(createStringEntry(doc, "centralWidget", centralWidgetStr));
+ QString mainDockWidgetStr = QString(dmain->getMainDockWidget()? dmain->getMainDockWidget()->name() : "");
+ base.appendChild(createStringEntry(doc, "mainDockWidget", mainDockWidgetStr));
+ } else {
+ base.appendChild(createStringEntry(doc, "mainWidget", mainWidgetStr));
+ }
+
+ base.appendChild(createRectEntry(doc, "geometry", QRect(main->frameGeometry().topLeft(), main->size())));
+}
+
+
+void PMDockManager::readConfig(QDomElement &base)
+{
+ if (base.namedItem("group").isNull()
+ && base.namedItem("tabgroup").isNull()
+ && base.namedItem("dock").isNull()) {
+ activate();
+ return;
+ }
+
+ autoCreateDock = new QObjectList();
+ autoCreateDock->setAutoDelete( true );
+
+ bool isMainVisible = main->isVisible();
+ main->hide();
+
+ QObjectListIt it(*childDock);
+ PMDockWidget *obj1;
+ while ( (obj1=(PMDockWidget*)it.current()) ) {
+ if ( !obj1->isGroup && !obj1->isTabGroup ) {
+ if ( obj1->parent() )
+ obj1->undock();
+ else
+ obj1->hide();
+ }
+ ++it;
+ }
+
+ QDomElement childEl = base.firstChild().toElement();
+ while (!childEl.isNull() ) {
+ PMDockWidget *obj = 0;
+
+ if (childEl.tagName() == "splitGroup") {
+ // Read a group
+ QString name = stringEntry(childEl, "name");
+ QString firstName = stringEntry(childEl, "firstName");
+ QString secondName = stringEntry(childEl, "secondName");
+ int orientation = numberEntry(childEl, "orientation");
+ int separatorPos = numberEntry(childEl, "separatorPos");
+
+ PMDockWidget *first = getDockWidgetFromName(firstName);
+ PMDockWidget *second = getDockWidgetFromName(secondName);
+ if (first && second) {
+ obj = first->manualDock(second,
+ (orientation == (int)Vertical)? PMDockWidget::DockLeft : PMDockWidget::DockTop,
+ separatorPos);
+ if (obj)
+ obj->setName(name.latin1());
+ }
+ } else if (childEl.tagName() == "tabGroup") {
+ // Read a tab group
+ QString name = stringEntry(childEl, "name");
+ QStrList list = listEntry(childEl, "tabs", "tab");
+
+ PMDockWidget *d1 = getDockWidgetFromName( list.first() );
+ list.next();
+ PMDockWidget *d2 = getDockWidgetFromName( list.current() );
+
+ PMDockWidget *obj = d2->manualDock( d1, PMDockWidget::DockCenter );
+ if (obj) {
+ PMDockTabGroup *tab = (PMDockTabGroup*)obj->widget;
+ list.next();
+ while (list.current() && obj) {
+ PMDockWidget *tabDock = getDockWidgetFromName(list.current());
+ obj = tabDock->manualDock(d1, PMDockWidget::DockCenter);
+ list.next();
+ }
+ if (obj) {
+ obj->setName(name.latin1());
+ tab->showPage(tab->page(numberEntry(childEl, "currentTab")));
+ }
+ }
+ } else if (childEl.tagName() == "dock") {
+ // Read an ordinary dock widget
+ obj = getDockWidgetFromName(stringEntry(childEl, "name"));
+ }
+
+ if (!boolEntry(childEl, "hasParent")) {
+ QRect r = rectEntry(childEl, "geometry");
+ obj = getDockWidgetFromName(stringEntry(childEl, "name"));
+ obj->applyToWidget(0);
+ obj->setGeometry(r);
+ if (boolEntry(childEl, "visible"))
+ obj->QWidget::show();
+ }
+
+ if (obj && obj->header && obj->header->inherits("PMDockWidgetHeader")) {
+ PMDockWidgetHeader *h = static_cast<PMDockWidgetHeader*>(obj->header);
+ h->setDragEnabled(boolEntry(childEl, "dragEnabled"));
+ }
+
+ childEl = childEl.nextSibling().toElement();
+ }
+
+ if (main->inherits("PMDockMainWindow")) {
+ PMDockMainWindow *dmain = (PMDockMainWindow*)main;
+
+ QString mv = stringEntry(base, "centralWidget");
+ if (!mv.isEmpty() && getDockWidgetFromName(mv) ) {
+ PMDockWidget *mvd = getDockWidgetFromName(mv);
+ mvd->applyToWidget(dmain);
+ mvd->show();
+ dmain->setCentralWidget(mvd);
+ }
+ QString md = stringEntry(base, "mainDockWidget");
+ if (!md.isEmpty() && getDockWidgetFromName(md)) {
+ PMDockWidget *mvd = getDockWidgetFromName(md);
+ dmain->setMainDockWidget(mvd);
+ }
+ } else {
+ QString mv = stringEntry(base, "mainWidget");
+ if (!mv.isEmpty() && getDockWidgetFromName(mv)) {
+ PMDockWidget *mvd = getDockWidgetFromName(mv);
+ mvd->applyToWidget(main);
+ mvd->show();
+ }
+ }
+
+ QRect mr = rectEntry(base, "geometry");
+ main->setGeometry(mr);
+ if (isMainVisible)
+ main->show();
+
+ delete autoCreateDock;
+ autoCreateDock = 0;
+}
+
+
+#ifndef NO_KDE2
+void PMDockManager::writeConfig( KConfig* c, QString group )
+{
+ //debug("BEGIN Write Config");
+ if ( !c ) c = KGlobal::config();
+ if ( group.isEmpty() ) group = "dock_setting_default";
+
+ c->setGroup( group );
+ c->writeEntry( "Version", DOCK_CONFIG_VERSION );
+
+ QStrList nameList;
+ QStrList findList;
+ QObjectListIt it( *childDock );
+ PMDockWidget * obj;
+
+ // collect PMDockWidget's name
+ QStrList nList;
+ while ( (obj=(PMDockWidget*)it.current()) ) {
+ ++it;
+ //debug(" +Add subdock %s", obj->name());
+ nList.append( obj->name() );
+ if ( obj->parent() == main )
+ c->writeEntry( "Main:view", obj->name() );
+ }
+
+ nList.first();
+ while ( nList.current() ){
+ //debug(" -Try to save %s", nList.current());
+ obj = getDockWidgetFromName( nList.current() );
+ QString cname = obj->name();
+ if ( obj->header ){
+ obj->header->saveConfig( c );
+ }
+/*************************************************************************************************/
+ if ( obj->isGroup ){
+ if ( findList.find( obj->firstName.latin1() ) != -1 && findList.find( obj->lastName.latin1() ) != -1 ){
+
+ c->writeEntry( cname+":type", "GROUP");
+ if ( !obj->parent() ){
+ c->writeEntry( cname+":parent", "___null___");
+ c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
+ c->writeEntry( cname+":visible", obj->isVisible());
+ } else {
+ c->writeEntry( cname+":parent", "yes");
+ }
+ c->writeEntry( cname+":first_name", obj->firstName );
+ c->writeEntry( cname+":last_name", obj->lastName );
+ c->writeEntry( cname+":orientation", (int)obj->splitterOrientation );
+ c->writeEntry( cname+":sepPos", ((PMDockSplitter*)obj->widget)->separatorPos() );
+
+ nameList.append( obj->name() );
+ findList.append( obj->name() );
+ //debug(" Save %s", nList.current());
+ nList.remove();
+ nList.first();
+ } else {
+/*************************************************************************************************/
+ //debug(" Skip %s", nList.current());
+ //if ( findList.find( obj->firstName ) == -1 )
+ // debug(" ? Not found %s", obj->firstName);
+ //if ( findList.find( obj->lastName ) == -1 )
+ // debug(" ? Not found %s", obj->lastName);
+ nList.next();
+ if ( !nList.current() ) nList.first();
+ }
+ } else {
+/*************************************************************************************************/
+ if ( obj->isTabGroup){
+ c->writeEntry( cname+":type", "TAB_GROUP");
+ if ( !obj->parent() ){
+ c->writeEntry( cname+":parent", "___null___");
+ c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
+ c->writeEntry( cname+":visible", obj->isVisible());
+ } else {
+ c->writeEntry( cname+":parent", "yes");
+ }
+ QStrList list;
+ for ( int i = 0; i < ((PMDockTabGroup*)obj->widget)->count(); ++i )
+ list.append( ((PMDockTabGroup*)obj->widget)->page( i )->name() );
+ c->writeEntry( cname+":tabNames", list );
+ c->writeEntry( cname+":curTab", ((PMDockTabGroup*)obj->widget)->currentPageIndex() );
+
+ nameList.append( obj->name() );
+ findList.append( obj->name() ); // not really need !!!
+ //debug(" Save %s", nList.current());
+ nList.remove();
+ nList.first();
+ } else {
+/*************************************************************************************************/
+ if ( !obj->parent() ){
+ c->writeEntry( cname+":type", "NULL_DOCK");
+ c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
+ c->writeEntry( cname+":visible", obj->isVisible());
+ } else {
+ c->writeEntry( cname+":type", "DOCK");
+ }
+ nameList.append( cname.latin1() );
+ //debug(" Save %s", nList.current());
+ findList.append( obj->name() );
+ nList.remove();
+ nList.first();
+ }
+ }
+ }
+ c->writeEntry( "NameList", nameList );
+
+ c->writeEntry( "Main:Geometry", QRect(main->frameGeometry().topLeft(), main->size()) );
+ c->writeEntry( "Main:visible", main->isVisible()); // curently nou use
+
+ if ( main->inherits("PMDockMainWindow") ){
+ PMDockMainWindow* dmain = (PMDockMainWindow*)main;
+ // for PMDockMainWindow->setView() in readConfig()
+ c->writeEntry( "Main:view", dmain->centralWidget() ? dmain->centralWidget()->name():"" );
+ c->writeEntry( "Main:dock", dmain->getMainDockWidget() ? dmain->getMainDockWidget()->name() :"" );
+ }
+
+ c->sync();
+ //debug("END Write Config");
+}
+#include <qmessagebox.h>
+void PMDockManager::readConfig( KConfig* c, QString group )
+{
+ if ( !c ) c = KGlobal::config();
+ if ( group.isEmpty() ) group = "dock_setting_default";
+
+ c->setGroup( group );
+ QStrList nameList;
+ c->readListEntry( "NameList", nameList );
+ QString ver = c->readEntry( "Version", "0.0.1" );
+ nameList.first();
+ if ( !nameList.current() || ver != DOCK_CONFIG_VERSION ){
+ activate();
+ return;
+ }
+
+ autoCreateDock = new QObjectList();
+ autoCreateDock->setAutoDelete( true );
+
+ bool isMainVisible = main->isVisible();
+ // if (isMainVisible) // CCC
+ //QMessageBox::information(0,"","hallo");
+//COMMENTED4TESTING main->hide();
+
+ QObjectListIt it( *childDock );
+ PMDockWidget * obj;
+
+ while ( (obj=(PMDockWidget*)it.current()) ){
+ ++it;
+ if ( !obj->isGroup && !obj->isTabGroup )
+ {
+ if ( obj->parent() ) obj->undock(); else obj->hide();
+ }
+ }
+
+ nameList.first();
+ while ( nameList.current() ){
+ QString oname = nameList.current();
+ c->setGroup( group );
+ QString type = c->readEntry( oname + ":type" );
+ obj = 0L;
+
+ if ( type == "GROUP" ){
+ PMDockWidget* first = getDockWidgetFromName( c->readEntry( oname + ":first_name" ) );
+ PMDockWidget* last = getDockWidgetFromName( c->readEntry( oname + ":last_name" ) );
+ int sepPos = c->readNumEntry( oname + ":sepPos" );
+
+ Orientation p = (Orientation)c->readNumEntry( oname + ":orientation" );
+ if ( first && last ){
+ obj = first->manualDock( last, ( p == Vertical ) ? PMDockWidget::DockLeft : PMDockWidget::DockTop, sepPos );
+ if (obj){
+ obj->setName( oname.latin1() );
+ }
+ }
+ }
+
+ if ( type == "TAB_GROUP" ){
+ QStrList list;
+ PMDockWidget* tabDockGroup = 0L;
+ c->readListEntry( oname+":tabNames", list );
+ PMDockWidget* d1 = getDockWidgetFromName( list.first() );
+ list.next();
+ PMDockWidget* d2 = getDockWidgetFromName( list.current() );
+ tabDockGroup = d2->manualDock( d1, PMDockWidget::DockCenter );
+ if ( tabDockGroup ){
+ PMDockTabGroup* tab = (PMDockTabGroup*)tabDockGroup->widget;
+ list.next();
+ while ( list.current() && tabDockGroup ){
+ PMDockWidget* tabDock = getDockWidgetFromName( list.current() );
+ tabDockGroup = tabDock->manualDock( d1, PMDockWidget::DockCenter );
+ list.next();
+ }
+ if ( tabDockGroup ){
+ tabDockGroup->setName( oname.latin1() );
+ c->setGroup( group );
+ tab->showPage( tab->page( c->readNumEntry( oname+":curTab" ) ) );
+ }
+ }
+ obj = tabDockGroup;
+ }
+
+ if ( type == "NULL_DOCK" || c->readEntry( oname + ":parent") == "___null___" ){
+ QRect r = c->readRectEntry( oname + ":geometry" );
+ obj = getDockWidgetFromName( oname );
+ obj->applyToWidget( 0L );
+ obj->setGeometry(r);
+
+ c->setGroup( group );
+ if ( c->readBoolEntry( oname + ":visible" ) ){
+ obj->QWidget::show();
+ }
+ }
+
+ if ( type == "DOCK" ){
+ obj = getDockWidgetFromName( oname );
+ }
+
+ if ( obj && obj->header){
+ obj->header->loadConfig( c );
+ }
+ nameList.next();
+ }
+
+ if ( main->inherits("PMDockMainWindow") ){
+ PMDockMainWindow* dmain = (PMDockMainWindow*)main;
+
+ c->setGroup( group );
+ QString mv = c->readEntry( "Main:view" );
+ if ( !mv.isEmpty() && getDockWidgetFromName( mv ) ){
+ PMDockWidget* mvd = getDockWidgetFromName( mv );
+ mvd->applyToWidget( dmain );
+ mvd->show();
+ dmain->setView( mvd );
+ }
+ c->setGroup( group );
+ QString md = c->readEntry( "Main:dock" );
+ if ( !md.isEmpty() && getDockWidgetFromName( md ) ){
+ PMDockWidget* mvd = getDockWidgetFromName( md );
+ dmain->setMainDockWidget( mvd );
+ }
+ } else {
+ c->setGroup( group );
+ QString mv = c->readEntry( "Main:view" );
+ if ( !mv.isEmpty() && getDockWidgetFromName( mv ) ){
+ PMDockWidget* mvd = getDockWidgetFromName( mv );
+ mvd->applyToWidget( main );
+ mvd->show();
+ }
+
+ }
+ // delete all autocreate dock
+ delete autoCreateDock;
+ autoCreateDock = 0L;
+
+ c->setGroup( group );
+ QRect mr = c->readRectEntry("Main:Geometry");
+ main->setGeometry(mr);
+ if ( isMainVisible ) main->show();
+}
+#endif
+
+PMDockWidget* PMDockManager::getDockWidgetFromName( const QString& dockName )
+{
+ QObjectListIt it( *childDock );
+ PMDockWidget * obj;
+ while ( (obj=(PMDockWidget*)it.current()) ) {
+ ++it;
+ if ( QString(obj->name()) == dockName ) return obj;
+ }
+
+ PMDockWidget* autoCreate = 0L;
+ if ( autoCreateDock ){
+ autoCreate = new PMDockWidget( this, dockName.latin1(), QPixmap("") );
+ autoCreateDock->append( autoCreate );
+ }
+ return autoCreate;
+}
+void PMDockManager::setSplitterOpaqueResize(bool b)
+{
+ d->splitterOpaqueResize = b;
+}
+
+bool PMDockManager::splitterOpaqueResize() const
+{
+ return d->splitterOpaqueResize;
+}
+
+void PMDockManager::setSplitterKeepSize(bool b)
+{
+ d->splitterKeepSize = b;
+}
+
+bool PMDockManager::splitterKeepSize() const
+{
+ return d->splitterKeepSize;
+}
+
+void PMDockManager::setSplitterHighResolution(bool b)
+{
+ d->splitterHighResolution = b;
+}
+
+bool PMDockManager::splitterHighResolution() const
+{
+ return d->splitterHighResolution;
+}
+
+void PMDockManager::slotMenuPopup()
+{
+ menu->clear();
+ menuData->clear();
+
+ QObjectListIt it( *childDock );
+ PMDockWidget * obj;
+ int numerator = 0;
+ while ( (obj=(PMDockWidget*)it.current()) ) {
+ ++it;
+ if ( obj->mayBeHide() )
+ {
+ menu->insertItem( obj->icon() ? *(obj->icon()) : QPixmap(), QString("Hide ") + obj->caption(), numerator++ );
+ menuData->append( new MenuDockData( obj, true ) );
+ }
+
+ if ( obj->mayBeShow() )
+ {
+ menu->insertItem( obj->icon() ? *(obj->icon()) : QPixmap(), QString("Show ") + obj->caption(), numerator++ );
+ menuData->append( new MenuDockData( obj, false ) );
+ }
+ }
+}
+
+void PMDockManager::slotMenuActivated( int id )
+{
+ MenuDockData* data = menuData->at( id );
+ data->dock->changeHideShowState();
+}
+
+PMDockWidget* PMDockManager::findWidgetParentDock( QWidget* w ) const
+{
+ QObjectListIt it( *childDock );
+ PMDockWidget * dock;
+ PMDockWidget * found = 0L;
+
+ while ( (dock=(PMDockWidget*)it.current()) ) {
+ ++it;
+ if ( dock->widget == w ){ found = dock; break; }
+ }
+ return found;
+}
+
+void PMDockManager::drawDragRectangle()
+{
+ if (d->oldDragRect == d->dragRect)
+ return;
+
+ int i;
+ QRect oldAndNewDragRect[2];
+ oldAndNewDragRect[0] = d->oldDragRect;
+ oldAndNewDragRect[1] = d->dragRect;
+
+ // 2 calls, one for the old and one for the new drag rectangle
+ for (i = 0; i <= 1; i++) {
+ if (oldAndNewDragRect[i].isEmpty())
+ continue;
+
+ PMDockWidget* pDockWdgAtRect = (PMDockWidget*) QApplication::widgetAt( oldAndNewDragRect[i].topLeft(), true );
+ if (!pDockWdgAtRect)
+ continue;
+
+ bool isOverMainWdg = false;
+ bool unclipped;
+ PMDockMainWindow* pMain = 0L;
+ PMDockWidget* pTLDockWdg = 0L;
+ QWidget* topWdg;
+ if (pDockWdgAtRect->topLevelWidget() == main) {
+ isOverMainWdg = true;
+ topWdg = pMain = (PMDockMainWindow*) main;
+ unclipped = pMain->testWFlags( WPaintUnclipped );
+ pMain->setWFlags( WPaintUnclipped );
+ }
+ else {
+ topWdg = pTLDockWdg = (PMDockWidget*) pDockWdgAtRect->topLevelWidget();
+ unclipped = pTLDockWdg->testWFlags( WPaintUnclipped );
+ pTLDockWdg->setWFlags( WPaintUnclipped );
+ }
+
+ // draw the rectangle unclipped over the main dock window
+ QPainter p;
+ p.begin( topWdg );
+ if ( !unclipped ) {
+ if (isOverMainWdg)
+ pMain->clearWFlags(WPaintUnclipped);
+ else
+ pTLDockWdg->clearWFlags(WPaintUnclipped);
+ }
+ // draw the rectangle
+ p.setRasterOp(Qt::NotXorROP);
+ QRect r = oldAndNewDragRect[i];
+ r.moveTopLeft( r.topLeft() - topWdg->mapToGlobal(QPoint(0,0)) );
+ p.drawRect(r.x(), r.y(), r.width(), r.height());
+ p.end();
+ }
+
+ // memorize the current rectangle for later removing
+ d->oldDragRect = d->dragRect;
+}
+
+
+#ifdef _JOWENN_EXPERIMENTAL_
+
+PMDockArea::PMDockArea( QWidget* parent, const char *name)
+:QWidget( parent, name)
+{
+ QString new_name = QString(name) + QString("_DockManager");
+ dockManager = new PMDockManager( this, new_name.latin1() );
+ mainDockWidget = 0L;
+}
+
+PMDockArea::~PMDockArea()
+{
+ delete dockManager;
+}
+
+PMDockWidget* PMDockArea::createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel)
+{
+ return new PMDockWidget( dockManager, name.latin1(), pixmap, parent, strCaption, strTabPageLabel );
+}
+
+void PMDockArea::makeDockVisible( PMDockWidget* dock )
+{
+ if ( dock != 0L)
+ dock->makeDockVisible();
+}
+
+void PMDockArea::makeDockInvisible( PMDockWidget* dock )
+{
+ if ( dock != 0L)
+ dock->undock();
+}
+
+void PMDockArea::makeWidgetDockVisible( QWidget* widget )
+{
+ makeDockVisible( dockManager->findWidgetParentDock(widget) );
+}
+
+void PMDockArea::writeDockConfig(QDomElement &base)
+{
+ dockManager->writeConfig(base);
+}
+
+void PMDockArea::readDockConfig(QDomElement &base)
+{
+ dockManager->readConfig(base);
+}
+
+void PMDockArea::slotDockWidgetUndocked()
+{
+ QObject* pSender = (QObject*) sender();
+ if (!pSender->inherits("PMDockWidget")) return;
+ PMDockWidget* pDW = (PMDockWidget*) pSender;
+ emit dockWidgetHasUndocked( pDW);
+}
+
+void PMDockArea::resizeEvent(QResizeEvent *rsize)
+{
+ QWidget::resizeEvent(rsize);
+ if (children()){
+#ifndef NO_KDE2
+ kdDebug()<<"PMDockArea::resize"<<endl;
+#endif
+ QObjectList *list=queryList("QWidget",0,false);
+
+ QObjectListIt it( *list ); // iterate over the buttons
+ QObject *obj;
+
+ while ( (obj = it.current()) != 0 ) {
+ // for each found object...
+ ((QWidget*)obj)->setGeometry(QRect(QPoint(0,0),size()));
+ break;
+ }
+ delete list;
+#if 0
+ PMDockSplitter *split;
+// for (unsigned int i=0;i<children()->count();i++)
+ {
+// QPtrList<QObject> list(children());
+// QObject *obj=((QPtrList<QObject*>)children())->at(i);
+ QObject *obj=children()->getFirst();
+ if (split=dynamic_cast<PMDockSplitter*>(obj))
+ {
+ split->setGeometry( QRect(QPoint(0,0), size() ));
+// break;
+ }
+ }
+#endif
+ }
+}
+
+#ifndef NO_KDE2
+void PMDockArea::writeDockConfig( KConfig* c, QString group )
+{
+ dockManager->writeConfig( c, group );
+}
+
+void PMDockArea::readDockConfig( KConfig* c, QString group )
+{
+ dockManager->readConfig( c, group );
+}
+
+void PMDockArea::setMainDockWidget( PMDockWidget* mdw )
+{
+ if ( mainDockWidget == mdw ) return;
+ mainDockWidget = mdw;
+ mdw->applyToWidget(this);
+}
+#endif
+
+
+#endif
+
+void PMDockWidgetAbstractHeader::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void PMDockWidgetAbstractHeaderDrag::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void PMDockWidgetHeaderDrag::virtual_hook( int id, void* data )
+{ PMDockWidgetAbstractHeaderDrag::virtual_hook( id, data ); }
+
+void PMDockWidgetHeader::virtual_hook( int id, void* data )
+{ PMDockWidgetAbstractHeader::virtual_hook( id, data ); }
+
+void PMDockTabGroup::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void PMDockWidget::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void PMDockManager::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void PMDockMainWindow::virtual_hook( int id, void* data )
+{ KMainWindow::virtual_hook( id, data ); }
+
+void PMDockArea::virtual_hook( int, void* )
+{ /*KMainWindow::virtual_hook( id, data );*/ }
+
+
+#ifndef NO_INCLUDE_MOCFILES // for Qt-only projects, because tmake doesn't take this name
+#include "pmdockwidget.moc"
+#endif
diff --git a/kpovmodeler/pmdockwidget.h b/kpovmodeler/pmdockwidget.h
new file mode 100644
index 00000000..29f6c34f
--- /dev/null
+++ b/kpovmodeler/pmdockwidget.h
@@ -0,0 +1,1478 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Copyright (C) 2000 Falk Brettschneider <falk@kdevelop.org>
+ Modified 2002 Andreas Zehender <zehender@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/*
+ activities:
+ -----------
+ 03/2002 : Copied from kdelibs. Slightly different docking
+ ; behavior by Andreas Zehender <zehender@kde.org>
+ 05/2001 - : useful patches, bugfixes by Christoph Cullmann <crossfire@babylon2k.de>,
+ Joseph Wenninger <jowenn@bigfoot.com> and Falk Brettschneider
+ 03/2001 - 05/2001 : maintained and enhanced by Falk Brettschneider <falk@kdevelop.org>
+ 03/2000 : class documentation added by Falk Brettschneider <gigafalk@yahoo.com>
+ 10/1999 - 03/2000 : programmed by Max Judin <novaprint@mtu-net.ru>
+
+ C++ classes in this file:
+ -------------------------
+ - PMDockWidgetAbstractHeader - minor helper class
+ - PMDockWidgetAbstractHeaderDrag - minor helper class
+ - PMDockWidgetHeaderDrag - drag panel in a dockwidget title bar
+ - PMDockWidgetHeader - dockwidget title bar containing the drag panel
+ - PMDockTabGroup - minor helper class
+ - PMDockWidget - IMPORTANT CLASS: the one and only dockwidget class
+ - PMDockManager - helper class
+ - PMDockMainWindow - IMPORTANT CLASS: a special KMainWindow that can have dockwidgets
+ - PMDockArea - like PMDockMainWindow but inherits just QWidget
+
+ IMPORTANT Note: This file compiles also in Qt-only mode by using the NO_KDE2 precompiler definition!
+*/
+
+/*
+ MODIFICATIONS (zehender)
+ Added kparts ability from kparts/dockmainwindow
+*/
+
+#define _JOWENN_EXPERIMENTAL_
+
+
+#ifndef KDOCKWIDGET_H
+#define KDOCKWIDGET_H
+
+#define _KDOCKWIDGET_2_2_
+
+#include <qpoint.h>
+#include <qptrlist.h>
+#include <qframe.h>
+#include <qdom.h>
+#include <qtabwidget.h>
+
+#ifndef NO_KDE2
+#include <kmainwindow.h>
+#include <netwm_def.h>
+#undef EXPORT_DOCKCLASS
+#define EXPORT_DOCKCLASS
+#else
+#include <qmainwindow.h>
+#include "exportdockclass.h"
+#include "dummykmainwindow.h"
+#endif
+
+#include <kparts/part.h>
+using namespace KParts;
+
+class PMDockSplitter;
+class PMDockManager;
+class PMDockMoveManager;
+class PMDockWidget;
+class PMDockButton_Private;
+class PMDockWidgetPrivate;
+class PMDockArea;
+class PMDockMainWindowPrivate;
+
+class QObjectList;
+class QPopupMenu;
+class QVBoxLayout;
+class QHBoxLayout;
+class QPixmap;
+
+#ifndef NO_KDE2
+class KToolBar;
+class KConfig;
+#else
+class QToolBar;
+#endif
+
+/**
+ * An abstract base clase for all dockwidget headers (and member of the dockwidget class set).
+ * See the class description of @ref PMDockWidgetHeader!
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class PMDockWidgetAbstractHeader : public QFrame
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs this.
+ *
+ * @param parent the parent widget (usually a dockwidget)
+ * @param name the object instance name
+ */
+ PMDockWidgetAbstractHeader( PMDockWidget* parent, const char* name = 0L );
+
+ /**
+ * Destructs this.
+ */
+ virtual ~PMDockWidgetAbstractHeader(){};
+
+ /**
+ * Provides things concerning to switching to toplevel mode. Must be overridden by an inheriting class.
+ */
+ virtual void setTopLevel( bool ){};
+
+#ifndef NO_KDE2
+ /**
+ * Provides saving the current configuration. Must be overridden by an inheriting class.
+ */
+ virtual void saveConfig( KConfig* ){};
+
+ /**
+ * Provides loading the current configuration. Must be overridden by an inheriting class
+ */
+ virtual void loadConfig( KConfig* ){};
+#endif
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class PMDockWidgetAbstractHeaderPrivate;
+ PMDockWidgetAbstractHeaderPrivate *d;
+};
+
+/**
+ * An abstract class for all dockwidget drag-panels of a dockwidgets (and member of the dockwidget class set).
+ * See the class description of @ref PMDockWidgetHeaderDrag!
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class PMDockWidgetAbstractHeaderDrag : public QFrame
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs this.
+ *
+ * @param parent the parent widget (usually a dockwidget header)
+ * @param dock the dockwidget where it belongs to
+ * @param name the object instance name
+ */
+ PMDockWidgetAbstractHeaderDrag( PMDockWidgetAbstractHeader* parent,
+ PMDockWidget* dock, const char* name = 0L );
+
+ /**
+ * Destructs this.
+ */
+ virtual ~PMDockWidgetAbstractHeaderDrag(){};
+
+ /**
+ * @return the dockwidget where this belongs to
+ */
+ PMDockWidget* dockWidget() const { return dw; }
+
+private:
+ /**
+ * the dockwidget where this belongs to
+ */
+ PMDockWidget* dw;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class PMDockWidgetAbstractHeaderDragPrivate;
+ PMDockWidgetAbstractHeaderDragPrivate *d;
+};
+
+/**
+ * This special widget is the panel one can grip with the mouses (and member of the dockwidget class set).
+ * The widget for dragging, so to speak.
+ * Usually it is located in the @ref PMDockWidgetHeader.
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class PMDockWidgetHeaderDrag : public PMDockWidgetAbstractHeaderDrag
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs this.
+ *
+ * @param parent the parent widget (usually a dockwidget header)
+ * @param dock the dockwidget where it belongs to
+ * @param name the object instance name
+ */
+ PMDockWidgetHeaderDrag( PMDockWidgetAbstractHeader* parent, PMDockWidget* dock,
+ const char* name = 0L );
+
+ /**
+ * Destructs this.
+ */
+ virtual ~PMDockWidgetHeaderDrag(){};
+
+protected:
+
+ /**
+ * Draws the drag panel (a double line)
+ */
+ virtual void paintEvent( QPaintEvent* );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class PMDockWidgetHeaderDragPrivate;
+ PMDockWidgetHeaderDragPrivate *d;
+};
+
+/**
+ * The header (additional bar) for a @ref PMDockWidget s (and member of the dockwidget class set).
+ * It have got the buttons located there. And it is for recording and reading the button states.
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class PMDockWidgetHeader : public PMDockWidgetAbstractHeader
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs this.
+ *
+ * @param parent the parent widget (usually a dockwidget)
+ * @param name the object instance name
+ */
+ PMDockWidgetHeader( PMDockWidget* parent, const char* name = 0L );
+
+ /**
+ * Destructs this.
+ */
+ virtual ~PMDockWidgetHeader(){};
+
+ /**
+ * Hides the close button and stay button when switching to toplevel or vice versa shows them.
+ *
+ * @param t toplevel or not
+ */
+ virtual void setTopLevel( bool t);
+
+ /**
+ * Sets the drag panel of this header.
+ *
+ * @param nd A pointer to the new drag panel
+ */
+ void setDragPanel( PMDockWidgetHeaderDrag* nd );
+
+ bool dragEnabled() const;
+ void setDragEnabled(bool b);
+
+#ifndef NO_KDE2
+ /**
+ * Saves the current button state to a KDE config container object.
+ *
+ * @param c the configuration safe
+ */
+ virtual void saveConfig( KConfig* c);
+
+ /**
+ * Loads the current button state from a KDE config container object.
+ *
+ * @param c the configuration safe
+ */
+ virtual void loadConfig( KConfig* );
+#endif
+
+protected slots:
+ /**
+ * Sets dragging the dockwidget off when the stay button is pressed down and vice versa.
+ */
+ void slotStayClicked();
+
+protected:
+
+ /**
+ * A layout manager for placing the embedded buttons (close and stay)
+ */
+ QHBoxLayout* layout;
+
+ /**
+ * a little button for closing (undocking and hiding) the dockwidget
+ */
+ PMDockButton_Private* closeButton;
+
+ /**
+ * a little button for undocking the dockwidget and add it as
+ * level widget
+ */
+ PMDockButton_Private* toDesktopButton;
+
+ /**
+ * a little button for enabling/disabling dragging the dockwidget with the mouse
+ */
+ PMDockButton_Private* stayButton;
+
+ /**
+ * a little button for dock back the dockwidget to it's previous dockwidget
+ */
+ PMDockButton_Private* dockbackButton;
+
+ /**
+ * the drag panel (double line)
+ */
+ PMDockWidgetHeaderDrag* drag;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class PMDockWidgetHeaderPrivate;
+ PMDockWidgetHeaderPrivate *d;
+};
+
+/**
+ * It just hides the special implementation of a dockwidget tab groups (and is member of the dockwidget class set).
+ * An abstraction what it is currently.
+ * In general it is like @ref QTabWidget but is more useful for the dockwidget class set.
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class EXPORT_DOCKCLASS PMDockTabGroup : public QTabWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructs this. It just calls the method of the base class.
+ */
+ PMDockTabGroup( QWidget *parent = 0, const char *name = 0 )
+ :QTabWidget( parent, name ){};
+
+ /**
+ * Destructs a PMDockTabGroup.
+ */
+ virtual ~PMDockTabGroup(){};
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class PMDockTabGroupPrivate;
+ PMDockTabGroupPrivate *d;
+};
+
+/**
+ * Floatable widget that can be dragged around with the mouse and
+ * encapsulate the actual widgets (and member of the dockwidget class
+ * set).
+ *
+ * You just grip the double-lined panel, tear it off its parent
+ * widget, drag it somewhere and let it loose. Depending on the
+ * position where you leave it, the dockwidget becomes a toplevel
+ * window on the desktop (floating mode) or docks to a new widget
+ * (dock mode). Note: A PMDockWidget can only be docked to a
+ * PMDockWidget.
+ *
+ * If you want to use this kind of widget, your main application
+ * window has to be a @ref PMDockMainWindow. That is because it has
+ * got several additional dock management features, for instance a
+ * @ref PMDockManager that has an overview over all dockwidgets and and
+ * a dockmovemanager (internal class) that handles the dock process.
+ *
+ * Usually you create an PMDockWidget that covers the actual widget in this way:
+ * <PRE>
+ * ...
+ * PMDockMainWindow* mainWidget;
+ * ...
+ * PMDockWidget* dock = 0L;
+ * dock = mainWidget->createDockWidget( "Any window caption", nicePixmap, 0L, i18n("window caption")); // 0L==no parent
+ * QWidget* actualWidget = new QWidget( dock);
+ * dock->setWidget( actualWidget); // embed it
+ * dock->setToolTipString(i18n("That's me")); // available when appearing as tab page
+ * ...
+ * </PRE>
+ *
+ * See @ref PMDockMainWindow how a dockwidget is docked in.
+ *
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class EXPORT_DOCKCLASS PMDockWidget: public QWidget
+{
+ Q_OBJECT
+friend class PMDockManager;
+friend class PMDockSplitter;
+friend class PMDockMainWindow;
+friend class PMDockArea;
+
+public:
+ /**
+ * Construct a dockwidget.
+ *
+ * Initially, docking to another and docking to this is allowed for
+ * every @p DockPosition. It is supposed to be no (tab) group. It will
+ * taken under control of its dockmanager.
+ *
+ * @param dockManager The responsible manager (dock helper)
+ * @param name Object instance name
+ * @param pixmap An icon (for instance shown when docked centered)
+ * @param parent Parent widget
+ * @param strCaption Title of the dockwidget window (shown when toplevel)
+ * @param strTabPageLabel The title of the tab page (shown when in tab page mode), if it is "", only the icon will be shown, if it is 0L, the label is set to strCaption
+ */
+ PMDockWidget( PMDockManager* dockManager, const char* name,
+ const QPixmap &pixmap, QWidget* parent = 0L, const QString& strCaption = 0L,
+ const QString& strTabPageLabel = " ", WFlags f = 0);
+
+ /**
+ * Destructs a dockwidget.
+ */
+ virtual ~PMDockWidget();
+
+ /**
+ * The possible positions where a dockwidget can dock to another dockwidget
+ */
+ enum DockPosition
+ {
+ DockNone = 0,
+ DockTop = 0x0001,
+ DockLeft = 0x0002,
+ DockRight = 0x0004,
+ DockBottom = 0x0008,
+ DockCenter = 0x0010,
+ DockDesktop= 0x0020,
+
+ DockCorner = DockTop | DockLeft | DockRight | DockBottom,
+ DockFullSite = DockCorner | DockCenter,
+ DockFullDocking = DockFullSite | DockDesktop
+ };
+
+ /**
+ * This is a key method of this class! Use it to dock dockwidgets to
+ * another dockwidget at the right position within its
+ * @ref PMDockMainWindow or a toplevel dockwidget.
+ *
+ *
+ * If the target is null, it will become a toplevel dockwidget at position pos;
+ * Note: Docking to another dockwidget means exactly:
+ * A new parent dockwidget will be created, that replaces the target dockwidget and contains another single helper widget (tab widget or panner)
+ * which contains both dockwidgets, this and the target dockwidget. So consider parent<->child relationships change completely during such actions.
+ *
+ * @param target The dockwidget to dock to
+ * @param dockPos One of the DockPositions this is going to dock to
+ * @param spliPos The split relation (in percent, or percent*100 in high resolution) between both dockwidgets, target and this
+ * @param pos The dock position, mainly of interest for docking to the desktop (as toplevel dockwidget)
+ * @param check Only for internal use;
+ * @param tabIndex The position index of the tab widget (when in tab page mode), -1 (default) means append
+ * @return result The group dockwidget that replaces the target dockwidget and will be grandparent of target and @p this.
+ */
+ PMDockWidget* manualDock( PMDockWidget* target, DockPosition dockPos, int spliPos = 50, QPoint pos = QPoint(0,0), bool check = false, int tabIndex = -1);
+
+ /**
+ * Specify where it is either possible or impossible for this to dock to another dockwidget.
+ *
+ * @param pos An OR'ed set of @p DockPositions
+ */
+ void setEnableDocking( int pos );
+
+ /**
+ * @return Where it is either possible or impossible for this to dock to another dockwidget (an OR'ed set of DockPositions).
+ */
+ int enableDocking() const { return eDocking; }
+
+ /**
+ * Specify where it is either possible or impossible for another dockwidget to dock to this.
+ *
+ * @param pos An OR'ed set of @p DockPositions
+ */
+ void setDockSite( int pos ){ sDocking = pos;}
+
+ /**
+ * @return There it is either possible or impossible for another dockwidget to dock to this (an OR'ed set of @p DockPositions).
+ */
+ int dockSite() const
+ {
+ // no docking if a floating dock widget
+ if( !parent( ) )
+ return 0;
+ return sDocking;
+ }
+
+ /**
+ * Sets the embedded widget.
+ *
+ * A QLayout takes care about proper resizing, automatically.
+ *
+ * @param w The pointer to the dockwidget's child widget.
+ */
+ void setWidget( QWidget* w);
+
+ /**
+ * Get the embedded widget.
+ *
+ * @return The pointer to the dockwidget's child widget, 0L if there's no such child.
+ */
+ QWidget* getWidget() const { return widget; };
+
+ /**
+ * Sets the header of this dockwidget.
+ *
+ * A @ref QLayout takes care about proper resizing, automatically.
+ * The header contains the drag panel, the close button and the stay button.
+ *
+ * @param ah A base class pointer to the dockwidget header
+ */
+ void setHeader( PMDockWidgetAbstractHeader* ah);
+
+ /**
+ * Normally it simply shows the dockwidget.
+ *
+ * But additionally, if it is docked to a tab widget (@p DockCenter), it is set as the active (visible) tab page.
+ */
+ void makeDockVisible();
+
+ /**
+ * @return If it may be possible to hide this.
+ *
+ * There are reasons that it's impossible:
+ * @li It is a (tab) group.
+ * @li It is already invisible ;-)
+ * @li The parent of this is the @ref PMDockMainWindow.
+ * @li It isn't able to dock to another widget.
+ */
+ bool mayBeHide() const;
+
+ /**
+ * @return If it may be possible to show this.
+ * There are reasons that it's impossible:
+ * @li It is a (tab) group.
+ * @li It is already visible ;-)
+ * @li The parent of this is the @p PMDockMainWindow.
+ */
+ bool mayBeShow() const;
+
+ /**
+ * @return The dockmanager that is responsible for this.
+ */
+ PMDockManager* dockManager() const { return manager; }
+
+ /**
+ * Stores a string for a tooltip.
+ *
+ * That tooltip string has only a meaning when this dockwidget is shown as tab page.
+ * In this case the tooltip is shown when one holds the mouse cursor on the tab page header.
+ * Such tooltip will for instance be useful, if you use only icons there.
+ * Note: Setting an empty string switches the tooltip off.
+ *
+ * @param ttStr A string for the tooltip on the tab.
+ */
+ void setToolTipString(const QString& ttStr) { toolTipStr = ttStr; };
+
+ /**
+ * @return The tooltip string being shown on the appropriate tab page header when in dock-centered mode.
+ */
+ const QString& toolTipString() const { return toolTipStr; };
+
+ /**
+ * @return result @p true, if a dockback is possible, otherwise @p false.
+ */
+ bool isDockBackPossible() const;
+
+ /**
+ * Sets a string that is used for the label of the tab page when in tab page mode
+ * @param label The new tab page label.
+ */
+ void setTabPageLabel( const QString& label) { tabPageTitle = label; };
+
+ /**
+ * @return A string that is used for the label of the tab page when in tab page mode.
+ */
+ const QString& tabPageLabel() const { return tabPageTitle; };
+
+ /**
+ * Catches and processes some @ref QWidget events that are interesting for dockwidgets.
+ */
+ virtual bool event( QEvent * );
+
+ /**
+ * Add dockwidget management actions to @ref QWidget::show.
+ */
+ virtual void show();
+ /**
+ * @return the parent widget of this if it inherits class PMDockTabGroup
+ */
+ PMDockTabGroup* parentDockTabGroup() const;
+
+#ifndef NO_KDE2
+
+ /**
+ * Sets the type of the dock window
+ *
+ * @param windowType is type of dock window
+ */
+ void setDockWindowType (NET::WindowType windowType);
+
+#endif
+
+ /**
+ * Sets the type of the dock window
+ *
+ * @param windowType is type of dock window
+ */
+ void setDockWindowTransient (QWidget *parent, bool transientEnabled);
+
+ // MODIFICATION (lpassos)
+ /**
+ *
+ * Return the current dock position of the widget
+ */
+ DockPosition getDockPosition( ) const { return currentDockPos; }
+public slots:
+ /**
+ * Docks a dockwidget back to the dockwidget that was the neighbor
+ widget before the current dock position.
+ */
+ void dockBack();
+
+ /**
+ * Toggles the visibility state of the dockwidget if it is able to be shown or to be hidden.
+ */
+ void changeHideShowState();
+
+ /**
+ * Undocks this. It means it becomes a toplevel widget framed by the system window manager.
+ * A small panel at the top of this undocked widget gives the possibility to drag it into
+ * another dockwidget by mouse (docking).
+ */
+ void undock();
+
+ // MODIFICATION (zehender)
+ /**
+ * Docks the widget to the desktop (as a toplevel widget)
+ */
+ void toDesktop( );
+
+ /**
+ * Sets the caption and tab label
+ */
+ void slotSetCaption( const QString& );
+
+protected:
+
+ /**
+ * Checks some conditions and shows or hides the dockwidget header (drag panel).
+ * The header is hidden if:
+ * @li the parent widget is the PMDockMainWindow
+ * @li this is a (tab) group dockwidget
+ * @li it is not able to dock to another dockwidget
+ */
+ void updateHeader();
+
+signals:
+ /**
+ * Emitted when another dock widget is docking to this.
+ *
+ * @param dw the dockwidget that is docking to this
+ * @param dp the DockPosition where it wants to dock to
+ */
+ void docking( PMDockWidget* dw, PMDockWidget::DockPosition dp);
+
+ /**
+ * Signals that the dock default position is set.
+ */
+ void setDockDefaultPos();
+
+ /**
+ * Emitted when the close button of the panel (@ref PMDockWidgetHeader) has been clicked.
+ */
+ void headerCloseButtonClicked();
+
+ /**
+ * Emitted when the dockback button of the panel (@ref PMDockWidgetHeader) has been clicked.
+ */
+ void headerDockbackButtonClicked();
+
+ /**
+ * Emitted when the widget processes a close event.
+ */
+ void iMBeingClosed();
+ /**
+ * Emitted when the widget has undocked.
+ */
+ void hasUndocked();
+
+protected slots:
+
+ /**
+ * Does several things here when it has noticed that the former brother widget (closest neighbor) gets lost.
+ * The former brother widget is needed for a possible dockback action, to speak with the Beatles:
+ * "To get back to where you once belonged" ;-)
+ */
+ void loseFormerBrotherDockWidget();
+
+protected:
+ /**
+ * earlier closest neighbor widget, so it's possible to dock back to it.
+ */
+ PMDockWidget* formerBrotherDockWidget;
+ /**
+ * the current dock position.
+ */
+ DockPosition currentDockPos;
+ /**
+ * the former dock position when it really was at another position before.
+ */
+ DockPosition formerDockPos;
+ /**
+ * a string used as tooltip for the tab page header when in dock-centered mode.
+ */
+ QString toolTipStr;
+ /**
+ * a string used as title of the tab page when in tab page mode
+ */
+ QString tabPageTitle;
+
+private:
+ /**
+ * Sets the caption (window title) of the given tab widget.
+ *
+ * @param g the group (tab) widget
+ */
+ void setDockTabName( PMDockTabGroup* g);
+
+ /**
+ * Reparent to s or set this to the PMDockMainWindow's view if s is that dockmainwindow.
+ * If s is O, simply move the widget.
+ *
+ * @param s the target widget to reparent to
+ * @param p the point to move to (if it doesn't reparent)
+ */
+ void applyToWidget( QWidget* s, const QPoint& p = QPoint(0,0) );
+
+ /**
+ * A base class pointer to the header of this dockwidget
+ */
+ PMDockWidgetAbstractHeader* header;
+
+ /**
+ * the embedded widget
+ */
+ QWidget* widget;
+
+ /**
+ * the layout manager that takes care about proper resizing and moving the embedded widget and the header
+ */
+ QVBoxLayout* layout;
+
+ /**
+ * the responsible dockmanager
+ */
+ PMDockManager* manager;
+
+ /**
+ * an icon for the tab widget header
+ */
+ QPixmap* pix;
+
+ /**
+ * Information about the ability for docking to another dockwidget.
+ */
+ int eDocking;
+
+ /**
+ * Information which site of this dockwidget is free for docking of other dockwidgets.
+ */
+ int sDocking;
+
+ /**
+ * Previous side (left,right,top,bottom) where this dockwidget was before a dragging action, none if it wasn't dragged before.
+ */
+ PMDockWidget::DockPosition prevSideDockPosBeforeDrag;
+
+ // GROUP data
+ QString firstName;
+ QString lastName;
+ Orientation splitterOrientation;
+ bool isGroup;
+ bool isTabGroup;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ PMDockWidgetPrivate *d;
+};
+
+/**
+ * The manager that knows all dockwidgets and handles the dock process (and member of the dockwidget class set).
+ * More or less a helper class for the PMDockWidget class set but of interest for some functionality
+ * that can be called within a @ref PMDockMainWindow or a @ref PMDockWidget .
+ *
+ * An important feature is the ability to read or save the current state of all things concerning to
+ * dockwidgets to @ref KConfig .
+ *
+ * The dockmanager is also often used when a certain dockwidget or a child of such dockwidget must be found.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class EXPORT_DOCKCLASS PMDockManager: public QObject
+{
+ Q_OBJECT
+friend class PMDockWidget;
+friend class PMDockMainWindow;
+
+public:
+ /**
+ * Constructs a dockmanager. Some initialization happen:
+ * @li It installs an event filter for the main window,
+ * @li a control list for dock objects
+ * @li a control list for menu items concerning to menus provided by the dockmanager
+ * @li Some state variables are set
+ *
+ * @param mainWindow the main window controlled by this
+ * @param name the internal QOject name
+ */
+ PMDockManager( QWidget* mainWindow, const char* name = 0L );
+
+ /**
+ * Destructs a dockmanager.
+ */
+ virtual ~PMDockManager();
+
+#ifndef NO_KDE2
+ /**
+ * Saves the current state of the dockmanager and of all controlled widgets.
+ * State means here to save the geometry, visibility, parents, internal object names, orientation,
+ * separator positions, dockwidget-group information, tab widget states (if it is a tab group) and
+ * last but not least some necessary things for recovering the dockmainwindow state.
+ *
+ * @param c the KDE configuration saver
+ * @param group the name of the section in KConfig
+ */
+ void writeConfig( KConfig* c = 0L, QString group = QString::null );
+
+ /**
+ * Like writeConfig but reads the whole stuff in.
+ *
+ * In order to restore a window configuration
+ * from a config file, it looks up widgets by name
+ * (QObject::name) in the childDock variable of
+ * PMDockManager. This list in turn contains all
+ * PMDockWidgets (according to the PMDockWidget constructor).
+ * So in principle, in order to restore a window layout,
+ * one must first construct all widgets, put each of them in a
+ * PMDockWidget and then call readConfig(). And for all that
+ * to work, each widget must have a unique name.
+ *
+ * @param c the KDE configuration saver
+ * @param group the name of the section in KConfig
+ */
+ void readConfig ( KConfig* c = 0L, QString group = QString::null );
+#endif
+
+ /**
+ * Saves the current dock window layout into a DOM tree below the given element.
+ */
+ void writeConfig(QDomElement &base);
+ /**
+ * Reads the current dock window layout from a DOM tree below the given element.
+ */
+ void readConfig(QDomElement &base);
+
+ /**
+ * Shows all encapsulated widgets of all controlled dockwidgets and shows all dockwidgets which are
+ * parent of a dockwidget tab group.
+ */
+ void activate();
+
+ /**
+ * It's more or less a method that catches several events which are interesting for the dockmanager.
+ * Mainly mouse events during the drag process of a dockwidgets are of interest here.
+ *
+ * @param _ the object that sends the event
+ * @param _ the event
+ * @return the return value of the method call of the base class method
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+ /**
+ * This method finds out what a widgets' dockwidget is. That means the dockmanager has a look at all
+ * dockwidgets it knows and tells you when one of those dockwidgets covers the given widget.
+ *
+ * @param w any widget that is supposed to be encapsulated by one of the controlled dockwidgets
+ * @return the dockwidget that encapsulates that widget, otherwise 0
+ */
+ PMDockWidget* findWidgetParentDock( QWidget* w) const;
+
+ /**
+ * Works like makeDockVisible() but can be called for widgets that covered by a dockwidget.
+ *
+ * @param w the widget that is encapsulated by a dockwidget that turns to visible.
+ */
+ void makeWidgetDockVisible( QWidget* w ){ findWidgetParentDock(w)->makeDockVisible(); }
+
+ /**
+ * @return the popupmenu for showing/hiding dockwidgets
+ */
+ QPopupMenu* dockHideShowMenu() const { return menu; }
+
+ /**
+ * @param dockName an internal QObject name
+ * @return the dockwidget that has got that internal QObject name
+ */
+ PMDockWidget* getDockWidgetFromName( const QString& dockName );
+
+ /**
+ * Enables opaque resizing. Opaque resizing is initially turned off.
+ * Call this method before you create any dock widgets!
+ */
+ void setSplitterOpaqueResize(bool b=true);
+
+ /**
+ * Returns TRUE if opaque resizing is enabled, FALSE otherwise.
+ */
+ bool splitterOpaqueResize() const;
+
+ /**
+ * Try to preserve the widget's size. Works like KeepSize resize mode
+ * of QSplitter. Off by default.
+ * Call this method before you create any dock widgets!
+ */
+ void setSplitterKeepSize(bool b=true);
+
+ /**
+ * Returns TRUE if the KeepSize is enabled, FALSE otherwise.
+ */
+ bool splitterKeepSize() const;
+
+ /**
+ * Operate the splitter with a higher resolution. Off by default.
+ * Call this method before you create any dock widgets!
+ * If high resolution is used all splitter position parameters
+ * are percent*100 instead of percent.
+ */
+ void setSplitterHighResolution(bool b=true);
+
+ /**
+ * Returns TRUE if the splitter uses the high resolution, FALSE otherwise.
+ */
+ bool splitterHighResolution() const;
+
+ /**
+ * Returns the main dock widget
+ */
+ QWidget* dockMainWidget( ) const { return main; }
+
+signals:
+
+ /**
+ * Signals changes of the docking state of a dockwidget. Usually the dock-toolbar will be updated then.
+ */
+ void change();
+
+ /**
+ * Signals a dockwidget is replaced with another one.
+ */
+ void replaceDock( PMDockWidget* oldDock, PMDockWidget* newDock );
+
+ /**
+ * Signals a dockwidget without parent (toplevel) is shown.
+ */
+ void setDockDefaultPos( PMDockWidget* );
+
+private slots:
+
+ /**
+ * Clears the popupmenu for showing/hiding dockwidgets and fills it with the current states of all controlled dockwidgets.
+ */
+ void slotMenuPopup();
+
+ /**
+ * This method assumes a menuitem of the popupmenu for showing/hiding dockwidgets is selected and toggles that state.
+ *
+ * @param id the popupmenu id of the selected menuitem
+ */
+ void slotMenuActivated( int id);
+
+ /* clears the old drawn drag rectangle (oldDragRect) from screen and
+ * draws the new current drag rectangle (dragRect) depending on the current mouse position.
+ * This highlights the dockwidget which is the currently chosen target during a dock action.
+ */
+ void drawDragRectangle();
+
+private:
+
+ /**
+ * A data structure containing data about every dockwidget that is under control.
+ */
+ struct MenuDockData
+ {
+ MenuDockData( PMDockWidget* _dock, bool _hide )
+ {
+ dock = _dock;
+ hide = _hide;
+ };
+ ~MenuDockData(){};
+
+ PMDockWidget* dock;
+ bool hide;
+ };
+
+ /**
+ * Finds the PMDockWidget at the position given as parameter
+ *
+ * @param pos global (desktop) position of the wanted dockwidget
+ * @return the dockwidget at that position
+ */
+ PMDockWidget* findDockWidgetAt( const QPoint& pos );
+
+ /**
+ * Finds the QWidget recursively at the position given as parameter
+ *
+ * @param w a variable where the method puts the QWidget at that position (instead of a return value)
+ * @param p the parent widget where the recursive search should start from
+ * @param pos global (desktop) position of the wanted dockwidget
+ */
+ void findChildDockWidget( QWidget*& w, const QWidget* p, const QPoint& pos );
+ // MODIFICATION (lpassos)
+ // Made findChildDockWidget public
+public:
+ /**
+ * Finds all dockwidgets which are child, grandchild and so on of p.
+ *
+ * @param p the parent widget where the recursive search starts from
+ * @param l the widget list that contains the search result after the return of this method
+ */
+ void findChildDockWidget( const QWidget* p, QWidgetList& l);
+ /**
+ * Returns all floating dock widgets
+ */
+ void findFloatingWidgets( QPtrList<PMDockWidget>& l );
+
+private:
+ /**
+ * Sets a dockwidget in drag mode.
+ */
+ void startDrag( PMDockWidget* );
+
+ /**
+ * Moves a dockwidget that is in drag mode.
+ *
+ * @param d the dockwidget which is dragged
+ * @param pos the new position of the dragged dockwidget
+ */
+ void dragMove( PMDockWidget* d, QPoint pos );
+
+ /**
+ * Aborts the drag mode. Restores the cursor and hides the drag indicator.
+ */
+ void cancelDrop();
+
+ /**
+ * Finishes the drag mode. If the user let it drop on an other dockwidget, it will possibly be docked (if allowed),
+ * if the user drops it outside of the application window it becomes toplevel.
+ */
+ void drop();
+
+// class members
+
+ /**
+ * Usually the PMDockMainWindow but not necessarily.
+ */
+ QWidget* main;
+
+ /**
+ * The dockwidget that is being dragged at the moment
+ */
+ PMDockWidget* currentDragWidget;
+
+ /**
+ * The target dockwidget where the currentDragWidget is dropped
+ */
+ PMDockWidget* currentMoveWidget; // widget where mouse moving
+
+ /**
+ * It is of interest during the dock process. Then it contains all child dockwidgets.
+ */
+ QWidgetList* childDockWidgetList;
+
+ /**
+ * The dockposition where the dockwidget would be docked to, if we dropped it here.
+ */
+ PMDockWidget::DockPosition curPos;
+
+ /**
+ * A QList of all objects that are important for docking.
+ * Some serve as group widgets of dockwidgets, others encapsulate normal widgets.
+ */
+ QObjectList* childDock;
+
+ /**
+ * Contains dockwidgets that are created automatically by the dockmanager. For internal use.
+ */
+ QObjectList* autoCreateDock;
+
+ /**
+ * For storing the width during the dragging of a dockwidget.
+ */
+ int storeW;
+
+ /**
+ * For storing the height during the dragging of a dockwidget.
+ */
+ int storeH;
+
+ /**
+ * State variable if there is a drag process active.
+ */
+ bool draging;
+
+ /**
+ * State variable if there is an undock process active
+ */
+ bool undockProcess;
+
+ /**
+ * The dockmanager sets it to true if the user cancels the drag by moving the cursor
+ * on a invalid drop place
+ */
+ bool dropCancel;
+
+ /**
+ * A popup menu that contains one menuitem for each dockwidget that shows the current visibility state and
+ * to show or hide the appropriate dockwidget.
+ */
+ QPopupMenu* menu;
+
+ /**
+ * An internal list containing data for the menuitems for the visibility popup menu.
+ */
+ QPtrList<MenuDockData> *menuData;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class PMDockManagerPrivate;
+ PMDockManagerPrivate *d;
+};
+
+/**
+ * A special kind of @ref KMainWindow that is able to have dockwidget child widgets (and member of the dockwidget class set).
+ *
+ * The main widget should be a @ref PMDockWidget where other @ref PMDockWidget can be docked to
+ * the left, right, top, bottom or to the middle.
+ * Note: dock to the middle means to drop on a dockwidget and to unite them to a new widget, a tab control.
+ *
+ * Furthermore, the PMDockMainWindow has got the @ref PMDockManager and some data about the dock states.
+ *
+ * If you've got some dockwidgets, you can dock them to the dockmainwindow to initialize a start scene:
+ * Here an example:
+ * <PRE>
+ * DockApplication::DockApplication( const char* name) : PMDockMainWindow( name)
+ * {
+ * ...
+ * PMDockWidget* mainDock;
+ * mainDock = createDockWidget( "Falk's MainDockWidget", mainPixmap, 0L, "main_dock_widget");
+ * AnyContentsWidget* cw = new AnyContentsWidget( mainDock);
+ * mainDock->setWidget( cw);
+ * // allow others to dock to the 4 sides
+ * mainDock->setDockSite(PMDockWidget::DockCorner);
+ * // forbit docking abilities of mainDock itself
+ * mainDock->setEnableDocking(PMDockWidget::DockNone);
+ * setView( mainDock); // central widget in a KDE mainwindow
+ * setMainDockWidget( mainDock); // master dockwidget
+ * ...
+ * PMDockWidget* dockLeft;
+ * dockLeft = createDockWidget( "Intially left one", anyOtherPixmap, 0L, i18n("The left dockwidget"));
+ * AnotherWidget* aw = new AnotherWidget( dockLeft);
+ * dockLeft->setWidget( aw);
+ * dockLeft->manualDock( mainDock, // dock target
+ * PMDockWidget::DockLeft, // dock site
+ * 20 ); // relation target/this (in percent)
+ * ...
+ * </PRE>
+ *
+ * Docking is fully dynamical at runtime. That means you can always move dockwidgets via drag and drop.
+ *
+ * And last but not least you can use the popupmenu for showing or hiding any controlled dockwidget
+ * of this class and insert it to your main menu bar or anywhere else.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class EXPORT_DOCKCLASS PMDockMainWindow : public KMainWindow, virtual public PartBase
+{
+ Q_OBJECT
+
+friend class PMDockManager;
+
+public:
+
+ /**
+ * Constructs a dockmainwindow. It calls its base class constructor and does additional things concerning
+ * to the dock stuff:
+ * @li information about the dock state of this' children gets initialized
+ * @li a dockmanager is created...
+ * @li ...and gets initialized
+ * @li the main dockwidget is set to 0
+ *
+ * @param name object name
+ */
+ PMDockMainWindow( QWidget* parent = 0L, const char *name = 0L, WFlags f = WType_TopLevel | WDestructiveClose );
+
+ /**
+ * Destructs a dockmainwindow.
+ */
+ virtual ~PMDockMainWindow();
+
+ /**
+ * Returns the dockmanager of this. (see @ref PMDockManager)
+ * @return pointer to the wanted dockmanager
+ */
+ PMDockManager* manager() const { return dockManager; }
+
+ /**
+ * Sets a new main dockwidget.
+ * Additionally, the toolbar is re-initialized.
+ *
+ * @param _ dockwidget that become the new main dockwidget
+ */
+ void setMainDockWidget( PMDockWidget* );
+
+ /**
+ * Returns the main dockwidget.
+ *
+ * @return pointer to the main dockwidget
+ */
+ PMDockWidget* getMainDockWidget() const { return mainDockWidget; }
+
+ /**
+ * This is one of the most important methods!
+ * The PMDockMainWindow creates a new dockwidget object here that usually should encapsulate the user's widget.
+ * The new dockwidget is automatically taken under control by the dockmanager of the dockmainwindow.
+ *
+ * @param name QObject name (default dockwidget caption)
+ * @param pixmap window icon (for instance shown when docked as tabwidget entry)
+ * @param parent parent widget for the new dockwidget
+ * @param strCaption window title (shown when toplevel)
+ * @param strTabPageLabel title of the tab page (visible when in tab page mode), if it is "", only the icon will be shown; if it is 0L, the label is set to strCaption
+ * @return a pointer to the new created dockwidget
+ */
+ PMDockWidget* createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent = 0L, const QString& strCaption = 0L, const QString& strTabPageLabel = " ");
+
+ /**
+ * Saves the current dock window layout into a DOM tree below the given element.
+ */
+ void writeDockConfig(QDomElement &base);
+ /**
+ * Reads the current dock window layout from a DOM tree below the given element.
+ */
+ void readDockConfig(QDomElement &base);
+
+#ifndef NO_KDE2
+ /**
+ * It writes the current dock state in the given section of KConfig.
+ *
+ * @param c KDE class for saving configurations
+ * @param group name of section to write to
+ */
+ void writeDockConfig( KConfig* c = 0L, QString group = QString::null );
+
+ /**
+ * It reads the current dock state from the given section of KConfig.
+ *
+ * @param c KDE class for saving configurations
+ * @param group name of section to read from
+ */
+ void readDockConfig ( KConfig* c = 0L, QString group = QString::null );
+#endif
+
+ /**
+ * It runs through all dockwidgets which are under control of the dockmanager and calls show() for every
+ * encapsulated widget and show() for the dockwidget itself if it is not in tab mode.
+ * Additionally, if the main dockwidget is not a QDialog, it will be shown.
+ */
+ void activateDock(){ dockManager->activate(); }
+
+ /**
+ * Returns a popup menu that contains entries for all controlled dockwidgets making hiding and showing
+ * them possible.
+ *
+ * @return the wanted popup menu
+ */
+ QPopupMenu* dockHideShowMenu() const { return dockManager->dockHideShowMenu(); }
+
+ /**
+ * This method shows the given dockwidget.
+ * The clue is that it also considers the dockwidget could be a tab page
+ * and must set to be the activate one.
+ *
+ * @param dock the dockwidget that is to be shown
+ */
+ void makeDockVisible( PMDockWidget* dock );
+
+ /**
+ * This method hides the given dockwidget.
+ *
+ * @param dock the dockwidget that is to be shown
+ */
+ void makeDockInvisible( PMDockWidget* dock );
+
+ /**
+ * This is an overloaded member function, provided for convenience.
+ * It differs from the above function only in what argument(s) it accepts.
+ */
+ void makeWidgetDockVisible( QWidget* widget );
+
+ /**
+ * This method calls the base class method.
+ * If the given widget inherits PMDockWidget, applyToWidget(this) is called.
+ *
+ * @param _ any widget that should become the main view
+ */
+ void setView( QWidget* );
+
+signals:
+ /**
+ * Signals a certain dockwidget is undocked now.
+ */
+ void dockWidgetHasUndocked(PMDockWidget*);
+
+protected:
+
+ /**
+ * A pointer to the main dockwidget (where one can manualDock() to
+ */
+ PMDockWidget* mainDockWidget;
+
+ /**
+ * A pointer to the manager for the dock process
+ */
+ PMDockManager* dockManager;
+
+protected slots:
+ /**
+ * Called whenever one of the dockwidgets of this has been undocked.
+ */
+ void slotDockWidgetUndocked();
+
+ // kparts/dockmainwindow stuff
+protected slots:
+
+ /**
+ * Create the GUI (by merging the host's and the active part's)
+ *
+ * Called on startup and whenever the active part changes
+ * For this you need to connect this slot to the
+ * @ref KPartManager::activePartChanged() signal
+ * @param part The active part (set to 0L if no part).
+ */
+ void createGUI( KParts::Part * part );
+
+ /**
+ * Called when the active part wants to change the statusbar message
+ * Reimplement if your dock-mainwindow has a complex statusbar
+ * (with several items)
+ */
+ virtual void slotSetStatusBarText( const QString & );
+
+protected:
+ virtual void createShellGUI( bool create = true );
+ // end kparts/dockmainwindow stuff
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ PMDockMainWindowPrivate *d;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifdef _JOWENN_EXPERIMENTAL_
+/* Joseph Wenninger jowenn@kde.org Experimental (Just all KMainWindow references changed to QWidget, otherwise nearly exactly the
+same as PMDockMainWindow*/
+
+class EXPORT_DOCKCLASS PMDockArea : public QWidget
+{
+ Q_OBJECT
+
+friend class PMDockManager;
+
+public:
+
+
+ PMDockArea( QWidget* parent = 0L, const char *name = 0L);
+
+ virtual ~PMDockArea();
+
+ PMDockManager* manager(){ return dockManager; }
+
+
+ void setMainDockWidget( PMDockWidget* );
+ PMDockWidget* getMainDockWidget(){ return mainDockWidget; }
+
+ PMDockWidget* createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent = 0L, const QString& strCaption = 0L, const QString& strTabPageLabel = " ");
+
+ void writeDockConfig(QDomElement &base);
+ void readDockConfig(QDomElement &base);
+
+#ifndef NO_KDE2
+ void writeDockConfig( KConfig* c = 0L, QString group = QString::null );
+ void readDockConfig ( KConfig* c = 0L, QString group = QString::null );
+#endif
+
+
+
+ void activateDock(){ dockManager->activate(); }
+ QPopupMenu* dockHideShowMenu(){ return dockManager->dockHideShowMenu(); }
+ void makeDockVisible( PMDockWidget* dock );
+ void makeDockInvisible( PMDockWidget* dock );
+ void makeWidgetDockVisible( QWidget* widget );
+ //void setView( QWidget* );
+
+signals:
+ /**
+ * Signals a certain dockwidget is undocked now.
+ */
+ void dockWidgetHasUndocked(PMDockWidget*);
+
+protected:
+
+ PMDockWidget* mainDockWidget;
+ PMDockManager* dockManager;
+
+protected slots:
+ void slotDockWidgetUndocked();
+
+public:
+ virtual void resizeEvent(QResizeEvent *);
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class PMDockMainWindowPrivate;
+ PMDockMainWindowPrivate *d;
+};
+
+#endif
+
+#endif
+
+
diff --git a/kpovmodeler/pmdockwidget_private.cpp b/kpovmodeler/pmdockwidget_private.cpp
new file mode 100644
index 00000000..cdf21930
--- /dev/null
+++ b/kpovmodeler/pmdockwidget_private.cpp
@@ -0,0 +1,372 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Modified 2002 Andreas Zehender <zehender@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "pmdockwidget.h"
+#include "pmdockwidget_private.h"
+
+#include <qpainter.h>
+#include <qcursor.h>
+
+PMDockSplitter::PMDockSplitter(QWidget *parent, const char *name, Orientation orient, int pos, bool highResolution)
+: QWidget(parent, name)
+{
+ divider = 0L;
+ child0 = 0L;
+ child1 = 0L;
+ orientation = orient;
+ mOpaqueResize = false;
+ mKeepSize = false;
+ mHighResolution = highResolution;
+ setSeparatorPos( pos, false );
+ initialised = false;
+}
+
+void PMDockSplitter::activate(QWidget *c0, QWidget *c1)
+{
+ if ( c0 ) child0 = c0;
+ if ( c1 ) child1 = c1;
+
+ setupMinMaxSize();
+
+ if (divider) delete divider;
+ divider = new QFrame(this, "pannerdivider");
+ divider->setFrameStyle(QFrame::Panel | QFrame::Raised);
+ divider->setLineWidth(1);
+ divider->raise();
+
+ if (orientation == Horizontal)
+ divider->setCursor(QCursor(sizeVerCursor));
+ else
+ divider->setCursor(QCursor(sizeHorCursor));
+
+ divider->installEventFilter(this);
+
+ initialised= true;
+
+ updateName();
+
+ divider->show();
+ resizeEvent(0);
+}
+
+void PMDockSplitter::setupMinMaxSize()
+{
+ // Set the minimum and maximum sizes
+ int minx, maxx, miny, maxy;
+ if (orientation == Horizontal) {
+ miny = child0->minimumSize().height() + child1->minimumSize().height()+4;
+ maxy = child0->maximumSize().height() + child1->maximumSize().height()+4;
+ minx = (child0->minimumSize().width() > child1->minimumSize().width()) ? child0->minimumSize().width() : child1->minimumSize().width();
+ maxx = (child0->maximumSize().width() > child1->maximumSize().width()) ? child0->maximumSize().width() : child1->maximumSize().width();
+
+ miny = (miny > 4) ? miny : 4;
+ maxy = (maxy < 32000) ? maxy : 32000;
+ minx = (minx > 2) ? minx : 2;
+ maxx = (maxx < 32000) ? maxx : 32000;
+ } else {
+ minx = child0->minimumSize().width() + child1->minimumSize().width()+4;
+ maxx = child0->maximumSize().width() + child1->maximumSize().width()+4;
+ miny = (child0->minimumSize().height() > child1->minimumSize().height()) ? child0->minimumSize().height() : child1->minimumSize().height();
+ maxy = (child0->maximumSize().height() > child1->maximumSize().height()) ? child0->maximumSize().height() : child1->maximumSize().height();
+
+ minx = (minx > 4) ? minx : 4;
+ maxx = (maxx < 32000) ? maxx : 32000;
+ miny = (miny > 2) ? miny : 2;
+ maxy = (maxy < 32000) ? maxy : 32000;
+ }
+ setMinimumSize(minx, miny);
+ setMaximumSize(maxx, maxy);
+}
+
+void PMDockSplitter::deactivate()
+{
+ if (divider) delete divider;
+ divider = 0L;
+ initialised= false;
+}
+
+void PMDockSplitter::setSeparatorPos(int pos, bool do_resize)
+{
+ xpos = pos;
+ if (do_resize)
+ resizeEvent(0);
+}
+
+int PMDockSplitter::separatorPos() const
+{
+ return xpos;
+}
+
+void PMDockSplitter::resizeEvent(QResizeEvent *ev)
+{
+ if (initialised){
+ int factor = (mHighResolution)? 10000:100;
+ // real resize event, recalculate xpos
+ if (ev && mKeepSize && isVisible()) {
+ if (orientation == Horizontal) {
+ if (ev->oldSize().height() != ev->size().height())
+ xpos = factor * checkValue( child0->height()+1 ) / height();
+ } else {
+ if (ev->oldSize().width() != ev->size().width())
+ xpos = factor * checkValue( child0->width()+1 ) / width();
+ }
+ }
+ int position = checkValue( (orientation == Vertical ? width() : height()) * xpos/factor );
+ if (orientation == Horizontal){
+ child0->setGeometry(0, 0, width(), position);
+ child1->setGeometry(0, position+4, width(), height()-position-4);
+ divider->setGeometry(0, position, width(), 4);
+ } else {
+ child0->setGeometry(0, 0, position, height());
+ child1->setGeometry(position+4, 0, width()-position-4, height());
+ divider->setGeometry(position, 0, 4, height());
+ }
+ }
+}
+
+int PMDockSplitter::checkValue( int position ) const
+{
+ if (initialised){
+ if (orientation == Vertical){
+ if (position < (child0->minimumSize().width()))
+ position = child0->minimumSize().width();
+ if ((width()-4-position) < (child1->minimumSize().width()))
+ position = width() - (child1->minimumSize().width()) -4;
+ } else {
+ if (position < (child0->minimumSize().height()))
+ position = (child0->minimumSize().height());
+ if ((height()-4-position) < (child1->minimumSize().height()))
+ position = height() - (child1->minimumSize().height()) -4;
+ }
+ }
+
+ if (position < 0) position = 0;
+
+ if ((orientation == Vertical) && (position > width()))
+ position = width();
+ if ((orientation == Horizontal) && (position > height()))
+ position = height();
+
+ return position;
+}
+
+bool PMDockSplitter::eventFilter(QObject *o, QEvent *e)
+{
+ QMouseEvent *mev;
+ bool handled = false;
+ int factor = (mHighResolution)? 10000:100;
+
+ switch (e->type()) {
+ case QEvent::MouseMove:
+ mev= (QMouseEvent*)e;
+ child0->setUpdatesEnabled(mOpaqueResize);
+ child1->setUpdatesEnabled(mOpaqueResize);
+ if (orientation == Horizontal) {
+ if (!mOpaqueResize) {
+ int position = checkValue( mapFromGlobal(mev->globalPos()).y() );
+ divider->move( 0, position );
+ } else {
+ xpos = factor * checkValue( mapFromGlobal(mev->globalPos()).y() ) / height();
+ resizeEvent(0);
+ divider->repaint(true);
+ }
+ } else {
+ if (!mOpaqueResize) {
+ int position = checkValue( mapFromGlobal(QCursor::pos()).x() );
+ divider->move( position, 0 );
+ } else {
+ xpos = factor * checkValue( mapFromGlobal( mev->globalPos()).x() ) / width();
+ resizeEvent(0);
+ divider->repaint(true);
+ }
+ }
+ handled= true;
+ break;
+ case QEvent::MouseButtonRelease:
+ child0->setUpdatesEnabled(true);
+ child1->setUpdatesEnabled(true);
+ mev= (QMouseEvent*)e;
+ if (orientation == Horizontal){
+ xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).y() ) / height();
+ resizeEvent(0);
+ divider->repaint(true);
+ } else {
+ xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).x() ) / width();
+ resizeEvent(0);
+ divider->repaint(true);
+ }
+ handled= true;
+ break;
+ default:
+ break;
+ }
+ return (handled) ? true : QWidget::eventFilter( o, e );
+}
+
+bool PMDockSplitter::event( QEvent* e )
+{
+ if ( e->type() == QEvent::LayoutHint ){
+ // change children min/max size
+ setupMinMaxSize();
+ setSeparatorPos(xpos);
+ }
+ return QWidget::event(e);
+}
+
+QWidget* PMDockSplitter::getAnother( QWidget* w ) const
+{
+ return ( w == child0 ) ? child1 : child0;
+}
+
+void PMDockSplitter::updateName()
+{
+ if ( !initialised ) return;
+
+ QString new_name = QString( child0->name() ) + "," + child1->name();
+ parentWidget()->setName( new_name.latin1() );
+ parentWidget()->setCaption( child0->caption() + "," + child1->caption() );
+ parentWidget()->repaint( false );
+
+ ((PMDockWidget*)parentWidget())->firstName = child0->name();
+ ((PMDockWidget*)parentWidget())->lastName = child1->name();
+ ((PMDockWidget*)parentWidget())->splitterOrientation = orientation;
+
+ QWidget* p = parentWidget()->parentWidget();
+ if ( p != 0L && p->inherits("PMDockSplitter" ) )
+ ((PMDockSplitter*)p)->updateName();
+}
+
+void PMDockSplitter::setOpaqueResize(bool b)
+{
+ mOpaqueResize = b;
+}
+
+bool PMDockSplitter::opaqueResize() const
+{
+ return mOpaqueResize;
+}
+
+void PMDockSplitter::setKeepSize(bool b)
+{
+ mKeepSize = b;
+}
+
+bool PMDockSplitter::keepSize() const
+{
+ return mKeepSize;
+}
+
+void PMDockSplitter::setHighResolution(bool b)
+{
+ if (mHighResolution) {
+ if (!b) xpos = xpos/100;
+ } else {
+ if (b) xpos = xpos*100;
+ }
+ mHighResolution = b;
+}
+
+bool PMDockSplitter::highResolution() const
+{
+ return mHighResolution;
+}
+
+
+/*************************************************************************/
+PMDockButton_Private::PMDockButton_Private( QWidget *parent, const char * name )
+:QPushButton( parent, name )
+{
+ moveMouse = false;
+ setFocusPolicy( NoFocus );
+}
+
+PMDockButton_Private::~PMDockButton_Private()
+{
+}
+
+void PMDockButton_Private::drawButton( QPainter* p )
+{
+ p->fillRect( 0,0, width(), height(), QBrush(colorGroup().brush(QColorGroup::Background)) );
+ p->drawPixmap( (width() - pixmap()->width()) / 2, (height() - pixmap()->height()) / 2, *pixmap() );
+ if ( moveMouse && !isDown() ){
+ p->setPen( white );
+ p->moveTo( 0, height() - 1 );
+ p->lineTo( 0, 0 );
+ p->lineTo( width() - 1, 0 );
+
+ p->setPen( colorGroup().dark() );
+ p->lineTo( width() - 1, height() - 1 );
+ p->lineTo( 0, height() - 1 );
+ }
+ if ( isOn() || isDown() ){
+ p->setPen( colorGroup().dark() );
+ p->moveTo( 0, height() - 1 );
+ p->lineTo( 0, 0 );
+ p->lineTo( width() - 1, 0 );
+
+ p->setPen( white );
+ p->lineTo( width() - 1, height() - 1 );
+ p->lineTo( 0, height() - 1 );
+ }
+}
+
+void PMDockButton_Private::enterEvent( QEvent * )
+{
+ moveMouse = true;
+ repaint();
+}
+
+void PMDockButton_Private::leaveEvent( QEvent * )
+{
+ moveMouse = false;
+ repaint();
+}
+
+/*************************************************************************/
+PMDockWidgetPrivate::PMDockWidgetPrivate()
+ : QObject()
+ ,index(-1)
+ ,splitPosInPercent(50)
+ ,pendingFocusInEvent(false)
+ ,blockHasUndockedSignal(false)
+{
+#ifndef NO_KDE2
+ windowType = NET::Normal;
+#endif
+
+ _parent = 0L;
+ transient = false;
+}
+
+PMDockWidgetPrivate::~PMDockWidgetPrivate()
+{
+}
+
+void PMDockWidgetPrivate::slotFocusEmbeddedWidget(QWidget* w)
+{
+ if (w) {
+ QWidget* embeddedWdg = ((PMDockWidget*)w)->getWidget();
+ if (embeddedWdg && ((embeddedWdg->focusPolicy() == QWidget::ClickFocus) || (embeddedWdg->focusPolicy() == QWidget::StrongFocus))) {
+ embeddedWdg->setFocus();
+ }
+ }
+}
+
+#ifndef NO_INCLUDE_MOCFILES // for Qt-only projects, because tmake doesn't take this name
+#include "pmdockwidget_private.moc"
+#endif
diff --git a/kpovmodeler/pmdockwidget_private.h b/kpovmodeler/pmdockwidget_private.h
new file mode 100644
index 00000000..353eb390
--- /dev/null
+++ b/kpovmodeler/pmdockwidget_private.h
@@ -0,0 +1,142 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Modified 2002 Andreas Zehender <zehender@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/*
+ IMPORTANT Note: This file compiles also in Qt-only mode by using the NO_KDE2 precompiler definition
+*/
+
+#ifndef KDOCKWIDGET_PRIVATE_H
+#define KDOCKWIDGET_PRIVATE_H
+
+#include <qwidget.h>
+#include <qpushbutton.h>
+
+#ifndef NO_KDE2
+#include <netwm_def.h>
+#endif
+
+class QFrame;
+
+/**
+ * Like QSplitter but specially designed for dockwidgets stuff.
+ * @internal
+ *
+ * @author Max Judin.
+*/
+class PMDockSplitter : public QWidget
+{
+ Q_OBJECT
+public:
+ PMDockSplitter(QWidget *parent= 0, const char *name= 0, Orientation orient= Vertical, int pos= 50, bool highResolution=false);
+ virtual ~PMDockSplitter(){};
+
+ void activate(QWidget *c0, QWidget *c1 = 0L);
+ void deactivate();
+
+ int separatorPos() const;
+ void setSeparatorPos(int pos, bool do_resize = true);
+
+ virtual bool eventFilter(QObject *, QEvent *);
+ virtual bool event( QEvent * );
+
+ QWidget* getFirst() const { return child0; }
+ QWidget* getLast() const { return child1; }
+ QWidget* getAnother( QWidget* ) const;
+ void updateName();
+
+ void setOpaqueResize(bool b=true);
+ bool opaqueResize() const;
+
+ void setKeepSize(bool b=true);
+ bool keepSize() const;
+
+ void setHighResolution(bool b=true);
+ bool highResolution() const;
+
+ // MODIFICATION (Zehender)
+ Orientation splitterOrientation( ) const { return orientation; }
+
+protected:
+ int checkValue( int ) const;
+ virtual void resizeEvent(QResizeEvent *);
+
+private:
+ void setupMinMaxSize();
+
+ QWidget *child0, *child1;
+ Orientation orientation;
+ bool initialised;
+ QFrame* divider;
+ int xpos;
+ bool mOpaqueResize, mKeepSize, mHighResolution;
+};
+
+/**
+ * A mini-button usually placed in the dockpanel.
+ * @internal
+ *
+ * @author Max Judin.
+*/
+class PMDockButton_Private : public QPushButton
+{
+ Q_OBJECT
+public:
+ PMDockButton_Private( QWidget *parent=0, const char *name=0 );
+ ~PMDockButton_Private();
+
+protected:
+ virtual void drawButton( QPainter * );
+ virtual void enterEvent( QEvent * );
+ virtual void leaveEvent( QEvent * );
+
+private:
+ bool moveMouse;
+};
+
+/**
+ * additional PMDockWidget stuff (private)
+*/
+class PMDockWidgetPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ PMDockWidgetPrivate();
+ ~PMDockWidgetPrivate();
+
+public slots:
+ /**
+ * Especially used for Tab page docking. Switching the pages requires additional setFocus() for the embedded widget.
+ */
+ void slotFocusEmbeddedWidget(QWidget* w = 0L);
+
+public:
+ int index;
+ int splitPosInPercent;
+ bool pendingFocusInEvent;
+ bool blockHasUndockedSignal;
+
+#ifndef NO_KDE2
+ NET::WindowType windowType;
+#endif
+
+ QWidget *_parent;
+ bool transient;
+};
+
+#endif
diff --git a/kpovmodeler/pmdocumentationmap.cpp b/kpovmodeler/pmdocumentationmap.cpp
new file mode 100644
index 00000000..9c898c4c
--- /dev/null
+++ b/kpovmodeler/pmdocumentationmap.cpp
@@ -0,0 +1,193 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmdocumentationmap.h"
+
+#include <kconfig.h>
+#include <kstandarddirs.h>
+
+#include <qfile.h>
+#include <qdom.h>
+
+#include "pmdebug.h"
+
+PMDocumentationMap* PMDocumentationMap::s_pInstance = 0;
+KStaticDeleter<PMDocumentationMap> PMDocumentationMap::s_staticDeleter;
+
+QString PMDocumentationVersion::documentation( const QString& className ) const
+{
+ if( m_map.contains( className ) )
+ return m_map[className];
+ return m_index;
+}
+
+void PMDocumentationVersion::loadData( QDomElement& e )
+{
+ QString className;
+ QString target;
+
+ m_version = e.attribute( "number", "3.1" );
+ m_index = e.attribute( "index", "index.htm" );
+
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ className = me.attribute( "className", "" );
+ target = me.attribute( "target", "" );
+ if( !className.isEmpty( ) && !target.isEmpty( ) )
+ m_map.insert( className, target );
+ }
+ m = m.nextSibling( );
+ }
+}
+
+PMDocumentationMap::PMDocumentationMap( )
+{
+ m_pCurrentVersion = 0;
+ m_mapLoaded = false;
+}
+
+PMDocumentationMap::~PMDocumentationMap( )
+{
+ m_maps.setAutoDelete( true );
+ m_maps.clear( );
+}
+
+void PMDocumentationMap::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Povray" );
+ cfg->writePathEntry( "DocumentationPath", m_documentationPath );
+ cfg->writeEntry( "DocumentationVersion", m_currentVersion );
+}
+
+void PMDocumentationMap::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Povray" );
+ m_documentationPath = cfg->readPathEntry( "DocumentationPath" );
+ m_currentVersion = cfg->readEntry( "DocumentationVersion", "3.1" );
+}
+
+void PMDocumentationMap::setDocumentationVersion( const QString& v )
+{
+ m_currentVersion = v;
+ if( m_mapLoaded )
+ findVersion( );
+}
+
+QValueList<QString> PMDocumentationMap::availableVersions( )
+{
+ if( !m_mapLoaded )
+ loadMap( );
+
+ QValueList<QString> result;
+ QPtrListIterator<PMDocumentationVersion> it( m_maps );
+
+ for( ; it.current( ); ++it )
+ result.push_back( it.current( )->version( ) );
+
+ return result;
+}
+
+QString PMDocumentationMap::documentation( const QString& objectName )
+{
+ if( !m_mapLoaded )
+ loadMap( );
+
+ QString url;
+
+ if( !m_documentationPath.isEmpty( ) )
+ if( !m_documentationPath.endsWith( QString( "/" ) ) )
+ m_documentationPath += "/";
+
+ if( !m_documentationPath.isEmpty( ) && m_pCurrentVersion )
+ url = m_documentationPath
+ + m_pCurrentVersion->documentation( objectName );
+
+ return url;
+}
+
+void PMDocumentationMap::loadMap( )
+{
+ if( !m_mapLoaded )
+ {
+ m_mapLoaded = true;
+
+ QString fileName = locate( "data", "kpovmodeler/povraydocmap.xml" );
+ if( fileName.isEmpty( ) )
+ {
+ kdError( PMArea ) << "Povray documentation map not found" << endl;
+ return;
+ }
+
+ QFile file( fileName );
+ if( !file.open( IO_ReadOnly ) )
+ {
+ kdError( PMArea ) << "Could not open the povray documentation map file"
+ << endl;
+ return;
+ }
+
+ QDomDocument doc( "DOCMAP" );
+ doc.setContent( &file );
+
+ QDomElement e = doc.documentElement( );
+ QDomNode c = e.firstChild( );
+
+ QString str;
+
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ PMDocumentationVersion* v = new PMDocumentationVersion( );
+ m_maps.append( v );
+ v->loadData( ce );
+ }
+ c = c.nextSibling( );
+ }
+
+ findVersion( );
+ }
+}
+
+void PMDocumentationMap::findVersion( )
+{
+ QPtrListIterator< PMDocumentationVersion > it( m_maps );
+ bool found = false;
+
+ m_pCurrentVersion = 0;
+
+ for( ; it.current( ) && !found; ++it )
+ {
+ if( it.current( )->version( ) == m_currentVersion )
+ {
+ found = true;
+ m_pCurrentVersion = it.current( );
+ }
+ }
+}
+
+PMDocumentationMap* PMDocumentationMap::theMap( )
+{
+ if( !s_pInstance )
+ s_staticDeleter.setObject( s_pInstance, new PMDocumentationMap( ) );
+ return s_pInstance;
+}
diff --git a/kpovmodeler/pmdocumentationmap.h b/kpovmodeler/pmdocumentationmap.h
new file mode 100644
index 00000000..3027095c
--- /dev/null
+++ b/kpovmodeler/pmdocumentationmap.h
@@ -0,0 +1,138 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDOCUMENTATIONMAP_H
+#define PMDOCUMENTATIONMAP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qmap.h>
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <kstaticdeleter.h>
+
+class KConfig;
+class QDomElement;
+
+/**
+ * Class used internally by @ref PMDocumentationMap
+ */
+class PMDocumentationVersion
+{
+public:
+ /**
+ * Constructor
+ */
+ PMDocumentationVersion( ) { }
+ /**
+ * Destructor
+ */
+ ~PMDocumentationVersion( ) { }
+
+ QString version( ) const { return m_version; }
+ void setVersion( const QString& str ) { m_version = str; }
+ QString index( ) const { return m_index; }
+ void setIndex( const QString& str ) { m_index = str; }
+
+ QString documentation( const QString& className ) const;
+
+ void loadData( QDomElement& e );
+
+private:
+ QString m_version;
+ QString m_index;
+ QMap< QString, QString > m_map;
+};
+
+/**
+ * Class that maps the class name to the corresponding povray
+ * user documentation file
+ */
+class PMDocumentationMap
+{
+public:
+ /**
+ * Destructor
+ */
+ ~PMDocumentationMap( );
+ /**
+ * Returns the map instance (singleton)
+ */
+ static PMDocumentationMap* theMap( );
+
+ /**
+ * Sets the path to the povray user documentation
+ */
+ void setPovrayDocumentationPath( const QString& s )
+ {
+ m_documentationPath = s;
+ }
+ /**
+ * Returns the path to the povray user documentation
+ */
+ QString povrayDocumentationPath( )
+ {
+ return m_documentationPath;
+ }
+
+ /**
+ * Sets the povray documentation version
+ */
+ void setDocumentationVersion( const QString& str );
+ /**
+ * Returns the povray documentation version
+ */
+ QString documentationVersion( ) const { return m_currentVersion; }
+
+ /**
+ * Returns the list of available documentation versions
+ */
+ QValueList<QString> availableVersions( );
+
+ /**
+ * Returns the povray documentation file for the
+ * given object type
+ */
+ QString documentation( const QString& objectName );
+
+ void saveConfig( KConfig* cfg );
+ void restoreConfig( KConfig* cfg );
+
+private:
+
+ /**
+ * Constructor
+ */
+ PMDocumentationMap( );
+ void loadMap( );
+ void findVersion( );
+
+ QString m_documentationPath;
+ bool m_mapLoaded;
+ QPtrList< PMDocumentationVersion > m_maps;
+ PMDocumentationVersion* m_pCurrentVersion;
+ QString m_currentVersion;
+
+ static PMDocumentationMap* s_pInstance;
+ static KStaticDeleter<PMDocumentationMap> s_staticDeleter;
+};
+
+#endif
diff --git a/kpovmodeler/pmdocumentformat.h b/kpovmodeler/pmdocumentformat.h
new file mode 100644
index 00000000..1551f9e4
--- /dev/null
+++ b/kpovmodeler/pmdocumentformat.h
@@ -0,0 +1,26 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDOCUMENTFORMAT_H
+#define PMDOCUMENTFORMAT_H
+
+// the current document format number
+// (1.0)
+const int c_majorDocumentFormat = 1;
+const int c_minorDocumentFormat = 0;
+
+#endif
diff --git a/kpovmodeler/pmdragwidget.cpp b/kpovmodeler/pmdragwidget.cpp
new file mode 100644
index 00000000..7b63baf5
--- /dev/null
+++ b/kpovmodeler/pmdragwidget.cpp
@@ -0,0 +1,49 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmdragwidget.h"
+
+PMDragWidget::PMDragWidget( QWidget* parent, const char* name, WFlags f )
+ : QWidget( parent, name, f )
+{
+ dragging = false;
+}
+
+void PMDragWidget::mousePressEvent( QMouseEvent* )
+{
+ dragging = true;
+}
+
+void PMDragWidget::mouseReleaseEvent( QMouseEvent* )
+{
+ dragging = false;
+}
+
+void PMDragWidget::mouseMoveEvent( QMouseEvent* )
+{
+ if( dragging )
+ {
+ startDrag( );
+ dragging = false;
+ }
+}
+
+void PMDragWidget::startDrag( )
+{
+}
+
+#include "pmdragwidget.moc"
diff --git a/kpovmodeler/pmdragwidget.h b/kpovmodeler/pmdragwidget.h
new file mode 100644
index 00000000..30b15045
--- /dev/null
+++ b/kpovmodeler/pmdragwidget.h
@@ -0,0 +1,51 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMDRAGWIDGET_H
+#define PMDRAGWIDGET_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qstring.h>
+
+/**
+ * This class implements a widget that exposes a signal for drag
+ * and drop.
+ *
+ * It will emit startDrag when it's time to start a drag.
+ */
+class PMDragWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ PMDragWidget( QWidget* parent = 0, const char* name = 0, WFlags f = 0 );
+
+ virtual void startDrag( );
+
+protected:
+ void mousePressEvent( QMouseEvent* );
+ void mouseReleaseEvent( QMouseEvent* );
+ void mouseMoveEvent( QMouseEvent* );
+
+private:
+ bool dragging;
+};
+
+#endif
diff --git a/kpovmodeler/pmenumproperty.cpp b/kpovmodeler/pmenumproperty.cpp
new file mode 100644
index 00000000..72a03788
--- /dev/null
+++ b/kpovmodeler/pmenumproperty.cpp
@@ -0,0 +1,57 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmenumproperty.h"
+
+PMEnumProperty::PMEnumProperty( const char* name, bool readOnly,
+ bool writeOnly )
+ : PMPropertyBase( name, PMVariant::String, readOnly, writeOnly )
+{
+}
+
+void PMEnumProperty::addEnumValue( const QString& str, int value )
+{
+ m_valueMap[value] = str;
+ m_stringMap[str] = value;
+}
+
+QStringList PMEnumProperty::enumValues( ) const
+{
+ QStringList l;
+ PMEnumStringValueMap::const_iterator it;
+ for( it = m_stringMap.begin( ); it != m_stringMap.end( ); ++it )
+ l.append( it.key( ) );
+ return l;
+}
+
+bool PMEnumProperty::setProtected( PMObject* obj, const PMVariant& v )
+{
+ PMEnumStringValueMap::iterator it = m_stringMap.find( v.stringData( ) );
+ if( it == m_stringMap.end( ) )
+ return false;
+ setEnum( obj, it.data( ) );
+ return true;
+}
+
+PMVariant PMEnumProperty::getProtected( const PMObject* obj )
+{
+ int v = getEnum( obj );
+ PMEnumValueStringMap::const_iterator it = m_valueMap.find( v );
+ if( it == m_valueMap.end( ) )
+ return PMVariant( QString::null );
+ return it.data( );
+}
diff --git a/kpovmodeler/pmenumproperty.h b/kpovmodeler/pmenumproperty.h
new file mode 100644
index 00000000..a8d6085e
--- /dev/null
+++ b/kpovmodeler/pmenumproperty.h
@@ -0,0 +1,110 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMENUMPROPERTY_H
+#define PMENUMPROPERTY_H
+
+#include "pmmetaobject.h"
+#include <qmap.h>
+
+typedef QMap<int, QString> PMEnumValueStringMap;
+typedef QMap<QString, int> PMEnumStringValueMap;
+
+/**
+ * Base class for enum properties
+ */
+class PMEnumProperty : public PMPropertyBase
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMEnumProperty( const char* name, bool readOnly = false,
+ bool writeOnly = false );
+
+ /**
+ * Adds the string to the list of enum values and sets the enum flag
+ * to true
+ */
+ void addEnumValue( const QString& str, int value );
+
+ /**
+ * Returns true if the property is an enum
+ */
+ virtual bool isEnum( ) const { return true; }
+ /**
+ * Returns the list of enum values
+ */
+ virtual QStringList enumValues( ) const;
+
+protected:
+ /**
+ * Do not reimplement this method in a sub class
+ */
+ virtual bool setProtected( PMObject* obj, const PMVariant& v );
+ /**
+ * Do not reimplement this method in a sub class
+ */
+ virtual PMVariant getProtected( const PMObject* obj );
+
+ /**
+ * Reimplement this method in sub classes. You can safetly
+ * cast the integer to the enum type
+ */
+ virtual void setEnum( PMObject* obj, int value ) = 0;
+ /**
+ * Reimplement this method in sub classes.
+ */
+ virtual int getEnum( const PMObject* obj ) = 0;
+
+private:
+ PMEnumValueStringMap m_valueMap;
+ PMEnumStringValueMap m_stringMap;
+};
+
+#define PMDefineEnumPropertyClass( ObjectClass, EnumType, PropertyClass ) \
+class PropertyClass : public PMEnumProperty \
+{ \
+public: \
+ typedef void ( ObjectClass::*SetPtr ) ( EnumType ); \
+ typedef EnumType ( ObjectClass::*GetPtr ) ( void ) const; \
+ \
+ PropertyClass( const char* name, SetPtr setFktn, GetPtr getFktn ) \
+ : PMEnumProperty( name, setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunktion = setFktn; \
+ m_getFunktion = getFktn; \
+ } \
+protected: \
+ virtual void setEnum( PMObject* obj, int value ) \
+ { \
+ ObjectClass* o = ( ObjectClass* ) obj; \
+ ( o->*m_setFunktion )( ( EnumType ) value ); \
+ } \
+ virtual int getEnum( const PMObject* obj ) \
+ { \
+ const ObjectClass* o = ( const ObjectClass* ) obj; \
+ return ( o->*m_getFunktion )( ); \
+ } \
+private: \
+ SetPtr m_setFunktion; \
+ GetPtr m_getFunktion; \
+}
+// no semicolon, put a semicolon after the macro!
+
+#endif
diff --git a/kpovmodeler/pmerrordialog.cpp b/kpovmodeler/pmerrordialog.cpp
new file mode 100644
index 00000000..721cd302
--- /dev/null
+++ b/kpovmodeler/pmerrordialog.cpp
@@ -0,0 +1,136 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmerrordialog.h"
+#include "pmerrorflags.h"
+
+#include <klocale.h>
+#include <qlabel.h>
+#include <qtextedit.h>
+
+#include <kconfig.h>
+
+
+QSize PMErrorDialog::s_size = QSize( 150, 200 );
+
+PMErrorDialog::PMErrorDialog( const PMMessageList& messages, int errorFlags,
+ QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Messages" ),
+ Ok | Cancel, Cancel )
+{
+ QVBox* page = makeVBoxMainWidget( );
+ QLabel* text = new QLabel( QString( "" ), ( QWidget* )page );
+
+
+ m_pTextView = new QTextEdit( ( QWidget* )page );
+ m_pTextView->setReadOnly( true );
+
+ m_messageDict.setAutoDelete( true );
+ m_messages.setAutoDelete( true );
+
+ PMMessageList::ConstIterator it;
+ for( it = messages.begin( ); it != messages.end( ); ++it )
+ m_messages.append( new PMMessage( *it ) );
+
+ QPtrListIterator<PMMessage> pit( m_messages );
+ for( ; pit.current( ); ++pit )
+ {
+ PMObject* obj = pit.current( )->linkedObject( );
+ for( ; obj; obj = obj->parent( ) )
+ {
+ QPtrList<PMMessage>* pList = m_messageDict.find( obj );
+ if( !pList )
+ {
+ pList = new QPtrList<PMMessage>;
+ m_messageDict.insert( obj, pList );
+ }
+ pList->append( pit.current( ) );
+ if( !obj->parent( ) )
+ {
+ if( obj->type( ) != "scene" )
+ {
+ kdError( PMArea ) << "A message contains an object that is not inserted in the scene" << endl;
+ pit.current( )->setLinkedObject( 0 );
+ }
+ }
+ }
+ }
+
+ displayMessages( );
+
+ if( errorFlags & PMEWarning )
+ {
+ if( ( errorFlags & PMEError ) || ( errorFlags & PMEFatal ) )
+ text->setText( i18n( "There were warnings and errors:" ) );
+ else
+ text->setText( i18n( "There were warnings:" ) );
+ }
+ else
+ text->setText( i18n( "There were errors:" ) );
+
+ setButtonOKText( KStdGuiItem::ok().text(),
+ i18n( "Proceed" ),
+ i18n( "When clicking <b>Proceed</b>, the program\n"
+ "will try to proceed with the current action." ) );
+ setButtonCancelText( KStdGuiItem::cancel().text(),
+ i18n( "&Cancel" ),
+ i18n( "When clicking <b>Cancel<b>, the program\n"
+ "will cancel the current action." ) );
+
+ if( errorFlags & PMEFatal )
+ showButtonOK( false );
+ else
+ new QLabel( i18n( "Still try to proceed?" ), ( QWidget* )page );
+
+ resize( s_size );
+}
+
+void PMErrorDialog::displayMessages( )
+{
+ QPtrListIterator<PMMessage> pit( m_messages );
+ QString text;
+
+ text = "<qt>\n";
+
+ for( ; pit.current( ); ++pit )
+ text += "<p>" + pit.current( )->text( ) + "</p>\n";
+
+ text += "</qt>";
+
+ m_pTextView->setText( text );
+}
+
+void PMErrorDialog::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+ cfg->writeEntry( "ErrorDialogSize", s_size );
+}
+
+void PMErrorDialog::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+
+ QSize defaultSize( 150, 200 );
+ s_size = cfg->readSizeEntry( "ErrorDialogSize", &defaultSize );
+}
+
+void PMErrorDialog::resizeEvent( QResizeEvent* ev )
+{
+ s_size = ev->size( );
+}
+#include "pmerrordialog.moc"
diff --git a/kpovmodeler/pmerrordialog.h b/kpovmodeler/pmerrordialog.h
new file mode 100644
index 00000000..972d55ab
--- /dev/null
+++ b/kpovmodeler/pmerrordialog.h
@@ -0,0 +1,73 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMERRORDIALOG_H
+#define PMERRORDIALOG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+#include <qvaluelist.h>
+#include <qptrdict.h>
+#include <qptrlist.h>
+
+class KConfig;
+class QTextEdit;
+class PMObject;
+
+#include "pmmessage.h"
+
+/**
+ * Dialog that is shown if some errors or warnings occurred during
+ * parsing or execution of commands.
+ */
+class PMErrorDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a modal PMErrorDialog with parent and name.
+ *
+ * messages is the message list. If the list contains a message of type
+ * FatalError, the 'Proceed" button will not be shown.
+ *
+ * PMErrorDialog::exec( ) returns QDialog::Accepted if the command
+ * should be continued.
+ */
+ PMErrorDialog( const PMMessageList& messages, int errorFlags,
+ QWidget* parent = 0, const char* name = 0 );
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+
+protected:
+ virtual void resizeEvent( QResizeEvent* ev );
+
+private:
+ void displayMessages( );
+
+ static QSize s_size;
+ QTextEdit* m_pTextView;
+ QPtrDict< QPtrList<PMMessage> > m_messageDict;
+ QPtrList<PMMessage> m_messages;
+};
+
+#endif
diff --git a/kpovmodeler/pmerrorflags.h b/kpovmodeler/pmerrorflags.h
new file mode 100644
index 00000000..ce604c9b
--- /dev/null
+++ b/kpovmodeler/pmerrorflags.h
@@ -0,0 +1,31 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMERRORFLAGS_H
+#define PMERRORFLAGS_H
+
+/**
+ * Error flags
+ *
+ * These flags are returnd by @ref PMParser::errorFlags( )
+ * and PMCommand::errorFlags( )
+ */
+
+enum PMErrorFlags { PMENone = 0, PMEWarning = 1, PMEError = 2, PMEFatal = 4 };
+
+#endif
diff --git a/kpovmodeler/pmface.cpp b/kpovmodeler/pmface.cpp
new file mode 100644
index 00000000..654a31b0
--- /dev/null
+++ b/kpovmodeler/pmface.cpp
@@ -0,0 +1,119 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+#include <new>
+#include "pmface.h"
+
+GLuint PMFace::s_dummy = 0;
+
+PMFace::PMFace( const PMFace& face )
+{
+ m_points = new( std::nothrow ) GLuint[ face.m_size ];
+ for( unsigned i = 0; i < face.m_size; ++i )
+ m_points[ i ] = face.m_points[ i ];
+ m_size = face.m_size;
+ m_normal = face.m_normal;
+}
+
+PMFace::PMFace( const GLuint pt1, const GLuint pt2, const GLuint pt3, const PMVector& normal )
+{
+ m_points = new( std::nothrow ) GLuint[ 3 ];
+ m_points[ 0 ] = pt1;
+ m_points[ 1 ] = pt2;
+ m_points[ 2 ] = pt3;
+ m_size = 3;
+ m_normal = normal;
+}
+
+PMFace::PMFace( const GLuint pt1, const GLuint pt2, const GLuint pt3, const GLuint pt4, const PMVector& normal )
+{
+ m_points = new( std::nothrow ) GLuint[ 4 ];
+ m_points[ 0 ] = pt1;
+ m_points[ 1 ] = pt2;
+ m_points[ 2 ] = pt3;
+ m_points[ 3 ] = pt4;
+ m_size = 4;
+ m_normal = normal;
+}
+
+PMFace& PMFace::operator=( const PMFace& face )
+{
+ delete m_points;
+ m_points = new( std::nothrow ) GLuint[ face.m_size ];
+ for( unsigned i = 0; i < face.m_size; ++i )
+ m_points[ i ] = face.m_points[ i ];
+ m_size = face.m_size;
+ m_normal = face.m_normal;
+ return *this;
+}
+
+bool PMFace::operator==( const PMFace& face ) const
+{
+ if( m_size == face.m_size && m_normal == face.m_normal )
+ {
+ for( unsigned i = 0; i < m_size; ++i )
+ {
+ if( m_points[i] != face.m_points[i] )
+ return false;
+ }
+ return true;
+ }
+ else
+ return false;
+}
+
+bool PMFace::operator!=( const PMFace& face ) const
+{
+ return !( *this == face );
+}
+
+bool PMFace::resize( const unsigned int size )
+{
+ if( size != m_size )
+ {
+ GLuint* temp = new( std::nothrow ) GLuint[ size ];
+ if( temp )
+ {
+ for( unsigned i = 0; i < m_size && i < size; ++i )
+ temp[i] = m_points[i];
+
+ for( unsigned i = m_size; i < size; ++i )
+ temp[i] = 0;
+
+ delete [] m_points;
+ m_points = temp;
+ }
+ else
+ return false;
+ }
+ return true;
+}
+
+GLuint& PMFace::operator[] ( int index )
+{
+ if( ( index >= 0 ) && ( index < ( signed ) m_size ) )
+ return m_points[index];
+ kdError( PMArea ) << "Bad index in PMFace operator []\n";
+ return s_dummy;
+}
+
+const GLuint& PMFace::operator[] ( int index ) const
+{
+ if( ( index >= 0 ) && ( index < ( signed ) m_size ) )
+ return m_points[index];
+ kdError( PMArea ) << "Bad index in PMFace operator []\n";
+ return s_dummy;
+}
diff --git a/kpovmodeler/pmface.h b/kpovmodeler/pmface.h
new file mode 100644
index 00000000..46da64bb
--- /dev/null
+++ b/kpovmodeler/pmface.h
@@ -0,0 +1,130 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+#ifndef PMFACE_H
+#define PMFACE_H
+
+#include <qptrlist.h>
+#include <qvaluevector.h>
+#include <GL/gl.h>
+#include "pmdebug.h"
+#include "pmvector.h"
+
+/**
+ * face to display with index of points. Points must be in clockwise order.
+ *
+ * Face of a @ref PMViewStructure. Only the indices in a @ref PMPointArray
+ * are stored.
+ *
+ * Optimized for OpenGL
+ */
+class PMFace
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMFace( )
+ {
+ m_points = 0;
+ m_size = 0;
+ }
+ /**
+ * Copy Constructor
+ */
+ PMFace( const PMFace& face );
+ /**
+ * Destructor
+ */
+ ~PMFace( ) { delete m_points; }
+ /**
+ * Creates a face with three points.
+ */
+ PMFace( const GLuint pt1, const GLuint pt2, const GLuint pt3, const PMVector& normal = PMVector() );
+ /**
+ * Creates a face with four points.
+ */
+ PMFace( const GLuint pt1, const GLuint pt2, const GLuint pt3, const GLuint pt4, const PMVector& normal = PMVector() );
+
+ /**
+ * Operator assignment
+ */
+ PMFace& operator=( const PMFace& face );
+ /**
+ * Operator equals
+ */
+ bool operator==( const PMFace& face ) const;
+ /**
+ * Operator unequals
+ */
+ bool operator!=( const PMFace& face ) const;
+
+ /**
+ * Resizes the number of points in the face.
+ * @return True if successful
+ */
+ bool resize( const unsigned int size );
+ /**
+ * @return The number of points in the face.
+ */
+ unsigned int size( ) const { return m_size; }
+
+ /**
+ * Returns a reference to a point in the face
+ */
+ GLuint& operator[] ( int index );
+ /**
+ * Returns a const reference to a point in the face
+ */
+ const GLuint& operator[] ( int index ) const;
+
+ /**
+ * Calculates the normal for the face
+ */
+ void setNormal( const PMVector& normal ) { m_normal = normal; }
+ /**
+ * Returns the normal for the face
+ */
+ PMVector normal( ) const { return m_normal; }
+
+private:
+ /**
+ * The face points (indices!)
+ */
+ GLuint* m_points;
+ /**
+ * The number of points in the face
+ */
+ unsigned int m_size;
+ /**
+ * The normal of the face, calculated automatically
+ */
+ PMVector m_normal;
+ static GLuint s_dummy;
+};
+
+typedef QPtrListIterator<PMFace> PMFaceListIterator;
+
+/**
+ * A list of @ref PMFace objects.
+ *
+ * This class stores all faces of a @ref PMViewStructure. Only the indices
+ * in a @ref PMPointArray are stored.
+ */
+typedef QValueVector<PMFace> PMFaceArray;
+
+#endif
diff --git a/kpovmodeler/pmfactory.cpp b/kpovmodeler/pmfactory.cpp
new file mode 100644
index 00000000..4a3631ae
--- /dev/null
+++ b/kpovmodeler/pmfactory.cpp
@@ -0,0 +1,102 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+
+#include "pmfactory.h"
+#include "pmpart.h"
+#include "pmdebug.h"
+#include "version.h"
+
+extern "C"
+{
+ void* init_libkpovmodelerpart( )
+ {
+ return new PMFactory( );
+ }
+}
+
+static const char description[] = I18N_NOOP( "Modeler for POV-Ray Scenes" );
+
+KInstance* PMFactory::s_instance = 0L;
+KAboutData* PMFactory::s_aboutData = 0L;
+
+PMFactory::PMFactory( )
+{
+ kdDebug( ) << "PMFactory::PMFactory( )\n";
+}
+
+PMFactory::~PMFactory( )
+{
+ if( s_instance )
+ delete s_instance;
+ if( s_aboutData )
+ delete s_aboutData;
+
+ s_instance = 0L;
+ s_aboutData = 0L;
+}
+
+KParts::Part* PMFactory::createPartObject( QWidget* parentWidget,
+ const char* widgetName,
+ QObject* parent, const char* name,
+ const char* classname,
+ const QStringList& /*args*/ )
+{
+ kdDebug( ) << "PMFactory: Created new part\n";
+
+ bool readwrite = !( ( strcmp( classname, "Browser/View" ) == 0 )
+ || ( strcmp( classname, "KParts::ReadOnlyPart" ) == 0 ) );
+
+ KParts::ReadWritePart *part = new PMPart( parentWidget, widgetName,
+ parent, name, readwrite );
+
+ return part;
+}
+
+KInstance* PMFactory::instance( )
+{
+ if( !s_instance )
+ s_instance = new KInstance( aboutData( ) );
+ return s_instance;
+}
+
+const KAboutData* PMFactory::aboutData( )
+{
+ if( !s_aboutData )
+ {
+ s_aboutData =
+ new KAboutData( "kpovmodeler", I18N_NOOP( "KPovModeler" ),
+ KPOVMODELER_VERSION, description,
+ KAboutData::License_GPL, "(c) 2001-2006, Andreas Zehender" );
+ s_aboutData->addAuthor( "Andreas Zehender", 0,
+ "zehender@kde.org", "http://www.azweb.de" );
+ s_aboutData->addAuthor( "Luis Passos Carvalho", I18N_NOOP( "Textures" ),
+ "lpassos@mail.telepac.pt" );
+ s_aboutData->addAuthor( "Leon Pennington", I18N_NOOP( "POV-Ray 3.5 objects" ),
+ "leon@leonscape.co.uk" );
+ s_aboutData->addAuthor( "Philippe Van Hecke", I18N_NOOP( "Some graphical objects" ),
+ "lephiloux@tiscalinet.be" );
+ s_aboutData->addAuthor( "Leonardo Skorianez", I18N_NOOP( "Some graphical objects" ),
+ "skorianez@bol.com.br" );
+ }
+ return s_aboutData;
+}
+#include "pmfactory.moc"
diff --git a/kpovmodeler/pmfactory.h b/kpovmodeler/pmfactory.h
new file mode 100644
index 00000000..b44c6bd3
--- /dev/null
+++ b/kpovmodeler/pmfactory.h
@@ -0,0 +1,48 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMFACTORY_H
+#define PMFACTORY_H
+
+#include <kparts/factory.h>
+
+class KAboutData;
+class KInstance;
+
+class PMFactory : public KParts::Factory
+{
+ Q_OBJECT
+public:
+ PMFactory( );
+ virtual ~PMFactory( );
+
+ virtual KParts::Part* createPartObject( QWidget* parentWidget,
+ const char* widgetName,
+ QObject* parent, const char* name,
+ const char* classname,
+ const QStringList& args );
+
+ static KInstance* instance( );
+ static const KAboutData* aboutData( );
+private:
+ static KInstance* s_instance;
+ static KAboutData* s_aboutData;
+};
+
+#endif
diff --git a/kpovmodeler/pmfiledialog.cpp b/kpovmodeler/pmfiledialog.cpp
new file mode 100644
index 00000000..68030f8c
--- /dev/null
+++ b/kpovmodeler/pmfiledialog.cpp
@@ -0,0 +1,104 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmfiledialog.h"
+#include "pmpart.h"
+
+#include <kfilefiltercombo.h>
+
+
+PMFileDialog::PMFileDialog( const QString& startDir, const QString& filter, QWidget* parent, const char* name, bool modal )
+ : KFileDialog( startDir, filter, parent, name, modal )
+{
+
+}
+
+QString PMFileDialog::getImportFileName( QWidget* parent, PMPart* part,
+ PMIOFormat*& format )
+{
+ PMIOManager* manager = part->ioManager( );
+ QString filter;
+ QPtrListIterator<PMIOFormat> it( manager->formats( ) );
+ QPtrList<PMIOFormat> formats;
+
+ for( ; it.current( ); ++it )
+ {
+ if( it.current( )->services( ) & PMIOFormat::Import )
+ {
+ QStringList patterns = it.current( )->importPatterns( );
+ QStringList::Iterator pit;
+ for( pit = patterns.begin( ); pit != patterns.end( ); ++pit )
+ {
+ if( !filter.isEmpty( ) )
+ filter += "\n";
+ filter += *pit;
+ formats.append( it.current( ) );
+ }
+ }
+ }
+
+ PMFileDialog dlg( QString::null, filter, parent, "import file dialog", true );
+ dlg.setOperationMode( Opening );
+ dlg.setMode( KFile::File | KFile::LocalOnly );
+ dlg.setCaption( i18n( "Import" ) );
+ dlg.filterWidget->setEditable( false );
+ dlg.exec( );
+
+ format = formats.at( dlg.filterWidget->currentItem( ) );
+
+ return dlg.selectedFile( );
+}
+
+QString PMFileDialog::getExportFileName( QWidget* parent, PMPart* part,
+ PMIOFormat*& format, QString& selectedFilter )
+{
+ PMIOManager* manager = part->ioManager( );
+ QString filter;
+ QPtrListIterator<PMIOFormat> it( manager->formats( ) );
+ QPtrList<PMIOFormat> formats;
+
+ for( ; it.current( ); ++it )
+ {
+ if( it.current( )->services( ) & PMIOFormat::Export )
+ {
+ QStringList patterns = it.current( )->exportPatterns( );
+ QStringList::Iterator pit;
+ for( pit = patterns.begin( ); pit != patterns.end( ); ++pit )
+ {
+ if( !filter.isEmpty( ) )
+ filter += "\n";
+ filter += *pit;
+ formats.append( it.current( ) );
+ }
+ }
+ }
+
+ PMFileDialog dlg( QString::null, filter, parent, "export file dialog", true );
+ dlg.setOperationMode( Saving );
+ dlg.setMode( KFile::File | KFile::LocalOnly );
+ dlg.setCaption( i18n( "Export" ) );
+ dlg.filterWidget->setEditable( false );
+ dlg.exec( );
+
+ format = formats.at( dlg.filterWidget->currentItem( ) );
+ selectedFilter = dlg.currentFilter( );
+
+ return dlg.selectedFile( );
+}
+
+#include "pmfiledialog.moc"
diff --git a/kpovmodeler/pmfiledialog.h b/kpovmodeler/pmfiledialog.h
new file mode 100644
index 00000000..e98a84ab
--- /dev/null
+++ b/kpovmodeler/pmfiledialog.h
@@ -0,0 +1,60 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMFILEDIALOG_H
+#define PMFILEDIALOG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmiomanager.h"
+#include <kfiledialog.h>
+
+class PMPart;
+
+/**
+ * File dialog used for the import and export action.
+ *
+ * The filters will be set automatically dependent on the
+ * supported file formats
+ * @see PMIOManager
+ */
+class PMFileDialog : public KFileDialog
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor, use the static methods
+ * @ref getImportFileName or @ref getExportFileName instead
+ */
+ PMFileDialog( const QString& startDir, const QString& filter, QWidget* parent, const char* name, bool modal );
+ /**
+ * Opens a modal file dialog and returns a selected file and the chosen
+ * file format.
+ */
+ static QString getImportFileName( QWidget* parent, PMPart* part, PMIOFormat*& format );
+ /**
+ * Opens a modal file dialog and returns a selected file and the chosen
+ * file format and filter.
+ */
+ static QString getExportFileName( QWidget* parent, PMPart* part,
+ PMIOFormat*& format, QString& filter );
+};
+
+#endif
diff --git a/kpovmodeler/pmfinish.cpp b/kpovmodeler/pmfinish.cpp
new file mode 100644
index 00000000..a98b9a2c
--- /dev/null
+++ b/kpovmodeler/pmfinish.cpp
@@ -0,0 +1,765 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmfinish.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmfinishedit.h"
+
+#include <klocale.h>
+
+const PMColor ambientColorDefault = PMColor( 0.0, 0.0, 0.0, 0.0, 0.0 );
+const double diffuseDefault = 0.6;
+const double brillianceDefault = 1.0;
+const double crandDefault = 0.0;
+const double phongDefault = 0.0;
+const double phongSizeDefault = 40.0;
+const double metallicDefault = 1.0;
+const double specularDefault = 0.0;
+const double roughnessDefault = 0.05;
+const double iridAmountDefault = 0.0;
+const double iridThicknessDefault = 0.0;
+const double iridTurbulenceDefault = 0.0;
+const PMColor reflectionColorDefault = PMColor( 0.0, 0.0, 0.0, 0.0, 0.0 );
+const double reflectionFalloffDefault = 0.0;
+const double reflectionExponentDefault = 1.0;
+const double reflectionMetallicDefault = 1.0;
+
+PMDefinePropertyClass( PMFinish, PMFinishProperty );
+
+PMMetaObject* PMFinish::s_pMetaObject = 0;
+PMObject* createNewFinish( PMPart* part )
+{
+ return new PMFinish( part );
+}
+
+PMFinish::PMFinish( PMPart* part )
+ : Base( part )
+{
+ m_ambientColor = ambientColorDefault;
+ m_diffuse = diffuseDefault;
+ m_brilliance = brillianceDefault;
+ m_crand = crandDefault;
+ m_conserveEnergy = false;
+ m_phong = phongDefault;
+ m_phongSize = phongSizeDefault;
+ m_metallic = metallicDefault;
+ m_specular = specularDefault;
+ m_roughness = roughnessDefault;
+ m_iridAmount = iridAmountDefault;
+ m_iridThickness = iridThicknessDefault;
+ m_iridTurbulence = iridTurbulenceDefault;
+ m_reflectionColor = reflectionColorDefault;
+ m_reflectionMinColor = reflectionColorDefault;
+ m_reflectionFresnel = false;
+ m_reflectionFalloff = reflectionFalloffDefault;
+ m_reflectionExponent = reflectionExponentDefault;
+ m_reflectionMetallic = reflectionMetallicDefault;
+ m_enableAmbient = false;
+ m_enableDiffuse = false;
+ m_enableBrilliance = false;
+ m_enableCrand = false;
+ m_enablePhong = false;
+ m_enablePhongSize = false;
+ m_enableMetallic = false;
+ m_enableSpecular = false;
+ m_enableRoughness = false;
+ m_enableReflection = false;
+ m_enableReflectionMin = false;
+ m_enableRefFalloff = false;
+ m_enableRefExponent = false;
+ m_enableRefMetallic = false;
+ m_irid = false;
+}
+
+PMFinish::PMFinish( const PMFinish& f )
+ : Base( f )
+{
+ m_ambientColor = f.m_ambientColor;
+ m_diffuse = f.m_diffuse;
+ m_brilliance = f.m_brilliance;
+ m_crand = f.m_crand;
+ m_conserveEnergy = f.m_conserveEnergy;
+ m_phong = f.m_phong;
+ m_phongSize = f.m_phongSize;
+ m_metallic = f.m_metallic;
+ m_specular = f.m_specular;
+ m_roughness = f.m_roughness;
+ m_iridAmount = f.m_iridAmount;
+ m_iridThickness = f.m_iridThickness;
+ m_iridTurbulence = f.m_iridTurbulence;
+ m_reflectionColor = f.m_reflectionColor;
+ m_reflectionMinColor = f.m_reflectionMinColor;
+ m_reflectionFresnel = f.m_reflectionFresnel;
+ m_reflectionFalloff = f.m_reflectionFalloff;
+ m_reflectionExponent = f.m_reflectionExponent;
+ m_reflectionMetallic = f.m_reflectionMetallic;
+ m_enableAmbient = f.m_enableAmbient;
+ m_enableDiffuse = f.m_enableDiffuse;
+ m_enableBrilliance = f.m_enableBrilliance;
+ m_enableCrand = f.m_enableCrand;
+ m_enablePhong = f.m_enablePhong;
+ m_enablePhongSize = f.m_enablePhongSize;
+ m_enableMetallic = f.m_enableMetallic;
+ m_enableSpecular = f.m_enableSpecular;
+ m_enableRoughness = f.m_enableRoughness;
+ m_enableReflection = f.m_enableReflection;
+ m_enableReflectionMin = f.m_enableReflectionMin;
+ m_enableRefFalloff = f.m_enableRefFalloff;
+ m_enableRefExponent = f.m_enableRefExponent;
+ m_enableRefMetallic = f.m_enableRefMetallic;
+ m_irid = f.m_irid;
+}
+
+PMFinish::~PMFinish( )
+{
+}
+
+PMMetaObject* PMFinish::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Finish", Base::metaObject( ),
+ createNewFinish );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "ambientColor", &PMFinish::setAmbientColor, &PMFinish::ambientColor ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "phong", &PMFinish::setPhong, &PMFinish::phong ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "diffuse", &PMFinish::setDiffuse, &PMFinish::diffuse ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "brilliance", &PMFinish::setBrilliance, &PMFinish::brilliance ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "crand", &PMFinish::setCrand, &PMFinish::crand ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "conserveEnergy", &PMFinish::setConserveEnergy, &PMFinish::conserveEnergy ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "specular", &PMFinish::setSpecular, &PMFinish::specular ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "roughness", &PMFinish::setRoughness, &PMFinish::roughness ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "metallic", &PMFinish::setMetallic, &PMFinish::metallic ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "irid", &PMFinish::setIrid, &PMFinish::irid ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "iridAmount", &PMFinish::setIridAmount, &PMFinish::iridAmount ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "iridThickness", &PMFinish::setIridThickness, &PMFinish::iridThickness ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "reflectionColor", &PMFinish::setReflectionColor, &PMFinish::reflectionColor ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "reflectionMinColor", &PMFinish::setReflectionMinColor, &PMFinish::reflectionMinColor ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "reflectionFresnel", &PMFinish::setReflectionFresnel, &PMFinish::reflectionFresnel ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "reflectionFalloff", &PMFinish::setReflectionFalloff, &PMFinish::reflectionFalloff ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "reflectionExponent", &PMFinish::setReflectionExponent, &PMFinish::reflectionExponent ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "reflectionMetallic", &PMFinish::setReflectionMetallic, &PMFinish::reflectionMetallic ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "ambientEnabled", &PMFinish::enableAmbient, &PMFinish::isAmbientEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "phongEnabled", &PMFinish::enablePhong, &PMFinish::isPhongEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "phongSizeEnabled", &PMFinish::enablePhongSize, &PMFinish::isPhongSizeEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "diffuseEnabled", &PMFinish::enableDiffuse, &PMFinish::isDiffuseEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "brillianceEnabled", &PMFinish::enableBrilliance, &PMFinish::isBrillianceEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "crandEnabled", &PMFinish::enableCrand, &PMFinish::isCrandEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "specularEnabled", &PMFinish::enableSpecular, &PMFinish::isSpecularEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "roughnessEnabled", &PMFinish::enableRoughness, &PMFinish::isRoughnessEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "metallicEnabled", &PMFinish::enableMetallic, &PMFinish::isMetallicEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "reflectionEnabled", &PMFinish::enableReflection, &PMFinish::isReflectionEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "reflectionMinEnabled", &PMFinish::enableReflectionMin, &PMFinish::isReflectionMinEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "refFalloffEnabled", &PMFinish::enableRefFalloff, &PMFinish::isRefFalloffEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "refExponentEnabled", &PMFinish::enableRefExponent, &PMFinish::isRefExponentEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFinishProperty( "refMetallicEnabled", &PMFinish::enableRefMetallic, &PMFinish::isRefMetallicEnabled ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMFinish::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMFinish::description( ) const
+{
+ return i18n( "finish" );
+}
+
+void PMFinish::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ Base::serialize( e, doc );
+ e.setAttribute( "enable_ambient", m_enableAmbient );
+ e.setAttribute( "enable_diffuse", m_enableDiffuse );
+ e.setAttribute( "enable_brilliance", m_enableBrilliance );
+ e.setAttribute( "enable_crand", m_enableCrand );
+ e.setAttribute( "enable_phong", m_enablePhong );
+ e.setAttribute( "enable_phong_size", m_enablePhongSize );
+ e.setAttribute( "enable_metallic", m_enableMetallic );
+ e.setAttribute( "enable_specular", m_enableSpecular );
+ e.setAttribute( "enable_roughness", m_enableRoughness );
+ e.setAttribute( "enable_reflection", m_enableReflection );
+ e.setAttribute( "enable_reflection_min", m_enableReflectionMin );
+ e.setAttribute( "enable_reflection_falloff", m_enableRefFalloff );
+ e.setAttribute( "enable_reflection_exponent", m_enableRefExponent );
+ e.setAttribute( "enable_reflection_metallic", m_enableRefMetallic );
+ e.setAttribute( "ambient", m_ambientColor.serializeXML( ) );
+ e.setAttribute( "diffuse", m_diffuse );
+ e.setAttribute( "brilliance", m_brilliance );
+ e.setAttribute( "crand", m_crand );
+ e.setAttribute( "conserve_energy", m_conserveEnergy );
+ e.setAttribute( "phong", m_phong );
+ e.setAttribute( "phongsize", m_phongSize );
+ e.setAttribute( "metallic", m_metallic );
+ e.setAttribute( "specular", m_specular );
+ e.setAttribute( "roughness", m_roughness );
+ e.setAttribute( "irid", m_irid );
+ e.setAttribute( "irid_amount", m_iridAmount );
+ e.setAttribute( "irid_thickness", m_iridThickness );
+ e.setAttribute( "irid_turbulence", m_iridTurbulence );
+ e.setAttribute( "reflection", m_reflectionColor.serializeXML( ) );
+ e.setAttribute( "reflection_min", m_reflectionMinColor.serializeXML( ) );
+ e.setAttribute( "reflection_fresnel", m_reflectionFresnel );
+ e.setAttribute( "reflection_falloff", m_reflectionFalloff );
+ e.setAttribute( "reflection_exponent", m_reflectionExponent );
+ e.setAttribute( "reflection_metallic", m_reflectionMetallic );
+}
+
+void PMFinish::readAttributes( const PMXMLHelper& h )
+{
+ Base::readAttributes( h );
+ m_enableAmbient = h.boolAttribute( "enable_ambient", false );
+ m_enableDiffuse = h.boolAttribute( "enable_diffuse", false );
+ m_enableBrilliance = h.boolAttribute( "enable_brilliance", false );
+ m_enableCrand = h.boolAttribute( "enable_crand", false );
+ m_enablePhong = h.boolAttribute( "enable_phong", false );
+ m_enablePhongSize = h.boolAttribute( "enable_phong_size", false );
+ m_enableMetallic = h.boolAttribute( "enable_metallic", false );
+ m_enableSpecular = h.boolAttribute( "enable_specular", false );
+ m_enableRoughness = h.boolAttribute( "enable_roughness", false );
+ m_enableReflection = h.boolAttribute( "enable_reflection", false );
+ m_enableReflectionMin = h.boolAttribute( "enable_reflection_min", false );
+ m_enableRefFalloff = h.boolAttribute( "enable_reflection_falloff", false );
+ m_enableRefExponent = h.boolAttribute( "enable_reflection_exponent", false );
+ m_enableRefMetallic = h.boolAttribute( "enable_reflection_metallic", false );
+ m_irid = h.boolAttribute( "irid", false );
+ m_ambientColor = h.colorAttribute( "ambient", ambientColorDefault );
+ m_diffuse = h.doubleAttribute( "diffuse", diffuseDefault );
+ m_brilliance = h.doubleAttribute( "brilliance", crandDefault );
+ m_crand = h.doubleAttribute( "crand", crandDefault );
+ m_conserveEnergy = h.boolAttribute( "conserve_energy", false );
+ m_phong = h.doubleAttribute( "phong", phongDefault );
+ m_phongSize = h.doubleAttribute( "phongsize", phongSizeDefault );
+ m_metallic = h.doubleAttribute( "metallic", metallicDefault );
+ m_specular = h.doubleAttribute( "specular", specularDefault );
+ m_roughness = h.doubleAttribute( "roughness", roughnessDefault );
+ m_iridAmount = h.doubleAttribute( "irid_amount", iridAmountDefault );
+ m_iridThickness = h.doubleAttribute( "irid_thickness", iridThicknessDefault );
+ m_iridTurbulence = h.doubleAttribute( "irid_turbulence", iridTurbulenceDefault );
+ m_reflectionColor = h.colorAttribute( "reflection", reflectionColorDefault );
+ m_reflectionMinColor = h.colorAttribute( "reflection_min", reflectionColorDefault );
+ m_reflectionFresnel = h.boolAttribute( "reflection_fresnel", false );
+ m_reflectionFalloff = h.doubleAttribute( "reflection_falloff", reflectionFalloffDefault );
+ m_reflectionExponent = h.doubleAttribute( "reflection_exponent", reflectionExponentDefault );
+ m_reflectionMetallic = h.doubleAttribute( "reflection_metallic", reflectionMetallicDefault );
+}
+
+void PMFinish::setPhong( double c )
+{
+ if( c != m_phong )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPhongID, m_phong );
+ m_phong = c;
+ }
+}
+
+void PMFinish::setPhongSize( double c )
+{
+ if( c != m_phongSize )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPhongSizeID, m_phongSize );
+ m_phongSize = c;
+ }
+}
+
+void PMFinish::setMetallic( double c )
+{
+ if( c != m_metallic )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMetallicID, m_metallic );
+ m_metallic = c;
+ }
+}
+
+void PMFinish::setAmbientColor( const PMColor& c )
+{
+ if( c != m_ambientColor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAmbientColorID, m_ambientColor );
+ m_ambientColor = c;
+ }
+}
+
+void PMFinish::setDiffuse( double c )
+{
+ if( c != m_diffuse )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDiffuseID, m_diffuse );
+ m_diffuse = c;
+ }
+}
+
+void PMFinish::setBrilliance( double c )
+{
+ if( c != m_brilliance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBrillianceID, m_brilliance );
+ m_brilliance = c;
+ }
+}
+
+void PMFinish::setCrand( double c )
+{
+ if( c != m_crand )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCrandID, m_crand );
+ m_crand = c;
+ }
+}
+
+void PMFinish::setConserveEnergy( bool c )
+{
+ if( c != m_conserveEnergy )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMConserveEnergyID, m_conserveEnergy );
+ m_conserveEnergy = c;
+ }
+}
+
+void PMFinish::setSpecular( double c )
+{
+ if( c != m_specular )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSpecularID, m_specular );
+ m_specular = c;
+ }
+}
+
+void PMFinish::setRoughness( double c )
+{
+ if( c != m_roughness )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRoughnessID, m_roughness );
+ m_roughness = c;
+ }
+}
+
+void PMFinish::setIrid( bool c )
+{
+ if( c != m_irid )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMIridID, m_irid );
+ m_irid = c;
+ }
+}
+
+void PMFinish::setReflectionColor( const PMColor& c )
+{
+ if( c != m_reflectionColor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMReflectionColorID, m_reflectionColor );
+ m_reflectionColor = c;
+ }
+}
+
+void PMFinish::setReflectionMinColor( const PMColor& c )
+{
+ if( c != m_reflectionMinColor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMReflectionMinColorID, m_reflectionMinColor );
+ m_reflectionMinColor = c;
+ }
+}
+
+void PMFinish::setReflectionFresnel( bool c )
+{
+ if( c != m_reflectionFresnel )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMReflectionFresnelID, m_reflectionFresnel );
+ m_reflectionFresnel = c;
+ }
+}
+
+void PMFinish::setReflectionFalloff( double c )
+{
+ if( c != m_reflectionFalloff )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMReflectionFalloffID, m_reflectionFalloff );
+ m_reflectionFalloff = c;
+ }
+}
+
+void PMFinish::setReflectionExponent( double c )
+{
+ if( c != m_reflectionExponent )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMReflectionExponentID, m_reflectionExponent );
+ m_reflectionExponent = c;
+ }
+}
+
+void PMFinish::setReflectionMetallic( double c )
+{
+ if( c != m_reflectionMetallic )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMReflectionMetallicID, m_reflectionMetallic );
+ m_reflectionMetallic = c;
+ }
+}
+
+void PMFinish::enableAmbient( bool c )
+{
+ if( c != m_enableAmbient )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableAmbientID, m_enableAmbient );
+ m_enableAmbient = c;
+ }
+}
+
+void PMFinish::enableDiffuse( bool c )
+{
+ if( c != m_enableDiffuse )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableDiffuseID, m_enableDiffuse );
+ m_enableDiffuse = c;
+ }
+}
+
+void PMFinish::enablePhong( bool c )
+{
+ if( c != m_enablePhong )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnablePhongID, m_enablePhong );
+ m_enablePhong = c;
+ }
+}
+
+void PMFinish::enablePhongSize( bool c )
+{
+ if( c != m_enablePhongSize )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnablePhongSizeID, m_enablePhongSize );
+ m_enablePhongSize = c;
+ }
+}
+
+void PMFinish::enableBrilliance( bool c )
+{
+ if( c != m_enableBrilliance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableBrillianceID, m_enableBrilliance );
+ m_enableBrilliance = c;
+ }
+}
+
+void PMFinish::enableCrand( bool c )
+{
+ if( c != m_enableCrand )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableCrandID, m_enableCrand );
+ m_enableCrand = c;
+ }
+}
+
+void PMFinish::enableSpecular( bool c )
+{
+ if( c != m_enableSpecular )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableSpecularID, m_enableSpecular );
+ m_enableSpecular = c;
+ }
+}
+
+void PMFinish::enableRoughness( bool c )
+{
+ if( c != m_enableRoughness )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableRoughnessID, m_enableRoughness );
+ m_enableRoughness = c;
+ }
+}
+
+void PMFinish::enableMetallic( bool c )
+{
+ if( c != m_enableMetallic )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableMetallicID, m_enableMetallic );
+ m_enableMetallic = c;
+ }
+}
+
+void PMFinish::enableReflection( bool c )
+{
+ if( c != m_enableReflection )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableReflectionID, m_enableReflection );
+ m_enableReflection = c;
+ }
+}
+
+void PMFinish::enableReflectionMin( bool c )
+{
+ if( c != m_enableReflectionMin )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableReflectionMinID, m_enableReflectionMin );
+ m_enableReflectionMin = c;
+ }
+}
+
+void PMFinish::enableRefFalloff( bool c )
+{
+ if( c != m_enableRefFalloff )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableRefFalloffID, m_enableRefFalloff );
+ m_enableRefFalloff = c;
+ }
+}
+
+void PMFinish::enableRefExponent( bool c )
+{
+ if( c != m_enableRefExponent )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableRefExponentID, m_enableRefExponent );
+ m_enableRefExponent = c;
+ }
+}
+
+void PMFinish::enableRefMetallic( bool c )
+{
+ if( c != m_enableRefMetallic )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableRefMetallicID, m_enableRefMetallic );
+ m_enableRefMetallic = c;
+ }
+}
+
+void PMFinish::setIridAmount( double c )
+{
+ if( c != m_iridAmount )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMIridAmountID, m_iridAmount );
+ m_iridAmount = c;
+ }
+}
+
+void PMFinish::setIridThickness( double c )
+{
+ if( c != m_iridThickness )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMIridThicknessID, m_iridThickness );
+ m_iridThickness = c;
+ }
+}
+
+void PMFinish::setIridTurbulence( double c )
+{
+ if( c != m_iridTurbulence )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMIridTurbulenceID, m_iridTurbulence );
+ m_iridTurbulence = c;
+ }
+}
+
+PMDialogEditBase* PMFinish::editWidget( QWidget* parent ) const
+{
+ return new PMFinishEdit( parent );
+}
+
+void PMFinish::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMAmbientColorID:
+ setAmbientColor( data->colorData( ) );
+ break;
+ case PMDiffuseID:
+ setDiffuse( data->doubleData( ) );
+ break;
+ case PMBrillianceID:
+ setBrilliance( data->doubleData( ) );
+ break;
+ case PMCrandID:
+ setCrand( data->doubleData( ) );
+ break;
+ case PMConserveEnergyID:
+ setConserveEnergy( data->boolData( ) );
+ case PMPhongID:
+ setPhong( data->doubleData( ) );
+ break;
+ case PMPhongSizeID:
+ setPhongSize( data->doubleData( ) );
+ break;
+ case PMMetallicID:
+ setMetallic( data->doubleData( ) );
+ break;
+ case PMSpecularID:
+ setSpecular( data->doubleData( ) );
+ break;
+ case PMRoughnessID:
+ setRoughness( data->doubleData( ) );
+ break;
+ case PMIridID:
+ setIrid( data->boolData( ) );
+ break;
+ case PMIridAmountID:
+ setIridAmount( data->doubleData( ) );
+ break;
+ case PMIridThicknessID:
+ setIridThickness( data->doubleData( ) );
+ break;
+ case PMIridTurbulenceID:
+ setIridTurbulence( data->doubleData( ) );
+ break;
+ case PMReflectionColorID:
+ setReflectionColor( data->colorData( ) );
+ break;
+ case PMReflectionMinColorID:
+ setReflectionMinColor( data->colorData( ) );
+ break;
+ case PMReflectionFresnelID:
+ setReflectionFresnel( data->boolData( ) );
+ break;
+ case PMReflectionFalloffID:
+ setReflectionFalloff( data->doubleData( ) );
+ break;
+ case PMReflectionExponentID:
+ setReflectionExponent( data->doubleData( ) );
+ break;
+ case PMReflectionMetallicID:
+ setReflectionMetallic( data->doubleData( ) );
+ break;
+ case PMEnableAmbientID:
+ enableAmbient( data->boolData( ) );
+ break;
+ case PMEnablePhongID:
+ enablePhong( data->boolData( ) );
+ break;
+ case PMEnablePhongSizeID:
+ enablePhongSize( data->boolData( ) );
+ break;
+ case PMEnableDiffuseID:
+ enableDiffuse( data->boolData( ) );
+ break;
+ case PMEnableBrillianceID:
+ enableBrilliance( data->boolData( ) );
+ break;
+ case PMEnableCrandID:
+ enableCrand( data->boolData( ) );
+ break;
+ case PMEnableSpecularID:
+ enableSpecular( data->boolData( ) );
+ break;
+ case PMEnableRoughnessID:
+ enableRoughness( data->boolData( ) );
+ break;
+ case PMEnableMetallicID:
+ enableMetallic( data->boolData( ) );
+ break;
+ case PMEnableReflectionID:
+ enableReflection( data->boolData( ) );
+ break;
+ case PMEnableReflectionMinID:
+ enableReflectionMin( data->boolData( ) );
+ break;
+ case PMEnableRefFalloffID:
+ enableRefFalloff( data->boolData( ) );
+ break;
+ case PMEnableRefExponentID:
+ enableRefExponent( data->boolData( ) );
+ break;
+ case PMEnableRefMetallicID:
+ enableRefMetallic( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMFinish::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmfinish.h b/kpovmodeler/pmfinish.h
new file mode 100644
index 00000000..072a0f7c
--- /dev/null
+++ b/kpovmodeler/pmfinish.h
@@ -0,0 +1,208 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMFINISH_H
+#define PMFINISH_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+#include "pmcolor.h"
+
+/**
+ * Class for povray finishs
+ */
+class PMFinish : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMFinish
+ */
+ PMFinish( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMFinish( const PMFinish& f );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMFinish( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMFinish( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMFinishEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmfinish" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ PMColor ambientColor( ) const { return m_ambientColor; }
+ double phong( ) const { return m_phong; }
+ double phongSize( ) const { return m_phongSize; }
+ double diffuse( ) const { return m_diffuse; }
+ double brilliance( ) const { return m_brilliance; }
+ double crand( ) const { return m_crand; }
+ bool conserveEnergy( ) const { return m_conserveEnergy; }
+ double specular( ) const { return m_specular; }
+ double roughness( ) const { return m_roughness; }
+ double metallic( ) const { return m_metallic; }
+ bool irid( ) const { return m_irid; }
+ double iridAmount( ) const { return m_iridAmount; }
+ double iridThickness( ) const { return m_iridThickness; }
+ double iridTurbulence( ) const { return m_iridTurbulence; }
+ PMColor reflectionColor( ) const { return m_reflectionColor; }
+ PMColor reflectionMinColor( ) const { return m_reflectionMinColor;}
+ bool reflectionFresnel( ) const { return m_reflectionFresnel; }
+ double reflectionFalloff( ) const { return m_reflectionFalloff; }
+ double reflectionExponent( ) const { return m_reflectionExponent; }
+ double reflectionMetallic( ) const { return m_reflectionMetallic; }
+ bool isAmbientEnabled( ) const { return m_enableAmbient; }
+ bool isPhongEnabled( ) const { return m_enablePhong; }
+ bool isPhongSizeEnabled( ) const { return m_enablePhongSize; }
+ bool isDiffuseEnabled( ) const { return m_enableDiffuse; }
+ bool isBrillianceEnabled( ) const { return m_enableBrilliance; }
+ bool isCrandEnabled( ) const { return m_enableCrand; }
+ bool isSpecularEnabled( ) const { return m_enableSpecular; }
+ bool isRoughnessEnabled( ) const { return m_enableRoughness; }
+ bool isMetallicEnabled( ) const { return m_enableMetallic; }
+ bool isReflectionEnabled( ) const { return m_enableReflection; }
+ bool isReflectionMinEnabled( ) const { return m_enableReflectionMin; }
+ bool isRefFalloffEnabled( ) const { return m_enableRefFalloff; }
+ bool isRefExponentEnabled( ) const { return m_enableRefExponent; }
+ bool isRefMetallicEnabled( ) const { return m_enableRefMetallic; }
+
+ //This is here for povrat31serialization (It won't compile otherwise)
+ bool isExponentEnabled( ) const { return m_enableRefExponent; }
+
+ void setAmbientColor( const PMColor& c );
+ void setPhong( double c );
+ void setPhongSize( double c );
+ void setDiffuse( double c );
+ void setBrilliance( double c );
+ void setCrand( double c );
+ void setConserveEnergy( bool c );
+ void setSpecular( double c );
+ void setRoughness( double c );
+ void setMetallic( double c );
+ void setIrid( bool c );
+ void setIridAmount( double c );
+ void setIridThickness( double c );
+ void setIridTurbulence( double c );
+ void setReflectionColor( const PMColor& c );
+ void setReflectionMinColor( const PMColor& c );
+ void setReflectionFresnel( bool c );
+ void setReflectionFalloff( double c );
+ void setReflectionExponent( double c );
+ void setReflectionMetallic( double c );
+ void enableAmbient( bool c );
+ void enablePhong( bool c );
+ void enablePhongSize( bool c );
+ void enableDiffuse( bool c );
+ void enableBrilliance( bool c );
+ void enableCrand( bool c );
+ void enableSpecular( bool c );
+ void enableRoughness( bool c );
+ void enableMetallic( bool c );
+ void enableReflection( bool c );
+ void enableReflectionMin( bool c );
+ void enableRefFalloff( bool c );
+ void enableRefExponent( bool c );
+ void enableRefMetallic( bool c );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMFinishMementoID { PMAmbientColorID, PMPhongID, PMPhongSizeID,
+ PMMetallicID, PMDiffuseID, PMBrillianceID,
+ PMCrandID, PMConserveEnergyID, PMSpecularID,
+ PMRoughnessID,
+ PMIridID, PMIridAmountID, PMIridThicknessID,
+ PMReflectionColorID, PMReflectionMinColorID,
+ PMReflectionFresnelID, PMReflectionFalloffID,
+ PMReflectionExponentID, PMReflectionMetallicID,
+ PMIridTurbulenceID, PMEnableAmbientID,
+ PMEnablePhongID, PMEnablePhongSizeID,
+ PMEnableMetallicID,
+ PMEnableDiffuseID, PMEnableBrillianceID,
+ PMEnableCrandID, PMEnableSpecularID,
+ PMEnableRoughnessID, PMEnableReflectionID,
+ PMEnableReflectionMinID, PMEnableRefFalloffID,
+ PMEnableRefExponentID, PMEnableRefMetallicID };
+
+ PMColor m_ambientColor;
+ double m_phong;
+ double m_phongSize;
+ double m_diffuse;
+ double m_brilliance;
+ double m_crand;
+ bool m_conserveEnergy;
+ double m_specular;
+ double m_roughness;
+ double m_metallic;
+ bool m_irid;
+ double m_iridAmount;
+ double m_iridThickness;
+ double m_iridTurbulence;
+ PMColor m_reflectionColor;
+ PMColor m_reflectionMinColor;
+ bool m_reflectionFresnel;
+ double m_reflectionFalloff;
+ double m_reflectionExponent;
+ double m_reflectionMetallic;
+
+ bool m_enableAmbient;
+ bool m_enableDiffuse;
+ bool m_enableBrilliance;
+ bool m_enableCrand;
+ bool m_enablePhong;
+ bool m_enablePhongSize;
+ bool m_enableMetallic;
+ bool m_enableSpecular;
+ bool m_enableRoughness;
+ bool m_enableReflection;
+ bool m_enableReflectionMin;
+ bool m_enableRefFalloff;
+ bool m_enableRefExponent;
+ bool m_enableRefMetallic;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmfinishedit.cpp b/kpovmodeler/pmfinishedit.cpp
new file mode 100644
index 00000000..809cbd66
--- /dev/null
+++ b/kpovmodeler/pmfinishedit.cpp
@@ -0,0 +1,474 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmfinishedit.h"
+#include "pmfinish.h"
+#include "pmlineedits.h"
+#include "pmcoloredit.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+#include <kdialog.h>
+
+
+PMFinishEdit::PMFinishEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMFinishEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ QGridLayout* layout = new QGridLayout( hl, 2, 2 );
+ m_pEnableAmbientEdit = new QCheckBox( i18n( "Ambient color" ), this );
+ m_pAmbientColorLabel = new QLabel( i18n( "Color:" ), this );
+ m_pAmbientColorEdit = new PMColorEdit( true, this );
+ layout->addMultiCellWidget( m_pEnableAmbientEdit, 0, 0, 0, 1 );
+ layout->addWidget( m_pAmbientColorLabel, 1, 0, AlignTop );
+ layout->addWidget( m_pAmbientColorEdit, 1, 1 );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ layout = new QGridLayout( hl, 4, 2 );
+ m_pEnableDiffuseEdit = new QCheckBox( i18n( "Diffuse:" ), this );
+ m_pDiffuseEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableDiffuseEdit, 0, 0 );
+ layout->addWidget( m_pDiffuseEdit, 0, 1 );
+ m_pEnableBrillianceEdit = new QCheckBox( i18n( "Brilliance:" ), this );
+ m_pBrillianceEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableBrillianceEdit, 1, 0 );
+ layout->addWidget( m_pBrillianceEdit, 1, 1 );
+ m_pEnableCrandEdit = new QCheckBox( i18n( "Crand:" ), this );
+ m_pCrandEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableCrandEdit, 2, 0 );
+ layout->addWidget( m_pCrandEdit, 2, 1 );
+ m_pConserveEnergyEdit = new QCheckBox(
+ i18n( "Conserve energy for reflection" ), this );
+ layout->addMultiCellWidget( m_pConserveEnergyEdit, 3, 3, 0, 1 );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ layout = new QGridLayout( hl, 2, 2 );
+ m_pEnablePhongEdit = new QCheckBox( i18n( "Phong:" ), this );
+ m_pPhongEdit = new PMFloatEdit( this );
+ m_pEnablePhongSizeEdit = new QCheckBox( i18n( "Phong size:" ), this );
+ m_pPhongSizeEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnablePhongEdit, 0, 0 );
+ layout->addWidget( m_pPhongEdit, 0, 1 );
+ layout->addWidget( m_pEnablePhongSizeEdit, 1, 0 );
+ layout->addWidget( m_pPhongSizeEdit, 1, 1 );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ layout = new QGridLayout( hl, 3, 2 );
+ m_pEnableSpecularEdit = new QCheckBox( i18n( "Specular:" ), this );
+ m_pSpecularEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableSpecularEdit, 0, 0 );
+ layout->addWidget( m_pSpecularEdit, 0, 1 );
+ m_pEnableRoughnessEdit = new QCheckBox( i18n( "Roughness:" ), this );
+ m_pRoughnessEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableRoughnessEdit, 1, 0 );
+ layout->addWidget( m_pRoughnessEdit, 1, 1 );
+ m_pEnableMetallicEdit = new QCheckBox( i18n( "Metallic:" ), this );
+ m_pMetallicEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableMetallicEdit, 2, 0 );
+ layout->addWidget( m_pMetallicEdit, 2, 1 );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ layout = new QGridLayout( hl, 6, 2 );
+ m_pIridEdit = new QCheckBox( i18n( "Iridiscence" ), this );
+ layout->addMultiCellWidget( m_pIridEdit, 0, 0, 0, 1 );
+ m_pIridAmountLabel = new QLabel( i18n( "Amount:" ), this );
+ m_pIridAmountEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pIridAmountLabel, 1, 0 );
+ layout->addWidget( m_pIridAmountEdit, 1, 1 );
+ m_pIridThicknessLabel = new QLabel( i18n( "Thickness:" ), this );
+ m_pIridThicknessEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pIridThicknessLabel, 2, 0 );
+ layout->addWidget( m_pIridThicknessEdit, 2, 1 );
+ m_pIridTurbulenceEdit = new PMFloatEdit( this );
+ m_pIridTurbulenceLabel = new QLabel( i18n( "Turbulence:" ), this );
+ layout->addWidget( m_pIridTurbulenceLabel, 3, 0 );
+ layout->addWidget( m_pIridTurbulenceEdit, 3, 1 );
+ m_pEnableReflectionEdit = new QCheckBox( i18n( "Reflection" ), this );
+ layout->addMultiCellWidget( m_pEnableReflectionEdit, 4, 4, 0, 1 );
+ hl->addStretch( 1 );
+
+ m_pReflectionWidget = new QWidget( this );
+ QVBoxLayout* vl = new QVBoxLayout( m_pReflectionWidget, 0, KDialog::spacingHint( ) );
+ QGridLayout* gl = new QGridLayout( vl, 2, 2 );
+ m_pEnableReflectionMinEdit = new QCheckBox( i18n( "Minimum:" ),
+ m_pReflectionWidget );
+ m_pReflectionMinColorEdit = new PMColorEdit( false, m_pReflectionWidget );
+ gl->addWidget( m_pEnableReflectionMinEdit, 0, 0, AlignTop );
+ gl->addWidget( m_pReflectionMinColorEdit, 0, 1 );
+ QLabel* label = new QLabel( i18n( "Maximum:" ), m_pReflectionWidget );
+ m_pReflectionColorEdit = new PMColorEdit( false, m_pReflectionWidget );
+ gl->addWidget( label, 1, 0, AlignTop );
+ gl->addWidget( m_pReflectionColorEdit, 1, 1 );
+
+ gl = new QGridLayout( vl, 4, 2 );
+ m_pReflectionFresnelEdit = new QCheckBox( i18n( "Fresnel reflectivity" ),
+ m_pReflectionWidget );
+ gl->addMultiCellWidget( m_pReflectionFresnelEdit, 0, 0, 0, 1 );
+ m_pEnableRefFalloffEdit = new QCheckBox( i18n( "Falloff:" ),
+ m_pReflectionWidget );
+ m_pReflectionFalloffEdit = new PMFloatEdit( m_pReflectionWidget );
+ gl->addWidget( m_pEnableRefFalloffEdit, 1, 0 );
+ gl->addWidget( m_pReflectionFalloffEdit, 1, 1 );
+ m_pEnableRefExponentEdit = new QCheckBox( i18n( "Exponent:" ),
+ m_pReflectionWidget );
+ m_pReflectionExponentEdit = new PMFloatEdit( m_pReflectionWidget );
+ gl->addWidget( m_pEnableRefExponentEdit, 2, 0 );
+ gl->addWidget( m_pReflectionExponentEdit, 2, 1 );
+ m_pEnableRefMetallicEdit = new QCheckBox( i18n( "Metallic:" ),
+ m_pReflectionWidget );
+ m_pReflectionMetallicEdit = new PMFloatEdit( m_pReflectionWidget );
+ gl->addWidget( m_pEnableRefMetallicEdit, 3, 0 );
+ gl->addWidget( m_pReflectionMetallicEdit, 3, 1 );
+ vl->addStretch( 1 );
+ layout->addMultiCellWidget( m_pReflectionWidget, 5, 5, 0, 1 );
+
+
+ connect( m_pAmbientColorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDiffuseEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pBrillianceEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCrandEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pConserveEnergyEdit, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPhongEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPhongSizeEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMetallicEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSpecularEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRoughnessEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pIridAmountEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pIridThicknessEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pIridTurbulenceEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pIridEdit, SIGNAL( clicked( ) ), SLOT( slotIridClicked( ) ) );
+ connect( m_pReflectionColorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pReflectionMinColorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pReflectionFresnelEdit, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pReflectionFalloffEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pReflectionExponentEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pReflectionMetallicEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pEnableAmbientEdit, SIGNAL( clicked( ) ), SLOT( slotAmbientClicked( ) ) );
+ connect( m_pEnablePhongEdit, SIGNAL( clicked( ) ), SLOT( slotPhongClicked( ) ) );
+ connect( m_pEnablePhongSizeEdit, SIGNAL( clicked( ) ), SLOT( slotPhongSizeClicked( ) ) );
+ connect( m_pEnableDiffuseEdit, SIGNAL( clicked( ) ), SLOT( slotDiffuseClicked( ) ) );
+ connect( m_pEnableBrillianceEdit, SIGNAL( clicked( ) ), SLOT( slotBrillianceClicked( ) ) );
+ connect( m_pEnableCrandEdit, SIGNAL( clicked( ) ), SLOT( slotCrandClicked( ) ) );
+ connect( m_pEnableSpecularEdit, SIGNAL( clicked( ) ), SLOT( slotSpecularClicked( ) ) );
+ connect( m_pEnableRoughnessEdit, SIGNAL( clicked( ) ), SLOT( slotRoughnessClicked( ) ) );
+ connect( m_pEnableMetallicEdit, SIGNAL( clicked( ) ), SLOT( slotMetallicClicked( ) ) );
+ connect( m_pEnableReflectionEdit, SIGNAL( clicked( ) ), SLOT( slotReflectionClicked( ) ) );
+ connect( m_pEnableReflectionMinEdit, SIGNAL( clicked( ) ), SLOT( slotReflectionMinClicked( ) ) );
+ connect( m_pEnableRefFalloffEdit, SIGNAL( clicked( ) ), SLOT( slotRefFalloffClicked( ) ) );
+ connect( m_pEnableRefExponentEdit, SIGNAL( clicked( ) ), SLOT( slotRefExponentClicked( ) ) );
+ connect( m_pEnableRefMetallicEdit, SIGNAL( clicked( ) ), SLOT( slotRefMetallicClicked( ) ) );
+}
+
+void PMFinishEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Finish" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMFinish* ) o;
+
+ m_pAmbientColorEdit->setColor( m_pDisplayedObject->ambientColor( ) );
+ m_pAmbientColorEdit->setReadOnly( readOnly );
+ m_pDiffuseEdit->setValue( m_pDisplayedObject->diffuse( ) );
+ m_pDiffuseEdit->setReadOnly( readOnly );
+ m_pBrillianceEdit->setValue( m_pDisplayedObject->brilliance( ) );
+ m_pBrillianceEdit->setReadOnly( readOnly );
+ m_pCrandEdit->setValue( m_pDisplayedObject->crand( ) );
+ m_pCrandEdit->setReadOnly( readOnly );
+ m_pConserveEnergyEdit->setChecked( m_pDisplayedObject->conserveEnergy( ) );
+ m_pConserveEnergyEdit->setEnabled( !readOnly );
+ m_pPhongEdit->setValue( m_pDisplayedObject->phong( ) );
+ m_pPhongEdit->setReadOnly( readOnly );
+ m_pPhongSizeEdit->setValue( m_pDisplayedObject->phongSize( ) );
+ m_pPhongSizeEdit->setReadOnly( readOnly );
+ m_pMetallicEdit->setValue( m_pDisplayedObject->metallic( ) );
+ m_pMetallicEdit->setReadOnly( readOnly );
+ m_pSpecularEdit->setValue( m_pDisplayedObject->specular( ) );
+ m_pSpecularEdit->setReadOnly( readOnly );
+ m_pRoughnessEdit->setValue( m_pDisplayedObject->roughness( ) );
+ m_pRoughnessEdit->setReadOnly( readOnly );
+ m_pIridEdit->setChecked( m_pDisplayedObject->irid( ) );
+ m_pIridEdit->setEnabled( !readOnly );
+ m_pIridAmountEdit->setValue( m_pDisplayedObject->iridAmount( ) );
+ m_pIridAmountEdit->setReadOnly( readOnly );
+ m_pIridThicknessEdit->setValue( m_pDisplayedObject->iridThickness( ) );
+ m_pIridThicknessEdit->setReadOnly( readOnly );
+ m_pIridTurbulenceEdit->setValue( m_pDisplayedObject->iridTurbulence( ) );
+ m_pIridTurbulenceEdit->setReadOnly( readOnly );
+ m_pReflectionColorEdit->setColor( m_pDisplayedObject->reflectionColor( ) );
+ m_pReflectionColorEdit->setReadOnly( readOnly );
+ m_pReflectionMinColorEdit->setColor( m_pDisplayedObject->reflectionMinColor( ) );
+ m_pReflectionMinColorEdit->setReadOnly( readOnly );
+ m_pReflectionFresnelEdit->setChecked( m_pDisplayedObject->reflectionFresnel( ) );
+ m_pReflectionFresnelEdit->setEnabled( !readOnly );
+ m_pReflectionFalloffEdit->setValue( m_pDisplayedObject->reflectionFalloff( ) );
+ m_pReflectionFalloffEdit->setReadOnly( readOnly );
+ m_pReflectionExponentEdit->setValue( m_pDisplayedObject->reflectionExponent( ) );
+ m_pReflectionExponentEdit->setReadOnly( readOnly );
+ m_pReflectionMetallicEdit->setValue( m_pDisplayedObject->reflectionMetallic( ) );
+ m_pReflectionMetallicEdit->setReadOnly( readOnly );
+ m_pEnableAmbientEdit->setChecked( m_pDisplayedObject->isAmbientEnabled( ) );
+ m_pEnableAmbientEdit->setEnabled( !readOnly );
+ m_pEnablePhongEdit->setChecked( m_pDisplayedObject->isPhongEnabled( ) );
+ m_pEnablePhongEdit->setEnabled( !readOnly );
+ m_pEnablePhongSizeEdit->setChecked( m_pDisplayedObject->isPhongSizeEnabled( ) );
+ m_pEnablePhongSizeEdit->setEnabled( !readOnly );
+ m_pEnableDiffuseEdit->setChecked( m_pDisplayedObject->isDiffuseEnabled( ) );
+ m_pEnableDiffuseEdit->setEnabled( !readOnly );
+ m_pEnableBrillianceEdit->setChecked( m_pDisplayedObject->isBrillianceEnabled( ) );
+ m_pEnableBrillianceEdit->setEnabled( !readOnly );
+ m_pEnableCrandEdit->setChecked( m_pDisplayedObject->isCrandEnabled( ) );
+ m_pEnableCrandEdit->setEnabled( !readOnly );
+ m_pEnableMetallicEdit->setChecked( m_pDisplayedObject->isMetallicEnabled( ) );
+ m_pEnableMetallicEdit->setEnabled( !readOnly );
+ m_pEnableSpecularEdit->setChecked( m_pDisplayedObject->isSpecularEnabled( ) );
+ m_pEnableSpecularEdit->setEnabled( !readOnly );
+ m_pEnableRoughnessEdit->setChecked( m_pDisplayedObject->isRoughnessEnabled( ) );
+ m_pEnableRoughnessEdit->setEnabled( !readOnly );
+ m_pEnableReflectionEdit->setChecked( m_pDisplayedObject->isReflectionEnabled( ) );
+ m_pEnableReflectionEdit->setEnabled( !readOnly );
+ m_pEnableReflectionMinEdit->setChecked( m_pDisplayedObject->isReflectionMinEnabled( ) );
+ m_pEnableReflectionMinEdit->setEnabled( !readOnly );
+ m_pEnableRefFalloffEdit->setChecked( m_pDisplayedObject->isRefFalloffEnabled( ) );
+ m_pEnableRefFalloffEdit->setEnabled( !readOnly );
+ m_pEnableRefExponentEdit->setChecked( m_pDisplayedObject->isRefExponentEnabled( ) );
+ m_pEnableRefExponentEdit->setEnabled( !readOnly );
+ m_pEnableRefMetallicEdit->setChecked( m_pDisplayedObject->isRefMetallicEnabled( ) );
+ m_pEnableRefMetallicEdit->setEnabled( !readOnly );
+ slotIridClicked( );
+ slotAmbientClicked( );
+ slotPhongClicked( );
+ slotPhongSizeClicked( );
+ slotBrillianceClicked( );
+ slotDiffuseClicked( );
+ slotMetallicClicked( );
+ slotCrandClicked( );
+ slotSpecularClicked( );
+ slotRoughnessClicked( );
+ slotReflectionClicked( );
+ slotReflectionMinClicked( );
+ slotRefFalloffClicked( );
+ slotRefExponentClicked( );
+ slotRefMetallicClicked( );
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMFinishEdit: Can't display object\n";
+}
+
+void PMFinishEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setAmbientColor( m_pAmbientColorEdit->color( ) );
+ m_pDisplayedObject->setDiffuse( m_pDiffuseEdit->value( ) );
+ m_pDisplayedObject->setBrilliance( m_pBrillianceEdit->value( ) );
+ m_pDisplayedObject->setCrand( m_pCrandEdit->value( ) );
+ m_pDisplayedObject->setConserveEnergy( m_pConserveEnergyEdit->isChecked( ) );
+ m_pDisplayedObject->setPhong( m_pPhongEdit->value( ) );
+ m_pDisplayedObject->setPhongSize( m_pPhongSizeEdit->value( ) );
+ m_pDisplayedObject->setMetallic( m_pMetallicEdit->value( ) );
+ m_pDisplayedObject->setSpecular( m_pSpecularEdit->value( ) );
+ m_pDisplayedObject->setRoughness( m_pRoughnessEdit->value( ) );
+ m_pDisplayedObject->setIrid( m_pIridEdit->isChecked( ) );
+ m_pDisplayedObject->setIridAmount( m_pIridAmountEdit->value( ) );
+ m_pDisplayedObject->setIridThickness( m_pIridThicknessEdit->value( ) );
+ m_pDisplayedObject->setIridTurbulence( m_pIridTurbulenceEdit->value( ) );
+ m_pDisplayedObject->setReflectionColor( m_pReflectionColorEdit->color( ) );
+ m_pDisplayedObject->setReflectionMinColor( m_pReflectionMinColorEdit->color( ) );
+ m_pDisplayedObject->setReflectionFresnel( m_pReflectionFresnelEdit->isChecked( ) );
+ m_pDisplayedObject->setReflectionFalloff( m_pReflectionFalloffEdit->value( ) );
+ m_pDisplayedObject->setReflectionExponent( m_pReflectionExponentEdit->value( ) );
+ m_pDisplayedObject->setReflectionMetallic( m_pReflectionMetallicEdit->value( ) );
+ m_pDisplayedObject->enableAmbient( m_pEnableAmbientEdit->isChecked( ) );
+ m_pDisplayedObject->enablePhong( m_pEnablePhongEdit->isChecked( ) );
+ m_pDisplayedObject->enablePhongSize( m_pEnablePhongSizeEdit->isChecked( ) );
+ m_pDisplayedObject->enableBrilliance( m_pEnableBrillianceEdit->isChecked( ) );
+ m_pDisplayedObject->enableDiffuse( m_pEnableDiffuseEdit->isChecked( ) );
+ m_pDisplayedObject->enableCrand( m_pEnableCrandEdit->isChecked( ) );
+ m_pDisplayedObject->enableMetallic( m_pEnableMetallicEdit->isChecked( ) );
+ m_pDisplayedObject->enableRoughness( m_pEnableRoughnessEdit->isChecked( ) );
+ m_pDisplayedObject->enableSpecular( m_pEnableSpecularEdit->isChecked( ) );
+ m_pDisplayedObject->enableReflection( m_pEnableReflectionEdit->isChecked( ) );
+ m_pDisplayedObject->enableReflectionMin( m_pEnableReflectionMinEdit->isChecked( ) );
+ m_pDisplayedObject->enableRefFalloff( m_pEnableRefFalloffEdit->isChecked( ) );
+ m_pDisplayedObject->enableRefExponent( m_pEnableRefExponentEdit->isChecked( ) );
+ m_pDisplayedObject->enableRefMetallic( m_pEnableRefMetallicEdit->isChecked( ) );
+ }
+}
+
+bool PMFinishEdit::isDataValid( )
+{
+ if( !m_pDiffuseEdit->isDataValid( ) ) return false;
+ if( !m_pBrillianceEdit->isDataValid( ) ) return false;
+ if( !m_pCrandEdit->isDataValid( ) ) return false;
+ if( !m_pPhongEdit->isDataValid( ) ) return false;
+ if( !m_pPhongSizeEdit->isDataValid( ) ) return false;
+ if( !m_pMetallicEdit->isDataValid( ) ) return false;
+ if( !m_pSpecularEdit->isDataValid( ) ) return false;
+ if( !m_pRoughnessEdit->isDataValid( ) ) return false;
+ if( !m_pIridAmountEdit->isDataValid( ) ) return false;
+ if( !m_pIridThicknessEdit->isDataValid( ) ) return false;
+ if( !m_pIridTurbulenceEdit->isDataValid( ) ) return false;
+ if( !m_pReflectionFalloffEdit->isDataValid( ) ) return false;
+ if( !m_pReflectionExponentEdit->isDataValid( ) ) return false;
+ if( !m_pReflectionMetallicEdit->isDataValid( ) ) return false;
+ return Base::isDataValid( );
+}
+
+void PMFinishEdit::slotIridClicked( )
+{
+ if( m_pIridEdit->isChecked( ) )
+ {
+ m_pIridAmountLabel->show( );
+ m_pIridAmountEdit->show( );
+ m_pIridThicknessLabel->show( );
+ m_pIridThicknessEdit->show( );
+ m_pIridTurbulenceEdit->show( );
+ m_pIridTurbulenceLabel->show( );
+ }
+ else
+ {
+ m_pIridAmountLabel->hide( );
+ m_pIridAmountEdit->hide( );
+ m_pIridThicknessLabel->hide( );
+ m_pIridThicknessEdit->hide( );
+ m_pIridTurbulenceEdit->hide( );
+ m_pIridTurbulenceLabel->hide( );
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMFinishEdit::slotAmbientClicked( )
+{
+ if( m_pEnableAmbientEdit->isChecked( ) )
+ {
+ m_pAmbientColorEdit->show( );
+ m_pAmbientColorLabel->show( );
+ }
+ else
+ {
+ m_pAmbientColorEdit->hide( );
+ m_pAmbientColorLabel->hide( );
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMFinishEdit::slotPhongClicked( )
+{
+ m_pPhongEdit->setEnabled( m_pEnablePhongEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotPhongSizeClicked( )
+{
+ m_pPhongSizeEdit->setEnabled( m_pEnablePhongSizeEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotBrillianceClicked( )
+{
+ m_pBrillianceEdit->setEnabled( m_pEnableBrillianceEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotDiffuseClicked( )
+{
+ m_pDiffuseEdit->setEnabled( m_pEnableDiffuseEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotMetallicClicked( )
+{
+ m_pMetallicEdit->setEnabled( m_pEnableMetallicEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotCrandClicked( )
+{
+ m_pCrandEdit->setEnabled( m_pEnableCrandEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotSpecularClicked( )
+{
+ m_pSpecularEdit->setEnabled( m_pEnableSpecularEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotRoughnessClicked( )
+{
+ m_pRoughnessEdit->setEnabled( m_pEnableRoughnessEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotReflectionClicked( )
+{
+ if( m_pEnableReflectionEdit->isChecked( ) )
+ m_pReflectionWidget->show( );
+ else
+ m_pReflectionWidget->hide( );
+
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMFinishEdit::slotReflectionMinClicked( )
+{
+ m_pReflectionMinColorEdit->setEnabled( m_pEnableReflectionMinEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotRefFalloffClicked( )
+{
+ m_pReflectionFalloffEdit->setEnabled( m_pEnableRefFalloffEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotRefExponentClicked( )
+{
+ m_pReflectionExponentEdit->setEnabled( m_pEnableRefExponentEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMFinishEdit::slotRefMetallicClicked( )
+{
+ m_pReflectionMetallicEdit->setEnabled( m_pEnableRefMetallicEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+#include "pmfinishedit.moc"
diff --git a/kpovmodeler/pmfinishedit.h b/kpovmodeler/pmfinishedit.h
new file mode 100644
index 00000000..313b35dc
--- /dev/null
+++ b/kpovmodeler/pmfinishedit.h
@@ -0,0 +1,122 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMFINISHEDIT_H
+#define PMFINISHEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMFinish;
+class PMFloatEdit;
+class PMColorEdit;
+class QCheckBox;
+class QLabel;
+class QWidget;
+
+/**
+ * Dialog edit class for @ref PMFinish
+ */
+class PMFinishEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMFinishEdit with parent and name
+ */
+ PMFinishEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotIridClicked( );
+ void slotAmbientClicked( );
+ void slotPhongClicked( );
+ void slotPhongSizeClicked( );
+ void slotBrillianceClicked( );
+ void slotDiffuseClicked( );
+ void slotMetallicClicked( );
+ void slotCrandClicked( );
+ void slotSpecularClicked( );
+ void slotRoughnessClicked( );
+ void slotReflectionClicked( );
+ void slotReflectionMinClicked( );
+ void slotRefFalloffClicked( );
+ void slotRefExponentClicked( );
+ void slotRefMetallicClicked( );
+
+private:
+ PMFinish* m_pDisplayedObject;
+ PMColorEdit* m_pAmbientColorEdit;
+ QLabel* m_pAmbientColorLabel;
+ PMFloatEdit* m_pDiffuseEdit;
+ PMFloatEdit* m_pBrillianceEdit;
+ PMFloatEdit* m_pCrandEdit;
+ QCheckBox* m_pConserveEnergyEdit;
+ PMFloatEdit* m_pPhongEdit;
+ PMFloatEdit* m_pPhongSizeEdit;
+ PMFloatEdit* m_pMetallicEdit;
+ PMFloatEdit* m_pSpecularEdit;
+ PMFloatEdit* m_pRoughnessEdit;
+ QCheckBox* m_pIridEdit;
+ PMFloatEdit* m_pIridAmountEdit;
+ PMFloatEdit* m_pIridThicknessEdit;
+ PMFloatEdit* m_pIridTurbulenceEdit;
+ QLabel* m_pIridAmountLabel;
+ QLabel* m_pIridThicknessLabel;
+ QLabel* m_pIridTurbulenceLabel;
+ QCheckBox* m_pEnableAmbientEdit;
+ QCheckBox* m_pEnablePhongEdit;
+ QCheckBox* m_pEnablePhongSizeEdit;
+ QCheckBox* m_pEnableDiffuseEdit;
+ QCheckBox* m_pEnableBrillianceEdit;
+ QCheckBox* m_pEnableCrandEdit;
+ QCheckBox* m_pEnableSpecularEdit;
+ QCheckBox* m_pEnableRoughnessEdit;
+ QCheckBox* m_pEnableMetallicEdit;
+
+ QWidget* m_pReflectionWidget;
+ PMColorEdit* m_pReflectionColorEdit;
+ PMColorEdit* m_pReflectionMinColorEdit;
+ QCheckBox* m_pReflectionFresnelEdit;
+ PMFloatEdit* m_pReflectionFalloffEdit;
+ PMFloatEdit* m_pReflectionExponentEdit;
+ PMFloatEdit* m_pReflectionMetallicEdit;
+ QCheckBox* m_pEnableReflectionEdit;
+ QCheckBox* m_pEnableReflectionMinEdit;
+ QCheckBox* m_pEnableRefFalloffEdit;
+ QCheckBox* m_pEnableRefExponentEdit;
+ QCheckBox* m_pEnableRefMetallicEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmfog.cpp b/kpovmodeler/pmfog.cpp
new file mode 100644
index 00000000..5f2f1581
--- /dev/null
+++ b/kpovmodeler/pmfog.cpp
@@ -0,0 +1,347 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmfog.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmfogedit.h"
+#include "pmvector.h"
+
+#include <klocale.h>
+
+const int fogTypeDefault = 1;
+const double distanceDefault = 0.0;
+const PMColor colorDefault = PMColor( 0.0, 0.0, 0.0 );
+const double lambdaDefault = 2.0;
+const double fogOffsetDefault = 0.0;
+const double fogAltDefault = 0.0;
+const PMVector turbulenceDefault = PMVector( 0.0, 0.0, 0.0 );
+const int octavesDefault = 6;
+const double omegaDefault = 0.5;
+const double turbDepthDefault = 0.5;
+const PMVector upDefault = PMVector( 0.0, 1.0, 0.0 );
+
+PMDefinePropertyClass( PMFog, PMFogProperty );
+
+PMMetaObject* PMFog::s_pMetaObject = 0;
+PMObject* createNewFog( PMPart* part )
+{
+ return new PMFog( part );
+}
+
+PMFog::PMFog( PMPart* part )
+ : Base( part )
+{
+ m_fogType = fogTypeDefault;
+ m_distance = distanceDefault;
+ m_color = colorDefault;
+ m_enableTurbulence = false;
+ m_valueVector = turbulenceDefault;
+ m_octaves = octavesDefault;
+ m_omega = omegaDefault;
+ m_depth = turbDepthDefault;
+ m_fogOffset = fogOffsetDefault;
+ m_fogAlt = fogAltDefault;
+ m_up = upDefault;
+ m_lambda = 0;
+}
+
+PMFog::PMFog( const PMFog& f )
+ : Base( f )
+{
+ m_fogType = f.m_fogType;
+ m_distance = f.m_distance;
+ m_color = f.m_color;
+ m_enableTurbulence = f.m_enableTurbulence;
+ m_valueVector = f.m_valueVector;
+ m_octaves = f.m_octaves;
+ m_omega = f.m_omega;
+ m_depth = f.m_depth;
+ m_fogOffset = f.m_fogOffset;
+ m_fogAlt = f.m_fogAlt;
+ m_up = f.m_up;
+ m_lambda = f.m_lambda;
+}
+
+PMFog::~PMFog( )
+{
+}
+
+PMMetaObject* PMFog::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Fog", Base::metaObject( ),
+ createNewFog );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "fogType", &PMFog::setFogType, &PMFog::fogType ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "distance", &PMFog::setDistance, &PMFog::distance ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "color", &PMFog::setColor, &PMFog::color ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "turbulenceEnabled", &PMFog::enableTurbulence, &PMFog::isTurbulenceEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "turbulence", &PMFog::setValueVector, &PMFog::valueVector ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "octaves", &PMFog::setOctaves, &PMFog::octaves ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "omega", &PMFog::setOmega, &PMFog::omega ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "lambda", &PMFog::setLambda, &PMFog::lambda ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "depth", &PMFog::setDepth, &PMFog::depth ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "offset", &PMFog::setFogOffset, &PMFog::fogOffset ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "altitude", &PMFog::setFogAlt, &PMFog::fogAlt ) );
+ s_pMetaObject->addProperty(
+ new PMFogProperty( "up", &PMFog::setUp, &PMFog::up ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMFog::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMFog::description( ) const
+{
+ return i18n( "fog" );
+}
+
+void PMFog::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ Base::serialize( e, doc );
+ e.setAttribute( "fog_type", m_fogType );
+ e.setAttribute( "distance", m_distance );
+ e.setAttribute( "color", m_color.serializeXML( ) );
+ e.setAttribute( "enable_turbulence", m_enableTurbulence );
+ e.setAttribute( "value_vector", m_valueVector.serializeXML( ) );
+ e.setAttribute( "octaves", m_octaves );
+ e.setAttribute( "omega", m_omega );
+ e.setAttribute( "lambda", m_lambda );
+ e.setAttribute( "depth", m_depth );
+ e.setAttribute( "fog_offset", m_fogOffset );
+ e.setAttribute( "fog_alt", m_fogAlt );
+ e.setAttribute( "up", m_up.serializeXML( ) );
+}
+
+void PMFog::readAttributes( const PMXMLHelper& h )
+{
+ Base::readAttributes( h );
+ m_fogType = h.intAttribute( "fog_type", fogTypeDefault );
+ m_distance = h.doubleAttribute( "distance", distanceDefault );
+ m_color = h.colorAttribute( "color", colorDefault );
+ m_enableTurbulence = h.boolAttribute( "enable_turbulence", false );
+ m_valueVector = h.vectorAttribute( "value_vector", turbulenceDefault );
+ m_octaves = h.intAttribute( "octaves", octavesDefault );
+ m_omega = h.doubleAttribute( "omega", omegaDefault );
+ m_lambda = h.doubleAttribute( "lambda", lambdaDefault );
+ m_depth = h.doubleAttribute( "depth", turbDepthDefault );
+ m_fogOffset = h.doubleAttribute( "fog_offset", fogOffsetDefault );
+ m_fogAlt = h.doubleAttribute( "fog_alt", fogAltDefault );
+ m_up = h.vectorAttribute( "up", upDefault );
+}
+
+void PMFog::setFogType( int c )
+{
+ if( c != m_fogType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFogTypeID, m_fogType );
+ m_fogType = c;
+ }
+}
+
+void PMFog::setDistance( double c )
+{
+ if( c != m_distance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDistanceID, m_distance );
+ m_distance = c;
+ }
+}
+
+void PMFog::setColor( const PMColor& c )
+{
+ if( c != m_color )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMColorID, m_color );
+ m_color = c;
+ }
+}
+
+void PMFog::enableTurbulence( bool c )
+{
+ if( c != m_enableTurbulence )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableTurbulenceID, m_enableTurbulence );
+ m_enableTurbulence = c;
+ }
+}
+
+void PMFog::setValueVector( const PMVector& c )
+{
+ if( c != m_valueVector )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMValueVectorID, m_valueVector );
+ m_valueVector = c;
+ }
+}
+
+void PMFog::setOctaves( int c )
+{
+ if( c != m_octaves )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOctavesID, m_octaves );
+ m_octaves = c;
+ }
+}
+
+void PMFog::setOmega( double c )
+{
+ if( c != m_omega )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOmegaID, m_omega );
+ m_omega = c;
+ }
+}
+
+void PMFog::setLambda( double c )
+{
+ if( c != m_lambda )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLambdaID, m_lambda );
+ m_lambda = c;
+ }
+}
+
+void PMFog::setDepth( double c )
+{
+ if( c != m_depth )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDepthID, m_depth );
+ m_depth = c;
+ }
+}
+
+void PMFog::setFogOffset( double c )
+{
+ if( c != m_fogOffset )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFogOffsetID, m_fogOffset );
+ m_fogOffset = c;
+ }
+}
+
+void PMFog::setFogAlt( double c )
+{
+ if( c != m_fogAlt )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFogAltID, m_fogAlt );
+ m_fogAlt = c;
+ }
+}
+
+void PMFog::setUp( const PMVector& c )
+{
+ if( c != m_up )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUpID, m_up );
+ m_up = c;
+ }
+}
+
+PMDialogEditBase* PMFog::editWidget( QWidget* parent ) const
+{
+ return new PMFogEdit( parent );
+}
+
+void PMFog::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMFogTypeID:
+ setFogType( data->intData( ) );
+ break;
+ case PMDistanceID:
+ setDistance( data->doubleData( ) );
+ break;
+ case PMColorID:
+ setColor( data->colorData( ) );
+ break;
+ case PMEnableTurbulenceID:
+ enableTurbulence( data->boolData( ) );
+ break;
+ case PMValueVectorID:
+ setValueVector( data->vectorData( ) );
+ break;
+ case PMOctavesID:
+ setOctaves( data->intData( ) );
+ break;
+ case PMOmegaID:
+ setOmega( data->doubleData( ) );
+ break;
+ case PMLambdaID:
+ setLambda( data->doubleData( ) );
+ break;
+ case PMDepthID:
+ setDepth( data->doubleData( ) );
+ break;
+ case PMFogOffsetID:
+ setFogOffset( data->doubleData( ) );
+ break;
+ case PMFogAltID:
+ setFogAlt( data->doubleData( ) );
+ break;
+ case PMUpID:
+ setUp( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMFog::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmfog.h b/kpovmodeler/pmfog.h
new file mode 100644
index 00000000..444fa54a
--- /dev/null
+++ b/kpovmodeler/pmfog.h
@@ -0,0 +1,129 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMFOG_H
+#define PMFOG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+#include "pmcolor.h"
+#include "pmvector.h"
+
+/**
+ * Class for povray fogs
+ */
+class PMFog : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMFog
+ */
+ PMFog( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMFog( const PMFog& f );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMFog( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMFog( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMFogEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmfog" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ int fogType( ) const { return m_fogType; }
+ double distance( ) const { return m_distance; }
+ PMColor color( ) const { return m_color; }
+ bool isTurbulenceEnabled( ) const { return m_enableTurbulence; }
+ PMVector valueVector( ) const { return m_valueVector; }
+ int octaves( ) const { return m_octaves; }
+ double omega( ) const { return m_omega; }
+ double lambda( ) const { return m_lambda; }
+ double depth( ) const { return m_depth; }
+ double fogOffset( ) const { return m_fogOffset; }
+ double fogAlt( ) const { return m_fogAlt; }
+ PMVector up( ) const { return m_up; }
+
+ void setFogType( int c );
+ void setDistance( double c );
+ void setColor( const PMColor& c );
+ void enableTurbulence( bool c );
+ void setValueVector( const PMVector& v );
+ void setOctaves( int c );
+ void setOmega( double c );
+ void setLambda( double c );
+ void setDepth( double c );
+ void setFogOffset( double c );
+ void setFogAlt( double c );
+ void setUp( const PMVector& v );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMFogMementoID { PMFogTypeID, PMDistanceID, PMColorID,
+ PMEnableTurbulenceID, PMValueVectorID,
+ PMOctavesID, PMOmegaID, PMLambdaID,
+ PMDepthID, PMFogOffsetID, PMFogAltID,
+ PMUpID };
+
+ int m_fogType;
+ double m_distance;
+ PMColor m_color;
+ bool m_enableTurbulence;
+ PMVector m_valueVector;
+ int m_octaves;
+ double m_omega;
+ double m_lambda;
+ double m_depth;
+ double m_fogOffset;
+ double m_fogAlt;
+ PMVector m_up;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmfogedit.cpp b/kpovmodeler/pmfogedit.cpp
new file mode 100644
index 00000000..64cb915e
--- /dev/null
+++ b/kpovmodeler/pmfogedit.cpp
@@ -0,0 +1,240 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmfogedit.h"
+#include "pmfog.h"
+#include "pmlineedits.h"
+#include "pmvectoredit.h"
+#include "pmcoloredit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+
+PMFogEdit::PMFogEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMFogEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+ QVBoxLayout* vl;
+ QGridLayout* gl;
+ QLabel* lbl;
+
+ Base::createTopWidgets( );
+
+ lbl = new QLabel( i18n( "Fog type:" ), this );
+ m_pFogTypeEdit = new QComboBox( this );
+ m_pFogTypeEdit->insertItem( i18n( "Constant" ) );
+ m_pFogTypeEdit->insertItem( i18n( "Ground" ) );
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pFogTypeEdit );
+ hl->addStretch( 1 );
+
+ lbl = new QLabel( i18n( "Distance:" ), this );
+ m_pDistance = new PMFloatEdit( this );
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pDistance );
+ hl->addStretch( 1 );
+
+ lbl = new QLabel( i18n( "Color:" ), this );
+ m_pColor = new PMColorEdit( false, this );
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pColor );
+ hl->addStretch( 1 );
+
+ m_pTurbulenceCheck = new QCheckBox( i18n( "Turbulence" ), this );
+ topLayout( )->addWidget( m_pTurbulenceCheck );
+
+ m_pTurbulenceWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pTurbulenceWidget, 0, KDialog::spacingHint( ) );
+ hl = new QHBoxLayout( vl );
+ lbl = new QLabel( i18n( "Value: " ), m_pTurbulenceWidget );
+ m_pTurbulenceVector = new PMVectorEdit( "x", "y", "z", m_pTurbulenceWidget);
+ hl->addWidget( lbl );
+ hl->addWidget( m_pTurbulenceVector );
+ hl->addStretch( 1 );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 4, 2 );
+ lbl = new QLabel( i18n( "Octaves:" ), m_pTurbulenceWidget );
+ m_pOctaves = new PMIntEdit( m_pTurbulenceWidget );
+ gl->addWidget( lbl, 0, 0 );
+ gl->addWidget( m_pOctaves, 0, 1 );
+ lbl = new QLabel( i18n( "Omega:" ), m_pTurbulenceWidget );
+ m_pOmega = new PMFloatEdit( m_pTurbulenceWidget );
+ gl->addWidget( lbl, 1, 0 );
+ gl->addWidget( m_pOmega, 1, 1 );
+ lbl = new QLabel( i18n( "Lambda:" ), m_pTurbulenceWidget );
+ m_pLambda = new PMFloatEdit( m_pTurbulenceWidget );
+ gl->addWidget( lbl, 2, 0 );
+ gl->addWidget( m_pLambda, 2, 1 );
+ lbl = new QLabel( i18n( "Depth:" ), m_pTurbulenceWidget );
+ m_pDepth = new PMFloatEdit( m_pTurbulenceWidget );
+ gl->addWidget( lbl, 3, 0 );
+ gl->addWidget( m_pDepth, 3, 1 );
+ hl->addStretch( 1 );
+ topLayout( )->addWidget( m_pTurbulenceWidget );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 2, 2 );
+ m_pFogOffsetLabel = new QLabel( i18n( "Offset: " ), this );
+ m_pFogOffset = new PMFloatEdit( this );
+ m_pFogAltLabel = new QLabel( i18n( "Altitude: " ), this );
+ m_pFogAlt = new PMFloatEdit( this );
+ gl->addWidget( m_pFogOffsetLabel, 0, 0 );
+ gl->addWidget( m_pFogOffset, 0, 1 );
+ gl->addWidget( m_pFogAltLabel, 1, 0 );
+ gl->addWidget( m_pFogAlt, 1, 1 );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pUpLabel = new QLabel( i18n( "Up: " ), this );
+ m_pUp = new PMVectorEdit( "x", "y", "z", this );
+ hl->addWidget( m_pUpLabel );
+ hl->addWidget( m_pUp );
+
+ connect( m_pFogTypeEdit, SIGNAL( activated( int ) ), SLOT( slotFogTypeChanged( int ) ) );
+ connect( m_pDistance, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pColor, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pTurbulenceCheck, SIGNAL( clicked( ) ), SLOT( slotTurbulenceClicked( ) ) );
+ connect( m_pTurbulenceVector, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOctaves, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOmega, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pLambda, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDepth, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFogOffset, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFogAlt, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pUp, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMFogEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Fog" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMFog* ) o;
+
+ m_pFogTypeEdit->setCurrentItem( m_pDisplayedObject->fogType( ) - 1 );
+ m_pFogTypeEdit->setEnabled( !readOnly );
+ m_pDistance->setValue( m_pDisplayedObject->distance( ) );
+ m_pDistance->setReadOnly( readOnly );
+ m_pColor->setColor( m_pDisplayedObject->color( ) );
+ m_pColor->setReadOnly( readOnly );
+ m_pTurbulenceCheck->setChecked( m_pDisplayedObject->isTurbulenceEnabled( ) );
+ m_pTurbulenceCheck->setEnabled( !readOnly );
+ m_pTurbulenceVector->setVector( m_pDisplayedObject->valueVector( ) );
+ m_pTurbulenceVector->setReadOnly( readOnly );
+ m_pOctaves->setValue( m_pDisplayedObject->octaves( ) );
+ m_pOctaves->setReadOnly( readOnly );
+ m_pOmega->setValue( m_pDisplayedObject->omega( ) );
+ m_pOmega->setReadOnly( readOnly );
+ m_pLambda->setValue( m_pDisplayedObject->lambda( ) );
+ m_pLambda->setReadOnly( readOnly );
+ m_pDepth->setValue( m_pDisplayedObject->depth( ) );
+ m_pDepth->setReadOnly( readOnly );
+ m_pFogOffset->setValue( m_pDisplayedObject->fogOffset( ) );
+ m_pFogOffset->setReadOnly( readOnly );
+ m_pFogAlt->setValue( m_pDisplayedObject->fogAlt( ) );
+ m_pFogAlt->setReadOnly( readOnly );
+ m_pUp->setVector( m_pDisplayedObject->up( ) );
+ m_pUp->setReadOnly( readOnly );
+
+ slotTurbulenceClicked( );
+ slotFogTypeChanged( m_pFogTypeEdit->currentItem( ) );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMFogEdit: Can't display object\n";
+}
+
+void PMFogEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ m_pDisplayedObject->setFogType( m_pFogTypeEdit->currentItem( ) + 1 );
+ m_pDisplayedObject->setDistance( m_pDistance->value( ) );
+ m_pDisplayedObject->setColor( m_pColor->color( ) );
+ m_pDisplayedObject->enableTurbulence( m_pTurbulenceCheck->isChecked( ) );
+ m_pDisplayedObject->setValueVector( m_pTurbulenceVector->vector( ) );
+ m_pDisplayedObject->setOctaves( m_pOctaves->value( ) );
+ m_pDisplayedObject->setOmega( m_pOmega->value( ) );
+ m_pDisplayedObject->setLambda( m_pLambda->value( ) );
+ m_pDisplayedObject->setDepth( m_pDepth->value( ) );
+ m_pDisplayedObject->setFogOffset( m_pFogOffset->value( ) );
+ m_pDisplayedObject->setFogAlt( m_pFogAlt->value( ) );
+ m_pDisplayedObject->setUp( m_pUp->vector( ) );
+ Base::saveContents( );
+ }
+}
+
+bool PMFogEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+void PMFogEdit::slotTurbulenceClicked( )
+{
+ if( m_pTurbulenceCheck->isChecked( ) )
+ m_pTurbulenceWidget->show( );
+ else
+ m_pTurbulenceWidget->hide( );
+
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMFogEdit::slotFogTypeChanged( int val )
+{
+ switch( val )
+ {
+ case 0: // Constant Fog
+ m_pFogOffsetLabel->hide( );
+ m_pFogOffset->hide( );
+ m_pFogAltLabel->hide( );
+ m_pFogAlt->hide( );
+ m_pUpLabel->hide( );
+ m_pUp->hide( );
+ break;
+ case 1: // Ground Fog
+ m_pFogOffsetLabel->show( );
+ m_pFogOffset->show( );
+ m_pFogAltLabel->show( );
+ m_pFogAlt->show( );
+ m_pUpLabel->show( );
+ m_pUp->show( );
+ break;
+ default:
+ break;
+ }
+
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+#include "pmfogedit.moc"
diff --git a/kpovmodeler/pmfogedit.h b/kpovmodeler/pmfogedit.h
new file mode 100644
index 00000000..880b578c
--- /dev/null
+++ b/kpovmodeler/pmfogedit.h
@@ -0,0 +1,95 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMFOGEDIT_H
+#define PMFOGEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMFog;
+class PMVectorEdit;
+class PMFloatEdit;
+class PMIntEdit;
+class PMColorEdit;
+class QCheckBox;
+class QComboBox;
+class QWidget;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMFog
+ */
+class PMFogEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMFogEdit with parent and name
+ */
+ PMFogEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * Slot called whenever turbulence is activated/deactivated
+ */
+ void slotTurbulenceClicked( );
+ /**
+ * Slot called whenever a new fog type is selected
+ */
+ void slotFogTypeChanged( int val );
+
+private:
+ PMFog* m_pDisplayedObject;
+
+ QComboBox* m_pFogTypeEdit;
+ PMFloatEdit* m_pDistance;
+ PMColorEdit* m_pColor;
+ QCheckBox* m_pTurbulenceCheck;
+ QWidget* m_pTurbulenceWidget;
+ PMVectorEdit* m_pTurbulenceVector;
+ PMIntEdit* m_pOctaves;
+ PMFloatEdit* m_pOmega;
+ PMFloatEdit* m_pLambda;
+ PMFloatEdit* m_pDepth;
+ QLabel* m_pFogOffsetLabel;
+ PMFloatEdit* m_pFogOffset;
+ QLabel* m_pFogAltLabel;
+ PMFloatEdit* m_pFogAlt;
+ QLabel* m_pUpLabel;
+ PMVectorEdit* m_pUp;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmformulalabel.cpp b/kpovmodeler/pmformulalabel.cpp
new file mode 100644
index 00000000..ac2e98d3
--- /dev/null
+++ b/kpovmodeler/pmformulalabel.cpp
@@ -0,0 +1,190 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmformulalabel.h"
+#include "pmpolynomexponents.h"
+
+#include <qapplication.h>
+#include <qsimplerichtext.h>
+#include <qpainter.h>
+
+const int c_indent = 3;
+const int c_dotSize = 3;
+
+QString PMFormulaLabel::s_xyz[3] =
+{
+ QString( "x" ), QString( "y" ), QString( "z" )
+};
+
+QString PMFormulaLabel::s_digit[10] =
+{
+ QString( "0" ),
+ QString( "1" ),
+ QString( "2" ),
+ QString( "3" ),
+ QString( "4" ),
+ QString( "5" ),
+ QString( "6" ),
+ QString( "7" ),
+ QString( "8" ),
+ QString( "9" )
+};
+
+QString PMFormulaLabel::s_nullString = QString( "= 0" );
+
+PMFormulaLabel::PMFormulaLabel( const PMPolynomExponents& exp, QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ m_exponents[0] = exp.exponent( 0 );
+ m_exponents[1] = exp.exponent( 1 );
+ m_exponents[2] = exp.exponent( 2 );
+
+ calculateSizeHint( );
+}
+
+PMFormulaLabel::PMFormulaLabel( int x, int y, int z, QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ m_exponents[0] = x;
+ m_exponents[1] = y;
+ m_exponents[2] = z;
+
+ calculateSizeHint( );
+}
+
+PMFormulaLabel::~PMFormulaLabel( )
+{
+}
+
+void PMFormulaLabel::drawContents( QPainter* p )
+{
+ QRect cr = rect( );
+ int i;
+ cr.setLeft( cr.left( ) + c_indent );
+
+ int sum = m_exponents[0] + m_exponents[1] + m_exponents[2];
+ if( sum == 0 )
+ p->drawText( cr, Qt::AlignVCenter | Qt::AlignLeft, s_nullString );
+ else
+ {
+ // draw dot
+ int center = ( cr.top( ) + cr.bottom( ) ) / 2;
+ int rad = c_dotSize / 2;
+ p->setBrush( QBrush( colorGroup( ).text( ) ) );
+ p->drawEllipse( cr.left( ), center - rad, c_dotSize, c_dotSize );
+ cr.setLeft( cr.left( ) + c_dotSize + c_indent );
+
+ QFontMetrics m1( font( ) );
+ QFont f2 = exponentFont( );
+ QFontMetrics m2( f2 );
+ int up = m1.height( ) / 2;
+
+ for( i = 0; i < 3; i++ )
+ {
+
+ if( m_exponents[i] > 0 )
+ {
+ p->drawText( cr, Qt::AlignVCenter | Qt::AlignLeft, s_xyz[i] );
+ cr.setLeft( cr.left( ) + m1.width( s_xyz[i] ) );
+ if( m_exponents[i] > 1 )
+ {
+ cr.setBottom( cr.bottom( ) - up );
+ p->setFont( f2 );
+ p->drawText( cr, Qt::AlignVCenter | Qt::AlignLeft,
+ s_digit[m_exponents[i]] );
+ cr.setLeft( cr.left( ) + m2.width( s_digit[m_exponents[i]] ) + 1 );
+ cr.setBottom( cr.bottom( ) + up );
+ p->setFont( font( ) );
+ }
+ }
+ }
+ }
+}
+
+void PMFormulaLabel::paintEvent( QPaintEvent* ev )
+{
+ QPainter paint( this );
+ if( ev->rect( ).intersects( rect( ) ) )
+ {
+ paint.setClipRegion( ev->region( ).intersect( rect( ) ) );
+ drawContents( &paint );
+ }
+}
+
+void PMFormulaLabel::calculateSizeHint( )
+{
+ int sum = m_exponents[0] + m_exponents[1] + m_exponents[2];
+
+ QFontMetrics m1( font( ) );
+ if( sum == 0 )
+ m_sizeHint.setWidth( m1.width( s_nullString ) );
+ else
+ {
+ QFontMetrics m2( exponentFont( ) );
+ int width = c_indent * 3 + c_dotSize;
+ int i;
+ for( i = 0; i < 3; i++ )
+ {
+ if( m_exponents[i] > 0 )
+ {
+ width += m1.width( s_xyz[i] );
+ if( m_exponents[i] > 1 )
+ width += m2.width( s_digit[m_exponents[i]] ) + 1;
+ }
+ }
+ m_sizeHint.setWidth( width );
+ }
+ m_sizeHint.setHeight( m1.height( ) + 7 );
+}
+
+QSize PMFormulaLabel::sizeHint( ) const
+{
+ return minimumSizeHint( );
+}
+
+QSize PMFormulaLabel::minimumSizeHint( ) const
+{
+ return m_sizeHint;
+}
+
+void PMFormulaLabel::fontChange( const QFont& )
+{
+ calculateSizeHint( );
+}
+
+
+QFont PMFormulaLabel::exponentFont( ) const
+{
+ QFont small = font( );
+ int fs = small.pointSize( );
+ if( fs > 0 )
+ {
+ fs = fs * 2 / 3;
+ if( fs == 0 )
+ fs = 1;
+ small.setPointSize( fs );
+ }
+ else
+ {
+ fs = small.pixelSize( );
+ fs = fs * 2 / 3;
+ if( fs == 0 )
+ fs = 1;
+ small.setPixelSize( fs );
+ }
+ return small;
+}
diff --git a/kpovmodeler/pmformulalabel.h b/kpovmodeler/pmformulalabel.h
new file mode 100644
index 00000000..329ba639
--- /dev/null
+++ b/kpovmodeler/pmformulalabel.h
@@ -0,0 +1,69 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMFORMULALABEL_H
+#define PMFORMULALABEL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+
+class PMPolynomExponents;
+
+/**
+ * QLabel with a rich text to display a polynom for the quadric,
+ * cubic, quartic and polynom objects.
+ */
+class PMFormulaLabel : public QWidget
+{
+public:
+ /**
+ * Displays the exponents of the @ref PMPolynomExponents
+ */
+ PMFormulaLabel( const PMPolynomExponents& exp, QWidget* parent, const char* name = 0 );
+ /**
+ * Displays the given exponents
+ */
+ PMFormulaLabel( int x, int y, int z, QWidget* parent, const char* name = 0 );
+ /**
+ * Destructor
+ */
+ ~PMFormulaLabel( );
+ virtual QSize sizeHint( ) const;
+ virtual QSize minimumSizeHint( ) const;
+
+protected:
+ virtual void drawContents( QPainter* p );
+ virtual void paintEvent( QPaintEvent* e );
+ virtual void fontChange( const QFont& oldFont );
+
+private:
+ QFont exponentFont( ) const;
+ void calculateSizeHint( );
+
+ QSize m_sizeHint;
+ int m_exponents[3];
+
+ static QString s_xyz[3];
+ static QString s_digit[10];
+ static QString s_nullString;
+};
+
+#endif
diff --git a/kpovmodeler/pmglobalphotons.cpp b/kpovmodeler/pmglobalphotons.cpp
new file mode 100644
index 00000000..4a24855f
--- /dev/null
+++ b/kpovmodeler/pmglobalphotons.cpp
@@ -0,0 +1,521 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmglobalphotons.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmenumproperty.h"
+#include "pmglobalphotonsedit.h"
+
+#include <klocale.h>
+
+const double spacingDefault = 0.01;
+const int countDefault = 20000;
+const int gatherMinDefault = 20;
+const int gatherMaxDefault = 100;
+const int mediaMaxStepsDefault = 0;
+const double mediaFactorDefault = 1.0;
+const double jitterDefault = 0.4;
+const int maxTraceLevelDefault = 0;
+const double adcBailoutDefault = 0.01;
+const double autostopDefault = 0.0;
+const double expandIncreaseDefault = 0.2;
+const int expandMinDefault = 40;
+const double radiusGatherDefault = 0.0;
+const double radiusGatherMultiDefault = 1.0;
+const double radiusMediaDefault = 0.0;
+const double radiusMediaMultiDefault = 1.0;
+
+PMDefinePropertyClass( PMGlobalPhotons, PMGlobalPhotonsProperty );
+PMDefineEnumPropertyClass( PMGlobalPhotons, PMGlobalPhotons::PMNumberType, PMNumberProperty );
+
+PMMetaObject* PMGlobalPhotons::s_pMetaObject = 0;
+PMObject* createNewGlobalPhotons( PMPart* part )
+{
+ return new PMGlobalPhotons( part );
+}
+
+PMGlobalPhotons::PMGlobalPhotons( PMPart* part ) : Base( part )
+{
+ m_numberType = Spacing;
+ m_spacing = spacingDefault;
+ m_count = countDefault;
+ m_gatherMin = gatherMinDefault;
+ m_gatherMax = gatherMaxDefault;
+ m_mediaMaxSteps = mediaMaxStepsDefault;
+ m_mediaFactor = mediaFactorDefault;
+ m_jitter = jitterDefault;
+ m_maxTraceLevelGlobal = true;
+ m_maxTraceLevel = maxTraceLevelDefault;
+ m_adcBailoutGlobal = true;
+ m_adcBailout = adcBailoutDefault;
+ m_autostop = autostopDefault;
+ m_expandIncrease = expandIncreaseDefault;
+ m_expandMin = expandMinDefault;
+ m_radiusGather = radiusGatherDefault;
+ m_radiusGatherMulti = radiusGatherMultiDefault;
+ m_radiusMedia = radiusMediaDefault;
+ m_radiusMediaMulti = radiusMediaMultiDefault;
+}
+
+PMGlobalPhotons::PMGlobalPhotons( const PMGlobalPhotons& p )
+ : Base( p )
+{
+ m_numberType = p.m_numberType;
+ m_spacing = p.m_spacing;
+ m_count = p.m_count;
+ m_gatherMin = p.m_gatherMin;
+ m_gatherMax = p.m_gatherMax;
+ m_mediaMaxSteps = p.m_mediaMaxSteps;
+ m_mediaFactor = p.m_mediaFactor;
+ m_jitter = p.m_jitter;
+ m_maxTraceLevelGlobal = p.m_maxTraceLevelGlobal;
+ m_maxTraceLevel = p.m_maxTraceLevel;
+ m_adcBailoutGlobal = p.m_adcBailoutGlobal;
+ m_adcBailout = p.m_adcBailout;
+ m_autostop = p.m_autostop;
+ m_expandIncrease = p.m_expandIncrease;
+ m_expandMin = p.m_expandMin;
+ m_radiusGather = p.m_radiusGather;
+ m_radiusGatherMulti = p.m_radiusGatherMulti;
+ m_radiusMedia = p.m_radiusMedia;
+ m_radiusMediaMulti = p.m_radiusMediaMulti;
+}
+
+PMGlobalPhotons::~PMGlobalPhotons( )
+{
+}
+
+PMMetaObject* PMGlobalPhotons::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "GlobalPhotons", Base::metaObject( ),
+ createNewGlobalPhotons );
+
+ PMNumberProperty* p1 = new PMNumberProperty( "numberType",
+ &PMGlobalPhotons::setNumberType, &PMGlobalPhotons::numberType );
+ p1->addEnumValue( "Spacing", Spacing );
+ p1->addEnumValue( "Count", Count );
+ s_pMetaObject->addProperty( p1 );
+
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "spacing",
+ &PMGlobalPhotons::setSpacing, &PMGlobalPhotons::spacing ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "count",
+ &PMGlobalPhotons::setCount, &PMGlobalPhotons::count ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "gatherMin",
+ &PMGlobalPhotons::setGatherMin, &PMGlobalPhotons::gatherMin ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "gatherMax",
+ &PMGlobalPhotons::setGatherMax, &PMGlobalPhotons::gatherMax ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "mediaMaxSteps",
+ &PMGlobalPhotons::setMediaMaxSteps, &PMGlobalPhotons::mediaMaxSteps ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "mediaFactor",
+ &PMGlobalPhotons::setMediaFactor, &PMGlobalPhotons::mediaFactor ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "jitter",
+ &PMGlobalPhotons::setJitter, &PMGlobalPhotons::jitter ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "maxTraceLevelGlobal",
+ &PMGlobalPhotons::setMaxTraceLevelGlobal, &PMGlobalPhotons::maxTraceLevelGlobal ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "maxTraceLevel",
+ &PMGlobalPhotons::setMaxTraceLevel, &PMGlobalPhotons::maxTraceLevel ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "adcBailoutGlobal",
+ &PMGlobalPhotons::setAdcBailoutGlobal, &PMGlobalPhotons::adcBailoutGlobal ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "adcBailout",
+ &PMGlobalPhotons::setAdcBailout, &PMGlobalPhotons::adcBailout ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "autostop",
+ &PMGlobalPhotons::setAutostop, &PMGlobalPhotons::autostop ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "expandIncrease",
+ &PMGlobalPhotons::setExpandIncrease, &PMGlobalPhotons::expandIncrease ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "expandMin",
+ &PMGlobalPhotons::setExpandMin, &PMGlobalPhotons::expandMin ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "radiusGather",
+ &PMGlobalPhotons::setRadiusGather, &PMGlobalPhotons::radiusGather ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "radiusGatherMulti",
+ &PMGlobalPhotons::setRadiusGatherMulti, &PMGlobalPhotons::radiusGatherMulti ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "radiusMedia",
+ &PMGlobalPhotons::setRadiusMedia, &PMGlobalPhotons::radiusMedia ) );
+ s_pMetaObject->addProperty( new PMGlobalPhotonsProperty( "radiusMediaMulti",
+ &PMGlobalPhotons::setRadiusMediaMulti, &PMGlobalPhotons::radiusMediaMulti ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMGlobalPhotons::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMGlobalPhotons::description( ) const
+{
+ return i18n( "global photons" );
+}
+
+void PMGlobalPhotons::serialize( QDomElement& e, QDomDocument& ) const
+{
+ if( m_numberType == Spacing )
+ {
+ e.setAttribute( "number_type", "spacing" );
+ e.setAttribute( "spacing", m_spacing );
+ }
+ else
+ {
+ e.setAttribute( "number_type", "count" );
+ e.setAttribute( "count", m_count );
+ }
+
+ e.setAttribute( "gather_min", m_gatherMin );
+ e.setAttribute( "gather_max", m_gatherMax );
+ e.setAttribute( "media_max_steps", m_mediaMaxSteps );
+ e.setAttribute( "media_factor", m_mediaFactor );
+ e.setAttribute( "jitter", m_jitter );
+ e.setAttribute( "max_trace_level_global", m_maxTraceLevelGlobal );
+ e.setAttribute( "max_trace_level", m_maxTraceLevel );
+ e.setAttribute( "adc_bailout_global", m_adcBailoutGlobal );
+ e.setAttribute( "adc_bailout", m_adcBailout );
+ e.setAttribute( "autostop", m_autostop );
+ e.setAttribute( "expand_increase", m_expandIncrease );
+ e.setAttribute( "expand_min", m_expandMin );
+ e.setAttribute( "radius_gather", m_radiusGather );
+ e.setAttribute( "radius_gather_multi", m_radiusGatherMulti );
+ e.setAttribute( "radius_media", m_radiusMedia );
+ e.setAttribute( "radius_media_multi", m_radiusMediaMulti );
+}
+
+void PMGlobalPhotons::readAttributes( const PMXMLHelper& h )
+{
+ QString str;
+
+ str = h.stringAttribute( "number_type", "spacing" );
+ if( str == "count" )
+ m_numberType = Count;
+ else
+ m_numberType = Spacing;
+
+ m_spacing = h.doubleAttribute( "spacing", spacingDefault );
+ m_count = h.intAttribute( "count", countDefault );
+ m_gatherMin = h.intAttribute( "gather_min", gatherMinDefault );
+ m_gatherMax = h.intAttribute( "gather_max", gatherMaxDefault );
+ m_mediaMaxSteps = h.intAttribute( "media_max_steps", mediaMaxStepsDefault );
+ m_mediaFactor = h.doubleAttribute( "media_factor", mediaFactorDefault );
+ m_jitter = h.doubleAttribute( "jitter", jitterDefault );
+ m_maxTraceLevelGlobal = h.boolAttribute( "max_trace_level_global", true );
+ m_maxTraceLevel = h.intAttribute( "max_trace_level", maxTraceLevelDefault );
+ m_adcBailoutGlobal = h.boolAttribute( "adc_bailout_global", true );
+ m_adcBailout = h.doubleAttribute( "adc_bailout", adcBailoutDefault );
+ m_autostop = h.doubleAttribute( "autostop", autostopDefault );
+ m_expandIncrease = h.doubleAttribute( "expand_increase", expandIncreaseDefault );
+ m_expandMin = h.intAttribute( "expand_min", expandMinDefault );
+ m_radiusGather = h.doubleAttribute( "radius_gather", radiusGatherDefault );
+ m_radiusGatherMulti = h.doubleAttribute( "radius_gather_multi",
+ radiusGatherMultiDefault );
+
+ m_radiusMedia = h.doubleAttribute( "radius_media", radiusMediaDefault );
+ m_radiusMediaMulti = h.doubleAttribute( "radius_media_multi",
+ radiusMediaMultiDefault );
+}
+
+void PMGlobalPhotons::setNumberType( PMNumberType nt )
+{
+ if( nt != m_numberType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNumberTypeID, m_numberType );
+ m_numberType = nt;
+ }
+}
+
+void PMGlobalPhotons::setSpacing( double s )
+{
+ if( s != m_spacing )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSpacingID, m_spacing );
+ m_spacing = s;
+ }
+}
+
+void PMGlobalPhotons::setCount( int c )
+{
+ if( c != m_count )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCountID, m_count );
+ m_count = c;
+ }
+}
+
+void PMGlobalPhotons::setGatherMin( int gm )
+{
+ if( gm > m_gatherMax )
+ {
+ kdError( PMArea ) << "Gather Minimum > Gather Maximum in PMGlobalPhotons::setGatherMin\n";
+ gm = m_gatherMax;
+ }
+
+ if( gm != m_gatherMin )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMGatherMinID, m_gatherMin );
+ m_gatherMin = gm;
+ }
+}
+
+void PMGlobalPhotons::setGatherMax( int gm )
+{
+ if( gm < m_gatherMin )
+ {
+ kdError( PMArea ) << "Gather Maximum < Gather Minimum in PMGlobalPhotons::setGatherMax\n";
+ gm = m_gatherMin;
+ }
+
+ if( gm != m_gatherMax )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMGatherMaxID, m_gatherMax );
+ m_gatherMax = gm;
+ }
+}
+
+void PMGlobalPhotons::setMediaMaxSteps( int mms )
+{
+ if( mms != m_mediaMaxSteps )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMediaMaxStepsID, m_mediaMaxSteps );
+ m_mediaMaxSteps = mms;
+ }
+}
+
+void PMGlobalPhotons::setMediaFactor( double mf )
+{
+ if( mf != m_mediaFactor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMediaFactorID, m_mediaFactor );
+ m_mediaFactor = mf;
+ }
+}
+
+void PMGlobalPhotons::setJitter( double j )
+{
+ if( j != m_jitter )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMJitterID, m_jitter );
+ m_jitter = j;
+ }
+}
+
+void PMGlobalPhotons::setMaxTraceLevelGlobal( bool mtlg )
+{
+ if( mtlg != m_maxTraceLevelGlobal )
+ {
+ if( m_pMemento )
+ m_pMemento->addData(
+ s_pMetaObject, PMMaxTraceLevelGlobalID, m_maxTraceLevelGlobal );
+ m_maxTraceLevelGlobal = mtlg;
+ }
+}
+
+void PMGlobalPhotons::setMaxTraceLevel( int mtl )
+{
+ if( mtl != m_maxTraceLevel )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMaxTraceLevelID, m_maxTraceLevel );
+ m_maxTraceLevel = mtl;
+ }
+}
+
+void PMGlobalPhotons::setAdcBailoutGlobal( bool abg )
+{
+ if( abg != m_adcBailoutGlobal )
+ {
+ if( m_pMemento )
+ m_pMemento->addData(
+ s_pMetaObject, PMAdcBailoutGlobalID, m_adcBailoutGlobal );
+ m_adcBailoutGlobal = abg;
+ }
+}
+
+void PMGlobalPhotons::setAdcBailout( double ab )
+{
+ if( ab != m_adcBailout )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAdcBailoutID, m_adcBailout );
+ m_adcBailout = ab;
+ }
+}
+
+void PMGlobalPhotons::setAutostop( double a )
+{
+ if( a != m_autostop )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAutostopID, m_autostop );
+ m_autostop = a;
+ }
+}
+
+void PMGlobalPhotons::setExpandIncrease( double ei )
+{
+ if( ei != m_expandIncrease )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMExpandIncreaseID, m_expandIncrease );
+ m_expandIncrease = ei;
+ }
+}
+
+void PMGlobalPhotons::setExpandMin( int em )
+{
+ if(em != m_expandMin )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMExpandMinID, m_expandMin );
+ m_expandMin = em;
+ }
+}
+
+void PMGlobalPhotons::setRadiusGather( double rg )
+{
+ if ( rg != m_radiusGather )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusGatherID, m_radiusGather );
+ m_radiusGather = rg;
+ }
+}
+
+void PMGlobalPhotons::setRadiusGatherMulti( double rgm )
+{
+ if ( rgm != m_radiusGatherMulti )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusGatherID, m_radiusGatherMulti );
+ m_radiusGatherMulti = rgm;
+ }
+}
+
+void PMGlobalPhotons::setRadiusMedia( double rm )
+{
+ if ( rm != m_radiusMedia )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusGatherID, m_radiusMedia );
+ m_radiusMedia = rm;
+ }
+}
+
+void PMGlobalPhotons::setRadiusMediaMulti( double rmm )
+{
+ if ( rmm != m_radiusMediaMulti )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusGatherID, m_radiusMediaMulti );
+ m_radiusMediaMulti = rmm;
+ }
+}
+
+PMDialogEditBase* PMGlobalPhotons::editWidget( QWidget* parent ) const
+{
+ return new PMGlobalPhotonsEdit( parent );
+}
+
+void PMGlobalPhotons::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMNumberTypeID:
+ setNumberType( ( PMNumberType ) ( data->intData( ) ) );
+ break;
+ case PMSpacingID:
+ setSpacing( data->doubleData( ) );
+ break;
+ case PMCountID:
+ setCount( data->intData( ) );
+ break;
+ case PMGatherMinID:
+ setGatherMin( data->intData( ) );
+ break;
+ case PMGatherMaxID:
+ setGatherMax( data->intData( ) );
+ break;
+ case PMMediaMaxStepsID:
+ setMediaMaxSteps( data->intData( ) );
+ break;
+ case PMMediaFactorID:
+ setMediaFactor( data->doubleData( ) );
+ break;
+ case PMJitterID:
+ setJitter( data->doubleData( ) );
+ break;
+ case PMMaxTraceLevelGlobalID:
+ setMaxTraceLevelGlobal( data->boolData( ) );
+ break;
+ case PMMaxTraceLevelID:
+ setMaxTraceLevel( data->intData( ) );
+ break;
+ case PMAdcBailoutGlobalID:
+ setAdcBailoutGlobal( data->boolData( ) );
+ break;
+ case PMAdcBailoutID:
+ setAdcBailout( data->doubleData( ) );
+ break;
+ case PMAutostopID:
+ setAutostop( data->doubleData( ) );
+ break;
+ case PMExpandIncreaseID:
+ setExpandIncrease( data->doubleData( ) );
+ break;
+ case PMExpandMinID:
+ setExpandMin( data->intData( ) );
+ break;
+ case PMRadiusGatherID:
+ setRadiusGather( data->doubleData( ) );
+ break;
+ case PMRadiusGatherMultiID:
+ setRadiusGatherMulti( data->doubleData( ) );
+ break;
+ case PMRadiusMediaID:
+ setRadiusMedia( data->doubleData( ) );
+ break;
+ case PMRadiusMediaMultiID:
+ setRadiusMediaMulti( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMRadiosity::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmglobalphotons.h b/kpovmodeler/pmglobalphotons.h
new file mode 100644
index 00000000..b56cc6b1
--- /dev/null
+++ b/kpovmodeler/pmglobalphotons.h
@@ -0,0 +1,284 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMGLOBALPHOTONS_H
+#define PMGLOBALPHOTONS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+/**
+ * Class for GlobalPhotons settings.
+ */
+
+class PMGlobalPhotons : public PMObject
+{
+ typedef PMObject Base;
+public:
+ enum PMNumberType { Spacing=0, Count=1 };
+
+ /**
+ * Creates a PMGlobalPhotons
+ */
+ PMGlobalPhotons( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMGlobalPhotons( const PMGlobalPhotons& p );
+ /**
+ * deletes the PMGlobalPhotons
+ */
+ virtual ~PMGlobalPhotons( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMGlobalPhotons( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMGlobalPhotonsEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmglobalphotons" ); }
+
+ /**
+ * Returns the number type
+ */
+ PMNumberType numberType( ) const { return m_numberType; }
+ /**
+ * Sets the number type
+ */
+ void setNumberType( PMNumberType nt );
+
+ /**
+ * Returns the photons spacing value
+ */
+ double spacing( ) const { return m_spacing; }
+ /**
+ * Sets the photons spacing value
+ */
+ void setSpacing( double s );
+
+ /**
+ * Returns the number of photons to shoot
+ */
+ int count( ) const { return m_count; }
+ /**
+ * Sets the number of photons to shoot
+ */
+ void setCount( int c );
+
+ /**
+ * Returns the minimum gather
+ */
+ int gatherMin( ) const { return m_gatherMin; }
+ /**
+ * Sets the minimum gather
+ */
+ void setGatherMin( int gm );
+
+ /**
+ * Returns the maximum gather
+ */
+ int gatherMax( ) const { return m_gatherMax; }
+ /**
+ * Sets the maximum gather
+ */
+ void setGatherMax( int gm );
+
+ /**
+ * Returns the media maximum steps
+ */
+ int mediaMaxSteps( ) const { return m_mediaMaxSteps; }
+ /**
+ * Sets the media maximum steps
+ */
+ void setMediaMaxSteps( int mms );
+
+ /**
+ * Returns the media factor
+ */
+ double mediaFactor( ) const { return m_mediaFactor; }
+ /**
+ * Sets the media factor
+ */
+ void setMediaFactor( double mf );
+
+ /**
+ * Returns jitter amount
+ */
+ double jitter( ) const { return m_jitter; }
+ /**
+ * Sets the jitter amount
+ */
+ void setJitter( double j );
+
+ /**
+ * Returns the maximum trace level global flag
+ */
+ bool maxTraceLevelGlobal( ) const { return m_maxTraceLevelGlobal; }
+ /**
+ * Sets the maximum trace level global flag
+ */
+ void setMaxTraceLevelGlobal( bool mtlg );
+
+ /**
+ * Returns the maximum trace level
+ */
+ int maxTraceLevel( ) const { return m_maxTraceLevel; }
+ /**
+ * Sets the maximum trace level
+ */
+ void setMaxTraceLevel( int mtl );
+
+ /**
+ * Returns the adc bailout global flag
+ */
+ bool adcBailoutGlobal( ) const { return m_adcBailoutGlobal; }
+ /**
+ * Sets the adc bailout global flag
+ */
+ void setAdcBailoutGlobal( bool abg );
+
+ /**
+ * Returns the adc bailout
+ */
+ double adcBailout( ) const { return m_adcBailout; }
+ /**
+ * Sets the adc bailout
+ */
+ void setAdcBailout( double ab );
+
+ /**
+ * Returns the autostop fraction
+ */
+ double autostop( ) const { return m_autostop; }
+ /**
+ * Sets the autostop fraction
+ */
+ void setAutostop( double a );
+
+ /**
+ * Returns the expand threshold percent increase
+ */
+ double expandIncrease( ) const { return m_expandIncrease; }
+ /**
+ * Sets the expand threshold percent increase
+ */
+ void setExpandIncrease( double ei );
+
+ /**
+ * Returns the expand threshold minimum
+ */
+ int expandMin( ) const { return m_expandMin; }
+ /**
+ * Sets the expand threshold minimum
+ */
+ void setExpandMin( int em );
+
+ /**
+ * Retuens the gather radius
+ */
+ double radiusGather( ) const { return m_radiusGather; }
+ /**
+ * Sets the gather radius
+ */
+ void setRadiusGather( double rg );
+
+ /**
+ * Returns the gather radius multiplier
+ */
+ double radiusGatherMulti( ) const { return m_radiusGatherMulti; }
+ /**
+ * Sets the radius gather multiplier
+ */
+ void setRadiusGatherMulti( double rgm );
+
+ /**
+ * Returns the media gather radius
+ */
+ double radiusMedia( ) const { return m_radiusMedia; }
+ /**
+ * Sets the media gather radius
+ */
+ void setRadiusMedia( double rm );
+
+ /**
+ * Returns the media gather radius multiplier
+ */
+ double radiusMediaMulti( ) const { return m_radiusMediaMulti; }
+ /**
+ * Sets the media gather radius multiplier
+ */
+ void setRadiusMediaMulti( double rmm );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMGlobalPhotonsMementoID
+ { PMNumberTypeID, PMSpacingID, PMCountID, PMGatherMinID, PMGatherMaxID,
+ PMMediaMaxStepsID, PMMediaFactorID, PMJitterID, PMMaxTraceLevelGlobalID,
+ PMMaxTraceLevelID, PMAdcBailoutGlobalID, PMAdcBailoutID, PMAutostopID,
+ PMExpandIncreaseID, PMExpandMinID, PMRadiusGatherID, PMRadiusGatherMultiID,
+ PMRadiusMediaID, PMRadiusMediaMultiID };
+
+ PMNumberType m_numberType;
+ double m_spacing;
+ int m_count;
+ int m_gatherMin;
+ int m_gatherMax;
+ int m_mediaMaxSteps;
+ double m_mediaFactor;
+ double m_jitter;
+ bool m_maxTraceLevelGlobal;
+ int m_maxTraceLevel;
+ bool m_adcBailoutGlobal;
+ double m_adcBailout;
+ double m_autostop;
+ double m_expandIncrease;
+ int m_expandMin;
+ double m_radiusGather;
+ double m_radiusGatherMulti;
+ double m_radiusMedia;
+ double m_radiusMediaMulti;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmglobalphotonsedit.cpp b/kpovmodeler/pmglobalphotonsedit.cpp
new file mode 100644
index 00000000..e241f597
--- /dev/null
+++ b/kpovmodeler/pmglobalphotonsedit.cpp
@@ -0,0 +1,328 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmglobalphotonsedit.h"
+#include "pmglobalphotons.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+
+
+PMGlobalPhotonsEdit::PMGlobalPhotonsEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMGlobalPhotonsEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+ QGridLayout* gl;
+ QLabel* lbl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Photon numbers" ), this );
+ m_pNumberType = new QComboBox( false, this );
+ m_pNumberType->insertItem( i18n( "Spacing" ) );
+ m_pNumberType->insertItem( i18n( "Count" ) );
+ m_pSpacing = new PMFloatEdit( this );
+ m_pSpacing->setValidation( true, 0, false, 0 );
+ m_pCount = new PMIntEdit( this );
+ m_pCount->setValidation( true, 0, false, 0 );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pNumberType );
+ hl->addWidget( m_pSpacing );
+ hl->addWidget( m_pCount );
+ hl->addStretch( 1 );
+
+ gl = new QGridLayout( topLayout( ), 2, 5 );
+ lbl = new QLabel( i18n( "Gather" ), this );
+ gl->addWidget( lbl, 0, 0 );
+ lbl = new QLabel( i18n( "Min:" ), this );
+ gl->addWidget( lbl, 0, 1 );
+ m_pGatherMin = new PMIntEdit( this );
+ m_pGatherMin->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pGatherMin, 0, 2 );
+ lbl = new QLabel( i18n( "Max:" ), this );
+ gl->addWidget( lbl, 0, 3 );
+ m_pGatherMax = new PMIntEdit( this );
+ m_pGatherMax->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pGatherMax, 0, 4 );
+
+ lbl = new QLabel( i18n( "Media" ), this );
+ gl->addWidget( lbl, 1, 0 );
+ lbl = new QLabel( i18n( "Max stop:" ), this );
+ gl->addWidget( lbl, 1, 1 );
+ m_pMediaMaxSteps = new PMIntEdit( this );
+ m_pMediaMaxSteps->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pMediaMaxSteps, 1, 2 );
+ lbl = new QLabel( i18n( "Factor:" ), this );
+ gl->addWidget( lbl,1, 3 );
+ m_pMediaFactor = new PMFloatEdit( this );
+ m_pMediaFactor->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pMediaFactor, 1, 4 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Jitter:" ), this );
+ m_pJitter = new PMFloatEdit( this );
+ m_pJitter->setValidation ( true, 0, false, 0 );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pJitter );
+ hl->addStretch( 1 );
+
+ gl = new QGridLayout( topLayout( ), 2, 3 );
+ lbl = new QLabel( i18n( "Max trace level:" ), this );
+ m_pMaxTraceLevel = new PMIntEdit ( this );
+ m_pMaxTraceLevel->setValidation( true, 0, false, 0 );
+ m_pMaxTraceLevelGlobal = new QCheckBox( i18n( "Use global" ), this );
+ gl->addWidget( lbl, 0, 0 );
+ gl->addWidget( m_pMaxTraceLevel, 0, 1 );
+ gl->addWidget( m_pMaxTraceLevelGlobal, 0, 2 );
+
+ lbl = new QLabel( i18n( "Adc bailout:" ), this );
+ m_pAdcBailout = new PMFloatEdit ( this );
+ m_pAdcBailout->setValidation( true, 0, true, 1 );
+ m_pAdcBailoutGlobal = new QCheckBox( i18n( "Use global" ), this );
+ gl->addWidget( lbl, 1, 0 );
+ gl->addWidget( m_pAdcBailout, 1, 1 );
+ gl->addWidget( m_pAdcBailoutGlobal, 1, 2 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Autostop:" ), this );
+ m_pAutostop = new PMFloatEdit ( this );
+ m_pAutostop->setValidation( true, 0, true, 1 );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pAutostop );
+ hl->addStretch( 1 );
+
+ gl = new QGridLayout( topLayout( ), 3, 5 );
+ lbl = new QLabel( i18n( "Expand" ), this );
+ gl->addWidget( lbl, 0, 0 );
+ lbl = new QLabel( i18n( "Increase:" ), this );
+ gl->addWidget( lbl, 0, 1 );
+ m_pExpandIncrease = new PMFloatEdit( this );
+ m_pExpandIncrease->setValidation( true, 0, true, 1 );
+ gl->addWidget( m_pExpandIncrease, 0, 2 );
+ lbl = new QLabel( i18n( "Minimum:" ), this );
+ gl->addWidget( lbl, 0, 3 );
+ m_pExpandMin = new PMIntEdit( this );
+ m_pExpandMin->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pExpandMin, 0, 4 );
+
+ lbl = new QLabel( i18n( "Gather" ), this );
+ gl->addWidget( lbl, 1, 0 );
+ lbl = new QLabel( i18n( "Radius:" ), this );
+ gl->addWidget( lbl, 1, 1 );
+ m_pRadiusGather = new PMFloatEdit( this );
+ m_pRadiusGather->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pRadiusGather, 1, 2 );
+ lbl = new QLabel( i18n( "Multiplier:" ), this );
+ gl->addWidget( lbl, 1, 3 );
+ m_pRadiusGatherMulti = new PMFloatEdit( this );
+ m_pRadiusGatherMulti->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pRadiusGatherMulti, 1, 4 );
+
+ lbl = new QLabel( i18n( "Media" ), this );
+ gl->addWidget( lbl, 2, 0 );
+ lbl = new QLabel( i18n( "Radius:" ), this );
+ gl->addWidget( lbl, 2, 1 );
+ m_pRadiusMedia = new PMFloatEdit( this );
+ m_pRadiusMedia->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pRadiusMedia, 2, 2 );
+ lbl = new QLabel( i18n( "Multiplier:" ), this );
+ gl->addWidget( lbl, 2, 3 );
+ m_pRadiusMediaMulti = new PMFloatEdit( this );
+ m_pRadiusMediaMulti->setValidation( true, 0, false, 0 );
+ gl->addWidget( m_pRadiusMediaMulti, 2, 4 );
+
+ connect( m_pNumberType, SIGNAL( activated( int ) ),
+ SLOT( slotNumberTypeActivated( int ) ) );
+ connect( m_pSpacing, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCount, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pGatherMin, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pGatherMax, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMediaMaxSteps, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMediaFactor, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pJitter, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMaxTraceLevelGlobal, SIGNAL( clicked( ) ),
+ SLOT( slotMaxTraceLevelGlobalClicked( ) ) );
+ connect( m_pMaxTraceLevel, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAdcBailoutGlobal, SIGNAL( clicked( ) ),
+ SLOT( slotAdcBailoutGlobalClicked( ) ) );
+ connect( m_pAdcBailout, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAutostop, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pExpandIncrease, SIGNAL( dataChanged( ) ), SIGNAL ( dataChanged( ) ) );
+ connect( m_pExpandMin, SIGNAL( dataChanged( ) ), SIGNAL ( dataChanged( ) ) );
+ connect( m_pRadiusGather, SIGNAL( dataChanged( ) ), SIGNAL ( dataChanged( ) ) );
+ connect( m_pRadiusGatherMulti, SIGNAL( dataChanged( ) ), SIGNAL ( dataChanged( ) ) );
+ connect( m_pRadiusMedia, SIGNAL( dataChanged( ) ), SIGNAL ( dataChanged( ) ) );
+ connect( m_pRadiusMediaMulti, SIGNAL( dataChanged( ) ), SIGNAL ( dataChanged( ) ) );
+}
+
+void PMGlobalPhotonsEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "GlobalPhotons" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMGlobalPhotons* ) o;
+
+ m_pNumberType->setCurrentItem( m_pDisplayedObject->numberType( ) );
+ m_pNumberType->setEnabled( !readOnly );
+ m_pSpacing->setValue( m_pDisplayedObject->spacing( ) );
+ m_pSpacing->setReadOnly( readOnly );
+ m_pCount->setValue( m_pDisplayedObject->count( ) );
+ m_pCount->setReadOnly( readOnly );
+ m_pGatherMin->setValue( m_pDisplayedObject->gatherMin( ) );
+ m_pGatherMin->setReadOnly( readOnly );
+ m_pGatherMax->setValue( m_pDisplayedObject->gatherMax( ) );
+ m_pGatherMax->setReadOnly( readOnly );
+ m_pMediaMaxSteps->setValue( m_pDisplayedObject->mediaMaxSteps( ) );
+ m_pMediaMaxSteps->setReadOnly( readOnly );
+ m_pMediaFactor->setValue( m_pDisplayedObject->mediaFactor( ) );
+ m_pMediaFactor->setReadOnly( readOnly );
+ m_pJitter->setValue( m_pDisplayedObject->jitter( ) );
+ m_pJitter->setReadOnly( readOnly );
+ m_pMaxTraceLevelGlobal->setChecked( m_pDisplayedObject->maxTraceLevelGlobal( ) );
+ m_pMaxTraceLevelGlobal->setEnabled( !readOnly );
+ m_pMaxTraceLevel->setValue( m_pDisplayedObject->maxTraceLevel( ) );
+ m_pMaxTraceLevel->setReadOnly( readOnly );
+ m_pAdcBailoutGlobal->setChecked( m_pDisplayedObject->adcBailoutGlobal( ) );
+ m_pAdcBailoutGlobal->setEnabled( !readOnly );
+ m_pAdcBailout->setValue( m_pDisplayedObject->adcBailout( ) );
+ m_pAdcBailout->setReadOnly( readOnly );
+ m_pAutostop->setValue( m_pDisplayedObject->autostop( ) );
+ m_pAutostop->setReadOnly( readOnly );
+ m_pExpandIncrease->setValue( m_pDisplayedObject->expandIncrease( ) );
+ m_pExpandIncrease->setReadOnly( readOnly );
+ m_pExpandMin->setValue( m_pDisplayedObject->expandMin( ) );
+ m_pExpandMin->setReadOnly( readOnly );
+ m_pRadiusGather->setValue( m_pDisplayedObject->radiusGather( ) );
+ m_pRadiusGather->setReadOnly( readOnly );
+ m_pRadiusGatherMulti->setValue( m_pDisplayedObject->radiusGatherMulti( ) );
+ m_pRadiusGatherMulti->setReadOnly( readOnly );
+ m_pRadiusMedia->setValue( m_pDisplayedObject->radiusMedia( ) );
+ m_pRadiusMedia->setReadOnly( readOnly );
+ m_pRadiusMediaMulti->setValue( m_pDisplayedObject->radiusMediaMulti( ) );
+ m_pRadiusMediaMulti->setReadOnly( readOnly );
+
+ slotNumberTypeActivated( m_pDisplayedObject->numberType( ) );
+ slotMaxTraceLevelGlobalClicked( );
+ slotAdcBailoutGlobalClicked( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMGlobalPhotonsEdit: Can't display object\n";
+}
+
+void PMGlobalPhotonsEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setNumberType(
+ ( PMGlobalPhotons::PMNumberType ) m_pNumberType->currentItem( ) );
+ m_pDisplayedObject->setSpacing( m_pSpacing->value( ) );
+ m_pDisplayedObject->setCount( m_pCount->value( ) );
+ m_pDisplayedObject->setGatherMin( m_pGatherMin->value( ) );
+ m_pDisplayedObject->setGatherMax( m_pGatherMax->value( ) );
+ m_pDisplayedObject->setMediaMaxSteps( m_pMediaMaxSteps->value( ) );
+ m_pDisplayedObject->setMediaFactor( m_pMediaFactor->value( ) );
+ m_pDisplayedObject->setJitter( m_pJitter->value( ) );
+ m_pDisplayedObject->setMaxTraceLevelGlobal(
+ m_pMaxTraceLevelGlobal->isChecked( ) );
+ m_pDisplayedObject->setMaxTraceLevel( m_pMaxTraceLevel->value( ) );
+ m_pDisplayedObject->setAdcBailoutGlobal(
+ m_pAdcBailoutGlobal->isChecked( ) );
+ m_pDisplayedObject->setAdcBailout( m_pAdcBailout->value( ) );
+ m_pDisplayedObject->setAutostop( m_pAutostop->value( ) );
+ m_pDisplayedObject->setExpandIncrease( m_pExpandIncrease->value( ) );
+ m_pDisplayedObject->setExpandMin( m_pExpandMin->value( ) );
+ m_pDisplayedObject->setRadiusGather( m_pRadiusGather->value( ) );
+ m_pDisplayedObject->setRadiusGatherMulti( m_pRadiusGatherMulti->value( ) );
+ m_pDisplayedObject->setRadiusMedia( m_pRadiusMedia->value( ) );
+ m_pDisplayedObject->setRadiusMediaMulti( m_pRadiusMediaMulti->value( ) );
+ }
+}
+
+bool PMGlobalPhotonsEdit::isDataValid( )
+{
+ if( !m_pSpacing->isDataValid( ) ) return false;
+ if( !m_pCount->isDataValid( ) ) return false;
+ if( !m_pGatherMin->isDataValid( ) ) return false;
+ if( !m_pGatherMax->isDataValid( ) ) return false;
+ if( !m_pMediaMaxSteps->isDataValid( ) ) return false;
+ if( !m_pMediaFactor->isDataValid( ) ) return false;
+ if( !m_pJitter->isDataValid( ) ) return false;
+ if( !m_pMaxTraceLevel->isDataValid( ) ) return false;
+ if( !m_pAdcBailout->isDataValid( ) ) return false;
+ if( !m_pAutostop->isDataValid( ) ) return false;
+ if( !m_pExpandIncrease->isDataValid( ) ) return false;
+ if( !m_pExpandMin->isDataValid( ) ) return false;
+ if( !m_pRadiusGather->isDataValid( ) ) return false;
+ if( !m_pRadiusGatherMulti->isDataValid( ) ) return false;
+ if( !m_pRadiusMedia->isDataValid( ) ) return false;
+ if( !m_pRadiusMediaMulti->isDataValid( ) ) return false;
+
+ return Base::isDataValid( );
+}
+
+void PMGlobalPhotonsEdit::slotNumberTypeActivated( int index )
+{
+ if( index == 0 )
+ {
+ m_pSpacing->show( );
+ m_pCount->hide( );
+ }
+ else
+ {
+ m_pSpacing->hide( );
+ m_pCount->show( );
+ }
+ emit dataChanged( );
+}
+
+void PMGlobalPhotonsEdit::slotMaxTraceLevelGlobalClicked( )
+{
+ if( m_pMaxTraceLevelGlobal->isChecked( ) )
+ m_pMaxTraceLevel->setEnabled( false );
+ else if ( m_pMaxTraceLevelGlobal->isEnabled( ) )
+ m_pMaxTraceLevel->setEnabled( true );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMGlobalPhotonsEdit::slotAdcBailoutGlobalClicked( )
+{
+ if( m_pAdcBailoutGlobal->isChecked( ) )
+ m_pAdcBailout->setEnabled( false );
+ else if ( m_pAdcBailoutGlobal->isEnabled( ) )
+ m_pAdcBailout->setEnabled( true );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+#include "pmglobalphotonsedit.moc"
diff --git a/kpovmodeler/pmglobalphotonsedit.h b/kpovmodeler/pmglobalphotonsedit.h
new file mode 100644
index 00000000..ec06f749
--- /dev/null
+++ b/kpovmodeler/pmglobalphotonsedit.h
@@ -0,0 +1,98 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMGLOBALPHOTONSEDIT_H
+#define PMGLOBALPHOTONSEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMGlobalPhotons;
+class PMFloatEdit;
+class PMIntEdit;
+class QComboBox;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMGlobalPhotons.
+ */
+class PMGlobalPhotonsEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMGlobalPhotonsEdit with parent and name
+ */
+ PMGlobalPhotonsEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * Slot Called whenever NumberType is altered
+ */
+ void slotNumberTypeActivated( int index );
+ /**
+ * slot Called whenever MaxTraceLevelGlobal is Clicked
+ */
+ void slotMaxTraceLevelGlobalClicked( );
+ /**
+ * slot Called whenever AdcBailoutGlobal is Clicked
+ */
+ void slotAdcBailoutGlobalClicked( );
+
+private:
+ PMGlobalPhotons* m_pDisplayedObject;
+
+ QComboBox* m_pNumberType;
+ PMFloatEdit* m_pSpacing;
+ PMIntEdit* m_pCount;
+ PMIntEdit* m_pGatherMin;
+ PMIntEdit* m_pGatherMax;
+ PMIntEdit* m_pMediaMaxSteps;
+ PMFloatEdit* m_pMediaFactor;
+ PMFloatEdit* m_pJitter;
+ QCheckBox* m_pMaxTraceLevelGlobal;
+ PMIntEdit* m_pMaxTraceLevel;
+ QCheckBox* m_pAdcBailoutGlobal;
+ PMFloatEdit* m_pAdcBailout;
+ PMFloatEdit* m_pAutostop;
+ PMFloatEdit* m_pExpandIncrease;
+ PMIntEdit* m_pExpandMin;
+ PMFloatEdit* m_pRadiusGather;
+ PMFloatEdit* m_pRadiusGatherMulti;
+ PMFloatEdit* m_pRadiusMedia;
+ PMFloatEdit* m_pRadiusMediaMulti;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmglobals.h b/kpovmodeler/pmglobals.h
new file mode 100644
index 00000000..0a50b2b6
--- /dev/null
+++ b/kpovmodeler/pmglobals.h
@@ -0,0 +1,29 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMGLOBALS_H
+#define PMGLOBALS_H
+
+#ifdef PMEnableSimpleProfiling
+#include <qdatetime.h>
+extern QTime PMDebugTime;
+#endif
+
+#define PMArea 0 // no area for debug messages yet
+
+
+#endif
diff --git a/kpovmodeler/pmglobalsettings.cpp b/kpovmodeler/pmglobalsettings.cpp
new file mode 100644
index 00000000..a4740378
--- /dev/null
+++ b/kpovmodeler/pmglobalsettings.cpp
@@ -0,0 +1,516 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmglobalsettings.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmglobalsettingsedit.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+const double adcBailoutDefault = 1.0 / 255.0;
+const PMColor ambientLightDefault = PMColor( 1.0, 1.0, 1.0, 0.0, 0.0 );
+const double assumedGammaDefault = 0.0;
+const bool hfGray16Default = false;
+const PMColor iridWaveLengthDefault = PMColor( 0.25, 0.18, 0.14, 0.0, 0.0 );
+const int maxIntersectionsDefault = 0; // ???
+const int maxTraceLevelDefault = 0; // ???
+const int numberWavesDefault = 10;
+const bool radiosityDefault = false;
+const double brightnessDefault = 1.0;
+const int countDefault = 35;
+const double distanceMaximumDefault = 0; // ???
+const double errorBoundDefault = 1.8;
+const double grayThresholdDefault = 0.0;
+const double lowErrorFactorDefault = 0.5;
+const double minimumReuseDefault = 0.015;
+const int nearestCountDefault = 5;
+const int recursionLimitDefault = 2;
+
+PMDefinePropertyClass( PMGlobalSettings, PMGlobalSettingsProperty );
+PMDefineEnumPropertyClass( PMGlobalSettings, PMGlobalSettings::PMNoiseType, PMNoiseProperty );
+
+PMMetaObject* PMGlobalSettings::s_pMetaObject = 0;
+PMObject* createNewGlobalSettings( PMPart* part )
+{
+ return new PMGlobalSettings( part );
+}
+
+PMGlobalSettings::PMGlobalSettings( PMPart* part )
+ : Base( part )
+{
+ m_adcBailout = adcBailoutDefault;
+ m_ambientLight = ambientLightDefault;
+ m_assumedGamma = assumedGammaDefault;
+ m_hfGray16 = hfGray16Default;
+ m_iridWaveLength = iridWaveLengthDefault;
+ m_maxIntersections = maxIntersectionsDefault;
+ m_maxTraceLevel = maxTraceLevelDefault;
+ m_numberWaves = numberWavesDefault;
+ m_noiseGenerator = RangeCorrected;
+ m_radiosityEnabled = radiosityDefault;
+ m_brightness = brightnessDefault;
+ m_count = countDefault;
+ m_distanceMaximum = distanceMaximumDefault;
+ m_errorBound = errorBoundDefault;
+ m_grayThreshold = grayThresholdDefault;
+ m_lowErrorFactor = lowErrorFactorDefault;
+ m_minimumReuse = minimumReuseDefault;
+ m_nearestCount = nearestCountDefault;
+ m_recursionLimit = recursionLimitDefault;
+}
+
+PMGlobalSettings::PMGlobalSettings( const PMGlobalSettings& s )
+ : Base( s )
+{
+ m_adcBailout = s.m_adcBailout;
+ m_ambientLight = s.m_ambientLight;
+ m_assumedGamma = s.m_assumedGamma;
+ m_hfGray16 = s.m_hfGray16;
+ m_iridWaveLength = s.m_iridWaveLength;
+ m_maxIntersections = s.m_maxIntersections;
+ m_maxTraceLevel = s.m_maxTraceLevel;
+ m_numberWaves = s.m_numberWaves;
+ m_noiseGenerator = s.m_noiseGenerator;
+ m_radiosityEnabled = s.m_radiosityEnabled;
+ m_brightness = s.m_brightness;
+ m_count = s.m_count;
+ m_distanceMaximum = s.m_distanceMaximum;
+ m_errorBound = s.m_errorBound;
+ m_grayThreshold = s.m_grayThreshold;
+ m_lowErrorFactor = s.m_lowErrorFactor;
+ m_minimumReuse = s.m_minimumReuse;
+ m_nearestCount = s.m_nearestCount;
+ m_recursionLimit = s.m_recursionLimit;
+}
+
+PMGlobalSettings::~PMGlobalSettings( )
+{
+}
+
+PMMetaObject* PMGlobalSettings::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "GlobalSettings", Base::metaObject( ),
+ createNewGlobalSettings );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "adcBailout", &PMGlobalSettings::setAdcBailout, &PMGlobalSettings::adcBailout ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "ambientLight", &PMGlobalSettings::setAmbientLight, &PMGlobalSettings::ambientLight ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "assumedGamma", &PMGlobalSettings::setAssumedGamma, &PMGlobalSettings::assumedGamma ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "hfGray16", &PMGlobalSettings::setHfGray16, &PMGlobalSettings::hfGray16 ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "iridWaveLength", &PMGlobalSettings::setIridWaveLength, &PMGlobalSettings::iridWaveLength ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "maxIntersections", &PMGlobalSettings::setMaxIntersections, &PMGlobalSettings::maxIntersections ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "maxTraceLevel", &PMGlobalSettings::setMaxTraceLevel, &PMGlobalSettings::maxTraceLevel ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "numberWaves", &PMGlobalSettings::setNumberWaves, &PMGlobalSettings::numberWaves ) );
+
+ PMNoiseProperty* p = new PMNoiseProperty( "noiseGenerator", &PMGlobalSettings::setNoiseGenerator,
+ &PMGlobalSettings::noiseGenerator );
+ p->addEnumValue( "Original", Original );
+ p->addEnumValue( "RangeCorrected", RangeCorrected );
+ p->addEnumValue( "Perlin", Perlin );
+ s_pMetaObject->addProperty( p );
+
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "radiosity", &PMGlobalSettings::enableRadiosity, &PMGlobalSettings::isRadiosityEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "brightness", &PMGlobalSettings::setBrightness, &PMGlobalSettings::brightness ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "count", &PMGlobalSettings::setCount, &PMGlobalSettings::count ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "distanceMaximum", &PMGlobalSettings::setDistanceMaximum, &PMGlobalSettings::distanceMaximum ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "errorBound", &PMGlobalSettings::setErrorBound, &PMGlobalSettings::errorBound ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "grayThreshold", &PMGlobalSettings::setGrayThreshold, &PMGlobalSettings::grayThreshold ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "lowErrorFactor", &PMGlobalSettings::setLowErrorFactor, &PMGlobalSettings::lowErrorFactor ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "minimumReuse", &PMGlobalSettings::setMinimumReuse, &PMGlobalSettings::minimumReuse ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "nearestCount", &PMGlobalSettings::setNearestCount, &PMGlobalSettings::nearestCount ) );
+ s_pMetaObject->addProperty(
+ new PMGlobalSettingsProperty( "recursionLimit", &PMGlobalSettings::setRecursionLimit, &PMGlobalSettings::recursionLimit ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMGlobalSettings::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMGlobalSettings::description( ) const
+{
+ return i18n( "global settings" );
+}
+
+void PMGlobalSettings::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "adc_bailout", m_adcBailout );
+ e.setAttribute( "ambient_light", m_ambientLight.serializeXML( ) );
+ e.setAttribute( "assumed_gamma", m_assumedGamma );
+ e.setAttribute( "hf_gray_16", m_hfGray16 );
+ e.setAttribute( "irid_wavelength", m_iridWaveLength.serializeXML( ) );
+ e.setAttribute( "max_intersections", m_maxIntersections );
+ e.setAttribute( "max_trace_level", m_maxTraceLevel );
+ e.setAttribute( "number_of_waves", m_numberWaves );
+ e.setAttribute( "radiosity", m_radiosityEnabled );
+ switch ( m_noiseGenerator )
+ {
+ case Original:
+ e.setAttribute( "noise_generator", "original" );
+ break;
+ case RangeCorrected:
+ e.setAttribute( "noise_generator", "range_corrected" );
+ break;
+ case Perlin:
+ e.setAttribute( "noise_generator", "perlin" );
+ break;
+ }
+ e.setAttribute( "brightness", m_brightness );
+ e.setAttribute( "count", m_count );
+ e.setAttribute( "distance_maximum", m_distanceMaximum );
+ e.setAttribute( "error_bound", m_errorBound );
+ e.setAttribute( "gray_threshold", m_grayThreshold );
+ e.setAttribute( "low_error_factor", m_lowErrorFactor );
+ e.setAttribute( "minimum_reuse", m_minimumReuse );
+ e.setAttribute( "nearest_count", m_nearestCount );
+ e.setAttribute( "recursion_limit", m_recursionLimit );
+
+ Base::serialize( e, doc );
+}
+
+void PMGlobalSettings::readAttributes( const PMXMLHelper& h )
+{
+ QString str;
+
+ m_adcBailout = h.doubleAttribute( "adc_bailout", adcBailoutDefault );
+ m_ambientLight = h.colorAttribute( "ambient_light", ambientLightDefault );
+ m_assumedGamma = h.doubleAttribute( "assumed_gamma", assumedGammaDefault );
+ m_hfGray16 = h.boolAttribute( "hf_gray_16", hfGray16Default );
+ m_iridWaveLength = h.colorAttribute( "irid_wavelength", iridWaveLengthDefault );
+ m_maxIntersections = h.intAttribute( "max_intersections", maxIntersectionsDefault );
+ m_maxTraceLevel = h.intAttribute( "max_trace_level", maxTraceLevelDefault );
+ m_numberWaves = h.intAttribute( "number_of_waves", numberWavesDefault );
+ str = h.stringAttribute( "noise_generator", "range_corrected" );
+ if ( str == "original" )
+ m_noiseGenerator = Original;
+ else if ( str == "perlin" )
+ m_noiseGenerator = Perlin;
+ else
+ m_noiseGenerator = RangeCorrected;
+ m_radiosityEnabled = h.boolAttribute( "radiosity", radiosityDefault );
+ m_brightness = h.doubleAttribute( "brightness", brightnessDefault );
+ m_count = h.intAttribute( "count", countDefault );
+ m_distanceMaximum = h.doubleAttribute( "distance_maximum", distanceMaximumDefault );
+ m_errorBound = h.doubleAttribute( "error_bound", errorBoundDefault );
+ m_grayThreshold = h.doubleAttribute( "gray_threshold", grayThresholdDefault );
+ m_lowErrorFactor = h.doubleAttribute( "low_error_factor", lowErrorFactorDefault );
+ m_minimumReuse = h.doubleAttribute( "minimum_reuse", minimumReuseDefault );
+ m_nearestCount = h.intAttribute( "nearest_count", nearestCountDefault );
+ m_recursionLimit = h.intAttribute( "recursion_limit", recursionLimitDefault );
+
+ Base::readAttributes( h );
+}
+
+void PMGlobalSettings::setAdcBailout( double c )
+{
+ if( c != m_adcBailout )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAdcBailoutID, m_adcBailout );
+ m_adcBailout = c;
+ }
+}
+
+void PMGlobalSettings::setAmbientLight( const PMColor& c )
+{
+ if( c != m_ambientLight )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAmbientLightID, m_ambientLight );
+ m_ambientLight = c;
+ }
+}
+
+void PMGlobalSettings::setAssumedGamma( double c )
+{
+ if( c != m_assumedGamma )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAssumedGammaID, m_assumedGamma );
+ m_assumedGamma = c;
+ }
+}
+
+void PMGlobalSettings::setIridWaveLength( const PMColor& c )
+{
+ if( c != m_iridWaveLength )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMIridWaveLengthID, m_iridWaveLength );
+ m_iridWaveLength = c;
+ }
+}
+
+void PMGlobalSettings::setHfGray16( bool c )
+{
+ if( c != m_hfGray16 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHfGray16ID, m_hfGray16 );
+ m_hfGray16 = c;
+ }
+}
+
+void PMGlobalSettings::setMaxIntersections( int c )
+{
+ if( c != m_maxIntersections )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMaxIntersectionsID, m_maxIntersections );
+ m_maxIntersections = c;
+ }
+}
+
+void PMGlobalSettings::setMaxTraceLevel( int c )
+{
+ if( c != m_maxTraceLevel )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMaxTraceLevelID, m_maxTraceLevel );
+ m_maxTraceLevel = c;
+ }
+}
+
+void PMGlobalSettings::setNumberWaves( int c )
+{
+ if( c != m_numberWaves )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNumberWavesID, m_numberWaves );
+ m_numberWaves = c;
+ }
+}
+
+void PMGlobalSettings::setNoiseGenerator( PMNoiseType c )
+{
+ if( c != m_noiseGenerator )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNoiseGeneratorID, m_noiseGenerator );
+ m_noiseGenerator = c;
+ }
+}
+
+void PMGlobalSettings::enableRadiosity( bool c )
+{
+ if( c != m_radiosityEnabled )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiosityEnabledID, m_radiosityEnabled );
+ m_radiosityEnabled = c;
+ }
+}
+
+void PMGlobalSettings::setBrightness( double c )
+{
+ if( c != m_brightness )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBrightnessID, m_brightness );
+ m_brightness = c;
+ }
+}
+
+void PMGlobalSettings::setCount( int c )
+{
+ if( c != m_count )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCountID, m_count );
+ m_count = c;
+ }
+}
+
+void PMGlobalSettings::setDistanceMaximum( double c )
+{
+ if( c != m_distanceMaximum )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDistanceMaximumID, m_distanceMaximum );
+ m_distanceMaximum = c;
+ }
+}
+
+void PMGlobalSettings::setErrorBound( double c )
+{
+ if( c != m_errorBound )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMErrorBoundID, m_errorBound );
+ m_errorBound = c;
+ }
+}
+
+void PMGlobalSettings::setGrayThreshold( double c )
+{
+ if( c != m_grayThreshold )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMGrayThresholdID, m_grayThreshold );
+ m_grayThreshold = c;
+ }
+}
+
+void PMGlobalSettings::setLowErrorFactor( double c )
+{
+ if( c != m_lowErrorFactor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLowErrorFactorID, m_lowErrorFactor );
+ m_lowErrorFactor = c;
+ }
+}
+
+void PMGlobalSettings::setMinimumReuse( double c )
+{
+ if( c != m_minimumReuse )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMinimumReuseID, m_minimumReuse );
+ m_minimumReuse = c;
+ }
+}
+
+void PMGlobalSettings::setNearestCount( int c )
+{
+ if( c != m_nearestCount )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNearestCountID, m_nearestCount );
+ m_nearestCount = c;
+ }
+}
+
+void PMGlobalSettings::setRecursionLimit( int c )
+{
+ if( c != m_recursionLimit )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRecursionLimitID, m_recursionLimit );
+ m_recursionLimit = c;
+ }
+}
+
+PMDialogEditBase* PMGlobalSettings::editWidget( QWidget* parent ) const
+{
+ return new PMGlobalSettingsEdit( parent );
+}
+
+void PMGlobalSettings::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMAdcBailoutID:
+ setAdcBailout( data->doubleData( ) );
+ break;
+ case PMAmbientLightID:
+ setAmbientLight( data->colorData( ) );
+ break;
+ case PMAssumedGammaID:
+ setAssumedGamma( data->doubleData( ) );
+ break;
+ case PMHfGray16ID:
+ setHfGray16( data->boolData( ) );
+ break;
+ case PMIridWaveLengthID:
+ setIridWaveLength( data->colorData( ) );
+ break;
+ case PMMaxIntersectionsID:
+ setMaxIntersections( data->intData( ) );
+ break;
+ case PMMaxTraceLevelID:
+ setMaxTraceLevel( data->intData( ) );
+ break;
+ case PMNumberWavesID:
+ setNumberWaves( data->intData( ) );
+ break;
+ case PMNoiseGeneratorID:
+ setNoiseGenerator( ( PMNoiseType ) ( data->intData( ) ) );
+ break;
+ case PMRadiosityEnabledID:
+ enableRadiosity( data->boolData( ) );
+ break;
+ case PMBrightnessID:
+ setBrightness( data->doubleData( ) );
+ break;
+ case PMCountID:
+ setCount( data->intData( ) );
+ break;
+ case PMDistanceMaximumID:
+ setDistanceMaximum( data->doubleData( ) );
+ break;
+ case PMErrorBoundID:
+ setErrorBound( data->doubleData( ) );
+ break;
+ case PMGrayThresholdID:
+ setGrayThreshold( data->doubleData( ) );
+ break;
+ case PMLowErrorFactorID:
+ setLowErrorFactor( data->doubleData( ) );
+ break;
+ case PMMinimumReuseID:
+ setMinimumReuse( data->doubleData( ) );
+ break;
+ case PMNearestCountID:
+ setNearestCount( data->intData( ) );
+ break;
+ case PMRecursionLimitID:
+ setRecursionLimit( data->intData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMGlobalSettings::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmglobalsettings.h b/kpovmodeler/pmglobalsettings.h
new file mode 100644
index 00000000..e552293e
--- /dev/null
+++ b/kpovmodeler/pmglobalsettings.h
@@ -0,0 +1,268 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMGLOBALSETTINGS_H
+#define PMGLOBALSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcompositeobject.h"
+#include "pmcolor.h"
+
+/**
+ * Class for global settings.
+ */
+
+class PMGlobalSettings : public PMCompositeObject
+{
+ typedef PMCompositeObject Base;
+public:
+ enum PMNoiseType { Original = 0, RangeCorrected = 1, Perlin = 2 };
+
+ /**
+ * Creates a PMGlobalSettings
+ */
+ PMGlobalSettings( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMGlobalSettings( const PMGlobalSettings& s );
+ /**
+ * deletes the PMGlobalSettings
+ */
+ virtual ~PMGlobalSettings( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMGlobalSettings( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMGlobalSettingsEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmglobalsettings" ); }
+
+ /**
+ * Returns the adc bailout
+ */
+ double adcBailout( ) const { return m_adcBailout; }
+ /**
+ * Sets the adc bailout
+ */
+ void setAdcBailout( double c );
+ /**
+ * Returns the ambient color
+ */
+ PMColor ambientLight( ) const { return m_ambientLight; }
+ /**
+ * Sets the ambient color
+ */
+ void setAmbientLight( const PMColor& c );
+ /**
+ * Returns the assumed gamma
+ */
+ double assumedGamma( ) const { return m_assumedGamma; }
+ /**
+ * Sets the assumed gamma
+ */
+ void setAssumedGamma( double c );
+ /**
+ * Returns the hf gray 16
+ */
+ bool hfGray16( ) const { return m_hfGray16; }
+ /**
+ * Sets the hf gray 16
+ */
+ void setHfGray16( bool c );
+ /**
+ * Returns the iridiscence wavelength
+ */
+ PMColor iridWaveLength( ) const { return m_iridWaveLength; }
+ /**
+ * Sets the iridiscence wavelength
+ */
+ void setIridWaveLength( const PMColor& c );
+ /**
+ * Returns the maximum number of intersections
+ */
+ int maxIntersections( ) const { return m_maxIntersections; }
+ /**
+ * Sets the maximum number of intersections
+ */
+ void setMaxIntersections( int c );
+ /**
+ * Returns the maximum trace level
+ */
+ int maxTraceLevel( ) const { return m_maxTraceLevel; }
+ /**
+ * Sets the maximum trace level
+ */
+ void setMaxTraceLevel( int c );
+ /**
+ * Returns the number of waves
+ */
+ int numberWaves( ) const { return m_numberWaves; }
+ /**
+ * Sets the number of waves
+ */
+ void setNumberWaves( int c );
+ /**
+ * Returns the current noise generator
+ */
+ PMNoiseType noiseGenerator( ) const { return m_noiseGenerator; }
+ /**
+ * Sets the noise generator
+ */
+ void setNoiseGenerator( PMNoiseType c );
+ /**
+ * Returns true if radiosity is enabled
+ */
+ bool isRadiosityEnabled( ) const { return m_radiosityEnabled; }
+ /**
+ * Enables/Disables radiosity
+ */
+ void enableRadiosity( bool c );
+ /**
+ * Returns brightness
+ */
+ double brightness( ) const { return m_brightness; }
+ /**
+ * Sets the brightness
+ */
+ void setBrightness( double c );
+ /**
+ * Returns count
+ */
+ int count( ) const { return m_count; }
+ /**
+ * Sets the count
+ */
+ void setCount( int c );
+ /**
+ * Returns maximum distance
+ */
+ double distanceMaximum( ) const { return m_distanceMaximum; }
+ /**
+ * Sets the maximum distance
+ */
+ void setDistanceMaximum( double c );
+ /**
+ * Returns error boundary
+ */
+ double errorBound( ) const { return m_errorBound; }
+ /**
+ * Sets the error boundary
+ */
+ void setErrorBound( double c );
+ /**
+ * Returns gray threshold
+ */
+ double grayThreshold( ) const { return m_grayThreshold; }
+ /**
+ * Sets the gray threshold
+ */
+ void setGrayThreshold( double c );
+ /**
+ * Returns low error factor
+ */
+ double lowErrorFactor( ) const { return m_lowErrorFactor; }
+ /**
+ * Sets the low error factor
+ */
+ void setLowErrorFactor( double c );
+ /**
+ * Returns minimum reuse
+ */
+ double minimumReuse( ) const { return m_minimumReuse; }
+ /**
+ * Sets the minimum reuse
+ */
+ void setMinimumReuse( double c );
+ /**
+ * Returns nearest count
+ */
+ int nearestCount( ) const { return m_nearestCount; }
+ /**
+ * Sets the nearest count
+ */
+ void setNearestCount( int c );
+ /**
+ * Returns recursion limit
+ */
+ int recursionLimit( ) const { return m_recursionLimit; }
+ /**
+ * Sets the recursion limit
+ */
+ void setRecursionLimit( int c );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMGlobalSettingsMementoID { PMAdcBailoutID, PMAmbientLightID, PMAssumedGammaID,
+ PMHfGray16ID, PMIridWaveLengthID, PMMaxIntersectionsID,
+ PMMaxTraceLevelID, PMNumberWavesID, PMNoiseGeneratorID,
+ PMRadiosityEnabledID, PMBrightnessID, PMCountID,
+ PMDistanceMaximumID, PMErrorBoundID, PMGrayThresholdID,
+ PMLowErrorFactorID, PMMinimumReuseID, PMNearestCountID,
+ PMRecursionLimitID };
+
+ double m_adcBailout;
+ PMColor m_ambientLight;
+ double m_assumedGamma;
+ bool m_hfGray16;
+ PMColor m_iridWaveLength;
+ int m_maxIntersections;
+ int m_maxTraceLevel;
+ int m_numberWaves;
+ PMNoiseType m_noiseGenerator;
+ bool m_radiosityEnabled;
+ double m_brightness;
+ int m_count;
+ double m_distanceMaximum;
+ double m_errorBound;
+ double m_grayThreshold;
+ double m_lowErrorFactor;
+ double m_minimumReuse;
+ int m_nearestCount;
+ int m_recursionLimit;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmglobalsettingsedit.cpp b/kpovmodeler/pmglobalsettingsedit.cpp
new file mode 100644
index 00000000..8a297738
--- /dev/null
+++ b/kpovmodeler/pmglobalsettingsedit.cpp
@@ -0,0 +1,317 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmglobalsettingsedit.h"
+#include "pmglobalsettings.h"
+#include "pmlineedits.h"
+#include "pmcoloredit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+
+PMGlobalSettingsEdit::PMGlobalSettingsEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMGlobalSettingsEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+ QLabel* lbl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Adc bailout:" ), this );
+ m_pAdcBailoutEdit = new PMFloatEdit( this );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pAdcBailoutEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Ambient light:" ), this );
+ m_pAmbientLightEdit = new PMColorEdit( false, this );
+ topLayout( )->addWidget( lbl );
+ topLayout( )->addWidget( m_pAmbientLightEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Assumed gamma:" ), this );
+ m_pAssumedGammaEdit = new PMFloatEdit( this );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pAssumedGammaEdit );
+ hl->addStretch( 1 );
+
+ m_pHfGray16Edit = new QCheckBox( i18n( "Hf gray 16" ), this );
+ topLayout( )->addWidget( m_pHfGray16Edit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Iridiscence wave length:" ), this );
+ m_pIridWaveLengthEdit = new PMColorEdit( false, this );
+ topLayout( )->addWidget( lbl );
+ topLayout( )->addWidget( m_pIridWaveLengthEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ QGridLayout* layout = new QGridLayout( hl, 4, 2 );
+ lbl = new QLabel( i18n( "Maximum intersections:" ), this );
+ m_pMaxIntersectionsEdit = new PMIntEdit( this );
+ layout->addWidget( lbl, 0, 0 );
+ layout->addWidget( m_pMaxIntersectionsEdit, 0, 1 );
+ lbl = new QLabel( i18n( "Maximum trace level:" ), this );
+ m_pMaxTraceLevelEdit = new PMIntEdit( this );
+ layout->addWidget( lbl, 1, 0 );
+ layout->addWidget( m_pMaxTraceLevelEdit, 1, 1 );
+ lbl = new QLabel( i18n( "Number of waves:" ), this );
+ m_pNumberWavesEdit = new PMIntEdit( this );
+ layout->addWidget( lbl, 2, 0 );
+ layout->addWidget( m_pNumberWavesEdit, 2, 1 );
+ lbl = new QLabel( i18n( "Noise generator:" ), this );
+ m_pNoiseGeneratorEdit = new QComboBox( false, this );
+ m_pNoiseGeneratorEdit->insertItem( i18n( "Original" ) );
+ m_pNoiseGeneratorEdit->insertItem( i18n( "Range Corrected" ) );
+ m_pNoiseGeneratorEdit->insertItem( i18n( "Perlin" ) );
+ layout->addWidget( lbl, 3, 0 );
+ layout->addWidget( m_pNoiseGeneratorEdit, 3, 1 );
+ hl->addStretch( 1 );
+
+ m_pRadiosityEdit = new QCheckBox( i18n( "Radiosity (Povray 3.1)" ), this );
+ topLayout( )->addWidget( m_pRadiosityEdit );
+
+ m_pRadiosityWidget = new QWidget( this );
+ hl = new QHBoxLayout( m_pRadiosityWidget, 0, KDialog::spacingHint( ) );
+ layout = new QGridLayout( hl, 7, 2 );
+ lbl = new QLabel( i18n( "Brightness:" ), m_pRadiosityWidget );
+ m_pBrightnessEdit = new PMFloatEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 0, 0 );
+ layout->addWidget( m_pBrightnessEdit, 0, 1 );
+ lbl = new QLabel( i18n( "Count:" ), m_pRadiosityWidget );
+ m_pCountEdit = new PMIntEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 1, 0 );
+ layout->addWidget( m_pCountEdit, 1, 1 );
+ lbl = new QLabel( i18n( "Maximum distance:" ), m_pRadiosityWidget );
+ m_pDistanceMaximumEdit = new PMFloatEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 2, 0 );
+ layout->addWidget( m_pDistanceMaximumEdit, 2, 1 );
+ lbl = new QLabel( i18n( "Error boundary:" ), m_pRadiosityWidget );
+ m_pErrorBoundEdit = new PMFloatEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 3, 0 );
+ layout->addWidget( m_pErrorBoundEdit, 3, 1 );
+ lbl = new QLabel( i18n( "Gray threshold:" ), m_pRadiosityWidget );
+ m_pGrayThresholdEdit = new PMFloatEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 4, 0 );
+ layout->addWidget( m_pGrayThresholdEdit, 4, 1 );
+ lbl = new QLabel( i18n( "Low error factor:" ), m_pRadiosityWidget );
+ m_pLowErrorFactorEdit = new PMFloatEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 5, 0 );
+ layout->addWidget( m_pLowErrorFactorEdit, 5, 1 );
+ lbl = new QLabel( i18n( "Minimum reuse:" ), m_pRadiosityWidget );
+ m_pMinimumReuseEdit = new PMFloatEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 6, 0 );
+ layout->addWidget( m_pMinimumReuseEdit, 6, 1 );
+ lbl = new QLabel( i18n( "Nearest count:" ), m_pRadiosityWidget );
+ m_pNearestCountEdit = new PMIntEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 7, 0 );
+ layout->addWidget( m_pNearestCountEdit, 7, 1 );
+ lbl = new QLabel( i18n( "Recursion limit:" ), m_pRadiosityWidget );
+ m_pRecursionLimitEdit = new PMIntEdit( m_pRadiosityWidget );
+ layout->addWidget( lbl, 8, 0 );
+ layout->addWidget( m_pRecursionLimitEdit, 8, 1 );
+ hl->addStretch( 1 );
+
+ topLayout( )->addWidget( m_pRadiosityWidget );
+
+ connect( m_pAdcBailoutEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAmbientLightEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAssumedGammaEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pHfGray16Edit, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pIridWaveLengthEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMaxIntersectionsEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMaxTraceLevelEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pNumberWavesEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pNoiseGeneratorEdit, SIGNAL( activated( int ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadiosityEdit, SIGNAL( clicked( ) ), SLOT( slotRadiosityClicked( ) ) );
+ connect( m_pBrightnessEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCountEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDistanceMaximumEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pErrorBoundEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pGrayThresholdEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pLowErrorFactorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMinimumReuseEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pNearestCountEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRecursionLimitEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMGlobalSettingsEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "GlobalSettings" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMGlobalSettings* ) o;
+
+ m_pAdcBailoutEdit->setValue( m_pDisplayedObject->adcBailout( ) );
+ m_pAdcBailoutEdit->setReadOnly( readOnly );
+ m_pAmbientLightEdit->setColor( m_pDisplayedObject->ambientLight( ) );
+ m_pAmbientLightEdit->setReadOnly( readOnly );
+ m_pAssumedGammaEdit->setValue( m_pDisplayedObject->assumedGamma( ) );
+ m_pAssumedGammaEdit->setReadOnly( readOnly );
+ m_pHfGray16Edit->setChecked( m_pDisplayedObject->hfGray16( ) );
+ m_pHfGray16Edit->setEnabled( !readOnly );
+ m_pIridWaveLengthEdit->setColor( m_pDisplayedObject->iridWaveLength( ) );
+ m_pIridWaveLengthEdit->setReadOnly( readOnly );
+ m_pMaxIntersectionsEdit->setValue( m_pDisplayedObject->maxIntersections( ) );
+ m_pMaxIntersectionsEdit->setReadOnly( readOnly );
+ m_pMaxTraceLevelEdit->setValue( m_pDisplayedObject->maxTraceLevel( ) );
+ m_pMaxTraceLevelEdit->setReadOnly( readOnly );
+ m_pNumberWavesEdit->setValue( m_pDisplayedObject->numberWaves( ) );
+ m_pNumberWavesEdit->setReadOnly( readOnly );
+ m_pNoiseGeneratorEdit->setCurrentItem( m_pDisplayedObject->noiseGenerator( ) );
+ m_pNoiseGeneratorEdit->setEnabled( !readOnly );
+ m_pRadiosityEdit->setChecked( m_pDisplayedObject->isRadiosityEnabled( ) );
+ m_pRadiosityEdit->setEnabled( !readOnly );
+ m_pBrightnessEdit->setValue( m_pDisplayedObject->brightness( ) );
+ m_pBrightnessEdit->setReadOnly( readOnly );
+ m_pCountEdit->setValue( m_pDisplayedObject->count( ) );
+ m_pCountEdit->setReadOnly( readOnly );
+ m_pDistanceMaximumEdit->setValue( m_pDisplayedObject->distanceMaximum( ) );
+ m_pDistanceMaximumEdit->setReadOnly( readOnly );
+ m_pErrorBoundEdit->setValue( m_pDisplayedObject->errorBound( ) );
+ m_pErrorBoundEdit->setReadOnly( readOnly );
+ m_pGrayThresholdEdit->setValue( m_pDisplayedObject->grayThreshold( ) );
+ m_pGrayThresholdEdit->setReadOnly( readOnly );
+ m_pLowErrorFactorEdit->setValue( m_pDisplayedObject->lowErrorFactor( ) );
+ m_pLowErrorFactorEdit->setReadOnly( readOnly );
+ m_pMinimumReuseEdit->setValue( m_pDisplayedObject->minimumReuse( ) );
+ m_pMinimumReuseEdit->setReadOnly( readOnly );
+ m_pNearestCountEdit->setValue( m_pDisplayedObject->nearestCount( ) );
+ m_pNearestCountEdit->setReadOnly( readOnly );
+ m_pRecursionLimitEdit->setValue( m_pDisplayedObject->recursionLimit( ) );
+ m_pRecursionLimitEdit->setReadOnly( readOnly );
+ slotRadiosityClicked( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMGlobalSettingsEdit: Can't display object\n";
+}
+
+void PMGlobalSettingsEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setAdcBailout( m_pAdcBailoutEdit->value( ) );
+ m_pDisplayedObject->setAmbientLight( m_pAmbientLightEdit->color( ) );
+ m_pDisplayedObject->setAssumedGamma( m_pAssumedGammaEdit->value( ) );
+ m_pDisplayedObject->setHfGray16( m_pHfGray16Edit->isChecked( ) );
+ m_pDisplayedObject->setIridWaveLength( m_pIridWaveLengthEdit->color( ) );
+ m_pDisplayedObject->setMaxIntersections( m_pMaxIntersectionsEdit->value( ) );
+ m_pDisplayedObject->setMaxTraceLevel( m_pMaxTraceLevelEdit->value( ) );
+ m_pDisplayedObject->setNumberWaves( m_pNumberWavesEdit->value( ) );
+ m_pDisplayedObject->setNoiseGenerator(
+ ( PMGlobalSettings::PMNoiseType ) ( m_pNoiseGeneratorEdit->currentItem( ) ) );
+ m_pDisplayedObject->enableRadiosity( m_pRadiosityEdit->isChecked( ) );
+ m_pDisplayedObject->setBrightness( m_pBrightnessEdit->value( ) );
+ m_pDisplayedObject->setCount( m_pCountEdit->value( ) );
+ m_pDisplayedObject->setDistanceMaximum( m_pDistanceMaximumEdit->value( ) );
+ m_pDisplayedObject->setErrorBound( m_pErrorBoundEdit->value( ) );
+ m_pDisplayedObject->setGrayThreshold( m_pGrayThresholdEdit->value( ) );
+ m_pDisplayedObject->setLowErrorFactor( m_pLowErrorFactorEdit->value( ) );
+ m_pDisplayedObject->setMinimumReuse( m_pMinimumReuseEdit->value( ) );
+ m_pDisplayedObject->setNearestCount( m_pNearestCountEdit->value( ) );
+ m_pDisplayedObject->setRecursionLimit( m_pRecursionLimitEdit->value( ) );
+ }
+}
+
+bool PMGlobalSettingsEdit::isDataValid( )
+{
+ if( !m_pAdcBailoutEdit->isDataValid( ) ) return false;
+ if( !m_pAmbientLightEdit->isDataValid( ) ) return false;
+ if( !m_pAssumedGammaEdit->isDataValid( ) ) return false;
+ if( !m_pIridWaveLengthEdit->isDataValid( ) ) return false;
+ if( !m_pMaxIntersectionsEdit->isDataValid( ) ) return false;
+ if( !m_pMaxTraceLevelEdit->isDataValid( ) ) return false;
+ if( !m_pNumberWavesEdit->isDataValid( ) ) return false;
+ if( !m_pBrightnessEdit->isDataValid( ) ) return false;
+ if( !m_pCountEdit->isDataValid( ) ) return false;
+ if( !m_pDistanceMaximumEdit->isDataValid( ) ) return false;
+ if( !m_pErrorBoundEdit->isDataValid( ) ) return false;
+ if( !m_pGrayThresholdEdit->isDataValid( ) ) return false;
+ if( !m_pLowErrorFactorEdit->isDataValid( ) ) return false;
+ if( !m_pMinimumReuseEdit->isDataValid( ) ) return false;
+ if( !m_pNearestCountEdit->isDataValid( ) ) return false;
+ if( !m_pRecursionLimitEdit->isDataValid( ) ) return false;
+
+ if( m_pMaxIntersectionsEdit->value( ) < 0 )
+ {
+ KMessageBox::error( this, i18n( "Maximum intersections must be a positive value." ),
+ i18n( "Error" ) );
+ m_pMaxIntersectionsEdit->setFocus( );
+ return false;
+ }
+ if( m_pMaxTraceLevelEdit->value( ) < 0 )
+ {
+ KMessageBox::error( this, i18n( "Maximum trace level must be a positive value." ),
+ i18n( "Error" ) );
+ m_pMaxTraceLevelEdit->setFocus( );
+ return false;
+ }
+ if( m_pNumberWavesEdit->value( ) < 0 )
+ {
+ KMessageBox::error( this, i18n( "Number of waves must be a positive value." ),
+ i18n( "Error" ) );
+ m_pNumberWavesEdit->setFocus( );
+ return false;
+ }
+ if( m_pNearestCountEdit->value( ) < 1 || m_pNearestCountEdit->value( ) > 10 )
+ {
+ KMessageBox::error( this, i18n( "Nearest count must be between 1 and 10." ),
+ i18n( "Error" ) );
+ m_pNearestCountEdit->setFocus( );
+ return false;
+ }
+
+ if( m_pRecursionLimitEdit->value( ) < 1 || m_pRecursionLimitEdit->value( ) > 2 )
+ {
+ KMessageBox::error( this, i18n( "Recursion limit must be 1 or 2." ),
+ i18n( "Error" ) );
+ m_pRecursionLimitEdit->setFocus( );
+ return false;
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMGlobalSettingsEdit::slotRadiosityClicked( )
+{
+ if( m_pRadiosityEdit->isChecked( ) )
+ m_pRadiosityWidget->show( );
+ else
+ m_pRadiosityWidget->hide( );
+
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+#include "pmglobalsettingsedit.moc"
diff --git a/kpovmodeler/pmglobalsettingsedit.h b/kpovmodeler/pmglobalsettingsedit.h
new file mode 100644
index 00000000..2a439617
--- /dev/null
+++ b/kpovmodeler/pmglobalsettingsedit.h
@@ -0,0 +1,93 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMGLOBALSETTINGSEDIT_H
+#define PMGLOBALSETTINGSEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMGlobalSettings;
+class PMColorEdit;
+class PMFloatEdit;
+class PMIntEdit;
+class QCheckBox;
+class QComboBox;
+
+/**
+ * Dialog edit class for @ref PMGlobalSettings.
+ */
+class PMGlobalSettingsEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMGlobalSettingsEdit with parent and name
+ */
+ PMGlobalSettingsEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * Slot called whenever Radiosity is toggled
+ */
+ void slotRadiosityClicked( );
+
+private:
+ PMGlobalSettings* m_pDisplayedObject;
+
+ PMFloatEdit* m_pAdcBailoutEdit;
+ PMColorEdit* m_pAmbientLightEdit;
+ PMFloatEdit* m_pAssumedGammaEdit;
+ QCheckBox* m_pHfGray16Edit;
+ PMColorEdit* m_pIridWaveLengthEdit;
+ PMIntEdit* m_pMaxIntersectionsEdit;
+ PMIntEdit* m_pMaxTraceLevelEdit;
+ PMIntEdit* m_pNumberWavesEdit;
+ QComboBox* m_pNoiseGeneratorEdit;
+ QCheckBox* m_pRadiosityEdit;
+ QWidget* m_pRadiosityWidget;
+ PMFloatEdit* m_pBrightnessEdit;
+ PMIntEdit* m_pCountEdit;
+ PMFloatEdit* m_pDistanceMaximumEdit;
+ PMFloatEdit* m_pErrorBoundEdit;
+ PMFloatEdit* m_pGrayThresholdEdit;
+ PMFloatEdit* m_pLowErrorFactorEdit;
+ PMFloatEdit* m_pMinimumReuseEdit;
+ PMIntEdit* m_pNearestCountEdit;
+ PMIntEdit* m_pRecursionLimitEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmglview.cpp b/kpovmodeler/pmglview.cpp
new file mode 100644
index 00000000..43102de9
--- /dev/null
+++ b/kpovmodeler/pmglview.cpp
@@ -0,0 +1,1853 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmglview.h"
+#include "pmpart.h"
+#include "pmrendermanager.h"
+#include "pmcamera.h"
+#include "pmscene.h"
+#include "pmdatachangecommand.h"
+#include "pmdebug.h"
+#include "pmdefaults.h"
+
+#include <math.h>
+#include <qpopupmenu.h>
+#include <qpainter.h>
+#include <qapplication.h>
+#include <qcursor.h>
+#include <qcolor.h>
+#include <qglobal.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qdom.h>
+
+#include <kxmlguifactory.h>
+#include <kaction.h>
+#include <kconfig.h>
+#include <kstaticdeleter.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdialog.h>
+
+#include <GL/glx.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <X11/Xmu/StdCmap.h>
+
+const double c_sizeFactor = log( 2.0 ) / 100.0;
+const int c_mouseChangeDelayPixel = 3;
+const int c_mouseChangeDelayMs = 300;
+const int c_multipleSelectDelayPixel = 3;
+const double c_defaultAutoScrollSpeed = 200; // pixels per second
+const int c_minAutoScrollUpdateTime = 30; //ms
+
+const double keyMoveSpeed = 40.0;
+const double keyScaleFactor = 1.4;
+
+static int glxAttributeList[] = { GLX_LEVEL, 0,
+ GLX_DOUBLEBUFFER,
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ //GLX_ALPHA_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+ None };
+
+class PMGLViewStatic
+{
+public:
+ PMGLViewStatic( )
+ {
+ m_colormap = 0;
+ m_context = NULL;
+ m_colormapAllocated = false;
+ m_display = 0;
+ m_visualInfo = 0;
+ }
+ ~PMGLViewStatic( )
+ {
+ if( m_colormapAllocated )
+ XFreeColormap( m_display, m_colormap );
+ if( m_context != NULL )
+ glXDestroyContext( m_display, m_context );
+ if( m_visualInfo )
+ XFree( m_visualInfo );
+ }
+
+ Colormap m_colormap;
+ GLXContext m_context;
+ bool m_colormapAllocated;
+ Display* m_display;
+ XVisualInfo* m_visualInfo;
+};
+
+static PMGLViewStatic* s_pSharedData = 0;
+static KStaticDeleter<PMGLViewStatic> s_staticDeleter;
+bool PMGLView::s_bDirect = true;
+
+
+PMGLView::PMGLView( PMPart* part, PMViewType t,
+ QWidget* parent, const char* name, WFlags f )
+ : PMViewBase( parent, name, f | Qt::WWinOwnDC | Qt::WRepaintNoErase )
+{
+ m_pPart = part;
+ m_type = t;
+ m_bScaleMode = false;
+ m_scaleIntX = 0.0;
+ m_scaleIntY = 0.0;
+ m_bTranslateMode = false;
+ m_bGraphicalChangeMode = false;
+ m_bMousePressed = false;
+ m_bMidMousePressed = false;
+ m_dTransX = 0.0;
+ m_dTransY = 0.0;
+ m_dScale = 30.0;
+ m_bInverseValid = false;
+ m_pActiveObject = part->activeObject( );
+ m_bMementoCreated = false;
+ m_bSelectUnderMouse = false;
+ m_bDeselectUnderMouse = false;
+ m_bMultipleSelectionMode = false;
+ m_bSelectionStarted = false;
+ m_bAutoScroll = false;
+ m_autoScrollSpeed = c_defaultAutoScrollSpeed;
+ m_bAboutToUpdate = false;
+ m_projectionUpToDate = false;
+ m_contextClickPosition = PMVector( 0.0, 0.0 );
+ m_objectActions.setAutoDelete( true );
+
+ m_controlPointsPosition.setAutoDelete( true );
+ m_pUnderMouse = 0;
+
+ setCamera( m_pPart->firstCamera( ) );
+
+ initializeGL( );
+
+ setMouseTracking( true );
+ setFocusPolicy( WheelFocus );
+
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ rm->viewCreated( );
+
+ setMinimumSize( 50, 50 );
+
+ connect( part, SIGNAL( refresh( ) ), SLOT( slotRefresh( ) ) );
+ connect( part, SIGNAL( clear( ) ), SLOT( slotClear( ) ) );
+
+ connect( this, SIGNAL( objectChanged( PMObject*, const int, QObject* ) ),
+ part, SLOT( slotObjectChanged( PMObject*, const int, QObject* ) ) );
+ connect( part, SIGNAL( objectChanged( PMObject*, const int, QObject* ) ),
+ SLOT( slotObjectChanged( PMObject*, const int, QObject* ) ) );
+
+ connect( part, SIGNAL( activeRenderModeChanged( ) ),
+ SLOT( slotActiveRenderModeChanged( ) ) );
+
+ connect( &m_startTimer, SIGNAL( timeout( ) ),
+ SLOT( slotMouseChangeTimer( ) ) );
+ connect( &m_autoScrollTimer, SIGNAL( timeout( ) ),
+ SLOT( slotAutoScroll( ) ) );
+
+ connect( rm, SIGNAL( renderingStarted( PMGLView* ) ),
+ SLOT( slotRenderingStarted( PMGLView* ) ) );
+ connect( rm, SIGNAL( aboutToUpdate( PMGLView* ) ),
+ SLOT( slotAboutToUpdate( PMGLView* ) ) );
+ connect( rm, SIGNAL( renderingFinished( PMGLView* ) ),
+ SLOT( slotRenderingFinished( PMGLView* ) ) );
+ connect( rm, SIGNAL( renderingSettingsChanged( ) ),
+ SLOT( slotRefresh( ) ) );
+
+ connect( this, SIGNAL( controlPointMessage( const QString& ) ),
+ m_pPart, SIGNAL( controlPointMessage( const QString& ) ) );
+
+ updateControlPoints( );
+}
+
+void PMGLView::initializeGL( )
+{
+ Display* display = x11Display( );
+ int screen = x11Screen( );
+ int i;
+
+ if( !s_pSharedData )
+ {
+ s_staticDeleter.setObject( s_pSharedData, new PMGLViewStatic );
+ s_pSharedData->m_display = display;
+
+ if( PMRenderManager::hasOpenGL( ) )
+ {
+ // get an appropriate visual
+ XVisualInfo* vi = glXChooseVisual( display, screen, glxAttributeList );
+ s_pSharedData->m_visualInfo = vi;
+
+ if( vi )
+ {
+ kdDebug( PMArea ) << "PMGLView: XVisual found\n";
+
+ // create a color map (from qgl_x11.cpp)
+ // check if we can use the global colormap
+ // should be the default ?
+ if( vi->visualid ==
+ XVisualIDFromVisual( ( Visual* ) QPaintDevice::x11AppVisual( ) ) )
+ {
+ kdDebug( PMArea ) << "PMGLView: Default colormap used\n";
+ s_pSharedData->m_colormap = QPaintDevice::x11AppColormap();
+ s_pSharedData->m_colormapAllocated = false;
+ }
+
+ if( !s_pSharedData->m_colormap )
+ {
+ const char* v = glXQueryServerString( display, vi->screen,
+ GLX_VERSION );
+ bool mesa_gl = false;
+ if( v )
+ mesa_gl = strstr( v, "Mesa" ) != 0;
+ if( mesa_gl )
+ {
+ XStandardColormap* c;
+ int n;
+ Atom hp_cmaps = XInternAtom( display, "_HP_RGB_SMOOTH_MAP_LIST",
+ TRUE );
+
+ if( hp_cmaps && ( vi->visual->c_class == TrueColor )
+ && ( vi->depth == 8 ) )
+ {
+ if( XGetRGBColormaps( display, RootWindow( display,vi->screen ),
+ &c, &n, hp_cmaps ) )
+ {
+ i = 0;
+ while( ( i < n ) && ( s_pSharedData->m_colormap == 0 ) )
+ {
+ if( c[i].visualid == vi->visual->visualid )
+ {
+ s_pSharedData->m_colormap = c[i].colormap;
+ kdDebug( PMArea ) << "PMGLView: HP_RGB scmap used\n";
+ }
+ i++;
+ }
+ XFree( ( char* ) c );
+ }
+ }
+ }
+ }
+
+#if !defined(Q_OS_SOLARIS)
+ if( !s_pSharedData->m_colormap )
+ {
+ XStandardColormap* c;
+ int n;
+
+ if( XmuLookupStandardColormap( display, vi->screen, vi->visualid,
+ vi->depth, XA_RGB_DEFAULT_MAP,
+ FALSE, TRUE ) )
+ {
+ if( XGetRGBColormaps( display, RootWindow( display, vi->screen ),
+ &c, &n, XA_RGB_DEFAULT_MAP ) )
+ {
+ i = 0;
+ while( ( i < n ) && ( s_pSharedData->m_colormap == 0 ) )
+ {
+ if( c[i].visualid == vi->visualid )
+ {
+ s_pSharedData->m_colormap = c[i].colormap;
+ kdDebug( PMArea ) << "PMGLView: RGB_DEFAULT scmap used\n";
+ }
+ i++;
+ }
+ XFree( ( char* ) c );
+ }
+ }
+ }
+#endif
+
+ if( !s_pSharedData->m_colormap )
+ {
+ // create a new colormap otherwise
+ kdDebug( PMArea ) << "PMGLView: New colormap created\n";
+ s_pSharedData->m_colormap =
+ XCreateColormap( display,
+ RootWindow( display, vi->screen ),
+ vi->visual, AllocNone );
+ s_pSharedData->m_colormapAllocated = true;
+ }
+
+ // create the context
+ // this context is shared between all gl views!
+ s_pSharedData->m_context = glXCreateContext( display, vi, 0, s_bDirect );
+
+ if( s_pSharedData->m_context != NULL )
+ kdDebug( PMArea ) << "PMGLView: glx context created\n";
+
+ }
+ }
+ }
+
+ if( s_pSharedData->m_context != NULL )
+ {
+ XVisualInfo* vi = s_pSharedData->m_visualInfo;
+
+ // create the window
+ XSetWindowAttributes swa;
+ swa.colormap = s_pSharedData->m_colormap;
+ swa.border_pixel = 0;
+ swa.background_pixel = 0;
+
+ Window p;
+ p = RootWindow( display, vi->screen );
+ QWidget* pw = parentWidget( );
+ if( pw )
+ p = pw->winId( );
+
+ Window w = XCreateWindow( display, p, x( ), y( ), width( ),
+ height( ), 0, vi->depth, InputOutput,
+ vi->visual,
+ CWColormap | CWBorderPixel | CWBackPixel,
+ &swa );
+
+ // tell the windowmanager to use the colormap
+ Window* colorMapWindows = 0;
+ Window* newWindows = 0;
+ int num;
+ if( XGetWMColormapWindows( display, topLevelWidget( )->winId( ),
+ &colorMapWindows, &num ) )
+ {
+ // create a new list and append the new window
+ bool replaced = false;
+ newWindows = new Window[num+1];
+
+ for( i = 0; i < num; i++ )
+ {
+ newWindows[i] = colorMapWindows[i];
+ if( newWindows[i] == winId( ) ) // old window
+ {
+ newWindows[i] = w;
+ replaced = true;
+ }
+ }
+ if( !replaced )
+ {
+ newWindows[num] = w;
+ num++;
+ }
+ }
+ else
+ {
+ num = 1;
+ newWindows = new Window[1];
+ newWindows[0] = w;
+ }
+ // tell Qt to use this window
+ create( w );
+
+ XSetWMColormapWindows( display, topLevelWidget( )->winId( ),
+ newWindows, num );
+ delete[] newWindows;
+
+ XFlush( x11Display( ) );
+ }
+ else
+ {
+ QVBoxLayout* topLayout = new QVBoxLayout( this );
+ QLabel* label = new QLabel( i18n( "No OpenGL support" ), this );
+ label->setAlignment( Qt::AlignCenter );
+ topLayout->addWidget( label );
+ }
+
+ //setProjection( );
+}
+
+PMGLView::~PMGLView( )
+{
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ rm->removeView( this );
+ rm->viewDeleted( );
+ emit destroyed( this );
+}
+
+bool PMGLView::isValid( ) const
+{
+ if( s_pSharedData && ( s_pSharedData->m_context != NULL ) )
+ return true;
+ return false;
+}
+
+void PMGLView::makeCurrent( )
+{
+ if( isValid( ) )
+ glXMakeCurrent( x11Display( ), winId( ), s_pSharedData->m_context );
+}
+
+void PMGLView::swapBuffers( )
+{
+ if( isValid( ) )
+ glXSwapBuffers( x11Display( ), winId( ) );
+}
+
+void PMGLView::setScale( double scale )
+{
+ if( m_dScale > 0 )
+ {
+ m_dScale = scale;
+ invalidateProjection( );
+ }
+ else
+ kdError( PMArea ) << "Scale <= 0 in PMGLView::setScale\n";
+}
+
+void PMGLView::setTranslationX( double d )
+{
+ m_dTransX = d;
+ invalidateProjection( );
+}
+
+void PMGLView::setTranslationY( double d )
+{
+ m_dTransY = d;
+ invalidateProjection( );
+}
+
+void PMGLView::resizeEvent( QResizeEvent* )
+{
+ invalidateProjection( );
+}
+
+void PMGLView::paintEvent( QPaintEvent* )
+{
+ repaint( );
+}
+
+void PMGLView::invalidateProjection( bool graphicalChange /*= true*/ )
+{
+ m_viewTransformation = PMMatrix::identity( );
+
+
+ if( m_type != PMViewCamera )
+ {
+ m_viewTransformation = m_viewTransformation * PMMatrix::scale( m_dScale, m_dScale, m_dScale );
+ m_viewTransformation = m_viewTransformation * PMMatrix::translation( m_dTransX, m_dTransY, 0 );
+
+ switch( m_type )
+ {
+ case PMViewPosZ:
+ m_normal = PMVector( 0.0, 0.0, 1.0 );
+ break;
+ case PMViewNegZ:
+ m_viewTransformation = m_viewTransformation * PMMatrix::rotation( 0.0, M_PI, 0.0 );
+ m_normal = PMVector( 0.0, 0.0, -1.0 );
+ break;
+ case PMViewNegY:
+ m_viewTransformation = m_viewTransformation * PMMatrix::rotation( M_PI_2, 0.0, 0.0 );
+ m_normal = PMVector( 0.0, -1.0, 0.0 );
+ break;
+ case PMViewPosY:
+ m_normal = PMVector( 0.0, 1.0, 0.0 );
+ m_viewTransformation = m_viewTransformation * PMMatrix::rotation( -M_PI_2, 0.0, 0.0 );
+ break;
+ case PMViewPosX:
+ m_viewTransformation = m_viewTransformation * PMMatrix::rotation( 0.0, M_PI_2, 0.0 );
+ m_normal = PMVector( 1.0, 0.0, 0.0 );
+ break;
+ case PMViewNegX:
+ m_viewTransformation = m_viewTransformation * PMMatrix::rotation( 0.0, -M_PI_2, 0.0 );
+ m_normal = PMVector( -1.0, 0.0, 0.0 );
+ break;
+ default:
+ break;
+ }
+
+ m_viewTransformation = m_viewTransformation * PMMatrix::scale( 1.0, 1.0, -1.0 );
+
+ if( m_controlPoints.count( ) > 0 )
+ recalculateTransformations( );
+ recalculateControlPointPosition( );
+ }
+ m_projectionUpToDate = false;
+ repaint( graphicalChange );
+}
+
+void PMGLView::enableTranslateMode( bool yes )
+{
+ if( m_type != PMViewCamera )
+ {
+ m_bScaleMode = false;
+ m_bTranslateMode = yes;
+ setCursor( yes ? crossCursor : arrowCursor );
+ }
+}
+
+void PMGLView::enableScaleMode( bool yes )
+{
+ if( m_type != PMViewCamera )
+ {
+ m_bScaleMode = yes;
+ m_bTranslateMode = false;
+ setCursor( yes ? crossCursor : arrowCursor );
+ }
+}
+
+void PMGLView::mousePressEvent( QMouseEvent* e )
+{
+ if( m_bScaleMode || m_bTranslateMode )
+ {
+ if( ( e->button( ) & LeftButton ) && ( e->state( ) == 0 ) )
+ {
+ m_bMousePressed = true;
+ m_mousePos = e->pos( );
+ m_scaleIntX = screenToInternalX( e->x( ) );
+ m_scaleIntY = screenToInternalY( e->y( ) );
+ }
+ }
+ else if( m_type != PMViewCamera )
+ {
+ if( ( e->button( ) & LeftButton ) && m_bInverseValid
+ && m_pActiveObject )
+ {
+ if( m_pUnderMouse )
+ {
+ // check the control point selection
+ if( m_pActiveObject->multipleSelectControlPoints( ) )
+ {
+ if( m_pUnderMouse->selected( ) )
+ {
+ if( e->state( ) & ControlButton )
+ m_bDeselectUnderMouse = true;
+ else
+ m_bSelectUnderMouse = true;
+ }
+ else
+ {
+ if( e->state( ) & ControlButton )
+ selectControlPoint( m_pUnderMouse,
+ !m_pUnderMouse->selected( ), false );
+ else
+ selectControlPoint( m_pUnderMouse, true );
+ }
+ }
+ else
+ selectControlPoint( m_pUnderMouse, true );
+
+ // start the graphical change
+ if( !m_bGraphicalChangeMode )
+ {
+ m_bGraphicalChangeMode = true;
+ m_bMementoCreated = false;
+ m_changeStartPos = e->pos( );
+ m_changeStartTime = QTime::currentTime( );
+ m_currentMousePos = m_changeStartPos;
+ m_startTimer.start( c_mouseChangeDelayMs, true );
+ }
+ }
+ else
+ {
+ if( m_pActiveObject->multipleSelectControlPoints( ) )
+ {
+ // multiple selection mode
+ // start only when the view is rendered
+ if( !PMRenderManager::theManager( )->containsTask( this ) )
+ {
+ m_bMultipleSelectionMode = true;
+ m_bSelectionStarted = false;
+ m_selectionStart = e->pos( );
+ m_selectionEnd = m_selectionStart;
+ }
+ }
+ else
+ selectControlPoint( 0, false );
+ }
+ }
+ }
+
+
+ if( !( m_bGraphicalChangeMode || m_bMousePressed ) )
+ {
+ if( ( e->button( ) == RightButton ) && ( e->state( ) == 0 ) )
+ {
+ m_contextClickPosition = PMVector( screenToInternalX( e->x( ) ),
+ screenToInternalY( e->y( ) ) );
+
+ if( m_pUnderMouse )
+ {
+ // check the control point selection
+ if( m_pActiveObject->multipleSelectControlPoints( ) )
+ {
+ if( !m_pUnderMouse->selected( ) )
+ selectControlPoint( m_pUnderMouse, true );
+ }
+ else
+ selectControlPoint( m_pUnderMouse, true );
+ }
+
+ contextMenu( );
+ }
+ }
+
+ if( e->button( ) == MidButton )
+ {
+ m_bMidMousePressed = true;
+ m_mousePos = e->pos( );
+ }
+}
+
+void PMGLView::mouseReleaseEvent( QMouseEvent* e )
+{
+ m_bMousePressed = false;
+ if( m_bGraphicalChangeMode )
+ {
+ m_startTimer.stop( );
+
+ if( m_bMementoCreated )
+ {
+ PMDataChangeCommand* cmd;
+ cmd = new PMDataChangeCommand( m_pActiveObject->takeMemento( ) );
+ m_pPart->executeCommand( cmd );
+
+ checkUnderMouse( ( int ) screenToInternalX( e->x( ) ),
+ ( int ) screenToInternalY( e->y( ) ) );
+ }
+ else
+ {
+ if( m_pUnderMouse )
+ {
+ if( m_bSelectUnderMouse )
+ selectControlPoint( m_pUnderMouse, true );
+ else if( m_bDeselectUnderMouse )
+ selectControlPoint( m_pUnderMouse, false, false );
+ }
+ }
+ m_bGraphicalChangeMode = false;
+ }
+ else if( m_bMultipleSelectionMode )
+ {
+ if( m_bSelectionStarted )
+ {
+ int sx, sy, ex, ey, w, h;
+ double isx, isy, iex, iey;
+ QPtrListIterator<PMVector> pit( m_controlPointsPosition );
+ PMControlPointListIterator cit( m_controlPoints );
+ PMVector p;
+
+ calculateSelectionBox( sx, sy, ex, ey, w, h );
+ isx = screenToInternalX( sx );
+ iex = screenToInternalX( ex );
+ isy = screenToInternalY( ey );
+ iey = screenToInternalY( sy );
+ restoreSelectionBox( );
+
+ while( pit.current( ) && cit.current( ) )
+ {
+ p = *( pit.current( ) );
+
+ if( ( isx <= p[0] ) && ( iex >= p[0] )
+ && ( isy <= p[1] ) && ( iey >= p[1] ) )
+ selectControlPoint( cit.current( ), true, false );
+ else if( !( e->state( ) & ControlButton ) )
+ selectControlPoint( cit.current( ), false, false );
+
+ ++cit;
+ ++pit;
+ }
+ }
+ else
+ selectControlPoint( 0, false );
+
+ m_bMultipleSelectionMode = false;
+ }
+
+ if( m_bAutoScroll )
+ {
+ m_bAutoScroll = false;
+ m_autoScrollTimer.stop( );
+ }
+
+ if( e->button( ) & QEvent::MidButton )
+ m_bMidMousePressed = false;
+
+ m_bSelectUnderMouse = false;
+ m_bDeselectUnderMouse = false;
+}
+
+void PMGLView::mouseMoveEvent( QMouseEvent* e )
+{
+ if( m_bMousePressed )
+ {
+ if( m_bScaleMode )
+ {
+ int d = e->x( ) - m_mousePos.x( );
+ if( d != 0 )
+ {
+ double s = exp( d * c_sizeFactor );
+ double c = 1.0 / ( m_dScale * s ) - 1.0 / m_dScale;
+ m_dTransX += m_scaleIntX * c;
+ m_dTransY += m_scaleIntY * c;
+ m_dScale *= s;
+ invalidateProjection( );
+ }
+ }
+ else if( m_bTranslateMode )
+ {
+ m_dTransX += ( e->x( ) - m_mousePos.x( ) ) / m_dScale;
+ m_dTransY -= ( e->y( ) - m_mousePos.y( ) ) / m_dScale;
+ invalidateProjection( );
+ }
+ m_mousePos = e->pos( );
+ }
+ else if( m_bMidMousePressed )
+ {
+ m_dTransX += ( e->x( ) - m_mousePos.x( ) ) / m_dScale;
+ m_dTransY -= ( e->y( ) - m_mousePos.y( ) ) / m_dScale;
+ invalidateProjection( );
+
+ m_mousePos = e->pos( );
+ }
+ else if( m_bGraphicalChangeMode )
+ {
+ m_currentMousePos = e->pos( );
+ if( !m_bMementoCreated )
+ {
+ QPoint movement = e->pos( ) - m_changeStartPos;
+ if( ( m_changeStartTime.msecsTo( QTime::currentTime( ) ) > c_mouseChangeDelayMs )
+ || ( movement.manhattanLength( ) > c_mouseChangeDelayPixel ) )
+ {
+ m_startTimer.stop( );
+ startChange( m_changeStartPos );
+ }
+ }
+
+ if( m_bMementoCreated )
+ graphicalChange( e->pos( ) );
+ }
+ else if( m_bMultipleSelectionMode )
+ {
+ if( !m_bSelectionStarted )
+ {
+ m_selectionEnd = e->pos( );
+ startSelection( );
+ }
+ else
+ {
+ restoreSelectionBox( );
+ m_selectionEnd = e->pos( );
+ saveSelectionBox( );
+ paintSelectionBox( );
+ }
+ }
+ else if( !( m_bScaleMode || m_bTranslateMode ) )
+ {
+ checkUnderMouse( ( int ) screenToInternalX( e->x( ) ),
+ ( int ) screenToInternalY( e->y( ) ) );
+ }
+
+ if( m_bMultipleSelectionMode || m_bGraphicalChangeMode )
+ {
+ bool as = m_bAutoScroll;
+
+ if( e->x( ) < 0 )
+ m_autoScrollDirectionX = 1;
+ else if( e->x( ) >= width( ) )
+ m_autoScrollDirectionX = -1;
+ else
+ m_autoScrollDirectionX = 0;
+
+ if( e->y( ) < 0 )
+ m_autoScrollDirectionY = 1;
+ else if( e->y( ) >= height( ) )
+ m_autoScrollDirectionY = -1;
+ else
+ m_autoScrollDirectionY = 0;
+
+ if( ( m_autoScrollDirectionX != 0 ) || ( m_autoScrollDirectionY != 0 ) )
+ m_bAutoScroll = true;
+ else
+ m_bAutoScroll = false;
+
+ if( m_bAutoScroll && !as )
+ {
+ m_lastAutoScrollUpdate = QTime::currentTime( );
+ m_autoScrollTimer.start( c_minAutoScrollUpdateTime, true );
+ }
+ if( !m_bAutoScroll && as )
+ m_autoScrollTimer.stop( );
+ }
+}
+
+void PMGLView::wheelEvent( QWheelEvent* e )
+{
+ if( m_type != PMViewCamera )
+ {
+ double s = exp( e->delta( ) / 4 * c_sizeFactor );
+ double deltaX = screenToInternalX( e->x( ) );
+ double deltaY = screenToInternalY( e->y( ) );
+ double c = 1.0 / ( m_dScale * s ) - 1.0 / m_dScale;
+ m_dTransX += deltaX * c;
+ m_dTransY += deltaY * c;
+ m_dScale *= s;
+ invalidateProjection( );
+ }
+}
+
+void PMGLView::keyPressEvent( QKeyEvent* e )
+{
+ bool accept = true;
+
+ if( e->state( ) == 0 )
+ {
+ if( m_type != PMViewCamera )
+ {
+ if( m_dScale > 0 )
+ {
+ switch( e->key( ) )
+ {
+ case Key_Left:
+ m_dTransX -= keyMoveSpeed / m_dScale;
+ break;
+ case Key_Right:
+ m_dTransX += keyMoveSpeed / m_dScale;
+ break;
+ case Key_Up:
+ m_dTransY += keyMoveSpeed / m_dScale;
+ break;
+ case Key_Down:
+ m_dTransY -= keyMoveSpeed / m_dScale;
+ break;
+ default:
+ accept = false;
+ }
+ }
+ else
+ kdError( PMArea ) << "scale <= 0 in PMGLView::keyPressEvent\n";
+ }
+ }
+ else if( e->state( ) == ControlButton )
+ {
+ if( m_type != PMViewCamera )
+ {
+ switch( e->key( ) )
+ {
+ case Key_Left:
+ case Key_Down:
+ m_dScale /= keyScaleFactor;
+ break;
+ case Key_Right:
+ case Key_Up:
+ m_dScale *= keyScaleFactor;
+ break;
+ default:
+ accept = false;
+ }
+ }
+ }
+ else
+ accept = false;
+
+ if( accept )
+ invalidateProjection( );
+ else
+ e->ignore( );
+}
+
+void PMGLView::slotAutoScroll( )
+{
+ if( m_bAutoScroll )
+ {
+ QTime now = QTime::currentTime( );
+ int msecs = m_lastAutoScrollUpdate.msecsTo( now );
+ int pixels = ( int ) ( m_autoScrollSpeed * msecs / 1000.0 );
+
+ if( pixels < 1 )
+ pixels = 1;
+ if( pixels > ( width( ) * 3 / 4 ) )
+ pixels = width( ) * 3 / 4;
+ if( pixels > ( height( ) * 3 / 4 ) )
+ pixels = height( ) * 3 / 4;
+
+ if( m_bGraphicalChangeMode && !m_bMementoCreated )
+ startChange( m_changeStartPos );
+ if( m_bMultipleSelectionMode )
+ restoreSelectionBox( );
+
+ m_dTransX += pixels * m_autoScrollDirectionX / m_dScale;
+ m_dTransY -= pixels * m_autoScrollDirectionY / m_dScale;
+ invalidateProjection( );
+
+ if( m_bGraphicalChangeMode )
+ if( m_bMultipleSelectionMode )
+ {
+ m_selectionStart += QPoint( pixels * m_autoScrollDirectionX,
+ pixels * m_autoScrollDirectionY );
+
+ saveSelectionBox( );
+ paintSelectionBox( );
+ }
+
+ if( m_bGraphicalChangeMode )
+ graphicalChange( mapFromGlobal( QCursor::pos( ) ) );
+ else
+ repaint( );
+
+ m_lastAutoScrollUpdate = now;
+ }
+}
+
+void PMGLView::slotMouseChangeTimer( )
+{
+ if( !m_bMementoCreated )
+ {
+ if( m_currentMousePos != m_changeStartPos )
+ {
+ startChange( m_changeStartPos );
+ graphicalChange( m_currentMousePos );
+ }
+ }
+}
+
+void PMGLView::startChange( const QPoint& mousePos )
+{
+ m_pActiveObject->createMemento( );
+ m_bMementoCreated = true;
+
+ PMVector p = mousePosition( m_pUnderMouse, mousePos.x( ), mousePos.y( ) );
+ p.transform( m_inversePointsTransformation );
+
+ if( m_pActiveObject->multipleSelectControlPoints( ) )
+ {
+ PMControlPointListIterator it( m_controlPoints );
+ for( ; it.current( ); ++it )
+ if( it.current( )->selected( ) )
+ it.current( )->startChange( p, m_normal );
+ }
+ else
+ m_pUnderMouse->startChange( p, m_normal );
+}
+
+void PMGLView::graphicalChange( const QPoint& mousePos )
+{
+ PMVector p = mousePosition( m_pUnderMouse, mousePos.x( ), mousePos.y( ) );
+ p.transform( m_inversePointsTransformation );
+ if( m_pActiveObject->multipleSelectControlPoints( ) )
+ {
+ PMControlPointListIterator it( m_controlPoints );
+ for( ; it.current( ); ++it )
+ if( it.current( )->selected( ) )
+ it.current( )->change( p );
+ }
+ else
+ m_pUnderMouse->change( p );
+
+ PMObjectList changedObjects;
+ m_pActiveObject->controlPointsChangedList( m_controlPoints, changedObjects );
+
+ if( changedObjects.isEmpty( ) )
+ emit objectChanged( m_pActiveObject, PMCGraphicalChange, this );
+ else
+ {
+ PMObjectListIterator it( changedObjects );
+ for( ; it.current( ); ++it )
+ emit objectChanged( it.current( ), PMCGraphicalChange, this );
+ }
+}
+
+void PMGLView::checkUnderMouse( int x, int y )
+{
+ // is cursor over a control point?
+ // double z;
+ PMVector* v;
+ PMControlPoint* p;
+ PMControlPoint* old = m_pUnderMouse;
+
+ if( m_bInverseValid && ( m_type != PMViewCamera ) )
+ {
+ m_pUnderMouse = 0;
+// z = -1e10;
+
+ v = m_controlPointsPosition.first( );
+ p = m_controlPoints.first( );
+
+ while( p )
+ {
+ if( p->displayType( ) == PMControlPoint::CPCross )
+ {
+ if( !m_pUnderMouse )
+ m_pUnderMouse = p;
+ }
+ else
+ {
+ if( ( fabs( x - (*v)[0] ) < ( controlPointSize / 2.0 + 0.1 ) )
+ && ( fabs( y - (*v)[1] ) < ( controlPointSize / 2.0 + 0.1 ) ) )
+ {
+ if( m_pUnderMouse )
+ {
+ if( p->selected( ) && !m_pUnderMouse->selected( ) )
+ m_pUnderMouse = p;
+ }
+ else
+ m_pUnderMouse = p;
+ }
+ }
+
+ p = m_controlPoints.next( );
+ v = m_controlPointsPosition.next( );
+ }
+ }
+ else
+ m_pUnderMouse = 0;
+
+ setCursor( m_pUnderMouse ? crossCursor : arrowCursor );
+ if( m_pUnderMouse != old )
+ {
+ if( m_pUnderMouse )
+ emit controlPointMessage( m_pUnderMouse->description( ) );
+ else
+ emit controlPointMessage( "" );
+ }
+}
+
+void PMGLView::updateControlPoints( )
+{
+ m_controlPoints.clear( );
+ m_controlPoints = m_pPart->activeControlPoints( );
+
+ if( ( m_controlPoints.count( ) > 0 ) && m_pActiveObject )
+ {
+ m_objectsTransformation = m_pActiveObject->transformedWith( );
+ recalculateTransformations( );
+ }
+
+ if( m_bGraphicalChangeMode )
+ m_bGraphicalChangeMode = false;
+
+ recalculateControlPointPosition( );
+}
+
+void PMGLView::recalculateControlPointPosition( )
+{
+ PMControlPointListIterator it( m_controlPoints );
+ m_controlPointsPosition.clear( );
+ PMVector* v;
+
+ for( ; it.current( ); ++it )
+ {
+ v = new PMVector( m_controlPointsTransformation * it.current( )->position( ) );
+ m_controlPointsPosition.append( v );
+ }
+ if( !m_bGraphicalChangeMode )
+ {
+ m_pUnderMouse = 0;
+ emit controlPointMessage( "" );
+ }
+}
+
+PMVector PMGLView::mousePosition( PMControlPoint* cp, int x, int y )
+{
+ PMVector result;
+ int index;
+ PMVector* p;
+
+ result[0] = screenToInternalX( x );
+ result[1] = screenToInternalY( y );
+ if( cp )
+ {
+ index = m_controlPoints.findRef( cp );
+ if( index >= 0 )
+ {
+ p = m_controlPointsPosition.at( ( uint ) index );
+ if( p )
+ result[2] = p->z( );
+ }
+ }
+ return result;
+}
+
+void PMGLView::recalculateTransformations( )
+{
+ int r, c;
+
+ m_controlPointsTransformation = m_viewTransformation * m_objectsTransformation;
+
+ if( m_controlPointsTransformation.canBuildInverse( ) )
+ {
+ m_inversePointsTransformation = m_controlPointsTransformation.inverse( );
+
+ for( c = 0; c < 4; c++ )
+ for( r = 0; r < 4; r++ )
+ if( fabs( m_inversePointsTransformation[c][r] ) < 1e-8 )
+ m_inversePointsTransformation[c][r] = 0.0;
+
+ m_bInverseValid = true;
+ }
+ else
+ m_bInverseValid = false;
+}
+
+void PMGLView::setType( PMViewType t )
+{
+ if( m_type != t )
+ m_viewTransformation = PMMatrix::identity( );
+ m_type = t;
+ invalidateProjection( );
+
+ emit viewTypeChanged( viewTypeAsString( t ) );
+}
+
+void PMGLView::setCamera( PMCamera* c )
+{
+ m_pCamera = c;
+ invalidateProjection( );
+}
+
+void PMGLView::slotRefresh( )
+{
+ if( m_type == PMViewCamera )
+ if( !m_pCamera )
+ setCamera( m_pPart->firstCamera( ) );
+
+ repaint( );
+}
+
+void PMGLView::slotClear( )
+{
+ m_controlPointsPosition.clear( );
+ m_controlPoints.clear( );
+ m_pUnderMouse = 0;
+ m_pCamera = 0;
+ m_pActiveObject = 0;
+
+ slotStopRendering( );
+}
+
+void PMGLView::slotActiveRenderModeChanged( )
+{
+ if( ( m_type == PMViewCamera ) && m_pCamera )
+ invalidateProjection( );
+}
+
+void PMGLView::slotStopRendering( )
+{
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ rm->removeView( this );
+}
+
+void PMGLView::slotObjectChanged( PMObject* obj, const int mode,
+ QObject* sender )
+{
+ bool redraw = false;
+
+ if( mode & PMCNewSelection )
+ {
+ if( obj )
+ {
+ if( obj != m_pActiveObject )
+ {
+ m_pActiveObject = obj;
+ redraw = true;
+ }
+ }
+ else
+ {
+ m_pActiveObject = 0;
+ redraw = true;
+ }
+ }
+ if( mode & ( PMCSelected | PMCDeselected ) )
+ {
+ m_pActiveObject = 0;
+ redraw = true;
+ }
+ if( mode & ( PMCViewStructure | PMCGraphicalChange ) )
+ {
+ if( m_type == PMGLView::PMViewCamera )
+ {
+ if( obj->type( ) == "Camera" )
+ if( m_pCamera == ( PMCamera* ) obj )
+ invalidateProjection( );
+
+ if( obj->parent( ) )
+ if( obj->parent( )->type( ) == "Camera" )
+ if( m_pCamera == ( PMCamera* ) obj->parent( ) )
+ if( obj->hasTransformationMatrix( ) )
+ invalidateProjection( );
+ }
+
+ redraw = true;
+ }
+ if( mode & PMCNewControlPoints )
+ {
+ updateControlPoints( );
+ m_pActiveObject = m_pPart->activeObject( );
+ redraw = true;
+ }
+ if( mode & PMCControlPointSelection )
+ {
+ redraw = true;
+ }
+ if( mode & PMCDescription )
+ {
+ if( m_type == PMGLView::PMViewCamera && obj && obj == m_pCamera )
+ redraw = true;
+ }
+ if( mode & PMCAdd )
+ {
+ if( m_type == PMGLView::PMViewCamera )
+ {
+ if( obj->type( ) == "Camera" )
+ if( !m_pCamera )
+ setCamera( ( PMCamera* ) obj );
+ if( obj->parent( ) )
+ if( obj->parent( )->type( ) == "Camera" )
+ if( m_pCamera == ( PMCamera* ) obj->parent( ) )
+ if( obj->hasTransformationMatrix( ) )
+ invalidateProjection( );
+ }
+ redraw = true;
+ }
+
+ if( mode & PMCRemove )
+ {
+ if( obj->type( ) == "Camera" )
+ if( m_pCamera == ( PMCamera* ) obj )
+ setCamera( 0 );
+
+ if( m_type == PMGLView::PMViewCamera )
+ if( obj->parent( ) )
+ if( obj->parent( )->type( ) == "Camera" )
+ if( m_pCamera == ( PMCamera* ) obj->parent( ) )
+ if( obj->hasTransformationMatrix( ) )
+ invalidateProjection( );
+
+ redraw = true;
+ }
+
+ if( mode & PMCChildren )
+ redraw = true;
+
+ if( redraw )
+ repaint( sender == this );
+}
+
+void PMGLView::repaint( bool graphicalChange )
+{
+ if( isValid( ) )
+ {
+ PMObject* obj = m_pActiveObject;
+
+ if( obj )
+ obj = topLevelRenderingObject( obj );
+ else
+ {
+ const PMObjectList& selected = m_pPart->selectedObjects( );
+ PMObjectListIterator it( selected );
+ if( it.current( ) )
+ obj = topLevelRenderingObject( it.current( ) );
+
+ if( obj && ( obj->type( ) != "Scene" ) )
+ for( ++it; it.current( ) && obj; ++it )
+ if( topLevelRenderingObject( it.current( ) ) != obj )
+ obj = 0;
+ }
+
+ if( !obj )
+ obj = m_pPart->scene( );
+
+ if( obj )
+ {
+ double aspectRatio = 1.0;
+ PMRenderMode* mode = m_pPart->scene( )->renderModes( )->current( );
+ if( mode )
+ if( mode->height( ) != 0 )
+ aspectRatio = ( double ) mode->width( )
+ / ( double ) mode->height( );
+
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ rm->addView( this, m_pActiveObject, obj,
+ &m_controlPoints, aspectRatio,
+ m_pPart->scene( )->visibilityLevel( ), graphicalChange );
+ }
+ }
+}
+
+PMObject* PMGLView::topLevelRenderingObject( PMObject* o ) const
+{
+ PMObject* obj = o;
+ bool stop = false;
+
+ if( obj )
+ {
+ do
+ {
+ if( !obj )
+ stop = true;
+ else if( obj->isA( "Scene" ) || obj->isA( "Declare" ) )
+ stop = true;
+ else
+ obj = obj->parent( );
+ }
+ while( !stop );
+ }
+ else
+ obj = m_pPart->scene( );
+
+ return obj;
+}
+
+void PMGLView::selectControlPoint( PMControlPoint* cp, bool select, bool deselectOthers )
+{
+ bool selectionChanged = false;
+
+ if( cp )
+ {
+ if( deselectOthers )
+ {
+ PMControlPointListIterator it( m_controlPoints );
+ for( ; it.current( ); ++it )
+ {
+ bool s;
+ if( it.current( ) == cp )
+ s = select;
+ else
+ s = false;
+
+ if( s != it.current( )->selected( ) )
+ {
+ selectionChanged = true;
+ it.current( )->setSelected( s );
+ }
+ }
+ }
+ else
+ {
+ if( select != cp->selected( ) )
+ {
+ selectionChanged = true;
+ cp->setSelected( select );
+ }
+ }
+ }
+ else
+ {
+ PMControlPointListIterator it( m_controlPoints );
+ for( ; it.current( ); ++it )
+ {
+ if( select != it.current( )->selected( ) )
+ {
+ selectionChanged = true;
+ it.current( )->setSelected( select );
+ }
+ }
+ }
+
+ if( selectionChanged )
+ emit objectChanged( m_pActiveObject, PMCControlPointSelection, this );
+}
+
+void PMGLView::startSelection( )
+{
+ if( !m_bSelectionStarted )
+ {
+ saveSelectionBox( );
+ paintSelectionBox( );
+
+ m_bSelectionStarted = true;
+ }
+}
+
+void PMGLView::restoreSelectionBox( )
+{
+ if( !m_bAboutToUpdate )
+ {
+ int sx, sy, ex, ey, w, h;
+ calculateSelectionBox( sx, sy, ex, ey, w, h );
+
+ if( !m_selectionPixmap[0].isNull( ) )
+ bitBlt( this, sx, sy, &( m_selectionPixmap[0] ), 0, 0, w, 1, CopyROP );
+ if( !m_selectionPixmap[1].isNull( ) )
+ bitBlt( this, sx, ey, &( m_selectionPixmap[1] ), 0, 0, w, 1, CopyROP );
+ if( !m_selectionPixmap[2].isNull( ) )
+ bitBlt( this, sx, sy+1, &( m_selectionPixmap[2] ), 0, 0, 1, h-2, CopyROP );
+ if( !m_selectionPixmap[3].isNull( ) )
+ bitBlt( this, ex, sy+1, &( m_selectionPixmap[3] ), 0, 0, 1, h-2, CopyROP );
+ }
+}
+
+void PMGLView::saveSelectionBox( )
+{
+ if( !m_bAboutToUpdate )
+ {
+ int sx, sy, ex, ey, w, h;
+ calculateSelectionBox( sx, sy, ex, ey, w, h );
+
+ m_selectionPixmap[0].resize( w, 1 );
+ if( !m_selectionPixmap[0].isNull( ) )
+ bitBlt( &( m_selectionPixmap[0] ), 0, 0, this, sx, sy, w, 1, CopyROP );
+ m_selectionPixmap[1].resize( w, 1 );
+ if( !m_selectionPixmap[1].isNull( ) )
+ bitBlt( &( m_selectionPixmap[1] ), 0, 0, this, sx, ey, w, 1, CopyROP );
+
+ m_selectionPixmap[2].resize( 1, h-2 );
+ if( !m_selectionPixmap[2].isNull( ) )
+ bitBlt( &( m_selectionPixmap[2] ), 0, 0, this, sx, sy+1, 1, h-2, CopyROP );
+ m_selectionPixmap[3].resize( 1, h-2 );
+ if( !m_selectionPixmap[3].isNull( ) )
+ bitBlt( &( m_selectionPixmap[3] ), 0, 0, this, ex, sy+1, 1, h-2, CopyROP );
+ }
+}
+
+void PMGLView::paintSelectionBox( )
+{
+ if( !m_bAboutToUpdate )
+ {
+ int sx, sy, ex, ey, w, h;
+ calculateSelectionBox( sx, sy, ex, ey, w, h );
+ QPainter p;
+ p.begin( this );
+ p.setPen( PMRenderManager::theManager( )->controlPointColor( 1 ) );
+ p.drawRect( sx, sy, w, h );
+ p.end( );
+ }
+}
+
+void PMGLView::calculateSelectionBox( int& sx, int& sy, int& ex, int& ey,
+ int& w, int& h )
+{
+ if( m_selectionStart.x( ) < m_selectionEnd.x( ) )
+ {
+ sx = m_selectionStart.x( );
+ ex = m_selectionEnd.x( );
+ }
+ else
+ {
+ ex = m_selectionStart.x( );
+ sx = m_selectionEnd.x( );
+ }
+
+ if( m_selectionStart.y( ) < m_selectionEnd.y( ) )
+ {
+ sy = m_selectionStart.y( );
+ ey = m_selectionEnd.y( );
+ }
+ else
+ {
+ ey = m_selectionStart.y( );
+ sy = m_selectionEnd.y( );
+ }
+
+ w = ex - sx + 1;
+ h = ey - sy + 1;
+}
+
+double PMGLView::screenToInternalX( int x ) const
+{
+ return rint( x - width( ) / 2.0 + 0.1 );
+}
+
+double PMGLView::screenToInternalY( int y ) const
+{
+ return rint( height( ) / 2.0 - y - 0.1 );
+}
+
+void PMGLView::slotRenderingStarted( PMGLView* )
+{
+}
+
+void PMGLView::slotAboutToUpdate( PMGLView* view )
+{
+ if( view == this )
+ m_bAboutToUpdate = true;
+}
+
+void PMGLView::slotRenderingFinished( PMGLView* view )
+{
+ if( view == this )
+ {
+ m_bAboutToUpdate = false;
+ if( m_bMultipleSelectionMode )
+ {
+ saveSelectionBox( );
+ paintSelectionBox( );
+ }
+
+ if( m_bAutoScroll )
+ {
+ QTime now = QTime::currentTime( );
+ int msecs = m_lastAutoScrollUpdate.msecsTo( now );
+
+ if( msecs < c_minAutoScrollUpdateTime )
+ m_autoScrollTimer.start( c_minAutoScrollUpdateTime - msecs, true );
+ else
+ m_autoScrollTimer.start( 0, true );
+ }
+ }
+}
+
+QString PMGLView::viewTypeAsString( PMViewType t )
+{
+ QString str;
+
+ switch( t )
+ {
+ case PMViewPosX:
+ str = i18n( "Left" );
+ break;
+ case PMViewNegX:
+ str = i18n( "Right" );
+ break;
+ case PMViewPosY:
+ str = i18n( "Bottom" );
+ break;
+ case PMViewNegY:
+ str = i18n( "Top" );
+ break;
+ case PMViewPosZ:
+ str = i18n( "Front" );
+ break;
+ case PMViewNegZ:
+ str = i18n( "Back" );
+ break;
+ case PMViewCamera:
+ str = i18n( "Camera" );
+ break;
+ }
+ return str;
+}
+
+void PMGLView::saveConfig( KConfig* /*cfg*/ )
+{
+}
+
+void PMGLView::restoreConfig( KConfig* /*cfg*/ )
+{
+}
+
+void PMGLView::contextMenu( )
+{
+ QPopupMenu* m = new QPopupMenu( );
+ m->insertItem( i18n( "Left View" ), this, SLOT( slotSetTypePosX( ) ) );
+ m->insertItem( i18n( "Right View" ), this, SLOT( slotSetTypeNegX( ) ) );
+ m->insertItem( i18n( "Top View" ), this, SLOT( slotSetTypeNegY( ) ) );
+ m->insertItem( i18n( "Bottom View" ), this, SLOT( slotSetTypePosY( ) ) );
+ m->insertItem( i18n( "Front View" ), this, SLOT( slotSetTypePosZ( ) ) );
+ m->insertItem( i18n( "Back View" ), this, SLOT( slotSetTypeNegZ( ) ) );
+
+ QPopupMenu* cm = new QPopupMenu( m );
+ QPtrListIterator<PMCamera> it = m_pPart->cameras( );
+ QString name;
+ if( !it.current( ) )
+ cm->insertItem( i18n( "No Cameras" ) );
+ else
+ {
+ int cnr = 0;
+ for( ; it.current( ); ++it, ++cnr )
+ {
+ name = it.current( )->name( );
+ if( name.isEmpty( ) )
+ name = i18n( "(unnamed)" );
+ cm->insertItem( name, cnr );
+ }
+ }
+ connect( cm, SIGNAL( activated( int ) ), SLOT( slotCameraView( int ) ) );
+
+ m->insertItem( SmallIconSet( "pmcamera" ), i18n( "Camera" ), cm );
+
+ m->insertSeparator( );
+
+ m->insertItem( i18n( "Snap to Grid" ), this, SLOT( slotSnapToGrid( ) ) );
+ m_objectActions.clear( );
+ if( m_pActiveObject )
+ {
+ m_pActiveObject->addObjectActions( m_controlPoints, m_objectActions );
+ if( !m_objectActions.isEmpty( ) )
+ {
+ PMObjectAction* oa = 0;
+ QPtrListIterator<PMObjectAction> ait( m_objectActions );
+
+ for( ; ait.current( ); ++ait )
+ {
+ oa = ait.current( );
+ oa->setMenuID( m->insertItem( oa->description( ) ) );
+ }
+ }
+ }
+ connect( m, SIGNAL( activated( int ) ), SLOT( slotObjectAction( int ) ) );
+
+ m->insertSeparator( );
+
+ QPopupMenu* menu = new QPopupMenu( m );
+ PMControlPointListIterator pit( m_controlPoints );
+
+ if( !pit.current( ) )
+ menu->insertItem( i18n( "No Control Points" ) );
+ else
+ {
+ int cnr = 0;
+ for( ; pit.current( ); ++pit, ++cnr )
+ menu->insertItem( pit.current( )->description( ), cnr );
+ }
+ connect( menu, SIGNAL( activated( int ) ), SLOT( slotControlPoint( int ) ) );
+
+ m->insertItem( i18n( "Control Points" ), menu );
+
+ m->exec( QCursor::pos( ) );
+ delete m;
+}
+
+void PMGLView::slotCameraView( int id )
+{
+ int i;
+ QPtrListIterator<PMCamera> it = m_pPart->cameras( );
+
+ for( i = 0; i < id; i++ )
+ ++it;
+ if( it.current( ) )
+ {
+ setCamera( it.current( ) );
+ setType( PMGLView::PMViewCamera );
+ }
+}
+
+void PMGLView::slotObjectAction( int id )
+{
+ QPtrListIterator<PMObjectAction> it( m_objectActions );
+ PMObjectAction* oa = 0;
+
+ for( ; it.current( ) && !oa; ++it )
+ if( it.current( )->menuID( ) == id )
+ oa = it.current( );
+
+ if( oa && m_pActiveObject )
+ {
+ // otherwise no object action was selected in the context menu
+
+ m_pActiveObject->createMemento( );
+ m_pActiveObject->objectActionCalled( oa, m_controlPoints,
+ m_controlPointsPosition,
+ m_contextClickPosition );
+ PMDataChangeCommand* cmd;
+ cmd = new PMDataChangeCommand( m_pActiveObject->takeMemento( ) );
+ cmd->setText( oa->description( ) );
+ m_pPart->executeCommand( cmd );
+ }
+}
+
+void PMGLView::slotControlPoint( int id )
+{
+ PMControlPoint* p = m_controlPoints.at( id );
+ if( p )
+ {
+ PMControlPointListIterator cit( m_controlPoints );
+ for( ; cit.current( ); ++cit )
+ cit.current( )->setSelected( p == cit.current( ) );
+ emit objectChanged( m_pActiveObject, PMCControlPointSelection, this );
+ }
+}
+
+void PMGLView::slotSnapToGrid( )
+{
+ if( m_pActiveObject )
+ {
+ if( !m_pActiveObject->mementoCreated( ) )
+ m_pActiveObject->createMemento( );
+
+ PMControlPointListIterator it( m_controlPoints );
+ for( ; it.current( ); ++it )
+ if( it.current( )->selected( ) )
+ it.current( )->snapToGrid( );
+
+ m_pActiveObject->controlPointsChanged( m_controlPoints );
+
+ PMDataChangeCommand* cmd;
+ cmd = new PMDataChangeCommand( m_pActiveObject->takeMemento( ) );
+ cmd->setText( i18n( "Snap to Grid" ) );
+ m_pPart->executeCommand( cmd );
+ }
+}
+
+QString PMGLView::description( ) const
+{
+ return viewTypeAsString( m_type );
+}
+
+void PMGLView::restoreViewConfig( PMViewOptions* vo )
+{
+ if( vo && vo->viewType( ) == "glview" )
+ {
+ PMGLViewOptions* o = ( PMGLViewOptions* ) vo;
+ m_type = o->glViewType( );
+ }
+}
+
+void PMGLView::saveViewConfig( PMViewOptions* vo ) const
+{
+ if( vo && vo->viewType( ) == "glview" )
+ {
+ PMGLViewOptions* o = ( PMGLViewOptions* ) vo;
+ o->setGLViewType( m_type );
+ }
+}
+
+void PMGLViewOptions::loadData( QDomElement& e )
+{
+ QString s = e.attribute( "type", "Camera" );
+ if( s == "Camera" ) m_glViewType = PMGLView::PMViewCamera;
+ else if( s == "X" ) m_glViewType = PMGLView::PMViewPosX;
+ else if( s == "Y" ) m_glViewType = PMGLView::PMViewPosY;
+ else if( s == "Z" ) m_glViewType = PMGLView::PMViewPosZ;
+ else if( s == "NegX" ) m_glViewType = PMGLView::PMViewNegX;
+ else if( s == "NegY" ) m_glViewType = PMGLView::PMViewNegY;
+ else if( s == "NegZ" ) m_glViewType = PMGLView::PMViewNegZ;
+}
+
+void PMGLViewOptions::saveData( QDomElement& e )
+{
+ switch( m_glViewType )
+ {
+ case PMGLView::PMViewCamera:
+ e.setAttribute( "type", "Camera" );
+ break;
+ case PMGLView::PMViewPosX:
+ e.setAttribute( "type", "X" );
+ break;
+ case PMGLView::PMViewPosY:
+ e.setAttribute( "type", "Y" );
+ break;
+ case PMGLView::PMViewPosZ:
+ e.setAttribute( "type", "Z" );
+ break;
+ case PMGLView::PMViewNegX:
+ e.setAttribute( "type", "NegX" );
+ break;
+ case PMGLView::PMViewNegY:
+ e.setAttribute( "type", "NegY" );
+ break;
+ case PMGLView::PMViewNegZ:
+ e.setAttribute( "type", "NegZ" );
+ break;
+ default:
+ kdError( PMArea ) << i18n( "Unknown GL view type." )
+ << endl;
+ break;
+ }
+}
+
+QString PMGLViewFactory::description( ) const
+{
+ return i18n( "3D View" );
+}
+
+QString PMGLViewFactory::description( PMViewOptions* vo ) const
+{
+ if( vo && vo->viewType( ) == "glview" )
+ {
+ PMGLViewOptions* o = ( PMGLViewOptions* ) vo;
+ return i18n( "3D View (%1)" ).arg(
+ PMGLView::viewTypeAsString( o->glViewType( ) ) );
+ }
+ return description( );
+}
+
+PMViewOptionsWidget* PMGLViewFactory::newOptionsWidget( QWidget* parent,
+ PMViewOptions* o )
+{
+ return new PMGLViewOptionsWidget( parent, o );
+}
+
+PMViewOptions* PMGLViewFactory::newOptionsInstance( ) const
+{
+ PMGLViewOptions* o = new PMGLViewOptions( );
+ return o;
+}
+
+PMGLViewOptionsWidget::PMGLViewOptionsWidget( QWidget* parent,
+ PMViewOptions* o )
+ : PMViewOptionsWidget( parent )
+{
+ m_pOptions = ( PMGLViewOptions* ) o;
+
+ QHBoxLayout* hl = new QHBoxLayout( this, 0, KDialog::spacingHint( ) );
+ QLabel* l = new QLabel( i18n( "3D view type:" ), this );
+ hl->addWidget( l );
+
+ m_pGLViewType = new QComboBox( false, this );
+ m_pGLViewType->insertItem( i18n( "Top" ) );
+ m_pGLViewType->insertItem( i18n( "Bottom" ) );
+ m_pGLViewType->insertItem( i18n( "Left" ) );
+ m_pGLViewType->insertItem( i18n( "Right" ) );
+ m_pGLViewType->insertItem( i18n( "Front" ) );
+ m_pGLViewType->insertItem( i18n( "Back" ) );
+ m_pGLViewType->insertItem( i18n( "Camera" ) );
+
+ switch( m_pOptions->glViewType( ) )
+ {
+ case PMGLView::PMViewNegY:
+ m_pGLViewType->setCurrentItem( 0 );
+ break;
+ case PMGLView::PMViewPosY:
+ m_pGLViewType->setCurrentItem( 1 );
+ break;
+ case PMGLView::PMViewPosX:
+ m_pGLViewType->setCurrentItem( 2 );
+ break;
+ case PMGLView::PMViewNegX:
+ m_pGLViewType->setCurrentItem( 3 );
+ break;
+ case PMGLView::PMViewPosZ:
+ m_pGLViewType->setCurrentItem( 4 );
+ break;
+ case PMGLView::PMViewNegZ:
+ m_pGLViewType->setCurrentItem( 5 );
+ break;
+ case PMGLView::PMViewCamera:
+ m_pGLViewType->setCurrentItem( 6 );
+ break;
+ }
+
+ connect( m_pGLViewType, SIGNAL( activated( int ) ),
+ SLOT( slotGLViewTypeChanged( int ) ) );
+ hl->addWidget( m_pGLViewType );
+}
+
+void PMGLViewOptionsWidget::slotGLViewTypeChanged( int index )
+{
+ switch( index )
+ {
+ case 0:
+ m_pOptions->setGLViewType( PMGLView::PMViewNegY );
+ break;
+ case 1:
+ m_pOptions->setGLViewType( PMGLView::PMViewPosY );
+ break;
+ case 2:
+ m_pOptions->setGLViewType( PMGLView::PMViewPosX );
+ break;
+ case 3:
+ m_pOptions->setGLViewType( PMGLView::PMViewNegX );
+ break;
+ case 4:
+ m_pOptions->setGLViewType( PMGLView::PMViewPosZ );
+ break;
+ case 5:
+ m_pOptions->setGLViewType( PMGLView::PMViewNegZ );
+ break;
+ case 6:
+ m_pOptions->setGLViewType( PMGLView::PMViewCamera );
+ break;
+ }
+ emit viewTypeDescriptionChanged( );
+}
+
+#include "pmglview.moc"
diff --git a/kpovmodeler/pmglview.h b/kpovmodeler/pmglview.h
new file mode 100644
index 00000000..b33eeb2b
--- /dev/null
+++ b/kpovmodeler/pmglview.h
@@ -0,0 +1,589 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMGLVIEW_H
+#define PMGLVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qpoint.h>
+#include <qdatetime.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+
+#include "pmviewbase.h"
+#include "pmviewfactory.h"
+#include "pmcontrolpoint.h"
+#include "pmvector.h"
+#include "pmmatrix.h"
+#include "pmobjectaction.h"
+
+const int controlPointSize = 7;
+
+class PMObject;
+class PMPart;
+class PMCamera;
+class KConfig;
+class QComboBox;
+
+/**
+ * Widget for rendering the scene with OpenGL
+ */
+class PMGLView : public PMViewBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Type of the view
+ */
+ enum PMViewType { PMViewPosX, PMViewNegX, PMViewPosY, PMViewNegY,
+ PMViewPosZ, PMViewNegZ, PMViewCamera };
+ /**
+ * Constructor
+ */
+ PMGLView( PMPart* part, PMViewType t,
+ QWidget* parent = 0, const char* name = 0, WFlags f = 0 );
+ /**
+ * Destructor
+ */
+ ~PMGLView( );
+
+ /** */
+ virtual QString viewType( ) const { return QString( "glview" ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual void restoreViewConfig( PMViewOptions* );
+ /** */
+ virtual void saveViewConfig( PMViewOptions* ) const;
+
+ /**
+ * Enables/disables translating the view with the mouse
+ */
+ void enableTranslateMode( bool yes = true );
+ /**
+ * Enables/disables scaling the view with the mouse
+ */
+ void enableScaleMode( bool yes = true );
+
+ /**
+ * Returns true if the opengl projection is up to date
+ */
+ bool isProjectionUpToDate( ) const { return m_projectionUpToDate; }
+ /**
+ * Sets the projection up to date flag
+ */
+ void setProjectionUpToDate( bool yes ) { m_projectionUpToDate = yes; }
+
+ /**
+ * Sets the scale
+ */
+ void setScale( double scale );
+ /**
+ * Returns the scale
+ */
+ double scale( ) const { return m_dScale; }
+ /**
+ * Sets the views translation in x direction
+ */
+ void setTranslationX( double d );
+ /**
+ * Returns the views translation in x direction
+ */
+ double translationX( ) const { return m_dTransX; }
+ /**
+ * Sets the views translation in y direction
+ */
+ void setTranslationY( double d );
+ /**
+ * Returns the views translation in y direction
+ */
+ double translationY( ) const { return m_dTransY; }
+
+ /**
+ * Returns the 2D control points position in the view
+ */
+ const QPtrList<PMVector>& controlPointsPosition( ) const
+ {
+ return m_controlPointsPosition;
+ }
+ /**
+ * Returns the last right mouse click position
+ */
+ PMVector contextClickPosition( ) const { return m_contextClickPosition; }
+
+ /**
+ * Returns the view type
+ */
+ PMViewType type( ) const { return m_type; }
+ /**
+ * Sets the view type
+ */
+ void setType( PMViewType t );
+ /**
+ * Sets the camera
+ */
+ void setCamera( PMCamera* c );
+ /**
+ * Returns the camera
+ */
+ PMCamera* camera( ) const { return m_pCamera; }
+
+ /**
+ * Saves the configuration
+ */
+ static void saveConfig( KConfig* cfg );
+ /**
+ * Restores the configuration
+ */
+ static void restoreConfig( KConfig* cfg );
+
+ /**
+ * Returns true if the glx stuff was initialized successfully
+ */
+ bool isValid( ) const;
+ /**
+ * Sets this view as the current rendering view
+ */
+ void makeCurrent( );
+ /**
+ * Swaps the opengl buffers
+ */
+ void swapBuffers( );
+
+ /**
+ * Returns the view type as string
+ */
+ static QString viewTypeAsString( PMViewType t );
+ /**
+ * Sets the direct rendering flag
+ */
+ static void enableDirectRendering( bool yes ) { s_bDirect = yes; }
+ /**
+ * Returns the direct rendering flag
+ */
+ static bool isDirectRenderingEnabled( ) { return s_bDirect; }
+public slots:
+ /**
+ * Sets the view normal vector to the positive x-axes
+ */
+ void slotSetTypePosX( ) { setType( PMViewPosX ); }
+ /**
+ * Sets the view normal vector to the negative x-axes
+ */
+ void slotSetTypeNegX( ) { setType( PMViewNegX ); }
+ /**
+ * Sets the view normal vector to the positive y-axes
+ */
+ void slotSetTypePosY( ) { setType( PMViewPosY ); }
+ /**
+ * Sets the view normal vector to the negative y-axes
+ */
+ void slotSetTypeNegY( ) { setType( PMViewNegY ); }
+ /**
+ * Sets the view normal vector to the positive z-axes
+ */
+ void slotSetTypePosZ( ) { setType( PMViewPosZ ); }
+ /**
+ * Sets the view normal vector to the negative z-axes
+ */
+ void slotSetTypeNegZ( ) { setType( PMViewNegZ ); }
+
+ /**
+ * Called when an object is changed.
+ * @see PMPart::objectChanged( )
+ */
+ void slotObjectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Restarts rendering
+ */
+ void slotRefresh( );
+ /**
+ * Clears all data
+ */
+ void slotClear( );
+ /**
+ * Stops rendering
+ */
+ void slotStopRendering( );
+ /**
+ * Repaints the view if it is a camera view
+ */
+ void slotActiveRenderModeChanged( );
+
+ /**
+ * Connected to the render manager
+ */
+ void slotRenderingStarted( PMGLView* view );
+ /**
+ * Connected to the render manager
+ */
+ void slotAboutToUpdate( PMGLView* view );
+ /**
+ * Connected to the render manager
+ */
+ void slotRenderingFinished( PMGLView* view );
+
+protected slots:
+ /**
+ * Sets the view type to camera view
+ */
+ void slotCameraView( int id );
+ /**
+ * Called when an object action was selected in the context menu
+ */
+ void slotObjectAction( int id );
+ /**
+ * Called when a control point was selected in the context menu
+ */
+ void slotControlPoint( int id );
+ /**
+ * Aligns the selected control points to the grid
+ */
+ void slotSnapToGrid( );
+
+ void slotMouseChangeTimer( );
+ void slotAutoScroll( );
+
+signals:
+ /**
+ * Emitted when rendering has to be restarted
+ */
+ void refresh( PMGLView* w );
+ /**
+ * Emitted when an object is changed
+ */
+ void objectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Emitted when the mouse is over a control point
+ */
+ void controlPointMessage( const QString& msg );
+ /**
+ * Emitted in the destructor
+ */
+ void destroyed( PMGLView* v );
+ /**
+ * Emitted when the view type changes
+ */
+ void viewTypeChanged( const QString& str );
+
+protected:
+ /**
+ * Initializes the glx stuff
+ */
+ virtual void initializeGL( );
+ /** */
+ virtual void resizeEvent( QResizeEvent* e );
+ /** */
+ virtual void paintEvent( QPaintEvent* e );
+ /** */
+ virtual void mousePressEvent( QMouseEvent* e );
+ /** */
+ virtual void mouseReleaseEvent( QMouseEvent* e );
+ /** */
+ virtual void mouseMoveEvent( QMouseEvent* e );
+ /** */
+ virtual void keyPressEvent( QKeyEvent* e );
+ /**
+ * Event to zoom in / zoom out the viewport by mouse wheel
+ */
+ virtual void wheelEvent( QWheelEvent* e );
+
+private:
+ /**
+ * Updates the control points
+ */
+ void updateControlPoints( );
+ /**
+ * Recalculates the position of the control points on the screen
+ */
+ void recalculateControlPointPosition( );
+ /**
+ * Recalculates m_controlPointsTransformation and
+ * m_inversePointsTransformation
+ */
+ void recalculateTransformations( );
+ /**
+ * Returns the mouse 3D position, when the control point cp is selected
+ *
+ * x and y are the screen coordinates of the mouse.
+ */
+ PMVector mousePosition( PMControlPoint* cp, int x, int y );
+ /**
+ * Checks if a control point is under the mouse
+ */
+ void checkUnderMouse( int x, int y );
+ /**
+ * Repaints the view
+ */
+ void repaint( bool graphicalChange = false );
+ /**
+ * Starts a graphical change
+ */
+ void startChange( const QPoint& mousePos );
+ /**
+ * Graphical Change
+ */
+ void graphicalChange( const QPoint& mousePos );
+ /**
+ * Selects/deselecs the control point. If cp is 0, all control points are
+ * selected/deselected.
+ */
+ void selectControlPoint( PMControlPoint* cp, bool select, bool deselectOthers = true );
+ /**
+ * Invalidates the projection and repaints the view
+ */
+ void invalidateProjection( bool graphicaChange = false );
+
+ /**
+ * Starts multiple selection mode
+ */
+ void startSelection( );
+ /**
+ * Restores the widget under the selection rect
+ */
+ void restoreSelectionBox( );
+ /**
+ * Saves the widget under the selection rect
+ */
+ void saveSelectionBox( );
+ /**
+ * Paints the selection box
+ */
+ void paintSelectionBox( );
+ /**
+ * Calculates the selection box
+ */
+ void calculateSelectionBox( int& sx, int& sy, int& ex, int& ey, int& w, int& h );
+
+ double screenToInternalX( int x ) const;
+ double screenToInternalY( int y ) const;
+
+ /**
+ * Returns the top level object for rendering (a declaration or the scene)
+ */
+ PMObject* topLevelRenderingObject( PMObject* obj ) const;
+ /**
+ * Displays the context menu
+ */
+ void contextMenu( );
+
+ /**
+ * Type of the view (camera, xy, ... )
+ */
+ PMViewType m_type;
+ /**
+ * Pointer to the part
+ */
+ PMPart* m_pPart;
+ /**
+ * True if "scale view" is active
+ */
+ bool m_bScaleMode;
+ double m_scaleIntX, m_scaleIntY;
+ /**
+ * true if "translate view" is active
+ */
+ bool m_bTranslateMode;
+ /**
+ * True if "scale view" or "translate view" is active and the left
+ * mouse button is pressed.
+ */
+ bool m_bMousePressed;
+ /**
+ * MidButton pressed
+ */
+ bool m_bMidMousePressed;
+ /**
+ * True if a graphical change is active
+ */
+ bool m_bGraphicalChangeMode;
+ bool m_bMementoCreated;
+ /**
+ * The old mouse position
+ */
+ QPoint m_mousePos;
+ QPoint m_changeStartPos;
+ QPoint m_currentMousePos;
+ QTimer m_startTimer;
+ QTime m_changeStartTime;
+ bool m_bDeselectUnderMouse;
+ bool m_bSelectUnderMouse;
+
+ /**
+ * Member variables for multiple selection mode
+ */
+ QPixmap m_selectionPixmap[4];
+ QPoint m_selectionStart, m_selectionEnd;
+ bool m_bMultipleSelectionMode;
+ bool m_bSelectionStarted;
+
+ /**
+ * Member variables for autoscroll
+ */
+ bool m_bAutoScroll;
+ double m_autoScrollSpeed;
+ QTimer m_autoScrollTimer;
+ QTime m_lastAutoScrollUpdate;
+ int m_autoScrollDirectionX, m_autoScrollDirectionY;
+ /**
+ * Rendering
+ */
+ bool m_bAboutToUpdate;
+
+ /**
+ * Scale of the view
+ */
+ double m_dScale;
+ /**
+ * X-translation of the view
+ */
+ double m_dTransX;
+ /**
+ * Y-translation of the view
+ */
+ double m_dTransY;
+
+ /**
+ * Control points of the active object
+ */
+ PMControlPointList m_controlPoints;
+ /**
+ * Control point under the mouse
+ */
+ PMControlPoint* m_pUnderMouse;
+ /**
+ * Position of the control points on the screen
+ */
+ QPtrList<PMVector> m_controlPointsPosition;
+ /**
+ * Position of the last right mouse click
+ */
+ PMVector m_contextClickPosition;
+ /**
+ * Transformation of the control points
+ *
+ * Always m_viewTransformation * m_objectsTransformation.
+ */
+ PMMatrix m_controlPointsTransformation;
+ /**
+ * Inverse of m_controlPointsTransformation
+ */
+ PMMatrix m_inversePointsTransformation;
+ /**
+ * True if m_inversePointsTransformation is valid
+ */
+ bool m_bInverseValid;
+ /**
+ * Normal vector of the view
+ */
+ PMVector m_normal;
+ /**
+ * Transformation of the view (scale and translation)
+ */
+ PMMatrix m_viewTransformation;
+ /**
+ * Transformation of the active object
+ */
+ PMMatrix m_objectsTransformation;
+ /**
+ * The camera
+ */
+ PMCamera* m_pCamera;
+ PMObject* m_pActiveObject;
+ /**
+ * true if the opengl projection is up to date
+ */
+ bool m_projectionUpToDate;
+ int m_visibilityLevel;
+ /**
+ * The current object actions
+ */
+ QPtrList<PMObjectAction> m_objectActions;
+ static bool s_bDirect;
+};
+
+/**
+ * Options class for the opengl view
+ */
+class PMGLViewOptions : public PMViewOptions
+{
+public:
+ PMGLViewOptions( )
+ {
+ m_glViewType = PMGLView::PMViewPosX;
+ }
+ PMGLViewOptions( PMGLView::PMViewType t )
+ {
+ m_glViewType = t;
+ }
+ virtual PMViewOptions* copy( ) const { return new PMGLViewOptions( *this ); }
+ virtual QString viewType( ) const { return QString( "glview" ); }
+ PMGLView::PMViewType glViewType( ) const { return m_glViewType; }
+ void setGLViewType( PMGLView::PMViewType t ) { m_glViewType = t; }
+ virtual void loadData( QDomElement& e );
+ virtual void saveData( QDomElement& e );
+
+private:
+ PMGLView::PMViewType m_glViewType;
+};
+
+/**
+ * Factory class for 3d views
+ */
+class PMGLViewFactory : public PMViewTypeFactory
+{
+public:
+ PMGLViewFactory( ) { }
+ virtual QString viewType( ) const { return QString( "glview" ); }
+ virtual QString description( ) const;
+ virtual QString description( PMViewOptions* ) const;
+ virtual QString iconName( ) const { return QString( "pmglview" ); }
+ virtual PMViewBase* newInstance( QWidget* parent, PMPart* part ) const
+ {
+ return new PMGLView( part, PMGLView::PMViewPosX, parent );
+ }
+ virtual PMViewOptions* newOptionsInstance( ) const;
+ virtual PMViewOptionsWidget* newOptionsWidget( QWidget*, PMViewOptions* );
+};
+
+/**
+ * Configuration widget for the view layout settings dialog
+ */
+class PMGLViewOptionsWidget : public PMViewOptionsWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMGLViewOptionsWidget( QWidget* parent, PMViewOptions* o );
+
+protected slots:
+ void slotGLViewTypeChanged( int );
+
+private:
+ PMGLViewOptions* m_pOptions;
+ QComboBox* m_pGLViewType;
+};
+
+#endif
diff --git a/kpovmodeler/pmgraphicalobject.cpp b/kpovmodeler/pmgraphicalobject.cpp
new file mode 100644
index 00000000..85f4ad22
--- /dev/null
+++ b/kpovmodeler/pmgraphicalobject.cpp
@@ -0,0 +1,248 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmgraphicalobject.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+
+const bool c_defaultNoShadow = false;
+const bool c_defaultNoImage = false;
+const bool c_defaultNoReflection = false;
+const bool c_defaultDoubleIlluminate = false;
+const int c_defaultVisibilityLevel = 0;
+const bool c_defaultRelativeVisibility = true;
+const bool c_defaultExport = true;
+
+PMDefinePropertyClass( PMGraphicalObject, PMGraphicalObjectProperty );
+
+PMMetaObject* PMGraphicalObject::s_pMetaObject = 0;
+
+PMGraphicalObject::PMGraphicalObject( PMPart* part )
+ : Base( part )
+{
+ m_noShadow = c_defaultNoShadow;
+ m_noImage = c_defaultNoImage;
+ m_noReflection = c_defaultNoReflection;
+ m_doubleIlluminate = c_defaultDoubleIlluminate;
+ m_visibilityLevel = c_defaultVisibilityLevel;
+ m_relativeVisibility = c_defaultRelativeVisibility;
+ m_export = c_defaultExport;
+}
+
+PMGraphicalObject::PMGraphicalObject( const PMGraphicalObject& o )
+ : Base( o )
+{
+ m_noShadow = o.m_noShadow;
+ m_noImage = o.m_noImage;
+ m_noReflection = o.m_noReflection;
+ m_doubleIlluminate = o.m_doubleIlluminate;
+ m_visibilityLevel = o.m_visibilityLevel;
+ m_relativeVisibility = o.m_relativeVisibility;
+ m_export = o.m_export;
+}
+
+PMGraphicalObject::~PMGraphicalObject( )
+{
+}
+
+PMMetaObject* PMGraphicalObject::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "GraphicalObject", Base::metaObject( ) );
+ s_pMetaObject->addProperty(
+ new PMGraphicalObjectProperty( "noShadow", &PMGraphicalObject::setNoShadow,
+ &PMGraphicalObject::noShadow ) );
+ s_pMetaObject->addProperty(
+ new PMGraphicalObjectProperty( "noImage", &PMGraphicalObject::setNoImage,
+ &PMGraphicalObject::noImage ) );
+ s_pMetaObject->addProperty(
+ new PMGraphicalObjectProperty( "noReflection", &PMGraphicalObject::setNoReflection,
+ &PMGraphicalObject::noReflection ) );
+ s_pMetaObject->addProperty(
+ new PMGraphicalObjectProperty( "doubleIlluminate", &PMGraphicalObject::setDoubleIlluminate,
+ &PMGraphicalObject::doubleIlluminate ) );
+ s_pMetaObject->addProperty(
+ new PMGraphicalObjectProperty( "visibilityLevel", &PMGraphicalObject::setVisibilityLevel,
+ &PMGraphicalObject::visibilityLevel ) );
+ s_pMetaObject->addProperty(
+ new PMGraphicalObjectProperty( "relativeVisibilityLevel", &PMGraphicalObject::setVisibilityLevelRelative,
+ &PMGraphicalObject::isVisibilityLevelRelative ) );
+ s_pMetaObject->addProperty(
+ new PMGraphicalObjectProperty( "export", &PMGraphicalObject::setExportPovray,
+ &PMGraphicalObject::exportPovray ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMGraphicalObject::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMGraphicalObject::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "no_shadow", m_noShadow );
+ e.setAttribute( "no_image", m_noImage );
+ e.setAttribute( "no_reflection", m_noReflection );
+ e.setAttribute( "double_illuminate", m_doubleIlluminate );
+ e.setAttribute( "visibility_level", m_visibilityLevel );
+ e.setAttribute( "relative_visibility", m_relativeVisibility );
+ e.setAttribute( "export", m_export );
+ Base::serialize( e, doc );
+}
+
+void PMGraphicalObject::readAttributes( const PMXMLHelper& h )
+{
+ m_noShadow = h.boolAttribute( "no_shadow", c_defaultNoShadow );
+ m_noImage = h.boolAttribute( "no_image", c_defaultNoImage );
+ m_noReflection = h.boolAttribute( "no_reflection", c_defaultNoReflection );
+ m_doubleIlluminate = h.boolAttribute( "double_illuminate",
+ c_defaultDoubleIlluminate );
+ m_visibilityLevel = h.intAttribute( "visibility_level",
+ c_defaultVisibilityLevel );
+ m_relativeVisibility = h.boolAttribute( "relative_visibility",
+ c_defaultRelativeVisibility );
+ m_export = h.boolAttribute( "export", c_defaultExport );
+ Base::readAttributes( h );
+}
+
+void PMGraphicalObject::setNoShadow( bool yes )
+{
+ if( m_noShadow != yes )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNoShadowID, m_noShadow );
+ m_noShadow = yes;
+ }
+}
+
+void PMGraphicalObject::setNoImage( bool yes )
+{
+ if( m_noImage != yes )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNoImageID, m_noImage );
+ m_noImage = yes;
+ }
+}
+
+void PMGraphicalObject::setNoReflection( bool yes )
+{
+ if ( m_noReflection != yes )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNoReflectionID, m_noReflection );
+ m_noReflection = yes;
+ }
+}
+
+void PMGraphicalObject::setDoubleIlluminate( bool yes )
+{
+ if( m_doubleIlluminate != yes )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDoubleIlluminateID, m_doubleIlluminate );
+ m_doubleIlluminate = yes;
+ }
+}
+
+void PMGraphicalObject::setVisibilityLevel( int level )
+{
+ if( m_visibilityLevel != level )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMVisibilityID,
+ m_visibilityLevel );
+ // do not call PMCompositeObject::setViewStructureChanged because
+ // the view structure has not really changed.
+ // Only the scene has to be rendered.
+ m_pMemento->setViewStructureChanged( );
+ }
+ m_visibilityLevel = level;
+ }
+}
+
+void PMGraphicalObject::setVisibilityLevelRelative( bool relative )
+{
+ if( m_relativeVisibility != relative )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRelativeVisibilityID,
+ m_relativeVisibility );
+ m_relativeVisibility = relative;
+ }
+}
+
+void PMGraphicalObject::setExportPovray( bool ex )
+{
+ if( m_export != ex )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMExportID, m_export );
+ m_export = ex;
+ }
+}
+
+void PMGraphicalObject::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMNoShadowID:
+ setNoShadow( data->boolData( ) );
+ break;
+ case PMNoImageID:
+ setNoImage( data->boolData( ) );
+ break;
+ case PMNoReflectionID:
+ setNoReflection( data->boolData( ) );
+ break;
+ case PMDoubleIlluminateID:
+ setDoubleIlluminate( data->boolData( ) );
+ break;
+ case PMVisibilityID:
+ setVisibilityLevel( data->intData( ) );
+ break;
+ case PMRelativeVisibilityID:
+ setVisibilityLevelRelative( data->boolData( ) );
+ break;
+ case PMExportID:
+ setExportPovray( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMGraphicalObject::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmgraphicalobject.h b/kpovmodeler/pmgraphicalobject.h
new file mode 100644
index 00000000..f07ac46f
--- /dev/null
+++ b/kpovmodeler/pmgraphicalobject.h
@@ -0,0 +1,141 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMGRAPHICALOBJECT_H
+#define PMGRAPHICALOBJECT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdetailobject.h"
+
+
+/**
+ * Class for povray graphical objects
+ *
+ * Objects in povray can be:
+ * Finite Solid Primitives, Finite Patch Primitives, Infinite Solid Primitives and Constructive Solid Geometry
+ */
+class PMGraphicalObject : public PMDetailObject
+{
+ typedef PMDetailObject Base;
+public:
+ /**
+ * Creates an empty PMGraphicalObject
+ */
+ PMGraphicalObject( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMGraphicalObject( const PMGraphicalObject& o );
+ /**
+ * Deletes the object and all children
+ */
+ virtual ~PMGraphicalObject( );
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns the state of the no_shadow flag.
+ */
+ bool noShadow( ) const { return m_noShadow; }
+ /**
+ * Sets the no_shadow flag
+ */
+ void setNoShadow( bool yes );
+ /**
+ * Returns the state of the no_image flag.
+ */
+ bool noImage( ) const { return m_noImage; }
+ /**
+ * Sets the no_image flag
+ */
+ void setNoImage( bool yes );
+ /**
+ * Returns the state of the no_reflection flag
+ */
+ bool noReflection( ) const { return m_noReflection; }
+ /**
+ * Sets the no_reflection flag
+ */
+ void setNoReflection( bool yes );
+ /**
+ * Returns the state of the double_illuminate flag
+ */
+ bool doubleIlluminate( ) const { return m_doubleIlluminate; }
+ /**
+ * Sets the double_illuminate flag
+ */
+ void setDoubleIlluminate( bool yes );
+ /**
+ * Returns the visibility level
+ */
+ int visibilityLevel( ) const { return m_visibilityLevel; }
+ /**
+ * Sets the visibility level
+ */
+ void setVisibilityLevel( int level );
+ /**
+ * Returns true if the visibility level is relative to the objects parent
+ */
+ bool isVisibilityLevelRelative( ) const { return m_relativeVisibility; }
+ /**
+ * Sets the visibility level absolute or relative
+ */
+ void setVisibilityLevelRelative( bool relative );
+ /**
+ * Returns the export flag
+ */
+ virtual bool exportPovray( ) const { return m_export; }
+ /**
+ * Sets the export flag
+ */
+ void setExportPovray( bool ex );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMGraphicalObjectMementoID { PMNoShadowID, PMNoImageID, PMNoReflectionID,
+ PMDoubleIlluminateID, PMVisibilityID,
+ PMRelativeVisibilityID, PMExportID };
+
+ bool m_noShadow;
+ bool m_noImage;
+ bool m_noReflection;
+ bool m_doubleIlluminate;
+ int m_visibilityLevel;
+ bool m_relativeVisibility;
+ bool m_export;
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmgraphicalobjectedit.cpp b/kpovmodeler/pmgraphicalobjectedit.cpp
new file mode 100644
index 00000000..2a06485c
--- /dev/null
+++ b/kpovmodeler/pmgraphicalobjectedit.cpp
@@ -0,0 +1,168 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmgraphicalobjectedit.h"
+#include "pmgraphicalobject.h"
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <klocale.h>
+
+const int c_minValue = -1000;
+const int c_maxValue = 1000;
+
+PMGraphicalObjectEdit::PMGraphicalObjectEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMGraphicalObjectEdit::createBottomWidgets( )
+{
+ QGridLayout* gl = new QGridLayout( topLayout( ), 2, 2 );
+ m_pNoShadowButton = new QCheckBox( i18n( "No shadow" ), this );
+ gl->addWidget( m_pNoShadowButton, 0, 0 );
+ m_pNoImageButton = new QCheckBox( i18n( "No image" ), this );
+ gl->addWidget( m_pNoImageButton, 0, 1 );
+ m_pNoReflectionButton = new QCheckBox( i18n( "No reflection" ), this );
+ gl->addWidget( m_pNoReflectionButton, 1, 0 );
+ m_pDoubleIlluminateButton = new QCheckBox( i18n( "Double illuminate" ), this );
+ gl->addWidget( m_pDoubleIlluminateButton, 1, 1 );
+ m_pExport = new QCheckBox( i18n( "Export to renderer" ), this );
+ topLayout( )->addWidget( m_pExport );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Visibility level: " ), this ) );
+ m_pVisibilityLevel = new QSpinBox( c_minValue, c_maxValue, 1, this );
+ hl->addWidget( m_pVisibilityLevel );
+ m_pResultingVisibility = new QLabel( QString( "( )" ), this );
+ hl->addWidget( m_pResultingVisibility );
+ hl->addSpacing( 10 );
+ m_pRelativeVisibility = new QCheckBox( i18n( "Relative" ), this );
+ hl->addWidget( m_pRelativeVisibility );
+ hl->addStretch( 1 );
+
+ connect( m_pNoShadowButton, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pNoImageButton, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pNoReflectionButton, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDoubleIlluminateButton, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRelativeVisibility, SIGNAL( clicked( ) ),
+ SLOT( slotRelativeChanged( ) ) );
+ connect( m_pVisibilityLevel, SIGNAL( valueChanged( int ) ),
+ SLOT( slotLevelChanged( int ) ) );
+ connect( m_pExport, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+
+
+ Base::createBottomWidgets( );
+}
+
+void PMGraphicalObjectEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "GraphicalObject" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+
+ m_pDisplayedObject = ( PMGraphicalObject* ) o;
+ m_pNoShadowButton->setChecked( m_pDisplayedObject->noShadow( ) );
+ m_pNoShadowButton->setEnabled( !readOnly );
+ m_pNoImageButton->setChecked( m_pDisplayedObject->noImage( ) );
+ m_pNoImageButton->setEnabled( !readOnly );
+ m_pNoReflectionButton->setChecked( m_pDisplayedObject->noReflection( ) );
+ m_pNoReflectionButton->setEnabled( !readOnly );
+ m_pDoubleIlluminateButton->setChecked( m_pDisplayedObject->doubleIlluminate( ) );
+ m_pDoubleIlluminateButton->setEnabled( !readOnly );
+ bool sb = m_pVisibilityLevel->signalsBlocked( );
+ m_pVisibilityLevel->blockSignals( true );
+ m_pVisibilityLevel->setValue( m_pDisplayedObject->visibilityLevel( ) );
+ m_pVisibilityLevel->setEnabled( !readOnly );
+ m_pVisibilityLevel->blockSignals( sb );
+ sb = m_pRelativeVisibility->signalsBlocked( );
+ m_pRelativeVisibility->blockSignals( true );
+ m_pRelativeVisibility->setChecked( m_pDisplayedObject->isVisibilityLevelRelative( ) );
+ m_pRelativeVisibility->setEnabled( !readOnly );
+ m_pRelativeVisibility->blockSignals( sb );
+ m_pExport->setChecked( m_pDisplayedObject->exportPovray( ) );
+ m_pExport->setEnabled( !readOnly );
+
+ recalculateResultingVisibility( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMGraphicalObjectEdit: Can't display object\n";
+}
+
+void PMGraphicalObjectEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ m_pDisplayedObject->setNoShadow( m_pNoShadowButton->isChecked( ) );
+ m_pDisplayedObject->setNoImage( m_pNoImageButton->isChecked( ) );
+ m_pDisplayedObject->setNoReflection( m_pNoReflectionButton->isChecked( ) );
+ m_pDisplayedObject->setDoubleIlluminate( m_pDoubleIlluminateButton->isChecked( ) );
+ m_pDisplayedObject->setVisibilityLevel( m_pVisibilityLevel->value( ) );
+ m_pDisplayedObject->setVisibilityLevelRelative( m_pRelativeVisibility->isChecked( ) );
+ m_pDisplayedObject->setExportPovray( m_pExport->isChecked( ) );
+ Base::saveContents( );
+ }
+}
+
+bool PMGraphicalObjectEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+void PMGraphicalObjectEdit::slotRelativeChanged( )
+{
+ recalculateResultingVisibility( );
+ emit dataChanged( );
+}
+
+void PMGraphicalObjectEdit::slotLevelChanged( int )
+{
+ recalculateResultingVisibility( );
+ emit dataChanged( );
+}
+
+void PMGraphicalObjectEdit::recalculateResultingVisibility( )
+{
+ PMObject* o = m_pDisplayedObject->parent( );
+ PMGraphicalObject* go = 0;
+ int level = 0;
+ bool absoluteFound = false;
+
+ level = m_pVisibilityLevel->value( );
+ if( !m_pRelativeVisibility->isChecked( ) )
+ absoluteFound = true;
+
+ for( ; o && !absoluteFound; o = o->parent( ) )
+ {
+ if( o->isA( "GraphicalObject" ) )
+ {
+ go = ( PMGraphicalObject* ) o;
+ level += go->visibilityLevel( );
+ if( !go->isVisibilityLevelRelative( ) )
+ absoluteFound = true;
+ }
+ }
+ m_pResultingVisibility->setText( QString( "(%1)" ).arg( level ) );
+}
+
+#include "pmgraphicalobjectedit.moc"
diff --git a/kpovmodeler/pmgraphicalobjectedit.h b/kpovmodeler/pmgraphicalobjectedit.h
new file mode 100644
index 00000000..3b31a794
--- /dev/null
+++ b/kpovmodeler/pmgraphicalobjectedit.h
@@ -0,0 +1,78 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMGRAPHICALOBJECTEDIT_H
+#define PMGRAPHICALOBJECTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdetailobjectedit.h"
+
+class PMGraphicalObject;
+class QCheckBox;
+class QSpinBox;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMGraphicalObject.
+ */
+class PMGraphicalObjectEdit : public PMDetailObjectEdit
+{
+ Q_OBJECT
+ typedef PMDetailObjectEdit Base;
+public:
+ /**
+ * Creates a PMGraphicalObjectEdit with parent and name
+ */
+ PMGraphicalObjectEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createBottomWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotRelativeChanged( );
+ void slotLevelChanged( int );
+
+private:
+ void recalculateResultingVisibility( );
+
+private:
+ PMGraphicalObject* m_pDisplayedObject;
+ QCheckBox* m_pNoShadowButton;
+ QCheckBox* m_pNoImageButton;
+ QCheckBox* m_pNoReflectionButton;
+ QCheckBox* m_pDoubleIlluminateButton;
+ QSpinBox* m_pVisibilityLevel;
+ QCheckBox* m_pRelativeVisibility;
+ QLabel* m_pResultingVisibility;
+ QCheckBox* m_pExport;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmgridsettings.cpp b/kpovmodeler/pmgridsettings.cpp
new file mode 100644
index 00000000..20973935
--- /dev/null
+++ b/kpovmodeler/pmgridsettings.cpp
@@ -0,0 +1,155 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmgridsettings.h"
+
+#include "pmlineedits.h"
+#include "pmrendermanager.h"
+#include "pmcontrolpoint.h"
+#include "pmdefaults.h"
+
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <kcolorbutton.h>
+#include <klocale.h>
+
+PMGridSettings::PMGridSettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ QHBoxLayout* hlayout;
+ QVBoxLayout* vlayout;
+ QVBoxLayout* gvl;
+ QGridLayout* grid;
+ QGroupBox* gb;
+
+ vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+ gb = new QGroupBox( i18n( "Displayed Grid" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+
+ hlayout = new QHBoxLayout( gvl );
+ hlayout->addWidget( new QLabel( i18n( "Color:" ), gb ) );
+ m_pGridColor = new KColorButton( gb );
+ hlayout->addWidget( m_pGridColor );
+ hlayout->addStretch( 1 );
+
+ hlayout = new QHBoxLayout( gvl );
+ hlayout->addWidget( new QLabel( i18n( "Distance:" ), gb ) );
+ m_pGridDistance = new PMIntEdit( gb );
+ m_pGridDistance->setValidation( true, 20, false, 0 );
+ hlayout->addWidget( m_pGridDistance );
+ hlayout->addStretch( 1 );
+
+ gb = new QGroupBox( i18n( "Control Point Grid" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+
+ hlayout = new QHBoxLayout( gvl );
+ grid = new QGridLayout( hlayout, 3, 2 );
+ grid->addWidget( new QLabel( i18n( "2D/3D movement:" ), gb ), 0, 0 );
+ m_pMoveGrid = new PMFloatEdit( gb );
+ m_pMoveGrid->setValidation( true, 0.001, true, 100 );
+ grid->addWidget( m_pMoveGrid, 0, 1 );
+
+ grid->addWidget( new QLabel( i18n( "Scale:" ), gb ), 1, 0 );
+ m_pScaleGrid = new PMFloatEdit( gb );
+ m_pScaleGrid->setValidation( true, 0.001, true, 100 );
+ grid->addWidget( m_pScaleGrid, 1, 1 );
+
+ grid->addWidget( new QLabel( i18n( "Rotation:" ), gb ), 2, 0 );
+ m_pRotateGrid = new PMFloatEdit( gb );
+ m_pRotateGrid->setValidation( true, 0.001, true, 180 );
+ grid->addWidget( m_pRotateGrid, 2, 1 );
+
+ hlayout->addStretch( 1 );
+
+ vlayout->addStretch( 1 );
+}
+
+void PMGridSettings::displaySettings( )
+{
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ m_pGridColor->setColor( rm->gridColor( ) );
+ m_pGridDistance->setValue( rm->gridDistance( ) );
+ m_pMoveGrid->setValue( PMControlPoint::moveGrid( ) );
+ m_pScaleGrid->setValue( PMControlPoint::scaleGrid( ) );
+ m_pRotateGrid->setValue( PMControlPoint::rotateGrid( ) );
+}
+
+void PMGridSettings::displayDefaults( )
+{
+ m_pGridColor->setColor( c_defaultGridColor );
+ m_pGridDistance->setValue( c_defaultGridDistance );
+ m_pMoveGrid->setValue( c_defaultMoveGrid );
+ m_pScaleGrid->setValue( c_defaultScaleGrid );
+ m_pRotateGrid->setValue( c_defaultRotateGrid );
+}
+
+bool PMGridSettings::validateData( )
+{
+ if( !m_pGridDistance->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pGridDistance->setFocus( );
+ return false;
+ }
+ if( !m_pMoveGrid->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pMoveGrid->setFocus( );
+ return false;
+ }
+ if( !m_pScaleGrid->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pScaleGrid->setFocus( );
+ return false;
+ }
+ if( !m_pRotateGrid->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pRotateGrid->setFocus( );
+ return false;
+ }
+ return true;
+}
+
+void PMGridSettings::applySettings( )
+{
+ bool repaint = false;
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ if( rm->gridColor( ) != m_pGridColor->color( ) )
+ {
+ rm->setGridColor( m_pGridColor->color( ) );
+ repaint = true;
+ }
+ if( rm->gridDistance( ) != m_pGridDistance->value( ) )
+ {
+ rm->setGridDistance( m_pGridDistance->value( ) );
+ repaint = true;
+ }
+ PMControlPoint::setMoveGrid( m_pMoveGrid->value( ) );
+ PMControlPoint::setScaleGrid( m_pScaleGrid->value( ) );
+ PMControlPoint::setRotateGrid( m_pRotateGrid->value( ) );
+ if( repaint )
+ emit repaintViews( );
+}
+
+#include "pmgridsettings.moc"
diff --git a/kpovmodeler/pmgridsettings.h b/kpovmodeler/pmgridsettings.h
new file mode 100644
index 00000000..724ade35
--- /dev/null
+++ b/kpovmodeler/pmgridsettings.h
@@ -0,0 +1,60 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMGRIDSETTINGS_H
+#define PMGRIDSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+
+class KColorButton;
+class PMIntEdit;
+class PMFloatEdit;
+
+/**
+ * Grid configuration dialog page
+ */
+class PMGridSettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMGridSettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual void displayDefaults( );
+
+private:
+ PMIntEdit* m_pGridDistance;
+ KColorButton* m_pGridColor;
+ PMFloatEdit* m_pMoveGrid;
+ PMFloatEdit* m_pScaleGrid;
+ PMFloatEdit* m_pRotateGrid;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmheightfield.cpp b/kpovmodeler/pmheightfield.cpp
new file mode 100644
index 00000000..e729282a
--- /dev/null
+++ b/kpovmodeler/pmheightfield.cpp
@@ -0,0 +1,469 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmheightfield.h"
+
+#include "pmxmlhelper.h"
+#include "pmheightfieldedit.h"
+#include "pmheightfieldroam.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pmenumproperty.h"
+#include "pmdefaults.h"
+
+#include <klocale.h>
+
+const PMHeightField::HeightFieldType c_defaultType = PMHeightField::HFgif;
+const QString c_defaultTypeText = QString( "gif" );
+const QString c_defaultFileName = QString( "" );
+const bool c_defaultHierarchy = true;
+const bool c_defaultSmooth = false;
+const double c_defaultWaterLevel = 0.0;
+
+PMDefinePropertyClass( PMHeightField, PMHeightFieldProperty );
+PMDefineEnumPropertyClass( PMHeightField, PMHeightField::HeightFieldType,
+ PMHeightFieldTypeProperty );
+
+
+int PMHeightField::s_variance = c_defaultHeightFieldVariance;
+int PMHeightField::s_parameterKey = 0;
+
+PMViewStructure* PMHeightField::s_pDefaultViewStructure = 0;
+PMMetaObject* PMHeightField::s_pMetaObject = 0;
+
+PMObject* createNewHeightField( PMPart* part )
+{
+ return new PMHeightField( part );
+}
+
+PMHeightField::PMHeightField( PMPart* part )
+ : Base( part )
+{
+ m_hfType = c_defaultType;
+ m_fileName = c_defaultFileName;
+ m_hierarchy = c_defaultHierarchy;
+ m_smooth = c_defaultSmooth;
+ m_waterLevel = c_defaultWaterLevel;
+
+ m_modMap = true;
+ m_pROAM = 0;
+}
+
+PMHeightField::PMHeightField( const PMHeightField& f )
+ : Base( f )
+{
+ m_hfType = f.m_hfType;
+ m_fileName = f.m_fileName;
+ m_hierarchy = f.m_hierarchy;
+ m_smooth = f.m_smooth;
+ m_waterLevel = f.m_waterLevel;
+
+ m_modMap = true;
+ m_pROAM = 0;
+}
+
+PMHeightField::~PMHeightField( )
+{
+ delete m_pROAM;
+}
+
+QString PMHeightField::description( ) const
+{
+ return i18n( "height field" );
+}
+
+void PMHeightField::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "hf_type", typeToString( m_hfType ) );
+ e.setAttribute( "file_name", m_fileName );
+ e.setAttribute( "hierarchy", m_hierarchy );
+ e.setAttribute( "smooth", m_smooth );
+ e.setAttribute( "water_level", m_waterLevel );
+ Base::serialize( e, doc );
+}
+
+void PMHeightField::readAttributes( const PMXMLHelper& h )
+{
+ m_hfType = stringToType( h.stringAttribute( "hf_type", c_defaultTypeText ) );
+ m_fileName = h.stringAttribute( "file_name", c_defaultFileName );
+ m_hierarchy = h.boolAttribute( "hierarchy", c_defaultHierarchy );
+ m_smooth = h.boolAttribute( "smooth", c_defaultSmooth );
+ m_waterLevel = h.doubleAttribute( "water_level", c_defaultWaterLevel );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMHeightField::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "HeightField", Base::metaObject( ),
+ createNewHeightField );
+ s_pMetaObject->addProperty(
+ new PMHeightFieldProperty( "fileName", &PMHeightField::setFileName, &PMHeightField::fileName ) );
+ s_pMetaObject->addProperty(
+ new PMHeightFieldProperty( "hierarchy", &PMHeightField::setHierarchy, &PMHeightField::hierarchy ) );
+ s_pMetaObject->addProperty(
+ new PMHeightFieldProperty( "smooth", &PMHeightField::setSmooth, &PMHeightField::smooth ) );
+ s_pMetaObject->addProperty(
+ new PMHeightFieldProperty( "waterLevel", &PMHeightField::setWaterLevel, &PMHeightField::waterLevel ) );
+ PMHeightFieldTypeProperty* p =
+ new PMHeightFieldTypeProperty( "heightFieldType", &PMHeightField::setHeightFieldType,
+ &PMHeightField::heightFieldType );
+ p->addEnumValue( "Gif", HFgif );
+ p->addEnumValue( "Tga", HFtga );
+ p->addEnumValue( "Pot", HFpot );
+ p->addEnumValue( "Png", HFpng );
+ p->addEnumValue( "Pgm", HFpgm );
+ p->addEnumValue( "Ppm", HFppm );
+ p->addEnumValue( "Sys", HFsys );
+ s_pMetaObject->addProperty( p );
+ }
+ return s_pMetaObject;
+}
+
+void PMHeightField::setHeightFieldType( PMHeightField::HeightFieldType t )
+{
+ if( t != m_hfType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHeightFieldTypeID, m_hfType );
+ m_hfType = t;
+ }
+}
+
+void PMHeightField::setFileName( const QString& f )
+{
+ if( f != m_fileName )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFileNameID, m_fileName );
+ m_fileName = f;
+ m_modMap = true;
+ setViewStructureChanged( );
+ }
+}
+
+void PMHeightField::setHierarchy( bool h )
+{
+ if( h != m_hierarchy )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHierarchyID, m_hierarchy );
+ m_hierarchy = h;
+ }
+}
+
+void PMHeightField::setSmooth( bool s )
+{
+ if( s != m_smooth )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSmoothID, m_smooth );
+ m_smooth = s;
+ }
+}
+
+void PMHeightField::setWaterLevel( double wl )
+{
+ if( wl < 0.0 )
+ {
+ kdError( PMArea ) << "Water level < 0.0 in PMHeightField::setWaterLevel\n";
+ wl = 0.0;
+ }
+ if( wl > 1.0 )
+ {
+ kdError( PMArea ) << "Water level > 1.0 in PMHeightField::setWaterLevel\n";
+ wl = 1.0;
+ }
+
+ if( wl != m_waterLevel )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMWaterLevelID, m_waterLevel );
+ m_waterLevel = wl;
+ setViewStructureChanged( );
+ }
+}
+
+PMDialogEditBase* PMHeightField::editWidget( QWidget* parent ) const
+{
+ return new PMHeightFieldEdit( parent );
+}
+
+void PMHeightField::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMHeightFieldTypeID:
+ m_hfType = ( HeightFieldType ) data->intData( );
+ break;
+ case PMFileNameID:
+ m_fileName = data->stringData( );
+ break;
+ case PMHierarchyID:
+ m_hierarchy = data->boolData( );
+ break;
+ case PMSmoothID:
+ m_smooth = data->boolData( );
+ break;
+ case PMWaterLevelID:
+ m_waterLevel = data->doubleData( );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMHeightField::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+
+bool PMHeightField::isDefault( )
+{
+ return ( m_waterLevel == c_defaultWaterLevel && m_fileName.isEmpty( ) );
+}
+
+void PMHeightField::createViewStructure( )
+{
+ int detail = 65200 - ( ( s_variance * 163 ) * ( displayDetail( ) * displayDetail( ) ) );
+ if ( m_modMap )
+ {
+ m_modMap = false;
+
+ if ( m_pROAM )
+ {
+ delete m_pROAM;
+ m_pROAM = 0;
+ }
+
+ if ( !m_fileName.isEmpty( ) )
+ {
+ m_pROAM = new PMHeightFieldROAM( m_fileName );
+
+ if ( m_pROAM->isFailed( ) )
+ {
+ delete m_pROAM;
+ m_pROAM = 0;
+ }
+ }
+ }
+
+ if ( m_pROAM )
+ {
+ m_pROAM->setDisplayDetail( detail );
+ m_pROAM->setWaterLevel( m_waterLevel );
+ m_pROAM->updateModel( );
+ roamViewStructure( );
+ return;
+ }
+
+ if ( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ m_pViewStructure->lines( ).detach( );
+ }
+ else
+ {
+ m_pViewStructure->points( ).resize(
+ defaultViewStructure( )->points( ).size( ) );
+ m_pViewStructure->lines( ).resize(
+ defaultViewStructure( )->lines( ).size( ) );
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+
+ points[4][1] = m_waterLevel;
+ points[5][1] = m_waterLevel;
+ points[6][1] = m_waterLevel;
+ points[7][1] = m_waterLevel;
+}
+
+void PMHeightField::roamViewStructure( )
+{
+ if ( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ m_pViewStructure->lines( ).detach( );
+ }
+
+ int x, z, i, pts;
+ int size = m_pROAM->size( );
+ int currentLine = defaultViewStructure( )->lines( ).size( );
+ int defPointsNum = defaultViewStructure( )->points( ).size( );
+ double dx, dy, dz;
+ double sizeM1 = size - 1.0;
+
+ m_pViewStructure->points( ).resize( m_pROAM->usedPoints( ) + defPointsNum );
+ m_pViewStructure->lines( ).resize( m_pROAM->numLines( ) + currentLine );
+
+ PMPointArray& points = m_pViewStructure->points( );
+ PMLineArray& lines = m_pViewStructure->lines( );
+
+ points[4][1] = m_waterLevel;
+ points[5][1] = m_waterLevel;
+ points[6][1] = m_waterLevel;
+ points[7][1] = m_waterLevel;
+
+ for ( x = 0; x < size; ++x )
+ {
+ dx = x / sizeM1;
+ for ( z = 0; z < size; ++z )
+ {
+ dz = z / sizeM1;
+ if ( m_pROAM->usedPoint( x, z ) )
+ {
+ pts = m_pROAM->posPoint( x, z ) + defPointsNum;
+ dy = m_pROAM->height( x, z, true ) / 65535.0;
+ points[ pts ] = PMPoint( dx, dy, dz );
+
+ for ( i = 0; m_pROAM->lineExist( x, z, i ) && i < 8; ++i )
+ {
+ lines[ currentLine++ ] =
+ PMLine( pts, m_pROAM->endPoint( x, z, i ) + defPointsNum );
+ }
+ }
+ }
+ }
+}
+
+PMViewStructure* PMHeightField::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure )
+ {
+ s_pDefaultViewStructure = new PMViewStructure( 12, 16 );
+ PMPointArray& points = s_pDefaultViewStructure->points( );
+ PMLineArray& lines = s_pDefaultViewStructure->lines( );
+
+ points[ 0] = PMPoint( 0.0, 0.0, 0.0 );
+ points[ 1] = PMPoint( 1.0, 0.0, 0.0 );
+ points[ 2] = PMPoint( 1.0, 0.0, 1.0 );
+ points[ 3] = PMPoint( 0.0, 0.0, 1.0 );
+ points[ 4] = PMPoint( 0.0, c_defaultWaterLevel, 0.0 );
+ points[ 5] = PMPoint( 1.0, c_defaultWaterLevel, 0.0 );
+ points[ 6] = PMPoint( 1.0, c_defaultWaterLevel, 1.0 );
+ points[ 7] = PMPoint( 0.0, c_defaultWaterLevel, 1.0 );
+ points[ 8] = PMPoint( 0.0, 1.0, 0.0 );
+ points[ 9] = PMPoint( 1.0, 1.0, 0.0 );
+ points[10] = PMPoint( 1.0, 1.0, 1.0 );
+ points[11] = PMPoint( 0.0, 1.0, 1.0 );
+
+ lines[ 0] = PMLine( 0, 1 );
+ lines[ 1] = PMLine( 1, 2 );
+ lines[ 2] = PMLine( 2, 3 );
+ lines[ 3] = PMLine( 0, 3 );
+
+ lines[ 4] = PMLine( 0, 8 );
+ lines[ 5] = PMLine( 1, 9 );
+ lines[ 6] = PMLine( 2, 10 );
+ lines[ 7] = PMLine( 3, 11 );
+
+ lines[ 8] = PMLine( 4, 5 );
+ lines[ 9] = PMLine( 5, 6 );
+ lines[10] = PMLine( 6, 7 );
+ lines[11] = PMLine( 4, 7 );
+
+ lines[12] = PMLine( 8, 9 );
+ lines[13] = PMLine( 9, 10 );
+ lines[14] = PMLine( 10, 11 );
+ lines[15] = PMLine( 8, 11 );
+ }
+ return s_pDefaultViewStructure;
+}
+
+QString PMHeightField::typeToString( PMHeightField::HeightFieldType t )
+{
+ QString s;
+ switch( t )
+ {
+ case HFgif:
+ s = QString( "gif" );
+ break;
+ case HFtga:
+ s = QString( "tga" );
+ break;
+ case HFpot:
+ s = QString( "pot" );
+ break;
+ case HFpng:
+ s = QString( "png" );
+ break;
+ case HFpgm:
+ s = QString( "pgm" );
+ break;
+ case HFppm:
+ s = QString( "ppm" );
+ break;
+ case HFsys:
+ s = QString( "sys" );
+ break;
+ }
+ return s;
+}
+
+PMHeightField::HeightFieldType PMHeightField::stringToType( const QString &str )
+{
+ HeightFieldType t = HFgif;
+ if( str == "gif" )
+ t = HFgif;
+ else if( str == "tga" )
+ t = HFtga;
+ else if( str == "pot" )
+ t = HFpot;
+ else if( str == "png" )
+ t = HFpng;
+ else if( str == "pgm" )
+ t = HFpgm;
+ else if( str == "ppm" )
+ t = HFppm;
+ else if( str == "sys" )
+ t = HFsys;
+ return t;
+}
+
+void PMHeightField::setVariance( int v )
+{
+ if( v < 52 && v > 0 )
+ s_variance = v;
+ else
+ kdDebug( PMArea ) << "PMHeightField::setVariance: V must be less than 52 & greater than 0\n";
+ s_parameterKey++;
+}
+
+void PMHeightField::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmheightfield.h b/kpovmodeler/pmheightfield.h
new file mode 100644
index 00000000..4ab961c8
--- /dev/null
+++ b/kpovmodeler/pmheightfield.h
@@ -0,0 +1,180 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMHEIGHTFIELD_H
+#define PMHEIGHTFIELD_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+
+class PMViewStructure;
+class PMHeightFieldROAM;
+
+/**
+ * Class for povray height fields.
+ */
+
+class PMHeightField : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Height field type
+ */
+ enum HeightFieldType { HFgif, HFtga, HFpot, HFpng, HFpgm, HFppm, HFsys };
+ /**
+ * Creates an empty PMHeightField
+ */
+ PMHeightField( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMHeightField( const PMHeightField& f );
+ /**
+ * deletes the PMHeightField
+ */
+ virtual ~PMHeightField( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMHeightField( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMHeightFieldEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmheightfield" ); }
+
+ /**
+ * Returns the height field type
+ */
+ HeightFieldType heightFieldType( ) const { return m_hfType; }
+ /**
+ * Sets the height field type
+ */
+ void setHeightFieldType( HeightFieldType t );
+ /**
+ * Returns the file name
+ */
+ QString fileName( ) const { return m_fileName; }
+ /**
+ * Sets the file name
+ */
+ void setFileName( const QString& name );
+ /**
+ * Returns the hierarchy flag
+ */
+ bool hierarchy( ) const { return m_hierarchy; }
+ /**
+ * Sets the hierarchy flag
+ */
+ void setHierarchy( bool h );
+ /**
+ * Returns the smooth flag
+ */
+ bool smooth( ) const { return m_smooth; }
+ /**
+ * Sets the smooth flag
+ */
+ void setSmooth( bool s );
+ /**
+ * Returns the water level
+ */
+ double waterLevel( ) const { return m_waterLevel; }
+ /**
+ * Sets the water level
+ */
+ void setWaterLevel( double wl );
+
+ /**
+ * Sets the heightfield variance
+ */
+ static void setVariance( int v );
+ /**
+ * Returns the heightfield variance
+ */
+ static int variance( ) { return s_variance; }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual void cleanUp( ) const;
+
+ static QString typeToString( HeightFieldType t );
+ static HeightFieldType stringToType( const QString &str );
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey(); }
+
+private:
+ /**
+ * Creates the ROAM view structure
+ */
+ void roamViewStructure( );
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMHeightFieldMementoID { PMHeightFieldTypeID, PMFileNameID,
+ PMHierarchyID, PMSmoothID, PMWaterLevelID };
+
+ HeightFieldType m_hfType;
+ QString m_fileName;
+ bool m_hierarchy;
+ bool m_smooth;
+ double m_waterLevel;
+
+ bool m_modMap;
+ PMHeightFieldROAM* m_pROAM;
+
+ /**
+ * The default view structure. It can be shared between height fields
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_variance;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmheightfieldedit.cpp b/kpovmodeler/pmheightfieldedit.cpp
new file mode 100644
index 00000000..c5a65998
--- /dev/null
+++ b/kpovmodeler/pmheightfieldedit.cpp
@@ -0,0 +1,201 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmheightfieldedit.h"
+#include "pmheightfield.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qslider.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+
+PMHeightFieldEdit::PMHeightFieldEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMHeightFieldEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Type:" ), this ) );
+ m_pHeightFieldType = new QComboBox( false, this );
+ hl->addWidget( m_pHeightFieldType );
+ hl->addStretch( 0 );
+ m_pHeightFieldType->insertItem( "gif" );
+ m_pHeightFieldType->insertItem( "tga" );
+ m_pHeightFieldType->insertItem( "pot" );
+ m_pHeightFieldType->insertItem( "png" );
+ m_pHeightFieldType->insertItem( "pgm" );
+ m_pHeightFieldType->insertItem( "ppm" );
+ m_pHeightFieldType->insertItem( "sys" );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "File name:" ), this ) );
+ m_pFileName = new QLineEdit( this );
+ hl->addWidget( m_pFileName );
+ m_pChooseFileName = new QPushButton( this );
+ m_pChooseFileName->setPixmap( SmallIcon( "fileopen" ) );
+ hl->addWidget( m_pChooseFileName );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Water level:" ), this ) );
+ m_pWaterLevel = new PMFloatEdit( this );
+ m_pWaterLevel->setValidation( true, 0.0, true, 1.0 );
+ hl->addWidget( m_pWaterLevel );
+ hl->addStretch( 1 );
+
+ m_pHierarchy = new QCheckBox( i18n( "Hierarchy" ), this );
+ topLayout( )->addWidget( m_pHierarchy );
+
+ m_pSmooth = new QCheckBox( i18n( "Smooth" ), this );
+ topLayout( )->addWidget( m_pSmooth );
+
+ connect( m_pHeightFieldType, SIGNAL( activated( int ) ),
+ SLOT( slotTypeChanged( int ) ) );
+ connect( m_pFileName, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotFileNameChanged( const QString& ) ) );
+ connect( m_pChooseFileName, SIGNAL( clicked( ) ),
+ SLOT( slotFileNameClicked( ) ) );
+ connect( m_pWaterLevel, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pHierarchy, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSmooth, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMHeightFieldEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "HeightField" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMHeightField* ) o;
+
+ switch( m_pDisplayedObject->heightFieldType( ) )
+ {
+ case PMHeightField::HFgif:
+ m_pHeightFieldType->setCurrentItem( 0 );
+ break;
+ case PMHeightField::HFtga:
+ m_pHeightFieldType->setCurrentItem( 1 );
+ break;
+ case PMHeightField::HFpot:
+ m_pHeightFieldType->setCurrentItem( 2 );
+ break;
+ case PMHeightField::HFpng:
+ m_pHeightFieldType->setCurrentItem( 3 );
+ break;
+ case PMHeightField::HFpgm:
+ m_pHeightFieldType->setCurrentItem( 4 );
+ break;
+ case PMHeightField::HFppm:
+ m_pHeightFieldType->setCurrentItem( 5 );
+ break;
+ case PMHeightField::HFsys:
+ m_pHeightFieldType->setCurrentItem( 6 );
+ break;
+ }
+ m_pFileName->setText( m_pDisplayedObject->fileName( ) );
+ m_pWaterLevel->setValue( m_pDisplayedObject->waterLevel( ) );
+ m_pHierarchy->setChecked( m_pDisplayedObject->hierarchy( ) );
+ m_pSmooth->setChecked( m_pDisplayedObject->smooth( ) );
+
+ m_pHeightFieldType->setEnabled( !readOnly );
+ m_pFileName->setReadOnly( readOnly );
+ m_pChooseFileName->setEnabled( !readOnly );
+ m_pHierarchy->setEnabled( !readOnly );
+ m_pSmooth->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMHeightFieldEdit: Can't display object\n";
+}
+
+void PMHeightFieldEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ switch( m_pHeightFieldType->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setHeightFieldType( PMHeightField::HFgif );
+ break;
+ case 1:
+ m_pDisplayedObject->setHeightFieldType( PMHeightField::HFtga );
+ break;
+ case 2:
+ m_pDisplayedObject->setHeightFieldType( PMHeightField::HFpot );
+ break;
+ case 3:
+ m_pDisplayedObject->setHeightFieldType( PMHeightField::HFpng );
+ break;
+ case 4:
+ m_pDisplayedObject->setHeightFieldType( PMHeightField::HFpgm );
+ break;
+ case 5:
+ m_pDisplayedObject->setHeightFieldType( PMHeightField::HFppm );
+ break;
+ case 6:
+ m_pDisplayedObject->setHeightFieldType( PMHeightField::HFsys );
+ break;
+ }
+ m_pDisplayedObject->setFileName( m_pFileName->text( ) );
+ m_pDisplayedObject->setWaterLevel( m_pWaterLevel->value( ) );
+ m_pDisplayedObject->setHierarchy( m_pHierarchy->isChecked( ) );
+ m_pDisplayedObject->setSmooth( m_pSmooth->isChecked( ) );
+ }
+}
+
+bool PMHeightFieldEdit::isDataValid( )
+{
+ if( m_pWaterLevel->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+void PMHeightFieldEdit::slotTypeChanged( int )
+{
+ emit dataChanged( );
+}
+
+void PMHeightFieldEdit::slotFileNameChanged( const QString& )
+{
+ emit dataChanged( );
+}
+
+void PMHeightFieldEdit::slotFileNameClicked( )
+{
+ QString str = KFileDialog::getOpenFileName( QString::null, QString::null );
+
+ if( !str.isEmpty() )
+ {
+ m_pFileName->setText( str );
+ emit dataChanged( );
+ }
+}
+
+#include "pmheightfieldedit.moc"
diff --git a/kpovmodeler/pmheightfieldedit.h b/kpovmodeler/pmheightfieldedit.h
new file mode 100644
index 00000000..24ea2e6e
--- /dev/null
+++ b/kpovmodeler/pmheightfieldedit.h
@@ -0,0 +1,87 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMHEIGHTFIELDEDIT_H
+#define PMHEIGHTFIELDEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMHeightField;
+class PMFloatEdit;
+class QCheckBox;
+class QComboBox;
+class QLineEdit;
+class QPushButton;
+
+/**
+ * Dialog edit class for @ref PMHeightField
+ */
+class PMHeightFieldEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMHeightFieldEdit with parent and name
+ */
+ PMHeightFieldEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected slots:
+ /**
+ * Slot called when the height field type is changed
+ */
+ void slotTypeChanged( int t );
+ /**
+ * Slot called when the file name is changed
+ */
+ void slotFileNameChanged( const QString& s );
+ /**
+ * Slot called when the choose file button is pressed
+ */
+ void slotFileNameClicked( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMHeightField* m_pDisplayedObject;
+ QComboBox* m_pHeightFieldType;
+ QLineEdit* m_pFileName;
+ QPushButton* m_pChooseFileName;
+ QCheckBox* m_pSmooth;
+ QCheckBox* m_pHierarchy;
+ PMFloatEdit* m_pWaterLevel;
+
+};
+
+
+#endif
diff --git a/kpovmodeler/pmheightfieldroam.cpp b/kpovmodeler/pmheightfieldroam.cpp
new file mode 100644
index 00000000..eb2790a5
--- /dev/null
+++ b/kpovmodeler/pmheightfieldroam.cpp
@@ -0,0 +1,422 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+#include "pmheightfieldroam.h"
+
+#include <cstdlib>
+#include <new>
+
+#include <qstring.h>
+#include <qimage.h>
+#include <qcolor.h>
+
+#include <kdebug.h>
+
+PMHeightFieldROAM::PMHeightFieldROAM( const QString &fileName )
+{
+ m_size = 0;
+ m_numLines = m_usedPoints = 0;
+ m_waterLevel = m_displayDetail = 0;
+ m_mapMod = m_levelMod = true;
+ m_fail = false;
+ m_pPoints = 0;
+ m_pTree = 0;
+
+ if ( !imageToData( fileName ) )
+ {
+ if ( m_pPoints )
+ delete [] m_pPoints;
+ if ( m_pTree )
+ delete [] m_pTree;
+ m_pPoints = 0;
+ m_pTree = 0;
+ m_pNextNode = 0;
+ m_size = m_numPoints = m_numNodes = 0;
+ m_fail = true;
+ return;
+ }
+
+ calcLevel( );
+}
+
+PMHeightFieldROAM::~PMHeightFieldROAM( )
+{
+ delete [] m_pPoints;
+ delete [] m_pTree;
+}
+
+void PMHeightFieldROAM::updateModel( )
+{
+ if ( m_fail )
+ return;
+ int z = m_size - 1;
+ if ( m_mapMod )
+ {
+ m_mapMod = false;
+ m_levelMod = false;
+ clearPoints( );
+ clearNodes( true );
+
+ m_pNextNode = m_pTree + 1;
+ m_pNextNode->base = m_pTree;
+ m_pTree->base = m_pNextNode++;
+
+ varNode(m_pTree, z, 0, 0, 0, 0, z, 0);
+ varNode(m_pTree + 1, 0, z, z, z, z, 0, 0);
+
+ sptNode(m_pTree, 0);
+ sptNode(m_pTree + 1, 0);
+
+ pntNode(m_pTree, z, 0, 0, 0, 0, z);
+ pntNode(m_pTree + 1, 0, z, z, z, z, 0);
+ }
+ else if ( m_levelMod )
+ {
+ m_levelMod = false;
+ clearPoints( );
+ clearNodes( );
+
+ sptNode( m_pTree, 0 );
+ sptNode( m_pTree + 1, 0 );
+
+ pntNode( m_pTree, z, 0, 0, 0, 0, z );
+ pntNode( m_pTree + 1, 0, z, z, z, z, 0 );
+ }
+}
+
+void PMHeightFieldROAM::setDisplayDetail( int detail )
+{
+ if ( detail != m_displayDetail )
+ {
+ m_displayDetail = detail;
+ m_levelMod = true;
+ }
+}
+
+void PMHeightFieldROAM::setWaterLevel( double waterLevel )
+{
+ int waterConv = (int)( waterLevel * 65535 );
+ if ( waterConv != m_waterLevel )
+ {
+ m_waterLevel = waterConv;
+ m_levelMod = true;
+ }
+}
+
+double PMHeightFieldROAM::waterLevel( ) const
+{
+ double waterConv = m_waterLevel / 65535.0;
+ return waterConv;
+}
+
+unsigned short PMHeightFieldROAM::height( int x, int y, bool waterLevel ) const
+{
+ unsigned short hgt = m_pPoints[ x + ( y * m_size ) ].hgt;
+ if ( waterLevel )
+ {
+ if ( hgt <= m_waterLevel )
+ return m_waterLevel;
+ else
+ return hgt;
+ }
+ else
+ return hgt;
+}
+
+bool PMHeightFieldROAM::lineExist( int x, int y, int line ) const
+{
+ if ( m_pPoints[ x + ( y * m_size ) ].lines[ line ] ) return true;
+ else return false;
+}
+
+bool PMHeightFieldROAM::imageToData(const QString &fileName)
+{
+ QImage scaledMap;
+ QImage mapFile( fileName );
+
+ if ( mapFile.isNull( ) )
+ return false;
+
+ if ( mapFile.width( ) > 192 || mapFile.height( ) > 192 )
+ {
+ scaledMap = mapFile.scale( 257, 257 );
+ }
+ else if ( mapFile.width( ) > 96 || mapFile.height( ) > 96 )
+ {
+ scaledMap = mapFile.scale( 129, 129 );
+ }
+ else if ( mapFile.width( ) > 48 || mapFile.height( ) > 48)
+ {
+ scaledMap = mapFile.scale( 65, 65 );
+ }
+ else
+ {
+ scaledMap = mapFile.scale( 33, 33 );
+ }
+
+ if ( scaledMap.isNull( ) )
+ return false;
+
+ m_size = scaledMap.width( );
+ if ( !createPoints( ) || !createNodes( ) )
+ return false;
+
+ bool colourIndex;
+
+ if ( mapFile.depth( ) > 8 )
+ colourIndex = false;
+ else
+ {
+ scaledMap = scaledMap.convertDepthWithPalette( 8, mapFile.colorTable( ), 256 );
+ colourIndex = true;
+ }
+
+ for ( int y = 0, y2 = ( m_size - 1 ) ; y < m_size ; ++y, --y2 )
+ {
+ for ( int x = 0 ; x < m_size ; ++x )
+ {
+ if ( colourIndex )
+ setHeight( x, y2, scaledMap.pixelIndex( x, y ) * 256 );
+ else
+ setHeight( x, y2, ( 256 * qRed( scaledMap.pixel( x, y ) ) ) +
+ qGreen( scaledMap.pixel( x, y ) ) );
+ }
+ }
+
+ return true;
+}
+
+void PMHeightFieldROAM::calcLevel( )
+{
+ int i = 0;
+ int j = m_size;
+
+ while( j != 1)
+ {
+ j /= 2;
+ i++;
+ }
+ m_maxLevel = i * 2;
+}
+
+void PMHeightFieldROAM::varNode ( triNodeStructure* current,
+ int x1, int y1,
+ int x2, int y2,
+ int x3, int y3,
+ int level )
+{
+ int xm = (x1 + x3) >> 1;
+ int ym = (y1 + y3) >> 1;
+
+ if ( level >= m_maxLevel )
+ {
+ unsigned short z1 = height( x1, y1 );
+ unsigned short z3 = height( x3, y3 );
+
+ unsigned short zm = ( ( z3 - z1 ) / 2 ) + z1;
+ unsigned short hgt = height( xm, ym );
+
+ current->vari = abs( zm - hgt );
+ return;
+ }
+
+ current->lchd = m_pNextNode++;
+ current->rchd = m_pNextNode++;
+
+ varNode(current->lchd, x3, y3, xm, ym, x2, y2, level + 1);
+ varNode(current->rchd, x2, y2, xm, ym, x1, y1, level + 1);
+
+ current->vari = current->lchd->vari + current->rchd->vari;
+}
+
+void PMHeightFieldROAM::sptNode ( triNodeStructure* current, int level )
+{
+ if ( !current->split )
+ {
+ if ( level >= m_maxLevel ) return;
+
+ if (current->vari > m_displayDetail) split(current);
+ else return;
+ }
+
+ sptNode(current->lchd, level + 1);
+ sptNode(current->rchd, level + 1);
+}
+
+void PMHeightFieldROAM::split( triNodeStructure* current )
+{
+ current->split = true;
+
+ if ( current->base )
+ {
+ if ( current->base->base != current ) split( current->base );
+ }
+
+ triNodeStructure* child;
+
+ //left child
+ child = current->lchd;
+ child->base = current->lnbr;
+ if ( current->lnbr )
+ {
+ if ( current->lnbr->rnbr == current ) current->lnbr->rnbr = child;
+ else current->lnbr->base = child;
+ }
+ child->lnbr = current->rchd;
+
+ //rightchild
+ child = current->rchd;
+ child->base = current->rnbr;
+ if ( current->rnbr )
+ {
+ if ( current->rnbr->lnbr == current ) current->rnbr->lnbr = child;
+ else current->rnbr->base = child;
+ }
+ child->rnbr = current->lchd;
+
+ if ( current->base )
+ {
+ if ( !current->base->split ) split( current->base );
+ current->lchd->rnbr = current->base->rchd;
+ current->rchd->lnbr = current->base->lchd;
+ }
+}
+
+void PMHeightFieldROAM::pntNode( triNodeStructure* current,
+ int x1, int y1,
+ int x2, int y2,
+ int x3, int y3 )
+{
+ if (current->split)
+ {
+ int xm = (x1 + x3) >> 1;
+ int ym = (y1 + y3) >> 1;
+ pntNode( current->lchd, x3, y3, xm, ym, x2, y2 );
+ pntNode( current->rchd, x2, y2, xm, ym, x1, y1 );
+ }
+ else
+ {
+ pointStructure* pts[3];
+ pts[0] = &m_pPoints[ x1 + ( y1 * m_size ) ];
+ pts[1] = &m_pPoints[ x2 + ( y2 * m_size ) ];
+ pts[2] = &m_pPoints[ x3 + ( y3 * m_size ) ];
+
+ if ( m_waterLevel != 0 )
+ {
+ if ( pts[0]->hgt <= m_waterLevel &&
+ pts[1]->hgt <= m_waterLevel &&
+ pts[2]->hgt <= m_waterLevel )
+ return;
+ }
+
+ for ( int i = 0 ; i < 3 ; ++i )
+ {
+ if ( !pts[i]->used )
+ {
+ pts[i]->pos = m_usedPoints++;
+ pts[i]->used = true;
+ }
+ }
+
+ addLine( pts[0], pts[1] );
+ addLine( pts[1], pts[2] );
+ addLine( pts[2], pts[0] );
+ }
+}
+
+void PMHeightFieldROAM::addLine( pointStructure* pts1, pointStructure* pts2 )
+{
+ for ( int i = 0 ; i < 8 ; ++i )
+ {
+ if ( pts1->lines[i] )
+ {
+ if ( pts1->lines[i] == pts2 ) return;
+ }
+ else
+ {
+ for ( int j = 0 ; pts2->lines[j] ; ++j )
+ {
+ if ( pts2->lines[j] == pts1 ) return;
+ }
+ pts1->lines[i] = pts2;
+ m_numLines++;
+ return;
+ }
+ }
+}
+
+bool PMHeightFieldROAM::createPoints( )
+{
+ m_numPoints = m_size * m_size;
+ m_pPoints = new( std::nothrow ) pointStructure[ m_numPoints ];
+ if ( !m_pPoints )
+ return false;
+ else
+ {
+ clearPoints( true );
+ return true;
+ }
+}
+
+void PMHeightFieldROAM::clearPoints( bool all )
+{
+ int i, j;
+ for ( i = 0 ; i < m_numPoints ; ++i )
+ {
+ if ( all )
+ {
+ m_pPoints[i].hgt = 0;
+ m_pPoints[i].pos = 0;
+ }
+ for ( j = 0 ; j < 8 ; ++j )
+ m_pPoints[i].lines[j] = 0;
+ m_pPoints[i].used = false;
+ }
+
+ m_usedPoints = m_numLines = 0;
+}
+
+bool PMHeightFieldROAM::createNodes( )
+{
+ m_numNodes = ( ( m_size - 1 ) * ( 4 * ( m_size - 1 ) ) ) - 2;
+ m_pTree = new( std::nothrow ) triNodeStructure[ m_numNodes ];
+ if ( !m_pTree )
+ return false;
+ else
+ {
+ clearNodes( true );
+ return true;
+ }
+}
+
+void PMHeightFieldROAM::clearNodes( bool all )
+{
+ m_pNextNode = m_pTree;
+ for ( int i = 0; i < m_numNodes; ++i )
+ {
+ if ( all )
+ {
+ m_pNextNode->lchd = 0;
+ m_pNextNode->rchd = 0;
+ m_pNextNode->base = 0;
+ m_pNextNode->lnbr = 0;
+ m_pNextNode->rnbr = 0;
+ m_pNextNode->vari = 0;
+ }
+ m_pNextNode->split = false;
+ m_pNextNode++;
+ }
+}
diff --git a/kpovmodeler/pmheightfieldroam.h b/kpovmodeler/pmheightfieldroam.h
new file mode 100644
index 00000000..e2802c6b
--- /dev/null
+++ b/kpovmodeler/pmheightfieldroam.h
@@ -0,0 +1,283 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+#ifndef PMHEIGHTFIELDROAM_H
+#define PMHEIGHTFIELDROAM_H
+
+class QString;
+
+/**
+ * ROAM display class for @ref PMHeightField
+*/
+class PMHeightFieldROAM
+{
+ int m_size;
+ int m_numPoints;
+ int m_usedPoints;
+ int m_numLines;
+ int m_numNodes;
+ bool m_fail;
+ int m_maxLevel;
+ int m_displayDetail;
+ int m_waterLevel;
+ bool m_mapMod;
+ bool m_levelMod;
+
+ /**
+ * Point Structure holds most of the info
+ */
+ struct pointStructure
+ {
+ unsigned short hgt;
+ pointStructure* lines[ 8 ];
+ int pos;
+ bool used;
+ };
+ /**
+ * The points array
+ */
+ pointStructure* m_pPoints;
+
+ /**
+ * The Triangle Node structure used in the ROAM algorithm
+ */
+ struct triNodeStructure
+ {
+ triNodeStructure* lchd;
+ triNodeStructure* rchd;
+ triNodeStructure* base;
+ triNodeStructure* lnbr;
+ triNodeStructure* rnbr;
+ int vari;
+ bool split;
+ };
+ /**
+ * Tree Root node
+ */
+ triNodeStructure* m_pTree;
+ /**
+ * Next available node
+ */
+ triNodeStructure* m_pNextNode;
+
+ /**
+ * Loads and formats the image to the correct size, creates the points
+ * array. Then fills the points array with the heights and zero's the
+ * rest of the info
+ * @param filename The name of the file to load
+ * @return true if succesful false it it fails
+ */
+ bool imageToData( const QString &fileName );
+
+ /**
+ * Sets the Maximum Level of the tree.
+ */
+ void calcLevel( );
+
+ /**
+ * Generates the Variance for each node.
+ * @param current The current node
+ * @param x1-y1 The position of the first corner
+ * @param x2-y2 The position of the second corner
+ * @param x3-y3 The position of the third corner
+ * @param level The current level within a tree
+ */
+ void varNode( triNodeStructure* current,
+ int x1, int y1,
+ int x2, int y2,
+ int x3, int y3,
+ int level );
+
+ /**
+ * Generates the Split for the Tree.
+ * @param current The current node
+ * @param level The current level within a tree
+ */
+ void sptNode( triNodeStructure* current, int level );
+
+ /**
+ * Request the splitting of a node, checks too see if it can be
+ * Split or if its base neighbour requires splitting.
+ * @param current node to split
+ */
+ void split( triNodeStructure* current );
+
+ /**
+ * Counts up the lines and points in a model, and sets the points
+ * structure ready for returning
+ * @param current The current node
+ * @param x1-y1 The position of the first corner
+ * @param x2-y2 The position of the second corner
+ * @param x3-y3 The position of the third corner
+ */
+ void pntNode( triNodeStructure* current,
+ int x1, int y1,
+ int x2, int y2,
+ int x3, int y3 );
+
+ /**
+ * Adds a line makes sure that this line does not already exist
+ * @param pts1 The start point in the line
+ * @param pts2 The end point of the line
+ */
+ void addLine( pointStructure* pts1, pointStructure* pts2 );
+
+ /**
+ * creates the points array and clears it
+ * @return true if succesful
+ */
+ bool createPoints( );
+ /**
+ * Clears some of the points data for recalculation or all
+ * of it for initialization
+ * @param all true if all the data is to be cleared
+ */
+ void clearPoints( bool all = false );
+
+ /**
+ * creates the nodes array and clears it
+ * @return true if succesful
+ */
+ bool createNodes( );
+ /**
+ * Clears nodes for reuse in splitting recalculation or
+ * all of the data for initialization and variance
+ * @param all true if all the data is to be cleared
+ */
+ void clearNodes( bool all = false );
+
+ /**
+ * Sets the height of a point
+ * @param x the position of the point in X
+ * @param y the position of the point in Y
+ * @param hgt the new height
+ */
+ void setHeight( int x, int y, unsigned short hgt ) const
+ { m_pPoints[ x + ( y * m_size ) ].hgt = hgt; }
+
+public:
+ /**
+ * Constructor for class
+ * @param fileName Source file for the map
+ */
+ PMHeightFieldROAM( const QString &fileName );
+ /**
+ * Class Destructor relases all the memory
+ */
+ ~PMHeightFieldROAM( );
+
+ /**
+ * Returns true if there has been a problem
+ */
+ bool isFailed( ) { return m_fail; }
+
+ /**
+ * Creates the model based on the current map
+ * display detail and water level
+ */
+ void updateModel( );
+
+ /**
+ * Sets the display detail for the model
+ * @param detail The new level of detail
+ */
+ void setDisplayDetail( int detail );
+ /**
+ * Returns the current display detail
+ */
+ int displayDetail( ) const { return m_displayDetail; }
+
+ /**
+ * Sets the water level
+ * @param waterLevel the water level
+ */
+ void setWaterLevel( double m_waterLevel );
+ /**
+ * Returns the current water level
+ */
+ double waterLevel( ) const;
+
+ /**
+ * Return The size of the map in either direction
+ */
+ int size( ) const { return m_size; }
+ /**
+ * Return The total number of points in the model
+ */
+ int numPoints( ) const { return m_numPoints; }
+ /**
+ * Return The number of used points
+ */
+ int usedPoints( ) const { return m_usedPoints; }
+ /**
+ * Return The number of lines
+ */
+ int numLines( ) const { return m_numLines; }
+ /**
+ * Return the number of nodes
+ */
+ int numNodes( ) const { return m_numNodes; }
+
+ /**
+ * Returns a height of a point
+ * @param x the position of the point in X
+ * @param y the position of the point in Y
+ * @param waterLevel whether to return a point offset by water level
+ * @return the height of the point
+ */
+ unsigned short height( int x, int y, bool waterLevel = false ) const;
+
+ /**
+ * Determines if the point is used
+ * @param x The position of the point on the x axis.
+ * @param y The position of the point on the y axis.
+ * @return true if the point is used else false
+ */
+ bool usedPoint( int x, int y ) const
+ { return m_pPoints[ x + ( y * m_size ) ].used; }
+
+ /**
+ * Gets the used postion of a point
+ * @param x The position of the point on the x axis.
+ * @param y The position of the point on the y axis.
+ * @return the used position
+ */
+ int posPoint( int x, int y ) const
+ { return m_pPoints[ x + ( y * m_size ) ].pos; }
+
+ /**
+ * Returns the used position of a point at the end point of a line.
+ * @param x The position of the start point on the x axis.
+ * @param y The position of the start point on the y axis.
+ * @param line The Line Index
+ * @return The used positon of the end point
+ */
+ int endPoint( int x, int y, int line ) const
+ { return m_pPoints[ x + ( y * m_size ) ].lines[ line ]->pos; }
+
+ /**
+ * Returns whether this line exists
+ * @param x The position of the start point on the x axis.
+ * @param y The position of the start point on the y axis.
+ * @param line The Line Index
+ * @return Whether the line exists
+ */
+ bool lineExist( int x, int y, int line ) const;
+
+};
+
+#endif
diff --git a/kpovmodeler/pmimagemap.cpp b/kpovmodeler/pmimagemap.cpp
new file mode 100644
index 00000000..7fcaeb64
--- /dev/null
+++ b/kpovmodeler/pmimagemap.cpp
@@ -0,0 +1,522 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmimagemapedit.h"
+#include "pmimagemap.h"
+#include "pmpalettevalue.h"
+#include "pmpalettevaluememento.h"
+
+#include "pmxmlhelper.h"
+#include "pmcompositeobject.h"
+#include "pmmemento.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+const PMImageMap::PMBitmapType bitmapTypeDefault = PMImageMap::BitmapSys;
+const char *const bitmapFileDefault = 0;
+const bool enableFilterAllDefault = false;
+const bool enableTransmitAllDefault = false;
+const double filterAllDefault = 0.0;
+const double transmitAllDefault = 0.0;
+const bool onceDefault = false;
+const PMImageMap::PMMapType mapTypeDefault = PMImageMap::MapPlanar;
+const PMImageMap::PMInterpolateType interpolateTypeDefault = PMImageMap::InterpolateNone;
+
+PMDefinePropertyClass( PMImageMap, PMImageMapProperty );
+PMDefineEnumPropertyClass( PMImageMap, PMImageMap::PMBitmapType,
+ PMBitmapTypeProperty );
+PMDefineEnumPropertyClass( PMImageMap, PMImageMap::PMInterpolateType,
+ PMInterpolateTypeProperty );
+PMDefineEnumPropertyClass( PMImageMap, PMImageMap::PMMapType,
+ PMMapTypeProperty );
+
+PMMetaObject* PMImageMap::s_pMetaObject = 0;
+PMObject* createNewImageMap( PMPart* part )
+{
+ return new PMImageMap( part );
+}
+
+PMImageMap::PMImageMap( PMPart* part )
+ : Base( part )
+{
+ m_bitmapType = bitmapTypeDefault;
+ m_bitmapFile = bitmapFileDefault;
+ m_enableFilterAll = enableFilterAllDefault;
+ m_filterAll = filterAllDefault;
+ m_enableTransmitAll = enableTransmitAllDefault;
+ m_transmitAll = transmitAllDefault;
+ m_once = onceDefault;
+ m_mapType = mapTypeDefault;
+ m_interpolateType = interpolateTypeDefault;
+}
+
+PMImageMap::PMImageMap( const PMImageMap& m )
+ : Base( m )
+{
+ m_bitmapType = m.m_bitmapType;
+ m_bitmapFile = m.m_bitmapFile;
+ m_enableFilterAll = m.m_enableFilterAll;
+ m_filterAll = m.m_filterAll;
+ m_enableTransmitAll = m.m_enableTransmitAll;
+ m_transmitAll = m.m_transmitAll;
+ m_once = m.m_once;
+ m_mapType = m.m_mapType;
+ m_interpolateType = m.m_interpolateType;
+ m_filters = m.m_filters;
+ m_transmits = m.m_transmits;
+}
+
+PMImageMap::~PMImageMap( )
+{
+}
+
+void PMImageMap::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ switch( m_bitmapType )
+ {
+ case BitmapGif:
+ e.setAttribute( "bitmap_type", "gif" );
+ break;
+ case BitmapTga:
+ e.setAttribute( "bitmap_type", "tga" );
+ break;
+ case BitmapIff:
+ e.setAttribute( "bitmap_type", "iff" );
+ break;
+ case BitmapPpm:
+ e.setAttribute( "bitmap_type", "ppm" );
+ break;
+ case BitmapPgm:
+ e.setAttribute( "bitmap_type", "pgm" );
+ break;
+ case BitmapPng:
+ e.setAttribute( "bitmap_type", "png" );
+ break;
+ case BitmapJpeg:
+ e.setAttribute( "bitmap_type", "jpeg" );
+ break;
+ case BitmapTiff:
+ e.setAttribute( "bitmap_type", "tiff" );
+ break;
+ case BitmapSys:
+ e.setAttribute( "bitmap_type", "sys" );
+ break;
+ }
+ e.setAttribute( "file_name", m_bitmapFile );
+ e.setAttribute( "enable_filter_all", m_enableFilterAll );
+ e.setAttribute( "filter_all", m_filterAll );
+ e.setAttribute( "enable_transmit_all", m_enableTransmitAll );
+ e.setAttribute( "transmit_all", m_transmitAll );
+ e.setAttribute( "once", m_once );
+
+ QDomElement extra_data = doc.createElement( "extra_data" );
+
+ QDomElement data = doc.createElement( "indexed_filters" );
+ QDomElement p;
+
+ QValueList<PMPaletteValue>::ConstIterator it;
+ for( it = m_filters.begin( ); it != m_filters.end( ); ++it )
+ {
+ p = doc.createElement( "index_filter" );
+ ( *it ).serialize( p, doc );
+ data.appendChild( p );
+ }
+ extra_data.appendChild( data );
+
+ data = doc.createElement( "indexed_transmits" );
+ for( it = m_transmits.begin( ); it != m_transmits.end( ); ++it )
+ {
+ p = doc.createElement( "index_transmit" );
+ ( *it ).serialize( p, doc );
+ data.appendChild( p );
+ }
+ extra_data.appendChild( data );
+
+ e.appendChild( extra_data );
+
+ switch( m_mapType )
+ {
+ case MapPlanar:
+ e.setAttribute( "map_type", "planar" );
+ break;
+ case MapSpherical:
+ e.setAttribute( "map_type", "spherical" );
+ break;
+ case MapCylindrical:
+ e.setAttribute( "map_type", "cylindrical" );
+ break;
+ case MapToroidal:
+ e.setAttribute( "map_type", "toroidal" );
+ break;
+ }
+ switch( m_interpolateType )
+ {
+ case InterpolateNone:
+ e.setAttribute( "interpolate", "none" );
+ break;
+ case InterpolateBilinear:
+ e.setAttribute( "interpolate", "bilinear" );
+ break;
+ case InterpolateNormalized:
+ e.setAttribute( "interpolate", "normalized" );
+ break;
+ }
+ Base::serialize( e, doc );
+}
+
+void PMImageMap::readAttributes( const PMXMLHelper& h )
+{
+ QString str;
+
+ str = h.stringAttribute( "bitmap_type", "sys" );
+ if( str == "gif" )
+ m_bitmapType = BitmapGif;
+ else if( str == "tga" )
+ m_bitmapType = BitmapTga;
+ else if( str == "iff" )
+ m_bitmapType = BitmapIff;
+ else if( str == "ppm" )
+ m_bitmapType = BitmapPpm;
+ else if( str == "pgm" )
+ m_bitmapType = BitmapPgm;
+ else if( str == "png" )
+ m_bitmapType = BitmapPng;
+ else if( str == "jpeg" )
+ m_bitmapType = BitmapJpeg;
+ else if( str == "tiff" )
+ m_bitmapType = BitmapTiff;
+ else if( str == "sys" )
+ m_bitmapType = BitmapSys;
+
+ m_bitmapFile = h.stringAttribute( "file_name", bitmapFileDefault );
+ m_enableFilterAll = h.boolAttribute( "enable_filter_all", enableFilterAllDefault );
+ m_filterAll = h.doubleAttribute( "filter_all", filterAllDefault );
+ m_enableTransmitAll = h.boolAttribute( "enable_transmit_all", enableTransmitAllDefault );
+ m_transmitAll = h.doubleAttribute( "transmit_all", transmitAllDefault );
+ m_once = h.boolAttribute( "once", onceDefault );
+
+ QDomElement e = h.extraData( );
+ if( !e.isNull( ) )
+ {
+ QDomNode c = e.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ if( ce.tagName( ) == "indexed_filters" )
+ {
+ m_filters.clear( );
+ QDomNode cd = ce.firstChild( );
+ while( !cd.isNull( ) )
+ {
+ if( cd.isElement( ) )
+ {
+ PMPaletteValue pv;
+ pv.readAttributes( cd.toElement( ) );
+ m_filters.append( pv );
+ }
+ cd = cd.nextSibling( );
+ }
+ }
+ if( ce.tagName( ) == "indexed_transmits" )
+ {
+ m_transmits.clear( );
+ QDomNode cd = ce.firstChild( );
+ while( !cd.isNull( ) )
+ {
+ if( cd.isElement( ) )
+ {
+ PMPaletteValue pv;
+ pv.readAttributes( cd.toElement( ) );
+ m_transmits.append( pv );
+ }
+ cd = cd.nextSibling( );
+ }
+ }
+ }
+ c = c.nextSibling( );
+ }
+ }
+
+ str = h.stringAttribute( "map_type", "planar" );
+ if( str == "planar" )
+ m_mapType = MapPlanar;
+ else if( str == "spherical" )
+ m_mapType = MapSpherical;
+ else if( str == "cylindrical" )
+ m_mapType = MapCylindrical;
+ else if( str == "toroidal" )
+ m_mapType = MapToroidal;
+
+ str = h.stringAttribute( "interpolate", "none" );
+ if( str == "none" )
+ m_interpolateType = InterpolateNone;
+ else if( str == "bilinear" )
+ m_interpolateType = InterpolateBilinear;
+ else if( str == "normalized" )
+ m_interpolateType = InterpolateNormalized;
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMImageMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "ImageMap", Base::metaObject( ),
+ createNewImageMap );
+
+ PMBitmapTypeProperty* bp = new PMBitmapTypeProperty(
+ "bitmapType", &PMImageMap::setBitmapType, &PMImageMap::bitmapType );
+ bp->addEnumValue( "Gif", BitmapGif );
+ bp->addEnumValue( "Tga", BitmapTga );
+ bp->addEnumValue( "Iff", BitmapIff );
+ bp->addEnumValue( "Ppm", BitmapPpm );
+ bp->addEnumValue( "Pgm", BitmapPgm );
+ bp->addEnumValue( "Png", BitmapPng );
+ bp->addEnumValue( "Jpeg", BitmapJpeg );
+ bp->addEnumValue( "Tiff", BitmapTiff );
+ bp->addEnumValue( "Sys", BitmapSys );
+ s_pMetaObject->addProperty( bp );
+
+ PMInterpolateTypeProperty* ip = new PMInterpolateTypeProperty(
+ "interpolateType", &PMImageMap::setInterpolateType,
+ &PMImageMap::interpolateType );
+ ip->addEnumValue( "None", InterpolateNone );
+ ip->addEnumValue( "Bilinear", InterpolateBilinear );
+ ip->addEnumValue( "Normalized", InterpolateNormalized );
+ s_pMetaObject->addProperty( ip );
+
+ PMMapTypeProperty* mp = new PMMapTypeProperty(
+ "mapType", &PMImageMap::setMapType, &PMImageMap::mapType );
+ mp->addEnumValue( "Planar", MapPlanar );
+ mp->addEnumValue( "Spherical", MapSpherical );
+ mp->addEnumValue( "Cylindrical", MapCylindrical );
+ mp->addEnumValue( "Toroidal", MapToroidal );
+ s_pMetaObject->addProperty( mp );
+
+ s_pMetaObject->addProperty(
+ new PMImageMapProperty( "bitmapFile", &PMImageMap::setBitmapFileName,
+ &PMImageMap::bitmapFile ) );
+ s_pMetaObject->addProperty(
+ new PMImageMapProperty( "filterAllEnabled", &PMImageMap::enableFilterAll,
+ &PMImageMap::isFilterAllEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMImageMapProperty( "filterAll", &PMImageMap::setFilterAll,
+ &PMImageMap::filterAll ) );
+ s_pMetaObject->addProperty(
+ new PMImageMapProperty( "transmitAllEnabled", &PMImageMap::enableTransmitAll,
+ &PMImageMap::isTransmitAllEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMImageMapProperty( "transmitAll", &PMImageMap::setTransmitAll,
+ &PMImageMap::transmitAll ) );
+ s_pMetaObject->addProperty(
+ new PMImageMapProperty( "once", &PMImageMap::enableOnce, &PMImageMap::isOnceEnabled ) );
+
+ // TODO: filters and transmits properties
+ }
+ return s_pMetaObject;
+}
+
+void PMImageMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMImageMap::description( ) const
+{
+ return i18n( "imagemap" );
+}
+
+void PMImageMap::setBitmapType( PMBitmapType c )
+{
+ if( c != m_bitmapType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBitmapTypeID, m_bitmapType );
+ m_bitmapType = c;
+ }
+}
+
+void PMImageMap::setBitmapFileName( const QString& c )
+{
+ if( c != m_bitmapFile )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBitmapFileID, m_bitmapFile );
+ m_bitmapFile = c;
+ }
+}
+
+void PMImageMap::enableFilterAll( bool c )
+{
+ if( c != m_enableFilterAll )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableFilterAllID, m_enableFilterAll );
+ m_enableFilterAll = c;
+ }
+}
+
+void PMImageMap::enableTransmitAll( bool c )
+{
+ if( c != m_enableTransmitAll )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableTransmitAllID, m_enableTransmitAll );
+ m_enableTransmitAll = c;
+ }
+}
+
+void PMImageMap::setFilterAll( double c )
+{
+ if( c != m_filterAll )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFilterAllID, m_filterAll );
+ m_filterAll = c;
+ }
+}
+
+void PMImageMap::setTransmitAll( double c )
+{
+ if( c != m_transmitAll )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFilterAllID, m_transmitAll );
+ m_transmitAll = c;
+ }
+}
+
+void PMImageMap::enableOnce( bool c )
+{
+ if( c != m_once )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOnceID, m_once );
+ m_once = c;
+ }
+}
+
+void PMImageMap::setMapType( PMMapType c )
+{
+ if( c != m_mapType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMapTypeID, m_mapType );
+ m_mapType = c;
+ }
+}
+
+void PMImageMap::setInterpolateType( PMInterpolateType c )
+{
+ if( c != m_interpolateType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMInterpolateID, m_interpolateType );
+ m_interpolateType = c;
+ }
+}
+
+void PMImageMap::setFilters( const QValueList<PMPaletteValue>& c )
+{
+ if( m_filters != c )
+ {
+ if( m_pMemento )
+ ( ( PMPaletteValueMemento* ) m_pMemento )->setFilterPaletteValues( m_filters );
+ m_filters = c;
+ }
+}
+
+void PMImageMap::setTransmits( const QValueList<PMPaletteValue>& c )
+{
+ if( m_transmits != c )
+ {
+ if( m_pMemento )
+ ( ( PMPaletteValueMemento* ) m_pMemento )->setTransmitPaletteValues( m_transmits );
+ m_transmits = c;
+ }
+}
+
+PMDialogEditBase* PMImageMap::editWidget( QWidget* parent ) const
+{
+ return new PMImageMapEdit( parent );
+}
+
+void PMImageMap::restoreMemento( PMMemento* s )
+{
+ PMPaletteValueMemento* m = ( PMPaletteValueMemento* ) s;
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMBitmapTypeID:
+ setBitmapType( ( PMBitmapType )data->intData( ) );
+ break;
+ case PMBitmapFileID:
+ setBitmapFileName( data->stringData( ) );
+ break;
+ case PMEnableFilterAllID:
+ enableFilterAll( data->boolData( ) );
+ break;
+ case PMEnableTransmitAllID:
+ enableTransmitAll( data->boolData( ) );
+ break;
+ case PMFilterAllID:
+ setFilterAll( data->doubleData( ) );
+ break;
+ case PMTransmitAllID:
+ setTransmitAll( data->doubleData( ) );
+ break;
+ case PMOnceID:
+ enableOnce( data->boolData( ) );
+ break;
+ case PMMapTypeID:
+ setMapType( ( PMMapType )data->intData( ) );
+ break;
+ case PMInterpolateID:
+ setInterpolateType( ( PMInterpolateType )data->intData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMImageMap::restoreMemento\n";
+ break;
+ }
+ }
+ }
+
+ if( m->filterPaletteValuesSaved( ) )
+ setFilters( m->filterPaletteValues( ) );
+
+ if( m->transmitPaletteValuesSaved( ) )
+ setTransmits( m->transmitPaletteValues( ) );
+
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmimagemap.h b/kpovmodeler/pmimagemap.h
new file mode 100644
index 00000000..3291994d
--- /dev/null
+++ b/kpovmodeler/pmimagemap.h
@@ -0,0 +1,209 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMIMAGEMAP_H
+#define PMIMAGEMAP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+#include "pmpalettevalue.h"
+
+/**
+ * Class for povray imagemaps.
+ */
+
+class PMImageMap : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+public:
+ /**
+ * The bitmap type
+ */
+ enum PMBitmapType { BitmapGif, BitmapTga, BitmapIff, BitmapPpm,
+ BitmapPgm, BitmapPng, BitmapJpeg, BitmapTiff,
+ BitmapSys };
+ /**
+ * The interpolate method
+ */
+ enum PMInterpolateType { InterpolateNone, InterpolateBilinear,
+ InterpolateNormalized };
+ /**
+ * The mapping method
+ */
+ enum PMMapType { MapPlanar, MapSpherical, MapCylindrical,
+ MapToroidal };
+
+ /**
+ * Creates a PMImageMap
+ */
+ PMImageMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMImageMap( const PMImageMap& im );
+ /**
+ * deletes the PMImageMap
+ */
+ virtual ~PMImageMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMImageMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmimagemap" ); }
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMImageMapEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+
+ /**
+ * Gets the bitmap type
+ */
+ PMBitmapType bitmapType( ) const { return m_bitmapType; }
+ /**
+ * Gets the bitmap file name
+ */
+ QString bitmapFile( ) const { return m_bitmapFile; }
+ /**
+ * Returns true if filter all is enabled
+ */
+ bool isFilterAllEnabled( ) const { return m_enableFilterAll; }
+ /**
+ * Gets the value of filter for all colors
+ */
+ double filterAll( ) const { return m_filterAll; }
+ /**
+ * Returns true if transmit all is enabled
+ */
+ bool isTransmitAllEnabled( ) const { return m_enableTransmitAll; }
+ /**
+ * Gets the value of transmit all for all colors
+ */
+ double transmitAll( ) const { return m_transmitAll; }
+ /**
+ * Returns true if once is enabled
+ */
+ bool isOnceEnabled( ) const { return m_once; }
+ /**
+ * Gets the bitmap file type
+ */
+ PMMapType mapType( ) const { return m_mapType; }
+ /**
+ * Gets the interpolate method type
+ */
+ PMInterpolateType interpolateType( ) const { return m_interpolateType; }
+ /**
+ * Gets the list of indexed filters
+ */
+ QValueList<PMPaletteValue> filters( ) const { return m_filters; }
+ /**
+ * Gets the list of indexed transmits
+ */
+ QValueList<PMPaletteValue> transmits( ) const { return m_transmits; }
+
+ /**
+ * Sets the imagemap type
+ */
+ void setBitmapType( PMBitmapType c );
+ /**
+ * Sets the bitmap file name*/
+ void setBitmapFileName( const QString& c );
+ /**
+ * Enables/Disables Filter All
+ */
+ void enableFilterAll( bool c );
+ /**
+ * Sets the filter all value
+ */
+ void setFilterAll( double c );
+ /**
+ * Enables/Disables Transmit All
+ */
+ void enableTransmitAll( bool c );
+ /**
+ * Sets the transmit all value
+ */
+ void setTransmitAll( double c );
+ /**
+ * Sets if the bitmap should be mapped once
+ */
+ void enableOnce( bool c );
+ /**
+ * Sets the mapping method
+ */
+ void setMapType( const PMMapType c );
+ /**
+ * Sets the interpolating method
+ */
+ void setInterpolateType( PMInterpolateType c );
+ /**
+ * Set the list of indexed filters
+ */
+ void setFilters( const QValueList<PMPaletteValue>& filters );
+ /**
+ * Set the list of indexed transmits
+ */
+ void setTransmits( const QValueList<PMPaletteValue>& transmits );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMImageMapMementoID { PMBitmapTypeID, PMBitmapFileID,
+ PMEnableFilterAllID,
+ PMEnableTransmitAllID,
+ PMFilterAllID, PMTransmitAllID,
+ PMOnceID, PMMapTypeID,
+ PMInterpolateID };
+ /**
+ * ImageMap type
+ */
+ PMBitmapType m_bitmapType;
+ QString m_bitmapFile;
+ bool m_enableFilterAll;
+ float m_filterAll;
+ bool m_enableTransmitAll;
+ float m_transmitAll;
+ bool m_once;
+ PMMapType m_mapType;
+ PMInterpolateType m_interpolateType;
+ QValueList<PMPaletteValue> m_filters;
+ QValueList<PMPaletteValue> m_transmits;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmimagemapedit.cpp b/kpovmodeler/pmimagemapedit.cpp
new file mode 100644
index 00000000..c43443df
--- /dev/null
+++ b/kpovmodeler/pmimagemapedit.cpp
@@ -0,0 +1,625 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmimagemapedit.h"
+#include "pmimagemap.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmpalettevalueedit.h"
+#include "pmvector.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <ktabctl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+
+PMImageMapEdit::PMImageMapEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMImageMapEdit::createTopWidgets( )
+{
+ QLabel* lbl;
+ QHBoxLayout* hl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "File type:" ), this );
+ m_pImageFileTypeEdit = new QComboBox( this );
+ m_pImageFileTypeEdit->insertItem( "gif" );
+ m_pImageFileTypeEdit->insertItem( "tga" );
+ m_pImageFileTypeEdit->insertItem( "iff" );
+ m_pImageFileTypeEdit->insertItem( "ppm" );
+ m_pImageFileTypeEdit->insertItem( "pgm" );
+ m_pImageFileTypeEdit->insertItem( "png" );
+ m_pImageFileTypeEdit->insertItem( "jpeg" );
+ m_pImageFileTypeEdit->insertItem( "tiff" );
+ m_pImageFileTypeEdit->insertItem( "sys" );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pImageFileTypeEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "File name:" ), this );
+ m_pImageFileNameEdit = new QLineEdit( this );
+ m_pImageFileNameBrowse = new QPushButton( this );
+ m_pImageFileNameBrowse->setPixmap( SmallIcon( "fileopen" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pImageFileNameEdit );
+ hl->addWidget( m_pImageFileNameBrowse );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pEnableFilterAllEdit = new QCheckBox( i18n( "Filter all" ), this );
+ m_pFilterAllEdit = new PMFloatEdit( this );
+ hl->addWidget( m_pEnableFilterAllEdit );
+ hl->addWidget( m_pFilterAllEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pEnableTransmitAllEdit = new QCheckBox( i18n( "Transmit all" ), this );
+ m_pTransmitAllEdit = new PMFloatEdit( this );
+ hl->addWidget( m_pEnableTransmitAllEdit );
+ hl->addWidget( m_pTransmitAllEdit );
+ hl->addStretch( 1 );
+
+ m_pOnceEdit = new QCheckBox( i18n( "Once" ), this );
+ topLayout( )->addWidget( m_pOnceEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Interpolate:" ), this );
+ m_pInterpolateTypeEdit = new QComboBox( this );
+ m_pInterpolateTypeEdit->insertItem( i18n( "None" ) );
+ m_pInterpolateTypeEdit->insertItem( i18n( "Bilinear" ) );
+ m_pInterpolateTypeEdit->insertItem( i18n( "Normalized" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pInterpolateTypeEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Map type:" ), this );
+ m_pMapTypeEdit = new QComboBox( this );
+ m_pMapTypeEdit->insertItem( i18n( "Planar" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Spherical" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Cylindrical" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Toroidal" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pMapTypeEdit );
+
+ connect( m_pImageFileTypeEdit, SIGNAL( activated( int ) ), SLOT( slotImageFileTypeChanged( int ) ) );
+ connect( m_pMapTypeEdit, SIGNAL( activated( int ) ), SLOT( slotMapTypeChanged( int ) ) );
+ connect( m_pInterpolateTypeEdit, SIGNAL( activated( int ) ), SLOT( slotInterpolateTypeChanged( int ) ) );
+ connect( m_pImageFileNameBrowse, SIGNAL( clicked( ) ), SLOT( slotImageFileBrowseClicked( ) ) );
+ connect( m_pImageFileNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotImageFileNameChanged( const QString& ) ) );
+ connect( m_pEnableFilterAllEdit, SIGNAL( clicked( ) ), SLOT( slotFilterAllClicked( ) ) );
+ connect( m_pEnableTransmitAllEdit, SIGNAL( clicked( ) ), SLOT( slotTransmitAllClicked( ) ) );
+ connect( m_pFilterAllEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pTransmitAllEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOnceEdit, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMImageMapEdit::createBottomWidgets( )
+{
+ topLayout( )->addWidget( new QLabel( i18n( "Indexed filters" ), this ) );
+ m_pFiltersWidget = new QWidget( this );
+ topLayout( )->addWidget( m_pFiltersWidget );
+ topLayout( )->addWidget( new QLabel( i18n( "Indexed transmits" ), this ) );
+ m_pTransmitsWidget = new QWidget( this );
+ topLayout( )->addWidget( m_pTransmitsWidget );
+
+
+ Base::createBottomWidgets( );
+}
+
+void PMImageMapEdit::displayObject( PMObject* o )
+{
+ bool readOnly;
+
+ if( o->isA( "ImageMap" ) )
+ {
+ m_pDisplayedObject = ( PMImageMap* ) o;
+ readOnly = m_pDisplayedObject->isReadOnly( );
+
+ switch( m_pDisplayedObject->bitmapType( ) )
+ {
+ case PMImageMap::BitmapGif:
+ m_pImageFileTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMImageMap::BitmapTga:
+ m_pImageFileTypeEdit->setCurrentItem( 1 );
+ break;
+ case PMImageMap::BitmapIff:
+ m_pImageFileTypeEdit->setCurrentItem( 2 );
+ break;
+ case PMImageMap::BitmapPpm:
+ m_pImageFileTypeEdit->setCurrentItem( 3 );
+ break;
+ case PMImageMap::BitmapPgm:
+ m_pImageFileTypeEdit->setCurrentItem( 4 );
+ break;
+ case PMImageMap::BitmapPng:
+ m_pImageFileTypeEdit->setCurrentItem( 5 );
+ break;
+ case PMImageMap::BitmapJpeg:
+ m_pImageFileTypeEdit->setCurrentItem( 6 );
+ break;
+ case PMImageMap::BitmapTiff:
+ m_pImageFileTypeEdit->setCurrentItem( 7 );
+ break;
+ case PMImageMap::BitmapSys:
+ m_pImageFileTypeEdit->setCurrentItem( 8 );
+ break;
+ }
+ m_pImageFileTypeEdit->setEnabled( !readOnly );
+
+ switch( m_pDisplayedObject->interpolateType( ) )
+ {
+ case PMImageMap::InterpolateNone:
+ m_pInterpolateTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMImageMap::InterpolateBilinear:
+ m_pInterpolateTypeEdit->setCurrentItem( 1);
+ break;
+ case PMImageMap::InterpolateNormalized:
+ m_pInterpolateTypeEdit->setCurrentItem( 2 );
+ break;
+ }
+ m_pInterpolateTypeEdit->setEnabled( !readOnly );
+
+ switch( m_pDisplayedObject->mapType( ) )
+ {
+ case PMImageMap::MapPlanar:
+ m_pMapTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMImageMap::MapSpherical:
+ m_pMapTypeEdit->setCurrentItem( 1 );
+ break;
+ case PMImageMap::MapCylindrical:
+ m_pMapTypeEdit->setCurrentItem( 2 );
+ break;
+ case PMImageMap::MapToroidal:
+ m_pMapTypeEdit->setCurrentItem( 3 );
+ break;
+ }
+ m_pMapTypeEdit->setEnabled( !readOnly );
+
+ m_pImageFileNameEdit->setText( m_pDisplayedObject->bitmapFile( ) );
+ m_pImageFileNameEdit->setEnabled( !readOnly );
+ m_pOnceEdit->setChecked( m_pDisplayedObject->isOnceEnabled( ) );
+ m_pOnceEdit->setEnabled( !readOnly );
+ m_pEnableFilterAllEdit->setChecked( m_pDisplayedObject->isFilterAllEnabled( ) );
+ m_pEnableFilterAllEdit->setEnabled( !readOnly );
+ m_pFilterAllEdit->setValue( m_pDisplayedObject->filterAll( ) );
+ m_pFilterAllEdit->setReadOnly( readOnly );
+ m_pEnableTransmitAllEdit->setChecked( m_pDisplayedObject->isTransmitAllEnabled( ) );
+ m_pEnableTransmitAllEdit->setEnabled( !readOnly );
+ m_pTransmitAllEdit->setValue( m_pDisplayedObject->transmitAll( ) );
+ m_pTransmitAllEdit->setReadOnly( readOnly );
+
+ displayPaletteEntries( m_pDisplayedObject->filters( ), m_pDisplayedObject->transmits( ) );
+
+ slotFilterAllClicked( );
+ slotTransmitAllClicked( );
+
+ Base::displayObject( o );
+ }
+
+}
+
+void PMImageMapEdit::displayPaletteEntries( const QValueList<PMPaletteValue>& filters,
+ const QValueList<PMPaletteValue>& transmits )
+{
+ bool readOnly = m_pDisplayedObject->isReadOnly( );
+
+ int nfilters = ( int ) filters.count( );
+ int ntransmits = ( int ) transmits.count( );
+
+ int i;
+ PMPaletteValueEdit* edit;
+ QPushButton* button;
+ QGridLayout* gl;
+ QPixmap addButtonPixmap = SmallIcon( "pmaddpoint" );
+ QPixmap removeButtonPixmap = SmallIcon( "pmremovepoint" );
+
+ // First let's deal with the filter entries...
+ if( m_pFiltersWidget->layout( ) )
+ delete m_pFiltersWidget->layout( );
+
+ m_filterEntries.setAutoDelete( true );
+ m_filterAddButtons.setAutoDelete( true );
+ m_filterRemoveButtons.setAutoDelete( true );
+ m_filterEntries.clear( );
+ m_filterAddButtons.clear( );
+ m_filterRemoveButtons.clear( );
+ m_filterEntries.setAutoDelete( false );
+ m_filterAddButtons.setAutoDelete( false );
+ m_filterRemoveButtons.setAutoDelete( false );
+
+ gl = new QGridLayout( m_pFiltersWidget, nfilters + 1, 3, 0, KDialog::spacingHint( ) );
+
+ button = new QPushButton( m_pFiltersWidget );
+ button->setPixmap( addButtonPixmap );
+ m_filterAddButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotAddFilterEntry( ) ) );
+ gl->addWidget( button, 0, 1 );
+ button->show( );
+ button->setEnabled( !readOnly );
+ QToolTip::add( button, i18n( "Add new filter" ) );
+
+ for( i = 0; i < nfilters; i ++ )
+ {
+ edit = new PMPaletteValueEdit( m_pFiltersWidget );
+ m_filterEntries.append( edit );
+ connect( edit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ gl->addWidget( edit, i+1, 0 );
+ edit->setIndex( filters[ i ].index( ) );
+ edit->setValue( filters[ i ].value( ) );
+ edit->show( );
+ edit->setReadOnly( readOnly );
+
+ button = new QPushButton( m_pFiltersWidget );
+ button->setPixmap( addButtonPixmap );
+ m_filterAddButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotAddFilterEntry( ) ) );
+ gl->addWidget( button, i+1, 1 );
+ button->show( );
+ button->setEnabled( !readOnly );
+ QToolTip::add( button, i18n( "Add new filter" ) );
+
+ button = new QPushButton( m_pFiltersWidget );
+ button->setPixmap( removeButtonPixmap );
+ m_filterRemoveButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotRemoveFilterEntry( ) ) );
+ gl->addWidget( button, i+1, 2 );
+ button->show( );
+ button->setEnabled( !readOnly );
+ QToolTip::add( button, i18n( "Remove filter" ) );
+ }
+
+ // ...next the transmit entries
+ m_transmitEntries.setAutoDelete( true );
+ m_transmitAddButtons.setAutoDelete( true );
+ m_transmitRemoveButtons.setAutoDelete( true );
+ m_transmitEntries.clear( );
+ m_transmitAddButtons.clear( );
+ m_transmitRemoveButtons.clear( );
+ m_transmitEntries.setAutoDelete( false );
+ m_transmitAddButtons.setAutoDelete( false );
+ m_transmitRemoveButtons.setAutoDelete( false );
+
+ // recreate the entry edits
+ if( m_pTransmitsWidget->layout( ) )
+ delete m_pTransmitsWidget->layout( );
+
+ gl = new QGridLayout( m_pTransmitsWidget, ntransmits + 1, 3, 0, KDialog::spacingHint( ) );
+
+ button = new QPushButton( m_pTransmitsWidget );
+ button->setPixmap( addButtonPixmap );
+ m_transmitAddButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotAddTransmitEntry( ) ) );
+ gl->addWidget( button, 0, 1 );
+ button->show( );
+ button->setEnabled( !readOnly );
+ QToolTip::add( button, i18n( "Add new transmit" ) );
+
+ for( i = 0; i < ntransmits; i ++ )
+ {
+ edit = new PMPaletteValueEdit( m_pTransmitsWidget );
+ m_transmitEntries.append( edit );
+ connect( edit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ gl->addWidget( edit, i+1, 0 );
+ edit->setIndex( transmits[ i ].index( ) );
+ edit->setValue( transmits[ i ].value( ) );
+ edit->show( );
+ edit->setReadOnly( readOnly );
+
+ button = new QPushButton( m_pTransmitsWidget );
+ button->setPixmap( addButtonPixmap );
+ m_transmitAddButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotAddTransmitEntry( ) ) );
+ gl->addWidget( button, i+1, 1 );
+ button->show( );
+ button->setEnabled( !readOnly );
+ QToolTip::add( button, i18n( "Add new transmit" ) );
+
+ button = new QPushButton( m_pTransmitsWidget );
+ button->setPixmap( removeButtonPixmap );
+ m_transmitRemoveButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotRemoveTransmitEntry( ) ) );
+ gl->addWidget( button, i+1, 2 );
+ button->show( );
+ button->setEnabled( !readOnly );
+ QToolTip::add( button, i18n( "Remove transmit" ) );
+ }
+}
+
+void PMImageMapEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ switch( m_pImageFileTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapGif );
+ break;
+ case 1:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapTga );
+ break;
+ case 2:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapIff );
+ break;
+ case 3:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapPpm );
+ break;
+ case 4:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapPgm );
+ break;
+ case 5:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapPng );
+ break;
+ case 6:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapJpeg );
+ break;
+ case 7:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapTiff );
+ break;
+ case 8:
+ m_pDisplayedObject->setBitmapType( PMImageMap::BitmapSys );
+ break;
+ }
+
+ switch( m_pInterpolateTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setInterpolateType( PMImageMap::InterpolateNone );
+ break;
+ case 1:
+ m_pDisplayedObject->setInterpolateType( PMImageMap::InterpolateBilinear );
+ break;
+ case 2:
+ m_pDisplayedObject->setInterpolateType( PMImageMap::InterpolateNormalized );
+ break;
+ }
+
+ switch( m_pMapTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setMapType( PMImageMap::MapPlanar );
+ break;
+ case 1:
+ m_pDisplayedObject->setMapType( PMImageMap::MapSpherical );
+ break;
+ case 2:
+ m_pDisplayedObject->setMapType( PMImageMap::MapCylindrical );
+ break;
+ case 3:
+ m_pDisplayedObject->setMapType( PMImageMap::MapToroidal );
+ break;
+ }
+
+ m_pDisplayedObject->setFilters( filters( ) );
+ m_pDisplayedObject->setTransmits( transmits( ) );
+
+ m_pDisplayedObject->setBitmapFileName( m_pImageFileNameEdit->text( ) );
+ m_pDisplayedObject->enableFilterAll( m_pEnableFilterAllEdit->isChecked( ) );
+ m_pDisplayedObject->setFilterAll( m_pFilterAllEdit->value( ) );
+ m_pDisplayedObject->enableTransmitAll( m_pEnableTransmitAllEdit->isChecked( ) );
+ m_pDisplayedObject->setTransmitAll( m_pTransmitAllEdit->value( ) );
+ m_pDisplayedObject->enableOnce( m_pOnceEdit->isChecked( ) );
+ }
+}
+
+bool PMImageMapEdit::isDataValid( )
+{
+ if( !m_pFilterAllEdit->isDataValid( ) ) return false;
+ if( !m_pTransmitAllEdit->isDataValid( ) ) return false;
+
+ QPtrListIterator<PMPaletteValueEdit> it_filters( m_filterEntries );
+ for( ; it_filters.current( ); ++it_filters )
+ if( !( it_filters.current( )->isDataValid( ) ) )
+ return false;
+
+ QPtrListIterator<PMPaletteValueEdit> it_transmits( m_transmitEntries );
+ for( ; it_transmits.current( ); ++it_transmits )
+ if( !( it_transmits.current( )->isDataValid( ) ) )
+ return false;
+
+ return Base::isDataValid( );
+}
+
+void PMImageMapEdit::slotInterpolateTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMImageMapEdit::slotImageFileTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMImageMapEdit::slotMapTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMImageMapEdit::slotImageFileNameChanged( const QString& /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMImageMapEdit::slotImageFileBrowseClicked( )
+{
+ QString str = KFileDialog::getOpenFileName( QString::null, QString::null );
+
+ if( !str.isEmpty() )
+ {
+ m_pImageFileNameEdit->setText( str );
+ emit dataChanged( );
+ }
+}
+
+void PMImageMapEdit::slotFilterAllClicked( )
+{
+ if( m_pEnableFilterAllEdit->isChecked( ) )
+ m_pFilterAllEdit->setEnabled( true );
+ else
+ m_pFilterAllEdit->setEnabled( false );
+ emit sizeChanged( );
+ emit dataChanged( );
+}
+
+void PMImageMapEdit::slotTransmitAllClicked( )
+{
+ if( m_pEnableTransmitAllEdit->isChecked( ) )
+ m_pTransmitAllEdit->setEnabled( true );
+ else
+ m_pTransmitAllEdit->setEnabled( false );
+ emit sizeChanged( );
+ emit dataChanged( );
+}
+
+QValueList<PMPaletteValue> PMImageMapEdit::filters( )
+{
+ QValueList<PMPaletteValue> entries;
+ QPtrListIterator<PMPaletteValueEdit> it( m_filterEntries );
+
+ for( ; it.current( ); ++it )
+ entries.append( PMPaletteValue( it.current( )->index( ), it.current( )->value( ) ) );
+
+ return entries;
+}
+
+QValueList<PMPaletteValue> PMImageMapEdit::transmits( )
+{
+ QValueList<PMPaletteValue> entries;
+ QPtrListIterator<PMPaletteValueEdit> it( m_transmitEntries );
+
+ for( ; it.current( ); ++it )
+ entries.append( PMPaletteValue( it.current( )->index( ), it.current( )->value( ) ) );
+
+ return entries;
+}
+
+void PMImageMapEdit::slotAddFilterEntry( )
+{
+ QValueList<PMPaletteValue> entriesFilters;
+ QValueListIterator<PMPaletteValue> it;
+ PMPaletteValue newEntry;
+ QPushButton* button = ( QPushButton* ) sender( );
+
+ if( button )
+ {
+ int index = m_filterAddButtons.findRef( button );
+ if( index >= 0 )
+ {
+ entriesFilters = filters( );
+ if( index == 0 )
+ entriesFilters.prepend( newEntry );
+ else
+ {
+ it = entriesFilters.at( index );
+ entriesFilters.insert( it, newEntry );
+ }
+ displayPaletteEntries( entriesFilters, transmits( ) );
+ emit sizeChanged( );
+ emit dataChanged( );
+ }
+ }
+}
+
+void PMImageMapEdit::slotRemoveFilterEntry( )
+{
+ QValueList<PMPaletteValue> entriesFilters;
+ QValueListIterator<PMPaletteValue> it;
+ QPushButton* button = ( QPushButton* ) sender( );
+
+ if( button )
+ {
+ int index = m_filterRemoveButtons.findRef( button );
+ if( index >= 0 )
+ {
+ entriesFilters = filters( );
+ it = entriesFilters.at( index );
+ entriesFilters.remove( it );
+ displayPaletteEntries( entriesFilters, transmits( ) );
+ emit sizeChanged( );
+ emit dataChanged( );
+ }
+ }
+}
+
+void PMImageMapEdit::slotAddTransmitEntry( )
+{
+ QValueList<PMPaletteValue> entriesTransmits;
+ QValueListIterator<PMPaletteValue> it;
+ PMPaletteValue newEntry;
+ QPushButton* button = ( QPushButton* ) sender( );
+
+ if( button )
+ {
+ int index = m_transmitAddButtons.findRef( button );
+ if( index >= 0 )
+ {
+ entriesTransmits = transmits( );
+ if( index == 0 )
+ entriesTransmits.prepend( newEntry );
+ else
+ {
+ it = entriesTransmits.at( index );
+ entriesTransmits.insert( it, newEntry );
+ }
+ displayPaletteEntries( filters( ), entriesTransmits );
+ emit sizeChanged( );
+ emit dataChanged( );
+ }
+ }
+}
+
+void PMImageMapEdit::slotRemoveTransmitEntry( )
+{
+ QValueList<PMPaletteValue> entriesTransmits;
+ QValueListIterator<PMPaletteValue> it;
+ QPushButton* button = ( QPushButton* ) sender( );
+
+ if( button )
+ {
+ int index = m_transmitRemoveButtons.findRef( button );
+ if( index >= 0 )
+ {
+ entriesTransmits = transmits( );
+ it = entriesTransmits.at( index );
+ entriesTransmits.remove( it );
+ displayPaletteEntries( filters( ), entriesTransmits );
+ emit sizeChanged( );
+ emit dataChanged( );
+ }
+ }
+}
+
+#include "pmimagemapedit.moc"
diff --git a/kpovmodeler/pmimagemapedit.h b/kpovmodeler/pmimagemapedit.h
new file mode 100644
index 00000000..86055ea2
--- /dev/null
+++ b/kpovmodeler/pmimagemapedit.h
@@ -0,0 +1,121 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMIMAGEMAPEDIT_H
+#define PMIMAGEMAPEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmpalettevalueedit.h"
+#include "pmdialogeditbase.h"
+
+class PMImageMap;
+class PMPaletteValue;
+class PMVectorEdit;
+class QComboBox;
+class PMFloatEdit;
+class PMIntEdit;
+class QLabel;
+class QCheckBox;
+class QWidget;
+class QLineEdit;
+class QPushButton;
+
+/**
+ * Dialog edit class for @ref PMImageMap.
+ */
+class PMImageMapEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMImageMapEdit with parent and name
+ */
+ PMImageMapEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void createBottomWidgets( );
+ /** */
+ virtual void saveContents( );
+ /** */
+ QValueList<PMPaletteValue> filters( );
+ /** */
+ QValueList<PMPaletteValue> transmits( );
+ /** */
+ void displayPaletteEntries( const QValueList<PMPaletteValue>& filters,
+ const QValueList<PMPaletteValue>& transmits );
+
+private slots:
+ /** */
+ void slotImageFileTypeChanged( int a );
+ /** */
+ void slotMapTypeChanged( int a );
+ /** */
+ void slotInterpolateTypeChanged( int a );
+ /** */
+ void slotImageFileNameChanged( const QString& a );
+ /** */
+ void slotImageFileBrowseClicked( );
+ /** */
+ void slotFilterAllClicked( );
+ /** */
+ void slotTransmitAllClicked( );
+ /** */
+ void slotAddFilterEntry( );
+ /** */
+ void slotRemoveFilterEntry( );
+ /** */
+ void slotAddTransmitEntry( );
+ /** */
+ void slotRemoveTransmitEntry( );
+private:
+ PMImageMap* m_pDisplayedObject;
+ QComboBox* m_pImageFileTypeEdit;
+ QLineEdit* m_pImageFileNameEdit;
+ QPushButton* m_pImageFileNameBrowse;
+ QCheckBox* m_pOnceEdit;
+ QComboBox* m_pMapTypeEdit;
+ QComboBox* m_pInterpolateTypeEdit;
+ QCheckBox* m_pEnableFilterAllEdit;
+ QCheckBox* m_pEnableTransmitAllEdit;
+ PMFloatEdit* m_pFilterAllEdit;
+ PMFloatEdit* m_pTransmitAllEdit;
+ QWidget* m_pFiltersWidget;
+ QWidget* m_pTransmitsWidget;
+
+ QPtrList<PMPaletteValueEdit> m_filterEntries;
+ QPtrList<QPushButton> m_filterAddButtons;
+ QPtrList<QPushButton> m_filterRemoveButtons;
+ QPtrList<PMPaletteValueEdit> m_transmitEntries;
+ QPtrList<QPushButton> m_transmitAddButtons;
+ QPtrList<QPushButton> m_transmitRemoveButtons;
+};
+
+#endif
diff --git a/kpovmodeler/pminserterrordialog.cpp b/kpovmodeler/pminserterrordialog.cpp
new file mode 100644
index 00000000..766db20a
--- /dev/null
+++ b/kpovmodeler/pminserterrordialog.cpp
@@ -0,0 +1,51 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pminserterrordialog.h"
+#include <klocale.h>
+#include <qlabel.h>
+#include <qlistbox.h>
+#include <qvbox.h>
+
+PMInsertErrorDialog::PMInsertErrorDialog(
+ int numObj, int numErrors,
+ const QStringList& details,
+ QWidget* parent /*= 0*/, const char* name /*= 0*/ )
+ : KDialogBase( parent, name, true, i18n( "Insert Errors" ),
+ Help | Ok | User1, Ok, false, i18n( "Details" ) )
+{
+ QVBox* page = makeVBoxMainWidget( );
+ new QLabel( i18n( "%1 of %2 objects couldn't be inserted." )
+ .arg( numErrors ).arg( numObj ), page );
+
+ m_pDetailsLabel = new QLabel( i18n( "Objects not inserted:" ), page );
+ m_pDetailsLabel->hide( );
+
+ m_pDetails = new QListBox( page );
+ m_pDetails->insertStringList( details, 0 );
+ m_pDetails->setMinimumHeight( 150 );
+ m_pDetails->hide( );
+
+}
+
+void PMInsertErrorDialog::slotUser1( )
+{
+ m_pDetailsLabel->show( );
+ m_pDetails->show( );
+}
+#include "pminserterrordialog.moc"
diff --git a/kpovmodeler/pminserterrordialog.h b/kpovmodeler/pminserterrordialog.h
new file mode 100644
index 00000000..d94be0f6
--- /dev/null
+++ b/kpovmodeler/pminserterrordialog.h
@@ -0,0 +1,54 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMINSERTERRORDIALOG_H
+#define PMINSERTERRORDIALOG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+#include <qstringlist.h>
+
+class QListBox;
+class QLabel;
+
+/**
+ * Dialog that is shown if not all objects could be inserted
+ during the execution of a command */
+class PMInsertErrorDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a modal PMInsertErrorDialog with parent and name.
+ */
+ PMInsertErrorDialog( int NumberOfObjects, int NumberOfInsertErrors,
+ const QStringList& details,
+ QWidget* parent = 0, const char* name = 0 );
+protected slots:
+ void slotUser1( );
+
+private:
+ QListBox* m_pDetails;
+ QLabel* m_pDetailsLabel;
+};
+
+#endif
diff --git a/kpovmodeler/pminsertpopup.cpp b/kpovmodeler/pminsertpopup.cpp
new file mode 100644
index 00000000..be6a527d
--- /dev/null
+++ b/kpovmodeler/pminsertpopup.cpp
@@ -0,0 +1,90 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pminsertpopup.h"
+#include <klocale.h>
+#include <kiconloader.h>
+#include <qcursor.h>
+
+PMInsertPopup::PMInsertPopup( QWidget* parent, bool multipleObjects,
+ int items, bool canInsertAllAsFirstChildren,
+ bool canInsertAllAsLastChildren,
+ bool canInsertAllAsSiblings, const char* name )
+ : KPopupMenu( parent, name )
+{
+ QString itemText;
+ if( multipleObjects )
+ {
+ insertTitle( i18n( "Insert Objects As" ) );
+ if( ( items & PMIFirstChild ) == PMIFirstChild )
+ {
+ itemText = i18n( "First Children" );
+ if( !canInsertAllAsFirstChildren )
+ itemText += " (" + i18n( "some" ) + ")";
+ insertItem( SmallIcon( "pminsertfirstchild" ),
+ itemText, PMIFirstChild );
+ }
+ if( ( items & PMILastChild ) == PMILastChild )
+ {
+ itemText = i18n( "Last Children" );
+ if( !canInsertAllAsLastChildren )
+ itemText += " (" + i18n( "some" ) + ")";
+ insertItem( SmallIcon( "pminsertlastchild" ),
+ itemText, PMILastChild );
+ }
+ if( ( items & PMISibling ) == PMISibling )
+ {
+ itemText = i18n( "Siblings" );
+ if( !canInsertAllAsSiblings )
+ itemText += " (" + i18n( "some" ) + ")";
+ insertItem( SmallIcon( "pminsertsibling" ),
+ itemText, PMISibling );
+ }
+ }
+ else
+ {
+ insertTitle( i18n( "Insert Object As" ) );
+ if( ( items & PMIFirstChild ) == PMIFirstChild )
+ insertItem( SmallIcon( "pminsertfirstchild" ),
+ i18n( "First Child" ), PMIFirstChild );
+ if( ( items & PMILastChild ) == PMILastChild )
+ insertItem( SmallIcon( "pminsertlastchild" ),
+ i18n( "Last Child" ), PMILastChild );
+ if( ( items & PMISibling ) == PMISibling )
+ insertItem( SmallIcon( "pminsertsibling" ),
+ i18n( "Sibling" ), PMISibling );
+ }
+}
+
+int PMInsertPopup::choosePlace( QWidget* parent, bool multipleObjects,
+ int items, bool canInsertAllAsFirstChildren,
+ bool canInsertAllAsLastChildren,
+ bool canInsertAllAsSiblings )
+{
+ int result;
+ PMInsertPopup* popup = new PMInsertPopup( parent, multipleObjects, items,
+ canInsertAllAsFirstChildren,
+ canInsertAllAsLastChildren,
+ canInsertAllAsSiblings );
+ result = popup->exec( QCursor::pos( ) );
+ if( result < 0 )
+ result = 0;
+ delete popup;
+
+ return result;
+}
diff --git a/kpovmodeler/pminsertpopup.h b/kpovmodeler/pminsertpopup.h
new file mode 100644
index 00000000..c5e99dac
--- /dev/null
+++ b/kpovmodeler/pminsertpopup.h
@@ -0,0 +1,81 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMINSERTPOPUP_H
+#define PMINSERTPOPUP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kpopupmenu.h>
+
+/**
+ * Popup menu. Ask the user where to insert new objects
+ */
+class PMInsertPopup : public KPopupMenu
+{
+public:
+ /**
+ * Places where a new object can be inserted
+ */
+ enum { PMIFirstChild = 1, PMILastChild = 2, PMISibling = 4 };
+ /**
+ * Creates a popup menu
+ *
+ * @param parent The parent widget
+ * @param multipleObjects True if more than one object will be inserted
+ * @param items Which items to display. Can be a bitwise combination
+ * of PMIFirstChild, PMILastChild, PMISibling.
+ * @param name Internal name of the popup menu
+ */
+ PMInsertPopup( QWidget* parent, bool multipleObjects,
+ int items = PMIFirstChild | PMILastChild | PMISibling,
+ bool canInsertAllAsFirstChildren = true,
+ bool canInsertAllAsLastChildren = true,
+ bool canInsertAllAsSiblings = true,
+ const char* name = 0 );
+ /**
+ * Deletes the popup menu
+ */
+ ~PMInsertPopup( ) { };
+
+ /**
+ * Popups a PMInsertPopup menu
+ *
+ * @param parent The parent widget
+ * @param multipleObjects True if more than one object will be inserted
+ * @param items Which items to display. Can be a bitwise combination
+ * of PMIFirstChild, PMILastChild, PMISibling.
+ * @param canInsertAllAsChildren If false the text "(some)" will appear
+ * behind the "first Children" and "last Children" items
+ * @param canInsertAllAsSiblings If false the text "(some)" will appear
+ * behind the "Siblings" items
+ *
+ * Returns the selected item or 0 if no item was selected.
+ */
+ static int choosePlace( QWidget* parent, bool multipleObjects,
+ int items = PMIFirstChild | PMILastChild
+ | PMISibling,
+ bool canInsertAllAsFirstChildren = true,
+ bool canInsertAllAsLastChildren = true,
+ bool canInsertAllAsSiblings = true );
+};
+
+#endif
diff --git a/kpovmodeler/pminsertrules.dtd b/kpovmodeler/pminsertrules.dtd
new file mode 100644
index 00000000..a3c2128c
--- /dev/null
+++ b/kpovmodeler/pminsertrules.dtd
@@ -0,0 +1,97 @@
+<!-- Simple dtd for kpovmodeler insert rules
+ Autor: Andreas Zehender <zehender@kde.org> -->
+
+<!-- Validation command for xemacs:
+ nsgmls -sv /usr/doc/jade-1.2.1/pubtext/xml.dcl <file> -->
+
+<!-- The root element. -->
+<!ELEMENT insertrules (definegroup*, targetclass+)>
+<!ATTLIST insertrules
+ format CDATA #REQUIRED
+>
+
+<!-- Groups together a list of classes. Groups can be nested. -->
+<!ELEMENT definegroup ((class | group)+)>
+<!ATTLIST definegroup
+ name CDATA #REQUIRED
+>
+
+<!-- Reference to an object class. -->
+<!ELEMENT class EMPTY>
+<!ATTLIST class
+ name CDATA #REQUIRED
+>
+
+<!-- Reference to a defined group. -->
+<!ELEMENT group EMPTY>
+<!ATTLIST group
+ name CDATA #REQUIRED
+>
+
+<!-- Contains the insert rules for one class
+ (the class where the new object is inserted) -->
+<!ELEMENT targetclass (definegroup*, rule+)>
+<!ATTLIST targetclass
+ name CDATA #REQUIRED
+>
+
+<!-- One rule for the current class.
+ Insert a list of groups and classes (the object classes that can be inserted)
+ and one condition. If the condition is omitted,
+ the classes can allways be inserted. -->
+<!ELEMENT rule ((group | class)+, (and | or | not | before | after | contains
+ | greater | less | equal)?)>
+
+<!-- Simple negation. Insert one condition -->
+<!ELEMENT not (and | or | before | after | contains | greater | less | equal)>
+
+<!-- Logical and. Insert any number of conditions -->
+<!ELEMENT and (and | or | not | before | after | contains | greater | less | equal)+>
+
+<!-- Logical or. Insert any number of conditions -->
+<!ELEMENT or (and | or | not | before | after | contains | greater | less | equal)+>
+
+<!-- Condition. Value is true if the object already contains
+ objects of the given class or group before the insert point. -->
+<!ELEMENT before (class | group)>
+
+<!-- Condition. Value is true if the object already contains
+ objects of the given class or group after the insert point. -->
+<!ELEMENT after (class | group)>
+
+<!-- Condition. Value is true if the two values (child xml tags)
+ are equal. -->
+<!ELEMENT equal ((property | count | const), (property | count | const))>
+
+<!-- Condition. Value is true if the first value (child xml tag)
+ is greater than the second. -->
+<!ELEMENT greater ((property | count | const), (property | count | const))>
+
+<!-- Condition. Value is true if the first value (child xml tag)
+ is less than the second. -->
+<!ELEMENT less ((property | count | const), (property | count | const))>
+
+<!-- Condition. Value is true if the object contains
+ objects of the given classes and groups. -->
+<!ELEMENT contains (group | class)+>
+
+
+<!-- Value. Value is the class property of the object, where the
+ new object should be inserted into. -->
+<!ELEMENT property EMPTY>
+<!ATTLIST property
+ name CDATA #REQUIRED
+>
+
+<!-- Value. Defines a constant (number or string). -->
+<!ELEMENT const EMPTY>
+<!ATTLIST const
+ value CDATA #REQUIRED
+>
+
+<!-- Value. Counts the number of already inserted instances of the given
+ groups or classes. -->
+<!ELEMENT count (group | class)+>
+
+
+
diff --git a/kpovmodeler/pminsertrulesystem.cpp b/kpovmodeler/pminsertrulesystem.cpp
new file mode 100644
index 00000000..0e7b7be2
--- /dev/null
+++ b/kpovmodeler/pminsertrulesystem.cpp
@@ -0,0 +1,1061 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pminsertrulesystem.h"
+#include "pmprototypemanager.h"
+#include "pmpart.h"
+#include "pmvariant.h"
+#include "pmdebug.h"
+
+#include <qfile.h>
+#include <kstandarddirs.h>
+
+bool isCategory( QDomElement& e )
+{
+ return( e.tagName( ) == "class" || e.tagName( ) == "group" );
+}
+
+PMRuleCategory* newCategory( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+{
+ if( e.tagName( ) == "class" )
+ return new PMRuleClass( e );
+ if( e.tagName( ) == "group" )
+ return new PMRuleGroup( e, globalGroups, localGroups );
+ return 0;
+}
+
+PMPrototypeManager* PMRuleClass::s_pPrototypeManager = 0;
+
+PMRuleClass::PMRuleClass( QDomElement& e )
+ : PMRuleCategory( )
+{
+ m_pPrototypeManager = s_pPrototypeManager;
+ m_className = e.attribute( "name" );
+ if( m_className.isEmpty( ) )
+ kdError( PMArea ) << "RuleSystem: Invalid class name" << endl;
+ if( !m_pPrototypeManager->existsClass( m_className ) )
+ kdError( PMArea ) << "RuleSystem: Unknown class: "
+ << m_className << endl;
+}
+
+bool PMRuleClass::matches( const QString& className )
+{
+ return m_pPrototypeManager->isA( className, m_className );
+}
+
+PMRuleGroup::PMRuleGroup( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCategory( )
+{
+ m_pGroup = 0;
+ QString groupName = e.attribute( "name" );
+ if( groupName.isEmpty( ) )
+ kdError( PMArea ) << "RuleSystem: Invalid group name" << endl;
+ // find group
+ QPtrListIterator<PMRuleDefineGroup> lit( localGroups );
+ for( ; lit.current( ) && !m_pGroup; ++lit )
+ if( lit.current( )->name( ) == groupName )
+ m_pGroup = lit.current( );
+ QPtrListIterator<PMRuleDefineGroup> git( globalGroups );
+ for( ; git.current( ) && !m_pGroup; ++git )
+ if( git.current( )->name( ) == groupName )
+ m_pGroup = git.current( );
+ if( !m_pGroup )
+ kdError( PMArea ) << "RuleSystem: Group not defined: "
+ << groupName << endl;
+}
+
+bool PMRuleGroup::matches( const QString& className )
+{
+ if( m_pGroup )
+ return m_pGroup->matches( className );
+ return false;
+}
+
+PMRuleDefineGroup::PMRuleDefineGroup( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+{
+ m_name = e.attribute( "name" );
+ if( m_name.isEmpty( ) )
+ kdError( PMArea ) << "RuleSystem: Invalid group name" << endl;
+
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCategory( me ) )
+ m_categories.append( newCategory( me, globalGroups, localGroups ) );
+ }
+ m = m.nextSibling( );
+ }
+}
+
+PMRuleDefineGroup::~PMRuleDefineGroup( )
+{
+ m_categories.setAutoDelete( true );
+ m_categories.clear( );
+}
+
+bool PMRuleDefineGroup::matches( const QString& className )
+{
+ bool m = false;
+ QPtrListIterator<PMRuleCategory> it( m_categories );
+ for( ; it.current( ) && !m; ++it )
+ m = it.current( )->matches( className );
+ return m;
+}
+
+
+bool isValue( QDomElement& e )
+{
+ return( e.tagName( ) == "property" || e.tagName( ) == "const" ||
+ e.tagName( ) == "count" );
+}
+
+bool isCondition( QDomElement& e )
+{
+ return( e.tagName( ) == "not" || e.tagName( ) == "and" ||
+ e.tagName( ) == "or" || e.tagName( ) == "before" ||
+ e.tagName( ) == "after" || e.tagName( ) == "contains" ||
+ e.tagName( ) == "greater" || e.tagName( ) == "less" ||
+ e.tagName( ) == "equal" );
+}
+
+PMRuleValue* newValue( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+{
+ if( e.tagName( ) == "property" )
+ return new PMRuleProperty( e );
+ if( e.tagName( ) == "const" )
+ return new PMRuleConstant( e );
+ if( e.tagName( ) == "count" )
+ return new PMRuleCount( e, globalGroups, localGroups );
+ return 0;
+}
+
+PMRuleCondition* newCondition( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+{
+ if( e.tagName( ) == "not" )
+ return new PMRuleNot( e, globalGroups, localGroups );
+ if( e.tagName( ) == "and" )
+ return new PMRuleAnd( e, globalGroups, localGroups );
+ if( e.tagName( ) == "or" )
+ return new PMRuleOr( e, globalGroups, localGroups );
+ if( e.tagName( ) == "before" )
+ return new PMRuleBefore( e, globalGroups, localGroups );
+ if( e.tagName( ) == "after" )
+ return new PMRuleAfter( e, globalGroups, localGroups );
+ if( e.tagName( ) == "contains" )
+ return new PMRuleContains( e, globalGroups, localGroups );
+ if( e.tagName( ) == "greater" )
+ return new PMRuleGreater( e, globalGroups, localGroups );
+ if( e.tagName( ) == "less" )
+ return new PMRuleLess( e, globalGroups, localGroups );
+ if( e.tagName( ) == "equal" )
+ return new PMRuleEqual( e, globalGroups, localGroups );
+ return 0;
+}
+
+PMRuleBase::~PMRuleBase( )
+{
+ m_children.setAutoDelete( true );
+ m_children.clear( );
+}
+
+void PMRuleBase::countChild( const QString& className, bool afterInsertPoint )
+{
+ countChildProtected( className, afterInsertPoint );
+
+ QPtrListIterator<PMRuleBase> it( m_children );
+ for( ; it.current( ); ++it )
+ it.current( )->countChild( className, afterInsertPoint );
+}
+
+void PMRuleBase::reset( )
+{
+ resetProtected( );
+
+ QPtrListIterator<PMRuleBase> it( m_children );
+ for( ; it.current( ); ++it )
+ it.current( )->reset( );
+}
+
+PMRuleProperty::PMRuleProperty( QDomElement& e )
+ : PMRuleValue( )
+{
+ m_property = e.attribute( "name" );
+ if( m_property.isNull( ) )
+ kdError( PMArea ) << "RuleSystem: Invalid property name" << endl;
+}
+
+PMVariant PMRuleProperty::evaluate( const PMObject* o )
+{
+ PMVariant v = o->property( m_property );
+ if( v.isNull( ) )
+ kdError( PMArea ) << "RuleSystem: Invalid property name: "
+ << m_property << endl;
+ return v;
+}
+
+
+PMRuleConstant::PMRuleConstant( QDomElement& e )
+ : PMRuleValue( )
+{
+ QString v = e.attribute( "value" );
+ if( v.isNull( ) )
+ kdError( PMArea ) << "RuleSystem: Invalid value" << endl;
+
+ m_value = PMVariant( v );
+}
+
+PMVariant PMRuleConstant::evaluate( const PMObject* )
+{
+ return m_value;
+}
+
+bool PMRuleConstant::convertTo( PMVariant::PMVariantDataType type )
+{
+ return m_value.convertTo( type );
+}
+
+
+PMRuleCount::PMRuleCount( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleValue( )
+{
+ m_number = 0;
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCategory( me ) )
+ m_categories.append( newCategory( me, globalGroups, localGroups ) );
+ }
+ m = m.nextSibling( );
+ }
+}
+
+PMRuleCount::~PMRuleCount( )
+{
+ m_categories.setAutoDelete( true );
+ m_categories.clear( );
+}
+
+PMVariant PMRuleCount::evaluate( const PMObject* )
+{
+ return PMVariant( m_number );
+}
+
+void PMRuleCount::countChildProtected( const QString& className, bool )
+{
+ bool m = false;
+ QPtrListIterator<PMRuleCategory> it( m_categories );
+ for( ; it.current( ) && !m; ++it )
+ m = it.current( )->matches( className );
+ if( m )
+ m_number++;
+}
+
+void PMRuleCount::resetProtected( )
+{
+ m_number = 0;
+}
+
+PMRuleNot::PMRuleNot( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCondition( )
+{
+ m_pChild = 0;
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) && !m_pChild )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCondition( me ) )
+ {
+ m_pChild = newCondition( me, globalGroups, localGroups );
+ m_children.append( m_pChild );
+ }
+ }
+ m = m.nextSibling( );
+ }
+}
+
+bool PMRuleNot::evaluate( const PMObject* object )
+{
+ if( m_pChild )
+ return !m_pChild->evaluate( object );
+ return true;
+}
+
+PMRuleAnd::PMRuleAnd( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCondition( )
+{
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCondition( me ) )
+ {
+ PMRuleCondition* c = newCondition( me, globalGroups, localGroups );
+ m_children.append( c );
+ m_conditions.append( c );
+ }
+ }
+ m = m.nextSibling( );
+ }
+}
+
+bool PMRuleAnd::evaluate( const PMObject* object )
+{
+ bool b = true;
+ QPtrListIterator<PMRuleCondition> it( m_conditions );
+ for( ; it.current( ) && b; ++it )
+ b = it.current( )->evaluate( object );
+ return b;
+}
+
+PMRuleOr::PMRuleOr( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCondition( )
+{
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCondition( me ) )
+ {
+ PMRuleCondition* c = newCondition( me, globalGroups, localGroups );
+ m_children.append( c );
+ m_conditions.append( c );
+ }
+ }
+ m = m.nextSibling( );
+ }
+}
+
+bool PMRuleOr::evaluate( const PMObject* object )
+{
+ bool b = false;
+ QPtrListIterator<PMRuleCondition> it( m_conditions );
+ for( ; it.current( ) && !b; ++it )
+ b = it.current( )->evaluate( object );
+ return b;
+}
+
+PMRuleBefore::PMRuleBefore( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCondition( )
+{
+ m_contains = false;
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCategory( me ) )
+ m_categories.append( newCategory( me, globalGroups, localGroups ) );
+ }
+ m = m.nextSibling( );
+ }
+}
+
+PMRuleBefore::~PMRuleBefore( )
+{
+ m_categories.setAutoDelete( true );
+ m_categories.clear( );
+}
+
+bool PMRuleBefore::evaluate( const PMObject* )
+{
+ return m_contains;
+}
+
+void PMRuleBefore::countChildProtected( const QString& className,
+ bool afterInsertPoint )
+{
+ if( afterInsertPoint && !m_contains )
+ {
+ QPtrListIterator<PMRuleCategory> it( m_categories );
+ for( ; it.current( ) && !m_contains; ++it )
+ m_contains = it.current( )->matches( className );
+ }
+}
+
+void PMRuleBefore::resetProtected( )
+{
+ m_contains = false;
+}
+
+PMRuleAfter::PMRuleAfter( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCondition( )
+{
+ m_contains = false;
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCategory( me ) )
+ m_categories.append( newCategory( me, globalGroups, localGroups ) );
+ }
+ m = m.nextSibling( );
+ }
+}
+
+PMRuleAfter::~PMRuleAfter( )
+{
+ m_categories.setAutoDelete( true );
+ m_categories.clear( );
+}
+
+bool PMRuleAfter::evaluate( const PMObject* )
+{
+ return m_contains;
+}
+
+void PMRuleAfter::countChildProtected( const QString& className,
+ bool afterInsertPoint )
+{
+ if( !afterInsertPoint && !m_contains )
+ {
+ QPtrListIterator<PMRuleCategory> it( m_categories );
+ for( ; it.current( ) && !m_contains; ++it )
+ m_contains = it.current( )->matches( className );
+ }
+}
+
+void PMRuleAfter::resetProtected( )
+{
+ m_contains = false;
+}
+
+PMRuleContains::PMRuleContains( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCondition( )
+{
+ m_contains = false;
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCategory( me ) )
+ m_categories.append( newCategory( me, globalGroups, localGroups ) );
+ }
+ m = m.nextSibling( );
+ }
+}
+
+PMRuleContains::~PMRuleContains( )
+{
+ m_categories.setAutoDelete( true );
+ m_categories.clear( );
+}
+
+bool PMRuleContains::evaluate( const PMObject* )
+{
+ return m_contains;
+}
+
+void PMRuleContains::countChildProtected( const QString& className, bool )
+{
+ if( !m_contains )
+ {
+ QPtrListIterator<PMRuleCategory> it( m_categories );
+ for( ; it.current( ) && !m_contains; ++it )
+ m_contains = it.current( )->matches( className );
+ }
+}
+
+void PMRuleContains::resetProtected( )
+{
+ m_contains = false;
+}
+
+PMRuleCompare::PMRuleCompare( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCondition( )
+{
+ m_pValue[0] = 0;
+ m_pValue[1] = 0;
+
+ int i = 0;
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) && !m_pValue[1] )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isValue( me ) )
+ {
+ m_pValue[i] = newValue( me, globalGroups, localGroups );
+ m_children.append( m_pValue[i] );
+ i++;
+ }
+ }
+ m = m.nextSibling( );
+ }
+ if( !m_pValue[1] )
+ kdError( PMArea ) << "RuleSystem: Comparison needs two values" << endl;
+}
+
+bool PMRuleCompare::evaluate( const PMObject* object )
+{
+ if( !m_pValue[1] )
+ return false;
+
+ PMVariant v[2];
+ v[0] = m_pValue[0]->evaluate( object );
+ v[1] = m_pValue[1]->evaluate( object );
+
+ if( v[0].isNull( ) || v[1].isNull( ) )
+ return false;
+
+ bool convertError = false;
+
+ if( v[0].dataType( ) != v[1].dataType( ) )
+ {
+ if( m_pValue[1]->type( ) == "Constant" )
+ {
+ if( v[1].convertTo( v[0].dataType( ) ) )
+ ( ( PMRuleConstant* ) m_pValue[1] )->convertTo( v[0].dataType( ) );
+ else
+ convertError = true;
+ }
+ else if( m_pValue[0]->type( ) == "Constant" )
+ {
+ if( v[0].convertTo( v[1].dataType( ) ) )
+ ( ( PMRuleConstant* ) m_pValue[0] )->convertTo( v[1].dataType( ) );
+ else
+ convertError = true;
+ }
+ else
+ convertError = true;
+ }
+ if( convertError )
+ {
+ kdError( PMArea ) << "RuleSystem: Types in comparison must match" << endl;
+ return false;
+ }
+
+ return compare( v[0], v[1] );
+}
+
+PMRuleLess::PMRuleLess( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCompare( e, globalGroups, localGroups )
+{
+}
+
+bool PMRuleLess::compare( const PMVariant& v1, const PMVariant& v2 )
+{
+ bool c = false;
+
+ switch( v1.dataType( ) )
+ {
+ case PMVariant::Integer:
+ c = v1.intData( ) < v2.intData( );
+ break;
+ case PMVariant::Unsigned:
+ c = v1.unsignedData( ) < v2.unsignedData( );
+ break;
+ case PMVariant::Double:
+ c = v1.doubleData( ) < v2.doubleData( );
+ break;
+ case PMVariant::String:
+ c = v1.stringData( ) < v2.stringData( );
+ break;
+ case PMVariant::Bool:
+ kdError( PMArea ) << "RuleSystem: Less: Can't compare booleans" << endl;
+ break;
+ case PMVariant::ThreeState:
+ kdError( PMArea ) << "RuleSystem: Less: Can't compare ThreeStates" << endl;
+ break;
+ case PMVariant::Vector:
+ kdError( PMArea ) << "RuleSystem: Less: Can't compare vectors" << endl;
+ break;
+ case PMVariant::Color:
+ kdError( PMArea ) << "RuleSystem: Less: Can't compare colors" << endl;
+ break;
+ case PMVariant::ObjectPointer:
+ kdError( PMArea ) << "RuleSystem: Less: Can't compare object pointers" << endl;
+ break;
+ case PMVariant::None:
+ kdError( PMArea ) << "RuleSystem: Less: Value has type none" << endl;
+ break;
+ }
+ return c;
+}
+
+PMRuleGreater::PMRuleGreater( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCompare( e, globalGroups, localGroups )
+{
+}
+
+bool PMRuleGreater::compare( const PMVariant& v1, const PMVariant& v2 )
+{
+ bool c = false;
+
+ switch( v1.dataType( ) )
+ {
+ case PMVariant::Integer:
+ c = v1.intData( ) > v2.intData( );
+ break;
+ case PMVariant::Unsigned:
+ c = v1.unsignedData( ) > v2.unsignedData( );
+ break;
+ case PMVariant::Double:
+ c = v1.doubleData( ) > v2.doubleData( );
+ break;
+ case PMVariant::String:
+ c = v1.stringData( ) > v2.stringData( );
+ break;
+ case PMVariant::Bool:
+ kdError( PMArea ) << "RuleSystem: Greater: Can't compare booleans" << endl;
+ break;
+ case PMVariant::ThreeState:
+ kdError( PMArea ) << "RuleSystem: Greater: Can't compare ThreeStates" << endl;
+ break;
+ case PMVariant::Vector:
+ kdError( PMArea ) << "RuleSystem: Greater: Can't compare vectors" << endl;
+ break;
+ case PMVariant::Color:
+ kdError( PMArea ) << "RuleSystem: Greater: Can't compare colors" << endl;
+ break;
+ case PMVariant::ObjectPointer:
+ kdError( PMArea ) << "RuleSystem: Greater: Can't compare object pointers" << endl;
+ break;
+ case PMVariant::None:
+ kdError( PMArea ) << "RuleSystem: Greater: Value has type none" << endl;
+ break;
+ }
+ return c;
+}
+
+PMRuleEqual::PMRuleEqual( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleCompare( e, globalGroups, localGroups )
+{
+}
+
+bool PMRuleEqual::compare( const PMVariant& v1, const PMVariant& v2 )
+{
+ bool c = false;
+
+ switch( v1.dataType( ) )
+ {
+ case PMVariant::Integer:
+ c = v1.intData( ) == v2.intData( );
+ break;
+ case PMVariant::Unsigned:
+ c = v1.unsignedData( ) == v2.unsignedData( );
+ break;
+ case PMVariant::Double:
+ c = v1.doubleData( ) == v2.doubleData( );
+ break;
+ case PMVariant::String:
+ c = v1.stringData( ) == v2.stringData( );
+ break;
+ case PMVariant::Bool:
+ c = v1.boolData( ) == v2.boolData( );
+ break;
+ case PMVariant::ThreeState:
+ c = v1.threeStateData( ) == v2.threeStateData( );
+ break;
+ case PMVariant::Vector:
+ kdError( PMArea ) << "RuleSystem: Equal: Can't compare vectors" << endl;
+ break;
+ case PMVariant::Color:
+ kdError( PMArea ) << "RuleSystem: Equal: Can't compare colors" << endl;
+ break;
+ case PMVariant::ObjectPointer:
+ kdError( PMArea ) << "RuleSystem: Equal: Can't compare object pointers" << endl;
+ break;
+ case PMVariant::None:
+ kdError( PMArea ) << "RuleSystem: Equal: Value has type none" << endl;
+ break;
+ }
+ return c;
+}
+
+
+PMRule::PMRule( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups )
+ : PMRuleBase( )
+{
+ m_pCondition = 0;
+
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) && !m_pCondition )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( isCategory( me ) )
+ m_categories.append( newCategory( me, globalGroups, localGroups ) );
+ else if( isCondition( me ) )
+ {
+ m_pCondition = newCondition( me, globalGroups, localGroups );
+ m_children.append( m_pCondition );
+ }
+ }
+ m = m.nextSibling( );
+ }
+}
+
+PMRule::~PMRule( )
+{
+ m_categories.setAutoDelete( true );
+ m_categories.clear( );
+}
+
+bool PMRule::matches( const QString& className )
+{
+ bool m = false;
+ QPtrListIterator<PMRuleCategory> it( m_categories );
+ for( ; it.current( ) && !m; ++it )
+ m = it.current( )->matches( className );
+ return m;
+}
+
+bool PMRule::evaluate( const PMObject* parent )
+{
+ if( !m_pCondition )
+ return true;
+ else
+ return m_pCondition->evaluate( parent );
+}
+
+PMRuleTargetClass::PMRuleTargetClass( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups )
+{
+ m_class = e.attribute( "name" );
+ if( m_class.isEmpty( ) )
+ kdError( PMArea ) << "RuleSystem: Invalid class name" << endl;
+
+ appendRules( e, globalGroups );
+}
+
+void PMRuleTargetClass::appendRules( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups )
+{
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ if( me.tagName( ) == "definegroup" )
+ m_groups.append( new PMRuleDefineGroup( me, globalGroups, m_groups ) );
+ if( me.tagName( ) == "rule" )
+ m_rules.append( new PMRule( me, globalGroups, m_groups ) );
+ if( me.tagName( ) == "exception" )
+ m_exceptions.append( me.attribute( "class" ) );
+ }
+ m = m.nextSibling( );
+ }
+}
+
+PMRuleTargetClass::~PMRuleTargetClass( )
+{
+ m_groups.setAutoDelete( true );
+ m_groups.clear( );
+ m_rules.setAutoDelete( true );
+ m_rules.clear( );
+}
+
+PMInsertRuleSystem::PMInsertRuleSystem( PMPart* part )
+{
+ m_pPart = part;
+}
+
+PMInsertRuleSystem::~PMInsertRuleSystem( )
+{
+ m_groups.setAutoDelete( true );
+ m_groups.clear( );
+ m_classRules.setAutoDelete( true );
+ m_classRules.clear( );
+}
+
+void PMInsertRuleSystem::loadRules( const QString& fileName )
+{
+ PMRuleClass::s_pPrototypeManager = m_pPart->prototypeManager( );
+ if( m_loadedFiles.find( fileName ) != m_loadedFiles.end( ) )
+ return;
+ m_loadedFiles.push_back( fileName );
+
+
+ QString ruleFile = locate( "data", QString( "kpovmodeler/" + fileName ) );
+ if( ruleFile.isEmpty( ) )
+ {
+ kdError( PMArea ) << "Rule file 'kpovmodeler/" << fileName
+ << "' not found." << endl;
+ return;
+ }
+
+ QFile file( ruleFile );
+ if( !file.open( IO_ReadOnly ) )
+ {
+ kdError( PMArea ) << "Could not open rule file 'kpovmodeler/" << fileName
+ << "'" << endl;
+ return;
+ }
+
+ QDomDocument doc( "insertrules" );
+ doc.setContent( &file );
+
+ QDomElement e = doc.documentElement( );
+ if( e.attribute( "format" ) != "1.0" )
+ kdError( PMArea ) << "Rule format " << e.attribute( "format" )
+ << " not supported." << endl;
+ else
+ {
+ QDomNode c = e.firstChild( );
+ QPtrList<PMRuleDefineGroup> dummyLocalGroups;
+
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ if( ce.tagName( ) == "definegroup" )
+ m_groups.append( new PMRuleDefineGroup( ce, m_groups,
+ dummyLocalGroups ) );
+ else if( ce.tagName( ) == "targetclass" )
+ {
+ QString className = ce.attribute( "name" );
+ // find a target class with the same name
+ PMRuleTargetClass* target = 0;
+
+ if( !m_rulesDict.isEmpty( ) )
+ target = m_rulesDict.find( className );
+
+ if( target )
+ target->appendRules( ce, m_groups );
+ else
+ {
+ target = new PMRuleTargetClass( ce, m_groups );
+ m_rulesDict.insert( className, target );
+ m_classRules.append( target );
+ }
+ }
+ }
+ c = c.nextSibling( );
+ }
+ }
+ file.close( );
+
+ PMRuleClass::s_pPrototypeManager = 0;
+}
+
+bool PMInsertRuleSystem::canInsert( const PMObject* parentObject,
+ const QString& className,
+ const PMObject* after,
+ const PMObjectList* objectsBetween )
+{
+ bool possible = false;
+
+ // find rules for target class
+ PMMetaObject* meta = parentObject->metaObject( );
+ for( ; meta && !possible; meta = meta->superClass( ) )
+ {
+ PMRuleTargetClass* tc = m_rulesDict.find( meta->className( ) );
+ if( tc )
+ {
+ // check the exception list
+ QStringList exceptions = tc->exceptions( );
+ bool exceptionFound = false;
+ QStringList::ConstIterator it;
+ for( it = exceptions.begin( );
+ it != exceptions.end( ) && !exceptionFound; ++it )
+ if( parentObject->isA( *it ) )
+ exceptionFound = true;
+
+ if( !exceptionFound )
+ {
+ QPtrListIterator<PMRule> rit = tc->rules( );
+ // find matching rules for class name
+ for( ; rit.current( ) && !possible; ++rit )
+ {
+ PMRule* rule = rit.current( );
+ if( rule->matches( className ) )
+ {
+ // matching rule found
+ // reset the rule
+ rit.current( )->reset( );
+
+ // count already inserted child objects
+ bool afterInsertPoint = false;
+ PMObject* o = parentObject->firstChild( );
+ if( !after )
+ afterInsertPoint = true;
+ for( ; o; o = o->nextSibling( ) )
+ {
+ rule->countChild( o->className( ), afterInsertPoint );
+ if( o == after )
+ afterInsertPoint = true;
+ }
+ if( objectsBetween )
+ {
+ PMObjectListIterator it( *objectsBetween );
+ for( ; it.current( ); ++it )
+ rule->countChild( it.current( )->type( ), false );
+ }
+
+ // evaluate condition value
+ possible = rule->evaluate( parentObject );
+ }
+ }
+ }
+ }
+ }
+
+ return possible;
+}
+
+bool PMInsertRuleSystem::canInsert( const PMObject* parentObject,
+ const PMObject* object,
+ const PMObject* after,
+ const PMObjectList* objectsBetween )
+{
+ return canInsert( parentObject, object->type( ), after, objectsBetween );
+}
+
+int PMInsertRuleSystem::canInsert( const PMObject* parentObject,
+ const PMObjectList& list,
+ const PMObject* after )
+{
+ PMObjectListIterator it( list );
+ QStringList classes;
+ for( ; it.current( ); ++it )
+ classes.append( it.current( )->type( ) );
+ return canInsert( parentObject, classes, after );
+}
+
+int PMInsertRuleSystem::canInsert( const PMObject* parentObject,
+ const QStringList& list,
+ const PMObject* after )
+{
+ if( list.size( ) == 1 )
+ {
+ // more efficient
+ if( canInsert( parentObject, list.first( ), after ) )
+ return 1;
+ else
+ return 0;
+ }
+
+ // find rules for target class
+ QPtrList<PMRuleTargetClass> targetClassList;
+ PMMetaObject* meta = parentObject->metaObject( );
+ for( ; meta; meta = meta->superClass( ) )
+ {
+ PMRuleTargetClass* tc = m_rulesDict.find( meta->className( ) );
+ if( tc )
+ targetClassList.append( tc );
+ }
+ if( targetClassList.isEmpty( ) )
+ return 0; // not rules found
+
+ // count already inserted children
+ QPtrListIterator<PMRuleTargetClass> tit( targetClassList );
+ for( ; tit.current( ); ++tit ) // ... for all target classes
+ {
+ QPtrListIterator<PMRule> rit = tit.current( )->rules( );
+ for( ; rit.current( ); ++rit ) // ... and all rules
+ {
+ rit.current( )->reset( );
+ bool afterInsertPoint = false;
+ PMObject* o = parentObject->firstChild( );
+ if( !after )
+ afterInsertPoint = true;
+ for( ; o; o = o->nextSibling( ) )
+ {
+ rit.current( )->countChild( o->className( ), afterInsertPoint );
+ if( o == after )
+ afterInsertPoint = true;
+ }
+ }
+ }
+
+ int number = 0;
+ QStringList::const_iterator oit;
+
+ for( oit = list.begin( ); oit != list.end( ); ++oit )
+ {
+ bool possible = false;
+ for( tit.toFirst( ); tit.current( ) && !possible; ++tit )
+ {
+ QPtrListIterator<PMRule> rit = tit.current( )->rules( );
+
+ for( ; rit.current( ) && !possible; ++rit )
+ {
+ PMRule* rule = rit.current( );
+ if( rule->matches( *oit ) )
+ possible = rule->evaluate( parentObject );
+ }
+ }
+ if( possible )
+ {
+ // object can be inserted, count it
+ for( ; tit.current( ); ++tit )
+ {
+ QPtrListIterator<PMRule> rit = tit.current( )->rules( );
+ for( ; rit.current( ); ++rit )
+ rit.current( )->countChild( *oit, false );
+ }
+ number++;
+ }
+ }
+
+ return number;
+}
diff --git a/kpovmodeler/pminsertrulesystem.h b/kpovmodeler/pminsertrulesystem.h
new file mode 100644
index 00000000..499cbc8e
--- /dev/null
+++ b/kpovmodeler/pminsertrulesystem.h
@@ -0,0 +1,678 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMINSERTRULESYSTEM_H
+#define PMINSERTRULESYSTEM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+#include <qstringlist.h>
+#include <qptrlist.h>
+#include <qdict.h>
+#include <qdom.h>
+
+class PMInsertRuleSystem;
+class PMPrototypeManager;
+
+/**
+ * Base class for all object categories (class and group)
+ * for the insert rule system
+ */
+class PMRuleCategory
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMRuleCategory( ) { }
+ /**
+ * Destructor
+ */
+ virtual ~PMRuleCategory( ) { }
+ /**
+ * Returns true if the given class types matches the category.
+ */
+ virtual bool matches( const QString& className ) = 0;
+};
+
+/**
+ * Represents a class for the insert rule system
+ */
+class PMRuleClass : public PMRuleCategory
+{
+public:
+ /**
+ * Workaround to tell a created instance which
+ * prototype manager to use.
+ */
+ static PMPrototypeManager* s_pPrototypeManager;
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleClass( QDomElement& e );
+ /** */
+ virtual bool matches( const QString& className );
+private:
+ QString m_className;
+ PMPrototypeManager* m_pPrototypeManager;
+};
+
+/**
+ * Groups together multiple classes or groups to form a new
+ * category for the insert rule system.
+ */
+class PMRuleDefineGroup
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleDefineGroup( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /**
+ * Destructor
+ */
+ virtual ~PMRuleDefineGroup( );
+ /**
+ * Returns true if the given class types matches the category.
+ */
+ virtual bool matches( const QString& className );
+ /**
+ * Returns the group's name
+ */
+ QString name( ) const { return m_name; }
+private:
+ QPtrList<PMRuleCategory> m_categories;
+ QString m_name;
+};
+
+/**
+ * Represents a group for the insert rule system
+ */
+class PMRuleGroup : public PMRuleCategory
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleGroup( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /** */
+ bool matches( const QString& className );
+private:
+ PMRuleDefineGroup* m_pGroup;
+};
+
+
+/**
+ * Base class for all nodes for the insert rule system
+ */
+class PMRuleBase
+{
+public:
+ /**
+ * Default constructor.
+ */
+ PMRuleBase( ) { }
+ /**
+ * Destructor
+ */
+ virtual ~PMRuleBase( );
+ /**
+ * Returns the node type.
+ */
+ virtual QString type( ) const = 0;
+ /**
+ * Calls countChildProtected for this node and all child nodes
+ */
+ void countChild( const QString& className, bool afterInsertPoint );
+ /**
+ * Calls resetProtected for this node and all child nodes
+ */
+ void reset( );
+ /**
+ * Returns an iterator to all child nodes
+ */
+ QPtrListIterator<PMRuleBase> childIterator( ) const
+ {
+ return QPtrListIterator<PMRuleBase>( m_children );
+ }
+protected:
+ /**
+ * Reimplement this method if the nodes value depends
+ * on already inserted child objects.
+ */
+ virtual void countChildProtected( const QString&, bool ) { }
+ /**
+ * Reset all cached data (like counted child objects) here.
+ */
+ virtual void resetProtected( ) { }
+
+ /**
+ * Add all child nodes to this list.
+ */
+ QPtrList<PMRuleBase> m_children;
+};
+
+/**
+ * Base class for values used by the rule system
+ */
+class PMRuleValue : public PMRuleBase
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMRuleValue( ) : PMRuleBase( ) { }
+ /**
+ * Returns the node's value as variant.
+ *
+ * Reimplement this method in sub classes.
+ */
+ virtual PMVariant evaluate( const PMObject* o ) = 0;
+};
+
+
+/**
+ * Value node for object properties
+ */
+class PMRuleProperty : public PMRuleValue
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleProperty( QDomElement& e );
+ /** */
+ virtual QString type( ) const { return QString( "Property" ); }
+ /** */
+ virtual PMVariant evaluate( const PMObject* o );
+private:
+ QString m_property;
+};
+
+
+/**
+ * Simple constant
+ */
+class PMRuleConstant : public PMRuleValue
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleConstant( QDomElement& e );
+ /** */
+ virtual QString type( ) const { return QString( "Constant" ); }
+ /** */
+ virtual PMVariant evaluate( const PMObject* );
+ /**
+ * Converts the constant to the given type and returns true if
+ * successful.
+ */
+ bool convertTo( PMVariant::PMVariantDataType type );
+private:
+ PMVariant m_value;
+};
+
+/**
+ * Rule that counts child objects of certaint types
+ */
+class PMRuleCount : public PMRuleValue
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleCount( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /**
+ * Destructor
+ */
+ virtual ~PMRuleCount( );
+ /** */
+ virtual QString type( ) const { return QString( "Count" ); }
+ /** */
+ virtual PMVariant evaluate( const PMObject* );
+protected:
+ /** */
+ virtual void countChildProtected( const QString& className,
+ bool afterInsertPoint );
+ /**
+ * Reset all cached data (like counted child objects) here.
+ */
+ virtual void resetProtected( );
+private:
+ QPtrList<PMRuleCategory> m_categories;
+ int m_number;
+};
+
+/**
+ * Base class for conditions
+ */
+class PMRuleCondition : public PMRuleBase
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMRuleCondition( ) : PMRuleBase( ) { }
+ /**
+ * Returns the condition's value.
+ *
+ * Reimplement this method in sub classes.
+ */
+ virtual bool evaluate( const PMObject* object ) = 0;
+};
+
+
+/**
+ * Logical negation
+ */
+class PMRuleNot : public PMRuleCondition
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleNot( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /** */
+ virtual QString type( ) const { return QString( "Not" ); }
+ /** */
+ virtual bool evaluate( const PMObject* object );
+private:
+ PMRuleCondition* m_pChild;
+};
+
+
+/**
+ * Logical and
+ */
+class PMRuleAnd : public PMRuleCondition
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleAnd( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /** */
+ virtual QString type( ) const { return QString( "And" ); }
+ /** */
+ virtual bool evaluate( const PMObject* object );
+private:
+ QPtrList<PMRuleCondition> m_conditions;
+};
+
+/**
+ * Logical or
+ */
+class PMRuleOr : public PMRuleCondition
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleOr( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /** */
+ virtual QString type( ) const { return QString( "Or" ); }
+ /** */
+ virtual bool evaluate( const PMObject* object );
+private:
+ QPtrList<PMRuleCondition> m_conditions;
+};
+
+/**
+ * Condition. Value is true if the object already contains
+ * objects of certaint classes before the insert point.
+ */
+class PMRuleBefore : public PMRuleCondition
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleBefore( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /**
+ * Destructor
+ */
+ virtual ~PMRuleBefore( );
+ /** */
+ virtual QString type( ) const { return QString( "Before" ); }
+ /** */
+ virtual bool evaluate( const PMObject* object );
+protected:
+ /** */
+ virtual void countChildProtected( const QString& className,
+ bool afterInsertPoint );
+ /** */
+ virtual void resetProtected( );
+private:
+ QPtrList<PMRuleCategory> m_categories;
+ bool m_contains;
+};
+
+/**
+ * Condition. Value is true if the object already contains
+ * objects of certaint classes after the insert point.
+ */
+class PMRuleAfter : public PMRuleCondition
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleAfter( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /**
+ * Destructor
+ */
+ virtual ~PMRuleAfter( );
+ /** */
+ virtual QString type( ) const { return QString( "After" ); }
+ /** */
+ virtual bool evaluate( const PMObject* object );
+protected:
+ /** */
+ virtual void countChildProtected( const QString& className,
+ bool afterInsertPoint );
+ /** */
+ virtual void resetProtected( );
+private:
+ QPtrList<PMRuleCategory> m_categories;
+ bool m_contains;
+};
+
+/**
+ * Condition. Value is true if the object already contains
+ * objects of certaint classes.
+ */
+class PMRuleContains : public PMRuleCondition
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleContains( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /**
+ * Destructor
+ */
+ virtual ~PMRuleContains( );
+ /** */
+ virtual QString type( ) const { return QString( "Contains" ); }
+ /** */
+ virtual bool evaluate( const PMObject* object );
+protected:
+ /** */
+ virtual void countChildProtected( const QString& className,
+ bool afterInsertPoint );
+ /** */
+ virtual void resetProtected( );
+private:
+ QPtrList<PMRuleCategory> m_categories;
+ bool m_contains;
+};
+
+/**
+ * Base class for comparisons
+ */
+class PMRuleCompare : public PMRuleCondition
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleCompare( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /** */
+ virtual bool evaluate( const PMObject* object );
+protected:
+ /**
+ * Compares the two variants. The variants have the same type.
+ *
+ * Reimplement this method in sub classes.
+ */
+ virtual bool compare( const PMVariant& v1, const PMVariant& v2 ) = 0;
+private:
+ PMRuleValue* m_pValue[2];
+};
+
+/**
+ * Less than comparison
+ */
+class PMRuleLess : public PMRuleCompare
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleLess( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /** */
+ virtual QString type( ) const { return QString( "Less" ); }
+protected:
+ /** */
+ virtual bool compare( const PMVariant& v1, const PMVariant& v2 );
+};
+
+/**
+ * Greater than comparison
+ */
+class PMRuleGreater : public PMRuleCompare
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleGreater( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /** */
+ virtual QString type( ) const { return QString( "Greater" ); }
+protected:
+ /** */
+ virtual bool compare( const PMVariant& v1, const PMVariant& v2 );
+};
+
+/**
+ * Equal comparison
+ */
+class PMRuleEqual : public PMRuleCompare
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleEqual( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /** */
+ virtual QString type( ) const { return QString( "Equal" ); }
+protected:
+ /** */
+ virtual bool compare( const PMVariant& v1, const PMVariant& v2 );
+};
+
+class PMRule : public PMRuleBase
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRule( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups,
+ QPtrList<PMRuleDefineGroup>& localGroups );
+ /**
+ * Destructor
+ */
+ virtual ~PMRule( );
+ /** */
+ virtual QString type( ) const { return QString( "Rule" ); }
+ /**
+ * Returns true if this rule matches for the given class.
+ */
+ bool matches( const QString& className );
+ /**
+ * Returns the conditions value.
+ */
+ bool evaluate( const PMObject* parent );
+
+private:
+ QPtrList<PMRuleCategory> m_categories;
+ PMRuleCondition* m_pCondition;
+};
+
+/**
+ * Class used internally by the insert rule system
+ *
+ * Stores all rules for one class.
+ */
+class PMRuleTargetClass
+{
+public:
+ /**
+ * Reads the data from the QDomElement.
+ */
+ PMRuleTargetClass( QDomElement& e,
+ QPtrList<PMRuleDefineGroup>& globalGroups );
+ /**
+ * Destructor
+ */
+ ~PMRuleTargetClass( );
+
+ /**
+ * Reads rules and groups from the QDomELement and appends
+ * them to the local ones.
+ */
+ void appendRules( QDomElement& e, QPtrList<PMRuleDefineGroup>& globalGroups );
+ /**
+ * Returns an iterator to the rules
+ */
+ QPtrListIterator<PMRule> rules( ) const
+ {
+ return QPtrListIterator<PMRule>( m_rules );
+ }
+ /**
+ * Returns the class name
+ */
+ QString name( ) const { return m_class; }
+ /**
+ * Returns a list of exceptions for this rule.
+ */
+ QStringList exceptions( ) const { return m_exceptions; }
+private:
+ QPtrList<PMRuleDefineGroup> m_groups;
+ QPtrList<PMRule> m_rules;
+ QString m_class;
+ QStringList m_exceptions;
+};
+
+/**
+ * Rule based system that checks which objects can be inserted as child
+ * into another object.
+ *
+ * The rules are defined in the file "pmbaseinsertrules.xml".
+ * The file "pminsertrules.dtd" is a DTD file that can be used
+ * to validate rule files.
+ *
+ * Plugins can add additional rules to the system.
+ */
+class PMInsertRuleSystem
+{
+public:
+ /**
+ * Constructor
+ */
+ PMInsertRuleSystem( PMPart* part );
+ /**
+ * Destructor
+ */
+ ~PMInsertRuleSystem( );
+
+ /**
+ * Tells the system to load the rules from a file.
+ *
+ * Rules are never loaded twice for the same file. It is save
+ * to call this method twice for the same file.
+ */
+ void loadRules( const QString& fileName );
+
+ /**
+ * Returns true if an object of the given class can be inserted as child
+ * after the object after.
+ *
+ * The parser uses the third parameter for top level objects. These objects
+ * have to be treated as if they are inserted after the object after.
+ */
+ bool canInsert( const PMObject* parentObject, const QString& className,
+ const PMObject* after, const PMObjectList* objectsBetween = 0 );
+
+ /**
+ * Returns true if the object can be inserted as child
+ * after the object after.
+ *
+ * The parser uses the third parameter for top level objects. These objects
+ * have to be treated as if they are inserted after the object after.
+ *
+ * Same as canInsert( parentObject, object->class( ), after, objectsBetween )
+ */
+ bool canInsert( const PMObject* parentObject, const PMObject* object,
+ const PMObject* after, const PMObjectList* objectsBetween = 0 );
+
+ /**
+ * Returns the number of objects that can be inserted at that position
+ */
+ int canInsert( const PMObject* parentObject, const PMObjectList& list,
+ const PMObject* after );
+ /**
+ * Returns the number of objects that can be inserted at that position
+ */
+ int canInsert( const PMObject* parentObject, const QStringList& listOfClasses,
+ const PMObject* after );
+ /**
+ * Returns a pointer to the part
+ */
+ PMPart* part( ) const { return m_pPart; }
+
+private:
+ /**
+ * List of all rules.
+ */
+ QPtrList<PMRuleTargetClass> m_classRules;
+ /**
+ * List of global groups
+ */
+ QPtrList<PMRuleDefineGroup> m_groups;
+ /**
+ * Dictionary that maps from the class name
+ * to a list of rules that match.
+ */
+ QDict<PMRuleTargetClass> m_rulesDict;
+ /**
+ * List of already loaded files
+ */
+ QStringList m_loadedFiles;
+ PMPart* m_pPart;
+};
+
+#endif
diff --git a/kpovmodeler/pminterior.cpp b/kpovmodeler/pminterior.cpp
new file mode 100644
index 00000000..31d7bf5d
--- /dev/null
+++ b/kpovmodeler/pminterior.cpp
@@ -0,0 +1,343 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pminterior.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pminterioredit.h"
+
+#include <klocale.h>
+
+const double iorDefault = 1.0;
+const double causticsDefault = 0.0;
+const double dispersionDefault = 1.0;
+const int dispSamplesDefault = 7;
+const double fadeDistanceDefault = 0.0;
+const double fadePowerDefault = 0.0;
+
+PMDefinePropertyClass( PMInterior, PMInteriorProperty );
+
+PMMetaObject* PMInterior::s_pMetaObject = 0;
+PMObject* createNewInterior( PMPart* part )
+{
+ return new PMInterior( part );
+}
+
+PMInterior::PMInterior( PMPart* part )
+ : Base( part )
+{
+ m_ior = iorDefault;
+ m_caustics = causticsDefault;
+ m_dispersion = dispersionDefault;
+ m_dispSamples = dispSamplesDefault;
+ m_fadeDistance = fadeDistanceDefault;
+ m_fadePower = fadePowerDefault;
+ m_enableIor = false;
+ m_enableCaustics = false;
+ m_enableDispersion = false;
+ m_enableDispSamples = false;
+ m_enableFadeDistance = false;
+ m_enableFadePower = false;
+}
+
+PMInterior::PMInterior( const PMInterior& i )
+ : Base( i )
+{
+ m_ior = i.m_ior;
+ m_caustics = i.m_caustics;
+ m_dispersion = i.m_dispersion;
+ m_dispSamples = i.m_dispSamples;
+ m_fadeDistance = i.m_fadeDistance;
+ m_fadePower = i.m_fadePower;
+ m_enableIor = i.m_enableIor;
+ m_enableCaustics = i.m_enableCaustics;
+ m_enableDispersion = i.m_enableDispersion;
+ m_enableDispSamples = i.m_enableDispSamples;
+ m_enableFadeDistance = i.m_enableFadeDistance;
+ m_enableFadePower = i.m_enableFadePower;
+}
+
+PMInterior::~PMInterior( )
+{
+}
+
+PMMetaObject* PMInterior::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Interior", Base::metaObject( ),
+ createNewInterior );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "ior", &PMInterior::setIor, &PMInterior::ior ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "caustics", &PMInterior::setCaustics, &PMInterior::caustics ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "dispersion", &PMInterior::setDispersion, &PMInterior::dispersion ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "dispSamples", &PMInterior::setDispSamples, &PMInterior::dispSamples ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "fadeDistance", &PMInterior::setFadeDistance, &PMInterior::fadeDistance ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "fadePower", &PMInterior::setFadePower, &PMInterior::fadePower ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "iorEnabled", &PMInterior::enableIor, &PMInterior::isIorEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "causticsEnabled", &PMInterior::enableCaustics, &PMInterior::isCausticsEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "dispersionEnabled", &PMInterior::enableDispersion, &PMInterior::isDispersionEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "dispSamplesEnabled", &PMInterior::enableDispSamples, &PMInterior::isDispSamplesEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "fadeDistanceEnabled", &PMInterior::enableFadeDistance, &PMInterior::isFadeDistanceEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMInteriorProperty( "fadePowerEnabled", &PMInterior::enableFadePower, &PMInterior::isFadePowerEnabled ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMInterior::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMInterior::description( ) const
+{
+ return i18n( "interior" );
+}
+
+void PMInterior::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ Base::serialize( e, doc );
+ e.setAttribute( "enable_ior", m_enableIor );
+ e.setAttribute( "enable_caustics", m_enableCaustics );
+ e.setAttribute( "enable_dispersion", m_enableDispersion );
+ e.setAttribute( "enable_disp_samples", m_enableDispSamples );
+ e.setAttribute( "enable_fade_distance", m_enableFadeDistance );
+ e.setAttribute( "enable_fade_power", m_enableFadePower );
+ e.setAttribute( "ior", m_ior );
+ e.setAttribute( "caustics", m_caustics );
+ e.setAttribute( "dispersion", m_dispersion );
+ e.setAttribute( "disp_samples", m_dispSamples );
+ e.setAttribute( "fade_distance", m_fadeDistance );
+ e.setAttribute( "fade_power", m_fadePower );
+}
+
+void PMInterior::readAttributes( const PMXMLHelper& h )
+{
+ Base::readAttributes( h );
+ m_enableIor = h.boolAttribute( "enable_ior", false );
+ m_enableCaustics = h.boolAttribute( "enable_caustics", false );
+ m_enableDispersion = h.boolAttribute( "enable_dispersion", false );
+ m_enableDispSamples = h.boolAttribute( "enable_disp_samples", false );
+ m_enableFadeDistance = h.boolAttribute( "enable_fade_distance", false );
+ m_enableFadePower = h.boolAttribute( "enable_fade_power", false );
+ m_ior = h.doubleAttribute( "ior", iorDefault );
+ m_caustics = h.doubleAttribute( "caustics", causticsDefault );
+ m_dispersion = h.doubleAttribute( "dispersion", dispersionDefault );
+ m_dispSamples = h.intAttribute( "disp_samples", dispSamplesDefault );
+ m_fadeDistance = h.doubleAttribute( "fade_distance", fadeDistanceDefault );
+ m_fadePower = h.doubleAttribute( "fade_power", fadePowerDefault );
+}
+
+void PMInterior::setIor( double c )
+{
+ if( c != m_ior )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMIorID, m_ior );
+ m_ior = c;
+ }
+}
+
+void PMInterior::setCaustics( double c )
+{
+ if( c != m_caustics )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCausticsID, m_caustics );
+ m_caustics = c;
+ }
+}
+
+void PMInterior::setDispersion( double c )
+{
+ if ( c != m_dispersion )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDispersionID, m_dispersion );
+ m_dispersion = c;
+ }
+}
+
+void PMInterior::setDispSamples( int c )
+{
+ if ( c != m_dispSamples )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDispSamplesID, m_dispSamples );
+ m_dispSamples = c;
+ }
+}
+
+void PMInterior::setFadeDistance( double c )
+{
+ if( c != m_fadeDistance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFadeDistanceID, m_fadeDistance );
+ m_fadeDistance = c;
+ }
+}
+
+void PMInterior::setFadePower( double c )
+{
+ if( c != m_fadePower )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFadePowerID, m_fadePower );
+ m_fadePower = c;
+ }
+}
+
+void PMInterior::enableIor( bool c )
+{
+ if( c != m_enableIor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableIorID, m_enableIor );
+ m_enableIor = c;
+ }
+}
+
+void PMInterior::enableCaustics( bool c )
+{
+ if( c != m_enableCaustics )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableCausticsID, m_enableCaustics );
+ m_enableCaustics = c;
+ }
+}
+
+void PMInterior::enableDispersion( bool c )
+{
+ if( c != m_enableDispersion )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableDispersionID, m_enableDispersion );
+ m_enableDispersion = c;
+ }
+}
+
+void PMInterior::enableDispSamples( bool c )
+{
+ if( c != m_enableDispSamples )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableDispSamplesID, m_enableDispSamples );
+ m_enableDispSamples = c;
+ }
+}
+
+void PMInterior::enableFadeDistance( bool c )
+{
+ if( c != m_enableFadeDistance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableFadeDistanceID,
+ m_enableFadeDistance );
+ m_enableFadeDistance = c;
+ }
+}
+
+void PMInterior::enableFadePower( bool c )
+{
+ if( c != m_enableFadePower )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableFadePowerID,
+ m_enableFadePower );
+ m_enableFadePower = c;
+ }
+}
+
+PMDialogEditBase* PMInterior::editWidget( QWidget* parent ) const
+{
+ return new PMInteriorEdit( parent );
+}
+
+void PMInterior::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMIorID:
+ setIor( data->doubleData( ) );
+ break;
+ case PMCausticsID:
+ setCaustics( data->doubleData( ) );
+ break;
+ case PMDispersionID:
+ setDispersion( data->doubleData( ) );
+ break;
+ case PMDispSamplesID:
+ setDispSamples( data->intData( ) );
+ break;
+ case PMFadeDistanceID:
+ setFadeDistance( data->doubleData( ) );
+ break;
+ case PMFadePowerID:
+ setFadePower( data->doubleData( ) );
+ break;
+ case PMEnableIorID:
+ enableIor( data->boolData( ) );
+ break;
+ case PMEnableCausticsID:
+ enableCaustics( data->boolData( ) );
+ break;
+ case PMEnableDispersionID:
+ enableDispersion( data->boolData( ) );
+ break;
+ case PMEnableDispSamplesID:
+ enableDispSamples( data->boolData( ) );
+ case PMEnableFadeDistanceID:
+ enableFadeDistance( data->boolData( ) );
+ break;
+ case PMEnableFadePowerID:
+ enableFadePower( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMInterior::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pminterior.h b/kpovmodeler/pminterior.h
new file mode 100644
index 00000000..159b6b64
--- /dev/null
+++ b/kpovmodeler/pminterior.h
@@ -0,0 +1,128 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMINTERIOR_H
+#define PMINTERIOR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+#include "pmcolor.h"
+
+/**
+ * Class for povray interiors
+ */
+class PMInterior : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMInterior
+ */
+ PMInterior( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMInterior( const PMInterior& i );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMInterior( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMInterior( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMInteriorEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pminterior" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ double ior( ) const { return m_ior; }
+ double caustics( ) const { return m_caustics; }
+ double dispersion( ) const { return m_dispersion; }
+ int dispSamples( ) const { return m_dispSamples; }
+ double fadeDistance( ) const { return m_fadeDistance; }
+ double fadePower( ) const { return m_fadePower; }
+ bool isIorEnabled( ) const { return m_enableIor; }
+ bool isCausticsEnabled( ) const { return m_enableCaustics; }
+ bool isDispersionEnabled( ) const { return m_enableDispersion; }
+ bool isDispSamplesEnabled( ) const { return m_enableDispSamples; }
+ bool isFadeDistanceEnabled( ) const { return m_enableFadeDistance; }
+ bool isFadePowerEnabled( ) const { return m_enableFadePower; }
+
+ void setIor( double c );
+ void setCaustics( double c );
+ void setDispersion ( double c );
+ void setDispSamples ( int c );
+ void setFadeDistance( double c );
+ void setFadePower( double c );
+ void enableIor( bool c );
+ void enableCaustics( bool c );
+ void enableDispersion( bool c );
+ void enableDispSamples( bool c );
+ void enableFadeDistance( bool c );
+ void enableFadePower( bool c );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMInteriorMementoID { PMIorID, PMCausticsID, PMDispersionID,
+ PMDispSamplesID, PMFadeDistanceID, PMFadePowerID,
+ PMEnableIorID, PMEnableCausticsID,
+ PMEnableDispersionID, PMEnableDispSamplesID,
+ PMEnableFadeDistanceID, PMEnableFadePowerID };
+ double m_ior;
+ double m_caustics;
+ double m_dispersion;
+ int m_dispSamples;
+ double m_fadeDistance;
+ double m_fadePower;
+
+ bool m_enableIor;
+ bool m_enableCaustics;
+ bool m_enableDispersion;
+ bool m_enableDispSamples;
+ bool m_enableFadeDistance;
+ bool m_enableFadePower;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pminterioredit.cpp b/kpovmodeler/pminterioredit.cpp
new file mode 100644
index 00000000..b5df1825
--- /dev/null
+++ b/kpovmodeler/pminterioredit.cpp
@@ -0,0 +1,212 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pminterioredit.h"
+#include "pminterior.h"
+#include "pmlineedits.h"
+#include "pmcoloredit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+
+PMInteriorEdit::PMInteriorEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMInteriorEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ QGridLayout* layout = new QGridLayout( hl ,17 ,6);
+ m_pEnableIorEdit = new QCheckBox( i18n( "Refraction:" ), this );
+ m_pIorEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableIorEdit, 0, 0 );
+ layout->addWidget( m_pIorEdit, 0, 1 );
+ m_pEnableCausticsEdit = new QCheckBox( i18n( "Caustics:" ), this );
+ m_pCausticsEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableCausticsEdit, 1, 0 );
+ layout->addWidget( m_pCausticsEdit, 1, 1 );
+ m_pEnableDispersionEdit = new QCheckBox( i18n( "Dispersion:" ), this );
+ m_pDispersionEdit = new PMFloatEdit( this );
+ m_pDispersionEdit->setValidation( true, 0, false, 0 );
+ layout->addWidget( m_pEnableDispersionEdit, 2, 0 );
+ layout->addWidget( m_pDispersionEdit, 2, 1 );
+ m_pEnableDispSamplesEdit = new QCheckBox( i18n( "Dispersion samples:" ), this );
+ m_pDispSamplesEdit = new PMIntEdit( this );
+ m_pDispSamplesEdit->setValidation( true, 2, false, 0 );
+ layout->addWidget( m_pEnableDispSamplesEdit, 3, 0 );
+ layout->addWidget( m_pDispSamplesEdit, 3, 1 );
+ m_pEnableFadeDistanceEdit = new QCheckBox( i18n( "Fade distance:" ), this );
+ m_pFadeDistanceEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableFadeDistanceEdit, 4, 0 );
+ layout->addWidget( m_pFadeDistanceEdit, 4, 1 );
+ m_pEnableFadePowerEdit = new QCheckBox( i18n( "Fade power:" ), this );
+ m_pFadePowerEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pEnableFadePowerEdit, 5, 0 );
+ layout->addWidget( m_pFadePowerEdit, 5, 1 );
+ hl->addStretch( 1 );
+
+ connect( m_pIorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCausticsEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDispersionEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDispSamplesEdit, SIGNAL( dataChanged( ) ), SIGNAL ( dataChanged( ) ) );
+ connect( m_pFadeDistanceEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFadePowerEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnableIorEdit, SIGNAL( clicked( ) ), SLOT( slotIorClicked( ) ) );
+ connect( m_pEnableCausticsEdit, SIGNAL( clicked( ) ), SLOT( slotCausticsClicked( ) ) );
+ connect( m_pEnableDispersionEdit, SIGNAL( clicked( ) ), SLOT( slotDispersionClicked( ) ) );
+ connect( m_pEnableDispSamplesEdit, SIGNAL( clicked( ) ), SLOT( slotDispSamplesClicked( ) ) );
+ connect( m_pEnableFadeDistanceEdit, SIGNAL( clicked( ) ), SLOT( slotFadeDistanceClicked( ) ) );
+ connect( m_pEnableFadePowerEdit, SIGNAL( clicked( ) ), SLOT( slotFadePowerClicked( ) ) );
+}
+
+void PMInteriorEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Interior" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMInterior* ) o;
+
+ m_pIorEdit->setValue( m_pDisplayedObject->ior( ) );
+ m_pIorEdit->setReadOnly( readOnly );
+ m_pCausticsEdit->setValue( m_pDisplayedObject->caustics( ) );
+ m_pCausticsEdit->setReadOnly( readOnly );
+ m_pDispersionEdit->setValue( m_pDisplayedObject->dispersion( ) );
+ m_pDispersionEdit->setReadOnly( readOnly );
+ m_pDispSamplesEdit->setValue( m_pDisplayedObject->dispSamples( ) );
+ m_pDispSamplesEdit->setReadOnly( readOnly );
+ m_pFadeDistanceEdit->setValue( m_pDisplayedObject->fadeDistance( ) );
+ m_pFadeDistanceEdit->setReadOnly( readOnly );
+ m_pFadePowerEdit->setValue( m_pDisplayedObject->fadePower( ) );
+ m_pFadePowerEdit->setReadOnly( readOnly );
+ m_pEnableIorEdit->setChecked( m_pDisplayedObject->isIorEnabled( ) );
+ m_pEnableIorEdit->setEnabled( !readOnly );
+ m_pEnableCausticsEdit->setChecked( m_pDisplayedObject->isCausticsEnabled( ) );
+ m_pEnableCausticsEdit->setEnabled( !readOnly );
+ m_pEnableDispersionEdit->setChecked( m_pDisplayedObject->isDispersionEnabled( ) );
+ m_pEnableDispersionEdit->setEnabled( !readOnly );
+ m_pEnableDispSamplesEdit->setChecked( m_pDisplayedObject->isDispSamplesEnabled( ) );
+ m_pEnableDispSamplesEdit->setEnabled( !readOnly );
+ m_pEnableFadeDistanceEdit->setChecked( m_pDisplayedObject->isFadeDistanceEnabled( ) );
+ m_pEnableFadeDistanceEdit->setEnabled( !readOnly );
+ m_pEnableFadePowerEdit->setChecked( m_pDisplayedObject->isFadePowerEnabled( ) );
+ m_pEnableFadePowerEdit->setEnabled( !readOnly );
+ slotIorClicked( );
+ slotCausticsClicked( );
+ slotDispersionClicked( );
+ slotDispSamplesClicked( );
+ slotFadeDistanceClicked( );
+ slotFadePowerClicked( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMInteriorEdit: Can't display object\n";
+}
+
+void PMInteriorEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setIor( m_pIorEdit->value( ) );
+ m_pDisplayedObject->setCaustics( m_pCausticsEdit->value( ) );
+ m_pDisplayedObject->setDispersion( m_pDispersionEdit->value( ) );
+ m_pDisplayedObject->setDispSamples( m_pDispSamplesEdit->value( ) );
+ m_pDisplayedObject->setFadeDistance( m_pFadeDistanceEdit->value( ) );
+ m_pDisplayedObject->setFadePower( m_pFadePowerEdit->value( ) );
+ m_pDisplayedObject->enableIor( m_pEnableIorEdit->isChecked( ) );
+ m_pDisplayedObject->enableCaustics( m_pEnableCausticsEdit->isChecked( ) );
+ m_pDisplayedObject->enableDispersion( m_pEnableDispersionEdit->isChecked( ) );
+ m_pDisplayedObject->enableDispSamples( m_pEnableDispSamplesEdit->isChecked( ) );
+ m_pDisplayedObject->enableFadeDistance( m_pEnableFadeDistanceEdit->isChecked( ) );
+ m_pDisplayedObject->enableFadePower( m_pEnableFadePowerEdit->isChecked( ) );
+ }
+}
+
+bool PMInteriorEdit::isDataValid( )
+{
+ if( !m_pIorEdit->isDataValid( ) ) return false;
+ if( !m_pCausticsEdit->isDataValid( ) ) return false;
+ if( !m_pDispersionEdit->isDataValid( ) ) return false;
+ if( !m_pDispSamplesEdit->isDataValid( ) ) return false;
+ if( !m_pFadeDistanceEdit->isDataValid( ) ) return false;
+ if( !m_pFadePowerEdit->isDataValid( ) ) return false;
+ if( !m_pFadeDistanceEdit->isDataValid( ) ) return false;
+
+ return Base::isDataValid( );
+}
+
+void PMInteriorEdit::slotIorClicked( )
+{
+ if( m_pEnableIorEdit->isChecked( ) )
+ {
+ m_pIorEdit->setEnabled( true );
+ m_pEnableDispersionEdit->setEnabled( true );
+ m_pEnableDispSamplesEdit->setEnabled( true );
+ }
+ else
+ {
+ m_pIorEdit->setEnabled( false );
+ m_pEnableDispersionEdit->setEnabled( false );
+ m_pEnableDispSamplesEdit->setEnabled( false );
+ m_pEnableDispersionEdit->setChecked( false );
+ m_pEnableDispSamplesEdit->setChecked( false );
+ slotDispersionClicked( );
+ slotDispSamplesClicked( );
+ }
+ emit dataChanged( );
+}
+
+void PMInteriorEdit::slotCausticsClicked( )
+{
+ m_pCausticsEdit->setEnabled( m_pEnableCausticsEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMInteriorEdit::slotDispersionClicked( )
+{
+ m_pDispersionEdit->setEnabled( m_pEnableDispersionEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMInteriorEdit::slotDispSamplesClicked( )
+{
+ m_pDispSamplesEdit->setEnabled( m_pEnableDispSamplesEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMInteriorEdit::slotFadeDistanceClicked( )
+{
+ m_pFadeDistanceEdit->setEnabled( m_pEnableFadeDistanceEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMInteriorEdit::slotFadePowerClicked( )
+{
+ m_pFadePowerEdit->setEnabled( m_pEnableFadePowerEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+#include "pminterioredit.moc"
diff --git a/kpovmodeler/pminterioredit.h b/kpovmodeler/pminterioredit.h
new file mode 100644
index 00000000..93564bcb
--- /dev/null
+++ b/kpovmodeler/pminterioredit.h
@@ -0,0 +1,85 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMINTERIOREDIT_H
+#define PMINTERIOREDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMInterior;
+class PMIntEdit;
+class PMFloatEdit;
+class PMColorEdit;
+class QCheckBox;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMInterior
+ */
+class PMInteriorEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMInteriorEdit with parent and name
+ */
+ PMInteriorEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotIorClicked( );
+ void slotCausticsClicked( );
+ void slotDispersionClicked( );
+ void slotDispSamplesClicked( );
+ void slotFadePowerClicked( );
+ void slotFadeDistanceClicked( );
+
+private:
+ PMInterior* m_pDisplayedObject;
+ PMFloatEdit* m_pIorEdit;
+ PMFloatEdit* m_pCausticsEdit;
+ PMFloatEdit* m_pDispersionEdit;
+ PMIntEdit* m_pDispSamplesEdit;
+ PMFloatEdit* m_pFadeDistanceEdit;
+ PMFloatEdit* m_pFadePowerEdit;
+ QCheckBox* m_pEnableIorEdit;
+ QCheckBox* m_pEnableCausticsEdit;
+ QCheckBox* m_pEnableDispersionEdit;
+ QCheckBox* m_pEnableDispSamplesEdit;
+ QCheckBox* m_pEnableFadeDistanceEdit;
+ QCheckBox* m_pEnableFadePowerEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pminteriortexture.cpp b/kpovmodeler/pminteriortexture.cpp
new file mode 100644
index 00000000..f379e4b6
--- /dev/null
+++ b/kpovmodeler/pminteriortexture.cpp
@@ -0,0 +1,75 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pminteriortexture.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pminteriortextureedit.h"
+
+#include <klocale.h>
+
+PMMetaObject* PMInteriorTexture::s_pMetaObject = 0;
+PMObject* createNewInteriorTexture( PMPart* part )
+{
+ return new PMInteriorTexture( part );
+}
+
+PMInteriorTexture::PMInteriorTexture( PMPart* part )
+ : Base( part )
+{
+}
+
+PMInteriorTexture::PMInteriorTexture( const PMInteriorTexture& t )
+ : Base( t )
+{
+}
+
+PMInteriorTexture::~PMInteriorTexture( )
+{
+}
+
+PMMetaObject* PMInteriorTexture::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "InteriorTexture", Base::metaObject( ),
+ createNewInteriorTexture );
+ }
+ return s_pMetaObject;
+}
+
+void PMInteriorTexture::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMInteriorTexture::description( ) const
+{
+ return i18n( "interior texture" );
+}
+
+PMDialogEditBase* PMInteriorTexture::editWidget( QWidget* parent ) const
+{
+ return new PMInteriorTextureEdit( parent );
+}
+
diff --git a/kpovmodeler/pminteriortexture.h b/kpovmodeler/pminteriortexture.h
new file mode 100644
index 00000000..8682e69d
--- /dev/null
+++ b/kpovmodeler/pminteriortexture.h
@@ -0,0 +1,71 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMINTERIORTEXTURE_H
+#define PMINTERIORTEXTURE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+
+/**
+ * Class for povray interior textures
+ */
+class PMInteriorTexture : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMInteriorTexture
+ */
+ PMInteriorTexture( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMInteriorTexture( const PMInteriorTexture& t );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMInteriorTexture( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMInteriorTexture( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /**
+ * Returns a new @ref PMTextureEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pminteriortexture" ); }
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pminteriortextureedit.cpp b/kpovmodeler/pminteriortextureedit.cpp
new file mode 100644
index 00000000..47fe6f38
--- /dev/null
+++ b/kpovmodeler/pminteriortextureedit.cpp
@@ -0,0 +1,44 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pminteriortextureedit.h"
+#include "pminteriortexture.h"
+#include "pmlinkedit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMInteriorTextureEdit::PMInteriorTextureEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMInteriorTextureEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "InteriorTexture" ) )
+ {
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMInteriorTextureEdit: Can't display object\n";
+}
+
+#include "pminteriortextureedit.moc"
diff --git a/kpovmodeler/pminteriortextureedit.h b/kpovmodeler/pminteriortextureedit.h
new file mode 100644
index 00000000..1594ef6e
--- /dev/null
+++ b/kpovmodeler/pminteriortextureedit.h
@@ -0,0 +1,58 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMINTERIORTEXTUREEDIT_H
+#define PMINTERIORTEXTUREEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMInteriorTexture;
+
+/**
+ * Dialog edit class for @ref PMTexture
+ */
+class PMInteriorTextureEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMTextureEdit with parent and name
+ */
+ PMInteriorTextureEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+// virtual void createTopWidgets( );
+ /** */
+// virtual void saveContents( );
+
+private:
+ PMInteriorTexture* m_pDisplayedObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmiomanager.cpp b/kpovmodeler/pmiomanager.cpp
new file mode 100644
index 00000000..72a081d2
--- /dev/null
+++ b/kpovmodeler/pmiomanager.cpp
@@ -0,0 +1,96 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmiomanager.h"
+#include "pmdebug.h"
+#include "pmpovray31format.h"
+#include "pmpovray35format.h"
+
+PMIOFormat::PMIOFormat( )
+{
+}
+
+PMIOFormat::~PMIOFormat( )
+{
+
+}
+
+PMIOManager::PMIOManager( PMPart* part )
+{
+ m_pPart = part;
+ m_formats.setAutoDelete( true );
+
+ addFormat( new PMPovray35Format( ) );
+ //addFormat( new PMPovray31Format( ) );
+}
+
+PMIOManager::~PMIOManager( )
+{
+
+}
+
+void PMIOManager::addFormat( PMIOFormat* format )
+{
+ if( !format )
+ return;
+ if( !m_formats.containsRef( format ) )
+ {
+ if( !m_dict.find( format->name( ) ) )
+ {
+ m_formats.append( format );
+ m_dict.insert( format->name( ), format );
+ }
+ else
+ kdError( PMArea ) << "Format " << format->name( ) << "already registered" << endl;
+ }
+ else
+ kdError( PMArea ) << "Format " << format->name( ) << "already registered" << endl;
+}
+
+void PMIOManager::removeFormat( const QString& name )
+{
+ PMIOFormat* pFormat = format( name );
+ if( pFormat )
+ {
+ m_dict.remove( name );
+ m_formats.removeRef( pFormat );
+ }
+}
+
+PMIOFormat* PMIOManager::format( const QString& name ) const
+{
+ return m_dict.find( name );
+}
+
+PMIOFormat* PMIOManager::formatForMimeType( const QString& mime ) const
+{
+ QPtrListIterator<PMIOFormat> it( m_formats );
+ bool found = false;
+ PMIOFormat* pFormat = 0;
+
+ while( it.current( ) && !found )
+ {
+ pFormat = it.current( );
+ if( pFormat->mimeType( ) == mime )
+ found = true;
+ else
+ ++it;
+ }
+ if( found )
+ return pFormat;
+ return 0;
+}
diff --git a/kpovmodeler/pmiomanager.h b/kpovmodeler/pmiomanager.h
new file mode 100644
index 00000000..ac3b78eb
--- /dev/null
+++ b/kpovmodeler/pmiomanager.h
@@ -0,0 +1,184 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMIOMANAGER
+#define PMIOMANAGER
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qptrlist.h>
+#include <qdict.h>
+
+class PMParser;
+class PMSerializer;
+class PMRenderer;
+class PMPart;
+
+class QIODevice;
+
+/**
+ * Description class for input and output formats.
+ *
+ * A format may provide the following services:
+ *
+ * Import: The class can provide a parser to load and import data
+ *
+ * Export: The class can provide a output device to export and save data
+ *
+ * Renderer: A renderer exists to render the exported data
+ *
+ * The class @ref PMIOManager stores a list of instances
+ * of this class
+ */
+class PMIOFormat
+{
+public:
+ /**
+ * Format type enum
+ */
+ enum Services { Import = 1, Export = 2, Renderer = 4,
+ AllServices = Import | Export | Renderer };
+ /**
+ * Default constructor
+ */
+ PMIOFormat( );
+ /**
+ * Destructor
+ */
+ virtual ~PMIOFormat( );
+
+ /**
+ * Returns an unique name of this format.
+ */
+ virtual QString name( ) const = 0;
+ /**
+ * Returns a translated description of this format
+ */
+ virtual QString description( ) const = 0;
+ /**
+ * Returns the supported services
+ * (a bitwise combination of the Services enum values)
+ */
+ virtual int services( ) const = 0;
+ /**
+ * Returns a parser to parse the io device.
+ *
+ * The caller is responsible to delete the returned parser.
+ */
+ virtual PMParser* newParser( PMPart*, QIODevice* ) const
+ {
+ return 0;
+ };
+ /**
+ * Returns a parser to parse the byte array.
+ *
+ * The caller is responsible to delete the returned parser.
+ */
+ virtual PMParser* newParser( PMPart*, const QByteArray& ) const
+ {
+ return 0;
+ };
+ /**
+ * Returns an output device to export objects or the complete
+ * scene to the given io device.
+ *
+ * The caller is responsible to delete the returned device
+ */
+ virtual PMSerializer* newSerializer( QIODevice* )
+ {
+ return 0;
+ }
+ /**
+ * Returns a new renderer
+ */
+ virtual PMRenderer* newRenderer( PMPart* ) const
+ {
+ return 0;
+ }
+ /**
+ * Returns the mime type for this format
+ */
+ virtual QString mimeType( ) const
+ {
+ return QString::null;
+ }
+ /**
+ * Returns a list of patterns for the import file dialog
+ */
+ virtual QStringList importPatterns( ) const
+ {
+ return QStringList( );
+ }
+ /**
+ * Returns a list of patterns for the export file dialog
+ */
+ virtual QStringList exportPatterns( ) const
+ {
+ return QStringList( );
+ }
+};
+
+/**
+ * Manager class that handles all available input and output formats
+ * as well as renderers for one part
+ */
+class PMIOManager
+{
+public:
+ /**
+ * Creates an io manager for the part
+ */
+ PMIOManager( PMPart* part );
+ /**
+ * Deletes the io manager
+ */
+ ~PMIOManager( );
+
+ /**
+ * Adds a new format
+ */
+ void addFormat( PMIOFormat* format );
+ /**
+ * Removes a format by name
+ */
+ void removeFormat( const QString& name );
+
+ /**
+ * Returns the list of registered io formats
+ */
+ const QPtrList<PMIOFormat>& formats( ) const { return m_formats; }
+ /**
+ * Returns a view type by name
+ */
+ PMIOFormat* format( const QString& name ) const;
+ /**
+ * Returns the first io format that can handle the mime type
+ * or 0 if there is none
+ */
+ PMIOFormat* formatForMimeType( const QString& mime ) const;
+
+private:
+ QPtrList<PMIOFormat> m_formats;
+ QDict<PMIOFormat> m_dict;
+ PMPart* m_pPart;
+};
+
+#endif
diff --git a/kpovmodeler/pmisosurface.cpp b/kpovmodeler/pmisosurface.cpp
new file mode 100644
index 00000000..16e5e247
--- /dev/null
+++ b/kpovmodeler/pmisosurface.cpp
@@ -0,0 +1,419 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmisosurface.h"
+
+#include "pmxmlhelper.h"
+#include "pmisosurfaceedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+
+#include <klocale.h>
+
+const PMIsoSurface::ContainedByType c_defaultContainedBy = PMIsoSurface::Box;
+const PMVector c_defaultCorner1 = PMVector( -1, -1, -1 );
+const PMVector c_defaultCorner2 = PMVector( 1, 1, 1 );
+const PMVector c_defaultCenter = PMVector( 0, 0, 0 );
+const double c_defaultRadius = 1;
+
+const double c_defaultThreshold = 0.0;
+const double c_defaultAccuracy = 0.001;
+const double c_defaultMaxGradient = 1.1;
+const bool c_defaultEvaluate = false;
+const double c_defaultEvaluate0 = 5;
+const double c_defaultEvaluate1 = 1.2;
+const double c_defaultEvaluate2 = 0.95;
+const double c_defaultOpen = false;
+const int c_defaultMaxTrace = 1;
+const bool c_defaultAllIntersections = false;
+
+PMDefinePropertyClass( PMIsoSurface, PMIsoSurfaceProperty );
+
+PMViewStructure* PMIsoSurface::s_pDefaultViewStructure = 0;
+PMMetaObject* PMIsoSurface::s_pMetaObject = 0;
+PMObject* createNewIsoSurface( PMPart* part )
+{
+ return new PMIsoSurface( part );
+}
+
+PMIsoSurface::PMIsoSurface( PMPart* part )
+ : Base( part )
+{
+ m_containedBy = c_defaultContainedBy;
+ m_corner1 = c_defaultCorner1;
+ m_corner2 = c_defaultCorner2;
+ m_center = c_defaultCenter;
+ m_radius = c_defaultRadius;
+ m_threshold = c_defaultThreshold;
+ m_accuracy = c_defaultAccuracy;
+ m_maxGradient = c_defaultMaxGradient;
+ m_bEvaluate = c_defaultEvaluate;
+ m_evaluate[0] = c_defaultEvaluate0;
+ m_evaluate[1] = c_defaultEvaluate1;
+ m_evaluate[2] = c_defaultEvaluate2;
+ m_bOpen = c_defaultOpen;
+ m_maxTrace = c_defaultMaxTrace;
+ m_bAllIntersections = c_defaultAllIntersections;
+}
+
+PMIsoSurface::PMIsoSurface( const PMIsoSurface& b )
+ : Base( b )
+{
+ m_function = b.m_function;
+ m_containedBy = b.m_containedBy;
+ m_corner1 = b.m_corner1;
+ m_corner2 = b.m_corner2;
+ m_center = b.m_center;
+ m_radius = b.m_radius;
+ m_threshold = b.m_threshold;
+ m_accuracy = b.m_accuracy;
+ m_maxGradient = m_maxGradient;
+ m_bEvaluate = b.m_bEvaluate;
+ m_evaluate[0] = b.m_evaluate[0];
+ m_evaluate[1] = b.m_evaluate[1];
+ m_evaluate[2] = b.m_evaluate[2];
+ m_bOpen = b.m_bOpen;
+ m_maxTrace = b.m_maxTrace;
+ m_bAllIntersections = b.m_bAllIntersections;
+}
+
+PMIsoSurface::~PMIsoSurface( )
+{
+}
+
+QString PMIsoSurface::description( ) const
+{
+ return i18n( "isosurface" );
+}
+
+void PMIsoSurface::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ QDomText t = doc.createTextNode( m_function );
+ e.appendChild( t );
+
+ if( m_containedBy == Box )
+ e.setAttribute( "contained_by", "box" );
+ else
+ e.setAttribute( "contained_by", "sphere" );
+ e.setAttribute( "corner_a", m_corner1.serializeXML( ) );
+ e.setAttribute( "corner_b", m_corner2.serializeXML( ) );
+ e.setAttribute( "center", m_center.serializeXML( ) );
+ e.setAttribute( "radius", m_radius );
+ e.setAttribute( "threshold", m_threshold );
+ e.setAttribute( "accuracy", m_accuracy );
+ e.setAttribute( "max_gradient", m_maxGradient );
+ e.setAttribute( "evaluate", m_bEvaluate );
+ e.setAttribute( "e0", m_evaluate[0] );
+ e.setAttribute( "e1", m_evaluate[1] );
+ e.setAttribute( "e2", m_evaluate[2] );
+ e.setAttribute( "open", m_bOpen );
+ e.setAttribute( "max_trace", m_maxTrace );
+ e.setAttribute( "all_intersections", m_bAllIntersections );
+ Base::serialize( e, doc );
+}
+
+void PMIsoSurface::readAttributes( const PMXMLHelper& h )
+{
+ QDomNode e = h.element( ).firstChild( );
+ if( e.isText( ) )
+ m_function = e.toText( ).data( );
+
+ QString str = h.stringAttribute( "contained_by", "" );
+ if( str == "sphere" )
+ m_containedBy = Sphere;
+ else
+ m_containedBy = Box;
+
+ m_corner1 = h.vectorAttribute( "corner_a", c_defaultCorner1 );
+ m_corner2 = h.vectorAttribute( "corner_b", c_defaultCorner1 );
+ m_center = h.vectorAttribute( "center", c_defaultCenter );
+ m_radius = h.doubleAttribute( "radius", c_defaultRadius );
+ m_threshold = h.doubleAttribute( "threshold", c_defaultThreshold );
+ m_accuracy = h.doubleAttribute( "accuracy", c_defaultAccuracy );
+ m_maxGradient = h.doubleAttribute( "max_gradient", c_defaultMaxGradient );
+ m_bEvaluate = h.boolAttribute( "evaluate", c_defaultEvaluate );
+ m_evaluate[0] = h.doubleAttribute( "e0", c_defaultEvaluate0 );
+ m_evaluate[1] = h.doubleAttribute( "e1", c_defaultEvaluate1 );
+ m_evaluate[2] = h.doubleAttribute( "e2", c_defaultEvaluate2 );
+ m_bOpen = h.boolAttribute( "open", c_defaultOpen );
+ m_maxTrace = h.intAttribute( "max_trace", c_defaultMaxTrace );
+ m_bAllIntersections = h.boolAttribute( "all_intersections", c_defaultAllIntersections );
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMIsoSurface::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "IsoSurface", Base::metaObject( ),
+ createNewIsoSurface );
+ // TODO
+ /*
+ s_pMetaObject->addProperty(
+ new PMIsoSurfaceProperty( "corner1", &PMIsoSurface::setCorner1, &PMIsoSurface::corner1 ) );
+ s_pMetaObject->addProperty(
+ new PMIsoSurfaceProperty( "corner2", &PMIsoSurface::setCorner2, &PMIsoSurface::corner2 ) );
+ */
+ }
+ return s_pMetaObject;
+}
+
+void PMIsoSurface::setFunction( const QString& f )
+{
+ if( f != m_function )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, FunctionID, m_function );
+ m_function = f;
+ }
+}
+
+void PMIsoSurface::setContainedBy( ContainedByType type )
+{
+ if( type != m_containedBy )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, ContainedByID, m_containedBy );
+ m_containedBy = type;
+ }
+}
+
+void PMIsoSurface::setCorner1( const PMVector& p )
+{
+ if( p != m_corner1 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, Corner1ID, m_corner1 );
+ m_corner1 = p;
+ m_corner1.resize( 3 );
+ //setViewStructureChanged( );
+ }
+}
+
+void PMIsoSurface::setCorner2( const PMVector& p )
+{
+ if( p != m_corner2 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, Corner2ID, m_corner2 );
+ m_corner2 = p;
+ m_corner2.resize( 3 );
+ //setViewStructureChanged( );
+ }
+}
+
+void PMIsoSurface::setCenter( const PMVector& v )
+{
+ if( v != m_center )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, CenterID, m_center );
+ m_center = v;
+ }
+}
+
+void PMIsoSurface::setRadius( double r )
+{
+ if( r != m_radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, RadiusID, m_radius );
+ m_radius = r;
+ }
+}
+void PMIsoSurface::setThreshold( double d )
+{
+ if( d != m_threshold )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, ThresholdID, m_threshold );
+ m_threshold = d;
+ }
+}
+
+void PMIsoSurface::setAccuracy( double d )
+{
+ if( d != m_accuracy )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, AccuracyID, m_accuracy );
+ m_accuracy = d;
+ }
+}
+
+void PMIsoSurface::setMaxGradient( double d )
+{
+ if( d != m_maxGradient )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, MaxGradientID, m_maxGradient );
+ m_maxGradient = d;
+ }
+}
+void PMIsoSurface::setEvaluate( bool yes )
+{
+ if( yes != m_bEvaluate )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, EvaluateID, m_evaluate );
+ m_bEvaluate = yes;
+ }
+}
+
+void PMIsoSurface::setEvaluateValue( int index, double v )
+{
+ if( index < 0 || index > 2 )
+ {
+ kdError( PMArea ) << "Illegal index in PMIsoSurface::setEvaluateValue" << endl;
+ return;
+ }
+
+ if( v != m_evaluate[index] )
+ {
+ if( m_pMemento )
+ {
+ int id = Evaluate0ID;
+ switch( index )
+ {
+ case 0: id = Evaluate0ID; break;
+ case 1: id = Evaluate1ID; break;
+ case 2: id = Evaluate2ID; break;
+ default: break;
+ }
+
+ m_pMemento->addData( s_pMetaObject, id, m_evaluate[index] );
+ }
+ m_evaluate[index] = v;
+ }
+}
+
+void PMIsoSurface::setOpen( bool yes )
+{
+ if( yes != m_bOpen )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, OpenID, m_bOpen );
+ m_bOpen = yes;
+ }
+}
+
+void PMIsoSurface::setMaxTrace( int i )
+{
+ if( i != m_maxTrace )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, MaxTraceID, m_maxTrace );
+ m_maxTrace = i;
+ }
+}
+
+void PMIsoSurface::setAllIntersections( bool yes )
+{
+ if( yes != m_bAllIntersections )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, AllIntersectionsID, m_bAllIntersections );
+ m_bAllIntersections = yes;
+ }
+}
+
+PMDialogEditBase* PMIsoSurface::editWidget( QWidget* parent ) const
+{
+ return new PMIsoSurfaceEdit( parent );
+}
+
+void PMIsoSurface::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case FunctionID:
+ setFunction( data->stringData( ) );
+ break;
+ case ContainedByID:
+ setContainedBy( ( ContainedByType ) data->intData( ) );
+ break;
+ case Corner1ID:
+ setCorner1( data->vectorData( ) );
+ break;
+ case Corner2ID:
+ setCorner2( data->vectorData( ) );
+ break;
+ case CenterID:
+ setCenter( data->vectorData( ) );
+ break;
+ case RadiusID:
+ setRadius( data->doubleData( ) );
+ break;
+ case ThresholdID:
+ setThreshold( data->doubleData( ) );
+ break;
+ case AccuracyID:
+ setAccuracy( data->doubleData( ) );
+ break;
+ case MaxGradientID:
+ setMaxGradient( data->doubleData( ) );
+ break;
+ case EvaluateID:
+ setEvaluate( data->boolData( ) );
+ break;
+ case Evaluate0ID:
+ setEvaluateValue( 0, data->doubleData( ) );
+ break;
+ case Evaluate1ID:
+ setEvaluateValue( 1, data->doubleData( ) );
+ break;
+ case Evaluate2ID:
+ setEvaluateValue( 2, data->doubleData( ) );
+ break;
+ case OpenID:
+ setOpen( data->boolData( ) );
+ break;
+ case MaxTraceID:
+ setMaxTrace( data->intData( ) );
+ break;
+ case AllIntersectionsID:
+ setAllIntersections( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMIsoSurface::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+
+void PMIsoSurface::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmisosurface.h b/kpovmodeler/pmisosurface.h
new file mode 100644
index 00000000..0646aff3
--- /dev/null
+++ b/kpovmodeler/pmisosurface.h
@@ -0,0 +1,234 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMISOSURFACE_H
+#define PMISOSURFACE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray boxes.
+ */
+
+class PMIsoSurface : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Enum for the "contained_by" statement
+ */
+ enum ContainedByType { Box, Sphere };
+ /**
+ * Creates an empty PMIsoSurface
+ */
+ PMIsoSurface( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMIsoSurface( const PMIsoSurface& b );
+ /**
+ * deletes the PMIsoSurface
+ */
+ virtual ~PMIsoSurface( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMIsoSurface( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMIsoSurfaceEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmisosurface" ); }
+
+
+ /**
+ * Sets the isosurface function
+ */
+ void setFunction( const QString& f );
+ /**
+ * Returns the isosurface function
+ */
+ QString function( ) const { return m_function; }
+ /**
+ * Sets the type of the contained_by object
+ */
+ void setContainedBy( ContainedByType type );
+ /**
+ * Returns the type of the contained_by object
+ */
+ ContainedByType containedBy( ) const { return m_containedBy; }
+ /**
+ * Sets the first corner of a contained_by box
+ */
+ void setCorner1( const PMVector& v );
+ /**
+ * Returns the first corner of a contained_by box
+ */
+ PMVector corner1( ) const { return m_corner1; }
+ /**
+ * Sets the second corner of a contained_by box
+ */
+ void setCorner2( const PMVector& v );
+ /**
+ * Returns the second corner of a contained_by box
+ */
+ PMVector corner2( ) const { return m_corner2; }
+ /**
+ * Sets the center of a contained_by sphere
+ */
+ void setCenter( const PMVector& v );
+ /**
+ * Returns the center of a contained_by sphere
+ */
+ PMVector center( ) const { return m_center; }
+ /**
+ * Sets the radius of a contained_by sphere
+ */
+ void setRadius( double r );
+ /**
+ * Returns the radius of a contained_by sphere
+ */
+ double radius( ) const { return m_radius; }
+ /**
+ * Sets the threshold
+ */
+ void setThreshold( double d );
+ /**
+ * Returns the Threshold
+ */
+ double threshold( ) const { return m_threshold; }
+ /**
+ * Sets the accuracy
+ */
+ void setAccuracy( double d );
+ /**
+ * Returns the accuracy
+ */
+ double accuracy( ) const { return m_accuracy; }
+ /**
+ * Sets the maximal gradient
+ */
+ void setMaxGradient( double d );
+ /**
+ * Returns the maximal Gradient
+ */
+ double maxGradient( ) const { return m_maxGradient; }
+ /**
+ * Enables/disables the evaluate statement
+ */
+ void setEvaluate( bool yes );
+ /**
+ * Returns the evaluate flag
+ */
+ bool evaluate( ) const { return m_bEvaluate; }
+ /**
+ * Sets the i-th evaluate value, index is in [0..2]
+ */
+ void setEvaluateValue( int index, double v );
+ /**
+ * Returns the i-th evaluate value
+ */
+ double evaluateValue( int index ) const { return m_evaluate[index]; }
+ /**
+ * Sets the open flag
+ */
+ void setOpen( bool yes );
+ /**
+ * Returns the open flag
+ */
+ bool open( ) const { return m_bOpen; }
+ /**
+ * Sets the maximal number of intersections
+ */
+ void setMaxTrace( int i );
+ /**
+ * Returns the maximal number of intersections
+ */
+ int maxTrace( ) const { return m_maxTrace; }
+ /**
+ * Sets the all intersections flag
+ */
+ void setAllIntersections( bool yes );
+ /**
+ * Returns the all intersections flag
+ */
+ bool allIntersections( ) const { return m_bAllIntersections; }
+
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ //virtual bool isDefault( );
+ /** */
+ //virtual void createViewStructure( );
+ /** */
+ //virtual PMViewStructure* defaultViewStructure( ) const;
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMIsoSurfaceMementoID { FunctionID, ContainedByID, Corner1ID, Corner2ID,
+ CenterID, RadiusID, ThresholdID, AccuracyID,
+ MaxGradientID, EvaluateID,
+ Evaluate0ID, Evaluate1ID, Evaluate2ID,
+ OpenID, MaxTraceID, AllIntersectionsID };
+
+ QString m_function;
+ ContainedByType m_containedBy;
+ PMVector m_corner1, m_corner2, m_center;
+ double m_radius, m_threshold, m_accuracy, m_maxGradient;
+ bool m_bEvaluate;
+ double m_evaluate[3];
+ bool m_bOpen;
+ int m_maxTrace;
+ bool m_bAllIntersections;
+
+ /**
+ * The default view structure. It can be shared between boxes
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmisosurfaceedit.cpp b/kpovmodeler/pmisosurfaceedit.cpp
new file mode 100644
index 00000000..b4eb0216
--- /dev/null
+++ b/kpovmodeler/pmisosurfaceedit.cpp
@@ -0,0 +1,326 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmisosurfaceedit.h"
+#include "pmisosurface.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+PMIsoSurfaceEdit::PMIsoSurfaceEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMIsoSurfaceEdit::createTopWidgets( )
+{
+ int i;
+ QGridLayout* gl;
+ QHBoxLayout* hl;
+
+ Base::createTopWidgets( );
+
+ m_pFunction = new QLineEdit( this );
+ m_pContainedBy = new QComboBox( false, this );
+ m_pContainedBy->insertItem( i18n( "Box" ) );
+ m_pContainedBy->insertItem( i18n( "Sphere" ) );
+
+ m_pCorner1 = new PMVectorEdit( "x", "y", "z", this );
+ m_pCorner2 = new PMVectorEdit( "x", "y", "z", this );
+ m_pCenter = new PMVectorEdit( "x", "y", "z", this );
+ m_pRadius = new PMFloatEdit( this );
+ m_pCorner1Label = new QLabel( i18n( "Corner1:" ), this );
+ m_pCorner2Label = new QLabel( i18n( "Corner2:" ), this );
+ m_pCenterLabel = new QLabel( i18n( "Center:" ), this );
+ m_pRadiusLabel = new QLabel( i18n( "Radius:" ), this );
+
+ m_pThreshold = new PMFloatEdit( this );
+ m_pAccuracy = new PMFloatEdit( this );
+ m_pAccuracy->setValidation( true, 1e-8, false, 0 );
+ m_pMaxGradient = new PMFloatEdit( this );
+ m_pMaxGradient->setValidation( true, 1e-8, false, 0 );
+ m_pEvaluate = new QCheckBox( i18n( "Adapt maximum gradient" ), this );
+ for( i = 0; i < 3; i++ )
+ m_pEvaluateValue[i] = new PMFloatEdit( this );
+ m_pMaxTrace = new PMIntEdit( this );
+ m_pMaxTrace->setValidation( true, 1, false, 0 );
+ m_pAllIntersections = new QCheckBox( i18n( "All intersections" ), this );
+ m_pOpen = new QCheckBox( i18n( "type of the object", "Open" ), this );
+
+ gl = new QGridLayout( topLayout( ), 8, 2 );
+ gl->addWidget( new QLabel( i18n( "Function:" ), this ), 0, 0 );
+ gl->addWidget( m_pFunction, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Container:" ), this ), 1, 0 );
+ gl->addWidget( m_pContainedBy, 1, 1 );
+ gl->addWidget( m_pCorner1Label, 2, 0 );
+ gl->addWidget( m_pCorner1, 2, 1 );
+ gl->addWidget( m_pCorner2Label, 3, 0 );
+ gl->addWidget( m_pCorner2, 3, 1 );
+ gl->addWidget( m_pCenterLabel, 4, 0 );
+ gl->addWidget( m_pCenter, 4, 1 );
+ gl->addWidget( m_pRadiusLabel, 5, 0 );
+ gl->addWidget( m_pRadius, 5, 1 );
+ gl->addWidget( new QLabel( i18n( "Threshold:" ), this ), 6, 0 );
+ gl->addWidget( m_pThreshold, 6, 1 );
+ gl->addWidget( new QLabel( i18n( "Accuracy:" ), this ), 7, 0 );
+ gl->addWidget( m_pAccuracy, 7, 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Maximum gradient:" ), this ) );
+ hl->addWidget( m_pMaxGradient );
+
+ topLayout( )->addWidget( m_pEvaluate );
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Values:" ), this ) );
+ for( i = 0; i < 3; i++ )
+ {
+ hl->addWidget( new QLabel( QString( "P%1" ).arg( i ), this ) );
+ hl->addWidget( m_pEvaluateValue[i] );
+ }
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Maximum traces:" ), this ) );
+ hl->addWidget( m_pMaxTrace );
+ topLayout( )->addWidget( m_pAllIntersections );
+ topLayout( )->addWidget( m_pOpen );
+
+ connect( m_pFunction, SIGNAL( textChanged( const QString& ) ),
+ SLOT( textChanged( const QString& ) ) );
+ connect( m_pContainedBy, SIGNAL( activated( int ) ),
+ SLOT( currentChanged( int ) ) );
+ connect( m_pCorner1, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCorner2, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCenter, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pThreshold, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAccuracy, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMaxGradient, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEvaluate, SIGNAL( toggled( bool ) ),
+ SLOT( evaluateToggled( bool ) ) );
+ connect( m_pMaxTrace, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ for( i = 0; i < 3; i++ )
+ connect( m_pEvaluateValue[i], SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOpen, SIGNAL( toggled( bool ) ), SLOT( toggled( bool ) ) );
+ connect( m_pAllIntersections, SIGNAL( toggled( bool ) ),
+ SLOT( allToggled( bool ) ) );
+}
+
+void PMIsoSurfaceEdit::displayObject( PMObject* o )
+{
+ int i;
+
+ if( o->isA( "IsoSurface" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMIsoSurface* ) o;
+
+ m_pFunction->setText( m_pDisplayedObject->function( ) );
+ if( m_pDisplayedObject->containedBy( ) == PMIsoSurface::Box )
+ {
+ m_pContainedBy->setCurrentItem( 0 );
+ m_pCorner1Label->show( );
+ m_pCorner2Label->show( );
+ m_pCorner1->show( );
+ m_pCorner2->show( );
+ m_pCenterLabel->hide( );
+ m_pCenter->hide( );
+ m_pRadiusLabel->hide( );
+ m_pRadius->hide( );
+ }
+ else
+ {
+ m_pContainedBy->setCurrentItem( 1 );
+ m_pCorner1Label->hide( );
+ m_pCorner2Label->hide( );
+ m_pCorner1->hide( );
+ m_pCorner2->hide( );
+ m_pCenterLabel->show( );
+ m_pCenter->show( );
+ m_pRadiusLabel->show( );
+ m_pRadius->show( );
+ }
+
+ m_pCorner1->setVector( m_pDisplayedObject->corner1( ) );
+ m_pCorner2->setVector( m_pDisplayedObject->corner2( ) );
+ m_pCenter->setVector( m_pDisplayedObject->center( ) );
+ m_pRadius->setValue( m_pDisplayedObject->radius( ) );
+ m_pThreshold->setValue( m_pDisplayedObject->threshold( ) );
+ m_pAccuracy->setValue( m_pDisplayedObject->accuracy( ) );
+ m_pMaxGradient->setValue( m_pDisplayedObject->maxGradient( ) );
+ bool ev = m_pDisplayedObject->evaluate( );
+ m_pEvaluate->setChecked( ev );
+
+ for( i = 0; i < 3; i++ )
+ {
+ m_pEvaluateValue[i]->setValue( m_pDisplayedObject->evaluateValue( i ) );
+ m_pEvaluateValue[i]->setEnabled( ev );
+ }
+
+ m_pOpen->setChecked( m_pDisplayedObject->open( ) );
+ m_pMaxTrace->setValue( m_pDisplayedObject->maxTrace( ) );
+ bool all = m_pDisplayedObject->allIntersections( );
+ m_pAllIntersections->setChecked( all );
+ m_pMaxTrace->setEnabled( !all );
+
+ m_pFunction->setReadOnly( readOnly );
+ m_pContainedBy->setEnabled( !readOnly );
+ m_pCorner1->setReadOnly( readOnly );
+ m_pCorner2->setReadOnly( readOnly );
+ m_pCenter->setReadOnly( readOnly );
+ m_pRadius->setReadOnly( readOnly );
+ m_pThreshold->setReadOnly( readOnly );
+ m_pAccuracy->setReadOnly( readOnly );
+ m_pMaxGradient->setReadOnly( readOnly );
+ m_pEvaluate->setEnabled( !readOnly );
+ for( i = 0; i < 3; i++ )
+ m_pEvaluateValue[i]->setReadOnly( readOnly );
+ m_pOpen->setEnabled( !readOnly );
+ m_pMaxTrace->setReadOnly( readOnly );
+ m_pAllIntersections->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMIsoSurfaceEdit: Can't display object\n";
+}
+
+void PMIsoSurfaceEdit::saveContents( )
+{
+ int i;
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setFunction( m_pFunction->text( ) );
+ if( m_pContainedBy->currentItem( ) == 0 )
+ {
+ m_pDisplayedObject->setContainedBy( PMIsoSurface::Box );
+ m_pDisplayedObject->setCorner1( m_pCorner1->vector( ) );
+ m_pDisplayedObject->setCorner2( m_pCorner2->vector( ) );
+ }
+ else
+ {
+ m_pDisplayedObject->setContainedBy( PMIsoSurface::Sphere );
+ m_pDisplayedObject->setCenter( m_pCenter->vector( ) );
+ m_pDisplayedObject->setRadius( m_pRadius->value( ) );
+ }
+ m_pDisplayedObject->setThreshold( m_pThreshold->value( ) );
+ m_pDisplayedObject->setAccuracy( m_pAccuracy->value( ) );
+ m_pDisplayedObject->setMaxGradient( m_pMaxGradient->value( ) );
+ m_pDisplayedObject->setEvaluate( m_pEvaluate->isChecked( ) );
+ if( m_pEvaluate->isChecked( ) )
+ for( i = 0; i < 3; i++ )
+ m_pDisplayedObject->setEvaluateValue( i, m_pEvaluateValue[i]->value( ) );
+ m_pDisplayedObject->setOpen( m_pOpen->isChecked( ) );
+ m_pDisplayedObject->setAllIntersections( m_pAllIntersections->isChecked( ) );
+ if( !m_pAllIntersections->isChecked( ) )
+ m_pDisplayedObject->setMaxTrace( m_pMaxTrace->value( ) );
+ }
+}
+
+bool PMIsoSurfaceEdit::isDataValid( )
+{
+ int i;
+
+ if( m_pContainedBy->currentItem( ) == 0 )
+ {
+ if( !m_pCorner1->isDataValid( ) )
+ return false;
+ if( !m_pCorner2->isDataValid( ) )
+ return false;
+ }
+ else
+ {
+ if( !m_pCenter->isDataValid( ) )
+ return false;
+ if( !m_pRadius->isDataValid( ) )
+ return false;
+ }
+ if( !m_pThreshold->isDataValid( ) )
+ return false;
+ if( !m_pAccuracy->isDataValid( ) )
+ return false;
+ if( !m_pMaxGradient->isDataValid( ) )
+ return false;
+ if( m_pEvaluate->isChecked( ) )
+ for( i = 0; i < 3; i++ )
+ if( !m_pEvaluateValue[i]->isDataValid( ) )
+ return false;
+ if( !m_pAllIntersections->isChecked( ) && !m_pMaxTrace->isDataValid( ) )
+ return false;
+ return Base::isDataValid( );
+}
+
+void PMIsoSurfaceEdit::textChanged( const QString& )
+{
+ emit dataChanged( );
+}
+
+void PMIsoSurfaceEdit::currentChanged( int i )
+{
+ if( i == 0 )
+ {
+ m_pCorner1Label->show( );
+ m_pCorner2Label->show( );
+ m_pCorner1->show( );
+ m_pCorner2->show( );
+ m_pCenterLabel->hide( );
+ m_pCenter->hide( );
+ m_pRadiusLabel->hide( );
+ m_pRadius->hide( );
+ }
+ else
+ {
+ m_pCorner1Label->hide( );
+ m_pCorner2Label->hide( );
+ m_pCorner1->hide( );
+ m_pCorner2->hide( );
+ m_pCenterLabel->show( );
+ m_pCenter->show( );
+ m_pRadiusLabel->show( );
+ m_pRadius->show( );
+ }
+ emit dataChanged( );
+}
+
+void PMIsoSurfaceEdit::evaluateToggled( bool yes )
+{
+ int i;
+ for( i = 0; i < 3; i++ )
+ m_pEvaluateValue[i]->setEnabled( yes );
+ emit dataChanged( );
+}
+
+void PMIsoSurfaceEdit::allToggled( bool yes )
+{
+ m_pMaxTrace->setEnabled( !yes );
+ emit dataChanged( );
+}
+
+void PMIsoSurfaceEdit::toggled( bool )
+{
+ emit dataChanged( );
+}
+
+#include "pmisosurfaceedit.moc"
diff --git a/kpovmodeler/pmisosurfaceedit.h b/kpovmodeler/pmisosurfaceedit.h
new file mode 100644
index 00000000..9ee6e872
--- /dev/null
+++ b/kpovmodeler/pmisosurfaceedit.h
@@ -0,0 +1,92 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMISOSURFACEEDIT_H
+#define PMISOSURFACEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMIsoSurface;
+class PMVectorEdit;
+class PMFloatEdit;
+class PMIntEdit;
+class QCheckBox;
+class QComboBox;
+class QLabel;
+class QLineEdit;
+
+/**
+ * Dialog edit class for @ref PMIsoSurface
+ */
+class PMIsoSurfaceEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMIsoSurfaceEdit with parent and name
+ */
+ PMIsoSurfaceEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private slots:
+ void textChanged( const QString& );
+ void currentChanged( int i );
+ void evaluateToggled( bool );
+ void allToggled( bool );
+ void toggled( bool );
+
+private:
+ PMIsoSurface* m_pDisplayedObject;
+ QLineEdit* m_pFunction;
+ QComboBox* m_pContainedBy;
+ PMVectorEdit* m_pCorner1;
+ PMVectorEdit* m_pCorner2;
+ PMVectorEdit* m_pCenter;
+ PMFloatEdit* m_pRadius;
+ QLabel* m_pCorner1Label;
+ QLabel* m_pCorner2Label;
+ QLabel* m_pCenterLabel;
+ QLabel* m_pRadiusLabel;
+ PMFloatEdit* m_pThreshold;
+ PMFloatEdit* m_pAccuracy;
+ PMFloatEdit* m_pMaxGradient;
+ QCheckBox* m_pEvaluate;
+ PMFloatEdit* m_pEvaluateValue[3];
+ QCheckBox* m_pOpen;
+ PMIntEdit* m_pMaxTrace;
+ QCheckBox* m_pAllIntersections;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmjuliafractal.cpp b/kpovmodeler/pmjuliafractal.cpp
new file mode 100644
index 00000000..49ca9de5
--- /dev/null
+++ b/kpovmodeler/pmjuliafractal.cpp
@@ -0,0 +1,449 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmjuliafractal.h"
+
+#include "pmxmlhelper.h"
+#include "pmjuliafractaledit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm3dcontrolpoint.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+const PMVector c_defaultJuliaParameter = PMVector( -0.083, 0.0, -0.83, -0.025 );
+const PMVector c_defaultSliceNormal = PMVector( 0.0, 0.0, 0.0, 1.0 );
+const double c_defaultSliceDistance = 0.0;
+const int c_defaultMaxIterations = 20;
+const PMJuliaFractal::AlgebraType c_defaultAlgebraType = PMJuliaFractal::Quaternion;
+const QString c_defaultAlgebraString = "quaternion";
+const PMJuliaFractal::FunctionType c_defaultFunctionType = PMJuliaFractal::FTsqr;
+const QString c_defaultFunctionString = "sqr";
+const PMVector c_defaultExponent = PMVector( 0.0, 0.0 );
+const double c_defaultPrecision = 20.0;
+
+
+PMDefinePropertyClass( PMJuliaFractal, PMJuliaFractalProperty );
+PMDefineEnumPropertyClass( PMJuliaFractal, PMJuliaFractal::AlgebraType,
+ PMAlgebraTypeProperty );
+PMDefineEnumPropertyClass( PMJuliaFractal, PMJuliaFractal::FunctionType,
+ PMFunctionTypeProperty );
+
+PMMetaObject* PMJuliaFractal::s_pMetaObject = 0;
+PMObject* createNewJuliaFractal( PMPart* part )
+{
+ return new PMJuliaFractal( part );
+}
+
+PMJuliaFractal::PMJuliaFractal( PMPart* part )
+ : Base( part )
+{
+ m_juliaParameter = c_defaultJuliaParameter;
+ m_algebraType = c_defaultAlgebraType;
+ m_functionType = c_defaultFunctionType;
+ m_maxIterations = c_defaultMaxIterations;
+ m_precision = c_defaultPrecision;
+ m_sliceNormal = c_defaultSliceNormal;
+ m_sliceDistance = c_defaultSliceDistance;
+ m_exponent = c_defaultExponent;
+}
+
+PMJuliaFractal::PMJuliaFractal( const PMJuliaFractal& f )
+ : Base( f )
+{
+ m_juliaParameter = f.m_juliaParameter;
+ m_algebraType = f.m_algebraType;
+ m_functionType = f.m_functionType;
+ m_maxIterations = f.m_maxIterations;
+ m_precision = f.m_precision;
+ m_sliceNormal = f.m_sliceNormal;
+ m_sliceDistance = f.m_sliceDistance;
+ m_exponent = f.m_exponent;
+}
+
+PMJuliaFractal::~PMJuliaFractal( )
+{
+}
+
+QString PMJuliaFractal::description( ) const
+{
+ return i18n( "julia fractal" );
+}
+
+void PMJuliaFractal::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "julia_parameter", m_juliaParameter.serializeXML( ) );
+ e.setAttribute( "algebra_type", algebraTypeToString( m_algebraType ) );
+ e.setAttribute( "function_type", functionTypeToString( m_functionType ) );
+ e.setAttribute( "max_iterations", m_maxIterations );
+ e.setAttribute( "precision", m_precision );
+ e.setAttribute( "slice_normal", m_sliceNormal.serializeXML( ) );
+ e.setAttribute( "slice_distance", m_sliceDistance );
+ e.setAttribute( "exponent", m_exponent.serializeXML( ) );
+ Base::serialize( e, doc );
+}
+
+void PMJuliaFractal::readAttributes( const PMXMLHelper& h )
+{
+ m_juliaParameter = h.vectorAttribute( "julia_parameter", c_defaultJuliaParameter );
+ m_algebraType = stringToAlgebraType( h.stringAttribute( "algebra_type", c_defaultAlgebraString ) );
+ m_functionType = stringToFunctionType( h.stringAttribute( "function_type", c_defaultFunctionString ) );
+ m_maxIterations = h.intAttribute( "max_iterations", c_defaultMaxIterations );
+ m_precision = h.doubleAttribute( "precision", c_defaultPrecision );
+ m_sliceNormal = h.vectorAttribute( "slice_normal", c_defaultSliceNormal );
+ m_sliceDistance = h.doubleAttribute( "slice_distance", c_defaultSliceDistance );
+ m_exponent = h.vectorAttribute( "exponent", c_defaultExponent );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMJuliaFractal::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "JuliaFractal", Base::metaObject( ),
+ createNewJuliaFractal );
+ s_pMetaObject->addProperty(
+ new PMJuliaFractalProperty( "juliaParameter", &PMJuliaFractal::setJuliaParameter,
+ &PMJuliaFractal::juliaParameter ) );
+ s_pMetaObject->addProperty(
+ new PMJuliaFractalProperty( "maximumIterations", &PMJuliaFractal::setMaximumIterations,
+ &PMJuliaFractal::maximumIterations ) );
+ s_pMetaObject->addProperty(
+ new PMJuliaFractalProperty( "precision", &PMJuliaFractal::setPrecision,
+ &PMJuliaFractal::precision ) );
+ s_pMetaObject->addProperty(
+ new PMJuliaFractalProperty( "sliceNormal", &PMJuliaFractal::setSliceNormal,
+ &PMJuliaFractal::sliceNormal ) );
+ s_pMetaObject->addProperty(
+ new PMJuliaFractalProperty( "sliceDistance", &PMJuliaFractal::setSliceDistance,
+ &PMJuliaFractal::sliceDistance ) );
+ s_pMetaObject->addProperty(
+ new PMJuliaFractalProperty( "exponent", &PMJuliaFractal::setExponent,
+ &PMJuliaFractal::exponent ) );
+
+ PMAlgebraTypeProperty* ap = new PMAlgebraTypeProperty(
+ "algebraType", &PMJuliaFractal::setAlgebraType, &PMJuliaFractal::algebraType );
+ ap->addEnumValue( "Quaternion", Quaternion );
+ ap->addEnumValue( "Hypercomplex", Hypercomplex );
+ s_pMetaObject->addProperty( ap );
+
+ PMFunctionTypeProperty* fp = new PMFunctionTypeProperty(
+ "functionType", &PMJuliaFractal::setFunctionType, &PMJuliaFractal::functionType );
+ fp->addEnumValue( "sqr", FTsqr );
+ fp->addEnumValue( "cube", FTcube );
+ fp->addEnumValue( "exp", FTexp );
+ fp->addEnumValue( "reciprocal", FTreciprocal );
+ fp->addEnumValue( "sin", FTsin );
+ fp->addEnumValue( "asin", FTasin );
+ fp->addEnumValue( "sinh", FTsinh );
+ fp->addEnumValue( "asinh", FTasinh );
+ fp->addEnumValue( "cos", FTcos );
+ fp->addEnumValue( "acos", FTacos );
+ fp->addEnumValue( "cosh", FTcosh );
+ fp->addEnumValue( "acosh", FTacosh );
+ fp->addEnumValue( "tan", FTtan );
+ fp->addEnumValue( "atan", FTatan );
+ fp->addEnumValue( "tanh", FTtanh );
+ fp->addEnumValue( "atanh", FTatanh );
+ fp->addEnumValue( "log", FTlog );
+ fp->addEnumValue( "pwr", FTpwr );
+ s_pMetaObject->addProperty( fp );
+ }
+ return s_pMetaObject;
+}
+
+void PMJuliaFractal::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMJuliaFractal::setJuliaParameter( const PMVector& p )
+{
+ if( p != m_juliaParameter )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMJuliaParameterID, m_juliaParameter );
+ m_juliaParameter = p;
+ m_juliaParameter.resize( 4 );
+ }
+}
+
+void PMJuliaFractal::setAlgebraType( PMJuliaFractal::AlgebraType t )
+{
+ if( m_algebraType != t )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAlgebraTypeID, m_algebraType );
+ m_algebraType = t;
+ }
+}
+
+void PMJuliaFractal::setFunctionType( PMJuliaFractal::FunctionType t )
+{
+ if( m_functionType != t )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFunctionTypeID, m_functionType );
+ m_functionType = t;
+ }
+}
+
+void PMJuliaFractal::setMaximumIterations( int max )
+{
+ if( max <= 0 )
+ {
+ kdError( PMArea ) << "max <= 0 in PMJuliaFractal::setMaximumIterations\n";
+ max = 20;
+ }
+ if( m_maxIterations != max )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMaxIterationsID, m_maxIterations );
+ m_maxIterations = max;
+ }
+}
+
+void PMJuliaFractal::setPrecision( double p )
+{
+ if( p < 1.0 )
+ {
+ kdError( PMArea ) << "p < 1.0 in PMJuliaFractal::setPrecision\n";
+ p = 1.0;
+ }
+
+ if( m_precision != p )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPrecisionID, m_precision );
+ m_precision = p;
+ }
+}
+
+void PMJuliaFractal::setSliceNormal( const PMVector& n )
+{
+ if( m_sliceNormal != n )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSliceNormalID, m_sliceNormal );
+ m_sliceNormal = n;
+ m_sliceNormal.resize( 4 );
+ }
+}
+
+void PMJuliaFractal::setSliceDistance( double d )
+{
+ if( m_sliceDistance != d )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSliceDistanceID, m_sliceDistance );
+ m_sliceDistance = d;
+ }
+}
+
+void PMJuliaFractal::setExponent( const PMVector& e )
+{
+ if( m_exponent != e )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMExponentID, m_exponent );
+ m_exponent = e;
+ m_exponent.resize( 2 );
+ }
+}
+
+PMDialogEditBase* PMJuliaFractal::editWidget( QWidget* parent ) const
+{
+ return new PMJuliaFractalEdit( parent );
+}
+
+void PMJuliaFractal::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMJuliaParameterID:
+ setJuliaParameter( data->vectorData( ) );
+ break;
+ case PMAlgebraTypeID:
+ setAlgebraType( ( AlgebraType ) data->intData( ) );
+ break;
+ case PMFunctionTypeID:
+ setFunctionType( ( FunctionType ) data->intData( ) );
+ break;
+ case PMMaxIterationsID:
+ setMaximumIterations( data->intData( ) );
+ break;
+ case PMPrecisionID:
+ setPrecision( data->doubleData( ) );
+ break;
+ case PMSliceNormalID:
+ setSliceNormal( data->vectorData( ) );
+ break;
+ case PMSliceDistanceID:
+ setSliceDistance( data->doubleData( ) );
+ break;
+ case PMExponentID:
+ setExponent( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMJuliaFractal::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+QString PMJuliaFractal::functionTypeToString( PMJuliaFractal::FunctionType t )
+{
+ QString result = "sqr";
+ switch( t )
+ {
+ case FTsqr:
+ result = "sqr";
+ break;
+ case FTcube:
+ result = "cube";
+ break;
+ case FTexp:
+ result = "exp";
+ break;
+ case FTreciprocal:
+ result = "reciprocal";
+ break;
+ case FTsin:
+ result = "sin";
+ break;
+ case FTasin:
+ result = "asin";
+ break;
+ case FTsinh:
+ result = "sinh";
+ break;
+ case FTasinh:
+ result = "asinh";
+ break;
+ case FTcos:
+ result = "cos";
+ break;
+ case FTacos:
+ result = "acos";
+ break;
+ case FTcosh:
+ result = "cosh";
+ break;
+ case FTacosh:
+ result = "acosh";
+ break;
+ case FTtan:
+ result = "tan";
+ break;
+ case FTatan:
+ result = "atan";
+ break;
+ case FTtanh:
+ result = "tanh";
+ break;
+ case FTatanh:
+ result = "atanh";
+ break;
+ case FTlog:
+ result = "log";
+ break;
+ case FTpwr:
+ result = "pwr";
+ break;
+ }
+ return result;
+}
+
+PMJuliaFractal::FunctionType PMJuliaFractal::stringToFunctionType( const QString& str )
+{
+ FunctionType t = c_defaultFunctionType;
+
+ if( str == "sqr" )
+ t = FTsqr;
+ else if( str == "cube" )
+ t = FTcube;
+ else if( str == "exp" )
+ t = FTexp;
+ else if( str == "reciprocal" )
+ t = FTreciprocal;
+ else if( str == "sin" )
+ t = FTsin;
+ else if( str == "asin" )
+ t = FTasin;
+ else if( str == "sinh" )
+ t = FTsinh;
+ else if( str == "asinh" )
+ t = FTasinh;
+ else if( str == "cos" )
+ t = FTcos;
+ else if( str == "acos" )
+ t = FTacos;
+ else if( str == "cosh" )
+ t = FTcosh;
+ else if( str == "acosh" )
+ t = FTacosh;
+ else if( str == "tan" )
+ t = FTtan;
+ else if( str == "atan" )
+ t = FTatan;
+ else if( str == "tanh" )
+ t = FTtanh;
+ else if( str == "atanh" )
+ t = FTatanh;
+ else if( str == "log" )
+ t = FTlog;
+ else if( str == "pwr" )
+ t = FTpwr;
+ return t;
+}
+
+QString PMJuliaFractal::algebraTypeToString( PMJuliaFractal::AlgebraType t )
+{
+ QString result;
+ if( t == Quaternion )
+ result = "quaternion";
+ else
+ result = "hypercomplex";
+ return result;
+}
+
+PMJuliaFractal::AlgebraType PMJuliaFractal::stringToAlgebraType( const QString& str )
+{
+ AlgebraType t = c_defaultAlgebraType;
+ if( str == "quaternion" )
+ t = Quaternion;
+ else if( str == "hypercomplex" )
+ t = Hypercomplex;
+ return t;
+}
diff --git a/kpovmodeler/pmjuliafractal.h b/kpovmodeler/pmjuliafractal.h
new file mode 100644
index 00000000..1e93a46c
--- /dev/null
+++ b/kpovmodeler/pmjuliafractal.h
@@ -0,0 +1,174 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMJULIAFRACTAL_H
+#define PMJULIAFRACTAL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray julia fractals.
+ */
+
+class PMJuliaFractal : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ enum AlgebraType { Quaternion, Hypercomplex };
+ enum FunctionType { FTsqr, FTcube, FTexp, FTreciprocal, FTsin, FTasin,
+ FTsinh, FTasinh, FTcos, FTacos, FTcosh, FTacosh,
+ FTtan, FTatan, FTtanh, FTatanh, FTlog, FTpwr };
+
+ /**
+ * Creates an empty PMJuliaFractal
+ */
+ PMJuliaFractal( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMJuliaFractal( const PMJuliaFractal& f );
+ /**
+ * deletes the PMJuliaFractal
+ */
+ virtual ~PMJuliaFractal( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMJuliaFractal( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMJuliaFractalEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmjuliafractal" ); }
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ /**
+ * Returns the 4d julia parameter vector
+ */
+ PMVector juliaParameter( ) const { return m_juliaParameter; }
+ /**
+ * Sets the julia parameter vector
+ */
+ void setJuliaParameter( const PMVector& p );
+ /**
+ * Returns the algebra type
+ */
+ AlgebraType algebraType( ) const { return m_algebraType; }
+ /**
+ * Sets the algebra type
+ */
+ void setAlgebraType( AlgebraType t );
+ /**
+ * Returns the function type
+ */
+ FunctionType functionType( ) const { return m_functionType; }
+ /**
+ * Sets the function type
+ */
+ void setFunctionType( FunctionType t );
+ /**
+ * Returns the maximum number of iterations
+ */
+ int maximumIterations( ) const { return m_maxIterations; }
+ /**
+ * Sets the maximum number of iterations
+ */
+ void setMaximumIterations( int m );
+ /**
+ * Returns the precision
+ */
+ double precision( ) const { return m_precision; }
+ /**
+ * Sets the precision
+ */
+ void setPrecision( double p );
+ /**
+ * Returns the slice normal (4D vector)
+ */
+ PMVector sliceNormal( ) const { return m_sliceNormal; }
+ /**
+ * Sets the slice normal (4D vector)
+ */
+ void setSliceNormal( const PMVector& v );
+ /**
+ * Returns the slice distance
+ */
+ double sliceDistance( ) const { return m_sliceDistance; }
+ /**
+ * Sets the slice distance
+ */
+ void setSliceDistance( double d );
+ /**
+ * Returns the exponent for the pow function type (2D vector)
+ */
+ PMVector exponent( ) const { return m_exponent; }
+ /**
+ * Sets the exponent for the pow function type (2D Vector)
+ */
+ void setExponent( const PMVector& p );
+
+ static QString functionTypeToString( FunctionType t );
+ static FunctionType stringToFunctionType( const QString& str );
+ static QString algebraTypeToString( AlgebraType t );
+ static AlgebraType stringToAlgebraType( const QString& str );
+private:
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMJuliaFractalMementoID { PMJuliaParameterID, PMAlgebraTypeID,
+ PMFunctionTypeID, PMMaxIterationsID,
+ PMPrecisionID, PMSliceNormalID,
+ PMSliceDistanceID, PMExponentID };
+ PMVector m_juliaParameter;
+ AlgebraType m_algebraType;
+ FunctionType m_functionType;
+ int m_maxIterations;
+ double m_precision;
+ PMVector m_sliceNormal;
+ double m_sliceDistance;
+ PMVector m_exponent;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmjuliafractaledit.cpp b/kpovmodeler/pmjuliafractaledit.cpp
new file mode 100644
index 00000000..43f351c5
--- /dev/null
+++ b/kpovmodeler/pmjuliafractaledit.cpp
@@ -0,0 +1,380 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmjuliafractaledit.h"
+#include "pmjuliafractal.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+PMJuliaFractalEdit::PMJuliaFractalEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMJuliaFractalEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl;
+ QGridLayout* gl;
+
+ topLayout( )->addWidget( new QLabel( i18n( "Julia parameter:" ), this ) );
+ m_pJuliaParameter = new PMVectorEdit( "", "i", "j", "k", this );
+ topLayout( )->addWidget( m_pJuliaParameter );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Algebra type:" ), this ) );
+ m_pAlgebraType = new QComboBox( false, this );
+ m_pAlgebraType->insertItem( i18n( "Quaternion" ) );
+ m_pAlgebraType->insertItem( i18n( "Hypercomplex" ) );
+ hl->addWidget( m_pAlgebraType );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Function type:" ), this ) );
+ m_pFunctionType = new QComboBox( false, this );
+ m_pFunctionType->insertItem( "sqr" );
+ m_pFunctionType->insertItem( "cube" );
+ m_pFunctionType->insertItem( "exp" );
+ m_pFunctionType->insertItem( "reciprocal" );
+ m_pFunctionType->insertItem( "sin" );
+ m_pFunctionType->insertItem( "asin" );
+ m_pFunctionType->insertItem( "sinh" );
+ m_pFunctionType->insertItem( "asinh" );
+ m_pFunctionType->insertItem( "cos" );
+ m_pFunctionType->insertItem( "acos" );
+ m_pFunctionType->insertItem( "cosh" );
+ m_pFunctionType->insertItem( "acosh" );
+ m_pFunctionType->insertItem( "tan" );
+ m_pFunctionType->insertItem( "atan" );
+ m_pFunctionType->insertItem( "tanh" );
+ m_pFunctionType->insertItem( "atanh" );
+ m_pFunctionType->insertItem( "log" );
+ m_pFunctionType->insertItem( "pwr" );
+ hl->addWidget( m_pFunctionType );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pExponentsLabel = new QLabel( i18n( "Exponent:" ), this );
+ hl->addWidget( m_pExponentsLabel );
+ m_pExponents = new PMVectorEdit( "", "i", this );
+ hl->addWidget( m_pExponents );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Maximum iterations:" ), this ), 0, 0 );
+ m_pMaxIterations = new PMIntEdit( this );
+ m_pMaxIterations->setValidation( true, 1, false, 0 );
+ gl->addWidget( m_pMaxIterations, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Precision:" ), this ), 1, 0 );
+ m_pPrecision = new PMFloatEdit( this );
+ m_pPrecision->setValidation( true, 1.0, false, 0.0 );
+ gl->addWidget( m_pPrecision, 1, 1 );
+ hl->addStretch( 1 );
+
+ topLayout( )->addWidget( new QLabel( i18n( "Slice normal:" ), this ) );
+ m_pSliceNormal = new PMVectorEdit( "", "i", "j", "k", this );
+ topLayout( )->addWidget( m_pSliceNormal );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Slice distance:" ), this ) );
+ m_pSliceDistance = new PMFloatEdit( this );
+ hl->addWidget( m_pSliceDistance );
+ hl->addStretch( 1 );
+
+ connect( m_pJuliaParameter, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAlgebraType, SIGNAL( activated( int ) ),
+ SLOT( slotAlgebraTypeSelected( int ) ) );
+ connect( m_pFunctionType, SIGNAL( activated( int ) ),
+ SLOT( slotFunctionTypeSelected( int ) ) );
+ connect( m_pExponents, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMaxIterations, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPrecision, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSliceNormal, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSliceDistance, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMJuliaFractalEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "JuliaFractal" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMJuliaFractal* ) o;
+
+ m_pJuliaParameter->setVector( m_pDisplayedObject->juliaParameter( ) );
+ switch( m_pDisplayedObject->algebraType( ) )
+ {
+ case PMJuliaFractal::Quaternion:
+ m_pAlgebraType->setCurrentItem( 0 );
+ break;
+ case PMJuliaFractal::Hypercomplex:
+ m_pAlgebraType->setCurrentItem( 1 );
+ break;
+ }
+ switch( m_pDisplayedObject->functionType( ) )
+ {
+ case PMJuliaFractal::FTsqr:
+ m_pFunctionType->setCurrentItem( 0 );
+ break;
+ case PMJuliaFractal::FTcube:
+ m_pFunctionType->setCurrentItem( 1 );
+ break;
+ case PMJuliaFractal::FTexp:
+ m_pFunctionType->setCurrentItem( 2 );
+ break;
+ case PMJuliaFractal::FTreciprocal:
+ m_pFunctionType->setCurrentItem( 3 );
+ break;
+ case PMJuliaFractal::FTsin:
+ m_pFunctionType->setCurrentItem( 4 );
+ break;
+ case PMJuliaFractal::FTasin:
+ m_pFunctionType->setCurrentItem( 5 );
+ break;
+ case PMJuliaFractal::FTsinh:
+ m_pFunctionType->setCurrentItem( 6 );
+ break;
+ case PMJuliaFractal::FTasinh:
+ m_pFunctionType->setCurrentItem( 7 );
+ break;
+ case PMJuliaFractal::FTcos:
+ m_pFunctionType->setCurrentItem( 8 );
+ break;
+ case PMJuliaFractal::FTacos:
+ m_pFunctionType->setCurrentItem( 9 );
+ break;
+ case PMJuliaFractal::FTcosh:
+ m_pFunctionType->setCurrentItem( 10 );
+ break;
+ case PMJuliaFractal::FTacosh:
+ m_pFunctionType->setCurrentItem( 11 );
+ break;
+ case PMJuliaFractal::FTtan:
+ m_pFunctionType->setCurrentItem( 12 );
+ break;
+ case PMJuliaFractal::FTatan:
+ m_pFunctionType->setCurrentItem( 13 );
+ break;
+ case PMJuliaFractal::FTtanh:
+ m_pFunctionType->setCurrentItem( 14 );
+ break;
+ case PMJuliaFractal::FTatanh:
+ m_pFunctionType->setCurrentItem( 15 );
+ break;
+ case PMJuliaFractal::FTlog:
+ m_pFunctionType->setCurrentItem( 16 );
+ break;
+ case PMJuliaFractal::FTpwr:
+ m_pFunctionType->setCurrentItem( 17 );
+ break;
+ }
+ m_pExponents->setVector( m_pDisplayedObject->exponent( ) );
+ if( m_pDisplayedObject->functionType( ) == PMJuliaFractal::FTpwr )
+ {
+ m_pExponents->show( );
+ m_pExponentsLabel->show( );
+ }
+ else
+ {
+ m_pExponents->hide( );
+ m_pExponentsLabel->hide( );
+ }
+
+ m_pMaxIterations->setValue( m_pDisplayedObject->maximumIterations( ) );
+ m_pPrecision->setValue( m_pDisplayedObject->precision( ) );
+ m_pSliceNormal->setVector( m_pDisplayedObject->sliceNormal( ) );
+ m_pSliceDistance->setValue( m_pDisplayedObject->sliceDistance( ) );
+
+ m_pJuliaParameter->setReadOnly( readOnly );
+ m_pAlgebraType->setEnabled( !readOnly );
+ m_pFunctionType->setEnabled( !readOnly );
+ m_pExponents->setReadOnly( readOnly );
+ m_pMaxIterations->setReadOnly( readOnly );
+ m_pPrecision->setReadOnly( readOnly );
+ m_pSliceNormal->setReadOnly( readOnly );
+ m_pSliceDistance->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMJuliaFractalEdit: Can't display object\n";
+}
+
+void PMJuliaFractalEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ PMVector p( 4 );
+
+ m_pDisplayedObject->setJuliaParameter( m_pJuliaParameter->vector( ) );
+ switch( m_pAlgebraType->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setAlgebraType( PMJuliaFractal::Quaternion );
+ break;
+ case 1:
+ m_pDisplayedObject->setAlgebraType( PMJuliaFractal::Hypercomplex );
+ break;
+ default:
+ m_pDisplayedObject->setAlgebraType( PMJuliaFractal::Quaternion );
+ break;
+ }
+ switch( m_pFunctionType->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTsqr );
+ break;
+ case 1:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTcube );
+ break;
+ case 2:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTexp );
+ break;
+ case 3:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTreciprocal );
+ break;
+ case 4:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTsin );
+ break;
+ case 5:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTasin );
+ break;
+ case 6:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTsinh );
+ break;
+ case 7:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTasinh );
+ break;
+ case 8:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTcos );
+ break;
+ case 9:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTacos );
+ break;
+ case 10:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTcosh );
+ break;
+ case 11:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTacosh );
+ break;
+ case 12:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTtan );
+ break;
+ case 13:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTatan );
+ break;
+ case 14:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTtanh );
+ break;
+ case 15:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTatanh );
+ break;
+ case 16:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTlog );
+ break;
+ case 17:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTpwr );
+ break;
+ default:
+ m_pDisplayedObject->setFunctionType( PMJuliaFractal::FTsqr );
+ break;
+ }
+ if( m_pExponents->isVisible( ) )
+ m_pDisplayedObject->setExponent( m_pExponents->vector( ) );
+ m_pDisplayedObject->setMaximumIterations( m_pMaxIterations->value( ) );
+ m_pDisplayedObject->setPrecision( m_pPrecision->value( ) );
+ m_pDisplayedObject->setSliceNormal( m_pSliceNormal->vector( ) );
+ m_pDisplayedObject->setSliceDistance( m_pSliceDistance->value( ) );
+ }
+}
+
+bool PMJuliaFractalEdit::isDataValid( )
+{
+ if( !m_pJuliaParameter->isDataValid( ) )
+ return false;
+ if( m_pExponents->isVisible( ) )
+ if( !m_pExponents->isDataValid( ) )
+ return false;
+ if( !m_pMaxIterations->isDataValid( ) )
+ return false;
+ if( !m_pPrecision->isDataValid( ) )
+ return false;
+ if( !m_pSliceNormal->isDataValid( ) )
+ return false;
+ PMVector v = m_pSliceNormal->vector( );
+ if( approxZero( v.abs( ) ) )
+ {
+ KMessageBox::error( this, i18n( "The slice normal vector may not be a null vector." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ if( approxZero( v[3] ) )
+ {
+ KMessageBox::error( this, i18n( "The 'k' component of the slice normal vector may not be zero." ),
+ i18n( "Error" ) );
+ return false;
+ }
+
+ if( !m_pSliceDistance->isDataValid( ) )
+ return false;
+
+ if( m_pAlgebraType->currentItem( ) == 0 )
+ {
+ if( m_pFunctionType->currentItem( ) > 1 )
+ {
+ KMessageBox::error( this, i18n( "Only the functions 'sqr' and 'cube' "
+ "are defined in the quaternion algebra." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ }
+
+
+ return Base::isDataValid( );
+}
+
+void PMJuliaFractalEdit::slotAlgebraTypeSelected( int )
+{
+ emit dataChanged( );
+}
+
+void PMJuliaFractalEdit::slotFunctionTypeSelected( int index )
+{
+ if( index == 17 )
+ {
+ m_pExponents->show( );
+ m_pExponentsLabel->show( );
+ }
+ else
+ {
+ m_pExponents->hide( );
+ m_pExponentsLabel->hide( );
+ }
+ emit dataChanged( );
+}
+
+#include "pmjuliafractaledit.moc"
diff --git a/kpovmodeler/pmjuliafractaledit.h b/kpovmodeler/pmjuliafractaledit.h
new file mode 100644
index 00000000..598ea144
--- /dev/null
+++ b/kpovmodeler/pmjuliafractaledit.h
@@ -0,0 +1,79 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMJULIAFRACTALEDIT_H
+#define PMJULIAFRACTALEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMJuliaFractal;
+class PMVectorEdit;
+class PMIntEdit;
+class PMFloatEdit;
+class QComboBox;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMJuliaFractal
+ */
+class PMJuliaFractalEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMJuliaFractalEdit with parent and name
+ */
+ PMJuliaFractalEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotAlgebraTypeSelected( int );
+ void slotFunctionTypeSelected( int );
+
+private:
+ PMJuliaFractal* m_pDisplayedObject;
+ PMVectorEdit* m_pJuliaParameter;
+ QComboBox* m_pAlgebraType;
+ QComboBox* m_pFunctionType;
+ PMVectorEdit* m_pExponents;
+ QLabel* m_pExponentsLabel;
+ PMIntEdit* m_pMaxIterations;
+ PMFloatEdit* m_pPrecision;
+ PMVectorEdit* m_pSliceNormal;
+ PMFloatEdit* m_pSliceDistance;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmlathe.cpp b/kpovmodeler/pmlathe.cpp
new file mode 100644
index 00000000..f6c3c3c3
--- /dev/null
+++ b/kpovmodeler/pmlathe.cpp
@@ -0,0 +1,948 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlathe.h"
+
+#include "pmxmlhelper.h"
+#include "pmlatheedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm2dcontrolpoint.h"
+#include "pmsplinememento.h"
+#include "pmsplinesegment.h"
+#include "pmdefaults.h"
+#include "pmenumproperty.h"
+#include "pmobjectaction.h"
+
+#include <klocale.h>
+
+const int defaultNumberOfPoints = 4;
+const PMVector defaultPoint[defaultNumberOfPoints] =
+{
+ PMVector( 0.0, 1.0 ),
+ PMVector( 0.5, 0.7 ),
+ PMVector( 0.5, 0.3 ),
+ PMVector( 0.0, 0.0 )
+};
+
+const bool defaultSturm = false;
+const PMLathe::SplineType defaultSplineType = PMLathe::LinearSpline;
+
+PMDefinePropertyClass( PMLathe, PMLatheProperty );
+PMDefineEnumPropertyClass( PMLathe, PMLathe::SplineType, PMSplineTypeProperty );
+
+PMMetaObject* PMLathe::s_pMetaObject = 0;
+PMObject* createNewLathe( PMPart* part )
+{
+ return new PMLathe( part );
+}
+
+class PMPointProperty : public PMPropertyBase
+{
+public:
+ PMPointProperty( )
+ : PMPropertyBase( "splinePoints", PMVariant::Vector )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ m_index = index;
+ }
+ virtual int size( PMObject* object, int /*dimension*/ ) const
+ {
+ return ( ( PMLathe* ) object )->numberOfPoints( );
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& var )
+ {
+ PMLathe* p = ( PMLathe* ) obj;
+ QValueList<PMVector> list = p->points( );
+ QValueList<PMVector>::Iterator it = list.begin( );
+ int i;
+ PMVector v = var.vectorData( );
+ v.resize( 2 );
+
+ for( i = 0; i < m_index && it != list.end( ); ++i )
+ ++it;
+ // expand the list if necessary
+ for( ; i < m_index; ++i )
+ list.insert( it, v );
+ if( it == list.end( ) )
+ it = list.insert( it, v );
+ else
+ *it = v;
+
+ p->setPoints( list );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ PMLathe* p = ( PMLathe* ) obj;
+ QValueList<PMVector> list = p->points( );
+ QValueList<PMVector>::ConstIterator it = list.at( m_index );
+
+ if( it == list.end( ) )
+ {
+ kdError( PMArea ) << "Range error in PMLathe::PointProperty::get" << endl;
+ return PMVariant( );
+ }
+
+ return PMVariant( *it );
+ }
+
+private:
+ int m_index;
+};
+
+
+int PMLathe::s_rSteps = c_defaultLatheRSteps;
+int PMLathe::s_sSteps = c_defaultLatheSSteps;
+int PMLathe::s_parameterKey = 0;
+
+PMLathe::PMLathe( PMPart* part )
+ : Base( part )
+{
+ int i;
+
+ for( i = 0; i < defaultNumberOfPoints; ++i )
+ m_points.append( defaultPoint[i] );
+ m_splineType = defaultSplineType;
+ m_sturm = defaultSturm;
+}
+
+PMLathe::PMLathe( const PMLathe& l )
+ : Base( l )
+{
+ m_points = l.m_points;
+ m_splineType = l.m_splineType;
+ m_sturm = l.m_sturm;
+}
+
+PMLathe::~PMLathe( )
+{
+}
+
+QString PMLathe::description( ) const
+{
+ return i18n( "lathe" );
+}
+
+void PMLathe::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ QDomElement data = doc.createElement( "extra_data" );
+ QDomElement p;
+
+ e.setAttribute( "spline_type", m_splineType );
+ e.setAttribute( "sturm", m_sturm );
+
+ QValueList<PMVector>::ConstIterator it;
+ for( it = m_points.begin( ); it != m_points.end( ); ++it )
+ {
+ p = doc.createElement( "point" );
+ p.setAttribute( "vector", ( *it ).serializeXML( ) );
+ data.appendChild( p );
+ }
+
+ e.appendChild( data );
+ Base::serialize( e, doc );
+}
+
+void PMLathe::readAttributes( const PMXMLHelper& h )
+{
+ m_splineType = ( SplineType ) h.intAttribute( "spline_type", defaultSplineType );
+ m_sturm = h.boolAttribute( "sturm", defaultSturm );
+
+ m_points.clear( );
+ PMVector v( 2 );
+
+ QDomElement e = h.extraData( );
+ if( !e.isNull( ) )
+ {
+ QDomNode c = e.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ if( ce.tagName( ) == "point" )
+ {
+ QString str = ce.attribute( "vector" );
+ if( !str.isNull( ) )
+ {
+ v.loadXML( str );
+ m_points.append( v );
+ }
+ }
+ }
+ c = c.nextSibling( );
+ }
+ }
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMLathe::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Lathe", Base::metaObject( ),
+ createNewLathe );
+ s_pMetaObject->addProperty(
+ new PMLatheProperty( "sturm", &PMLathe::setSturm, &PMLathe::sturm ) );
+ PMSplineTypeProperty* p = new PMSplineTypeProperty(
+ "splineType", &PMLathe::setSplineType, &PMLathe::splineType );
+ p->addEnumValue( "LinearSpline", LinearSpline );
+ p->addEnumValue( "QuadraticSpline", QuadraticSpline );
+ p->addEnumValue( "CubicSpline", CubicSpline );
+ p->addEnumValue( "BezierSpline", BezierSpline );
+ s_pMetaObject->addProperty( p );
+ s_pMetaObject->addProperty( new PMPointProperty( ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMLathe::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMLathe::setSplineType( PMLathe::SplineType t )
+{
+ if( m_splineType != t )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSplineTypeID, ( int ) m_splineType );
+ setViewStructureChanged( );
+ m_splineType = t;
+ }
+}
+
+void PMLathe::setSturm( bool s )
+{
+ if( m_sturm != s )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSturmID, m_sturm );
+ m_sturm = s;
+ }
+}
+
+void PMLathe::setPoints( const QValueList<PMVector>& points )
+{
+ if( m_points != points )
+ {
+ if( m_pMemento )
+ ( ( PMSplineMemento* ) m_pMemento )->setSplinePoints( m_points );
+
+ setViewStructureChanged( );
+ m_points = points;
+ }
+}
+
+PMDialogEditBase* PMLathe::editWidget( QWidget* parent ) const
+{
+ return new PMLatheEdit( parent );
+}
+
+void PMLathe::createMemento( )
+{
+ if( m_pMemento )
+ delete m_pMemento;
+ m_pMemento = new PMSplineMemento( this );
+}
+
+void PMLathe::restoreMemento( PMMemento* s )
+{
+ PMSplineMemento* m = ( PMSplineMemento* ) s;
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMSplineTypeID:
+ setSplineType( ( SplineType ) data->intData( ) );
+ break;
+ case PMSturmID:
+ setSturm( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMLathe::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ if( m->splinePointsSaved( ) )
+ setPoints( m->splinePoints( ) );
+
+ Base::restoreMemento( s );
+}
+
+
+void PMLathe::createViewStructure( )
+{
+ if( s_sSteps == 0 )
+ s_sSteps = c_defaultLatheSSteps;
+ if( s_rSteps == 0 )
+ s_rSteps = c_defaultLatheRSteps;
+
+ int rSteps = (int)( ( (float)s_rSteps / 2 ) * ( displayDetail( ) + 1 ) );
+ int sSteps = (int)( ( (float)s_sSteps / 2 ) * ( displayDetail( ) + 1 ) );
+
+ int np = m_points.count( );
+ int ns = 0;
+ int i, j, r, si;
+
+ // calculate number of segments
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ ns = np - 1;
+ break;
+ case QuadraticSpline:
+ ns = np - 2;
+ break;
+ case CubicSpline:
+ ns = np - 3;
+ break;
+ case BezierSpline:
+ ns = np / 4;
+ break;
+ }
+
+ // calculate number of points and lines of the view structure
+ int vsp = 0;
+ if( m_splineType != BezierSpline )
+ vsp = ns * sSteps + 1;
+ else
+ vsp = ns * ( sSteps + 1 );
+
+ int vsl = 0;
+ if( m_splineType != BezierSpline )
+ vsl = ( 2 * vsp - 1 ) * rSteps;
+ else
+ vsl = ns * ( ( 2 * sSteps + 1 ) * rSteps );
+
+ vsp *= rSteps;
+
+ if( m_pViewStructure )
+ {
+ if( m_pViewStructure->points( ).size( ) != ( unsigned ) vsp )
+ m_pViewStructure->points( ).resize( vsp );
+ if( m_pViewStructure->lines( ).size( ) != ( unsigned ) vsl )
+ m_pViewStructure->lines( ).resize( vsl );
+ }
+ else
+ m_pViewStructure = new PMViewStructure( vsp, vsl );
+
+
+ // calculate the spline segments
+ QValueList<PMSplineSegment> segments;
+ QValueList<PMVector>::Iterator it1, it2, it3, it4;
+ it1 = m_points.begin( );
+ it2 = it1; ++it2;
+ it3 = it2; ++it3;
+ it4 = it3; ++it4;
+ PMSplineSegment s;
+
+ for( i = 0; i < ns; ++i )
+ {
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ s.calculateLinear( *it1, *it2 );
+ ++it1;
+ ++it2;
+ break;
+ case QuadraticSpline:
+ s.calculateQuadratic( *it1, *it2, *it3 );
+ ++it1;
+ ++it2;
+ ++it3;
+ break;
+ case CubicSpline:
+ s.calculateCubic( *it1, *it2, *it3, *it4 );
+ ++it1;
+ ++it2;
+ ++it3;
+ ++it4;
+ break;
+ case BezierSpline:
+ s.calculateBezier( *it1, *it2, *it3, *it4 );
+ for( j = 0; j < 4; ++j )
+ {
+ ++it1;
+ ++it2;
+ ++it3;
+ ++it4;
+ }
+ break;
+ }
+ segments.append( s );
+ }
+
+ // create the line array
+ if( m_splineType != BezierSpline )
+ {
+ PMLineArray& lines = m_pViewStructure->lines( );
+ int vl = ns * sSteps;
+ int lb = 0;
+ for( i = 0; i < vl + 1; ++i )
+ {
+ for( j = 0; j < rSteps - 1; ++j )
+ lines[lb+j] = PMLine( lb + j, lb + j + 1 );
+ lines[lb+rSteps-1] = PMLine( lb, lb + rSteps - 1 );
+ lb += rSteps;
+ }
+ int pi = 0;
+ for( i = 0; i < vl; ++i )
+ {
+ for( j = 0; j < rSteps; ++j )
+ {
+ lines[lb] = PMLine( pi, pi + rSteps );
+ ++pi;
+ ++lb;
+ }
+ }
+ }
+ else
+ {
+ PMLineArray& lines = m_pViewStructure->lines( );
+ int lb = 0;
+ int pi = 0;
+
+ for( si = 0; si < ns; ++si )
+ {
+ for( i = 0; i < sSteps + 1; ++i )
+ {
+ for( j = 0; j < rSteps - 1; ++j )
+ lines[lb+j] = PMLine( lb + j, lb + j + 1 );
+ lines[lb+rSteps-1] = PMLine( lb, lb + rSteps - 1 );
+ lb += rSteps;
+ }
+ }
+ for( si = 0; si < ns; ++si )
+ {
+ for( i = 0; i < sSteps; ++i )
+ {
+ for( j = 0; j < rSteps; ++j )
+ {
+ lines[lb] = PMLine( pi, pi + rSteps );
+ ++pi;
+ ++lb;
+ }
+ }
+ pi += rSteps;
+ }
+ }
+ // calculate the points
+ PMVector point2, point3;
+ QValueList<PMSplineSegment>::Iterator sit = segments.begin( );
+ int pi = 0;
+
+ double poffset = 1.0 / sSteps;
+ PMMatrix rot = PMMatrix::rotation( 0.0, M_PI * 2.0 / rSteps, 0.0 );
+ PMPointArray& points = m_pViewStructure->points( );
+
+ if( m_splineType != BezierSpline )
+ {
+ for( i = 0; i < ns; ++i, ++sit )
+ {
+ for( j = 0; j < sSteps; ++j )
+ {
+ point2 = ( *sit ).point( poffset * j );
+ point3[0] = point2[0];
+ point3[1] = point2[1];
+ point3[2] = 0.0;
+
+ for( r = 0; r < rSteps; ++r )
+ {
+ points[pi] = PMPoint( point3 );
+ if( r != rSteps - 1 )
+ point3.transform( rot );
+ ++pi;
+ }
+ }
+ if( i == ns - 1 )
+ {
+ point2 = ( *sit ).point( 1.0 );
+ point3[0] = point2[0];
+ point3[1] = point2[1];
+ point3[2] = 0.0;
+
+ for( r = 0; r < rSteps; ++r )
+ {
+ points[pi] = PMPoint( point3 );
+ if( r != rSteps - 1 )
+ point3.transform( rot );
+ ++pi;
+ }
+ }
+ }
+ }
+ else
+ {
+ for( i = 0; i < ns; ++i, ++sit )
+ {
+ for( j = 0; j < sSteps + 1; ++j )
+ {
+ point2 = ( *sit ).point( poffset * j );
+ point3[0] = point2[0];
+ point3[1] = point2[1];
+ point3[2] = 0.0;
+
+ for( r = 0; r < rSteps; ++r )
+ {
+ points[pi] = PMPoint( point3 );
+ if( r != rSteps - 1 )
+ point3.transform( rot );
+ ++pi;
+ }
+ }
+ }
+ }
+}
+
+void PMLathe::controlPoints( PMControlPointList& list )
+{
+ QValueList<PMVector>::Iterator it;
+ int i, d;
+
+ PM2DControlPoint* cp = 0;
+ QPtrList<PM2DControlPoint> tmp[2];
+
+ for( d = 0; d < 2; ++d )
+ {
+ if( m_splineType != BezierSpline )
+ {
+ PM2DControlPoint* firstPoint = 0;
+ PM2DControlPoint* lastPoint = 0;
+
+ for( it = m_points.begin( ), i = 0; it != m_points.end( ); ++it, ++i )
+ {
+ lastPoint = cp;
+ if( d == 0 )
+ cp = new PM2DControlPoint( *it, PM2DControlPoint::PM2DXY, i,
+ i18n( "Point %1 (xy)" ).arg( i + 1 ) );
+ else
+ cp = new PM2DControlPoint( *it, PM2DControlPoint::PM2DZY, i,
+ i18n( "Point %1 (xy)" ).arg( i + 1 ) );
+
+ if( i == 0 )
+ firstPoint = cp;
+ if( ( i == 1 ) && ( m_splineType != LinearSpline ) )
+ firstPoint->setBasePoint( cp );
+
+ tmp[d].append( cp );
+ }
+ if( m_splineType == CubicSpline )
+ cp->setBasePoint( lastPoint );
+ }
+ else
+ {
+ PM2DControlPoint* helpPoint = 0;
+
+ for( it = m_points.begin( ), i = 0; it != m_points.end( ); ++it, ++i )
+ {
+ int imod4 = i % 4;
+ if( d == 0 )
+ cp = new PM2DControlPoint( *it, PM2DControlPoint::PM2DXY, i,
+ i18n( "Point %1 (xy)" ).arg( i + 1 ) );
+ else
+ cp = new PM2DControlPoint( *it, PM2DControlPoint::PM2DZY, i,
+ i18n( "Point %1 (xy)" ).arg( i + 1 ) );
+ switch( imod4 )
+ {
+ case 0:
+ helpPoint = cp;
+ break;
+ case 1:
+ cp->setBasePoint( helpPoint );
+ break;
+ case 2:
+ helpPoint = cp;
+ break;
+ case 3:
+ helpPoint->setBasePoint( cp );
+ break;
+ default:
+ break;
+ }
+
+ tmp[d].append( cp );
+ }
+ }
+ }
+
+ QPtrListIterator<PM2DControlPoint> cit1( tmp[0] ), cit2( tmp[1] );
+
+ for( ; cit1.current( ) && cit2.current( ); ++cit1, ++cit2 )
+ {
+ ( *cit1 )->setLatheLink( *cit2 );
+ ( *cit2 )->setLatheLink( *cit1 );
+ }
+ for( cit1.toFirst( ); cit1.current( ); ++cit1 )
+ list.append( *cit1 );
+ for( cit2.toFirst( ); cit2.current( ); ++cit2 )
+ list.append( *cit2 );
+}
+
+void PMLathe::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPointListIterator it1( list ), it2( list );
+ QValueList<PMVector>::Iterator pit = m_points.begin( );
+ PM2DControlPoint* p1;
+ PM2DControlPoint* p2;
+ bool firstChange = true;
+
+ for( it2 += list.count( ) / 2; it2.current( ); ++it1, ++it2, ++pit )
+ {
+ p1 = ( PM2DControlPoint* ) it1.current( );
+ p2 = ( PM2DControlPoint* ) it2.current( );
+
+ if( p1->changed( ) )
+ {
+ if( firstChange )
+ {
+ if( m_pMemento )
+ {
+ PMSplineMemento* m = ( PMSplineMemento* ) m_pMemento;
+ if( !m->splinePointsSaved( ) )
+ m->setSplinePoints( m_points );
+ }
+ firstChange = false;
+ setViewStructureChanged( );
+ }
+ p2->setPoint( p1->point( ) );
+ ( *pit ) = p1->point( );
+ }
+ else if( p2->changed( ) )
+ {
+ if( firstChange )
+ {
+ if( m_pMemento )
+ {
+ PMSplineMemento* m = ( PMSplineMemento* ) m_pMemento;
+ if( !m->splinePointsSaved( ) )
+ m->setSplinePoints( m_points );
+ }
+ firstChange = false;
+ setViewStructureChanged( );
+ }
+ p1->setPoint( p2->point( ) );
+ ( *pit ) = p2->point( );
+ }
+ }
+}
+
+void PMLathe::addObjectActions( const PMControlPointList& /*cp*/,
+ QPtrList<PMObjectAction>& actions )
+{
+ PMObjectAction* a;
+
+ a = new PMObjectAction( s_pMetaObject, PMSplitSegmentID,
+ i18n( "Add Point" ) );
+ actions.append( a );
+
+ a = new PMObjectAction( s_pMetaObject, PMJoinSegmentsID,
+ i18n( "Remove Point" ) );
+ int np = m_points.count( );
+ int minp = 3;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ minp = 3;
+ break;
+ case QuadraticSpline:
+ minp = 4;
+ break;
+ case CubicSpline:
+ minp = 5;
+ break;
+ case BezierSpline:
+ minp = 8;
+ break;
+ }
+
+ if( np < minp )
+ a->setEnabled( false );
+ actions.append( a );
+}
+
+void PMLathe::objectActionCalled( const PMObjectAction* action,
+ const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ if( action->objectType( ) == s_pMetaObject )
+ {
+ switch( action->actionID( ) )
+ {
+ case PMSplitSegmentID:
+ splitSegment( cp, cpViewPosition, clickPosition );
+ break;
+ case PMJoinSegmentsID:
+ joinSegments( cp, cpViewPosition, clickPosition );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMLathe::objectActionCalled\n";
+ break;
+ }
+ }
+ else
+ Base::objectActionCalled( action, cp, cpViewPosition, clickPosition );
+}
+
+void PMLathe::splitSegment( const PMControlPointList& /*cp*/,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ // find nearest segment
+ int nump = cpViewPosition.count( ) / 2 - 1;
+ double abs = 0.0, minabs = 1e10;
+ int ns = -1;
+ int i, j;
+ PMVector mid( 3 ), dist( 2 );
+
+ QPtrListIterator<PMVector> it1( cpViewPosition );
+ QPtrListIterator<PMVector> it2( cpViewPosition );
+ ++it2;
+
+ for( j = 0; j < 2; ++j )
+ {
+ for( i = 0; i < nump; ++i )
+ {
+ bool skip = false;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ case BezierSpline:
+ break;
+ case QuadraticSpline:
+ if( i == 0 )
+ skip = true;
+ break;
+ case CubicSpline:
+ if( ( i == 0 ) || ( i == ( nump - 1 ) ) )
+ skip = true;
+ break;
+ }
+
+ if( !skip )
+ {
+ mid = ( **it1 + **it2 ) / 2.0;
+ dist[0] = mid[0];
+ dist[1] = mid[1];
+ dist -= clickPosition;
+ abs = dist.abs( );
+
+ if( ( minabs > abs ) || ( ns < 0 ) )
+ {
+ minabs = abs;
+ ns = i;
+ }
+ }
+ ++it1;
+ ++it2;
+ }
+ ++it1;
+ ++it2;
+ }
+
+ // add a new segment
+ QValueList<PMVector> newPoints = m_points;
+
+ if( m_splineType == BezierSpline )
+ {
+ ns /= 4;
+ ns *= 4;
+ }
+ QValueList<PMVector>::Iterator it = newPoints.at( ( unsigned ) ns );
+ PMVector p[4];
+ QValueList<PMVector>::Iterator hit = it;
+
+ // calculate the spline segment
+ PMSplineSegment segment;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ for( i = 0; i < 2; ++i, ++hit )
+ p[i] = *hit;
+ segment.calculateLinear( p[0], p[1] );
+ break;
+ case QuadraticSpline:
+ --hit;
+ for( i = 0; i < 3; ++i, ++hit )
+ p[i] = *hit;
+ segment.calculateQuadratic( p[0], p[1], p[2] );
+ break;
+ case CubicSpline:
+ --hit;
+ for( i = 0; i < 4; ++i, ++hit )
+ p[i] = *hit;
+ segment.calculateCubic( p[0], p[1], p[2], p[3] );
+ break;
+ case BezierSpline:
+ for( i = 0; i < 4; ++i, ++hit )
+ p[i] = *hit;
+ segment.calculateBezier( p[0], p[1], p[2], p[3] );
+ break;
+ }
+
+ mid = segment.point( 0.5 );
+ if( m_splineType != BezierSpline )
+ {
+ ++it;
+ newPoints.insert( it, mid );
+ }
+ else
+ {
+ PMVector end = *it;
+ ++it;
+ *it = end + ( *it - end ) / 2.0;
+ ++it;
+
+ PMVector grad = segment.gradient( 0.5 ) / 4.0;
+
+ newPoints.insert( it, mid - grad );
+ newPoints.insert( it, mid );
+ newPoints.insert( it, mid );
+ newPoints.insert( it, mid + grad );
+
+ ++it;
+ end = *it;
+ --it;
+ *it = end + ( *it - end ) / 2.0;
+ }
+ setPoints( newPoints );
+}
+
+void PMLathe::joinSegments( const PMControlPointList& /*cp*/,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ // find nearest point
+ int nump = cpViewPosition.count( ) / 2;
+ int minp = 0;
+
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ minp = 3;
+ break;
+ case QuadraticSpline:
+ minp = 4;
+ break;
+ case CubicSpline:
+ minp = 5;
+ break;
+ case BezierSpline:
+ minp = 8;
+ break;
+ }
+
+ if( nump < minp )
+ {
+ kdError( PMArea ) << "Not enough points in PMLathe::joinSegments\n";
+ return;
+ }
+
+ double abs = 0.0, minabs = 1e10;
+ int ns = -1;
+ int i, j;
+ PMVector* p;
+ PMVector dist( 2 );
+
+ QPtrListIterator<PMVector> it1( cpViewPosition );
+
+ for( j = 0; j < 2; ++j )
+ {
+ for( i = 0; i < nump; ++i )
+ {
+ p = *it1;
+ dist[0] = (*p)[0];
+ dist[1] = (*p)[1];
+ dist -= clickPosition;
+ abs = dist.abs( );
+
+ if( ( minabs > abs ) || ( ns < 0 ) )
+ {
+ minabs = abs;
+ ns = i;
+ }
+ ++it1;
+ }
+ }
+
+ // join two segments
+ QValueList<PMVector> newPoints = m_points;
+ QValueList<PMVector>::Iterator it;
+
+ if( m_splineType != BezierSpline )
+ {
+ // never remove the first or last point
+ if( ns == 0 )
+ ++ns;
+ if( ns == ( nump - 1 ) )
+ --ns;
+ it = newPoints.at( ns );
+ newPoints.remove( it );
+ }
+ else
+ {
+ ns = ( ns - 2 ) / 4;
+ if( ns < 0 )
+ ns = 0;
+ if( ns >= ( nump / 4 - 1 ) )
+ ns = nump / 4 - 2;
+
+ it = newPoints.at( ns * 4 + 2 );
+ for( i = 0; i < 4; ++i )
+ it = newPoints.remove( it );
+ }
+ setPoints( newPoints );
+}
+
+void PMLathe::setRSteps( int r )
+{
+ if( r >= 4 )
+ s_rSteps = r;
+ else
+ kdDebug( PMArea ) << "PMLathe::setRSteps: R must be greater than 3\n";
+ ++s_parameterKey;
+}
+
+void PMLathe::setSSteps( int s )
+{
+ if( s >= 1 )
+ s_sSteps = s;
+ else
+ kdDebug( PMArea ) << "PMLathe::setSSteps: S must be greater than 0\n";
+ ++s_parameterKey;
+}
diff --git a/kpovmodeler/pmlathe.h b/kpovmodeler/pmlathe.h
new file mode 100644
index 00000000..99986a6f
--- /dev/null
+++ b/kpovmodeler/pmlathe.h
@@ -0,0 +1,193 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLATHE_H
+#define PMLATHE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <math.h>
+
+class PMViewStructure;
+
+/**
+ * Class for povray lathe objects.
+ */
+
+class PMLathe : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * The spline type
+ */
+ enum SplineType { LinearSpline, QuadraticSpline, CubicSpline, BezierSpline };
+ /**
+ * Creates an empty PMLathe
+ */
+ PMLathe( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMLathe( const PMLathe& l );
+ /**
+ * deletes the PMLathe
+ */
+ virtual ~PMLathe( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMLathe( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMLatheEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmlathe" ); }
+
+ /** */
+ virtual void createMemento( );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual bool multipleSelectControlPoints( ) const { return true; }
+ /** */
+ virtual void addObjectActions( const PMControlPointList&,
+ QPtrList<PMObjectAction>& );
+ /** */
+ virtual void objectActionCalled( const PMObjectAction*,
+ const PMControlPointList&,
+ const QPtrList<PMVector>&,
+ const PMVector& );
+
+ /**
+ * Returns the spline points
+ */
+ QValueList<PMVector> points( ) const { return m_points; }
+ /**
+ * Sets the spline points
+ */
+ void setPoints( const QValueList<PMVector>& points );
+ /**
+ * Returns the number of spline points
+ */
+ int numberOfPoints( ) const { return m_points.size( ); }
+ /**
+ * Returns the spline type
+ */
+ SplineType splineType( ) const { return m_splineType; }
+ /**
+ * Sets the spline type
+ */
+ void setSplineType( SplineType t );
+ /**
+ * Returns the sturm flag
+ */
+ bool sturm( ) const { return m_sturm; }
+ /**
+ * Sets the sturm flag
+ */
+ void setSturm( bool s );
+
+ /**
+ * Sets the number of steps around the y axis
+ */
+ static void setRSteps( int r );
+ /**
+ * Sets the number of subdivisions of one spline segment
+ */
+ static void setSSteps( int v );
+ /**
+ * Returns the number of steps around the y axis
+ */
+ static int rSteps( ) { return s_rSteps; }
+ /**
+ * Returns the number of subdivisions of one spline segment
+ */
+ static int sSteps( ) { return s_sSteps; }
+
+protected:
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey( ); }
+
+private:
+ /**
+ * Object action. Adds a spline point
+ */
+ void splitSegment( const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition );
+ /**
+ * Object action. Removes a spline point
+ */
+ void joinSegments( const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition );
+
+ void stringToValues( const QString& str );
+ QString valuesToString( ) const;
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMLatheMementoID { PMSplineTypeID, PMSturmID };
+ /**
+ * IDs for the object actions
+ */
+ enum PMLatheActionID { PMSplitSegmentID, PMJoinSegmentsID };
+ SplineType m_splineType;
+ QValueList<PMVector> m_points;
+ bool m_sturm;
+
+ static int s_rSteps;
+ static int s_sSteps;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmlatheedit.cpp b/kpovmodeler/pmlatheedit.cpp
new file mode 100644
index 00000000..970cc2f5
--- /dev/null
+++ b/kpovmodeler/pmlatheedit.cpp
@@ -0,0 +1,333 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlatheedit.h"
+#include "pmlathe.h"
+#include "pmvectoredit.h"
+#include "pmvectorlistedit.h"
+#include "pmpart.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+PMLatheEdit::PMLatheEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMLatheEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Spline type:" ), this ) );
+ m_pSplineType = new QComboBox( false, this );
+ m_pSplineType->insertItem( i18n( "Linear Spline" ) );
+ m_pSplineType->insertItem( i18n( "Quadratic Spline" ) );
+ m_pSplineType->insertItem( i18n( "Cubic Spline" ) );
+ m_pSplineType->insertItem( i18n( "Bezier Spline" ) );
+ hl->addWidget( m_pSplineType );
+ hl->addStretch( 1 );
+
+ connect( m_pSplineType, SIGNAL( activated( int ) ),
+ SLOT( slotTypeChanged( int ) ) );
+}
+
+void PMLatheEdit::createBottomWidgets( )
+{
+ topLayout( )->addWidget( new QLabel( i18n( "Spline points:" ), this ) );
+
+ m_pPoints = new PMVectorListEdit( "u", "v", this );
+ connect( m_pPoints, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPoints, SIGNAL( selectionChanged( ) ),
+ SLOT( slotSelectionChanged( ) ) );
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( m_pPoints, 2 );
+
+ m_pAddAbove = new QPushButton( this );
+ m_pAddAbove->setPixmap( SmallIcon( "pmaddpointabove" ) );
+ m_pAddBelow = new QPushButton( this );
+ m_pAddBelow->setPixmap( SmallIcon( "pmaddpoint" ) );
+ m_pRemove = new QPushButton( this );
+ m_pRemove->setPixmap( SmallIcon( "pmremovepoint" ) );
+ connect( m_pAddAbove, SIGNAL( clicked( ) ), SLOT( slotAddPointAbove( ) ) );
+ connect( m_pAddBelow, SIGNAL( clicked( ) ), SLOT( slotAddPointBelow( ) ) );
+ connect( m_pRemove, SIGNAL( clicked( ) ), SLOT( slotRemovePoint( ) ) );
+
+ QVBoxLayout* bl = new QVBoxLayout( hl );
+ bl->addWidget( m_pAddAbove );
+ bl->addWidget( m_pAddBelow );
+ bl->addWidget( m_pRemove );
+ bl->addStretch( 1 );
+
+ m_pSturm = new QCheckBox( i18n( "Sturm" ), this );
+ topLayout( )->addWidget( m_pSturm );
+ connect( m_pSturm, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+
+ Base::createBottomWidgets( );
+}
+
+void PMLatheEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Lathe" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMLathe* ) o;
+
+ switch( m_pDisplayedObject->splineType( ) )
+ {
+ case PMLathe::LinearSpline:
+ m_pSplineType->setCurrentItem( 0 );
+ break;
+ case PMLathe::QuadraticSpline:
+ m_pSplineType->setCurrentItem( 1 );
+ break;
+ case PMLathe::CubicSpline:
+ m_pSplineType->setCurrentItem( 2 );
+ break;
+ case PMLathe::BezierSpline:
+ m_pSplineType->setCurrentItem( 3 );
+ break;
+ }
+ m_pSplineType->setEnabled( !readOnly );
+ m_pSturm->setChecked( m_pDisplayedObject->sturm( ) );
+ m_pSturm->setEnabled( !readOnly );
+ m_pPoints->setReadOnly( readOnly );
+ m_pPoints->setVectors( m_pDisplayedObject->points( ), true );
+ updateControlPointSelection( );
+ updatePointButtons( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMLatheEdit: Can't display object\n";
+}
+
+void PMLatheEdit::updateControlPointSelection( )
+{
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp );
+ int i;
+ int np = cp.count( ) / 2;
+
+ if( np == m_pPoints->size( ) )
+ {
+ m_pPoints->blockSelectionUpdates( true );
+ bool sb = m_pPoints->signalsBlocked( );
+ m_pPoints->blockSignals( true );
+
+ m_pPoints->clearSelection( );
+ for( i = 0; i < np; i++, ++it )
+ if( ( *it )->selected( ) )
+ m_pPoints->select( i );
+ for( i = 0; i < np; i++, ++it )
+ if( ( *it )->selected( ) )
+ m_pPoints->select( i );
+
+ m_pPoints->blockSignals( sb );
+ m_pPoints->blockSelectionUpdates( false );
+ }
+}
+
+void PMLatheEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ m_pDisplayedObject->setPoints( m_pPoints->vectors( ) );
+
+ switch( m_pSplineType->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setSplineType( PMLathe::LinearSpline );
+ break;
+ case 1:
+ m_pDisplayedObject->setSplineType( PMLathe::QuadraticSpline );
+ break;
+ case 2:
+ m_pDisplayedObject->setSplineType( PMLathe::CubicSpline );
+ break;
+ case 3:
+ m_pDisplayedObject->setSplineType( PMLathe::BezierSpline );
+ break;
+ }
+ m_pDisplayedObject->setSturm( m_pSturm->isChecked( ) );
+ Base::saveContents( );
+ }
+}
+
+bool PMLatheEdit::isDataValid( )
+{
+ if( !m_pPoints->isDataValid( ) )
+ return false;
+
+ int np = m_pPoints->size( );
+ switch( m_pSplineType->currentItem( ) )
+ {
+ case 0:
+ if( np < 2 )
+ {
+ KMessageBox::error( this, i18n( "Linear splines need at least 2 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 1:
+ if( np < 3 )
+ {
+ KMessageBox::error( this, i18n( "Quadratic splines need at least 3 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 2:
+ if( np < 4 )
+ {
+ KMessageBox::error( this, i18n( "Cubic splines need at least 4 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 3:
+ if( ( np < 4 ) || ( ( np % 4 ) != 0 ) )
+ {
+ KMessageBox::error( this, i18n( "Bezier splines need 4 points for each segment." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMLatheEdit::slotTypeChanged( int )
+{
+ emit dataChanged( );
+}
+
+void PMLatheEdit::slotAddPointAbove( )
+{
+ int index = m_pPoints->currentRow( );
+ if( index >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ if( it != points.end( ) )
+ {
+ QValueListIterator<PMVector> it2 = it;
+ it2--;
+ PMVector v;
+ if( it2 == points.end( ) )
+ v = *it;
+ else
+ v = ( *it + *it2 ) / 2;
+
+ points.insert( it, v );
+ m_pPoints->setVectors( points, true );
+ updatePointButtons( );
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+}
+
+void PMLatheEdit::slotAddPointBelow( )
+{
+ int index = m_pPoints->currentRow( );
+ if( index >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ if( it != points.end( ) )
+ {
+ QValueListIterator<PMVector> it2 = it;
+ it2++;
+ PMVector v;
+ if( it2 == points.end( ) )
+ v = *it;
+ else
+ v = ( *it + *it2 ) / 2;
+
+ points.insert( it2, v );
+ m_pPoints->setVectors( points, true );
+ m_pPoints->setCurrentCell( index + 1, m_pPoints->currentColumn( ) );
+ updatePointButtons( );
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+}
+
+void PMLatheEdit::slotRemovePoint( )
+{
+ int row = m_pPoints->currentRow( );
+
+ if( row >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( row );
+
+ if( it != points.end( ) && points.size( ) > 1 )
+ {
+ points.remove( it );
+ m_pPoints->setVectors( points, true );
+ updatePointButtons( );
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+}
+
+void PMLatheEdit::slotSelectionChanged( )
+{
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp );
+ int np = cp.count( ) / 2;
+ int i;
+
+ if( np == m_pPoints->size( ) )
+ {
+ for( i = 0; i < np; i++, ++it )
+ ( *it )->setSelected( m_pPoints->isSelected( i ) );
+ for( i = 0; i < np; i++, ++it )
+ ( *it )->setSelected( m_pPoints->isSelected( i ) );
+ emit controlPointSelectionChanged( );
+ }
+ updatePointButtons( );
+}
+
+void PMLatheEdit::updatePointButtons( )
+{
+ int row = m_pPoints->currentRow( );
+ m_pAddAbove->setEnabled( row >= 0 );
+ m_pAddBelow->setEnabled( row >= 0 );
+ m_pRemove->setEnabled( row >= 0 && m_pPoints->size( ) > 2 );
+}
+
+#include "pmlatheedit.moc"
diff --git a/kpovmodeler/pmlatheedit.h b/kpovmodeler/pmlatheedit.h
new file mode 100644
index 00000000..ad8cf835
--- /dev/null
+++ b/kpovmodeler/pmlatheedit.h
@@ -0,0 +1,89 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLATHEEDIT_H
+#define PMLATHEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+#include "pmvectoredit.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+
+class PMLathe;
+class PMVectorListEdit;
+class QVBoxLayout;
+class QComboBox;
+class QCheckBox;
+class QPushButton;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMLathe
+ */
+class PMLatheEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMLatheEdit with parent and name
+ */
+ PMLatheEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+ /** */
+ virtual void updateControlPointSelection( );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void createBottomWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotTypeChanged( int );
+ void slotAddPointAbove( );
+ void slotAddPointBelow( );
+ void slotRemovePoint( );
+ void slotSelectionChanged( );
+
+private:
+ void updatePointButtons( );
+
+ PMLathe* m_pDisplayedObject;
+ QComboBox* m_pSplineType;
+ QCheckBox* m_pSturm;
+ PMVectorListEdit* m_pPoints;
+ QPushButton* m_pAddAbove;
+ QPushButton* m_pAddBelow;
+ QPushButton* m_pRemove;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmlayoutsettings.cpp b/kpovmodeler/pmlayoutsettings.cpp
new file mode 100644
index 00000000..398e5354
--- /dev/null
+++ b/kpovmodeler/pmlayoutsettings.cpp
@@ -0,0 +1,774 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlayoutsettings.h"
+
+#include "pmlineedits.h"
+#include "pmviewfactory.h"
+#include "pmdebug.h"
+
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlistbox.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+PMLayoutSettings::PMLayoutSettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ QHBoxLayout* hlayout;
+ QVBoxLayout* vlayout;
+ QVBoxLayout* gvl;
+ QGridLayout* grid;
+ QGroupBox* gb;
+ QGroupBox* gbe;
+ QHBoxLayout* ghe;
+ QVBoxLayout* gvle;
+
+ vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+
+ hlayout = new QHBoxLayout( vlayout );
+ hlayout->addWidget( new QLabel( i18n( "Default view layout:" ), this ) );
+ m_pDefaultLayout = new QComboBox( this );
+ hlayout->addWidget( m_pDefaultLayout, 1 );
+ hlayout->addStretch( 1 );
+
+ gb = new QGroupBox( i18n( "Available View Layouts" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+
+ grid = new QGridLayout( gvl, 3, 2 );
+ m_pViewLayouts = new QListBox( gb );
+ connect( m_pViewLayouts, SIGNAL( highlighted( int ) ),
+ SLOT( slotLayoutSelected( int ) ) );
+ grid->addMultiCellWidget( m_pViewLayouts, 0, 2, 0, 0 );
+ m_pAddLayout = new QPushButton( i18n( "Add" ), gb );
+ connect( m_pAddLayout, SIGNAL( clicked( ) ), SLOT( slotAddLayout( ) ) );
+ grid->addWidget( m_pAddLayout, 0, 1 );
+ m_pRemoveLayout = new QPushButton( i18n( "Remove" ), gb );
+ connect( m_pRemoveLayout, SIGNAL( clicked( ) ), SLOT( slotRemoveLayout( ) ) );
+ grid->addWidget( m_pRemoveLayout, 1, 1 );
+ grid->setRowStretch( 2, 1 );
+
+ gbe = new QGroupBox( i18n( "View Layout" ), gb );
+ gvl->addWidget( gbe );
+ gvle = new QVBoxLayout( gbe, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvle->addSpacing( 10 );
+ ghe = new QHBoxLayout( gvle );
+ ghe->addWidget( new QLabel( i18n( "Name:" ), gbe ) );
+ m_pViewLayoutName = new QLineEdit( gbe );
+ connect( m_pViewLayoutName, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotLayoutNameChanged( const QString& ) ) );
+ ghe->addWidget( m_pViewLayoutName );
+ grid = new QGridLayout( gvle, 4, 2 );
+ m_pViewEntries = new QListView( gbe );
+ m_pViewEntries->setAllColumnsShowFocus( true );
+ m_pViewEntries->addColumn( " " ); // This column is for the view entry number
+ m_pViewEntries->addColumn( i18n( "Type" ) );
+ m_pViewEntries->addColumn( i18n( "Position" ) );
+ m_pViewEntries->setSorting( -1 );
+ m_pViewEntries->setMaximumHeight( 150 );
+ connect( m_pViewEntries, SIGNAL( selectionChanged( QListViewItem* ) ),
+ SLOT( slotViewEntrySelected( QListViewItem* ) ) );
+ grid->addMultiCellWidget( m_pViewEntries, 0, 3, 0, 0 );
+ m_pAddEntry = new QPushButton( i18n( "Add" ), gbe );
+ connect( m_pAddEntry, SIGNAL( clicked( ) ), SLOT( slotAddViewEntryClicked( ) ) );
+ grid->addWidget( m_pAddEntry, 0, 1 );
+ m_pRemoveEntry = new QPushButton( i18n( "Remove" ), gbe );
+ connect( m_pRemoveEntry, SIGNAL( clicked( ) ), SLOT( slotRemoveViewEntryClicked( ) ) );
+ grid->addWidget( m_pRemoveEntry, 1, 1 );
+ /* //TODO
+ m_pMoveUpEntry = new QPushButton( i18n( "Move Up" ), gbe );
+ connect( m_pMoveUpEntry, SIGNAL( clicked( ) ), SLOT( slotMoveUpViewEntryClicked( ) ) );
+ grid->addWidget( m_pMoveUpEntry, 2, 1 );
+ m_pMoveDownEntry = new QPushButton( i18n( "Move Down" ), gbe );
+ connect( m_pMoveDownEntry, SIGNAL( clicked( ) ), SLOT( slotMoveDownViewEntryClicked( ) ) );
+ grid->addWidget( m_pMoveDownEntry, 3, 1 );
+ */
+
+ QHBoxLayout* ghl = new QHBoxLayout( gvle );
+ grid = new QGridLayout( ghl, 7, 4 );
+ grid->addWidget( new QLabel( i18n( "Type:" ), gbe ), 0, 0 );
+ grid->addWidget( new QLabel( i18n( "Dock position:" ), gbe ), 2, 0 );
+ m_pColumnWidthLabel = new QLabel( i18n( "Column width:" ), gbe );
+ grid->addWidget( m_pColumnWidthLabel, 3, 0 );
+ m_pViewHeightLabel = new QLabel( i18n( "View height:" ), gbe );
+ grid->addWidget( m_pViewHeightLabel, 4, 0 );
+ m_pViewTypeEdit = new QComboBox( gbe );
+
+ // insert all view types
+ const QPtrList<PMViewTypeFactory>& types =
+ PMViewFactory::theFactory( )->viewTypes( );
+ QPtrListIterator<PMViewTypeFactory> it( types );
+ for( ; *it; ++it )
+ m_pViewTypeEdit->insertItem( ( *it )->description( ) );
+
+ connect( m_pViewTypeEdit, SIGNAL( activated( int ) ),
+ SLOT( slotViewTypeChanged( int ) ) );
+ grid->addWidget( m_pViewTypeEdit, 0, 1 );
+ m_pDockPositionEdit = new QComboBox( gbe );
+ m_pDockPositionEdit->insertItem( i18n( "New Column" ) );
+ m_pDockPositionEdit->insertItem( i18n( "Below" ) );
+ m_pDockPositionEdit->insertItem( i18n( "Tabbed" ) );
+ m_pDockPositionEdit->insertItem( i18n( "Floating" ) );
+ connect( m_pDockPositionEdit, SIGNAL( activated( int ) ),
+ SLOT( slotDockPositionChanged( int ) ) );
+ grid->addWidget( m_pDockPositionEdit, 2, 1 );
+
+ m_pColumnWidthEdit = new PMIntEdit( gbe );
+ connect( m_pColumnWidthEdit, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotColumnWidthChanged( const QString& ) ) );
+ grid->addWidget( m_pColumnWidthEdit, 3, 1 );
+
+ m_pViewHeightEdit = new PMIntEdit( gbe );
+ connect( m_pViewHeightEdit, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotViewHeightChanged( const QString& ) ) );
+ grid->addWidget( m_pViewHeightEdit, 4, 1 );
+
+ m_pFloatingWidthLabel = new QLabel( i18n( "Width:" ), gbe );
+ m_pFloatingHeightLabel = new QLabel( i18n( "Height:" ), gbe );
+ m_pFloatingPosXLabel = new QLabel( i18n( "Position x:" ), gbe );
+ m_pFloatingPosYLabel = new QLabel( QString( "y:" ), gbe );
+ grid->addWidget( m_pFloatingWidthLabel, 5, 0 );
+ grid->addWidget( m_pFloatingHeightLabel, 5, 2 );
+ grid->addWidget( m_pFloatingPosXLabel, 6, 0 );
+ grid->addWidget( m_pFloatingPosYLabel, 6, 2 );
+
+ m_pFloatingWidth = new PMIntEdit( gbe );
+ connect( m_pFloatingWidth, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotFloatingWidthChanged( const QString& ) ) );
+ m_pFloatingHeight = new PMIntEdit( gbe );
+ connect( m_pFloatingHeight, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotFloatingHeightChanged( const QString& ) ) );
+ m_pFloatingPosX = new PMIntEdit( gbe );
+ connect( m_pFloatingPosX, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotFloatingPosXChanged( const QString& ) ) );
+ m_pFloatingPosY = new PMIntEdit( gbe );
+ connect( m_pFloatingPosY, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotFloatingPosYChanged( const QString& ) ) );
+ grid->addWidget( m_pFloatingWidth, 5, 1 );
+ grid->addWidget( m_pFloatingHeight, 5, 3 );
+ grid->addWidget( m_pFloatingPosX, 6, 1 );
+ grid->addWidget( m_pFloatingPosY, 6, 3 );
+
+ // create a holder widget for custom options widgets
+ m_pCustomOptionsWidget = 0;
+ m_pCustomOptionsHolder = new QWidget( gbe );
+
+ QVBoxLayout* covl = new QVBoxLayout( ghl );
+ covl->addWidget( m_pCustomOptionsHolder );
+ covl->addStretch( 1 );
+
+ ghl->addStretch( 1 );
+
+ vlayout->addStretch( 1 );
+}
+
+void PMLayoutSettings::displaySettings( )
+{
+ PMViewLayoutManager* m = PMViewLayoutManager::theManager( );
+ m_viewLayouts = m->layouts( );
+ m_currentViewLayout = m_viewLayouts.begin( );
+ m_defaultViewLayout = m_viewLayouts.begin( );
+ for( ; ( m_defaultViewLayout != m_viewLayouts.end( ) ) &&
+ ( *m_defaultViewLayout ).name( ) != m->defaultLayout( );
+ ++m_defaultViewLayout );
+ displayLayoutList( );
+ m_pViewLayouts->setCurrentItem( 0 );
+ if( m_pViewLayouts->numRows( ) == 1 )
+ m_pRemoveLayout->setEnabled( false );
+}
+
+void PMLayoutSettings::displayDefaults( )
+{
+}
+
+bool PMLayoutSettings::validateData( )
+{
+ QValueListIterator<PMViewLayout> lit;
+ for( lit = m_viewLayouts.begin( ); lit != m_viewLayouts.end( ); ++lit )
+ {
+ if( ( *lit ).name( ).isEmpty( ) )
+ {
+ emit showMe( );
+ KMessageBox::error( this, i18n( "View layouts may not have empty names." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ QValueListIterator<PMViewLayoutEntry> eit = ( *lit ).begin( );
+ if( eit != ( *lit ).end( ) )
+ {
+ if( ( *eit ).dockPosition( ) != PMDockWidget::DockRight )
+ {
+ emit showMe( );
+ KMessageBox::error( this, i18n( "The docking position of the first view layout entry has to be 'New Column'." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void PMLayoutSettings::applySettings( )
+{
+ QValueListIterator<PMViewLayout> lit;
+ for( lit = m_viewLayouts.begin( ); lit != m_viewLayouts.end( ); ++lit )
+ ( *lit ).normalize( );
+ PMViewLayoutManager::theManager( )->setDefaultLayout( m_pDefaultLayout->currentText( ) );
+ PMViewLayoutManager::theManager( )->setLayouts( m_viewLayouts );
+ PMViewLayoutManager::theManager( )->saveData( );
+}
+
+void PMLayoutSettings::displayLayoutList( )
+{
+ QValueListIterator<PMViewLayout> it;
+
+ m_pViewLayouts->clear( );
+ m_pDefaultLayout->clear( );
+ for( it = m_viewLayouts.begin( ); it != m_viewLayouts.end( ); ++it )
+ {
+ m_pViewLayouts->insertItem( ( *it ).name( ) );
+ m_pDefaultLayout->insertItem( ( *it ).name( ) );
+ if( it == m_defaultViewLayout )
+ m_pDefaultLayout->setCurrentText( ( *it ).name( ) );
+ }
+}
+
+void PMLayoutSettings::slotAddLayout( )
+{
+ QString new_name;
+ int i = 1;
+ QString str;
+
+ new_name = i18n( "Unnamed" );
+ str.setNum( i );
+ while( m_pViewLayouts->findItem( new_name, Qt::ExactMatch ) )
+ {
+ new_name = i18n( "Unnamed" ) + str;
+ i++;
+ str.setNum( i );
+ }
+
+ PMViewLayout l;
+ l.setName( new_name );
+
+ m_currentViewLayout++;
+ m_viewLayouts.insert( m_currentViewLayout, l );
+ displayLayoutList( );
+ m_pViewLayouts->setCurrentItem( m_pViewLayouts->findItem( new_name, Qt::ExactMatch ) );
+ m_pRemoveLayout->setEnabled( true );
+}
+
+void PMLayoutSettings::slotRemoveLayout( )
+{
+ if( m_currentViewLayout == m_defaultViewLayout )
+ {
+ m_defaultViewLayout--;
+ if( m_defaultViewLayout == m_viewLayouts.end( ) )
+ {
+ m_defaultViewLayout++;
+ m_defaultViewLayout++;
+ }
+ }
+ m_viewLayouts.remove( m_currentViewLayout );
+ displayLayoutList( );
+ m_pViewLayouts->setCurrentItem( m_pViewLayouts->firstItem( ) );
+
+ if( m_pViewLayouts->numRows( ) == 1 )
+ m_pRemoveLayout->setEnabled( false );
+}
+
+void PMLayoutSettings::slotLayoutSelected( int index )
+{
+ int i;
+ QString str;
+ bool sb;
+
+ m_currentViewLayout = m_viewLayouts.at( index );
+ m_currentViewEntry = ( *m_currentViewLayout ).begin( );
+
+ sb = m_pViewLayoutName->signalsBlocked( );
+ m_pViewLayoutName->blockSignals( true );
+ m_pViewLayoutName->setText( ( *m_currentViewLayout ).name( ) );
+ m_pViewLayoutName->blockSignals( sb );
+
+ PMViewLayout::iterator it;
+ QListViewItem* previous = NULL;
+ m_pViewEntries->clear( );
+ i = 0;
+ for( it = ( *m_currentViewLayout ).begin( );
+ it != ( *m_currentViewLayout ).end( ); ++it )
+ {
+ i++; str.setNum( i );
+ previous = new QListViewItem( m_pViewEntries, previous, str,
+ ( *it ).viewTypeAsString( ),
+ ( *it ).dockPositionAsString( ) );
+ if( i == 1 )
+ m_pViewEntries->setSelected( previous, true );
+ }
+ if( i == 0 )
+ slotViewEntrySelected( 0 );
+}
+
+void PMLayoutSettings::slotLayoutNameChanged( const QString& text )
+{
+ int n_item = m_pViewLayouts->currentItem( );
+ bool sb = m_pViewLayouts->signalsBlocked( );
+ m_pViewLayouts->blockSignals( true );
+ m_pViewLayouts->removeItem( n_item );
+ m_pViewLayouts->insertItem( text, n_item );
+ m_pViewLayouts->setCurrentItem( n_item );
+ m_pViewLayouts->blockSignals( sb );
+
+ ( *m_currentViewLayout ).setName( text );
+
+ QValueListIterator<PMViewLayout> it;
+ m_pDefaultLayout->clear( );
+ for( it = m_viewLayouts.begin( ); it != m_viewLayouts.end( ); ++it )
+ {
+ m_pDefaultLayout->insertItem( ( *it ).name( ) );
+ if( it == m_defaultViewLayout )
+ m_pDefaultLayout->setCurrentText( ( *it ).name( ) );
+ }
+}
+
+void PMLayoutSettings::slotViewEntrySelected( QListViewItem *item )
+{
+ if( item )
+ {
+ m_pViewTypeEdit->setEnabled( true );
+ m_pDockPositionEdit->setEnabled( true );
+
+ int n_item = item->text( 0 ).toInt( ) - 1;
+
+ m_currentViewEntry = ( *m_currentViewLayout ).at( n_item );
+ QString vt = ( *m_currentViewEntry ).viewType( );
+
+ // find the view type
+ int index = 0;
+ bool found = false;
+ const QPtrList<PMViewTypeFactory>& types =
+ PMViewFactory::theFactory( )->viewTypes( );
+ QPtrListIterator<PMViewTypeFactory> it( types );
+
+ for( ; *it && !found; ++it )
+ {
+ if( ( *it )->viewType( ) == vt )
+ found = true;
+ else
+ index++;
+ }
+
+ if( !found )
+ {
+ kdError( PMArea ) << "Unknown view type in PMLayoutSettings::slotViewEntrySelected" << endl;
+ m_pViewTypeEdit->setCurrentItem( 0 );
+ }
+ else
+ m_pViewTypeEdit->setCurrentItem( index );
+
+ /*
+ switch( ( *m_currentViewEntry ).glViewType( ) )
+ {
+ case PMGLView::PMViewNegY:
+ m_pGLViewTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMGLView::PMViewPosY:
+ m_pGLViewTypeEdit->setCurrentItem( 1 );
+ break;
+ case PMGLView::PMViewPosX:
+ m_pGLViewTypeEdit->setCurrentItem( 2 );
+ break;
+ case PMGLView::PMViewNegX:
+ m_pGLViewTypeEdit->setCurrentItem( 3 );
+ break;
+ case PMGLView::PMViewPosZ:
+ m_pGLViewTypeEdit->setCurrentItem( 4 );
+ break;
+ case PMGLView::PMViewNegZ:
+ m_pGLViewTypeEdit->setCurrentItem( 5 );
+ break;
+ case PMGLView::PMViewCamera:
+ m_pGLViewTypeEdit->setCurrentItem( 6 );
+ break;
+ }
+ */
+ switch( ( *m_currentViewEntry ).dockPosition( ) )
+ {
+ case PMDockWidget::DockRight:
+ m_pDockPositionEdit->setCurrentItem( 0 );
+ m_pColumnWidthLabel->show( );
+ m_pColumnWidthEdit->show( );
+ m_pViewHeightEdit->show( );
+ m_pViewHeightLabel->show( );
+ m_pFloatingWidth->hide( );
+ m_pFloatingHeight->hide( );
+ m_pFloatingPosX->hide( );
+ m_pFloatingPosY->hide( );
+ m_pFloatingWidthLabel->hide( );
+ m_pFloatingHeightLabel->hide( );
+ m_pFloatingPosXLabel->hide( );
+ m_pFloatingPosYLabel->hide( );
+ break;
+ case PMDockWidget::DockBottom:
+ m_pDockPositionEdit->setCurrentItem( 1 );
+ m_pColumnWidthLabel->hide( );
+ m_pColumnWidthEdit->hide( );
+ m_pViewHeightEdit->show( );
+ m_pViewHeightLabel->show( );
+ m_pFloatingWidth->hide( );
+ m_pFloatingHeight->hide( );
+ m_pFloatingPosX->hide( );
+ m_pFloatingPosY->hide( );
+ m_pFloatingWidthLabel->hide( );
+ m_pFloatingHeightLabel->hide( );
+ m_pFloatingPosXLabel->hide( );
+ m_pFloatingPosYLabel->hide( );
+ break;
+ case PMDockWidget::DockCenter:
+ m_pDockPositionEdit->setCurrentItem( 2 );
+ m_pColumnWidthLabel->hide( );
+ m_pColumnWidthEdit->hide( );
+ m_pViewHeightEdit->hide( );
+ m_pViewHeightLabel->hide( );
+ m_pFloatingWidth->hide( );
+ m_pFloatingHeight->hide( );
+ m_pFloatingPosX->hide( );
+ m_pFloatingPosY->hide( );
+ m_pFloatingWidthLabel->hide( );
+ m_pFloatingHeightLabel->hide( );
+ m_pFloatingPosXLabel->hide( );
+ m_pFloatingPosYLabel->hide( );
+ break;
+ default:
+ m_pDockPositionEdit->setCurrentItem( 3 );
+ m_pColumnWidthLabel->hide( );
+ m_pColumnWidthEdit->hide( );
+ m_pViewHeightEdit->hide( );
+ m_pViewHeightLabel->hide( );
+ m_pFloatingWidth->show( );
+ m_pFloatingHeight->show( );
+ m_pFloatingPosX->show( );
+ m_pFloatingPosY->show( );
+ m_pFloatingWidthLabel->show( );
+ m_pFloatingHeightLabel->show( );
+ m_pFloatingPosXLabel->show( );
+ m_pFloatingPosYLabel->show( );
+ break;
+ }
+ m_pColumnWidthEdit->setValue( ( *m_currentViewEntry ).columnWidth( ) );
+ m_pViewHeightEdit->setValue( ( *m_currentViewEntry ).height( ) );
+ m_pFloatingWidth->setValue( ( *m_currentViewEntry ).floatingWidth( ) );
+ m_pFloatingHeight->setValue( ( *m_currentViewEntry ).floatingHeight( ) );
+ m_pFloatingPosX->setValue( ( *m_currentViewEntry ).floatingPositionX( ) );
+ m_pFloatingPosY->setValue( ( *m_currentViewEntry ).floatingPositionY( ) );
+ m_pViewEntries->triggerUpdate( );
+ displayCustomOptions( );
+ }
+ else
+ {
+ m_pViewTypeEdit->setEnabled( false );
+ m_pDockPositionEdit->setEnabled( false );
+ m_pColumnWidthLabel->hide( );
+ m_pColumnWidthEdit->hide( );
+ m_pViewHeightEdit->hide( );
+ m_pViewHeightLabel->hide( );
+ m_pFloatingWidth->hide( );
+ m_pFloatingHeight->hide( );
+ m_pFloatingPosX->hide( );
+ m_pFloatingPosY->hide( );
+ m_pFloatingWidthLabel->hide( );
+ m_pFloatingHeightLabel->hide( );
+ m_pFloatingPosXLabel->hide( );
+ m_pFloatingPosYLabel->hide( );
+ }
+}
+
+void PMLayoutSettings::slotViewTypeChanged( int index )
+{
+ const QPtrList<PMViewTypeFactory>& types =
+ PMViewFactory::theFactory( )->viewTypes( );
+ QPtrListIterator<PMViewTypeFactory> it( types );
+ it += index;
+ const PMViewTypeFactory* factory = *it;
+ PMViewLayoutEntry& ve = ( *m_currentViewEntry );
+
+ if( factory && factory->viewType( ) != ve.viewType( ) )
+ {
+ ve.setViewType( factory->viewType( ) );
+ ve.setCustomOptions( factory->newOptionsInstance( ) );
+
+ QListViewItem* item = m_pViewEntries->currentItem( );
+ if( item )
+ {
+ if( ve.customOptions( ) )
+ item->setText( 1, factory->description( ve.customOptions( ) ) );
+ else
+ item->setText( 1, factory->description( ) );
+ displayCustomOptions( );
+ }
+ }
+}
+
+void PMLayoutSettings::slotDockPositionChanged( int index )
+{
+ switch( index )
+ {
+ case 0:
+ ( *m_currentViewEntry ).setDockPosition( PMDockWidget::DockRight );
+ m_pColumnWidthLabel->show( );
+ m_pColumnWidthEdit->show( );
+ m_pViewHeightEdit->show( );
+ m_pViewHeightLabel->show( );
+ m_pFloatingWidth->hide( );
+ m_pFloatingHeight->hide( );
+ m_pFloatingPosX->hide( );
+ m_pFloatingPosY->hide( );
+ m_pFloatingWidthLabel->hide( );
+ m_pFloatingHeightLabel->hide( );
+ m_pFloatingPosXLabel->hide( );
+ m_pFloatingPosYLabel->hide( );
+ break;
+ case 1:
+ ( *m_currentViewEntry ).setDockPosition( PMDockWidget::DockBottom );
+ m_pColumnWidthLabel->hide( );
+ m_pColumnWidthEdit->hide( );
+ m_pViewHeightEdit->show( );
+ m_pViewHeightLabel->show( );
+ m_pFloatingWidth->hide( );
+ m_pFloatingHeight->hide( );
+ m_pFloatingPosX->hide( );
+ m_pFloatingPosY->hide( );
+ m_pFloatingWidthLabel->hide( );
+ m_pFloatingHeightLabel->hide( );
+ m_pFloatingPosXLabel->hide( );
+ m_pFloatingPosYLabel->hide( );
+ break;
+ case 2:
+ ( *m_currentViewEntry ).setDockPosition( PMDockWidget::DockCenter );
+ m_pColumnWidthLabel->hide( );
+ m_pColumnWidthEdit->hide( );
+ m_pViewHeightEdit->hide( );
+ m_pViewHeightLabel->hide( );
+ m_pFloatingWidth->hide( );
+ m_pFloatingHeight->hide( );
+ m_pFloatingPosX->hide( );
+ m_pFloatingPosY->hide( );
+ m_pFloatingWidthLabel->hide( );
+ m_pFloatingHeightLabel->hide( );
+ m_pFloatingPosXLabel->hide( );
+ m_pFloatingPosYLabel->hide( );
+ break;
+ case 3:
+ ( *m_currentViewEntry ).setDockPosition( PMDockWidget::DockNone );
+ m_pColumnWidthLabel->hide( );
+ m_pColumnWidthEdit->hide( );
+ m_pViewHeightEdit->hide( );
+ m_pViewHeightLabel->hide( );
+ m_pFloatingWidth->show( );
+ m_pFloatingHeight->show( );
+ m_pFloatingPosX->show( );
+ m_pFloatingPosY->show( );
+ m_pFloatingWidthLabel->show( );
+ m_pFloatingHeightLabel->show( );
+ m_pFloatingPosXLabel->show( );
+ m_pFloatingPosYLabel->show( );
+ break;
+ }
+ QListViewItem* item = m_pViewEntries->currentItem( );
+ if( item )
+ item->setText( 2, ( *m_currentViewEntry ).dockPositionAsString( ) );
+}
+
+void PMLayoutSettings::slotViewHeightChanged( const QString& text )
+{
+ ( *m_currentViewEntry ).setHeight( text.toInt( ) );
+}
+
+void PMLayoutSettings::slotColumnWidthChanged( const QString& text )
+{
+ ( *m_currentViewEntry ).setColumnWidth( text.toInt( ) );
+}
+
+void PMLayoutSettings::slotFloatingWidthChanged( const QString& text )
+{
+ ( *m_currentViewEntry ).setFloatingWidth( text.toInt( ) );
+}
+
+void PMLayoutSettings::slotFloatingHeightChanged( const QString& text )
+{
+ ( *m_currentViewEntry ).setFloatingHeight( text.toInt( ) );
+}
+
+void PMLayoutSettings::slotFloatingPosXChanged( const QString& text )
+{
+ ( *m_currentViewEntry ).setFloatingPositionX( text.toInt( ) );
+}
+
+void PMLayoutSettings::slotFloatingPosYChanged( const QString& text )
+{
+ ( *m_currentViewEntry ).setFloatingPositionY( text.toInt( ) );
+}
+
+void PMLayoutSettings::slotAddViewEntryClicked( )
+{
+ PMViewLayoutEntry p;
+ QString str;
+ QListViewItem* temp;
+
+ temp = m_pViewEntries->currentItem( );
+ if( temp )
+ {
+ int n_item = temp->text( 0 ).toInt( );
+ ( *m_currentViewLayout ).addEntry( p, n_item );
+ n_item++;
+ str.setNum( n_item );
+ QListViewItem* a = new QListViewItem( m_pViewEntries, temp,
+ str, p.viewTypeAsString( ),
+ p.dockPositionAsString( ) );
+ m_pViewEntries->setSelected( a, true );
+ temp = a->nextSibling( );
+ while( temp )
+ {
+ n_item++;
+ str.setNum( n_item );
+ temp->setText( 0, str );
+ temp = temp->nextSibling( );
+ }
+ }
+ else
+ {
+ // If there is no selected the list must be empty
+ ( *m_currentViewLayout ).addEntry( p );
+ str.setNum( 1 );
+ QListViewItem* a = new QListViewItem( m_pViewEntries, NULL,
+ str, p.viewTypeAsString( ),
+ p.dockPositionAsString( ) );
+ m_pViewEntries->setSelected( a, true );
+ }
+}
+
+void PMLayoutSettings::slotRemoveViewEntryClicked( )
+{
+ QListViewItem* temp;
+ QString str;
+
+ QListViewItem* current = m_pViewEntries->currentItem( );
+ if( current )
+ {
+ int n_item = current->text( 0 ).toInt( ) - 1;
+ ( *m_currentViewLayout ).removeEntry( n_item );
+
+ // Save the next selected item in temp, since the current item will
+ // be removed.
+ temp = current->nextSibling( );
+ if( !temp )
+ temp = current->itemAbove( );
+ else
+ n_item++;
+
+ delete current;
+
+ if( temp )
+ {
+ str.setNum( n_item );
+ temp->setText( 0, str );
+ m_pViewEntries->setSelected( temp, true );
+ n_item++;
+ temp = temp->nextSibling( );
+ }
+ else
+ slotViewEntrySelected( 0 );
+ while( temp )
+ {
+ str.setNum( n_item );
+ temp->setText( 0, str );
+ n_item++;
+ temp = temp->nextSibling( );
+ }
+ }
+}
+
+void PMLayoutSettings::slotMoveUpViewEntryClicked( )
+{
+}
+
+void PMLayoutSettings::slotMoveDownViewEntryClicked( )
+{
+}
+
+void PMLayoutSettings::displayCustomOptions( )
+{
+ // delete an old widget
+ if( m_pCustomOptionsHolder->layout( ) )
+ delete m_pCustomOptionsHolder->layout( );
+ if( m_pCustomOptionsWidget )
+ {
+ delete m_pCustomOptionsWidget;
+ m_pCustomOptionsWidget = 0;
+ }
+
+ if( m_currentViewLayout != m_viewLayouts.end( ) &&
+ m_currentViewEntry != ( *m_currentViewLayout ).end( ) &&
+ ( *m_currentViewEntry ).customOptions( ) )
+ {
+ PMViewTypeFactory* vf = PMViewFactory::theFactory( )->viewFactory(
+ ( *m_currentViewEntry ).viewType( ) );
+ if( vf )
+ {
+ m_pCustomOptionsWidget =
+ vf->newOptionsWidget( m_pCustomOptionsHolder,
+ ( *m_currentViewEntry ).customOptions( ) );
+ if( m_pCustomOptionsWidget )
+ {
+ connect( m_pCustomOptionsWidget, SIGNAL( viewTypeDescriptionChanged( ) ),
+ SLOT( slotViewTypeDescriptionChanged( ) ) );
+ QHBoxLayout* hl = new QHBoxLayout( m_pCustomOptionsHolder,
+ 0, KDialog::spacingHint( ) );
+ hl->addWidget( m_pCustomOptionsWidget );
+ m_pCustomOptionsWidget->show( );
+ }
+ }
+ }
+}
+
+void PMLayoutSettings::slotViewTypeDescriptionChanged( )
+{
+ PMViewLayoutEntry& ve = *m_currentViewEntry;
+ const PMViewTypeFactory* factory =
+ PMViewFactory::theFactory( )->viewFactory( ve.viewType( ) );
+
+ if( factory )
+ {
+ QListViewItem* item = m_pViewEntries->currentItem( );
+ if( item )
+ {
+ if( ve.customOptions( ) )
+ item->setText( 1, factory->description( ve.customOptions( ) ) );
+ else
+ item->setText( 1, factory->description( ) );
+ }
+ }
+}
+
+#include "pmlayoutsettings.moc"
diff --git a/kpovmodeler/pmlayoutsettings.h b/kpovmodeler/pmlayoutsettings.h
new file mode 100644
index 00000000..4bca52e3
--- /dev/null
+++ b/kpovmodeler/pmlayoutsettings.h
@@ -0,0 +1,174 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLAYOUTSETTINGS_H
+#define PMLAYOUTSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+#include "pmviewlayoutmanager.h"
+
+#include <qvaluelist.h>
+
+class PMIntEdit;
+class PMViewOptionsWidget;
+class QComboBox;
+class QListBox;
+class QPushButton;
+class QLabel;
+
+/**
+ * View layout configuration dialog page
+ */
+class PMLayoutSettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMLayoutSettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual void displayDefaults( );
+
+protected slots:
+ /**
+ * Called when the browse add layout button is clicked
+ */
+ void slotAddLayout( );
+ /**
+ * Called when the remove layout button is clicked
+ */
+ void slotRemoveLayout( );
+ /**
+ * Called when the selected layout changes
+ */
+ void slotLayoutSelected( int i );
+ /**
+ * Called when the layout name changes
+ */
+ void slotLayoutNameChanged( const QString& text );
+ /**
+ * Called when the selected view entry changes
+ */
+ void slotViewEntrySelected( QListViewItem* text );
+ /**
+ * Called when the view type field changes value
+ */
+ void slotViewTypeChanged( int index );
+ /**
+ * Called when the gl view type field changes value
+ */
+ //void slotGLViewTypeChanged( int index );
+ /**
+ * Called when the dock position field changes value
+ */
+ void slotDockPositionChanged( int index );
+ /**
+ * Called when the view height field changes value
+ */
+ void slotViewHeightChanged( const QString& text );
+ /**
+ * Called when the column width field changes value
+ */
+ void slotColumnWidthChanged( const QString& text );
+ /**
+ * Called when the floating height changes value
+ */
+ void slotFloatingHeightChanged( const QString& text );
+ /**
+ * Called when the floating width changes value
+ */
+ void slotFloatingWidthChanged( const QString& text );
+ /**
+ * Called when the floating position x changes value
+ */
+ void slotFloatingPosXChanged( const QString& text );
+ /**
+ * Called when the floating position y changes value
+ */
+ void slotFloatingPosYChanged( const QString& text );
+ /**
+ * Called when the add view entry button is clicked
+ */
+ void slotAddViewEntryClicked( );
+ /**
+ * Called when the remove view entry button is clicked
+ */
+ void slotRemoveViewEntryClicked( );
+ /**
+ * Called when the move up view entry button is clicked
+ */
+ void slotMoveUpViewEntryClicked( );
+ /**
+ * Called when the move down view entry button is clicked
+ */
+ void slotMoveDownViewEntryClicked( );
+ /**
+ * Called when the view type description has changed
+ */
+ void slotViewTypeDescriptionChanged( );
+
+private:
+ void displayLayoutList( );
+ void displayCustomOptions( );
+
+ QComboBox* m_pDefaultLayout;
+ QListBox* m_pViewLayouts;
+ QPushButton* m_pAddLayout;
+ QPushButton* m_pRemoveLayout;
+ QLineEdit* m_pViewLayoutName;
+ QListView* m_pViewEntries;
+ QPushButton* m_pAddEntry;
+ QPushButton* m_pRemoveEntry;
+ QPushButton* m_pMoveUpEntry;
+ QPushButton* m_pMoveDownEntry;
+ QComboBox* m_pViewTypeEdit;
+ QComboBox* m_pDockPositionEdit;
+ PMIntEdit* m_pColumnWidthEdit;
+ QLabel* m_pColumnWidthLabel;
+ PMIntEdit* m_pViewHeightEdit;
+ QLabel* m_pViewHeightLabel;
+
+ PMIntEdit* m_pFloatingHeight;
+ PMIntEdit* m_pFloatingWidth;
+ QLabel* m_pFloatingHeightLabel;
+ QLabel* m_pFloatingWidthLabel;
+ PMIntEdit* m_pFloatingPosX;
+ PMIntEdit* m_pFloatingPosY;
+ QLabel* m_pFloatingPosXLabel;
+ QLabel* m_pFloatingPosYLabel;
+
+ PMViewOptionsWidget* m_pCustomOptionsWidget;
+ QWidget* m_pCustomOptionsHolder;
+
+ QValueList<PMViewLayout> m_viewLayouts;
+ QValueListIterator<PMViewLayout> m_currentViewLayout;
+ QValueListIterator<PMViewLayout> m_defaultViewLayout;
+ QValueListIterator<PMViewLayoutEntry> m_currentViewEntry;
+};
+
+#endif
diff --git a/kpovmodeler/pmlibrarybrowser.cpp b/kpovmodeler/pmlibrarybrowser.cpp
new file mode 100644
index 00000000..e133f08c
--- /dev/null
+++ b/kpovmodeler/pmlibrarybrowser.cpp
@@ -0,0 +1,304 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlibrarybrowser.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qsplitter.h>
+#include <qtimer.h>
+#include <qpushbutton.h>
+
+#include <kio/job.h>
+#include <kurl.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kdiroperator.h>
+#include <kiconloader.h>
+#include <kinputdialog.h>
+
+#include <stdlib.h>
+
+#include "pmlineedits.h"
+#include "pmdialogeditbase.h"
+#include "pmlibrarymanager.h"
+#include "pmlibraryhandle.h"
+#include "pmlibraryobject.h"
+#include "pmlibraryiconview.h"
+#include "pmlibraryentrypreview.h"
+
+// ************** PMLibraryBrowser **************************
+
+PMLibraryBrowserView::PMLibraryBrowserView( PMPart* /*part*/, QWidget* parent /*= 0*/,
+ const char* name /*=0*/ )
+ : PMViewBase( parent, name )
+{
+ QHBoxLayout* hl = new QHBoxLayout( this );
+ PMLibraryBrowserViewWidget* tv = new PMLibraryBrowserViewWidget( this );
+ hl->addWidget( tv );
+}
+
+QString PMLibraryBrowserView::description( ) const
+{
+ return i18n( "Library View" );
+}
+
+PMLibraryBrowserViewWidget::PMLibraryBrowserViewWidget( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ setCaption( i18n( "Library Objects" ) );
+
+ QVBoxLayout* vl = new QVBoxLayout( this, KDialog::spacingHint( ) );
+
+ QHBoxLayout* hl = new QHBoxLayout( vl );
+
+ m_pUpButton = new QPushButton( this );
+ m_pUpButton->setPixmap( SmallIcon( "up" ) );
+ m_pNewSubLibraryButton = new QPushButton( this );
+ m_pNewSubLibraryButton->setPixmap( SmallIcon( "folder_new" ) );
+ m_pNewObjectButton = new QPushButton( this );
+ m_pNewObjectButton->setPixmap( SmallIcon( "filenew" ) );
+ m_pDeleteObjectButton = new QPushButton( this );
+ m_pDeleteObjectButton->setPixmap( SmallIcon( "editdelete" ) );
+ QLabel* lbl = new QLabel( i18n( "Library: " ), this );
+ m_pLibraryComboBox = new QComboBox( this );
+ m_pLibraryComboBox->insertStringList( PMLibraryManager::theManager( )->availableLibraries( ) );
+ m_pLibraryComboBox->setDuplicatesEnabled( false );
+ m_pLibraryComboBox->setCurrentItem( 0 );
+ hl->addWidget( m_pUpButton );
+ hl->addWidget( m_pNewSubLibraryButton );
+ hl->addWidget( m_pNewObjectButton );
+ hl->addWidget( m_pDeleteObjectButton );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pLibraryComboBox );
+ hl->addStretch( 1 );
+
+ QSplitter *splitv = new QSplitter( this );
+ m_pLibraryIconView = new PMLibraryIconView( splitv );
+ m_pLibraryIconView->setMinimumSize( PMDialogEditBase::previewSize( )+20, PMDialogEditBase::previewSize( ) );
+ m_pLibraryEntryPreview = new PMLibraryEntryPreview( splitv );
+ vl->addWidget( splitv, 99 );
+
+ // Connect all the objects
+ connect( m_pUpButton, SIGNAL( clicked( ) ), SLOT( slotUpButtonClicked( ) ) );
+ connect( m_pNewSubLibraryButton, SIGNAL( clicked( ) ), SLOT( slotNewSubLibraryClicked( ) ) );
+ connect( m_pNewObjectButton, SIGNAL( clicked( ) ), SLOT( slotNewObjectClicked( ) ) );
+ connect( m_pDeleteObjectButton, SIGNAL( clicked( ) ), SLOT( slotDeleteClicked( ) ) );
+ connect( m_pLibraryComboBox, SIGNAL( highlighted( const QString& ) ),
+ SLOT( slotPathSelected( const QString& ) ) );
+ connect( m_pLibraryIconView, SIGNAL( selectionChanged( QIconViewItem* ) ),
+ SLOT( slotSelectionChanged( QIconViewItem* ) ) );
+ connect( m_pLibraryIconView, SIGNAL( executed( QIconViewItem* ) ),
+ SLOT( slotSelectionExecuted( QIconViewItem* ) ) );
+ connect( m_pLibraryEntryPreview, SIGNAL( objectChanged( ) ), SLOT( slotIconViewRefresh( ) ) );
+
+ // Set the selected library
+ slotPathSelected( m_pLibraryComboBox->currentText( ) );
+}
+
+void PMLibraryBrowserViewWidget::resizeEvent( QResizeEvent* /*ev*/ )
+{
+}
+
+void PMLibraryBrowserViewWidget::slotPathSelected( const QString& str )
+{
+ PMLibraryHandle* h = PMLibraryManager::theManager( )->getLibraryHandle( str );
+ if( h )
+ {
+ m_pLibraryIconView->setLibrary( h );
+ m_pCurrentLibrary = h;
+ // This can never be a sub library
+ m_pUpButton->setEnabled( false );
+ // If the top library is read-only so is everthing below it
+ m_topLibraryReadOnly = m_pCurrentLibrary->isReadOnly( );
+ m_pNewSubLibraryButton->setEnabled( !m_topLibraryReadOnly );
+ m_pNewObjectButton->setEnabled( !m_topLibraryReadOnly );
+ m_pDeleteObjectButton->setEnabled( !m_topLibraryReadOnly );
+ }
+ else
+ {
+ m_pUpButton->setEnabled( false );
+ m_pNewSubLibraryButton->setEnabled( false );
+ m_pNewObjectButton->setEnabled( false );
+ m_pDeleteObjectButton->setEnabled( false );
+ }
+}
+
+void PMLibraryBrowserViewWidget::slotIconViewRefresh( )
+{
+ m_pLibraryIconView->refresh( );
+}
+
+void PMLibraryBrowserViewWidget::slotIconViewSetLibrary( )
+{
+ m_pLibraryIconView->setLibrary( m_pFutureLibrary );
+ m_pCurrentLibrary = m_pFutureLibrary;
+ m_pFutureLibrary = NULL;
+}
+
+void PMLibraryBrowserViewWidget::slotSelectionChanged( QIconViewItem* item )
+{
+ PMLibraryIconViewItem* sel = static_cast<PMLibraryIconViewItem*>( item );
+ m_pLibraryIconView->setCurrentItem( sel );
+ if( sel->isSubLibrary( ) )
+ {
+ if( m_pLibraryEntryPreview->saveIfNeeded( ) )
+ QTimer::singleShot( 100, this, SLOT( slotIconViewRefresh( ) ) );
+ else
+ m_pLibraryEntryPreview->showPreview( sel->path( ), m_topLibraryReadOnly, true );
+ }
+ else
+ {
+ if( m_pLibraryEntryPreview->saveIfNeeded( ) )
+ QTimer::singleShot( 100, this, SLOT( slotIconViewRefresh( ) ) );
+ else
+ m_pLibraryEntryPreview->showPreview( sel->path( ), m_topLibraryReadOnly, false );
+ }
+ m_pLibraryIconView->setFocus();
+}
+
+void PMLibraryBrowserViewWidget::slotSelectionExecuted( QIconViewItem* item )
+{
+ PMLibraryIconViewItem* sel = static_cast<PMLibraryIconViewItem*>( item );
+ m_pLibraryIconView->setCurrentItem( sel );
+ if( sel->isSubLibrary( ) )
+ {
+ // It's a sub library
+ m_pFutureLibrary = new PMLibraryHandle( sel->path( ) );
+ m_pLibraryEntryPreview->clearPreview( );
+ QTimer::singleShot( 100, this, SLOT( slotIconViewSetLibrary( ) ) );
+ m_pUpButton->setEnabled( true );
+ }
+ else
+ {
+ // It's an object
+ if( m_pLibraryEntryPreview->saveIfNeeded( ) )
+ QTimer::singleShot( 100, this, SLOT( slotIconViewRefresh( ) ) );
+ else
+ m_pLibraryEntryPreview->showPreview( sel->path( ), m_topLibraryReadOnly, false );
+ }
+ m_pLibraryIconView->setFocus();
+}
+
+void PMLibraryBrowserViewWidget::slotUpButtonClicked( )
+{
+ QDir pathManipulator( m_pCurrentLibrary->path( ) );
+
+ pathManipulator.cdUp( );
+ m_pFutureLibrary = new PMLibraryHandle( pathManipulator.path( ) );
+ if( !m_pFutureLibrary->isSubLibrary( ) )
+ m_pUpButton->setEnabled( false );
+ QTimer::singleShot( 100, this, SLOT( slotIconViewSetLibrary( ) ) );
+
+ // Release the current Library
+ delete m_pCurrentLibrary;
+}
+
+void PMLibraryBrowserViewWidget::slotDeleteClicked( )
+{
+ PMLibraryIconViewItem* sel = static_cast<PMLibraryIconViewItem*>( m_pLibraryIconView->currentItem( ) );
+ PMLibraryHandle::PMResult rst;
+ if( !sel )
+ return;
+ else if( sel->isSubLibrary( ) )
+ rst = m_pCurrentLibrary->deleteSubLibrary( sel->path( ) );
+ else
+ rst = m_pCurrentLibrary->deleteObject( sel->path( ) );
+
+ switch( rst )
+ {
+ case PMLibraryHandle::Ok:
+ {
+ KIO::Job *job = KIO::del( sel->path() );
+ connect( job, SIGNAL( result( KIO::Job * ) ), SLOT( slotJobResult( KIO::Job * ) ) );
+ }
+ break;
+ case PMLibraryHandle::ReadOnlyLib:
+ KMessageBox::error( this, i18n( "This library is read only." ), i18n( "Error" ) );
+ break;
+ case PMLibraryHandle::NotInLib:
+ KMessageBox::error( this, i18n( "The current library does not contain that item." ), i18n( "Error" ) );
+ break;
+ default:
+ KMessageBox::error( this, i18n( "Could not remove item." ), i18n( "Error" ) );
+ break;
+ }
+}
+
+void PMLibraryBrowserViewWidget::slotNewObjectClicked( )
+{
+ m_pLibraryEntryPreview->saveIfNeeded( );
+
+ switch( m_pCurrentLibrary->createNewObject( ) )
+ {
+ case PMLibraryHandle::Ok:
+ QTimer::singleShot( 100, this, SLOT( slotIconViewRefresh( ) ) );
+ break;
+ case PMLibraryHandle::ReadOnlyLib:
+ KMessageBox::error( this, i18n( "This library is read only." ), i18n( "Error" ) );
+ break;
+ default:
+ KMessageBox::error( this, i18n( "Could not create a new object." ), i18n( "Error" ) );
+ }
+}
+
+void PMLibraryBrowserViewWidget::slotNewSubLibraryClicked( )
+{
+ bool result = false;
+
+ m_pLibraryEntryPreview->saveIfNeeded( );
+ QString subLibraryName = KInputDialog::getText( i18n( "Create Sub-Library" ),
+ i18n( "Enter the sub-library name: " ),
+ i18n( "Unknown" ),
+ &result );
+
+ if( result )
+ {
+ switch( m_pCurrentLibrary->createNewSubLibrary( subLibraryName ) )
+ {
+ case PMLibraryHandle::Ok:
+ m_pLibraryIconView->refresh( );
+ break;
+ case PMLibraryHandle::ExistingDir:
+ KMessageBox::error( this, i18n( "That library already exists." ), i18n( "Error" ) );
+ break;
+ case PMLibraryHandle::ReadOnlyLib:
+ KMessageBox::error( this, i18n( "This library is read only." ), i18n( "Error" ) );
+ break;
+ default:
+ KMessageBox::error( this, i18n( "Could not create a new sub library." ), i18n( "Error" ) );
+ }
+ }
+}
+
+void PMLibraryBrowserViewWidget::slotJobResult( KIO::Job * job )
+{
+ if( job->error( ) )
+ job->showErrorDialog( this );
+ QTimer::singleShot( 100, this, SLOT( slotIconViewRefresh( ) ) );
+}
+
+QString PMLibraryBrowserViewFactory::description( ) const
+{
+ return i18n( "Library View" );
+}
+
+#include "pmlibrarybrowser.moc"
diff --git a/kpovmodeler/pmlibrarybrowser.h b/kpovmodeler/pmlibrarybrowser.h
new file mode 100644
index 00000000..3d5af6ff
--- /dev/null
+++ b/kpovmodeler/pmlibrarybrowser.h
@@ -0,0 +1,119 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLIBRARYBROWSER_H
+#define PMLIBRARYBROWSER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qdict.h>
+
+#include "pmviewbase.h"
+#include "pmviewfactory.h"
+
+class QComboBox;
+class QIconViewItem;
+class QPushButton;
+class KConfig;
+class KDirOperator;
+class PMLibraryIconView;
+class PMLibraryEntryPreview;
+class PMLibraryHandle;
+class PMPart;
+namespace KIO{ class Job; }
+
+typedef QDict<QString> QStringDict;
+
+/**
+ * Wrapper class for the treeview/dock widget
+ */
+class PMLibraryBrowserView : public PMViewBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMLibraryBrowserView( PMPart* part, QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual QString viewType( ) const { return QString( "librarybrowserview" ); }
+ /** */
+ virtual QString description( ) const;
+};
+
+/**
+ * This class provides a non-modal dialog to browse the available libraries.
+ */
+class PMLibraryBrowserViewWidget: public QWidget
+{
+ Q_OBJECT
+public:
+ PMLibraryBrowserViewWidget( QWidget *parent, const char* name = NULL );
+
+private slots:
+ void resizeEvent( QResizeEvent* ev );
+ void slotPathSelected( const QString& str );
+ void slotSelectionChanged( QIconViewItem* item );
+ void slotSelectionExecuted( QIconViewItem* item );
+ void slotUpButtonClicked( );
+ void slotDeleteClicked( );
+ void slotNewObjectClicked( );
+ void slotNewSubLibraryClicked( );
+
+ void slotJobResult( KIO::Job * );
+
+ // These slots provide delayed activity on the IconView
+ void slotIconViewRefresh( );
+ void slotIconViewSetLibrary( );
+
+private:
+
+
+ QPushButton* m_pUpButton;
+ QPushButton* m_pNewSubLibraryButton;
+ QPushButton* m_pNewObjectButton;
+ QPushButton* m_pDeleteObjectButton;
+ QComboBox* m_pLibraryComboBox;
+ PMLibraryIconView* m_pLibraryIconView;
+ PMLibraryEntryPreview* m_pLibraryEntryPreview;
+ PMLibraryHandle* m_pCurrentLibrary;
+ PMLibraryHandle* m_pFutureLibrary;
+ bool m_topLibraryReadOnly;
+};
+
+/**
+ * Factory class for the tree view
+ */
+class PMLibraryBrowserViewFactory : public PMViewTypeFactory
+{
+public:
+ PMLibraryBrowserViewFactory( ) { }
+ virtual QString viewType( ) const { return QString( "librarybrowserview" ); }
+ virtual QString description( ) const;
+ virtual QString iconName( ) const { return QString( "pmlibrarybrowserview" ); }
+ virtual PMViewBase* newInstance( QWidget* parent, PMPart* part ) const
+ {
+ return new PMLibraryBrowserView( part, parent );
+ }
+};
+
+#endif
diff --git a/kpovmodeler/pmlibraryentrypreview.cpp b/kpovmodeler/pmlibraryentrypreview.cpp
new file mode 100644
index 00000000..b7232cdd
--- /dev/null
+++ b/kpovmodeler/pmlibraryentrypreview.cpp
@@ -0,0 +1,344 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlibraryobject.h"
+#include "pmlibraryhandle.h"
+#include "pmlibraryentrypreview.h"
+#include "pmdialogeditbase.h"
+#include "pmpart.h"
+#include "pmtreeview.h"
+#include "pmxmlparser.h"
+#include "pmscene.h"
+#include "pmobjectdrag.h"
+
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qmultilineedit.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qdragobject.h>
+
+#include <kurl.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+
+PMLibraryEntryPreview::PMLibraryEntryPreview( QWidget* parent ) :
+ QWidget( parent )
+{
+ setAcceptDrops( true );
+ m_pPart = new PMPart( this, "treeview", NULL, "part", false, true );
+ m_pPart->setReadWrite( false );
+ m_readOnly = true;
+ m_modified = false;
+ m_subLib = false;
+
+ setMaximumSize( 1000, 1000 );
+ QVBoxLayout* vl = new QVBoxLayout( this, KDialog::spacingHint( ) );
+
+ QHBoxLayout* hl = new QHBoxLayout( vl );
+ hl->addStretch( 1 );
+
+ QGridLayout* gl = new QGridLayout( vl, 4, 2 );
+ gl->setColStretch( 1, 1 );
+ QLabel* lbl = new QLabel( i18n( "Name: " ), this );
+ m_pName = new QLineEdit( this );
+ m_pName->setAlignment( Qt::AlignLeft );
+ m_pName->setReadOnly( true );
+ gl->addWidget( lbl, 0, 0 );
+ gl->addWidget( m_pName, 0, 1 );
+
+ lbl = new QLabel( i18n( "Description:" ), this );
+ lbl->setAlignment( Qt::AlignTop );
+ m_pDescription = new QMultiLineEdit( this );
+ m_pDescription->setAlignment( Qt::AlignTop | Qt::AlignLeft |
+ Qt::WordBreak | Qt::DontClip );
+ m_pDescription->setReadOnly( true );
+ gl->addWidget( lbl, 1, 0 );
+ gl->addWidget( m_pDescription, 1, 1 );
+
+ m_pKeywordsLabel = new QLabel( i18n( "Keywords:" ), this );
+ m_pKeywordsLabel->setAlignment( Qt::AlignTop );
+ m_pKeywords = new QMultiLineEdit( this );
+ m_pKeywords->setAlignment( Qt::AlignTop | Qt::AlignLeft |
+ Qt::WordBreak | Qt::DontClip );
+ m_pKeywords->setReadOnly( true );
+ gl->addWidget( m_pKeywordsLabel, 2, 0 );
+ gl->addWidget( m_pKeywords, 2, 1 );
+
+ m_pContentsLabel = new QLabel( i18n( "Contents:" ), this );
+ m_pContentsPreview = new PMTreeView( m_pPart, this );
+ gl->addMultiCellWidget( m_pContentsLabel, 3, 3, 0, 1 );
+ gl->addMultiCellWidget( m_pContentsPreview, 4, 4, 0, 1 );
+ gl->setRowStretch(4, 1);
+
+ hl = new QHBoxLayout( vl );
+ hl->addStretch( 1 );
+ m_pSetPreviewImageButton = new QPushButton( i18n( "Change Preview Image" ), this );
+ m_pSetPreviewImageButton->setEnabled( false );
+ hl->addWidget( m_pSetPreviewImageButton );
+
+ hl = new QHBoxLayout( vl );
+ hl->addStretch( 1 );
+ m_pApplyChanges = new QPushButton( i18n( "&Apply" ), this );
+ m_pApplyChanges->setEnabled( false );
+ hl->addWidget( m_pApplyChanges );
+ m_pCancelChanges = new QPushButton( i18n( "&Cancel" ), this );
+ m_pCancelChanges->setEnabled( false );
+ hl->addWidget( m_pCancelChanges );
+
+ connect( m_pName, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotTextChanged( const QString& ) ) );
+ connect( m_pDescription, SIGNAL( textChanged( ) ),
+ SLOT( slotTextChanged( ) ) );
+ connect( m_pKeywords, SIGNAL( textChanged( ) ),
+ SLOT( slotTextChanged( ) ) );
+ connect( m_pSetPreviewImageButton, SIGNAL( clicked( ) ),
+ SLOT( slotPreviewClicked( ) ) );
+ connect( m_pPart, SIGNAL( modified( ) ),
+ SLOT( slotTextChanged( ) ) );
+ connect( m_pApplyChanges, SIGNAL( clicked( ) ), SLOT( slotApplyClicked( ) ) );
+ connect( m_pCancelChanges, SIGNAL( clicked( ) ), SLOT( slotCancelClicked( ) ) );
+ vl->addStretch( 1 );
+}
+
+PMLibraryEntryPreview::~PMLibraryEntryPreview( )
+{
+// delete m_pPart;
+}
+
+bool PMLibraryEntryPreview::showPreview( KURL u, bool readOnly, bool subLib )
+{
+ bool result = false;
+
+ if( u.isLocalFile( ) )
+ {
+ result = saveIfNeeded( );
+
+ m_image.reset( );
+
+ m_subLib = subLib;
+ if( subLib )
+ {
+ // Load the new subLib to preview
+ PMLibraryHandle lib( u.path( ) );
+ m_pName->setText( lib.name( ) );
+ m_pDescription->setText( lib.description( ) );
+ m_pKeywords->setText( "" );
+ m_pPart->setReadWrite( true );
+ m_pPart->setScene( new PMScene( m_pPart ) );
+ m_pContentsPreview->slotRefresh( );
+ m_pPart->setReadWrite( false );
+ }
+ else
+ {
+ // Load the new object to preview
+ PMLibraryObject aux( u );
+
+ m_pName->setText( aux.name( ) );
+ m_pDescription->setText( aux.description( ) );
+ m_pKeywords->setText( aux.keywords( ) );
+ if( aux.preview( ) )
+ {
+ m_image = aux.preview( )->copy( );
+ }
+ loadObjects( aux.objects( ) );
+ // Save the preview location
+ }
+ m_pKeywordsLabel->setEnabled( !subLib );
+ m_pKeywords->setEnabled( !subLib );
+ m_pContentsLabel->setEnabled( !subLib );
+ m_pContentsPreview->setEnabled( !subLib );
+ setReadOnly( readOnly );
+ setModified( false );
+ m_currentURL = u;
+ }
+ return result;
+}
+
+void PMLibraryEntryPreview::loadObjects( QByteArray* obj )
+{
+
+ m_pPart->setReadWrite( true );
+ m_pPart->setScene( new PMScene( m_pPart ) );
+ if( obj )
+ {
+ PMXMLParser parser( m_pPart, *obj );
+ m_pPart->insertFromParser( i18n( "Object Load" ), &parser, m_pPart->scene( ) );
+ }
+ m_pPart->setReadWrite( false );
+ m_pContentsPreview->slotRefresh( );
+}
+
+void PMLibraryEntryPreview::clearPreview( )
+{
+ saveIfNeeded( );
+ m_pName->setText( "" );
+ m_pDescription->setText( "" );
+ m_pKeywords->setText( "" );
+ m_image.reset( );
+ m_pPart->setReadWrite( true );
+ m_pPart->setScene( new PMScene( m_pPart ) );
+ m_pContentsPreview->slotRefresh( );
+ m_pPart->setReadWrite( false );
+ setReadOnly( true );
+ setModified( false );
+}
+
+void PMLibraryEntryPreview::setReadOnly( bool b )
+{
+ m_readOnly = b;
+ if( b )
+ {
+ m_pName->setReadOnly( true );
+ m_pDescription->setReadOnly( true );
+ m_pKeywords->setReadOnly( true );
+ m_pSetPreviewImageButton->setEnabled( false );
+ m_pPart->setReadWrite( false );
+ }
+ else
+ {
+ m_pName->setReadOnly( false );
+ m_pDescription->setReadOnly( false );
+ if( m_subLib )
+ {
+ m_pKeywords->setReadOnly( true );
+ m_pSetPreviewImageButton->setEnabled( false );
+ m_pPart->setReadWrite( false );
+ }
+ else
+ {
+ m_pKeywords->setReadOnly( false );
+ m_pSetPreviewImageButton->setEnabled( true );
+ m_pPart->setReadWrite( true );
+ }
+ }
+}
+
+void PMLibraryEntryPreview::slotTextChanged( )
+{
+ setModified( true );
+}
+
+void PMLibraryEntryPreview::slotTextChanged( const QString& /* s */)
+{
+ setModified( true );
+}
+
+void PMLibraryEntryPreview::slotPreviewClicked( )
+{
+ KFileDialog dlg( QString::null, "", NULL, "", false );
+
+ dlg.setFilter( "image/jpeg image/gif image/tiff image/png image/x-bmp" );
+ if( dlg.exec( ) == QDialog::Accepted )
+ {
+ m_image.load( dlg.selectedFile( ) );
+ setModified( true );
+ }
+}
+
+void PMLibraryEntryPreview::slotApplyClicked( )
+{
+ saveIfNeeded( true );
+ emit objectChanged( );
+}
+
+void PMLibraryEntryPreview::slotCancelClicked( )
+{
+ setModified( false );
+ showPreview( m_currentURL, m_readOnly, m_subLib );
+}
+
+bool PMLibraryEntryPreview::saveIfNeeded( bool forceSave )
+{
+ if ( m_modified )
+ {
+ // ask if we must save the changes
+ if( forceSave || KMessageBox::questionYesNo( this,
+ i18n( "The object has been modified and not saved.\nDo you wish to save?" ),
+ i18n( "Warning" ), KStdGuiItem::save(), KStdGuiItem::discard() ) == KMessageBox::Yes )
+ {
+ if( m_subLib )
+ {
+ PMLibraryHandle lib( m_currentURL.path( ) );
+ lib.setName( m_pName->text( ) );
+ lib.setDescription( m_pDescription->text( ) );
+ lib.saveLibraryInfo( );
+ }
+ else
+ {
+ PMLibraryObject objToSave;
+ PMObjectList sortedList;
+ PMObject* tmp;
+
+ // First save the text parameters.
+ objToSave.setName( m_pName->text( ) );
+ objToSave.setDescription( m_pDescription->text( ) );
+ objToSave.setKeywords( m_pKeywords->text( ) );
+
+ // Gather the contents of the part.
+ tmp = m_pPart->scene( )->firstChild( );
+ while( tmp )
+ {
+ sortedList.append( tmp );
+ tmp = tmp->nextSibling();
+ }
+
+ // Add them to the object to save.
+ PMObjectDrag drag( m_pPart, sortedList );
+ objToSave.setObjects( drag.encodedData( "application/x-kpovmodeler" ) );
+
+ // Add the preview image
+ objToSave.setPreview( m_image.copy( ) );
+
+ // Finally save the object to a file.
+ kdDebug( 0 ) << m_currentURL.path( ) << "\n";
+ objToSave.save( m_currentURL.path( ) );
+ }
+ setModified( false );
+ return true;
+ }
+ setModified( false );
+ }
+ return false;
+}
+
+void PMLibraryEntryPreview::dragEnterEvent( QDragEnterEvent* event )
+{
+ event->accept( !m_readOnly && QImageDrag::canDecode( event ) );
+}
+
+void PMLibraryEntryPreview::dropEvent( QDropEvent* event )
+{
+ QImage img;
+ if( QImageDrag::decode( event, img ) )
+ {
+ m_image = img;
+ setModified( true );
+ }
+}
+
+void PMLibraryEntryPreview::setModified( bool modified )
+{
+ m_modified = modified;
+ m_pApplyChanges->setEnabled( modified );
+ m_pCancelChanges->setEnabled( modified );
+}
+
+#include "pmlibraryentrypreview.moc"
diff --git a/kpovmodeler/pmlibraryentrypreview.h b/kpovmodeler/pmlibraryentrypreview.h
new file mode 100644
index 00000000..95077299
--- /dev/null
+++ b/kpovmodeler/pmlibraryentrypreview.h
@@ -0,0 +1,119 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLIBRARYOBJECTPREVIEW_H
+#define PMLIBRARYOBJECTPREVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qimage.h>
+
+#include <kurl.h>
+
+class QLabel;
+class QLineEdit;
+class QMultiLineEdit;
+class QPushButton;
+class QFrame;
+class PMPart;
+class PMTreeView;
+
+/**
+ * Preview widget for Library Objects and sub Libs.
+ */
+class PMLibraryEntryPreview: public QWidget
+{
+ Q_OBJECT
+public:
+ /** Constructor */
+ PMLibraryEntryPreview( QWidget *parent );
+ /** Destructor */
+ ~PMLibraryEntryPreview( );
+
+ /**
+ * Called to show the file preview.
+ * @param url The path to the file
+ * @param readOnly Whether the top library is read only
+ * @param subLib Whether this is a sub library to preview
+ * @Return true if the previous file was saved to disk.
+ */
+ bool showPreview( KURL url, bool readOnly, bool subLib );
+ /**
+ * Clears the preview
+ */
+ virtual void clearPreview( );
+
+ /**
+ * Save the object, if needed.
+ * @param forceSave If true don't ask about changes just save them
+ * @Return true if a save was performed.
+ */
+ bool saveIfNeeded( bool forceSave = false );
+
+signals:
+ /** Emitted when the object name has been changed */
+ void objectChanged( );
+
+protected:
+ virtual void dragEnterEvent( QDragEnterEvent* event );
+
+ virtual void dropEvent( QDropEvent* event );
+
+private slots:
+ /** Called when description or keywords are changed */
+ void slotTextChanged( );
+ /** Called when the name is changed */
+ void slotTextChanged( const QString& s );
+ /** Called when the set preview button is clicked */
+ void slotPreviewClicked( );
+ /** Called when the apply button is clicked */
+ void slotApplyClicked( );
+ /** Called when the cancel button is clicked */
+ void slotCancelClicked( );
+
+private:
+ /** Called to load the object tree. */
+ void loadObjects( QByteArray* obj );
+ /** Sets whether the object is read only or not */
+ void setReadOnly( bool b );
+ /** Sets whether the object is modified or not */
+ void setModified( bool modified );
+
+ PMPart* m_pPart;
+ QLineEdit* m_pName;
+ QMultiLineEdit* m_pDescription;
+ QLabel* m_pKeywordsLabel;
+ QMultiLineEdit* m_pKeywords;
+ QLabel* m_pContentsLabel;
+ PMTreeView* m_pContentsPreview;
+ QPushButton* m_pSetPreviewImageButton;
+ QPushButton* m_pApplyChanges;
+ QPushButton* m_pCancelChanges;
+
+ QImage m_image;
+ KURL m_currentURL;
+
+ bool m_modified;
+ bool m_readOnly;
+ bool m_subLib;
+};
+
+#endif
diff --git a/kpovmodeler/pmlibraryhandle.cpp b/kpovmodeler/pmlibraryhandle.cpp
new file mode 100644
index 00000000..7902f789
--- /dev/null
+++ b/kpovmodeler/pmlibraryhandle.cpp
@@ -0,0 +1,395 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlibraryhandle.h"
+#include "pmlibraryobject.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qdom.h>
+#include <qtextstream.h>
+#include <qimage.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+
+#include "pmdebug.h"
+
+PMLibraryHandle::PMLibraryHandle( )
+{
+ setPath( "" );
+ setAuthor( i18n( "Unknown" ) );
+ setName( i18n( "Unknown" ) );
+ m_readOnly = false;
+ m_objects.setAutoDelete( true );
+ m_libraries.setAutoDelete( true );
+}
+
+PMLibraryHandle::PMLibraryHandle( const QString& path )
+{
+ setPath( path );
+ setAuthor( i18n( "Unknown" ) );
+ setName( i18n( "Unknown" ) );
+ m_objects.setAutoDelete( true );
+ m_libraries.setAutoDelete( true );
+ loadLibraryInfo( );
+}
+
+PMLibraryHandle::~PMLibraryHandle( )
+{
+}
+
+void PMLibraryHandle::setName( const QString& name )
+{
+ m_name = name;
+}
+
+void PMLibraryHandle::setPath( const QString& path )
+{
+ m_objects.clear( );
+ m_path = path;
+}
+
+void PMLibraryHandle::setAuthor( const QString& author )
+{
+ m_author = author;
+}
+
+void PMLibraryHandle::setDescription( const QString& description )
+{
+ m_description = description;
+}
+
+void PMLibraryHandle::setReadOnly( const bool rdOnly )
+{
+ m_readOnly = rdOnly;
+}
+
+void PMLibraryHandle::loadLibraryInfo( )
+{
+ // 1. Open the information file (library_index.xml)
+ QFile file( m_path + "/library_index.xml" );
+
+ if( !file.open( IO_ReadOnly ) )
+ {
+ kdError( PMArea ) << "Could not find the library index." << endl;
+ return;
+ }
+
+ // 2. Read the information
+ QDomDocument doc( "KPOVLIBINDEX" );
+ doc.setContent( &file );
+
+ QDomElement e = doc.documentElement( );
+
+ if( e.tagName( ) != "library" )
+ {
+ kdError( PMArea ) << "This doesn't appear to be a library index." << endl;
+ return;
+ }
+
+ // 3. The library entry
+ setName( e.attribute( "name", i18n( "Unknown" ) ) );
+ setAuthor( e.attribute( "author", i18n( "Unknown" ) ) );
+ setDescription( e.attribute( "description", "" ) );
+ if( e.attribute( "readonly", "false" ) == "false" )
+ m_readOnly = false;
+ else
+ m_readOnly = true;
+
+ if( e.attribute( "sublibrary", "false" ) == "false" )
+ m_subLibrary = false;
+ else
+ m_subLibrary = true;
+
+ // 4. The object entries
+ QDomNode n = e.firstChild( );
+ if( !n.isNull( ) )
+ {
+ if( n.isElement( ) )
+ {
+ QDomElement c = n.toElement( );
+ if( c.tagName( ) == "object_list" )
+ {
+ n = n.firstChild( );
+ while( !n.isNull( ) )
+ {
+ c = n.toElement( );
+ if( c.tagName( ) == "object_entry" )
+ {
+ m_objects.insert( c.attribute( "name", i18n( "Unknown" ) ),
+ new QString( c.attribute( "file", "" ) ) );
+ }
+ else if( c.tagName( ) == "library_entry" )
+ {
+ m_libraries.insert( c.attribute( "name", i18n( "Unknown" ) ),
+ new QString( c.attribute( "file", "" ) ) );
+ }
+ n = n.nextSibling( );
+ }
+ }
+ }
+ }
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::createLibrary( )
+{
+ // Test if the library exists.
+ QDir d( m_path );
+
+ if( !d.exists( ) )
+ {
+ // If it doesn't, create it
+ if( !d.mkdir( m_path ) )
+ {
+ return PMLibraryHandle::CouldNotCreateDir;
+ }
+ }
+ else
+ {
+ return PMLibraryHandle::ExistingDir;
+ }
+
+ return saveLibraryInfo( );
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::saveLibraryInfo( )
+{
+ // Save the information to the index
+ QFile file( m_path + "/library_index.xml" );
+ if( !file.open( IO_WriteOnly ) )
+ {
+ return PMLibraryHandle::CouldNotCreateInfo;
+ }
+
+ // Create the XML DOM tree
+ QDomDocument doc( "KPOVLIBINDEX" );
+ QDomElement e = doc.createElement( "library" );
+ e.setAttribute( "name", name( ) );
+ e.setAttribute( "author", author( ) );
+ e.setAttribute( "description", description( ) );
+ if( m_readOnly )
+ e.setAttribute( "readonly", "true" );
+ else
+ e.setAttribute( "readonly", "false" );
+
+ if( m_subLibrary )
+ e.setAttribute( "sublibrary", "true" );
+ else
+ e.setAttribute( "sublibrary", "false" );
+
+ // Add the object list to the tree
+ QDomElement l = doc.createElement( "object_list" );
+ for(QDictIterator<QString> it( m_objects ); it.current( ); ++it )
+ {
+ QDomElement n = doc.createElement( "object_entry" );
+ n.setAttribute( "name", it.currentKey( ) );
+ n.setAttribute( "file", *( it.current( ) ) );
+ l.appendChild( n );
+ }
+ for(QDictIterator<QString> it( m_libraries ); it.current( ); ++it )
+ {
+ QDomElement n = doc.createElement( "library_entry" );
+ n.setAttribute( "name", it.currentKey( ) );
+ n.setAttribute( "file", *( it.current( ) ) );
+ l.appendChild( n );
+ }
+ e.appendChild( l );
+ doc.appendChild( e );
+
+ // Save to the file
+ QTextStream str( &file );
+ str.setEncoding( QTextStream::UnicodeUTF8 );
+ str << doc.toString( );
+ file.close( );
+
+ return PMLibraryHandle::Ok;
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::createNewObject( )
+{
+ /// @todo Need to replace mkdtemp and mkstemps before enabling libs
+ return PMLibraryHandle::CouldNotCreateFile;
+ /*
+ PMLibraryObject aux;
+ QCString s = m_path.latin1( );
+ QString unknownIcon = locate( "data" , "kpovmodeler/questionmark.png" );
+ QImage img;
+ int fh;
+
+ if( m_readOnly )
+ return PMLibraryHandle::ReadOnlyLib;
+
+ aux.setName( i18n( "Empty" ) );
+ aux.setObjects( QByteArray( ) );
+ img.load( unknownIcon, "PNG" );
+ aux.setPreview( img );
+
+ s = s + "/objXXXXXX.kpml";
+ if( ( fh = mkstemps( s.data( ), 5 ) ) < 0 )
+ {
+ // Ooops! Error creating the file.
+ return PMLibraryHandle::CouldNotCreateFile;
+ }
+
+ // Success creating the file
+ close( fh );
+ m_objects.insert( i18n( "Empty" ), new QString( s ) );
+ aux.save( s );
+ saveLibraryInfo( );
+ return PMLibraryHandle::Ok;
+ */
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::addObject( const QString& path, const QString& name )
+{
+ if( m_readOnly )
+ return PMLibraryHandle::ReadOnlyLib;
+
+ m_objects.insert( name, new QString( path ) );
+ saveLibraryInfo( );
+ return PMLibraryHandle::Ok;
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::deleteObject( const QString& objectName )
+{
+ if( m_readOnly )
+ return PMLibraryHandle::ReadOnlyLib;
+
+ if( !m_objects.remove( objectName ) )
+ {
+ PMLibraryHandle::EntryIterator itr( m_objects );
+ for( ; itr.current( ); ++itr )
+ {
+ if( *(itr.current( )) == objectName )
+ {
+ m_objects.remove( itr.currentKey( ) );
+ saveLibraryInfo( );
+ return PMLibraryHandle::Ok;
+ }
+ }
+ }
+ return PMLibraryHandle::NotInLib;
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::createNewSubLibrary( const QString /*subLibName*/ )
+{
+ /// @todo Need to replace mkdtemp and mkstemps before enabling libs
+ return PMLibraryHandle::CouldNotCreateFile;
+ /*
+ char* dirname;
+ QCString s = m_path.latin1( );
+ PMLibraryHandle aux;
+
+ if( m_readOnly )
+ return PMLibraryHandle::ReadOnlyLib;
+
+ if( m_libraries.find( subLibName ) )
+ return PMLibraryHandle::ExistingDir;
+
+ s = s+ "/libXXXXXX";
+ if ( !( dirname = mkdtemp( s.data( ) ) ) )
+ {
+ // Ooops! Error creating the file.
+ return PMLibraryHandle::CouldNotCreateFile;
+ }
+
+ aux.setName( subLibName );
+ aux.setAuthor( author( ) );
+ aux.setPath( dirname );
+ aux.saveLibraryInfo( );
+ m_libraries.insert( subLibName, new QString( dirname ) );
+ saveLibraryInfo( );
+ return PMLibraryHandle::Ok;
+ */
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::addSubLibrary( const QString& path, const QString& subLibName )
+{
+ if( m_readOnly )
+ return PMLibraryHandle::ReadOnlyLib;
+
+ m_libraries.insert( subLibName, new QString( path ) );
+ saveLibraryInfo( );
+ return PMLibraryHandle::Ok;
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::deleteSubLibrary( const QString& subLibName )
+{
+ if( m_readOnly )
+ return PMLibraryHandle::ReadOnlyLib;
+
+ if( !m_libraries.remove( subLibName ) )
+ {
+ PMLibraryHandle::EntryIterator itr( m_libraries );
+ for( ; itr.current( ); ++itr )
+ {
+ if( *(itr.current( )) == subLibName )
+ {
+ m_libraries.remove( itr.currentKey( ) );
+ saveLibraryInfo( );
+ return PMLibraryHandle::Ok;
+ }
+ }
+ }
+ return PMLibraryHandle::NotInLib;
+}
+
+PMLibraryHandle::PMResult PMLibraryHandle::changeParentLibrary( const QString& parentPath )
+{
+ if( m_readOnly )
+ return PMLibraryHandle::ReadOnlyLib;
+
+ QString newPath = parentPath + "/" + m_path.section( '/', -1 );
+ PMLibraryHandle::EntryIterator itr( m_libraries );
+ for( ; itr.current( ); ++itr )
+ {
+ PMLibraryHandle lib = PMLibraryHandle( *itr.current( ) );
+ lib.changeParentLibrary( newPath );
+ m_libraries.replace( itr.currentKey( ), new QString( newPath + "/" + lib.path( ) ) );
+ }
+
+ PMLibraryHandle::EntryIterator objItr( m_objects );
+ for( ; objItr.current( ); ++objItr )
+ {
+ QString test = newPath + "/" + objItr.current( )->section( '/', -1 );
+ m_objects.replace( objItr.currentKey( ), new QString( newPath + "/" + objItr.current( )->section( '/', -1 ) ) );
+ }
+
+ saveLibraryInfo( );
+ m_path = newPath;
+ return PMLibraryHandle::Ok;
+}
+
+PMLibraryHandle::EntryIterator* PMLibraryHandle::createObjectIterator( )
+{
+ return new EntryIterator( m_objects );
+}
+
+PMLibraryHandle::EntryIterator* PMLibraryHandle::createSubLibraryIterator( )
+{
+ return new EntryIterator( m_libraries );
+}
+
+void PMLibraryHandle::setSubLibrary( bool isSubLibrary )
+{
+ m_subLibrary = isSubLibrary;
+}
diff --git a/kpovmodeler/pmlibraryhandle.h b/kpovmodeler/pmlibraryhandle.h
new file mode 100644
index 00000000..e906fd11
--- /dev/null
+++ b/kpovmodeler/pmlibraryhandle.h
@@ -0,0 +1,210 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLIBRARYHANDLE_H
+#define PMLIBRARYHANDLE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qdict.h>
+
+class QDomElement;
+
+/**
+ * Class that holds all the information about a specific library.
+ * The class can also create the library if it doesn't exists.
+ *
+ * A library is nothing more than a directory in the file system, and
+ * an index file stored in XML format.
+ *
+ * One library can have one or more sub-libraries. Sub-libraries can
+ * only contain the entries of object files and more sub-libraries.
+ *
+ */
+class PMLibraryHandle
+{
+public:
+ enum PMResult { Ok, CouldNotCreateDir, ExistingDir,
+ CouldNotCreateInfo, ReadOnlyLib,
+ CouldNotCreateFile, NotInLib };
+
+ /**
+ * Iterator for the objects in the library
+ */
+ typedef QDictIterator<QString> EntryIterator;
+
+ /**
+ * Constructor for an empty library
+ */
+ PMLibraryHandle( );
+
+ /**
+ * Constructor for a given directory.
+ */
+ PMLibraryHandle( const QString& path );
+
+ /**
+ * Destructor
+ */
+ ~PMLibraryHandle( );
+ /**
+ * Returns the library's name
+ */
+ QString name( ) const { return m_name; }
+
+ /**
+ * Returns the library's path
+ */
+ QString path( ) const { return m_path; }
+
+ /**
+ * Returns the library's author
+ */
+ QString author( ) const { return m_author; }
+
+ /**
+ * Returns the library's description
+ */
+ QString description( ) const { return m_description; }
+
+ /**
+ * Sets the library's name
+ */
+ void setName( const QString& name );
+
+ /**
+ * Sets the library's path
+ */
+ void setPath( const QString& path );
+
+ /**
+ * Sets the library's author
+ */
+ void setAuthor( const QString& author );
+
+ /**
+ * Sets the library's description
+ */
+ void setDescription( const QString& description );
+
+ /**
+ * Sets the library's erad only status
+ */
+ void setReadOnly( const bool rdonly = true );
+
+ /**
+ * Save the library's information file.
+ */
+ PMLibraryHandle::PMResult saveLibraryInfo( );
+
+ /**
+ * Create the library's information file.
+ */
+ PMLibraryHandle::PMResult createLibrary( );
+
+ /**
+ * Append a new object to the library.
+ * Returns PMLibraryHandle::Ok if successful or the reason of failure.
+ */
+ PMLibraryHandle::PMResult createNewObject( );
+ /**
+ * Adds an already existing object to the library
+ * @param path The path for the object
+ * @param name The name of the object
+ * @return PMLibraryHandle::Ok if successful or the reason of failure
+ */
+ PMLibraryHandle::PMResult addObject( const QString& path, const QString& name );
+ /**
+ * Deletes an object out of the library. Only removes the entry from the library
+ * doesn't delete the objects file
+ * @param objectName The name of the object ( or objects path ) to delete
+ * @return PMLibraryHandle::Ok if successul or the reason of failure
+ */
+ PMLibraryHandle::PMResult deleteObject( const QString& objectName );
+
+ /**
+ * Create a new sub library.
+ */
+ PMLibraryHandle::PMResult createNewSubLibrary( const QString subLibName );
+ /**
+ * Adds an already existing sub-library to the library
+ * @param path The path for the sub library
+ * @param subLibName The name of the sub library
+ * @return PMLibraryHandle::Ok if successful or the reason of failure
+ */
+ PMLibraryHandle::PMResult addSubLibrary( const QString& path, const QString& name );
+ /**
+ * Deletes a sub library. Only removes the entry from the library
+ * doesn't delete the objects file
+ * @param subLibName The name of the sub library ( or sub libraries path ) to delete
+ * @return PMLibraryHandle::Ok if successul or the reason of failure
+ */
+ PMLibraryHandle::PMResult deleteSubLibrary( const QString& subLibName );
+
+ /**
+ * Returns true if the library is set read-only
+ */
+ bool isReadOnly( ) const { return m_readOnly; }
+
+ /**
+ * Returns an object iterator. It has to be deleted afterwards.
+ */
+ PMLibraryHandle::EntryIterator* createObjectIterator( );
+
+ /**
+ * Returns a sub-library iterator. It has to be deleted afterwards.
+ */
+ PMLibraryHandle::EntryIterator* createSubLibraryIterator( );
+
+ /**
+ * Returns true if the library is a sub library.
+ */
+ bool isSubLibrary( ) const { return m_subLibrary; }
+
+ /**
+ * Changes the parent library if this is a sub library
+ * @param parentPath The new parent path for this library
+ * @return PMLibraryHandle::Ok if successful or the reason for failure
+ */
+ PMLibraryHandle::PMResult changeParentLibrary( const QString& parentPath );
+
+private:
+
+ /**
+ * Makes the library a sub library.
+ */
+ void setSubLibrary( bool isSubLibrary );
+
+
+ void loadLibraryInfo( );
+
+ QString m_name;
+ QString m_path;
+ QString m_author;
+ QString m_description;
+ bool m_readOnly;
+ bool m_subLibrary;
+
+ QDict<QString> m_objects;
+ QDict<QString> m_libraries;
+};
+
+#endif
diff --git a/kpovmodeler/pmlibraryhandleedit.cpp b/kpovmodeler/pmlibraryhandleedit.cpp
new file mode 100644
index 00000000..8c26682d
--- /dev/null
+++ b/kpovmodeler/pmlibraryhandleedit.cpp
@@ -0,0 +1,131 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlibraryhandleedit.h"
+
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlineedit.h>
+#include <qtextedit.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+
+#include "pmlineedits.h"
+#include "pmdialogeditbase.h"
+#include "pmlibraryhandle.h"
+
+QSize PMLibraryHandleEdit::s_size = QSize( 600, 400 );
+
+PMLibraryHandleEdit::PMLibraryHandleEdit( PMLibraryHandle* lib, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Create Library" ),
+ Ok | Cancel, Ok )
+{
+ m_pLibrary = lib;
+
+ resize( s_size );
+ QWidget* page = new QWidget( this );
+ setMainWidget( page );
+ QVBoxLayout* vl = new QVBoxLayout( page, KDialog::spacingHint( ) );
+
+ QGridLayout* grid = new QGridLayout( vl, 5, 2 );
+ QLabel* lbl = new QLabel( i18n( "Name: " ), page );
+ m_pNameEdit = new QLineEdit( page );
+ grid->addWidget( lbl, 0, 0 );
+ grid->addWidget( m_pNameEdit, 0, 1 );
+
+ lbl = new QLabel( i18n( "Author: " ), page );
+ m_pAuthorEdit = new QLineEdit( page );
+ grid->addWidget( lbl, 1, 0 );
+ grid->addWidget( m_pAuthorEdit, 1, 1 );
+
+ lbl = new QLabel( i18n( "Description: " ), page );
+ m_pDescriptionEdit = new QTextEdit( page );
+ m_pDescriptionEdit->setMaximumHeight( 120 );
+ grid->addWidget( lbl, 2, 0 );
+ grid->addMultiCellWidget( m_pDescriptionEdit, 2, 3, 1, 1 );
+ grid->setRowStretch( 3, 1 );
+
+ m_pReadOnlyEdit = new QCheckBox( i18n( "Allow changes to the library?" ), page );
+ grid->addMultiCellWidget( m_pReadOnlyEdit, 4, 4, 0, 1 );
+
+ // Load the fields with values
+ m_pNameEdit->setText( lib->name( ) );
+ m_pDescriptionEdit->setText( lib->description( ) );
+ m_pAuthorEdit->setText( lib->author( ) );
+ m_pReadOnlyEdit->setChecked( !lib->isReadOnly( ) );
+
+ // Setup the signals
+ connect( m_pNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotEditsChanged( const QString& ) ) );
+ connect( m_pAuthorEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotEditsChanged( const QString& ) ) );
+ connect( m_pDescriptionEdit, SIGNAL( textChanged( ) ), SLOT( slotDescriptionChanged( ) ) );
+ connect( m_pReadOnlyEdit, SIGNAL( clicked( ) ), SLOT( slotReadOnlyChanged( ) ) );
+
+ // On startup you can only cancel
+ enableButtonOK( false );
+}
+
+void PMLibraryHandleEdit::slotReadOnlyChanged( )
+{
+ enableButtonOK( true );
+}
+
+void PMLibraryHandleEdit::slotEditsChanged( const QString& /*str*/ )
+{
+ enableButtonOK( true );
+}
+
+void PMLibraryHandleEdit::slotDescriptionChanged( )
+{
+ enableButtonOK( true );
+}
+
+void PMLibraryHandleEdit::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+ cfg->writeEntry( "LibraryHandleEditSize", s_size );
+}
+
+void PMLibraryHandleEdit::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+
+ QSize defaultSize( 300, 200 );
+ s_size = cfg->readSizeEntry( "LibraryHandleEditSize", &defaultSize );
+}
+
+void PMLibraryHandleEdit::resizeEvent( QResizeEvent* ev )
+{
+ s_size = ev->size( );
+}
+
+void PMLibraryHandleEdit::slotOk( )
+{
+ m_pLibrary->setName( m_pNameEdit->text( ) );
+ m_pLibrary->setAuthor( m_pAuthorEdit->text( ) );
+ m_pLibrary->setDescription( m_pDescriptionEdit->text( ) );
+ m_pLibrary->setReadOnly( !m_pReadOnlyEdit->isChecked( ) );
+
+ accept( );
+}
+
+#include "pmlibraryhandleedit.moc"
diff --git a/kpovmodeler/pmlibraryhandleedit.h b/kpovmodeler/pmlibraryhandleedit.h
new file mode 100644
index 00000000..d0f53bb2
--- /dev/null
+++ b/kpovmodeler/pmlibraryhandleedit.h
@@ -0,0 +1,66 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLIBRARYHANDLEEDIT_H
+#define PMLIBRARYHANDLEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+
+class QLineEdit;
+class QTextEdit;
+class QListBox;
+class QCheckBox;
+class PMLibraryHandle;
+
+/**
+ * This class provides a dialog to edit the definitions of a library.
+ */
+class PMLibraryHandleEdit: public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Construct a dialog to edit the properties of lib. The library will be
+ * modified only if Ok is pressed.
+ */
+ PMLibraryHandleEdit( PMLibraryHandle* lib, QWidget *parent = NULL, const char* name = NULL );
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+ static QSize s_size;
+
+private slots:
+ void slotOk( );
+ void slotEditsChanged( const QString& );
+ void slotDescriptionChanged( );
+ void slotReadOnlyChanged( );
+ void resizeEvent( QResizeEvent *ev );
+
+private:
+ PMLibraryHandle* m_pLibrary;
+ QLineEdit* m_pNameEdit;
+ QLineEdit* m_pAuthorEdit;
+ QTextEdit* m_pDescriptionEdit;
+ QCheckBox* m_pReadOnlyEdit;
+};
+
+#endif
diff --git a/kpovmodeler/pmlibraryiconview.cpp b/kpovmodeler/pmlibraryiconview.cpp
new file mode 100644
index 00000000..9a59fcda
--- /dev/null
+++ b/kpovmodeler/pmlibraryiconview.cpp
@@ -0,0 +1,328 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlibraryiconview.h"
+
+#include <unistd.h>
+
+#include <qstring.h>
+#include <qdir.h>
+
+#include <kurl.h>
+#include <kio/job.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+#include <stdlib.h>
+
+#include "pmlibraryhandle.h"
+#include "pmlibraryobject.h"
+#include "pmdebug.h"
+
+const char* PMLibraryIconDrag::format( int i ) const
+{
+ switch( i )
+ {
+ case 0:
+ return "application/x-qiconlist";
+ break;
+ case 1:
+ return "text/sublib-list";
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
+QByteArray PMLibraryIconDrag::encodedData( const char* mime ) const
+{
+ QByteArray a;
+ if ( QString( mime ) == "application/x-qiconlist" )
+ a = QIconDrag::encodedData( mime );
+ else if ( QString( mime ) == "text/sublib-list" )
+ {
+ QString s , l;
+ for( unsigned i = 0; i < m_paths.count( ); ++i )
+ {
+ if( m_subLibs[i] )
+ l = "true";
+ else
+ l = "false";
+ s += m_paths[i] + "\r" + l + "\n";
+ }
+ a.resize( s.length( ) );
+ memcpy( a.data( ), s.latin1( ), s.length( ) );
+ }
+ return a;
+}
+
+bool PMLibraryIconDrag::canDecode( QMimeSource* e )
+{
+ return e->provides( "application/x-qiconlist" ) ||
+ e->provides( "text/sublib-list" );
+}
+
+bool PMLibraryIconDrag::decode( QMimeSource* e, QStringList& strList, QValueList<bool>& subLibList )
+{
+ QByteArray a = e->encodedData( "text/sublib-list" );
+ if( a.isEmpty( ) )
+ return false;
+
+ QStringList list = QStringList::split( "\n", QString( a ) );
+ for( unsigned i = 0; i < list.count( ); ++i )
+ {
+ strList.append( list[i].section( "\r", 0, 0 ) );
+ if( list[i].section( "\r", 1, 1 ) == "true" )
+ subLibList.append( true );
+ else
+ subLibList.append( false );
+ }
+ return true;
+}
+
+void PMLibraryIconDrag::append( const QIconDragItem &item, const QRect &pr,
+ const QRect &tr, const QString &path, bool isSubLibrary )
+{
+ QIconDrag::append( item, pr, tr );
+ m_paths << path;
+ m_subLibs.append( isSubLibrary );
+}
+
+PMLibraryIconView::PMLibraryIconView( QWidget* parent, const char* name )
+ : KIconView( parent, name )
+{
+ m_pLibrary = NULL;
+ m_pCurrentLibrary = NULL;
+ setSelectionMode( Single );
+ setMode( Execute );
+}
+
+void PMLibraryIconView::setLibrary( PMLibraryHandle* h )
+{
+ m_pLibrary = h;
+ refresh( );
+}
+
+void PMLibraryIconView::refresh( )
+{
+ // Clear all the icons
+ clear( );
+
+ PMLibraryHandle::EntryIterator* it;
+
+ // Scan all the library objects and load them into the view
+ // First let's add the libraries
+ it = m_pLibrary->createSubLibraryIterator( );
+ for( ; it->current( ); ++(*it) )
+ {
+ QString f_name = *( it->current( ) );
+ PMLibraryHandle h( f_name );
+
+ new PMLibraryIconViewItem( this, h.name( ), f_name, true );
+ }
+ delete it;
+
+ // Then the objects
+ it = m_pLibrary->createObjectIterator( );
+ for( ; it->current( ); ++(*it) )
+ {
+ QString f_name = *( it->current( ) );
+ PMLibraryObject obj( f_name );
+
+ if( obj.preview( ) )
+ new PMLibraryIconViewItem( this, obj.name( ), obj.preview( )->copy( ), f_name, false );
+ else
+ new PMLibraryIconViewItem( this, obj.name( ), f_name, false );
+ }
+ delete it;
+}
+
+void PMLibraryIconView::slotDropped( QDropEvent *e, const QValueList<QIconDragItem> & )
+{
+ e->ignore( );
+}
+
+QDragObject* PMLibraryIconView::dragObject( )
+{
+ if ( !currentItem( ) )
+ return 0;
+
+ QPoint orig = viewportToContents( viewport( )->mapFromGlobal( QCursor::pos( ) ) );
+ PMLibraryIconDrag *drag = new PMLibraryIconDrag( viewport( ) );
+ drag->setPixmap( *currentItem( )->pixmap( ),
+ QPoint( currentItem( )->pixmapRect( ).width( ) / 2,
+ currentItem( )->pixmapRect( ).height( ) / 2 ) );
+
+ for ( PMLibraryIconViewItem *item = (PMLibraryIconViewItem*)firstItem( );
+ item; item = ( PMLibraryIconViewItem* )item->nextItem( ) )
+ {
+ if ( item->isSelected( ) )
+ {
+ QIconDragItem id;
+ id.setData( QCString( item->path( ).latin1( ) ) );
+ drag->append( id,
+ QRect( item->pixmapRect( FALSE ).x( ) - orig.x( ),
+ item->pixmapRect( FALSE ).y( ) - orig.y( ),
+ item->pixmapRect( ).width( ),
+ item->pixmapRect( ).height( ) ),
+ QRect( item->textRect( FALSE ).x( ) - orig.x( ),
+ item->textRect( FALSE ).y( ) - orig.y( ),
+ item->textRect().width( ),
+ item->textRect( ).height( ) ),
+ item->path( ),
+ item->isSubLibrary( ) );
+ }
+ }
+ return drag;
+}
+
+PMLibraryIconViewItem::PMLibraryIconViewItem( QIconView *parent, const QString &text, const QString& path, bool isSubLibrary )
+ : KIconViewItem( parent, text )
+{
+ m_path = path;
+ m_isSubLibrary = isSubLibrary;
+}
+
+PMLibraryIconViewItem::PMLibraryIconViewItem( QIconView *parent, const QString &text, const QImage& image, const QString& path, bool isSubLibrary )
+ : KIconViewItem( parent, text, image )
+{
+ m_path = path;
+ m_isSubLibrary = isSubLibrary;
+}
+
+bool PMLibraryIconViewItem::acceptDrop( const QMimeSource *e ) const
+{
+ if ( m_isSubLibrary && e->provides( "text/sublib-list" ) )
+ return true;
+
+ return false;
+}
+
+void PMLibraryIconViewItem::dropped( QDropEvent *e, const QValueList<QIconDragItem> & )
+{
+ QStringList pathList;
+ QValueList<bool> subLibList;
+ if( m_isSubLibrary && PMLibraryIconDrag::decode( e, pathList, subLibList ) )
+ {
+ PMLibraryIconView* source = static_cast<PMLibraryIconView*>( e->source( )->parentWidget( ) );
+ PMLibraryHandle* parentLib = source->library( );
+ PMLibraryHandle newParentLib = PMLibraryHandle( m_path );
+ if ( parentLib->isReadOnly() || newParentLib.isReadOnly() )
+ {
+ e->ignore();
+ return;
+ }
+
+ for( unsigned i = 0; i < pathList.count( ); ++i )
+ {
+ bool success = true;
+ QString path = pathList[i];
+ if( path != ( m_path +"/" + path.section( '/', -1 ) ) )
+ {
+ if( subLibList[i] )
+ {
+ QString newpath = newPath( path, true );
+ if( parentLib->deleteSubLibrary( path ) == PMLibraryHandle::Ok )
+ {
+ PMLibraryHandle lib = PMLibraryHandle( path );
+ if( newParentLib.addSubLibrary( newpath, lib.name() ) == PMLibraryHandle::Ok )
+ {
+ lib.changeParentLibrary( m_path );
+ KIO::move( path, newpath );
+ }
+ else
+ {
+ success = false;
+ parentLib->addSubLibrary( path, lib.name( ) );
+ }
+ }
+ else
+ success = false;
+ }
+ else
+ {
+ QString newpath = newPath( path, false );
+ if( parentLib->deleteObject( path ) == PMLibraryHandle::Ok )
+ {
+ PMLibraryObject obj = PMLibraryObject( path );
+ if( newParentLib.addObject( newpath, obj.name() ) == PMLibraryHandle::Ok )
+ {
+ KIO::move( path, newpath );
+ }
+ else
+ {
+ success = false;
+ parentLib->addObject( path, obj.name( ) );
+ }
+ }
+ else
+ success = false;
+ }
+
+ if( !success )
+ {
+ KMessageBox::error( 0, i18n( "Error moving \"%1\" to \"%2\"" ).arg( path ).arg( m_path ) );
+ e->ignore( );
+ return;
+ }
+ }
+ }
+ e->acceptAction( );
+ source->refresh( );
+ }
+ else
+ {
+ e->ignore( );
+ }
+}
+
+QString PMLibraryIconViewItem::newPath( const QString oldPath, bool /*subLib*/ )
+{
+ /// @todo Need to replace mkdtemp and mkstemps before enabling libs
+ return oldPath;
+ /*
+ QString path = m_path + "/" + oldPath.section( '/', -1 );
+ if( subLib )
+ {
+ QString test = path + "/library_index.xml";
+ if( QFile::exists( test ) )
+ {
+ QCString s = m_path.latin1();
+ s+= "/libXXXXXX";
+ char* dirname = mkdtemp( s.data() );
+ rmdir( dirname );
+ path = dirname;
+ }
+ }
+ else if( QFile::exists( path ) )
+ {
+ // we need to rename it.
+ QCString s = m_path.latin1();
+ s += "/objXXXXXX.kpml";
+ int fh = mkstemps( s.data( ), 5 );
+ close( fh );
+ unlink( s.data() );
+ path = s;
+ }
+
+ return path;
+ */
+}
+
+#include "pmlibraryiconview.moc"
diff --git a/kpovmodeler/pmlibraryiconview.h b/kpovmodeler/pmlibraryiconview.h
new file mode 100644
index 00000000..a30ef529
--- /dev/null
+++ b/kpovmodeler/pmlibraryiconview.h
@@ -0,0 +1,123 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLIBRARYICONVIEW_H
+#define PMLIBRARYICONVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kiconview.h>
+
+class PMLibraryHandle;
+
+/**
+ * This class is the drag and drop object for the icon view
+ */
+class PMLibraryIconDrag : public QIconDrag
+{
+ Q_OBJECT
+public:
+ /** Constructor */
+ PMLibraryIconDrag( QWidget * dragSource, const char* name = 0 ) : QIconDrag( dragSource, name ) {}
+
+ /** @return The ith format, or NULL. */
+ const char* format( int i ) const;
+ /** @return The encoded payload of this object, in the specified MIME format. */
+ QByteArray encodedData( const char* mime ) const;
+ /** @return True if the information in e can be decoded */
+ static bool canDecode( QMimeSource* e );
+ /**
+ * Attempts to decode the data in e
+ * @return True if successful otherwise returns false
+ */
+ static bool decode( QMimeSource* e, QStringList& StrList, QValueList<bool>& subLibList );
+ /** Adds a item to the object */
+ void append( const QIconDragItem &item, const QRect &pr, const QRect &tr, const QString &path, bool subLib );
+
+private:
+ QStringList m_paths;
+ QValueList<bool> m_subLibs;
+};
+
+/**
+ * This class provides a view to browse objects, showing their previews.
+ */
+class PMLibraryIconView: public KIconView
+{
+ Q_OBJECT
+public:
+ PMLibraryIconView( QWidget *parent, const char* name = NULL );
+
+ /**
+ * Set the library base path
+ */
+ void setLibrary( PMLibraryHandle* h );
+ /**
+ * Returns the library in view
+ */
+ PMLibraryHandle* library( ) const { return m_pLibrary; }
+
+public slots:
+ /**
+ * refresh the icon view
+ */
+ void refresh( );
+
+ /** called when an Item is dropped onto the view */
+ void slotDropped( QDropEvent *e, const QValueList<QIconDragItem>& );
+
+protected:
+ /** @return a QDragObject for drag and drop */
+ virtual QDragObject* dragObject( );
+
+private:
+ PMLibraryHandle *m_pLibrary;
+ PMLibraryHandle *m_pCurrentLibrary;
+};
+
+/**
+ * This class holds a library object's icon. It also remembers the path
+ * where the file is.
+ */
+class PMLibraryIconViewItem: public KIconViewItem
+{
+public:
+ PMLibraryIconViewItem( QIconView *parent, const QString& text, const QString& path, bool isSubLibrary );
+ PMLibraryIconViewItem( QIconView *parent, const QString& text, const QImage& image, const QString& path, bool isSubLibrary );
+
+ /** Get the path of the entry */
+ QString path( ) const { return m_path; }
+ /** Is the entry a sublib library? */
+ bool isSubLibrary( ) const { return m_isSubLibrary; }
+ /** Reimplement accept drop to take items */
+ virtual bool acceptDrop( const QMimeSource *mime ) const;
+
+protected:
+ /** Tokes a dropped item */
+ void dropped( QDropEvent *evt, const QValueList<QIconDragItem>& );
+ /** Checks for the existance of oldpath and generates a new path as required */
+ QString newPath( const QString oldPath, bool subLib );
+
+private:
+ QString m_path;
+ bool m_isSubLibrary;
+};
+
+#endif
diff --git a/kpovmodeler/pmlibrarymanager.cpp b/kpovmodeler/pmlibrarymanager.cpp
new file mode 100644
index 00000000..2caeb6e3
--- /dev/null
+++ b/kpovmodeler/pmlibrarymanager.cpp
@@ -0,0 +1,121 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlibrarymanager.h"
+
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kglobal.h>
+
+#include <qfile.h>
+#include <qdir.h>
+
+#include "pmdebug.h"
+
+PMLibraryManager* PMLibraryManager::s_pInstance = 0;
+KStaticDeleter<PMLibraryManager> PMLibraryManager::s_staticDeleter;
+
+PMLibraryHandle* PMLibraryManager::getLibraryHandle( const QString& libraryName )
+{
+ QPtrListIterator<PMLibraryHandle> it( m_libraries );
+
+ for( ; it.current( ); ++it )
+ if( it.current( )->name( ) == libraryName )
+ return it.current( );
+
+ return NULL;
+}
+
+PMLibraryManager::PMLibraryManager( )
+{
+ m_libraries.setAutoDelete( true );
+ scanLibraries( );
+}
+
+PMLibraryManager::~PMLibraryManager( )
+{
+ m_libraries.clear( );
+}
+
+void PMLibraryManager::saveConfig( KConfig* /*cfg*/ )
+{
+}
+
+void PMLibraryManager::restoreConfig( KConfig* /*cfg*/ )
+{
+}
+
+QValueList<QString> PMLibraryManager::availableLibraries( )
+{
+ QValueList<QString> result;
+ QPtrListIterator<PMLibraryHandle> it( m_libraries );
+
+ for( ; it.current( ); ++it )
+ result.push_back( it.current( )->name( ) );
+
+ return result;
+}
+
+PMLibraryManager* PMLibraryManager::theManager( )
+{
+ if( !s_pInstance )
+ s_staticDeleter.setObject( s_pInstance, new PMLibraryManager( ) );
+ return s_pInstance;
+}
+
+void PMLibraryManager::scanLibraries( )
+{
+ QStringList libraryDirectories;
+
+ // Search for sub directories in /usr/share/kpovmodeler/library
+ libraryDirectories = KGlobal::dirs( )->findDirs( "data", "kpovmodeler/library" );
+
+ for( QStringList::Iterator i = libraryDirectories.begin( ); i != libraryDirectories.end( ); ++i )
+ {
+ QDir curDir( *i );
+ curDir.setFilter( QDir::Dirs );
+ QFileInfoListIterator it( *( curDir.entryInfoList( ) ) );
+
+ // For each sub directory
+ QFileInfo* fi;
+ for( ; ( fi = it.current( ) ) != NULL; ++it )
+ {
+ // check for the existance of library_index.xml
+ // If it's there it's a library
+ if( QFile::exists( fi->absFilePath( ) + "/library_index.xml" ) )
+ {
+ // Create the corresponding PMLibraryHandle
+ PMLibraryHandle* h;
+
+ h = new PMLibraryHandle( fi->absFilePath( ) );
+ if( !getLibraryHandle( h->name( ) ) )
+ m_libraries.append( h );
+ else
+ // a library with that name already exists
+ delete h;
+ }
+ }
+ }
+}
+
+void PMLibraryManager::refresh( )
+{
+ // TODO: Manage the list incrementaly so that previouly handed out
+ // PMLibraryHandle pointers are kept valid
+ m_libraries.clear( );
+ scanLibraries( );
+}
diff --git a/kpovmodeler/pmlibrarymanager.h b/kpovmodeler/pmlibrarymanager.h
new file mode 100644
index 00000000..8221ba19
--- /dev/null
+++ b/kpovmodeler/pmlibrarymanager.h
@@ -0,0 +1,97 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLIBRARYMANAGER_H
+#define PMLIBRARYMANAGER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qmap.h>
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <kstaticdeleter.h>
+
+#include "pmlibraryhandle.h"
+
+class KConfig;
+class QDomElement;
+
+/**
+ * Class that maintains the list of available libraries for kpovmodeler
+ *
+ * This class is a singleton, wich means all libraries will be known to
+ * all instances of the application.
+ *
+ * When the class is initialized, the following steps are taken:
+ * 1. The global kpovmodeler library path is scanned for libraries
+ * 2. The users' kpovmodeler library path is also scanned for libraries
+ *
+ * If more than one library has the same name, only the last one will be
+ * accessible.
+ */
+class PMLibraryManager
+{
+
+public:
+ /**
+ * Destructor
+ */
+ ~PMLibraryManager( );
+ /**
+ * Returns the manager instance (singleton)
+ */
+ static PMLibraryManager* theManager( );
+
+ /**
+ * Returns the list of available libraries
+ */
+ QValueList<QString> availableLibraries( );
+
+ /**
+ * Returns the handle for the indicated library
+ */
+ PMLibraryHandle* getLibraryHandle( const QString& libraryName );
+
+ /**
+ * Refreshes the list of libraries.
+ * WARNING: This function invalidates all previously given PMLibraryHandle pointers
+ */
+ void refresh( );
+
+ void saveConfig( KConfig* cfg );
+ void restoreConfig( KConfig* cfg );
+
+private:
+
+ /**
+ * Constructor
+ */
+ PMLibraryManager( );
+
+ void scanLibraries( );
+
+ QPtrList< PMLibraryHandle > m_libraries;
+
+ static PMLibraryManager* s_pInstance;
+ static KStaticDeleter<PMLibraryManager> s_staticDeleter;
+};
+
+#endif
diff --git a/kpovmodeler/pmlibraryobject.cpp b/kpovmodeler/pmlibraryobject.cpp
new file mode 100644
index 00000000..e84ba9e1
--- /dev/null
+++ b/kpovmodeler/pmlibraryobject.cpp
@@ -0,0 +1,331 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlibraryobject.h"
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qdom.h>
+#include <qbuffer.h>
+#include <qimage.h>
+
+#include <karchive.h>
+#include <kurl.h>
+#include <ktar.h>
+#include <kfilterdev.h>
+
+#include <stdlib.h>
+
+#include "pmdebug.h"
+
+PMLibraryObject::PMLibraryObject( )
+{
+ m_previewLoaded = false;
+ m_objectsLoaded = false;
+ m_preview = NULL;
+ m_objects = NULL;
+ m_data = NULL;
+ m_name = QString::null;
+ m_description = QString::null;
+ m_keywords = QString::null;
+}
+
+PMLibraryObject::PMLibraryObject( KURL u )
+{
+ m_previewLoaded = false;
+ m_objectsLoaded = false;
+ m_preview = NULL;
+ m_objects = NULL;
+ m_data = new KTar( u.path( ), "application/x-gzip" );
+ loadLibraryInfo( );
+}
+
+PMLibraryObject::~PMLibraryObject( )
+{
+ delete m_data;
+ if( m_previewLoaded )
+ delete m_preview;
+ if( m_objectsLoaded )
+ delete m_objects;
+}
+
+void PMLibraryObject::loadLibraryInfo( )
+{
+ if( m_data )
+ {
+ m_data->open( IO_ReadOnly );
+ // Position in the root of the file
+ const KArchiveDirectory* root = m_data->directory( );
+ if( !root )
+ return;
+
+ // Find the object info
+ const KArchiveEntry* entry = root->entry( "objectinfo.xml" );
+ if( entry && entry->isFile( ) )
+ {
+ QBuffer buffer( ( ( KArchiveFile* )entry )->data( ) );
+ buffer.open( IO_ReadOnly );
+
+ QDomDocument doc( "OBJECTINFO" );
+ doc.setContent( &buffer );
+
+ QDomElement e = doc.documentElement( );
+ m_name = e.attribute( "name", "empty" );
+
+ QDomNode c = e.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ // Description information
+ if( ce.tagName( ) == "description" )
+ {
+ QDomText te = ce.firstChild( ).toText( );
+ m_description = te.nodeValue( );
+ }
+ // Keywords information
+ else if( ce.tagName( ) == "keywords" )
+ {
+ QDomText te = ce.firstChild( ).toText( );
+ m_keywords = te.nodeValue( );
+ }
+ // Extra files list
+ else if( ce.tagName( ) == "file_entries" )
+ {
+ QDomNode entry = ce.firstChild( );
+ while( !entry.isNull( ) )
+ {
+ QDomElement entryElement = entry.toElement( );
+ if( entryElement.tagName( ) == "file" )
+ m_extraFiles.append( entryElement.attribute( "name", "" ) );
+ entry = entry.nextSibling( );
+ }
+ }
+ }
+ c = c.nextSibling( );
+ }
+ }
+ m_data->close( );
+ }
+}
+
+QImage* PMLibraryObject::preview( )
+{
+ if( !m_previewLoaded )
+ {
+ if( m_data )
+ {
+ m_data->open( IO_ReadOnly );
+ // Position in the root of the file
+ const KArchiveDirectory* root = m_data->directory( );
+ if( !root )
+ return NULL;
+
+ // Find the object preview
+ const KArchiveEntry* entry = root->entry( "preview.png" );
+ if( entry && entry->isFile( ) )
+ {
+ QBuffer buffer( ( ( KArchiveFile* )entry )->data( ) );
+ buffer.open( IO_ReadOnly );
+ m_preview = new QImage( buffer.readAll( ) );
+ m_previewLoaded = true;
+ }
+
+ m_data->close( );
+ }
+ }
+ return m_preview;
+}
+
+QByteArray* PMLibraryObject::objects( )
+{
+ if( !m_objectsLoaded )
+ {
+ if( m_data )
+ {
+ m_data->open( IO_ReadOnly );
+ // Position in the root of the file
+ const KArchiveDirectory* root = m_data->directory( );
+ if( !root )
+ return NULL;
+
+ // Find the object info
+ const KArchiveEntry* entry = root->entry( "objectdata.kpm" );
+ if( entry && entry->isFile( ) )
+ {
+ // Transfer the file contents to a QByteArray.
+ // TODO Maybe there is a smarter way of doing this.
+ char buf[256];
+ int nbytes;
+ QIODevice* aux_in = ( ( KArchiveFile* )entry )->device( );
+
+ m_objects = new QByteArray( );
+ QBuffer aux_out( *m_objects );
+
+ aux_in->open( IO_ReadOnly );
+ aux_out.open( IO_WriteOnly );
+ while( !aux_in->atEnd( ) )
+ {
+ nbytes = aux_in->readBlock( buf, 256 );
+ aux_out.writeBlock( buf, nbytes );
+ }
+ delete aux_in;
+ if( m_objects->size( ) != 0 )
+ m_objectsLoaded = true;
+ else
+ {
+ delete m_objects;
+ m_objects = NULL;
+ }
+ }
+ }
+ }
+ return m_objects;
+}
+
+void PMLibraryObject::setName( const QString& str )
+{
+ m_name = str;
+}
+
+void PMLibraryObject::setDescription( const QString& str )
+{
+ m_description = str;
+}
+
+void PMLibraryObject::setKeywords( const QString& str )
+{
+ m_keywords = str;
+}
+
+void PMLibraryObject::setPreview( const QImage& img )
+{
+ if( m_previewLoaded )
+ delete m_preview;
+
+ m_preview = new QImage( img );
+ m_previewLoaded = true;
+}
+
+void PMLibraryObject::setObjects( const QByteArray& obj )
+{
+ if( m_objectsLoaded )
+ delete m_objects;
+
+ m_objects = new QByteArray( obj );
+ m_objects->detach( );
+ m_objectsLoaded = true;
+}
+
+void PMLibraryObject::save( const QString& fileName )
+{
+ // create the library file
+ m_data = new KTar( fileName, "application/x-gzip" );
+ m_data->open( IO_WriteOnly );
+ // save object info
+ saveLibraryInfo( );
+ // save preview
+ savePreview( );
+ // save library objects
+ saveObjects( );
+ m_data->close( );
+}
+
+void PMLibraryObject::saveLibraryInfo( )
+{
+ // Pre-condition for the execution of this method.
+ if( !m_data || !m_data->isOpened( ) )
+ {
+ kdError( PMArea ) << "Trying to save to an unopened data file." << endl;
+ exit( 1 );
+ }
+
+ QBuffer buf;
+
+ // Document type
+ QDomDocument doc( "OBJECTINFO" );
+
+ // The root element for the document has one attribute: name
+ QDomElement root = doc.createElement( "object" );
+ doc.appendChild( root );
+ root.setAttribute( "name", m_name );
+
+ // Inside the root element we add the description node ...
+ QDomElement description = doc.createElement( "description" );
+ root.appendChild( description );
+ description.appendChild( doc.createTextNode( m_description ) );
+
+ // ... and the keywords node ...
+ QDomElement keywords = doc.createElement( "keywords" );
+ root.appendChild( keywords );
+ keywords.appendChild( doc.createTextNode( m_keywords ) );
+
+ // ... and finally the extra files information
+ QDomElement file_list = doc.createElement( "file_list" );
+ root.appendChild( file_list );
+ QStringList::Iterator it = m_extraFiles.begin( );
+ for( ; it != m_extraFiles.end( ); ++it )
+ {
+ QDomElement entry = doc.createElement( "file" );
+ entry.setAttribute( "name", *it );
+ file_list.appendChild( entry );
+ }
+
+ // Write the document to the buffer
+ QByteArray array;
+ QTextStream str( array, IO_WriteOnly );
+ str.setEncoding( QTextStream::UnicodeUTF8 );
+ str << doc.toString( );
+ m_data->writeFile( "objectinfo.xml", "user", "group", array.size( ), array.data( ) );
+}
+
+void PMLibraryObject::savePreview( )
+{
+ // Pre-condition for the execution of this method.
+ if( !m_data || !m_data->isOpened( ) )
+ {
+ kdError( PMArea ) << "Trying to save to an unopened data file." << endl;
+ exit( 1 );
+ }
+
+ QByteArray array;
+ QBuffer iods( array );
+ QImageIO img_io( &iods, "PNG" );
+
+ if( m_previewLoaded )
+ {
+ img_io.setImage( *m_preview );
+ iods.open( IO_WriteOnly );
+ img_io.write( );
+ m_data->writeFile( "preview.png", "user", "group", array.size( ), array.data( ) );
+ }
+}
+
+void PMLibraryObject::saveObjects( )
+{
+ // Pre-condition for the execution of this method.
+ if( !m_data || !m_data->isOpened( ) )
+ {
+ kdError( PMArea ) << "Trying to save to an unopened data file." << endl;
+ exit( 1 );
+ }
+
+ if( m_objectsLoaded )
+ m_data->writeFile( "objectdata.kpm", "user", "group", m_objects->size( ), m_objects->data( ) );
+}
diff --git a/kpovmodeler/pmlibraryobject.h b/kpovmodeler/pmlibraryobject.h
new file mode 100644
index 00000000..e3699c8f
--- /dev/null
+++ b/kpovmodeler/pmlibraryobject.h
@@ -0,0 +1,136 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLIBRARYOBJECT_H
+#define PMLIBRARYOBJECT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+#include <kstaticdeleter.h>
+#include <qstringlist.h>
+
+class KURL;
+class KArchive;
+class KTar;
+class QImage;
+
+/**
+ * This class implements a library object.
+ *
+ * A library object has a name, a textual description, a graphical
+ * preview and the object data, of course. It also contains a collection of
+ * keywords.
+ *
+ * When an instance of PMLibraryObject is created, the objects description is
+ * loaded.
+ *
+ * The graphical preview and the objects data are loaded only if needed.
+ *
+ */
+class PMLibraryObject
+{
+public:
+ /**
+ * Constructor for the library object. Creates an empty library object.
+ */
+ PMLibraryObject( );
+ /**
+ * Constructor for the library object.
+ * Loads the object data from the specified library object file.
+ */
+ PMLibraryObject( KURL u );
+ /**
+ * Destructor
+ */
+ ~PMLibraryObject( );
+
+ /**
+ * Name of the library object.
+ */
+ QString name( ) const { return m_name; }
+ /**
+ * Textual description of the library object.
+ */
+ QString description( ) const { return m_description; }
+ /**
+ * List of keywords for search of the library object.
+ */
+ QString keywords( ) const { return m_keywords; }
+ /**
+ * Graphical Preview.
+ */
+ QImage* preview( );
+ /**
+ * True is the preview has been loaded.
+ */
+ bool isPreviewLoaded( ) const { return m_previewLoaded; }
+ /**
+ * Objects for the scene
+ */
+ QByteArray* objects( );
+ bool areObjectsLoaded( ) const { return m_objectsLoaded; }
+
+ /**
+ * Set the library object name
+ */
+ void setName( const QString& str );
+ /**
+ * Set the library object description
+ */
+ void setDescription( const QString& str );
+ /**
+ * Set the library object keywords
+ */
+ void setKeywords( const QString& str );
+ /**
+ * Set the preview image
+ */
+ void setPreview( const QImage& img );
+ /**
+ * Set the object data
+ */
+ void setObjects( const QByteArray& obj );
+
+ /**
+ * Save the library object to a file
+ */
+ void save( const QString& fileName );
+
+private:
+ void loadLibraryInfo( );
+ void saveLibraryInfo( );
+ void savePreview( );
+ void saveObjects( );
+
+ bool m_previewLoaded;
+ bool m_objectsLoaded;
+ QString m_name;
+ QString m_description;
+ QString m_keywords;
+ KTar* m_data;
+ QImage* m_preview;
+ QByteArray* m_objects;
+ QStringList m_extraFiles;
+};
+
+#endif
diff --git a/kpovmodeler/pmlibraryobjectsearch.cpp b/kpovmodeler/pmlibraryobjectsearch.cpp
new file mode 100644
index 00000000..428da887
--- /dev/null
+++ b/kpovmodeler/pmlibraryobjectsearch.cpp
@@ -0,0 +1,86 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlibraryobject.h"
+#include "pmlibraryentrypreview.h"
+#include "pmlibraryobjectsearch.h"
+#include "pmdialogeditbase.h"
+
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qframe.h>
+
+#include <kurl.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <klistview.h>
+
+PMLibraryObjectSearch::PMLibraryObjectSearch( QWidget* parent ) :
+ QWidget( parent, "" )
+{
+ setMinimumSize( 780, 300 );
+ setMaximumSize( 800, 400 );
+ QVBoxLayout* vl = new QVBoxLayout( this, KDialog::spacingHint( ) );
+
+ // Search parameters
+ QFrame* frame = new QFrame( this );
+ QHBoxLayout* fhl = new QHBoxLayout( frame, KDialog::spacingHint( ) );
+ QGridLayout* grid = new QGridLayout( fhl, 3, 2 );
+ QLabel *lbl = new QLabel( i18n( "Search for:" ), frame );
+ m_pSearch = new QLineEdit( frame );
+ grid->addWidget( lbl, 0, 0 );
+ grid->addWidget( m_pSearch, 0, 1 );
+
+ QVBoxLayout* fvl = new QVBoxLayout( fhl );
+ m_pSearchButton = new QPushButton( i18n( "&Search" ), frame );
+ fvl->addWidget( m_pSearchButton );
+ fvl->addStretch( 1 );
+
+ vl->addWidget( frame );
+
+ // Search results
+ frame = new QFrame( this );
+ QHBoxLayout* hl = new QHBoxLayout( frame, KDialog::spacingHint( ) );
+ m_pFileList = new KListView( frame );
+ m_pFileList->addColumn( i18n( "File" ) );
+ m_pFileList->addColumn( i18n( "Path" ) );
+ m_pFileList->setFullWidth( true );
+ m_pPreview = new PMLibraryEntryPreview( frame );
+ hl->addWidget( m_pFileList, 1 );
+ hl->addWidget( m_pPreview );
+ vl->addWidget( frame );
+
+ // Connect signals and slots
+ connect( m_pSearchButton, SIGNAL( clicked( ) ), SLOT( slotSearchButtonPressed( ) ) );
+}
+
+void PMLibraryObjectSearch::slotSearchButtonPressed( )
+{
+// QStringList::Iterator it( s_libraryPath );
+ // For each of the defined libraries
+ //
+ // Open recursively each library file
+ // Check if any of the strings contains the search words
+ // If it does add to the list
+}
+
+#include "pmlibraryobjectsearch.moc"
diff --git a/kpovmodeler/pmlibraryobjectsearch.h b/kpovmodeler/pmlibraryobjectsearch.h
new file mode 100644
index 00000000..2ef5b07a
--- /dev/null
+++ b/kpovmodeler/pmlibraryobjectsearch.h
@@ -0,0 +1,55 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLIBRARYOBJECTSEARCH_H
+#define PMLIBRARYOBJECTSEARCH_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+
+class QLineEdit;
+class QListBox;
+class QPushButton;
+class PMLibraryEntryPreview;
+class KListView;
+
+/**
+ * Search widget for Library Objects.
+ * It also provides drag. If the user doesn't have a clear idea
+ * where the objects he wants are, this is the dialog to use.
+ */
+class PMLibraryObjectSearch: public QWidget
+{
+ Q_OBJECT
+public:
+ PMLibraryObjectSearch( QWidget *parent );
+
+private slots:
+ void slotSearchButtonPressed( );
+
+private:
+ QLineEdit* m_pSearch;
+ QPushButton* m_pSearchButton;
+ KListView* m_pFileList;
+ PMLibraryEntryPreview* m_pPreview;
+};
+
+#endif
diff --git a/kpovmodeler/pmlight.cpp b/kpovmodeler/pmlight.cpp
new file mode 100644
index 00000000..b715c7ee
--- /dev/null
+++ b/kpovmodeler/pmlight.cpp
@@ -0,0 +1,1064 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlight.h"
+
+#include "pmxmlhelper.h"
+#include "pmlightedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm3dcontrolpoint.h"
+#include "pmmath.h"
+#include "pmmatrix.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+const PMVector locationDefault = PMVector( 0, 0, 0 );
+const PMColor colorDefault = PMColor( 1.0, 1.0, 1.0 );
+const double radiusDefault = 70.0;
+const double falloffDefault = 70.0;
+const double tightnessDefault = 10;
+const PMVector pointAtDefault = PMVector( 0, 0, 1 );
+const bool parallelDefault = false;
+const PMVector areaAxis1Default = PMVector( 1, 0, 0 );
+const PMVector areaAxis2Default = PMVector( 0, 1, 0 );
+const int areaSize1Default = 3;
+const int areaSize2Default = 3;
+const int adaptiveDefault = 0;
+const bool orientDefault = false;
+const bool jitterDefault = false;
+const int fadePowerDefault = 1;
+const double fadeDistanceDefault = 10.0;
+
+PMViewStructure* PMLight::s_pDefaultPointStructure = 0;
+PMViewStructure* PMLight::s_pDefaultSpotStructure = 0;
+PMViewStructure* PMLight::s_pDefaultCylindricalStructure = 0;
+double PMLight::s_pointLightSize = 0.25;
+int PMLight::s_nCylinderLines = 8;
+int PMLight::s_nSpotLines = 8;
+double PMLight::s_length = 1.0;
+
+PMDefinePropertyClass( PMLight, PMLightProperty );
+PMDefineEnumPropertyClass( PMLight, PMLight::PMLightType, PMTypeProperty );
+PMDefineEnumPropertyClass( PMLight, PMLight::PMAreaType, PMAreaProperty );
+
+PMMetaObject* PMLight::s_pMetaObject = 0;
+PMObject* createNewLight( PMPart* part )
+{
+ return new PMLight( part );
+}
+
+PMLight::PMLight( PMPart* part )
+ : Base( part )
+{
+ m_location = locationDefault;
+ m_color = colorDefault;
+ m_type = PointLight;
+ m_radius = radiusDefault;
+ m_falloff = falloffDefault;
+ m_tightness = tightnessDefault;
+ m_pointAt = pointAtDefault;
+ m_parallel = parallelDefault;
+ m_bAreaLight = false;
+ m_areaType = Rectangular;
+ m_areaAxis1 = areaAxis1Default;
+ m_areaAxis2 = areaAxis2Default;
+ m_areaSize1 = areaSize1Default;
+ m_areaSize2 = areaSize2Default;
+ m_adaptive = adaptiveDefault;
+ m_orient = orientDefault;
+ m_jitter = jitterDefault;
+ m_bFading = false;
+ m_fadeDistance = fadeDistanceDefault;
+ m_fadePower = fadePowerDefault;
+ m_bMediaInteraction = true;
+ m_bMediaAttenuation = true;
+}
+
+PMLight::PMLight( const PMLight& l )
+ : Base( l )
+{
+ m_location = l.m_location;
+ m_color = l.m_color;
+ m_type = l.m_type;
+ m_radius = l.m_radius;
+ m_falloff = l.m_falloff;
+ m_tightness = l.m_tightness;
+ m_pointAt = l.m_pointAt;
+ m_parallel = l.m_parallel;
+ m_bAreaLight = l.m_bAreaLight;
+ m_areaType = l.m_areaType;
+ m_areaAxis1 = l.m_areaAxis1;
+ m_areaAxis2 = l.m_areaAxis2;
+ m_areaSize1 = l.m_areaSize1;
+ m_areaSize2 = l.m_areaSize2;
+ m_adaptive = l.m_adaptive;
+ m_orient = l.m_orient;
+ m_jitter = l.m_jitter;
+ m_bFading = l.m_bFading;
+ m_fadeDistance = l.m_fadeDistance;
+ m_fadePower = l.m_fadePower;
+ m_bMediaInteraction = l.m_bMediaInteraction;
+ m_bMediaAttenuation = l.m_bMediaAttenuation;
+}
+
+PMLight::~PMLight( )
+{
+}
+
+QString PMLight::description( ) const
+{
+ return i18n( "light" );
+}
+
+void PMLight::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "location", m_location.serializeXML( ) );
+ e.setAttribute( "color", m_color.serializeXML( ) );
+
+ switch( m_type )
+ {
+ case SpotLight:
+ e.setAttribute( "lighttype", "spotlight" );
+ break;
+ case CylinderLight:
+ e.setAttribute( "lighttype", "cylinder" );
+ break;
+ case ShadowlessLight:
+ e.setAttribute( "lighttype", "shadowless" );
+ break;
+ case PointLight:
+ e.setAttribute( "lighttype", "point" );
+ break;
+ }
+
+ if( ( m_type == SpotLight ) || ( m_type == CylinderLight ) )
+ {
+ e.setAttribute( "radius", m_radius );
+ e.setAttribute( "falloff", m_falloff );
+ e.setAttribute( "tightness", m_tightness );
+ e.setAttribute( "point_at", m_pointAt.serializeXML( ) );
+ }
+
+ if ( m_parallel )
+ e.setAttribute( "parallel", "1" );
+ else
+ e.setAttribute( "parallel", "0" );
+
+ if( m_bAreaLight )
+ {
+ if ( m_areaType == Rectangular )
+ e.setAttribute( "areatype", "rectangular" );
+ else
+ e.setAttribute( "areatype", "circular" );
+
+ e.setAttribute( "area_light", "1" );
+ e.setAttribute( "area_light_a", m_areaAxis1.serializeXML( ) );
+ e.setAttribute( "area_light_b", m_areaAxis2.serializeXML( ) );
+ e.setAttribute( "area_size_a", m_areaSize1 );
+ e.setAttribute( "area_size_b", m_areaSize2 );
+ e.setAttribute( "adaptive", m_adaptive );
+
+ if( m_orient )
+ e.setAttribute( "orient", "1" );
+ else
+ e.setAttribute( "orient", "0" );
+
+ if( m_jitter )
+ e.setAttribute( "jitter", "1" );
+ else
+ e.setAttribute( "jitter", "0" );
+ }
+ else
+ e.setAttribute( "area_light", "0" );
+
+ if( m_bFading )
+ {
+ e.setAttribute( "fading", "1" );
+ e.setAttribute( "fade_distance" , m_fadeDistance );
+ e.setAttribute( "fade_power", m_fadePower );
+ }
+ else
+ e.setAttribute( "fading", "0" );
+
+ if( m_bMediaInteraction )
+ e.setAttribute( "media_interaction", "1" );
+ else
+ e.setAttribute( "media_interaction", "0" );
+
+ if( m_bMediaAttenuation )
+ e.setAttribute( "media_attenuation", "1" );
+ else
+ e.setAttribute( "media_attenuation", "0" );
+
+ Base::serialize( e, doc );
+}
+
+void PMLight::readAttributes( const PMXMLHelper& h )
+{
+ QString str;
+
+ m_location = h.vectorAttribute( "location", locationDefault );
+ m_color = h.colorAttribute( "color", colorDefault );
+
+ str = h.stringAttribute( "lighttype", "point" );
+ if( str == "point" )
+ m_type = PointLight;
+ else if( str == "spotlight" )
+ m_type = SpotLight;
+ else if( str == "cylinder" )
+ m_type = CylinderLight;
+ else if( str == "shadowless" )
+ m_type = ShadowlessLight;
+ else
+ m_type = PointLight;
+
+ if( ( m_type == SpotLight ) || ( m_type == CylinderLight ) )
+ {
+ m_radius = h.doubleAttribute( "radius", radiusDefault );
+ m_falloff = h.doubleAttribute( "falloff", falloffDefault );
+ m_tightness = h.doubleAttribute( "tightness", tightnessDefault );
+ m_pointAt = h.vectorAttribute( "point_at", pointAtDefault );
+ }
+
+ m_parallel = h.boolAttribute( "parallel", parallelDefault );
+
+ m_bAreaLight = h.boolAttribute( "area_light", false );
+ if( m_bAreaLight )
+ {
+ str = h.stringAttribute( "areatype", "rectangular" );
+ if ( str == "circular" )
+ m_areaType = Circular;
+ else
+ m_areaType = Rectangular;
+
+ m_areaAxis1 = h.vectorAttribute( "area_light_a", areaAxis1Default );
+ m_areaAxis2 = h.vectorAttribute( "area_light_b", areaAxis2Default );
+ m_areaSize1 = h.intAttribute( "area_size_a", areaSize1Default );
+ m_areaSize2 = h.intAttribute( "area_size_b", areaSize2Default );
+ m_adaptive = h.intAttribute( "adaptive", adaptiveDefault );
+ m_orient = h.boolAttribute( "orient", orientDefault );
+ m_jitter = h.boolAttribute( "jitter", jitterDefault );
+ }
+ m_bFading = h.boolAttribute( "fading", false );
+ if( m_bFading )
+ {
+ m_fadeDistance = h.doubleAttribute( "fade_distance", fadeDistanceDefault );
+ m_fadePower = h.intAttribute( "fade_power", m_fadePower );
+ }
+ m_bMediaInteraction = h.boolAttribute( "media_interaction", true );
+ m_bMediaAttenuation = h.boolAttribute( "media_attenuation", true );
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMLight::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Light", Base::metaObject( ),
+ createNewLight );
+ PMTypeProperty* p = new PMTypeProperty( "lightType", &PMLight::setLightType,
+ &PMLight::lightType );
+ p->addEnumValue( "PointLight", PointLight );
+ p->addEnumValue( "SpotLight", SpotLight );
+ p->addEnumValue( "CylinderLight", CylinderLight );
+ p->addEnumValue( "ShadowlessLight", ShadowlessLight );
+ s_pMetaObject->addProperty( p );
+
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "location", &PMLight::setLocation, &PMLight::location ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "color", &PMLight::setColor, &PMLight::color ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "radius", &PMLight::setRadius, &PMLight::radius ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "falloff", &PMLight::setFalloff, &PMLight::falloff ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "tightness", &PMLight::setTightness, &PMLight::tightness ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "pointAt", &PMLight::setPointAt, &PMLight::pointAt ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "parallel", &PMLight::setParallel, &PMLight::parallel ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "areaLight", &PMLight::setAreaLight, &PMLight::isAreaLight ) );
+
+ PMAreaProperty* p2 = new PMAreaProperty( "areaType", &PMLight::setAreaType,
+ &PMLight::areaType );
+ p2->addEnumValue( "Rectangular", Rectangular );
+ p2->addEnumValue( "Circular", Circular );
+ s_pMetaObject->addProperty( p2 );
+
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "axis1", &PMLight::setAxis1, &PMLight::axis1 ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "axis2", &PMLight::setAxis2, &PMLight::axis2 ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "adaptive", &PMLight::setAdaptive, &PMLight::adaptive ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "orient", &PMLight::setOrient, &PMLight::orient ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "jitter", &PMLight::setJitter, &PMLight::jitter ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "fading", &PMLight::setFading, &PMLight::fading ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "fadeDistance", &PMLight::setFadeDistance, &PMLight::fadeDistance ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "fadePower", &PMLight::setFadePower, &PMLight::fadePower ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "mediaInteraction", &PMLight::setMediaInteraction,
+ &PMLight::mediaInteraction ) );
+ s_pMetaObject->addProperty(
+ new PMLightProperty( "mediaAttenuation", &PMLight::setMediaAttenuation,
+ &PMLight::mediaAttenuation ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMLight::setLocation( const PMVector& p )
+{
+ if( p != m_location )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLocationID, m_location );
+ m_location = p;
+ m_location.resize( 3 );
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setColor( const PMColor& c )
+{
+ if( c != m_color )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMColorID, m_color );
+ m_color = c;
+ }
+}
+
+void PMLight::setLightType( PMLightType t )
+{
+ if( t != m_type )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMTypeID, m_type );
+ m_type = t;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setRadius( double r )
+{
+ if( !approx( r, m_radius ) )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusID, m_radius );
+ m_radius = r;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setFalloff( double f )
+{
+ if( !approx( f, m_falloff ) )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFalloffID, m_falloff );
+ m_falloff = f;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setTightness( double t )
+{
+ if( !approx( t, m_tightness ) )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMTightnessID, m_tightness );
+ m_tightness = t;
+ }
+}
+
+void PMLight::setPointAt( const PMVector& v )
+{
+ if( !m_pointAt.approxEqual( v ) )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPointAtID, m_pointAt );
+ m_pointAt = v;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setParallel( bool p )
+{
+ if ( p != m_parallel )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMParallelID, m_parallel );
+ m_parallel = p;
+ }
+}
+
+void PMLight::setAreaLight( bool yes )
+{
+ if( yes != m_bAreaLight )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAreaLightID, m_bAreaLight );
+ m_bAreaLight = yes;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setAreaType( PMAreaType at )
+{
+ if ( at != m_areaType )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAreaTypeID, m_areaType );
+ m_areaType = at;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setAxis1( const PMVector& v )
+{
+ if( !m_areaAxis1.approxEqual( v ) )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAreaAxis1ID, m_areaAxis1 );
+ m_areaAxis1 = v;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setAxis2( const PMVector& v )
+{
+ if( !m_areaAxis2.approxEqual( v ) )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAreaAxis2ID, m_areaAxis2 );
+ m_areaAxis2 = v;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setSize1( int s )
+{
+ if( s != m_areaSize1 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAreaSize1ID, m_areaSize1 );
+ m_areaSize1 = s;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setSize2( int s )
+{
+ if( s != m_areaSize2 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAreaSize2ID, m_areaSize2 );
+ m_areaSize2 = s;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setAdaptive( int a )
+{
+ if( a != m_adaptive )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAdaptiveID, m_adaptive );
+ m_adaptive = a;
+ }
+}
+
+void PMLight::setOrient( bool o )
+{
+ if( o != m_orient )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOrientID, m_orient );
+ m_orient = o;
+ setViewStructureChanged( );
+ }
+}
+
+void PMLight::setJitter( bool j )
+{
+ if( j != m_jitter )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMJitterID, m_jitter );
+ m_jitter = j;
+ }
+}
+
+void PMLight::setFading( bool y )
+{
+ if( y != m_bFading )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFadingID, m_bFading );
+ m_bFading = y;
+ }
+}
+
+void PMLight::setFadeDistance( double d )
+{
+ if( !approx( d, m_fadeDistance ) )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFadeDistanceID, m_fadeDistance );
+ m_fadeDistance = d;
+ }
+}
+
+void PMLight::setFadePower( int p )
+{
+ if( p != m_fadePower )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFadePowerID, m_fadePower );
+ m_fadePower = p;
+ }
+}
+
+void PMLight::setMediaInteraction( bool y )
+{
+ if( y != m_bMediaInteraction )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMInteractionID, m_bMediaInteraction );
+ m_bMediaInteraction = y;
+ }
+}
+
+void PMLight::setMediaAttenuation( bool y )
+{
+ if( y != m_bMediaAttenuation )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAttenuationID, m_bMediaAttenuation );
+ m_bMediaAttenuation = y;
+ }
+}
+
+PMDialogEditBase* PMLight::editWidget( QWidget* parent ) const
+{
+ return new PMLightEdit( parent );
+}
+
+void PMLight::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMLocationID:
+ setLocation( data->vectorData( ) );
+ break;
+ case PMColorID:
+ setColor( data->colorData( ) );
+ break;
+ case PMTypeID:
+ setLightType( ( PMLightType ) ( data->intData( ) ) );
+ break;
+ case PMRadiusID:
+ setRadius( data->doubleData( ) );
+ break;
+ case PMFalloffID:
+ setFalloff( data->doubleData( ) );
+ break;
+ case PMTightnessID:
+ setTightness( data->doubleData( ) );
+ break;
+ case PMPointAtID:
+ setPointAt( data->vectorData( ) );
+ break;
+ case PMParallelID:
+ setParallel( data->boolData( ) );
+ break;
+ case PMAreaLightID:
+ setAreaLight( data->boolData( ) );
+ break;
+ case PMAreaTypeID:
+ setAreaType( ( PMAreaType ) ( data->intData( ) ) );
+ break;
+ case PMAreaAxis1ID:
+ setAxis1( data->vectorData( ) );
+ break;
+ case PMAreaAxis2ID:
+ setAxis2( data->vectorData( ) );
+ break;
+ case PMAreaSize1ID:
+ setSize1( data->intData( ) );
+ break;
+ case PMAreaSize2ID:
+ setSize2( data->intData( ) );
+ break;
+ case PMAdaptiveID:
+ setAdaptive( data->intData( ) );
+ break;
+ case PMOrientID:
+ setOrient( data->boolData( ) );
+ break;
+ case PMJitterID:
+ setJitter( data->boolData( ) );
+ break;
+ case PMFadingID:
+ setFading( data->boolData( ) );
+ break;
+ case PMFadeDistanceID:
+ setFadeDistance( data->doubleData( ) );
+ break;
+ case PMFadePowerID:
+ setFadePower( data->intData( ) );
+ break;
+ case PMInteractionID:
+ setMediaInteraction( data->boolData( ) );
+ break;
+ case PMAttenuationID:
+ setMediaAttenuation( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMLight::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+void PMLight::createViewStructure( )
+{
+ if( ( m_type == PointLight ) || ( m_type == ShadowlessLight ) )
+ {
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultPointStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+ else
+ {
+ m_pViewStructure->points( ).resize(
+ defaultPointStructure( )->points( ).size( ) );
+ m_pViewStructure->lines( ) = defaultPointStructure( )->lines( );
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+
+ int i;
+ double c = s_pointLightSize / sqrt( 3.0 );
+ for( i = 0; i < 14; i++ )
+ points[i] = PMPoint( m_location );
+
+ points[0][0] += s_pointLightSize;
+ points[1][0] -= s_pointLightSize;
+ points[2][1] += s_pointLightSize;
+ points[3][1] -= s_pointLightSize;
+ points[4][2] += s_pointLightSize;
+ points[5][2] -= s_pointLightSize;
+
+ for( i = 0; i < 4; i++ )
+ {
+ points[6+2*i][0] += c;
+ points[6+2*i][1] += ( i & 1 ? c : -c );
+ points[6+2*i][2] += ( i & 2 ? c : -c );
+ points[7+2*i][0] -= c;
+ points[7+2*i][1] -= ( i & 1 ? c : -c );
+ points[7+2*i][2] -= ( i & 2 ? c : -c );
+ }
+ }
+ else if( m_type == SpotLight )
+ {
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultSpotStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+ else
+ {
+ m_pViewStructure->points( ).resize(
+ defaultSpotStructure( )->points( ).size( ) );
+ m_pViewStructure->lines( ) = defaultSpotStructure( )->lines( );
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+
+ points[0] = PMPoint( m_location );
+
+ PMVector pointAtVector = m_pointAt - m_location;
+ double pl = pointAtVector.abs( );
+ if( approxZero( pl ) )
+ pointAtVector = PMVector( 0.0, 0.0, 1.0 );
+ else
+ pointAtVector /= pl;
+ PMVector endPoint = pointAtVector.orthogonal( );
+ PMMatrix rotation = PMMatrix::rotation( pointAtVector,
+ 2 * M_PI / s_nSpotLines );
+ double length, r1, r2, a1, a2;
+ length = s_length;
+ a1 = m_radius;
+ a2 = m_falloff;
+ if( a1 < 0 ) a1 = 0;
+ if( a2 < 0 ) a2 = 0;
+ if( a1 > a2 ) a1 = a2;
+ if( a1 >= 89.9 ) a1 = 89.9;
+ if( a2 >= 89.9 ) a2 = 89.9;
+ a1 *= M_PI / 180;
+ a2 *= M_PI / 180;
+ r1 = tan( a1 ) * length;
+ r2 = tan( a2 ) * length;
+
+ if( r2 > length )
+ {
+ double d = length / r2;
+ r1 *= d;
+ r2 *= d;
+ length *= d;
+ }
+
+ endPoint *= r2;
+ double r;
+ if( approxZero( r2 ) )
+ r = 1;
+ else
+ r = r1 / r2;
+
+ PMVector circleCenter = m_location + length * pointAtVector;
+ points[1] = PMPoint( circleCenter + endPoint );
+ points[s_nSpotLines + 1] = PMPoint( circleCenter + endPoint * r );
+
+ int i;
+ for( i = 2; i < ( s_nSpotLines + 1 ); i++ )
+ {
+ endPoint = rotation * endPoint;
+ points[i] = PMPoint( circleCenter + endPoint );
+ points[s_nSpotLines + i] = PMPoint( circleCenter + endPoint * r );
+ }
+ points[s_nSpotLines*2+1] = m_pointAt;
+ }
+ else if( m_type == CylinderLight )
+ {
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultCylindricalStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+ else
+ {
+ m_pViewStructure->points( ).resize(
+ defaultCylindricalStructure( )->points( ).size( ) );
+ m_pViewStructure->lines( ) = defaultCylindricalStructure( )->lines( );
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+
+ points[s_nCylinderLines*4] = PMPoint( m_location );
+ points[s_nCylinderLines*4+1] = PMPoint( m_pointAt );
+
+ PMVector pointAtVector = m_pointAt - m_location;
+ double pl = pointAtVector.abs( );
+ if( approxZero( pl ) )
+ pointAtVector = PMVector( 0.0, 0.0, 1.0 );
+ else
+ pointAtVector /= pl;
+ PMVector endPoint = pointAtVector.orthogonal( );
+ PMMatrix rotation = PMMatrix::rotation( pointAtVector,
+ 2 * M_PI / s_nCylinderLines );
+ double r1, r2;
+ r1 = m_radius / 100;
+ r2 = m_falloff / 100;
+ if( r1 < 0 ) r1 = 0;
+ if( r2 < 0 ) r2 = 0;
+ if( r1 > r2 ) r1 = r2;
+
+ endPoint *= r2;
+ double r;
+ if( approxZero( r2 ) )
+ r = 1;
+ else
+ r = r1 / r2;
+
+ PMVector circleCenter = m_location + s_length * pointAtVector;
+ points[0] = PMPoint( circleCenter + endPoint );
+ points[s_nCylinderLines] = PMPoint( m_location + endPoint );
+ points[2*s_nCylinderLines] = PMPoint( circleCenter + endPoint * r );
+ points[3*s_nCylinderLines] = PMPoint( m_location + endPoint * r );
+
+ int i;
+ for( i = 1; i < s_nCylinderLines; i++ )
+ {
+ endPoint = rotation * endPoint;
+ points[i] = PMPoint( circleCenter + endPoint );
+ points[s_nCylinderLines + i] = PMPoint( m_location + endPoint );
+ points[2*s_nCylinderLines + i] = PMPoint( circleCenter + endPoint * r );
+ points[3*s_nCylinderLines + i] = PMPoint( m_location + endPoint * r );
+ }
+ }
+
+ if( m_bAreaLight )
+ {
+ int s1, s2;
+
+ s1 = m_areaSize1;
+ s2 = m_areaSize2;
+ if( s1 < 1 ) s1 = 1;
+ if( s2 < 1 ) s2 = 1;
+
+ if( ( s1 > 1 ) || ( s2 > 1 ) )
+ {
+ int x, y, h;
+ int ps, ls;
+ PMVector bp;
+
+ PMPointArray& points = m_pViewStructure->points( );
+ PMLineArray& lines = m_pViewStructure->lines( );
+ points.detach( );
+ lines.detach( );
+
+ ps = points.size( );
+ ls = lines.size( );
+ points.resize( ps + s1*s2 );
+ lines.resize( ls + s1*(s2-1) + s2*(s1-1) );
+
+ if( s1 == 1 )
+ {
+ bp = m_location - m_areaAxis2/2;
+ for( y = 0; y < s2; y++ )
+ points[ps + y] = PMPoint( bp + m_areaAxis2
+ * ( (double)y/(double)(s2-1) ) );
+ for( y = 0; y < ( s2-1 ); y++ )
+ lines[ls+y] = PMLine( ps + y, ps + y+1 );
+ }
+ else if( s2 == 1 )
+ {
+ bp = m_location - m_areaAxis1/2;
+ for( x = 0; x < s1; x++ )
+ points[ps + x] = PMPoint( bp + m_areaAxis1
+ * ( (double)x/(double)(s1-1) ) );
+ for( x = 0; x < ( s1-1 ); x++ )
+ lines[ls+x] = PMLine( ps + x, ps + x+1 );
+ }
+ else
+ {
+ bp = m_location - m_areaAxis1/2 - m_areaAxis2/2;
+
+ if ( m_areaType == Rectangular || s1 < 2 || s2 < 2 )
+ {
+ for( x = 0; x < s1; x++ )
+ for( y = 0; y < s2; y++ )
+ points[ps + y*s1 + x] =
+ PMPoint( bp + m_areaAxis1 * ( (double)x/(double)(s1-1) )
+ + m_areaAxis2 * ( (double)y/(double)(s2-1) ) );
+ }
+ else
+ {
+ double stepX = ( 2.0 / (double)(s1-1) );
+ double stepY = ( 2.0 / (double)(s2-1) );
+ double doubleX, doubleY, xSqr, scaleFactor;
+
+ for ( x = 0; x < s1; ++x )
+ {
+ doubleX = ( (double)x * stepX ) - 1.0;
+ xSqr = doubleX * doubleX;
+ for ( y = 0; y < s2; ++y )
+ {
+ doubleY = ( (double)y * stepY ) - 1.0;
+
+ if ( doubleX == 0.0 && doubleY == 0.0 )
+ scaleFactor = 1.0;
+ else
+ {
+ if ( fabs( doubleX ) > fabs( doubleY ) )
+ scaleFactor = fabs( doubleX );
+ else
+ scaleFactor = fabs( doubleY );
+ scaleFactor /= sqrt( xSqr + doubleY * doubleY );
+ }
+
+ points[ps + y*s1 + x] =
+ PMPoint( bp + m_areaAxis1 *
+ ( ( ( doubleX * scaleFactor ) / 2.0 ) + 0.5 )
+ + m_areaAxis2 *
+ ( ( ( doubleY * scaleFactor ) / 2.0 ) + 0.5 ) );
+ }
+ }
+ }
+
+ for( x = 0; x < s1; x++ )
+ {
+ for( y = 0; y < (s2-1); y++ )
+ {
+ h = ps + x + s1*y;
+ lines[ls + x*(s2-1) + y] = PMLine( h, h+s1 );
+ }
+ }
+
+ ls += s1*(s2-1);
+ for( y = 0; y < s2; y++ )
+ {
+ for( x = 0; x < (s1-1); x++ )
+ {
+ h = ps + x + s1*y;
+ lines[ls + y*(s1-1) + x] = PMLine( h, h+1 );
+ }
+ }
+ }
+ }
+ }
+}
+
+PMViewStructure* PMLight::defaultPointStructure( ) const
+{
+ if( !s_pDefaultPointStructure )
+ {
+ s_pDefaultPointStructure = new PMViewStructure( 14, 7 );
+// PMPointArray& points = s_pDefaultPointStructure->points( );
+ PMLineArray& lines = s_pDefaultPointStructure->lines( );
+
+ lines[0] = PMLine( 0, 1 );
+ lines[1] = PMLine( 2, 3 );
+ lines[2] = PMLine( 4, 5 );
+ lines[3] = PMLine( 6, 7 );
+ lines[4] = PMLine( 8, 9 );
+ lines[5] = PMLine( 10, 11 );
+ lines[6] = PMLine( 12, 13 );
+ }
+ return s_pDefaultPointStructure;
+}
+
+PMViewStructure* PMLight::defaultSpotStructure( ) const
+{
+ if( !s_pDefaultSpotStructure )
+ {
+ s_pDefaultSpotStructure = new PMViewStructure( s_nSpotLines * 2 + 2, s_nSpotLines * 3 + 1 );
+// PMPointArray& points = s_pDefaultSpotStructure->points( );
+ PMLineArray& lines = s_pDefaultSpotStructure->lines( );
+
+ int i;
+ for( i = 0; i < s_nSpotLines; i++ )
+ {
+ lines[i] = PMLine( 0, i+1 );
+ lines[s_nSpotLines + i] = PMLine( i+1, i+2 );
+ lines[2*s_nSpotLines + i] = PMLine( s_nSpotLines + i+1,
+ s_nSpotLines + i+2 );
+ }
+ // fix for the last line
+ lines[2*s_nSpotLines - 1] = PMLine( 1, s_nSpotLines );
+ lines[3*s_nSpotLines - 1] = PMLine( s_nSpotLines + 1, s_nSpotLines*2 );
+ lines[3*s_nSpotLines] = PMLine( 0, s_nSpotLines*2 + 1 );
+ }
+ return s_pDefaultSpotStructure;
+}
+
+PMViewStructure* PMLight::defaultCylindricalStructure( ) const
+{
+ if( !s_pDefaultCylindricalStructure )
+ {
+ s_pDefaultCylindricalStructure = new PMViewStructure( s_nCylinderLines * 4 + 2, s_nCylinderLines * 5 + 1 );
+// PMPointArray& points = s_pDefaultCylindricalStructure->points( );
+ PMLineArray& lines = s_pDefaultCylindricalStructure->lines( );
+
+ int i;
+ for( i = 0; i < s_nCylinderLines; i++ )
+ {
+ lines[i] = PMLine( i, i+1 );
+ lines[s_nCylinderLines + i] = PMLine( i + s_nCylinderLines,
+ i + s_nCylinderLines + 1 );
+ lines[2*s_nCylinderLines + i] = PMLine( i + 2*s_nCylinderLines,
+ i + 2*s_nCylinderLines + 1 );
+ lines[3*s_nCylinderLines + i] = PMLine( i + 3*s_nCylinderLines,
+ i + 3*s_nCylinderLines + 1 );
+ lines[4*s_nCylinderLines + i] = PMLine( i, i + s_nCylinderLines );
+ }
+ // fix for some lines
+ lines[s_nCylinderLines-1] = PMLine( 0, s_nCylinderLines - 1 );
+ lines[2*s_nCylinderLines-1] = PMLine( s_nCylinderLines,
+ 2*s_nCylinderLines - 1 );
+ lines[3*s_nCylinderLines-1] = PMLine( 2*s_nCylinderLines,
+ 3*s_nCylinderLines - 1 );
+ lines[4*s_nCylinderLines-1] = PMLine( 3*s_nCylinderLines,
+ 4*s_nCylinderLines - 1 );
+ lines[5*s_nCylinderLines] = PMLine( 4*s_nCylinderLines,
+ 4*s_nCylinderLines + 1 );
+ }
+ return s_pDefaultCylindricalStructure;
+}
+
+void PMLight::controlPoints( PMControlPointList& list )
+{
+ list.append( new PM3DControlPoint( m_location, PMLocationID, i18n( "Location" ) ) );
+ if( ( m_type == SpotLight ) || ( m_type == CylinderLight ) )
+ list.append( new PM3DControlPoint( m_pointAt, PMPointAtID, i18n( "Point at" ) ) );
+}
+
+void PMLight::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMLocationID:
+ setLocation( ( ( PM3DControlPoint* ) p )->point( ) );
+ break;
+ case PMPointAtID:
+ setPointAt( ( ( PM3DControlPoint* ) p )->point( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMLight::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+}
+
+void PMLight::cleanUp( ) const
+{
+ if( s_pDefaultPointStructure )
+ delete s_pDefaultPointStructure;
+ s_pDefaultPointStructure = 0;
+ if( s_pDefaultSpotStructure )
+ delete s_pDefaultSpotStructure;
+ s_pDefaultSpotStructure = 0;
+ if( s_pDefaultCylindricalStructure )
+ delete s_pDefaultCylindricalStructure;
+ s_pDefaultCylindricalStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmlight.h b/kpovmodeler/pmlight.h
new file mode 100644
index 00000000..df40ec0a
--- /dev/null
+++ b/kpovmodeler/pmlight.h
@@ -0,0 +1,372 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLIGHT_H
+#define PMLIGHT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+#include "pmvector.h"
+#include "pmcolor.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray light sources.
+ */
+
+class PMLight : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+public:
+ enum PMLightType { PointLight=0, SpotLight=1, CylinderLight=2, ShadowlessLight=3 };
+ enum PMAreaType { Rectangular=0, Circular=1 };
+ /**
+ * Creates an empty PMLight
+ */
+ PMLight( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMLight( const PMLight& l );
+ /**
+ * deletes the PMLight
+ */
+ virtual ~PMLight( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMLight( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMLightEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmlight" ); }
+
+ /**
+ * Returns the type
+ */
+ PMLightType lightType( ) const { return m_type; }
+ /**
+ * Sets the type
+ */
+ void setLightType( PMLightType t );
+
+ /**
+ * Returns the location
+ */
+ PMVector location( ) const { return m_location; }
+ /**
+ * Sets the location
+ */
+ void setLocation( const PMVector& p );
+
+ /**
+ * Returns the color
+ */
+ PMColor color( ) const { return m_color; }
+ /**
+ * Sets the color
+ */
+ void setColor( const PMColor& c );
+
+ /**
+ * Returns the radius for cylinder and spot lights
+ */
+ double radius( ) const { return m_radius; }
+ /**
+ * Sets the radius for cylinder and spot lights
+ */
+ void setRadius( double r );
+
+ /**
+ * Returns the falloff for cylinder and spot lights
+ */
+ double falloff( ) const { return m_falloff; }
+ /**
+ * Sets the falloff for cylinder and spot lights
+ */
+ void setFalloff( double f );
+
+ /**
+ * Returns the tightness for cylinder and spot lights
+ */
+ double tightness( ) const { return m_tightness; }
+ /**
+ * Sets the tightness for cylinder and spot lights
+ */
+ void setTightness( double r );
+
+ /**
+ * Returns the pointAt point for cylinder and spot lights
+ */
+ PMVector pointAt( ) const { return m_pointAt; }
+ /**
+ * Sets the pointAt for cylinder and spot lights
+ */
+ void setPointAt( const PMVector& p );
+
+ /**
+ * Return true if the light is a parallel light
+ */
+ bool parallel( ) const { return m_parallel; }
+ /**
+ * Sets the parallel light flag
+ */
+ void setParallel( bool p );
+
+ /**
+ * Returns true if the light is a area light
+ */
+ bool isAreaLight( ) const { return m_bAreaLight; }
+ /**
+ * Sets the area light flag
+ */
+ void setAreaLight( bool yes );
+
+ /**
+ * Returns the area light type
+ */
+ PMAreaType areaType( ) const { return m_areaType; }
+ /**
+ * Sets the area light type
+ */
+ void setAreaType( PMAreaType at );
+
+ /**
+ * Returns the axis1 for area lights
+ */
+ PMVector axis1( ) const { return m_areaAxis1; }
+ /**
+ * Sets the axis1 for area lights
+ */
+ void setAxis1( const PMVector& v );
+
+ /**
+ * Returns the axis2 for area lights
+ */
+ PMVector axis2( ) const { return m_areaAxis2; }
+ /**
+ * Sets the axis2 for area lights
+ */
+ void setAxis2( const PMVector& v );
+
+ /**
+ * Returns the size1 for area lights
+ */
+ int size1( ) const { return m_areaSize1; }
+ /**
+ * Sets the size1 for area lights
+ */
+ void setSize1( int s );
+
+ /**
+ * Returns the size2 for area lights
+ */
+ int size2( ) const { return m_areaSize2; }
+ /**
+ * Sets the size2 for area lights
+ */
+ void setSize2( int s );
+
+ /**
+ * Returns the adaptive parameter for area lights
+ */
+ int adaptive( ) const { return m_adaptive; }
+ /**
+ * Sets the adaptive parameter for area lights
+ */
+ void setAdaptive( int s );
+
+ /**
+ * Returns if the area light is orientated
+ */
+ bool orient( ) const { return m_orient; }
+ /**
+ * Sets the orient flag
+ */
+ void setOrient( bool o );
+
+ /**
+ * Returns the jitter parameter for area lights
+ */
+ bool jitter( ) const { return m_jitter; }
+ /**
+ * Sets the jitter parameter for area lights
+ */
+ void setJitter( bool j );
+
+ /**
+ * Returns true if light fading is enabled
+ */
+ bool fading( ) const { return m_bFading; }
+ /**
+ * Enables/Disables light fading
+ */
+ void setFading( bool yes );
+
+ /**
+ * Returns the fading distance
+ */
+ double fadeDistance( ) const { return m_fadeDistance; }
+ /**
+ * Sets the fading distance
+ */
+ void setFadeDistance( double d );
+
+ /**
+ * Returns the fading power
+ */
+ int fadePower( ) const { return m_fadePower; }
+ /**
+ * Sets the fading power
+ */
+ void setFadePower( int p );
+
+ /**
+ * Returns the media interaction flag
+ */
+ bool mediaInteraction( ) const { return m_bMediaInteraction; }
+ /**
+ * Sets the media interaction flag
+ */
+ void setMediaInteraction( bool yes );
+
+ /**
+ * Returns the media attenuation flag
+ */
+ bool mediaAttenuation( ) const { return m_bMediaAttenuation; }
+ /**
+ * Sets the media attenuation flag
+ */
+ void setMediaAttenuation( bool yes );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( ) { return false; }
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const { return 0; }
+
+private:
+ /**
+ * Creates and returns the default view structure for point lights
+ */
+ PMViewStructure* defaultPointStructure( ) const;
+ /**
+ * Creates and returns the default view structure for spot lights
+ */
+ PMViewStructure* defaultSpotStructure( ) const;
+ /**
+ * Creates and returns the default view structure for cylindrical lights
+ */
+ PMViewStructure* defaultCylindricalStructure( ) const;
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMLightMementoID
+ { PMLocationID, PMColorID, PMRadiusID, PMFalloffID, PMTightnessID,
+ PMPointAtID, PMParallelID, PMAreaLightID, PMAreaTypeID, PMAreaAxis1ID,
+ PMAreaAxis2ID, PMAreaSize1ID, PMAreaSize2ID, PMAdaptiveID, PMOrientID,
+ PMJitterID, PMTypeID, PMFadingID, PMFadeDistanceID, PMFadePowerID,
+ PMInteractionID, PMAttenuationID };
+
+ PMLightType m_type;
+ PMVector m_location;
+ PMColor m_color;
+ double m_radius;
+ double m_falloff;
+ double m_tightness;
+ PMVector m_pointAt;
+ bool m_parallel;
+ bool m_bAreaLight;
+ PMAreaType m_areaType;
+ PMVector m_areaAxis1, m_areaAxis2;
+ int m_areaSize1, m_areaSize2;
+ int m_adaptive;
+ bool m_orient;
+ bool m_jitter;
+ bool m_bFading;
+ double m_fadeDistance;
+ int m_fadePower;
+ bool m_bMediaInteraction;
+ bool m_bMediaAttenuation;
+
+ /**
+ * The default view structure for point lights
+ */
+ static PMViewStructure* s_pDefaultPointStructure;
+ /**
+ * The default view structure for spot lights
+ */
+ static PMViewStructure* s_pDefaultSpotStructure;
+ /**
+ * The default view structure for cylindrical lights
+ */
+ static PMViewStructure* s_pDefaultCylindricalStructure;
+
+ /**
+ * The size of the point light for 3d views
+ */
+ static double s_pointLightSize;
+ /**
+ * Number of lines around the cylinder
+ */
+ static int s_nCylinderLines;
+ /**
+ * Number of lines around the spot
+ */
+ static int s_nSpotLines;
+ /**
+ * Length of the spot and cylinder
+ */
+ static double s_length;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmlightedit.cpp b/kpovmodeler/pmlightedit.cpp
new file mode 100644
index 00000000..23f5aa9d
--- /dev/null
+++ b/kpovmodeler/pmlightedit.cpp
@@ -0,0 +1,450 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlightedit.h"
+#include "pmlight.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmcoloredit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+
+#include <klocale.h>
+
+PMLightEdit::PMLightEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMLightEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pLocation = new PMVectorEdit( "x", "y", "z", this );
+ m_pColor = new PMColorEdit( false, this );
+ m_pType = new QComboBox( false, this );
+ m_pType->insertItem( i18n( "Point Light" ) );
+ m_pType->insertItem( i18n( "Spot Light" ) );
+ m_pType->insertItem( i18n( "Cylindrical Light" ) );
+ m_pType->insertItem( i18n( "Shadowless Light" ) );
+
+ m_pRadius = new PMFloatEdit( this );
+ m_pRadius->setValidation( false, 0, true, 90 );
+ m_pRadiusLabel = new QLabel( i18n( "Radius:" ), this );
+
+ m_pFalloff = new PMFloatEdit( this );
+ m_pFalloff->setValidation( false, 0, true, 90 );
+ m_pFalloffLabel = new QLabel( i18n( "Falloff:" ), this );
+
+ m_pTightness = new PMFloatEdit( this );
+ m_pTightness->setValidation( false, 0, true, 90 );
+ m_pTightnessLabel = new QLabel( i18n( "Tightness:" ), this );
+
+ m_pPointAt = new PMVectorEdit( "x", "y", "z", this );
+ m_pPointAtLabel = new QLabel( i18n( "Point at:" ), this );
+
+ m_pParallel = new QCheckBox( i18n( "Parallel" ), this );
+
+ m_pAreaLight = new QCheckBox( i18n( "Area light" ), this );
+
+ m_pAreaTypeLabel = new QLabel( i18n ( "Area type:" ), this );
+ m_pAreaType = new QComboBox( false, this );
+ m_pAreaType->insertItem( i18n( "Rectangular" ) );
+ m_pAreaType->insertItem( i18n( "Circular" ) );
+
+ m_pAxis1 = new PMVectorEdit( "x", "y", "z", this );
+ m_pAxis1Label = new QLabel( i18n( "Axis 1:" ), this );
+ m_pAxis2 = new PMVectorEdit( "x", "y", "z", this );
+ m_pAxis2Label = new QLabel( i18n( "Axis 2:" ), this );
+
+ m_pSize1 = new PMIntEdit( this );
+ m_pSize1->setValidation( true, 1, true, 50 );
+ m_pSize1Label = new QLabel( i18n( "Size 1:" ), this );
+ m_pSize2 = new PMIntEdit( this );
+ m_pSize2->setValidation( true, 1, true, 50 );
+ m_pSize2Label = new QLabel( i18n( "Size 2:" ), this );
+
+ m_pAdaptive = new PMIntEdit( this );
+ m_pAdaptive->setValidation( true, 0, false, 0 );
+ m_pAdaptiveLabel = new QLabel( i18n( "Adaptive:" ), this );
+ m_pOrient = new QCheckBox( i18n( "Orient" ), this );
+ m_pJitter = new QCheckBox( i18n( "Jitter" ), this );
+
+ m_pFading = new QCheckBox( i18n( "Fading" ), this );
+
+ m_pFadeDistance = new PMFloatEdit( this );
+ m_pFadeDistance->setValidation( true, 0, false, 0 );
+ m_pFadeDistanceLabel = new QLabel( i18n( "Fade distance:" ), this );
+
+ m_pFadePower = new PMIntEdit( this );
+ m_pFadePower->setValidation( true, 0, false, 0 );
+ m_pFadePowerLabel = new QLabel( i18n( "Fade power:" ), this );
+
+ m_pMediaInteraction = new QCheckBox( i18n( "Media interaction" ), this );
+ m_pMediaAttenuation = new QCheckBox( i18n( "Media attenuation" ), this );
+
+ QHBoxLayout* hl;
+ QGridLayout* gl;
+
+ gl = new QGridLayout( topLayout( ), 3, 2 );
+ gl->addWidget( new QLabel( i18n( "Location:" ), this ), 0, 0 );
+ gl->addWidget( m_pLocation, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Color:" ), this ), 1, 0, AlignTop );
+ gl->addWidget( m_pColor, 1, 1 );
+ gl->addWidget( new QLabel( i18n( "Type:" ), this ), 2, 0 );
+ hl = new QHBoxLayout( );
+ gl->addLayout( hl, 2, 1 );
+ hl->addWidget( m_pType );
+ hl->addStretch( 1 );
+
+ gl = new QGridLayout( topLayout( ), 4, 2 );
+ gl->addWidget( m_pRadiusLabel, 0, 0 );
+ gl->addWidget( m_pRadius, 0, 1, AlignLeft );
+ gl->addWidget( m_pFalloffLabel, 1, 0 );
+ gl->addWidget( m_pFalloff, 1, 1, AlignLeft );
+ gl->addWidget( m_pTightnessLabel, 2, 0 );
+ gl->addWidget( m_pTightness, 2, 1, AlignLeft );
+ gl->addWidget( m_pPointAtLabel, 3, 0 );
+ gl->addWidget( m_pPointAt, 3, 1 );
+
+ topLayout( )->addWidget( m_pParallel );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 7, 2 );
+ gl->addMultiCellWidget( m_pAreaLight, 0, 0, 0, 1 );
+ gl->addWidget( m_pAreaTypeLabel, 1, 0 );
+ gl->addWidget( m_pAreaType, 1, 1 );
+ gl->addWidget( m_pAxis1Label, 2, 0 );
+ gl->addWidget( m_pAxis1, 2, 1 );
+ gl->addWidget( m_pAxis2Label, 3, 0 );
+ gl->addWidget( m_pAxis2, 3, 1 );
+ gl->addWidget( m_pSize1Label, 4, 0 );
+ gl->addWidget( m_pSize1, 4, 1, AlignLeft );
+ gl->addWidget( m_pSize2Label, 5, 0 );
+ gl->addWidget( m_pSize2, 5, 1, AlignLeft );
+ gl->addWidget( m_pAdaptiveLabel, 6, 0 );
+ gl->addWidget( m_pAdaptive, 6, 1, AlignLeft );
+ hl->addStretch( 1 );
+
+ topLayout( )->addWidget( m_pOrient );
+ topLayout( )->addWidget( m_pJitter );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 3, 2 );
+ gl->addMultiCellWidget( m_pFading, 0, 0, 0, 1 );
+ gl->addWidget( m_pFadeDistanceLabel, 1, 0 );
+ gl->addWidget( m_pFadeDistance, 1, 1 );
+ gl->addWidget( m_pFadePowerLabel, 2, 0 );
+ gl->addWidget( m_pFadePower, 2, 1 );
+ hl->addStretch( 1 );
+
+ topLayout( )->addWidget( m_pMediaInteraction );
+ topLayout( )->addWidget( m_pMediaAttenuation );
+
+ connect( m_pLocation, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pColor, SIGNAL( dataChanged( ) ),
+ SIGNAL( dataChanged( ) ) );
+ connect( m_pType, SIGNAL( activated( int ) ),
+ SLOT( slotTypeActivated( int ) ) );
+ connect( m_pRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFalloff, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pTightness, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPointAt, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pParallel, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAreaLight, SIGNAL( clicked( ) ), SLOT( slotAreaClicked( ) ) );
+ connect( m_pAreaType, SIGNAL( activated ( int ) ), SLOT( slotOrientCheck( ) ) );
+ connect( m_pAxis1, SIGNAL( dataChanged( ) ), SLOT( slotOrientCheck( ) ) );
+ connect( m_pAxis2, SIGNAL( dataChanged( ) ), SLOT( slotOrientCheck( ) ) );
+ connect( m_pSize1, SIGNAL( dataChanged( ) ), SLOT( slotOrientCheck( ) ) );
+ connect( m_pSize2, SIGNAL( dataChanged( ) ), SLOT( slotOrientCheck( ) ) );
+ connect( m_pAdaptive, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOrient, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pJitter, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFading, SIGNAL( clicked( ) ), SLOT( slotFadingClicked( ) ) );
+ connect( m_pFadeDistance, SIGNAL( dataChanged( ) ),
+ SIGNAL( dataChanged( ) ) );
+ connect( m_pFadePower, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMediaInteraction, SIGNAL( clicked( ) ),
+ SIGNAL( dataChanged( ) ) );
+ connect( m_pMediaAttenuation, SIGNAL( clicked( ) ),
+ SIGNAL( dataChanged( ) ) );
+}
+
+void PMLightEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Light" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMLight* ) o;
+
+ m_pLocation->setVector( m_pDisplayedObject->location( ) );
+ m_pLocation->setReadOnly( readOnly );
+ m_pColor->setColor( m_pDisplayedObject->color( ) );
+ m_pColor->setReadOnly( readOnly );
+ m_pType->setCurrentItem( m_pDisplayedObject->lightType( ) );
+ m_pType->setEnabled( !readOnly );
+ slotTypeActivated( m_pDisplayedObject->lightType( ) );
+ m_pRadius->setValue( m_pDisplayedObject->radius( ) );
+ m_pRadius->setReadOnly( readOnly );
+ m_pFalloff->setValue( m_pDisplayedObject->falloff( ) );
+ m_pFalloff->setReadOnly( readOnly );
+ m_pTightness->setValue( m_pDisplayedObject->tightness( ) );
+ m_pTightness->setReadOnly( readOnly );
+ m_pPointAt->setVector( m_pDisplayedObject->pointAt( ) );
+ m_pPointAt->setReadOnly( readOnly );
+ m_pParallel->setChecked( m_pDisplayedObject->parallel( ) );
+ m_pParallel->setEnabled( !readOnly );
+ m_pAreaLight->setChecked( m_pDisplayedObject->isAreaLight( ) );
+ m_pAreaLight->setEnabled( !readOnly );
+ m_pAreaType->setCurrentItem( m_pDisplayedObject->areaType( ) );
+ m_pAreaType->setEnabled( !readOnly );
+ m_pAxis1->setVector( m_pDisplayedObject->axis1( ) );
+ m_pAxis1->setReadOnly( readOnly );
+ m_pAxis2->setVector( m_pDisplayedObject->axis2( ) );
+ m_pAxis2->setReadOnly( readOnly );
+ m_pSize1->setValue( m_pDisplayedObject->size1( ) );
+ m_pSize1->setReadOnly( readOnly );
+ m_pSize2->setValue( m_pDisplayedObject->size2( ) );
+ m_pSize2->setReadOnly( readOnly );
+ m_pAdaptive->setValue( m_pDisplayedObject->adaptive( ) );
+ m_pAdaptive->setReadOnly( readOnly );
+ m_pOrient->setChecked( m_pDisplayedObject->orient( ) );
+ m_pOrient->setEnabled( orientEnabled( readOnly ) );
+ m_pJitter->setChecked( m_pDisplayedObject->jitter( ) );
+ m_pJitter->setEnabled( !readOnly );
+ slotAreaClicked( );
+ m_pFading->setChecked( m_pDisplayedObject->fading( ) );
+ m_pFading->setEnabled( !readOnly );
+ m_pFadeDistance->setValue( m_pDisplayedObject->fadeDistance( ) );
+ m_pFadeDistance->setReadOnly( readOnly );
+ m_pFadePower->setValue( m_pDisplayedObject->fadePower( ) );
+ m_pFadePower->setReadOnly( readOnly );
+ slotFadingClicked( );
+ m_pMediaInteraction->setChecked( m_pDisplayedObject->mediaInteraction( ) );
+ m_pMediaInteraction->setEnabled( !readOnly );
+ m_pMediaAttenuation->setChecked( m_pDisplayedObject->mediaAttenuation( ) );
+ m_pMediaAttenuation->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMLightEdit: Can't display object\n";
+}
+
+void PMLightEdit::saveContents( )
+{
+ int index;
+
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setLocation( m_pLocation->vector( ) );
+ m_pDisplayedObject->setColor( m_pColor->color( ) );
+
+ index = m_pType->currentItem( );
+ if( ( index == 1 ) || ( index == 2 ) )
+ {
+ m_pDisplayedObject->setRadius( m_pRadius->value( ) );
+ m_pDisplayedObject->setFalloff( m_pFalloff->value( ) );
+ m_pDisplayedObject->setTightness( m_pTightness->value( ) );
+ m_pDisplayedObject->setPointAt( m_pPointAt->vector( ) );
+ }
+ m_pDisplayedObject->setLightType( ( PMLight::PMLightType ) index );
+
+ m_pDisplayedObject->setParallel( m_pParallel->isChecked( ) );
+
+ if( m_pAreaLight->isChecked( ) )
+ {
+ m_pDisplayedObject->setAreaType(
+ ( PMLight::PMAreaType ) m_pAreaType->currentItem( ) );
+ m_pDisplayedObject->setAxis1( m_pAxis1->vector( ) );
+ m_pDisplayedObject->setAxis2( m_pAxis2->vector( ) );
+ m_pDisplayedObject->setSize1( m_pSize1->value( ) );
+ m_pDisplayedObject->setSize2( m_pSize2->value( ) );
+ m_pDisplayedObject->setAdaptive( m_pAdaptive->value( ) );
+ m_pDisplayedObject->setOrient( m_pOrient->isChecked( ) );
+ m_pDisplayedObject->setJitter( m_pJitter->isChecked( ) );
+ }
+ m_pDisplayedObject->setAreaLight( m_pAreaLight->isChecked( ) );
+
+ if( m_pFading->isChecked( ) )
+ {
+ m_pDisplayedObject->setFadePower( m_pFadePower->value( ) );
+ m_pDisplayedObject->setFadeDistance( m_pFadeDistance->value( ) );
+ }
+ m_pDisplayedObject->setFading( m_pFading->isChecked( ) );
+
+ m_pDisplayedObject->setMediaInteraction( m_pMediaInteraction->isChecked( ) );
+ m_pDisplayedObject->setMediaAttenuation( m_pMediaAttenuation->isChecked( ) );
+ }
+}
+
+bool PMLightEdit::isDataValid( )
+{
+ int index;
+ if( !m_pLocation->isDataValid( ) ) return false;
+ if( !m_pColor->isDataValid( ) ) return false;
+
+ index = m_pType->currentItem( );
+ if( ( index == 1 ) || ( index == 2 ) )
+ {
+ if( !m_pRadius->isDataValid( ) ) return false;
+ if( !m_pFalloff->isDataValid( ) ) return false;
+ if( !m_pTightness->isDataValid( ) ) return false;
+ if( !m_pPointAt->isDataValid( ) ) return false;
+ }
+ if( m_pAreaLight->isChecked( ) )
+ {
+ if( !m_pAxis1->isDataValid( ) ) return false;
+ if( !m_pAxis2->isDataValid( ) ) return false;
+ if( !m_pSize1->isDataValid( ) ) return false;
+ if( !m_pSize2->isDataValid( ) ) return false;
+ if( !m_pAdaptive->isDataValid( ) ) return false;
+ }
+ if( m_pFading->isChecked( ) )
+ {
+ if( !m_pFadeDistance->isDataValid( ) ) return false;
+ if( !m_pFadePower->isDataValid( ) ) return false;
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMLightEdit::slotTypeActivated( int index )
+{
+ if( ( index == 1 ) || ( index == 2 ) )
+ {
+ m_pRadius->show( );
+ m_pRadiusLabel->show( );
+ m_pFalloff->show( );
+ m_pFalloffLabel->show( );
+ m_pTightness->show( );
+ m_pTightnessLabel->show( );
+ m_pPointAt->show( );
+ m_pPointAtLabel->show( );
+ }
+ else
+ {
+ m_pRadius->hide( );
+ m_pRadiusLabel->hide( );
+ m_pFalloff->hide( );
+ m_pFalloffLabel->hide( );
+ m_pTightness->hide( );
+ m_pTightnessLabel->hide( );
+ m_pPointAt->hide( );
+ m_pPointAtLabel->hide( );
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMLightEdit::slotAreaClicked( )
+{
+ if( m_pAreaLight->isChecked( ) )
+ {
+ m_pAreaTypeLabel->show( );
+ m_pAreaType->show( );
+ m_pAxis1->show( );
+ m_pAxis1Label->show( );
+ m_pAxis2->show( );
+ m_pAxis2Label->show( );
+ m_pSize1->show( );
+ m_pSize1Label->show( );
+ m_pSize2->show( );
+ m_pSize2Label->show( );
+ m_pAdaptive->show( );
+ m_pAdaptiveLabel->show( );
+ m_pOrient->show( );
+ m_pOrient->setEnabled( orientEnabled( !m_pJitter->isEnabled( ) ) );
+ m_pJitter->show( );
+ }
+ else
+ {
+ m_pAreaTypeLabel->hide( );
+ m_pAreaType->hide( );
+ m_pAxis1->hide( );
+ m_pAxis1Label->hide( );
+ m_pAxis2->hide( );
+ m_pAxis2Label->hide( );
+ m_pSize1->hide( );
+ m_pSize1Label->hide( );
+ m_pSize2->hide( );
+ m_pSize2Label->hide( );
+ m_pAdaptive->hide( );
+ m_pAdaptiveLabel->hide( );
+ m_pOrient->hide( );
+ m_pJitter->hide( );
+ }
+
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMLightEdit::slotOrientCheck( )
+{
+ m_pOrient->setEnabled( orientEnabled( !m_pJitter->isEnabled( ) ) );
+ emit dataChanged( );
+}
+
+void PMLightEdit::slotFadingClicked( )
+{
+ if( m_pFading->isChecked( ) )
+ {
+ m_pFadeDistance->show( );
+ m_pFadeDistanceLabel->show( );
+ m_pFadePower->show( );
+ m_pFadePowerLabel->show( );
+ }
+ else
+ {
+ m_pFadeDistance->hide( );
+ m_pFadeDistanceLabel->hide( );
+ m_pFadePower->hide( );
+ m_pFadePowerLabel->hide( );
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+bool PMLightEdit::orientEnabled( bool readOnly )
+{
+ if ( readOnly )
+ return false;
+
+ if ( m_pAreaLight )
+ {
+ if ( m_pAreaType->currentItem( ) == 1 )
+ {
+ int size1 = m_pSize1->value( );
+ int size2 = m_pSize2->value( );
+ if ( size1 > 1 && size2 > 1 && size1 == size2 )
+ {
+ if ( m_pAxis1->vector( ).abs( ) == m_pAxis2->vector( ).abs( ) )
+ return true;
+ }
+ }
+ }
+ m_pOrient->setChecked( false );
+ return false;
+}
+
+#include "pmlightedit.moc"
diff --git a/kpovmodeler/pmlightedit.h b/kpovmodeler/pmlightedit.h
new file mode 100644
index 00000000..0b9b5ffb
--- /dev/null
+++ b/kpovmodeler/pmlightedit.h
@@ -0,0 +1,115 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLIGHTEDIT_H
+#define PMLIGHTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobjectedit.h"
+
+class PMLight;
+class PMVectorEdit;
+class PMColorEdit;
+class QComboBox;
+class PMFloatEdit;
+class PMIntEdit;
+class QLabel;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMLight
+ */
+class PMLightEdit : public PMNamedObjectEdit
+{
+ Q_OBJECT
+ typedef PMNamedObjectEdit Base;
+public:
+ /**
+ * Creates a PMLightEdit with parent and name
+ */
+ PMLightEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+public slots:
+ void slotTypeActivated( int index );
+ void slotAreaClicked( );
+ void slotOrientCheck( );
+ void slotFadingClicked( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ /**
+ * Returns true if orient should be enabled
+ */
+ bool orientEnabled( bool readOnly );
+
+ PMLight* m_pDisplayedObject;
+ PMVectorEdit* m_pLocation;
+ PMColorEdit* m_pColor;
+ QComboBox* m_pType;
+
+ PMFloatEdit* m_pRadius;
+ QLabel* m_pRadiusLabel;
+ PMFloatEdit* m_pFalloff;
+ QLabel* m_pFalloffLabel;
+ PMFloatEdit* m_pTightness;
+ QLabel* m_pTightnessLabel;
+
+ PMVectorEdit* m_pPointAt;
+ QLabel* m_pPointAtLabel;
+ QCheckBox* m_pParallel;
+
+ QCheckBox* m_pAreaLight;
+ QLabel* m_pAreaTypeLabel;
+ QComboBox* m_pAreaType;
+ PMVectorEdit* m_pAxis1;
+ PMIntEdit* m_pSize1;
+ PMVectorEdit* m_pAxis2;
+ PMIntEdit* m_pSize2;
+ QLabel* m_pAxis1Label;
+ QLabel* m_pAxis2Label;
+ QLabel* m_pSize1Label;
+ QLabel* m_pSize2Label;
+ PMIntEdit* m_pAdaptive;
+ QLabel* m_pAdaptiveLabel;
+ QCheckBox* m_pOrient;
+ QCheckBox* m_pJitter;
+
+ QCheckBox* m_pFading;
+ PMFloatEdit* m_pFadeDistance;
+ QLabel* m_pFadeDistanceLabel;
+ PMIntEdit* m_pFadePower;
+ QLabel* m_pFadePowerLabel;
+ QCheckBox* m_pMediaInteraction;
+ QCheckBox* m_pMediaAttenuation;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmlightgroup.cpp b/kpovmodeler/pmlightgroup.cpp
new file mode 100644
index 00000000..e53e0e3b
--- /dev/null
+++ b/kpovmodeler/pmlightgroup.cpp
@@ -0,0 +1,134 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlightgroup.h"
+
+#include <klocale.h>
+#include "pmxmlhelper.h"
+#include "pmlightgroupedit.h"
+#include "pmmemento.h"
+
+PMDefinePropertyClass( PMLightGroup, PMLightGroupProperty );
+
+PMMetaObject* PMLightGroup::s_pMetaObject = 0;
+PMObject* createNewLightGroup( PMPart* part )
+{
+ return new PMLightGroup( part );
+}
+
+PMLightGroup::PMLightGroup( PMPart* part )
+ : Base( part )
+{
+ m_globalLights = false;
+}
+
+PMLightGroup::PMLightGroup( const PMLightGroup& lg )
+ : Base( lg )
+{
+ m_globalLights = lg.m_globalLights;
+}
+
+PMLightGroup::~PMLightGroup( )
+{
+}
+
+QString PMLightGroup::description( ) const
+{
+ return QString( i18n( "light group" ) );
+}
+
+void PMLightGroup::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ if( m_globalLights )
+ e.setAttribute( "global_lights", "1" );
+ else
+ e.setAttribute( "global_lights", "0" );
+
+ Base::serialize( e, doc );
+}
+
+void PMLightGroup::readAttributes( const PMXMLHelper& h )
+{
+ m_globalLights = h.boolAttribute( "global_lights", false );
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMLightGroup::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "LightGroup", Base::metaObject( ),
+ createNewLightGroup );
+
+ s_pMetaObject->addProperty( new PMLightGroupProperty( "globalLights",
+ &PMLightGroup::setGlobalLights, &PMLightGroup::globalLights ) );
+
+ }
+ return s_pMetaObject;
+}
+
+void PMLightGroup::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMLightGroup::setGlobalLights( bool gl )
+{
+ if( gl != m_globalLights )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMGlobalLightsID, m_globalLights );
+ m_globalLights = gl;
+ }
+}
+
+PMDialogEditBase* PMLightGroup::editWidget( QWidget* parent ) const
+{
+ return new PMLightGroupEdit( parent );
+}
+
+void PMLightGroup::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMGlobalLightsID:
+ setGlobalLights( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMCSG::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmlightgroup.h b/kpovmodeler/pmlightgroup.h
new file mode 100644
index 00000000..f488eaf2
--- /dev/null
+++ b/kpovmodeler/pmlightgroup.h
@@ -0,0 +1,98 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLIGHTGROUP_H
+#define PMLIGHTGROUP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+
+/**
+ * Class for povray light group objects.
+ */
+
+class PMLightGroup : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMLightGroup object
+ */
+ PMLightGroup( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMLightGroup( const PMLightGroup& lg );
+
+ /**
+ * deletes the PMLightGroup object
+ */
+ virtual ~PMLightGroup( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMLightGroup( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMLightGroupEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmlightgroup" ); }
+
+ /**
+ * Returns the global lights flag
+ */
+ bool globalLights( ) const { return m_globalLights; }
+ /**
+ * Sets the global lights flag
+ */
+ void setGlobalLights( bool gl );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMGlobalLightsMementoID { PMGlobalLightsID };
+
+ bool m_globalLights;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmlightgroupedit.cpp b/kpovmodeler/pmlightgroupedit.cpp
new file mode 100644
index 00000000..18feffbe
--- /dev/null
+++ b/kpovmodeler/pmlightgroupedit.cpp
@@ -0,0 +1,78 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlightgroupedit.h"
+#include "pmlightgroup.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+PMLightGroupEdit::PMLightGroupEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMLightGroupEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+ m_pGlobalLights = new QCheckBox( i18n( "Global lights" ), this );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( m_pGlobalLights );
+ layout->addStretch( 1 );
+
+ connect( m_pGlobalLights, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMLightGroupEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "LightGroup" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMLightGroup* ) o;
+
+ m_pGlobalLights->setChecked( m_pDisplayedObject->globalLights( ) );
+ m_pGlobalLights->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMLightGroupEdit: Can't display object\n";
+}
+
+void PMLightGroupEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+
+ m_pDisplayedObject->setGlobalLights( m_pGlobalLights->isChecked( ) );
+ }
+}
+
+bool PMLightGroupEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+#include "pmlightgroupedit.moc"
diff --git a/kpovmodeler/pmlightgroupedit.h b/kpovmodeler/pmlightgroupedit.h
new file mode 100644
index 00000000..2701d681
--- /dev/null
+++ b/kpovmodeler/pmlightgroupedit.h
@@ -0,0 +1,64 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLIGHTGROUPEDIT_H
+#define PMLIGHTGROUPEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMLightGroup;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMLightGroup
+ */
+class PMLightGroupEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMLightGroupEdit with parent and name
+ */
+ PMLightGroupEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+protected slots:
+
+private:
+ PMLightGroup* m_pDisplayedObject;
+
+ QCheckBox* m_pGlobalLights;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmline.cpp b/kpovmodeler/pmline.cpp
new file mode 100644
index 00000000..27ff752d
--- /dev/null
+++ b/kpovmodeler/pmline.cpp
@@ -0,0 +1,22 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmline.h"
+
+
+// nothing to be done here at the moment
diff --git a/kpovmodeler/pmline.h b/kpovmodeler/pmline.h
new file mode 100644
index 00000000..399555ea
--- /dev/null
+++ b/kpovmodeler/pmline.h
@@ -0,0 +1,102 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLINES_H
+#define PMLINES_H
+
+#include <qptrlist.h>
+#include <GL/gl.h>
+#include "pmdebug.h"
+
+/**
+ * Line to display with index of start and end point.
+ *
+ * Line of a @ref PMViewStructure. Only the indices in a @ref PMPointArray
+ * are stored.
+ *
+ * Optimized for OpenGL
+ */
+class PMLine
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMLine( )
+ {
+ m_start = 0;
+ m_end = 0;
+ }
+ /**
+ * Creates a line with start point si and end point ei. If si is greater
+ * than ei, si and ei are swapped.
+ */
+ PMLine( const GLuint si, const GLuint ei )
+ { m_start = si; m_end = ei; checkPoints( ); }
+
+ /**
+ * Sets the start point.
+ */
+ void setStartPoint( GLuint si ) { m_start = si; checkPoints( ); }
+ /**
+ * Sets the end point.
+ */
+ void setEndPoint( GLuint ei ) { m_end = ei; checkPoints( ); }
+ /**
+ * Returns the start point.
+ */
+ GLuint startPoint( ) const { return m_start; }
+ /**
+ * Returns the end point.
+ */
+ GLuint endPoint( ) const { return m_end; }
+
+private:
+ /**
+ * Swaps the two points.
+ */
+ void swapPoints( ) { GLuint help = m_start; m_start = m_end; m_end = help; }
+ /**
+ * Checks, if si < ei and swaps the two points if necessary
+ */
+ void checkPoints( )
+ {
+ if( m_start == m_end ) kdError( PMArea ) << "Start index = end index in PMLine" << "\n";
+ if( m_start > m_end ) swapPoints( );
+ }
+ /**
+ * The start and end points (indices!)
+ *
+ * THESE MEMBERS HAVE TO BE THE ONLY ONE (for rendering with OpenGl)
+ */
+ GLuint m_start, m_end;
+};
+
+typedef QPtrListIterator<PMLine> PMLineListIterator;
+
+/**
+ * A list of @ref PMLine objects.
+ *
+ * This class stores all lines of a @ref PMViewStructure. A line is
+ * described by a start and end point. Only the indices in a @ref PMPointArray
+ * are stored.
+ */
+typedef QMemArray<PMLine> PMLineArray;
+
+#endif
diff --git a/kpovmodeler/pmlineedits.cpp b/kpovmodeler/pmlineedits.cpp
new file mode 100644
index 00000000..05124d75
--- /dev/null
+++ b/kpovmodeler/pmlineedits.cpp
@@ -0,0 +1,229 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlineedits.h"
+#include <kmessagebox.h>
+#include <klocale.h>
+
+PMFloatEdit::PMFloatEdit( QWidget* parent, const char* name /*= 0*/ )
+ : QLineEdit( parent, name )
+{
+ m_bCheckLower = false;
+ m_bCheckUpper = false;
+ m_lowerValue = 0;
+ m_upperValue = 0;
+ m_lowerOp = OpGreaterEqual;
+ m_upperOp = OpLessEqual;
+
+ connect( this, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotEditTextChanged( const QString& ) ) );
+}
+
+void PMFloatEdit::setValidation( bool checkLower, double lowerValue,
+ bool checkUpper, double upperValue )
+{
+ m_bCheckLower = checkLower;
+ m_bCheckUpper = checkUpper;
+ m_lowerValue = lowerValue;
+ m_upperValue = upperValue;
+}
+
+void PMFloatEdit::setValidationOperator( ValidationOp l, ValidationOp u )
+{
+ m_lowerOp = l;
+ m_upperOp = u;
+}
+
+bool PMFloatEdit::isDataValid( )
+{
+ bool ok = true;
+ double d;
+ d = text( ).toDouble( &ok );
+
+ if( ok )
+ {
+ if( m_bCheckLower )
+ ok = ok && ( m_lowerOp == OpGreaterEqual ?
+ d >= m_lowerValue : d > m_lowerValue );
+ if( m_bCheckUpper )
+ ok = ok && ( m_upperOp == OpLessEqual ?
+ d <= m_upperValue : d < m_upperValue );
+ if( !ok )
+ {
+ if( m_bCheckLower && m_bCheckUpper )
+ KMessageBox::error( this, i18n( "Please enter a float value "
+ "between %1 and %2" )
+ .arg( m_lowerValue ).arg( m_upperValue ),
+ i18n( "Error" ) );
+ else if( m_bCheckLower )
+ {
+ if( m_lowerOp == OpGreaterEqual )
+ KMessageBox::error( this, i18n( "Please enter a float value "
+ ">= %1" ).arg( m_lowerValue ),
+ i18n( "Error" ) );
+ else
+ KMessageBox::error( this, i18n( "Please enter a float value "
+ "> %1" ).arg( m_lowerValue ),
+ i18n( "Error" ) );
+ }
+ else
+ {
+ if( m_upperOp == OpLessEqual )
+ KMessageBox::error( this, i18n( "Please enter a float value "
+ "<= %1" ).arg( m_upperValue ),
+ i18n( "Error" ) );
+ else
+ KMessageBox::error( this, i18n( "Please enter a float value "
+ "< %1" ).arg( m_upperValue ),
+ i18n( "Error" ) );
+ }
+ }
+ }
+ else
+ {
+ KMessageBox::error( this, i18n( "Please enter a valid float value!" ),
+ i18n( "Error" ) );
+ }
+
+ if( !ok )
+ {
+ setFocus( );
+ selectAll( );
+ }
+ return ok;
+}
+
+double PMFloatEdit::value( ) const
+{
+ return text( ).toDouble( );
+}
+
+void PMFloatEdit::setValue( double d, int precision )
+{
+ QString str;
+
+ str.setNum( d, 'g', precision );
+ setText( str );
+}
+
+void PMFloatEdit::slotEditTextChanged( const QString& /*t*/ )
+{
+ emit dataChanged( );
+}
+
+
+
+
+
+PMIntEdit::PMIntEdit( QWidget* parent, const char* name /*= 0*/ )
+ : QLineEdit( parent, name )
+{
+ m_bCheckLower = false;
+ m_bCheckUpper = false;
+ m_lowerValue = 0;
+ m_upperValue = 0;
+
+ connect( this, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotEditTextChanged( const QString& ) ) );
+}
+
+void PMIntEdit::setValidation( bool checkLower, int lowerValue,
+ bool checkUpper, int upperValue )
+{
+ m_bCheckLower = checkLower;
+ m_bCheckUpper = checkUpper;
+ m_lowerValue = lowerValue;
+ m_upperValue = upperValue;
+}
+
+bool PMIntEdit::isDataValid( )
+{
+ bool ok = true;
+ int i;
+ double d;
+
+ i = text( ).toInt( &ok );
+ if( !ok )
+ {
+ d = text( ).toDouble( &ok );
+ if( ok )
+ {
+ i = ( int ) d;
+ QString str;
+ bool b = signalsBlocked( );
+ blockSignals( true );
+ str.setNum( i );
+ setText( str );
+ blockSignals( b );
+ }
+ }
+
+ if( ok )
+ {
+ if( m_bCheckLower )
+ ok = ok && ( i >= m_lowerValue );
+ if( m_bCheckUpper )
+ ok = ok && ( i <= m_upperValue );
+ if( !ok )
+ {
+ if( m_bCheckLower && m_bCheckUpper )
+ KMessageBox::error( this, i18n( "Please enter an integer value "
+ "between %1 and %2" )
+ .arg( m_lowerValue ).arg( m_upperValue ),
+ i18n( "Error" ) );
+ else if( m_bCheckLower )
+ KMessageBox::error( this, i18n( "Please enter an integer value "
+ ">= %1" ).arg( m_lowerValue ),
+ i18n( "Error" ) );
+ else
+ KMessageBox::error( this, i18n( "Please enter an integer value "
+ "<= %1" ).arg( m_upperValue ),
+ i18n( "Error" ) );
+ }
+ }
+ else
+ {
+ KMessageBox::error( this, i18n( "Please enter a valid integer value!" ),
+ i18n( "Error" ) );
+ }
+
+ if( !ok )
+ {
+ setFocus( );
+ selectAll( );
+ }
+ return ok;
+}
+
+int PMIntEdit::value( ) const
+{
+ return text( ).toInt( );
+}
+
+void PMIntEdit::setValue( int i )
+{
+ QString str;
+
+ str.setNum( i );
+ setText( str );
+}
+
+void PMIntEdit::slotEditTextChanged( const QString& /*t*/ )
+{
+ emit dataChanged( );
+}
+#include "pmlineedits.moc"
diff --git a/kpovmodeler/pmlineedits.h b/kpovmodeler/pmlineedits.h
new file mode 100644
index 00000000..9a12c384
--- /dev/null
+++ b/kpovmodeler/pmlineedits.h
@@ -0,0 +1,133 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PM_LINEEDITS_H
+#define PM_LINEEDITS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qlineedit.h>
+
+/**
+ * Lineedit for float input
+ */
+
+class PMFloatEdit : public QLineEdit
+{
+ Q_OBJECT
+public:
+ enum ValidationOp { OpGreater, OpGreaterEqual,
+ OpLess, OpLessEqual };
+ /**
+ * Simple constructor
+ */
+ PMFloatEdit( QWidget* parent, const char* name = 0 );
+ /**
+ * Sets the validation for the lineedit.
+ *
+ * If checkLower is true, the value has to be >= the lowerValue.
+ *
+ * If checkUpper is true, the value has to be <= the upperValue.
+ *
+ * By default no range check is made.
+ */
+ void setValidation( bool checkLower, double lowerValue,
+ bool checkUpper, double upperValue );
+ /**
+ * Sets the validation operators for the lower and upper value.
+ *
+ * Valid values for lower are OpGreater and OpGreaterEqual,
+ * valid values for upper are OpLess and OpLessEqual.
+ */
+ void setValidationOperator( ValidationOp lower, ValidationOp upper );
+ /**
+ * Returns true, if the text is a valid float in the valid range
+ */
+ bool isDataValid( );
+ /**
+ * Returns the float value
+ */
+ double value( ) const;
+ /**
+ * Sets the value
+ */
+ void setValue( double d, int precision = 5 );
+signals:
+ /**
+ * emitted if the text is changed
+ */
+ void dataChanged( );
+public slots:
+ void slotEditTextChanged( const QString& t );
+private:
+ bool m_bCheckLower, m_bCheckUpper;
+ double m_lowerValue, m_upperValue;
+ ValidationOp m_lowerOp, m_upperOp;
+};
+
+
+/**
+ * Lineedit for int input
+ */
+
+class PMIntEdit : public QLineEdit
+{
+ Q_OBJECT
+public:
+ /**
+ * Simple constructor
+ */
+ PMIntEdit( QWidget* parent, const char* name = 0 );
+ /**
+ * Sets the validation for the lineedit.
+ *
+ * If checkLower is true, the value has to be >= the lowerValue.
+ *
+ * If checkUpper is true, the value has to be <= the upperValue.
+ *
+ * By default no range check is made.
+ */
+ void setValidation( bool checkLower, int lowerValue,
+ bool checkUpper, int upperValue );
+ /**
+ * Returns true, if the text is a valid integer in the valid range
+ */
+ bool isDataValid( );
+ /**
+ * Returns the integer value
+ */
+ int value( ) const;
+ /**
+ * Sets the value
+ */
+ void setValue( int i );
+signals:
+ /**
+ * emitted if the text is changed
+ */
+ void dataChanged( );
+public slots:
+ void slotEditTextChanged( const QString& t );
+private:
+ bool m_bCheckLower, m_bCheckUpper;
+ int m_lowerValue, m_upperValue;
+};
+
+#endif
diff --git a/kpovmodeler/pmlinkedit.cpp b/kpovmodeler/pmlinkedit.cpp
new file mode 100644
index 00000000..a878e02e
--- /dev/null
+++ b/kpovmodeler/pmlinkedit.cpp
@@ -0,0 +1,146 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlinkedit.h"
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+#include "pmdeclare.h"
+#include "pmobjectselect.h"
+
+PMLinkEdit::PMLinkEdit( const QString& declareType,
+ QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ m_declareTypes.append( declareType );
+ init( );
+}
+
+PMLinkEdit::PMLinkEdit( const QStringList& declareTypes,
+ QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ m_declareTypes = declareTypes;
+ init( );
+}
+
+PMLinkEdit::PMLinkEdit( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ init( );
+}
+
+void PMLinkEdit::init( )
+{
+ m_pDeclare = 0;
+ m_pDisplayedObject = 0;
+ m_bReadOnly = false;
+
+ QGridLayout* grid = new QGridLayout( this, 2, 2, 0, KDialog::spacingHint( ) );
+
+ grid->addWidget( new QLabel( i18n( "Prototype:" ), this ), 0, 0 );
+ grid->setColStretch( 0, 0 );
+ grid->setColStretch( 1, 1 );
+ m_pIDEdit = new QLineEdit( this );
+ m_pIDEdit->setReadOnly( true );
+ grid->addWidget( m_pIDEdit, 0, 1 );
+
+ QHBoxLayout* layout = new QHBoxLayout( );
+ grid->addLayout( layout, 1, 1 );
+ m_pSelectButton = new QPushButton( i18n( "Select..." ), this );
+ layout->addWidget( m_pSelectButton );
+ m_pClearButton = new KPushButton( KStdGuiItem::clear(), this );
+ layout->addWidget( m_pClearButton );
+
+ connect( m_pSelectButton, SIGNAL( clicked( ) ), SLOT( slotSelectClicked( ) ) );
+ connect( m_pClearButton, SIGNAL( clicked( ) ), SLOT( slotClearClicked( ) ) );
+}
+
+void PMLinkEdit::setDisplayedObject( PMObject* obj )
+{
+ m_pDisplayedObject = obj;
+ m_pDeclare = obj->linkedObject( );
+ if( m_pDeclare )
+ {
+ m_pIDEdit->setText( m_pDeclare->id( ) );
+ if( !m_bReadOnly )
+ m_pClearButton->setEnabled( true );
+ }
+ else
+ {
+ m_pIDEdit->clear( );
+ if( !m_bReadOnly )
+ m_pClearButton->setEnabled( false );
+ }
+}
+
+void PMLinkEdit::setLinkPossibility( const QString& t )
+{
+ m_declareTypes.clear( );
+ m_declareTypes.append( t );
+}
+
+
+void PMLinkEdit::setLinkPossibilities( const QStringList& t )
+{
+ m_declareTypes = t;
+}
+
+void PMLinkEdit::setReadOnly( bool yes )
+{
+ m_bReadOnly = yes;
+ m_pClearButton->setEnabled( !m_bReadOnly && m_pDeclare );
+ m_pSelectButton->setEnabled( !m_bReadOnly );
+}
+
+void PMLinkEdit::slotSelectClicked( )
+{
+ if( m_pDisplayedObject )
+ {
+ PMObject* obj = 0;
+ int result;
+
+ if( m_declareTypes.count( ) == 1 )
+ result = PMObjectSelect::selectDeclare(
+ m_pDisplayedObject, m_declareTypes.first( ), obj, this );
+ else
+ result = PMObjectSelect::selectDeclare(
+ m_pDisplayedObject, m_declareTypes, obj, this );
+
+ if( ( result == QDialog::Accepted ) && obj )
+ {
+ m_pDeclare = ( PMDeclare* ) obj;
+ m_pIDEdit->setText( m_pDeclare->id( ) );
+ m_pClearButton->setEnabled( true );
+ emit dataChanged( );
+ }
+ }
+}
+
+void PMLinkEdit::slotClearClicked( )
+{
+ m_pDeclare = 0;
+ m_pIDEdit->clear( );
+ emit dataChanged( );
+}
+
+#include "pmlinkedit.moc"
diff --git a/kpovmodeler/pmlinkedit.h b/kpovmodeler/pmlinkedit.h
new file mode 100644
index 00000000..f5abe182
--- /dev/null
+++ b/kpovmodeler/pmlinkedit.h
@@ -0,0 +1,105 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMLINKEDIT_H
+#define PMLINKEDIT_H
+
+#include <qwidget.h>
+#include "pmobject.h"
+#include "pmdeclare.h"
+
+#include <qvaluelist.h>
+
+class QString;
+class QLineEdit;
+class QPushButton;
+
+/**
+ * Edit widget for links with a QLineEdit, a select and a clear button.
+ */
+class PMLinkEdit : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a link edit widget with parent and name.
+ *
+ * Allows the selection of declares of type declareType.
+ */
+ PMLinkEdit( const QString& declareType, QWidget* parent, const char* name = 0 );
+ /**
+ * Creates a link edit widget with parent and name.
+ *
+ * Allows the selection of declares of type declares.
+ */
+ PMLinkEdit( const QStringList& declares, QWidget* parent, const char* name = 0 );
+ /**
+ * Creates a link edit widget with parent and name.
+ */
+ PMLinkEdit( QWidget* parent, const char* name = 0 );
+
+ /**
+ * Sets the displayed object and displays the link
+ */
+ void setDisplayedObject( PMObject* obj );
+ /**
+ * Returns the selected link
+ */
+ PMDeclare* link( ) const { return m_pDeclare; }
+
+ /**
+ * Sets the selection possibilities
+ */
+ void setLinkPossibility( const QString& t );
+ /**
+ * Sets the selection possibilities
+ */
+ void setLinkPossibilities( const QStringList& t );
+
+ /**
+ * Enables or disables read only mode
+ */
+ void setReadOnly( bool yes = true );
+signals:
+ /**
+ * Emitted when the link is changed
+ */
+ void dataChanged( );
+
+public slots:
+ /**
+ * Called when the select button is clicked
+ */
+ void slotSelectClicked( );
+ /**
+ * Called when the clear button is clicked
+ */
+ void slotClearClicked( );
+
+private:
+ void init( );
+ PMDeclare* m_pDeclare;
+ PMObject* m_pDisplayedObject;
+ QStringList m_declareTypes;
+
+ QLineEdit* m_pIDEdit;
+ QPushButton* m_pSelectButton;
+ QPushButton* m_pClearButton;
+ bool m_bReadOnly;
+};
+
+#endif
diff --git a/kpovmodeler/pmlistpattern.cpp b/kpovmodeler/pmlistpattern.cpp
new file mode 100644
index 00000000..299ab4fb
--- /dev/null
+++ b/kpovmodeler/pmlistpattern.cpp
@@ -0,0 +1,469 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlistpattern.h"
+
+#include "pmxmlhelper.h"
+#include "pmlistpatternedit.h"
+#include "pmcompositeobject.h"
+#include "pmmemento.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMListPattern, PMListPatternProperty );
+PMDefineEnumPropertyClass( PMListPattern, PMListPattern::PMListType,
+ PMListTypeProperty );
+
+const PMVector brickSizeDefault = PMVector( 8, 6, 4.5 );
+const double mortarDefault = 0.5;
+const double depthDefault = 0;
+
+PMMetaObject* PMListPattern::s_pMetaObject = 0;
+PMMetaObject* PMColorList::s_pMetaObject = 0;
+PMObject* createNewColorList( PMPart* part )
+{
+ return new PMColorList( part );
+}
+PMMetaObject* PMDensityList::s_pMetaObject = 0;
+PMObject* createNewDensityList( PMPart* part )
+{
+ return new PMDensityList( part );
+}
+PMMetaObject* PMNormalList::s_pMetaObject = 0;
+PMObject* createNewNormalList( PMPart* part )
+{
+ return new PMNormalList( part );
+}
+PMMetaObject* PMPigmentList::s_pMetaObject = 0;
+PMObject* createNewPigmentList( PMPart* part )
+{
+ return new PMPigmentList( part );
+}
+PMMetaObject* PMTextureList::s_pMetaObject = 0;
+PMObject* createNewTextureList( PMPart* part )
+{
+ return new PMTextureList( part );
+}
+
+PMListPattern::PMListPattern( PMPart* part )
+ : Base( part )
+{
+ m_listType = ListPatternChecker;
+ m_brickSize = brickSizeDefault;
+ m_mortar = mortarDefault;
+}
+
+PMListPattern::PMListPattern( const PMListPattern& p )
+ : Base( p )
+{
+ m_listType = p.m_listType;
+ m_brickSize = p.m_brickSize;
+ m_mortar = p.m_mortar;
+}
+
+PMListPattern::~PMListPattern( )
+{
+}
+
+void PMListPattern::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ switch( m_listType )
+ {
+ case ListPatternBrick:
+ e.setAttribute( "listtype", "brick" );
+ break;
+ case ListPatternChecker:
+ e.setAttribute( "listtype", "checker" );
+ break;
+ case ListPatternHexagon:
+ e.setAttribute( "listtype", "hexagon" );
+ break;
+ };
+ e.setAttribute( "bricksize", m_brickSize.serializeXML( ) );
+ e.setAttribute( "mortar", m_mortar );
+ Base::serialize( e, doc );
+}
+
+void PMListPattern::readAttributes( const PMXMLHelper& h )
+{
+ QString str = h.stringAttribute( "listtype", "checker" );
+ if( str == "checker" )
+ m_listType = ListPatternChecker;
+ else if( str == "brick" )
+ m_listType = ListPatternBrick;
+ else
+ m_listType = ListPatternHexagon;
+ m_brickSize = h.vectorAttribute( "bricksize", brickSizeDefault );
+ m_mortar = h.doubleAttribute( "mortar", mortarDefault );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMListPattern::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "ListPattern", Base::metaObject( ) );
+
+ PMListTypeProperty* p = new PMListTypeProperty(
+ "listType", &PMListPattern::setListType,
+ &PMListPattern::listType );
+ p->addEnumValue( QString( "Checker" ), ListPatternChecker );
+ p->addEnumValue( QString( "Brick" ), ListPatternBrick );
+ p->addEnumValue( QString( "Hexagon" ), ListPatternHexagon );
+ s_pMetaObject->addProperty( p );
+
+ s_pMetaObject->addProperty(
+ new PMListPatternProperty( "brickSize", &PMListPattern::setBrickSize,
+ &PMListPattern::brickSize ) );
+ s_pMetaObject->addProperty(
+ new PMListPatternProperty( "mortar", &PMListPattern::setMortar,
+ &PMListPattern::mortar ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMListPattern::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMListPattern::setListType( PMListType l )
+{
+ if( l != m_listType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMListTypeID, m_listType );
+ m_listType = l;
+ }
+}
+
+void PMListPattern::setBrickSize( const PMVector& n )
+{
+ if( n != m_brickSize )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBrickSizeID, m_brickSize );
+ m_brickSize = n;
+ }
+}
+
+void PMListPattern::setMortar( double n )
+{
+ if( n != m_mortar )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMortarID, m_mortar );
+ m_mortar = n;
+ }
+}
+
+PMDialogEditBase* PMListPattern::editWidget( QWidget* parent ) const
+{
+ return new PMListPatternEdit( parent );
+}
+
+void PMListPattern::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMListTypeID:
+ setListType( ( PMListType ) data->intData( ) );
+ break;
+ case PMBrickSizeID:
+ setBrickSize( data->vectorData( ) );
+ break;
+ case PMMortarID:
+ setMortar( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMListPattern::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+
+PMTextureList::PMTextureList( PMPart* part )
+ : Base( part )
+{
+}
+
+PMTextureList::PMTextureList( const PMTextureList& l )
+ : Base( l )
+{
+}
+
+PMTextureList::~PMTextureList( )
+{
+}
+
+PMMetaObject* PMTextureList::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "TextureList", Base::metaObject( ),
+ createNewTextureList );
+ }
+ return s_pMetaObject;
+}
+
+void PMTextureList::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMTextureList::description( ) const
+{
+ return i18n( "texture list" );
+}
+
+PMPigmentList::PMPigmentList( PMPart* part )
+ : Base( part )
+{
+}
+
+PMPigmentList::PMPigmentList( const PMPigmentList& l )
+ : Base( l )
+{
+}
+
+PMPigmentList::~PMPigmentList( )
+{
+}
+
+PMMetaObject* PMPigmentList::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "PigmentList", Base::metaObject( ),
+ createNewPigmentList );
+ }
+ return s_pMetaObject;
+}
+
+void PMPigmentList::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMPigmentList::description( ) const
+{
+ return i18n( "pigment list" );
+}
+
+PMColorList::PMColorList( PMPart* part )
+ : Base( part )
+{
+}
+
+PMColorList::PMColorList( const PMColorList& l )
+ : Base( l )
+{
+}
+
+PMColorList::~PMColorList( )
+{
+}
+
+PMMetaObject* PMColorList::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "ColorList", Base::metaObject( ),
+ createNewColorList );
+ }
+ return s_pMetaObject;
+}
+
+void PMColorList::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMColorList::description( ) const
+{
+ return i18n( "color list" );
+}
+
+PMDensityList::PMDensityList( PMPart* part )
+ : Base( part )
+{
+}
+
+PMDensityList::PMDensityList( const PMDensityList& l )
+ : Base( l )
+{
+}
+
+PMDensityList::~PMDensityList( )
+{
+}
+
+PMMetaObject* PMDensityList::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "DensityList", Base::metaObject( ),
+ createNewDensityList );
+ }
+ return s_pMetaObject;
+}
+
+void PMDensityList::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMDensityList::description( ) const
+{
+ return i18n( "density list" );
+}
+
+PMDefinePropertyClass( PMNormalList, PMNormalListProperty );
+
+PMNormalList::PMNormalList( PMPart* part )
+ : Base( part )
+{
+ m_depth = depthDefault;
+}
+
+PMNormalList::PMNormalList( const PMNormalList& l )
+ : Base( l )
+{
+ m_depth = depthDefault;
+}
+
+PMNormalList::~PMNormalList( )
+{
+}
+
+PMMetaObject* PMNormalList::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "NormalList", Base::metaObject( ),
+ createNewNormalList );
+ s_pMetaObject->addProperty(
+ new PMNormalListProperty( "depth", &PMNormalList::setDepth,
+ &PMNormalList::depth ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMNormalList::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMNormalList::description( ) const
+{
+ return i18n( "normal list" );
+}
+
+void PMNormalList::setDepth( double d )
+{
+ if( d != m_depth )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDepthID, m_depth );
+ m_depth = d;
+ }
+}
+
+void PMNormalList::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMDepthID:
+ setDepth( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMNormalList::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+void PMNormalList::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "depth", m_depth );
+ Base::serialize( e, doc );
+}
+
+void PMNormalList::readAttributes( const PMXMLHelper& h )
+{
+ m_depth = h.doubleAttribute( "depth", depthDefault );
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMNormalList::editWidget( QWidget* parent ) const
+{
+ return new PMListPatternEdit( parent );
+}
+
diff --git a/kpovmodeler/pmlistpattern.h b/kpovmodeler/pmlistpattern.h
new file mode 100644
index 00000000..f646d8ab
--- /dev/null
+++ b/kpovmodeler/pmlistpattern.h
@@ -0,0 +1,351 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLISTPATTERN_H
+#define PMLISTPATTERN_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcompositeobject.h"
+#include "pmvector.h"
+
+/**
+ * Base class for povray lists.
+ */
+
+class PMListPattern : public PMCompositeObject
+{
+ typedef PMCompositeObject Base;
+public:
+ /**
+ * The type of the pigment list
+ */
+ enum PMListType { ListPatternChecker, ListPatternBrick, ListPatternHexagon };
+ /**
+ * Creates a PMListPattern
+ */
+ PMListPattern( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMListPattern( const PMListPattern& p );
+ /**
+ * deletes the PMListPattern
+ */
+ virtual ~PMListPattern( );
+
+ /**
+ * Returns the list pattern object type
+ */
+ virtual QString listObjectType( ) const = 0;
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMListPatternEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+
+ /**
+ * Returns the color list type
+ */
+ PMListType listType( ) const { return m_listType; }
+ /**
+ * Returns the brick size
+ */
+ PMVector brickSize( ) const { return m_brickSize; }
+ /**
+ * Returns the mortar size
+ */
+ double mortar( ) const { return m_mortar; }
+
+ /**
+ * Sets the list type
+ */
+ void setListType( PMListType l );
+ /**
+ * Sets the brick size
+ */
+ void setBrickSize( const PMVector& n );
+ /**
+ * Sets the mortar size
+ */
+ void setMortar( double n );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMListPatternMementoID { PMListTypeID, PMBrickSizeID, PMMortarID };
+ /**
+ * List type
+ */
+ PMListType m_listType;
+ /**
+ * Brick Size
+ */
+ PMVector m_brickSize;
+ /**
+ * Mortar Size
+ */
+ double m_mortar;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for texture lists
+ */
+
+class PMTextureList : public PMListPattern
+{
+public:
+ typedef PMListPattern Base;
+ /**
+ * Creates a texture list
+ */
+ PMTextureList( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMTextureList( const PMTextureList& l );
+ /**
+ * Deletes the texture list
+ */
+ virtual ~PMTextureList( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMTextureList( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString listObjectType( ) const { return QString( "Texture" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmtexturelist" ); }
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for pigment lists
+ */
+
+class PMPigmentList : public PMListPattern
+{
+public:
+ typedef PMListPattern Base;
+ /**
+ * Creates a pigment list
+ */
+ PMPigmentList( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPigmentList( const PMPigmentList& l );
+ /**
+ * Deletes the pigment list
+ */
+ virtual ~PMPigmentList( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPigmentList( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString listObjectType( ) const { return QString( "Pigment" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmpigmentlist" ); }
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for color lists
+ */
+
+class PMColorList : public PMListPattern
+{
+public:
+ typedef PMListPattern Base;
+ /**
+ * Creates a color list
+ */
+ PMColorList( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMColorList( const PMColorList& l );
+ /**
+ * Deletes the color list
+ */
+ virtual ~PMColorList( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMColorList( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString listObjectType( ) const { return QString( "SolidColor" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmcolorlist" ); }
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for density lists
+ */
+
+class PMDensityList : public PMListPattern
+{
+public:
+ typedef PMListPattern Base;
+ /**
+ * Creates a density list
+ */
+ PMDensityList( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMDensityList( const PMDensityList& l );
+ /**
+ * Deletes the density list
+ */
+ virtual ~PMDensityList( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMDensityList( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString listObjectType( ) const { return QString( "Density" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmdensitylist" ); }
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for normal lists
+ */
+
+class PMNormalList : public PMListPattern
+{
+public:
+ typedef PMListPattern Base;
+ /**
+ * Creates a normal list
+ */
+ PMNormalList( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMNormalList( const PMNormalList& l );
+ /**
+ * Deletes the normal list
+ */
+ virtual ~PMNormalList( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMNormalList( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString listObjectType( ) const { return QString( "Normal" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /**
+ * Returns a new @ref PMListPatternEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmnormallist" ); }
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ /**
+ * Returns the normal's depth
+ */
+ double depth( ) const { return m_depth; }
+ /**
+ * Sets the normal's depth
+ */
+ void setDepth( double d );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMNormalListMementoID { PMDepthID };
+ /**
+ * Normal Depth
+ */
+ double m_depth;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmlistpatternedit.cpp b/kpovmodeler/pmlistpatternedit.cpp
new file mode 100644
index 00000000..f9eb3cf7
--- /dev/null
+++ b/kpovmodeler/pmlistpatternedit.cpp
@@ -0,0 +1,225 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmlistpatternedit.h"
+#include "pmlistpattern.h"
+#include "pmvectoredit.h"
+#include "pmvector.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include "pmlineedits.h"
+#include <ktabctl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+
+PMListPatternEdit::PMListPatternEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMListPatternEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QVBoxLayout* vlayout = new QVBoxLayout( topLayout( ) );
+
+ /* Field for Pattern List type */
+ QHBoxLayout* layout = new QHBoxLayout( vlayout );
+ QLabel* label = new QLabel( i18n( "Type:" ), this );
+ m_pTypeCombo = new QComboBox( false, this );
+ m_pTypeCombo->insertItem( i18n( "Checkers" ) );
+ m_pTypeCombo->insertItem( i18n( "Brick" ) );
+ m_pTypeCombo->insertItem( i18n( "Hexagon" ) );
+ layout->addWidget( label, 0, AlignTop );
+ layout->addWidget( m_pTypeCombo );
+ layout->addStretch( 1 );
+
+ /* The depth field */
+ layout = new QHBoxLayout( vlayout );
+ m_pDepthLabel = new QLabel( i18n( "Depth:" ), this );
+ m_pDepth = new PMFloatEdit( this );
+ layout->addWidget( m_pDepthLabel );
+ layout->addWidget( m_pDepth );
+ layout->addStretch( 1 );
+
+ /* The brick information */
+ QHBoxLayout* bricklayout = new QHBoxLayout( vlayout );
+ m_pBrickSizeLabel = new QLabel( i18n( "Brick size:" ), this );
+ m_pBrickSize = new PMVectorEdit( "x", "y", "z", this );
+ bricklayout->addWidget( m_pBrickSizeLabel );
+ bricklayout->addWidget( m_pBrickSize );
+ layout = new QHBoxLayout( vlayout );
+ m_pMortarLabel = new QLabel( i18n( "Mortar:" ), this );
+ m_pMortar = new PMFloatEdit( this );
+ layout->addWidget( m_pMortarLabel );
+ layout->addWidget( m_pMortar );
+ layout->addStretch( 1 );
+
+ /* connect all signals to slots/signals */
+ connect( m_pBrickSize, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pTypeCombo, SIGNAL( activated( int ) ), SLOT( slotComboChanged( int ) ) );
+ connect( m_pMortar, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDepth, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMListPatternEdit::displayObject( PMObject* o )
+{
+ QString str;
+
+ if( o->isA( "ListPattern" ) )
+ {
+ m_pDisplayedObject = ( PMListPattern* ) o;
+
+ switch( m_pDisplayedObject->listType( ) )
+ {
+ case PMListPattern::ListPatternChecker:
+ m_pTypeCombo->setCurrentItem( 0 );
+ m_pBrickSizeLabel->hide( );
+ m_pBrickSize->hide( );
+ m_pMortarLabel->hide( );
+ m_pMortar->hide( );
+ break;
+ case PMListPattern::ListPatternBrick:
+ m_pTypeCombo->setCurrentItem( 1 );
+ m_pBrickSizeLabel->show( );
+ m_pBrickSize->show( );
+ m_pMortarLabel->show( );
+ m_pMortar->show( );
+ break;
+ case PMListPattern::ListPatternHexagon:
+ m_pTypeCombo->setCurrentItem( 2 );
+ m_pBrickSizeLabel->hide( );
+ m_pBrickSize->hide( );
+ m_pMortarLabel->hide( );
+ m_pMortar->hide( );
+ break;
+ }
+ m_pMortar->setValue( m_pDisplayedObject->mortar( ) );
+ m_pBrickSize->setVector( m_pDisplayedObject->brickSize( ) );
+ if( o->type( ) == "NormalList" )
+ {
+ m_pDepth->setValue( ( ( PMNormalList* )o )->depth( ) );
+ m_pDepth->show( );
+ m_pDepthLabel->show( );
+ emit sizeChanged( );
+ }
+ else
+ {
+ m_pDepth->hide( );
+ m_pDepthLabel->hide( );
+ emit sizeChanged( );
+ }
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMListPatternEdit: Can't display object\n";
+}
+
+void PMListPatternEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ switch( m_pTypeCombo->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setListType( PMListPattern::ListPatternChecker );
+ break;
+ case 1:
+ m_pDisplayedObject->setListType( PMListPattern::ListPatternBrick );
+ m_pDisplayedObject->setMortar( m_pMortar->value( ) );
+ m_pDisplayedObject->setBrickSize( m_pBrickSize->vector( ) );
+ break;
+ case 2:
+ m_pDisplayedObject->setListType( PMListPattern::ListPatternHexagon );
+ break;
+ }
+ if( m_pDisplayedObject->type( ) == "NormalList" )
+ ( ( PMNormalList* )m_pDisplayedObject )->setDepth( m_pDepth->value( ) );
+ }
+}
+
+bool PMListPatternEdit::isDataValid( )
+{
+ int children = 0;
+ PMObject* o;
+
+ if( !m_pBrickSize->isDataValid( ) )
+ return false;
+ if( !m_pMortar->isDataValid( ) )
+ return false;
+
+ // count child objects
+ for( o = m_pDisplayedObject->firstChild( ); o; o = o->nextSibling( ) )
+ if( o->type( ) == m_pDisplayedObject->listObjectType( ) )
+ children++;
+
+ switch( m_pTypeCombo->currentItem( ) )
+ {
+ case 0:
+ case 1:
+ if( children > 2 )
+ {
+ KMessageBox::error( this, i18n( "You can have at most two child"
+ " items for that list type!" ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMListPatternEdit::slotComboChanged( int c )
+{
+ switch( c )
+ {
+ case 0:
+ m_pBrickSizeLabel->hide( );
+ m_pBrickSize->hide( );
+ m_pMortarLabel->hide( );
+ m_pMortar->hide( );
+ break;
+ case 1:
+ m_pBrickSizeLabel->show( );
+ m_pBrickSize->show( );
+ m_pMortarLabel->show( );
+ m_pMortar->show( );
+ break;
+ case 2:
+ m_pBrickSizeLabel->hide( );
+ m_pBrickSize->hide( );
+ m_pMortarLabel->hide( );
+ m_pMortar->hide( );
+ break;
+ default:
+ break;
+ }
+ emit sizeChanged( );
+ emit dataChanged( );
+}
+
+#include "pmlistpatternedit.moc"
diff --git a/kpovmodeler/pmlistpatternedit.h b/kpovmodeler/pmlistpatternedit.h
new file mode 100644
index 00000000..8ebd5e5b
--- /dev/null
+++ b/kpovmodeler/pmlistpatternedit.h
@@ -0,0 +1,78 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLISTPATTERNEDIT_H
+#define PMLISTPATTERNEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMListPattern;
+class PMVectorEdit;
+class QComboBox;
+class PMFloatEdit;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMListPattern.
+ */
+class PMListPatternEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMListPatternEdit with parent and name
+ */
+ PMListPatternEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * This slot is called when the list type is changed
+ */
+ void slotComboChanged( int c );
+
+private:
+ PMListPattern* m_pDisplayedObject;
+ QComboBox* m_pTypeCombo;
+ PMFloatEdit* m_pMortar;
+ PMVectorEdit* m_pBrickSize;
+ QLabel* m_pBrickSizeLabel;
+ QLabel* m_pMortarLabel;
+
+ QLabel* m_pDepthLabel;
+ PMFloatEdit* m_pDepth;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmlookslike.cpp b/kpovmodeler/pmlookslike.cpp
new file mode 100644
index 00000000..7e810605
--- /dev/null
+++ b/kpovmodeler/pmlookslike.cpp
@@ -0,0 +1,92 @@
+/*
+**************************************************************************
+ description
+ -------------------
+ and : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmlookslike.h"
+
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmnamedobjectedit.h"
+
+#include <klocale.h>
+
+PMMetaObject* PMLooksLike::s_pMetaObject = 0;
+PMObject* createNewLooksLike( PMPart* part )
+{
+ return new PMLooksLike( part );
+}
+
+PMLooksLike::PMLooksLike( PMPart* part )
+ : Base( part )
+{
+}
+
+PMLooksLike::PMLooksLike( const PMLooksLike& l )
+ : Base( l )
+{
+}
+
+PMLooksLike::~PMLooksLike( )
+{
+}
+
+
+QString PMLooksLike::description( ) const
+{
+ return i18n( "looks like" );
+}
+
+PMMetaObject* PMLooksLike::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "LooksLike", Base::metaObject( ),
+ createNewLooksLike );
+ // no properties
+ }
+ return s_pMetaObject;
+}
+
+void PMLooksLike::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMLooksLike::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ Base::serialize( e, doc );
+}
+
+void PMLooksLike::readAttributes( const PMXMLHelper& h )
+{
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMLooksLike::editWidget( QWidget* parent ) const
+{
+ return new PMNamedObjectEdit( parent );
+}
+
+void PMLooksLike::restoreMemento( PMMemento* s )
+{
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmlookslike.h b/kpovmodeler/pmlookslike.h
new file mode 100644
index 00000000..971519e0
--- /dev/null
+++ b/kpovmodeler/pmlookslike.h
@@ -0,0 +1,82 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ -------------------
+ and : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMLOOKSLIKE_H
+#define PMLOOKSLIKE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+
+/**
+ * Class for povray looks_like statements.
+ */
+class PMLooksLike : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+
+public:
+ /**
+ * Constructor
+ */
+ PMLooksLike( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMLooksLike( const PMLooksLike& l );
+ /**
+ * Deletes the PMLooksLike
+ */
+ virtual ~PMLooksLike( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMLooksLike( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMLooksLikeEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmlookslike" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmmapmemento.cpp b/kpovmodeler/pmmapmemento.cpp
new file mode 100644
index 00000000..5b4e9aaa
--- /dev/null
+++ b/kpovmodeler/pmmapmemento.cpp
@@ -0,0 +1,51 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmmapmemento.h"
+
+PMMapMemento::PMMapMemento( PMObject* originator )
+ : PMMemento( originator )
+{
+ m_bMapValuesSaved = false;
+ m_bRemovedValuesSaved = false;
+}
+
+PMMapMemento::~PMMapMemento( )
+{
+}
+
+void PMMapMemento::setMapValues( const QValueList<double>& v )
+{
+ if( !m_bMapValuesSaved )
+ {
+ m_mapValues = v;
+ m_bMapValuesSaved = true;
+ addChange( PMCData );
+ }
+}
+
+void PMMapMemento::setRemovedValues( const QValueList<double>& v )
+{
+ if( !m_bRemovedValuesSaved )
+ {
+ m_removedValues = v;
+ m_bRemovedValuesSaved = true;
+ addChange( PMCData );
+ }
+}
+
+
diff --git a/kpovmodeler/pmmapmemento.h b/kpovmodeler/pmmapmemento.h
new file mode 100644
index 00000000..e2f1fa0a
--- /dev/null
+++ b/kpovmodeler/pmmapmemento.h
@@ -0,0 +1,81 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMAPMEMENTO_H
+#define PMMAPMEMENTO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmmemento.h"
+#include <qvaluelist.h>
+
+
+/**
+ * Memento for @ref PMTextureMapBase
+ */
+class PMMapMemento : public PMMemento
+{
+public:
+ /**
+ * Creates a memento for the object originator
+ */
+ PMMapMemento( PMObject* originator );
+ /**
+ * Deletes the memento
+ */
+ virtual ~PMMapMemento( );
+
+ /**
+ * Saves the map values
+ */
+ void setMapValues( const QValueList<double>& v );
+ /**
+ * Returns the map values
+ */
+ QValueList<double> mapValues( ) const { return m_mapValues; }
+ /**
+ * Returns true if the map values were saved
+ */
+ bool mapValuesSaved( ) const { return m_bMapValuesSaved; }
+
+ /**
+ * Saves the removed values
+ */
+ void setRemovedValues( const QValueList<double>& v );
+ /**
+ * Returns the removed values
+ */
+ QValueList<double> removedValues( ) const { return m_removedValues; }
+ /**
+ * Returns true if the removed values were saved
+ */
+ bool removedValuesSaved( ) const { return m_bRemovedValuesSaved; }
+
+private:
+ /**
+ * The stored values
+ */
+ QValueList<double> m_mapValues;
+ QValueList<double> m_removedValues;
+ bool m_bMapValuesSaved, m_bRemovedValuesSaved;
+};
+
+#endif
diff --git a/kpovmodeler/pmmaterial.cpp b/kpovmodeler/pmmaterial.cpp
new file mode 100644
index 00000000..d50f0ed1
--- /dev/null
+++ b/kpovmodeler/pmmaterial.cpp
@@ -0,0 +1,75 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmaterial.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmmaterialedit.h"
+
+#include <klocale.h>
+
+PMMetaObject* PMMaterial::s_pMetaObject = 0;
+PMObject* createNewMaterial( PMPart* part )
+{
+ return new PMMaterial( part );
+}
+
+PMMaterial::PMMaterial( PMPart* part )
+ : Base( part )
+{
+}
+
+PMMaterial::PMMaterial( const PMMaterial& m )
+ : Base( m )
+{
+}
+
+PMMaterial::~PMMaterial( )
+{
+}
+
+PMMetaObject* PMMaterial::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Material", Base::metaObject( ),
+ createNewMaterial );
+ }
+ return s_pMetaObject;
+}
+
+void PMMaterial::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMMaterial::description( ) const
+{
+ return i18n( "material" );
+}
+
+PMDialogEditBase* PMMaterial::editWidget( QWidget* parent ) const
+{
+ return new PMMaterialEdit( parent );
+}
+
diff --git a/kpovmodeler/pmmaterial.h b/kpovmodeler/pmmaterial.h
new file mode 100644
index 00000000..40891f1e
--- /dev/null
+++ b/kpovmodeler/pmmaterial.h
@@ -0,0 +1,75 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMATERIAL_H
+#define PMMATERIAL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+
+/**
+ * Class for povray materials
+ */
+class PMMaterial : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMMaterial
+ */
+ PMMaterial( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMMaterial( const PMMaterial& m );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMMaterial( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMMaterial( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /**
+ * Returns a new @ref PMMaterialEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmmaterial" ); }
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+// enum PMMaterialMementoID { };
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmmaterialedit.cpp b/kpovmodeler/pmmaterialedit.cpp
new file mode 100644
index 00000000..ba63f579
--- /dev/null
+++ b/kpovmodeler/pmmaterialedit.cpp
@@ -0,0 +1,44 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmaterialedit.h"
+#include "pmmaterial.h"
+#include "pmlinkedit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMMaterialEdit::PMMaterialEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMMaterialEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Material" ) )
+ {
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMMaterialEdit: Can't display object\n";
+}
+
+#include "pmmaterialedit.moc"
diff --git a/kpovmodeler/pmmaterialedit.h b/kpovmodeler/pmmaterialedit.h
new file mode 100644
index 00000000..d273a72e
--- /dev/null
+++ b/kpovmodeler/pmmaterialedit.h
@@ -0,0 +1,58 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMATERIALEDIT_H
+#define PMMATERIALEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMMaterial;
+
+/**
+ * Dialog edit class for @ref PMMaterial
+ */
+class PMMaterialEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMMaterialEdit with parent and name
+ */
+ PMMaterialEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+// virtual void createTopWidgets( );
+ /** */
+// virtual void saveContents( );
+
+private:
+ PMMaterial* m_pDisplayedObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmmaterialmap.cpp b/kpovmodeler/pmmaterialmap.cpp
new file mode 100644
index 00000000..c70d85c9
--- /dev/null
+++ b/kpovmodeler/pmmaterialmap.cpp
@@ -0,0 +1,338 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmaterialmapedit.h"
+#include "pmmaterialmap.h"
+
+#include "pmxmlhelper.h"
+#include "pmcompositeobject.h"
+#include "pmmemento.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+const PMMaterialMap::PMBitmapType bitmapTypeDefault = PMMaterialMap::BitmapSys;
+const char *const bitmapFileDefault = 0;
+const bool enableFilterAllDefault = false;
+const bool enableTransmitAllDefault = false;
+const double filterAllDefault = 0.0;
+const double transmitAllDefault = 0.0;
+const bool onceDefault = false;
+const PMMaterialMap::PMMapType mapTypeDefault = PMMaterialMap::MapPlanar;
+const PMMaterialMap::PMInterpolateType interpolateTypeDefault = PMMaterialMap::InterpolateNone;
+
+PMDefinePropertyClass( PMMaterialMap, PMMaterialMapProperty );
+PMDefineEnumPropertyClass( PMMaterialMap, PMMaterialMap::PMBitmapType,
+ PMBitmapTypeProperty );
+PMDefineEnumPropertyClass( PMMaterialMap, PMMaterialMap::PMInterpolateType,
+ PMInterpolateTypeProperty );
+PMDefineEnumPropertyClass( PMMaterialMap, PMMaterialMap::PMMapType,
+ PMMapTypeProperty );
+
+PMMetaObject* PMMaterialMap::s_pMetaObject = 0;
+PMObject* createNewMaterialMap( PMPart* part )
+{
+ return new PMMaterialMap( part );
+}
+
+PMMaterialMap::PMMaterialMap( PMPart* part )
+ : Base( part )
+{
+ m_bitmapType = bitmapTypeDefault;
+ m_bitmapFile = bitmapFileDefault;
+ m_once = onceDefault;
+ m_mapType = mapTypeDefault;
+ m_interpolateType = interpolateTypeDefault;
+}
+
+PMMaterialMap::PMMaterialMap( const PMMaterialMap& m )
+ : Base( m )
+{
+ m_bitmapType = m.m_bitmapType;
+ m_bitmapFile = m.m_bitmapFile;
+ m_once = m.m_once;
+ m_mapType = m.m_mapType;
+ m_interpolateType = m.m_interpolateType;
+}
+
+PMMaterialMap::~PMMaterialMap( )
+{
+}
+
+void PMMaterialMap::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ switch( m_bitmapType )
+ {
+ case BitmapGif:
+ e.setAttribute( "bitmap_type", "gif" );
+ break;
+ case BitmapTga:
+ e.setAttribute( "bitmap_type", "tga" );
+ break;
+ case BitmapIff:
+ e.setAttribute( "bitmap_type", "iff" );
+ break;
+ case BitmapPpm:
+ e.setAttribute( "bitmap_type", "ppm" );
+ break;
+ case BitmapPgm:
+ e.setAttribute( "bitmap_type", "pgm" );
+ break;
+ case BitmapPng:
+ e.setAttribute( "bitmap_type", "png" );
+ break;
+ case BitmapJpeg:
+ e.setAttribute( "bitmap_type", "jpeg" );
+ break;
+ case BitmapTiff:
+ e.setAttribute( "bitmap_type", "tiff" );
+ break;
+ case BitmapSys:
+ e.setAttribute( "bitmap_type", "sys" );
+ break;
+ }
+ e.setAttribute( "file_name", m_bitmapFile );
+ e.setAttribute( "once", m_once );
+ switch( m_mapType )
+ {
+ case MapPlanar:
+ e.setAttribute( "map_type", "planar" );
+ break;
+ case MapSpherical:
+ e.setAttribute( "map_type", "spherical" );
+ break;
+ case MapCylindrical:
+ e.setAttribute( "map_type", "cylindrical" );
+ break;
+ case MapToroidal:
+ e.setAttribute( "map_type", "toroidal" );
+ break;
+ }
+ switch( m_interpolateType )
+ {
+ case InterpolateNone:
+ e.setAttribute( "interpolate", "none" );
+ break;
+ case InterpolateBilinear:
+ e.setAttribute( "interpolate", "bilinear" );
+ break;
+ case InterpolateNormalized:
+ e.setAttribute( "interpolate", "normalized" );
+ break;
+ }
+ Base::serialize( e, doc );
+}
+
+void PMMaterialMap::readAttributes( const PMXMLHelper& h )
+{
+ QString str;
+
+ str = h.stringAttribute( "bitmap_type", "sys" );
+ if( str == "gif" )
+ m_bitmapType = BitmapGif;
+ else if( str == "tga" )
+ m_bitmapType = BitmapTga;
+ else if( str == "iff" )
+ m_bitmapType = BitmapIff;
+ else if( str == "ppm" )
+ m_bitmapType = BitmapPpm;
+ else if( str == "pgm" )
+ m_bitmapType = BitmapPgm;
+ else if( str == "png" )
+ m_bitmapType = BitmapPng;
+ else if( str == "jpeg" )
+ m_bitmapType = BitmapJpeg;
+ else if( str == "tiff" )
+ m_bitmapType = BitmapTiff;
+ else if( str == "sys" )
+ m_bitmapType = BitmapSys;
+
+ m_bitmapFile = h.stringAttribute( "file_name", bitmapFileDefault );
+ m_once = h.boolAttribute( "once", onceDefault );
+
+ str = h.stringAttribute( "map_type", "planar" );
+ if( str == "planar" )
+ m_mapType = MapPlanar;
+ else if( str == "spherical" )
+ m_mapType = MapSpherical;
+ else if( str == "cylindrical" )
+ m_mapType = MapCylindrical;
+ else if( str == "toroidal" )
+ m_mapType = MapToroidal;
+
+ str = h.stringAttribute( "interpolate", "none" );
+ if( str == "none" )
+ m_interpolateType = InterpolateNone;
+ else if( str == "bilinear" )
+ m_interpolateType = InterpolateBilinear;
+ else if( str == "normalized" )
+ m_interpolateType = InterpolateNormalized;
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMMaterialMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "MaterialMap", Base::metaObject( ),
+ createNewMaterialMap );
+
+ PMBitmapTypeProperty* bp = new PMBitmapTypeProperty(
+ "bitmapType", &PMMaterialMap::setBitmapType, &PMMaterialMap::bitmapType );
+ bp->addEnumValue( "Gif", BitmapGif );
+ bp->addEnumValue( "Tga", BitmapTga );
+ bp->addEnumValue( "Iff", BitmapIff );
+ bp->addEnumValue( "Ppm", BitmapPpm );
+ bp->addEnumValue( "Pgm", BitmapPgm );
+ bp->addEnumValue( "Png", BitmapPng );
+ bp->addEnumValue( "Jpeg", BitmapJpeg );
+ bp->addEnumValue( "Tiff", BitmapTiff );
+ bp->addEnumValue( "Sys", BitmapSys );
+ s_pMetaObject->addProperty( bp );
+
+ PMInterpolateTypeProperty* ip = new PMInterpolateTypeProperty(
+ "interpolateType", &PMMaterialMap::setInterpolateType,
+ &PMMaterialMap::interpolateType );
+ ip->addEnumValue( "None", InterpolateNone );
+ ip->addEnumValue( "Bilinear", InterpolateBilinear );
+ ip->addEnumValue( "Normalized", InterpolateNormalized );
+ s_pMetaObject->addProperty( ip );
+
+ PMMapTypeProperty* mp = new PMMapTypeProperty(
+ "mapType", &PMMaterialMap::setMapType, &PMMaterialMap::mapType );
+ mp->addEnumValue( "Planar", MapPlanar );
+ mp->addEnumValue( "Spherical", MapSpherical );
+ mp->addEnumValue( "Cylindrical", MapCylindrical );
+ mp->addEnumValue( "Toroidal", MapToroidal );
+ s_pMetaObject->addProperty( mp );
+
+ s_pMetaObject->addProperty(
+ new PMMaterialMapProperty( "bitmapFile", &PMMaterialMap::setBitmapFileName,
+ &PMMaterialMap::bitmapFile ) );
+ s_pMetaObject->addProperty(
+ new PMMaterialMapProperty( "once", &PMMaterialMap::enableOnce, &PMMaterialMap::isOnceEnabled ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMMaterialMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMMaterialMap::description( ) const
+{
+ return i18n( "material map" );
+}
+
+void PMMaterialMap::setBitmapType( PMBitmapType c )
+{
+ if( c != m_bitmapType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBitmapTypeID, m_bitmapType );
+ m_bitmapType = c;
+ }
+}
+
+void PMMaterialMap::setBitmapFileName( const QString& c )
+{
+ if( c != m_bitmapFile )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBitmapFileID, m_bitmapFile );
+ m_bitmapFile = c;
+ }
+}
+
+void PMMaterialMap::setMapType( PMMapType c )
+{
+ if( c != m_mapType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMapTypeID, m_mapType );
+ m_mapType = c;
+ }
+}
+
+void PMMaterialMap::setInterpolateType( PMInterpolateType c )
+{
+ if( c != m_interpolateType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMInterpolateID, m_interpolateType );
+ m_interpolateType = c;
+ }
+}
+
+void PMMaterialMap::enableOnce( bool c )
+{
+ if( c != m_once )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOnceID, m_once );
+ m_once = c;
+ }
+}
+
+PMDialogEditBase* PMMaterialMap::editWidget( QWidget* parent ) const
+{
+ return new PMMaterialMapEdit( parent );
+}
+
+void PMMaterialMap::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMBitmapTypeID:
+ setBitmapType( ( PMBitmapType )data->intData( ) );
+ break;
+ case PMBitmapFileID:
+ setBitmapFileName( data->stringData( ) );
+ break;
+ case PMOnceID:
+ enableOnce( data->boolData( ) );
+ break;
+ case PMMapTypeID:
+ setMapType( ( PMMapType )data->intData( ) );
+ break;
+ case PMInterpolateID:
+ setInterpolateType( ( PMInterpolateType )data->intData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMMaterialMap::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmmaterialmap.h b/kpovmodeler/pmmaterialmap.h
new file mode 100644
index 00000000..c6713e9f
--- /dev/null
+++ b/kpovmodeler/pmmaterialmap.h
@@ -0,0 +1,153 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMATERIALMAP_H
+#define PMMATERIALMAP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+#include "pmpalettevalue.h"
+
+/**
+ * Class for povray material maps.
+ */
+
+class PMMaterialMap : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+public:
+ /**
+ * The bitmap type
+ */
+ enum PMBitmapType { BitmapGif, BitmapTga, BitmapIff, BitmapPpm,
+ BitmapPgm, BitmapPng, BitmapJpeg, BitmapTiff,
+ BitmapSys };
+ /**
+ * The interpolate method
+ */
+ enum PMInterpolateType { InterpolateNone, InterpolateBilinear,
+ InterpolateNormalized };
+ /**
+ * The mapping method
+ */
+ enum PMMapType { MapPlanar, MapSpherical, MapCylindrical,
+ MapToroidal };
+
+
+ /**
+ * Creates a PMMaterialMap
+ */
+ PMMaterialMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMMaterialMap( const PMMaterialMap& m );
+ /**
+ * deletes the PMMaterialMap
+ */
+ virtual ~PMMaterialMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMMaterialMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmmaterialmap" ); }
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMMaterialMapEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+
+ /**
+ * Gets the bitmap type
+ */
+ PMBitmapType bitmapType( ) const { return m_bitmapType; }
+ /**
+ * Gets the bitmap file name
+ */
+ QString bitmapFile( ) const { return m_bitmapFile; }
+ /**
+ * Returns true if once is enabled
+ */
+ bool isOnceEnabled( ) const { return m_once; }
+ /**
+ * Gets the bitmap file type
+ */
+ PMMapType mapType( ) const { return m_mapType; }
+ /**
+ * Gets the interpolate method type
+ */
+ PMInterpolateType interpolateType( ) const { return m_interpolateType; }
+
+
+ /**
+ * Sets the bumpmap type
+ */
+ void setBitmapType( PMBitmapType c );
+ /**
+ * Sets the bitmap file name*/
+ void setBitmapFileName( const QString& c );
+ /**
+ * Sets if the bitmap should be mapped once
+ */
+ void enableOnce( bool c );
+ /**
+ * Sets the mapping method
+ */
+ void setMapType( const PMMapType c );
+ /**
+ * Sets the interpolating method
+ */
+ void setInterpolateType( PMInterpolateType c );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMMaterialMapMementoID { PMBitmapTypeID, PMBitmapFileID,
+ PMOnceID, PMMapTypeID, PMInterpolateID };
+ /**
+ * MaterialMap type
+ */
+ PMBitmapType m_bitmapType;
+ QString m_bitmapFile;
+ bool m_once;
+ PMMapType m_mapType;
+ PMInterpolateType m_interpolateType;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmmaterialmapedit.cpp b/kpovmodeler/pmmaterialmapedit.cpp
new file mode 100644
index 00000000..d50e3d7b
--- /dev/null
+++ b/kpovmodeler/pmmaterialmapedit.cpp
@@ -0,0 +1,299 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmaterialmapedit.h"
+#include "pmmaterialmap.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmpalettevalueedit.h"
+#include "pmvector.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <ktabctl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+
+PMMaterialMapEdit::PMMaterialMapEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMMaterialMapEdit::createTopWidgets( )
+{
+ QLabel* lbl;
+ QHBoxLayout* hl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "File type:" ), this );
+ m_pImageFileTypeEdit = new QComboBox( this );
+ m_pImageFileTypeEdit->insertItem( "gif" );
+ m_pImageFileTypeEdit->insertItem( "tga" );
+ m_pImageFileTypeEdit->insertItem( "iff" );
+ m_pImageFileTypeEdit->insertItem( "ppm" );
+ m_pImageFileTypeEdit->insertItem( "pgm" );
+ m_pImageFileTypeEdit->insertItem( "png" );
+ m_pImageFileTypeEdit->insertItem( "jpeg" );
+ m_pImageFileTypeEdit->insertItem( "tiff" );
+ m_pImageFileTypeEdit->insertItem( "sys" );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pImageFileTypeEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "File name:" ), this );
+ m_pImageFileNameEdit = new QLineEdit( this );
+ m_pImageFileNameBrowse = new QPushButton( this );
+ m_pImageFileNameBrowse->setPixmap( SmallIcon( "fileopen" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pImageFileNameEdit );
+ hl->addWidget( m_pImageFileNameBrowse );
+ hl->addStretch( 1 );
+
+ m_pOnceEdit = new QCheckBox( i18n( "Once" ), this );
+ topLayout( )->addWidget( m_pOnceEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Interpolate:" ), this );
+ m_pInterpolateTypeEdit = new QComboBox( this );
+ m_pInterpolateTypeEdit->insertItem( i18n( "None" ) );
+ m_pInterpolateTypeEdit->insertItem( i18n( "Bilinear" ) );
+ m_pInterpolateTypeEdit->insertItem( i18n( "Normalized" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pInterpolateTypeEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ lbl = new QLabel( i18n( "Map type:" ), this );
+ m_pMapTypeEdit = new QComboBox( this );
+ m_pMapTypeEdit->insertItem( i18n( "Planar" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Spherical" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Cylindrical" ) );
+ m_pMapTypeEdit->insertItem( i18n( "Toroidal" ) );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pMapTypeEdit );
+ hl->addStretch( 1 );
+
+ connect( m_pImageFileTypeEdit, SIGNAL( activated( int ) ), SLOT( slotImageFileTypeChanged( int ) ) );
+ connect( m_pMapTypeEdit, SIGNAL( activated( int ) ), SLOT( slotMapTypeChanged( int ) ) );
+ connect( m_pInterpolateTypeEdit, SIGNAL( activated( int ) ), SLOT( slotInterpolateTypeChanged( int ) ) );
+ connect( m_pImageFileNameBrowse, SIGNAL( clicked( ) ), SLOT( slotImageFileBrowseClicked( ) ) );
+ connect( m_pImageFileNameEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotImageFileNameChanged( const QString& ) ) );
+ connect( m_pOnceEdit, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMMaterialMapEdit::displayObject( PMObject* o )
+{
+ bool readOnly;
+
+ if( o->isA( "MaterialMap" ) )
+ {
+ m_pDisplayedObject = ( PMMaterialMap* ) o;
+ readOnly = m_pDisplayedObject->isReadOnly( );
+
+ switch( m_pDisplayedObject->bitmapType( ) )
+ {
+ case PMMaterialMap::BitmapGif:
+ m_pImageFileTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMMaterialMap::BitmapTga:
+ m_pImageFileTypeEdit->setCurrentItem( 1 );
+ break;
+ case PMMaterialMap::BitmapIff:
+ m_pImageFileTypeEdit->setCurrentItem( 2 );
+ break;
+ case PMMaterialMap::BitmapPpm:
+ m_pImageFileTypeEdit->setCurrentItem( 3 );
+ break;
+ case PMMaterialMap::BitmapPgm:
+ m_pImageFileTypeEdit->setCurrentItem( 4 );
+ break;
+ case PMMaterialMap::BitmapPng:
+ m_pImageFileTypeEdit->setCurrentItem( 5 );
+ break;
+ case PMMaterialMap::BitmapJpeg:
+ m_pImageFileTypeEdit->setCurrentItem( 6 );
+ break;
+ case PMMaterialMap::BitmapTiff:
+ m_pImageFileTypeEdit->setCurrentItem( 7 );
+ break;
+ case PMMaterialMap::BitmapSys:
+ m_pImageFileTypeEdit->setCurrentItem( 8 );
+ break;
+ }
+ m_pImageFileTypeEdit->setEnabled( !readOnly );
+
+ switch( m_pDisplayedObject->interpolateType( ) )
+ {
+ case PMMaterialMap::InterpolateNone:
+ m_pInterpolateTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMMaterialMap::InterpolateBilinear:
+ m_pInterpolateTypeEdit->setCurrentItem( 1);
+ break;
+ case PMMaterialMap::InterpolateNormalized:
+ m_pInterpolateTypeEdit->setCurrentItem( 2 );
+ break;
+ }
+ m_pInterpolateTypeEdit->setEnabled( !readOnly );
+
+ switch( m_pDisplayedObject->mapType( ) )
+ {
+ case PMMaterialMap::MapPlanar:
+ m_pMapTypeEdit->setCurrentItem( 0 );
+ break;
+ case PMMaterialMap::MapSpherical:
+ m_pMapTypeEdit->setCurrentItem( 1 );
+ break;
+ case PMMaterialMap::MapCylindrical:
+ m_pMapTypeEdit->setCurrentItem( 2 );
+ break;
+ case PMMaterialMap::MapToroidal:
+ m_pMapTypeEdit->setCurrentItem( 3 );
+ break;
+ }
+ m_pMapTypeEdit->setEnabled( !readOnly );
+
+ m_pImageFileNameEdit->setText( m_pDisplayedObject->bitmapFile( ) );
+ m_pImageFileNameEdit->setEnabled( !readOnly );
+ m_pOnceEdit->setChecked( m_pDisplayedObject->isOnceEnabled( ) );
+ m_pOnceEdit->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+
+}
+
+void PMMaterialMapEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ switch( m_pImageFileTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapGif );
+ break;
+ case 1:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapTga );
+ break;
+ case 2:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapIff );
+ break;
+ case 3:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapPpm );
+ break;
+ case 4:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapPgm );
+ break;
+ case 5:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapPng );
+ break;
+ case 6:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapJpeg );
+ break;
+ case 7:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapTiff );
+ break;
+ case 8:
+ m_pDisplayedObject->setBitmapType( PMMaterialMap::BitmapSys );
+ break;
+ }
+
+ switch( m_pInterpolateTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setInterpolateType( PMMaterialMap::InterpolateNone );
+ break;
+ case 1:
+ m_pDisplayedObject->setInterpolateType( PMMaterialMap::InterpolateBilinear );
+ break;
+ case 2:
+ m_pDisplayedObject->setInterpolateType( PMMaterialMap::InterpolateNormalized );
+ break;
+ }
+
+ switch( m_pMapTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setMapType( PMMaterialMap::MapPlanar );
+ break;
+ case 1:
+ m_pDisplayedObject->setMapType( PMMaterialMap::MapSpherical );
+ break;
+ case 2:
+ m_pDisplayedObject->setMapType( PMMaterialMap::MapCylindrical );
+ break;
+ case 3:
+ m_pDisplayedObject->setMapType( PMMaterialMap::MapToroidal );
+ break;
+ }
+
+ m_pDisplayedObject->setBitmapFileName( m_pImageFileNameEdit->text( ) );
+ m_pDisplayedObject->enableOnce( m_pOnceEdit->isChecked( ) );
+ }
+}
+
+bool PMMaterialMapEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+void PMMaterialMapEdit::slotInterpolateTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMMaterialMapEdit::slotImageFileTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMMaterialMapEdit::slotMapTypeChanged( const int /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMMaterialMapEdit::slotImageFileNameChanged( const QString& /*a*/ )
+{
+ emit dataChanged( );
+}
+
+void PMMaterialMapEdit::slotImageFileBrowseClicked( )
+{
+ QString str = KFileDialog::getOpenFileName( QString::null, QString::null );
+
+ if( !str.isEmpty() )
+ {
+ m_pImageFileNameEdit->setText( str );
+ emit dataChanged( );
+ }
+}
+
+#include "pmmaterialmapedit.moc"
diff --git a/kpovmodeler/pmmaterialmapedit.h b/kpovmodeler/pmmaterialmapedit.h
new file mode 100644
index 00000000..f6ffa7f0
--- /dev/null
+++ b/kpovmodeler/pmmaterialmapedit.h
@@ -0,0 +1,81 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMATERIALMAPEDIT_H
+#define PMMATERIALMAPEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMMaterialMap;
+class QComboBox;
+class PMFloatEdit;
+class PMIntEdit;
+class QLabel;
+class QCheckBox;
+class QWidget;
+class QLineEdit;
+class QPushButton;
+
+/**
+ * Dialog edit class for @ref PMMaterialMap.
+ */
+class PMMaterialMapEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMMaterialMapEdit with parent and name
+ */
+ PMMaterialMapEdit( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displayObject( PMObject* o );
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+private slots:
+ /** */
+ void slotImageFileTypeChanged( int a );
+ /** */
+ void slotMapTypeChanged( int a );
+ /** */
+ void slotInterpolateTypeChanged( int a );
+ /** */
+ void slotImageFileNameChanged( const QString& a );
+ /** */
+ void slotImageFileBrowseClicked( );
+private:
+ PMMaterialMap* m_pDisplayedObject;
+ QComboBox* m_pImageFileTypeEdit;
+ QLineEdit* m_pImageFileNameEdit;
+ QPushButton* m_pImageFileNameBrowse;
+ QCheckBox* m_pOnceEdit;
+ QComboBox* m_pMapTypeEdit;
+ QComboBox* m_pInterpolateTypeEdit;
+};
+
+#endif
diff --git a/kpovmodeler/pmmath.cpp b/kpovmodeler/pmmath.cpp
new file mode 100644
index 00000000..8aedab76
--- /dev/null
+++ b/kpovmodeler/pmmath.cpp
@@ -0,0 +1,67 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+// some helper functions
+
+#include "pmmath.h"
+#include <math.h>
+
+bool approx( double v1, double v2, double epsilon )
+{
+ return fabs( v1 - v2 ) < epsilon;
+}
+
+bool approxZero( double v, double epsilon )
+{
+ return fabs( v ) < epsilon;
+}
+
+double rad2Deg( double rad )
+{
+ return rad / M_PI * 180.0;
+}
+
+double deg2Rad( double deg )
+{
+ return deg * M_PI / 180.0;
+}
+
+double pmatan( double s, double c )
+{
+ double a;
+ if( approxZero( c ) )
+ {
+ if( s > 0 )
+ a = M_PI_2;
+ else
+ a = -M_PI_2;
+ }
+ else
+ a = atan2( s, c );
+
+ return a;
+}
+
+int pmpot( int x, int y )
+{
+ int i;
+ int result = 1;
+ for( i = 0; i < y; i++ )
+ result *= x;
+ return result;
+}
diff --git a/kpovmodeler/pmmath.h b/kpovmodeler/pmmath.h
new file mode 100644
index 00000000..520b8b6d
--- /dev/null
+++ b/kpovmodeler/pmmath.h
@@ -0,0 +1,48 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMATH_H
+#define PMMATH_H
+
+/**
+ * Same as ( fabs( v1 - v2 ) < epsilon )
+ */
+bool approx( double v1, double v2, double epsilon = 1e-6 );
+/**
+ * Same as ( fabs( v ) < epsilon )
+ */
+bool approxZero( double v, double epsilon = 1e-6 );
+/**
+ * Converts rad to deg
+ */
+double rad2Deg( double rad );
+/**
+ * Converts deg to rad
+ */
+double deg2Rad( double deg );
+/**
+ * Returns the atan( s / c ) with all special cases
+ */
+double pmatan( double s, double c );
+/**
+ * Returns x^y. y has to be >= 0
+ */
+int pmpot( int x, int y );
+
+#endif
diff --git a/kpovmodeler/pmmatrix.cpp b/kpovmodeler/pmmatrix.cpp
new file mode 100644
index 00000000..217672e5
--- /dev/null
+++ b/kpovmodeler/pmmatrix.cpp
@@ -0,0 +1,442 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include <math.h>
+
+#include "pmmatrix.h"
+#include "pmvector.h"
+#include "pmdebug.h"
+
+#include <qtextstream.h>
+
+PMMatrix::PMMatrix( )
+{
+ int i;
+
+ for( i = 0; i < 16; i++ )
+ m_elements[i] = 0;
+}
+
+PMMatrix::~PMMatrix( )
+{
+}
+
+PMMatrix& PMMatrix::operator= ( const PMMatrix& m )
+{
+ int i;
+ for( i=0; i<16; i++ )
+ m_elements[i] = m.m_elements[i];
+
+ return *this;
+}
+
+PMMatrix PMMatrix::identity( )
+{
+ PMMatrix newMatrix;
+ int i;
+
+ for( i=0; i<4; i++ )
+ newMatrix[i][i] = 1.0;
+
+ return newMatrix;
+}
+
+PMMatrix PMMatrix::translation( double x, double y, double z )
+{
+ PMMatrix newMatrix;
+ newMatrix[3][0] = x;
+ newMatrix[3][1] = y;
+ newMatrix[3][2] = z;
+ newMatrix[0][0] = 1;
+ newMatrix[1][1] = 1;
+ newMatrix[2][2] = 1;
+ newMatrix[3][3] = 1;
+
+ return newMatrix;
+}
+
+PMMatrix PMMatrix::scale( double x, double y, double z )
+{
+ PMMatrix newMatrix;
+ newMatrix[0][0] = x;
+ newMatrix[1][1] = y;
+ newMatrix[2][2] = z;
+ newMatrix[3][3] = 1;
+
+ return newMatrix;
+}
+
+PMMatrix PMMatrix::rotation( double x, double y, double z )
+{
+ PMMatrix newMatrix;
+ double sinx, siny, sinz, cosx, cosy, cosz;
+ sinx = sin( x );
+ siny = sin( y );
+ sinz = sin( z );
+ cosx = cos( x );
+ cosy = cos( y );
+ cosz = cos( z );
+
+ newMatrix[0][0] = cosz*cosy;
+ newMatrix[1][0] = -sinz*cosx + cosz*siny*sinx;
+ newMatrix[2][0] = sinz*sinx + cosz*siny*cosx;
+ newMatrix[0][1] = sinz*cosy;
+ newMatrix[1][1] = cosz*cosx + sinz*siny*sinx;
+ newMatrix[2][1] = -cosz*sinx + sinz*siny*cosx;
+ newMatrix[0][2] = -siny;
+ newMatrix[1][2] = cosy*sinx;
+ newMatrix[2][2] = cosy*cosx;
+ newMatrix[3][3] = 1;
+
+ return newMatrix;
+}
+
+PMMatrix PMMatrix::rotation( const PMVector& n, double a )
+{
+ PMMatrix result( PMMatrix::identity( ) );
+ double rx, ry;
+
+ if( n.size( ) == 3 )
+ {
+ rx = pmatan( n.y( ), n.z( ) );
+ ry = - pmatan( n.x( ), sqrt( n.y( ) * n.y( ) + n.z( ) * n.z( ) ) );
+
+ result = rotation( -rx, 0.0, 0.0 ) * rotation( 0.0, -ry, 0.0 )
+ * rotation( rx, ry, a );
+
+ }
+ else
+ kdError( PMArea ) << "Wrong size in PMMatrix::rotation( )\n";
+
+ return result;
+}
+
+PMMatrix PMMatrix::viewTransformation( const PMVector& eye,
+ const PMVector& lookAt,
+ const PMVector& up )
+{
+ PMMatrix result;
+ PMVector x, y, z;
+ GLdouble len;
+ int i;
+
+ // create rotation matrix
+ z = eye - lookAt;
+ len = z.abs( );
+ if( !approxZero( len ) )
+ z /= len;
+
+ y = up;
+ x = PMVector::cross( y, z );
+ y = PMVector::cross( z, x );
+
+ // normalize vectors
+ len = x.abs( );
+ if( !approxZero( len ) )
+ x /= len;
+
+ len = y.abs( );
+ if( !approxZero( len ) )
+ y /= len;
+
+ for( i = 0; i < 3; i++ )
+ {
+ result[i][0] = x[i];
+ result[i][1] = y[i];
+ result[i][2] = z[i];
+ result[3][i] = 0.0;
+ result[i][3] = 0.0;
+ }
+ result[3][3] = 1.0;
+
+ // Translate eye to origin
+ return result * translation( -eye[0], -eye[1], -eye[2] );
+}
+
+void PMMatrix::toRotation( double* x, double* y, double* z )
+{
+ PMMatrix& m = *this;
+
+ if( !approx( fabs( m[0][2] ), 1.0 ) )
+ {
+ double cosy;
+ // | m[0][2] | != 1
+ // sin(y) != 1.0, cos(y) != 0.0
+ *y = asin( - m[0][2] );
+ cosy = cos( *y );
+
+ // sign of cosy is important!
+ *x = pmatan( m[1][2] / cosy, m[2][2] / cosy );
+ *z = pmatan( m[0][1] / cosy, m[0][0] / cosy );
+ }
+ else if( m[0][2] < 0 )
+ {
+ // m[0][2] == -1
+ // sin(y) == 1, cos(y) == 0
+ // z and x are dependent of each other, assume z = 0
+
+ double zminusx = pmatan( m[2][1], m[1][1] );
+
+ *y = M_PI_2;
+ *z = 0.0;
+ *x = - zminusx;
+ }
+ else
+ {
+ // m[0][2] == 1
+ // sin(y) == -1, cos(y) == 0
+ // z and x are dependent of each other, assume z = 0
+
+ double zplusx = pmatan( -m[2][1], m[1][1] );
+
+ *y = -M_PI_2;
+ *z = 0.0;
+ *x = zplusx;
+ }
+}
+
+PMMatrix PMMatrix::modelviewMatrix( )
+{
+ PMMatrix result;
+ glGetDoublev( GL_MODELVIEW_MATRIX, result.m_elements );
+ return result;
+}
+
+double PMMatrix::det( ) const
+{
+ PMMatrix tmp( *this );
+ double result = 1.0, help;
+ int i, k, e, row;
+
+ // make a upper triangular matrix
+ for( i=0; i<4; i++ )
+ {
+ row = tmp.notNullElementRow( i );
+ if( row == -1 )
+ return 0;
+ if( row != i )
+ {
+ tmp.exchangeRows( i, row );
+ result = -result;
+ }
+
+ result *= tmp[i][i];
+ for( k=i+1; k<4; k++ )
+ {
+ help = tmp[i][k];
+ for( e=0; e<4; e++ )
+ tmp[e][k] -= tmp[e][i] * help/tmp[i][i];
+ }
+ }
+ return result;
+}
+
+PMMatrix PMMatrix::inverse( ) const
+{
+ PMMatrix result( identity( ) );
+ PMMatrix tmp( *this );
+ int i, k, e, row;
+ double a;
+
+ // uses the Gauss algorithm
+ // row operations to make tmp a identity matrix
+ // result matrix is then the inverse
+ for( i=0; i<4; i++ )
+ {
+ row = tmp.notNullElementRow( i );
+ if( row == -1 )
+ return identity( );
+ if( row != i )
+ {
+ tmp.exchangeRows( i, row );
+ result.exchangeRows( i, row );
+ }
+ // tmp[i][i] != 0
+
+ a = tmp[i][i];
+ for( e=0; e<4; e++ )
+ {
+ result[e][i] /= a;
+ tmp[e][i] /= a;
+ }
+ // tmp[i][i] == 1
+
+ for( k=0; k<4; k++ )
+ {
+ if( k != i )
+ {
+ a = tmp[i][k];
+ for( e=0; e<4; e++ )
+ {
+ result[e][k] -= result[e][i] * a;
+ tmp[e][k] -= tmp[e][i] * a;
+ }
+ }
+ }
+ // tmp[!=i][i] == 0.0
+ }
+ return result;
+}
+
+void PMMatrix::exchangeRows( int r1, int r2 )
+{
+ GLdouble help;
+ int i;
+
+ for( i=0; i<4; i++ )
+ {
+ help = (*this)[i][r1];
+ (*this)[i][r1] = (*this)[i][r2];
+ (*this)[i][r2] = help;
+ }
+}
+
+int PMMatrix::notNullElementRow( const int index ) const
+{
+ int i, result = -1;
+ GLdouble max = 0.0, v;
+
+ // choose the row with abs( ) = max
+ for( i=index; i<4; i++ )
+ {
+ v = fabs((*this)[index][i]);
+ if( v > max )
+ {
+ result = i;
+ max = v;
+ }
+ }
+ return result;
+}
+
+PMMatrix& PMMatrix::operator*= ( const double d )
+{
+ int i;
+ for( i=0; i<16; i++ )
+ m_elements[i] *= d;
+ return *this;
+}
+
+PMMatrix& PMMatrix::operator/= ( const double d )
+{
+ int i;
+ if( approxZero( 0 ) )
+ kdError( PMArea ) << "Division by zero in PMMatrix::operator/=" << "\n";
+ else
+ for( i=0; i<16; i++ )
+ m_elements[i] /= d;
+ return *this;
+}
+
+PMMatrix& PMMatrix::operator*= ( const PMMatrix& m )
+{
+ *this = *this * m;
+ return *this;
+}
+
+PMMatrix operator- ( const PMMatrix& m )
+{
+ PMMatrix result;
+ int r,c;
+
+ for( r=0; r<4; r++ )
+ for( c=0; c<4; c++ )
+ result[c][r] = -m[c][r];
+ return result;
+}
+
+PMMatrix operator* ( const PMMatrix& m1, const PMMatrix& m2 )
+{
+ PMMatrix result;
+ int r, c, i;
+
+ for( r=0; r<4; r++ )
+ for( c=0; c<4; c++ )
+ for( i=0; i<4; i++ )
+ result[c][r] += m1[i][r] * m2[c][i];
+ return result;
+}
+
+PMMatrix operator* ( const PMMatrix& m1, const double d )
+{
+ PMMatrix result( m1 );
+ result *= d;
+ return result;
+}
+
+PMMatrix operator/ ( const PMMatrix& m1, const double d )
+{
+ PMMatrix result( m1 );
+ result /= d ;
+ return result;
+}
+
+PMMatrix operator* ( const double d, const PMMatrix& m1 )
+{
+ PMMatrix result( m1 );
+ result *= d;
+ return result;
+}
+
+#include <stdio.h>
+void PMMatrix::testOutput( )
+{
+ int r, c;
+
+ printf( "\n" );
+ for( r=0; r<4; r++ )
+ {
+ for( c=0; c<4; c++ )
+ printf( "% 20.18f ", (*this)[c][r] );
+ printf( "\n" );
+ }
+}
+
+QString PMMatrix::serializeXML( ) const
+{
+ QString result;
+ QTextStream str( &result, IO_WriteOnly );
+ int i;
+
+ for( i = 0; i < 16; i++ )
+ {
+ if( i > 0 )
+ str << ' ';
+ str << m_elements[i];
+ }
+
+ return result;
+}
+
+bool PMMatrix::loadXML( const QString& str )
+{
+ int i;
+ QString tmp( str );
+ QTextStream s( &tmp, IO_ReadOnly );
+ QString val;
+ bool ok;
+
+ for( i = 0; i < 16; i++ )
+ {
+ s >> val;
+ m_elements[i] = val.toDouble( &ok );
+ if( !ok )
+ return false;
+ }
+ return true;
+}
diff --git a/kpovmodeler/pmmatrix.h b/kpovmodeler/pmmatrix.h
new file mode 100644
index 00000000..62747aea
--- /dev/null
+++ b/kpovmodeler/pmmatrix.h
@@ -0,0 +1,188 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMATRIX_H
+#define PMMATRIX_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmmath.h"
+#include "math.h"
+
+#include <qstring.h>
+
+#include <GL/gl.h>
+
+class PMVector;
+
+/**
+ * 4x4 matrix for transformations with homogenous coordinates
+ *
+ * Optimized for OpenGL.
+ */
+class PMMatrix
+{
+public:
+ /**
+ * Creates a zero matrix
+ */
+ PMMatrix( );
+ /**
+ * Deletes the matrix
+ */
+ ~PMMatrix( );
+ /**
+ * Assigns m to the matrix
+ */
+ PMMatrix& operator= ( const PMMatrix& m );
+ /**
+ * Creates an identity matrix
+ */
+ static PMMatrix identity( );
+ /**
+ * Creates a matrix for translation.
+ */
+ static PMMatrix translation( double x, double y, double z );
+ /**
+ * Creates a matrix for rotations. Rotation first around the x, then y
+ * and then around the z axis.
+ *
+ * x, y and z in rad
+ */
+ static PMMatrix rotation( double x, double y, double z );
+ /**
+ * Creates a matrix for rotation around the direction n with angle a.
+ *
+ * a in rad.
+ */
+ static PMMatrix rotation( const PMVector& n, double a );
+ /**
+ * Creates a viewing matrix.
+ *
+ * The viewpoint is specified by the parameter eye. The parameter
+ * lookAt specifies any point along the line of sight. The up vector
+ * indicate which direction is up.
+ */
+ static PMMatrix viewTransformation( const PMVector& eye,
+ const PMVector& lookAt,
+ const PMVector& up );
+ /**
+ * Backwards calculate the rotations from the matrix
+ */
+ void toRotation( double* x, double* y, double* z );
+
+ /**
+ * Creates a matrix for scale.
+ */
+ static PMMatrix scale( double x, double y, double z );
+ /**
+ * Returns the current gl modelview matrix
+ */
+ static PMMatrix modelviewMatrix( );
+
+ /**
+ * Returns a pointer to the column (!) at position index.
+ * That means matrix[i][j] is the element at column i and row j*/
+ GLdouble* operator[] ( int index ) { return &( m_elements[index*4] ); }
+ /**
+ * Returns a pointer to the column (!) at position index.
+ * That means matrix[i][j] is the element at column i and row j*/
+ const GLdouble* operator[] ( int index ) const
+ { return &(m_elements[index*4]); }
+ /**
+ * Returns true if an inverse matrix can be calculated
+ */
+ bool canBuildInverse( ) const { return ! approxZero( det( ) ); }
+ /**
+ * Returns the inverse matrix if possible, otherwise a identity matrix
+ */
+ PMMatrix inverse( ) const;
+ /**
+ * Returns the determinant of the matrix
+ */
+ double det( ) const;
+ /**
+ * Multiplies m to the matrix from the right side
+ */
+ PMMatrix& operator*= ( const PMMatrix& m );
+ /**
+ * Multiplies each element with d
+ */
+ PMMatrix& operator*= ( const double d );
+ /**
+ * Divides each element by d
+ */
+ PMMatrix& operator/= ( const double d );
+
+ /**
+ * Returns a matrix with negated elements
+ */
+ friend PMMatrix operator- ( const PMMatrix& m );
+ /**
+ * Multiplies m2 with m1 from the right side (m1*m2)*/
+ friend PMMatrix operator* ( const PMMatrix& m1, const PMMatrix& m2 );
+ /**
+ * Multiplies d to all elements
+ */
+ friend PMMatrix operator* ( const PMMatrix& m, const double d );
+ /**
+ * Multiplies d to all elements
+ */
+ friend PMMatrix operator* ( const GLdouble d, const PMMatrix& m );
+ /**
+ * Divides all elements by d
+ */
+ friend PMMatrix operator/ ( const PMMatrix& m, const double d );
+
+ /**
+ * Only for tests
+ */
+ void testOutput( );
+ /**
+ * Returns a pointer to the data. Can be used in glMultMatrixd
+ */
+ const GLdouble* data( ) const { return m_elements; }
+
+ /**
+ * Returns a string for xml output
+ */
+ QString serializeXML( ) const;
+ /**
+ * loads the vector data from the xml string
+ */
+ bool loadXML( const QString& str );
+private:
+ /**
+ * Exchanges two rows
+ */
+ void exchangeRows( int r1, int r2 );
+ /**
+ * Finds a row with not zero element in column index. Begins to
+ * search in row at position index. Used for det() and inverse()
+ *
+ * Returns -1 if all rows are zero in that column
+ */
+ int notNullElementRow( const int index ) const;
+
+ GLdouble m_elements[16];
+};
+
+#endif
diff --git a/kpovmodeler/pmmedia.cpp b/kpovmodeler/pmmedia.cpp
new file mode 100644
index 00000000..e5229d47
--- /dev/null
+++ b/kpovmodeler/pmmedia.cpp
@@ -0,0 +1,480 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmedia.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmmediaedit.h"
+#include "pmcolor.h"
+
+#include <klocale.h>
+
+const int methodDefault = 1;
+const int intervalsDefault = 10;
+const int samplesMinDefault = 1;
+const int samplesMaxDefault = 1;
+const double confidenceDefault = 0.9;
+const double varianceDefault = 0.0078125;
+const double ratioDefault = 0.9;
+const int aaLevelDefault = 4;
+const double aaThresholdDefault = 0.1;
+const PMColor absorptionDefault = PMColor( 0.0, 0.0, 0.0 );
+const PMColor emissionDefault = PMColor( 0.0, 0.0, 0.0 );
+const int scatteringTypeDefault = 0;
+const PMColor scatteringColorDefault = PMColor( 0.0, 0.0, 0.0 );
+const double scatteringEccentricityDefault = 0;
+const double scatteringExtinctionDefault = 1.0;
+
+PMDefinePropertyClass( PMMedia, PMMediaProperty );
+PMMetaObject* PMMedia::s_pMetaObject = 0;
+PMObject* createNewMedia( PMPart* part )
+{
+ return new PMMedia( part );
+}
+
+PMMedia::PMMedia( PMPart* part )
+ : Base( part )
+{
+ m_method = methodDefault;
+ m_intervals = intervalsDefault;
+ m_samplesMin = samplesMinDefault;
+ m_samplesMax = samplesMaxDefault;
+ m_confidence = confidenceDefault;
+ m_variance = varianceDefault;
+ m_ratio = ratioDefault;
+ m_aaLevel = aaLevelDefault;
+ m_aaThreshold = aaThresholdDefault;
+ m_absorption = absorptionDefault;
+ m_emission = emissionDefault;
+ m_scatteringType = scatteringTypeDefault;
+ m_scatteringColor = scatteringColorDefault;
+ m_scatteringEccentricity = scatteringEccentricityDefault;
+ m_scatteringExtinction = scatteringExtinctionDefault;
+ m_enableAbsorption = false;
+ m_enableEmission = false;
+ m_enableScattering = false;
+}
+
+PMMedia::PMMedia( const PMMedia& m )
+ : Base( m )
+{
+ m_method = m.m_method;
+ m_intervals = m.m_intervals;
+ m_samplesMin = m.m_samplesMin;
+ m_samplesMax = m.m_samplesMax;
+ m_aaLevel = m.m_aaLevel;
+ m_confidence = m.m_confidence;
+ m_variance = m.m_variance;
+ m_ratio = m.m_ratio;
+ m_aaThreshold = m.m_aaThreshold;
+ m_absorption = m.m_absorption;
+ m_emission = m.m_emission;
+ m_scatteringType = m.m_scatteringType;
+ m_scatteringColor = m.m_scatteringColor;
+ m_scatteringEccentricity = m.m_scatteringEccentricity;
+ m_scatteringExtinction = m.m_scatteringExtinction;
+ m_enableAbsorption = m.m_enableAbsorption;
+ m_enableEmission = m.m_enableEmission;
+ m_enableScattering = m.m_enableScattering;
+}
+
+PMMedia::~PMMedia( )
+{
+}
+
+PMMetaObject* PMMedia::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Media", Base::metaObject( ),
+ createNewMedia );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "method", &PMMedia::setMethod, &PMMedia::method ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "intervals", &PMMedia::setIntervals, &PMMedia::intervals ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "samplesMin", &PMMedia::setSamplesMin, &PMMedia::samplesMin ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "samplesMax", &PMMedia::setSamplesMax, &PMMedia::samplesMax ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "aaLevel", &PMMedia::setAALevel, &PMMedia::aaLevel ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "confidence", &PMMedia::setConfidence, &PMMedia::confidence ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "variance", &PMMedia::setVariance, &PMMedia::variance ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "ratio", &PMMedia::setRatio, &PMMedia::ratio ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "aaThreshold", &PMMedia::setAAThreshold, &PMMedia::aaThreshold ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "absorption", &PMMedia::setAbsorption, &PMMedia::absorption ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "emission", &PMMedia::setEmission, &PMMedia::emission ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "scatteringType", &PMMedia::setScatteringType, &PMMedia::scatteringType ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "scatteringColor", &PMMedia::setScatteringColor, &PMMedia::scatteringColor ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "scatteringExtinction", &PMMedia::setScatteringExtinction, &PMMedia::scatteringExtinction ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "scatteringEccentricity", &PMMedia::setScatteringEccentricity, &PMMedia::scatteringEccentricity ) );
+
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "absorptionEnabled", &PMMedia::enableAbsorption, &PMMedia::isAbsorptionEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "emissionEnabled", &PMMedia::enableEmission, &PMMedia::isEmissionEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMMediaProperty( "scatteringEnabled", &PMMedia::enableScattering, &PMMedia::isScatteringEnabled ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMMedia::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMMedia::description( ) const
+{
+ return i18n( "media" );
+}
+
+void PMMedia::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ Base::serialize( e, doc );
+ e.setAttribute( "enable_absorption", m_enableAbsorption );
+ e.setAttribute( "enable_emission", m_enableEmission );
+ e.setAttribute( "enable_scattering", m_enableScattering );
+ e.setAttribute( "method", m_method );
+ e.setAttribute( "intervals", m_intervals );
+ e.setAttribute( "samples_min", m_samplesMin );
+ e.setAttribute( "samples_max", m_samplesMax );
+ e.setAttribute( "aa_level", m_aaLevel );
+ e.setAttribute( "confidence", m_confidence );
+ e.setAttribute( "variance", m_variance );
+ e.setAttribute( "ratio", m_ratio );
+ e.setAttribute( "aa_threshold", m_aaThreshold );
+ e.setAttribute( "absorption", m_absorption.serializeXML( ) );
+ e.setAttribute( "emission", m_emission.serializeXML( ) );
+ e.setAttribute( "scattering_type", m_scatteringType );
+ e.setAttribute( "scattering_color", m_scatteringColor.serializeXML( ) );
+ e.setAttribute( "scattering_eccentricity", m_scatteringEccentricity );
+ e.setAttribute( "scattering_extinction", m_scatteringExtinction );
+}
+
+void PMMedia::readAttributes( const PMXMLHelper& h )
+{
+ Base::readAttributes( h );
+ m_enableAbsorption = h.boolAttribute( "enable_absorption", false );
+ m_enableEmission = h.boolAttribute( "enable_emission", false );
+ m_enableScattering = h.boolAttribute( "enable_scattering", false );
+ m_method = h.intAttribute( "method", methodDefault );
+ m_intervals = h.intAttribute( "intervals", intervalsDefault );
+ m_samplesMin = h.intAttribute( "samples_min", samplesMinDefault );
+ m_samplesMax = h.intAttribute( "samples_max", samplesMaxDefault );
+ m_aaLevel = h.intAttribute( "aa_level", aaLevelDefault );
+ m_confidence = h.doubleAttribute( "confidence", confidenceDefault );
+ m_variance = h.doubleAttribute( "variance", varianceDefault );
+ m_ratio = h.doubleAttribute( "ratio", ratioDefault );
+ m_aaThreshold = h.doubleAttribute( "aa_threshold", aaThresholdDefault );
+ m_absorption = h.colorAttribute( "absorption", absorptionDefault );
+ m_emission = h.colorAttribute( "emission", emissionDefault );
+ m_scatteringType = h.intAttribute( "scattering_type", scatteringTypeDefault );
+ m_scatteringColor = h.colorAttribute( "scattering_color", scatteringColorDefault );
+ m_scatteringEccentricity = h.doubleAttribute( "scattering_eccentricity",
+ scatteringEccentricityDefault );
+ m_scatteringExtinction = h.doubleAttribute( "scattering_extinction",
+ scatteringExtinctionDefault );
+}
+
+void PMMedia::setMethod( int c )
+{
+ if ( c < 1 )
+ {
+ kdError( PMArea ) << "method is < 1 in PMMedia::setMethod\n";
+ c = 1;
+ }
+
+ if ( c > 3 )
+ {
+ kdError( PMArea ) << "method is > 3 in PMMedia::setMethod\n";
+ c = 3;
+ }
+
+ if ( c != m_method )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMethodID, m_method );
+ m_method = c;
+ }
+}
+
+void PMMedia::setIntervals( int c )
+{
+ if( c != m_intervals )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMIntervalsID, m_intervals );
+ m_intervals = c;
+ }
+}
+
+void PMMedia::setSamplesMin( int c )
+{
+ if( c != m_samplesMin )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSamplesMinID, m_samplesMin );
+ m_samplesMin = c;
+ }
+}
+
+void PMMedia::setSamplesMax( int c )
+{
+ if( c != m_samplesMax )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSamplesMaxID, m_samplesMax );
+ m_samplesMax = c;
+ }
+}
+
+void PMMedia::setAALevel( int c )
+{
+ if ( c != m_aaLevel )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAALevelID, m_aaLevel );
+ m_aaLevel = c;
+ }
+}
+
+void PMMedia::setConfidence( double c )
+{
+ if( c != m_confidence )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMConfidenceID, m_confidence );
+ m_confidence = c;
+ }
+}
+
+void PMMedia::setVariance( double c )
+{
+ if( c != m_variance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMVarianceID, m_variance );
+ m_variance = c;
+ }
+}
+
+void PMMedia::setRatio( double c )
+{
+ if( c != m_ratio )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRatioID, m_ratio );
+ m_ratio = c;
+ }
+}
+
+void PMMedia::setAAThreshold( double c )
+{
+ if ( c != m_aaThreshold )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAAThresholdID, m_aaThreshold );
+ m_aaThreshold = c;
+ }
+}
+
+void PMMedia::setAbsorption( const PMColor& c )
+{
+ if( c != m_absorption )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAbsorptionID, m_absorption );
+ m_absorption = c;
+ }
+}
+
+void PMMedia::setEmission( const PMColor& c )
+{
+ if( c != m_emission )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEmissionID, m_emission );
+ m_emission = c;
+ }
+}
+
+void PMMedia::setScatteringType( int c )
+{
+ if( c != m_scatteringType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMScatteringTypeID, m_scatteringType );
+ m_scatteringType = c;
+ }
+}
+
+void PMMedia::setScatteringColor( const PMColor& c )
+{
+ if( c != m_scatteringColor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMScatteringColorID, m_scatteringColor );
+ m_scatteringColor = c;
+ }
+}
+
+void PMMedia::setScatteringEccentricity( double c )
+{
+ if( c != m_scatteringEccentricity )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMScatteringEccentricityID, m_scatteringEccentricity );
+ m_scatteringEccentricity = c;
+ }
+}
+
+void PMMedia::setScatteringExtinction( double c )
+{
+ if( c != m_scatteringExtinction )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMScatteringExtinctionID, m_scatteringExtinction );
+ m_scatteringExtinction = c;
+ }
+}
+
+void PMMedia::enableAbsorption( bool c )
+{
+ if( c != m_enableAbsorption )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableAbsorptionID, m_enableAbsorption );
+ m_enableAbsorption = c;
+ }
+}
+
+void PMMedia::enableEmission( bool c )
+{
+ if( c != m_enableEmission )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableEmissionID, m_enableEmission );
+ m_enableEmission = c;
+ }
+}
+
+void PMMedia::enableScattering( bool c )
+{
+ if( c != m_enableScattering )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableScatteringID, m_enableScattering );
+ m_enableScattering = c;
+ }
+}
+
+PMDialogEditBase* PMMedia::editWidget( QWidget* parent ) const
+{
+ return new PMMediaEdit( parent );
+}
+
+void PMMedia::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMEnableAbsorptionID:
+ enableAbsorption( data->boolData( ) );
+ break;
+ case PMEnableEmissionID:
+ enableEmission( data->boolData( ) );
+ break;
+ case PMEnableScatteringID:
+ enableScattering( data->boolData( ) );
+ break;
+ case PMMethodID:
+ setMethod( data->intData( ) );
+ break;
+ case PMIntervalsID:
+ setIntervals( data->intData( ) );
+ break;
+ case PMSamplesMinID:
+ setSamplesMin( data->intData( ) );
+ break;
+ case PMSamplesMaxID:
+ setSamplesMax( data->intData( ) );
+ break;
+ case PMAALevelID:
+ setAALevel( data->intData( ) );
+ break;
+ case PMConfidenceID:
+ setConfidence( data->doubleData( ) );
+ break;
+ case PMVarianceID:
+ setVariance( data->doubleData( ) );
+ break;
+ case PMRatioID:
+ setRatio( data->doubleData( ) );
+ break;
+ case PMAAThresholdID:
+ setAAThreshold( data->doubleData( ) );
+ break;
+ case PMAbsorptionID:
+ setAbsorption( data->colorData( ) );
+ break;
+ case PMEmissionID:
+ setEmission( data->colorData( ) );
+ break;
+ case PMScatteringTypeID:
+ setScatteringType( data->intData( ) );
+ break;
+ case PMScatteringColorID:
+ setScatteringColor( data->colorData( ) );
+ break;
+ case PMScatteringEccentricityID:
+ setScatteringEccentricity( data->doubleData( ) );
+ break;
+ case PMScatteringExtinctionID:
+ setScatteringExtinction( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMMedia::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmmedia.h b/kpovmodeler/pmmedia.h
new file mode 100644
index 00000000..3bf6705b
--- /dev/null
+++ b/kpovmodeler/pmmedia.h
@@ -0,0 +1,149 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMEDIA_H
+#define PMMEDIA_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+#include "pmcolor.h"
+
+/**
+ * Class for povray medias
+ */
+class PMMedia : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMMedia
+ */
+ PMMedia( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMMedia( const PMMedia& m );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMMedia( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMMedia( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMMediaEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmmedia" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ int method( ) const { return m_method; }
+ int intervals( ) const { return m_intervals; }
+ int samplesMin( ) const { return m_samplesMin; }
+ int samplesMax( ) const { return m_samplesMax; }
+ double confidence( ) const { return m_confidence; }
+ double variance( ) const { return m_variance; }
+ double ratio( ) const { return m_ratio; }
+ int aaLevel( ) const { return m_aaLevel; }
+ double aaThreshold( ) const { return m_aaThreshold; }
+ PMColor absorption( ) const { return m_absorption; }
+ PMColor emission( ) const { return m_emission; }
+ int scatteringType( ) const { return m_scatteringType; }
+ PMColor scatteringColor( ) const { return m_scatteringColor; }
+ double scatteringEccentricity( ) const { return m_scatteringEccentricity; }
+ double scatteringExtinction( ) const { return m_scatteringExtinction; }
+ bool isAbsorptionEnabled( ) const { return m_enableAbsorption; }
+ bool isEmissionEnabled( ) const { return m_enableEmission; }
+ bool isScatteringEnabled( ) const { return m_enableScattering; }
+
+ void setMethod( int c );
+ void setIntervals( int c );
+ void setSamplesMin( int c );
+ void setSamplesMax( int c );
+ void setAALevel( int c );
+ void setConfidence( double c );
+ void setVariance( double c );
+ void setRatio( double c );
+ void setAAThreshold( double c );
+ void setAbsorption( const PMColor& c );
+ void setEmission( const PMColor& c );
+ void setScatteringType( int c );
+ void setScatteringColor( const PMColor& c );
+ void setScatteringEccentricity( double c );
+ void setScatteringExtinction( double c );
+ void enableAbsorption( bool c );
+ void enableEmission( bool c );
+ void enableScattering( bool c );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMMediaMementoID { PMMethodID, PMIntervalsID, PMSamplesMinID, PMSamplesMaxID,
+ PMConfidenceID, PMVarianceID, PMRatioID,
+ PMAALevelID, PMAAThresholdID, PMAbsorptionID, PMEmissionID,
+ PMScatteringTypeID, PMScatteringColorID,
+ PMScatteringEccentricityID, PMScatteringExtinctionID,
+ PMEnableAbsorptionID, PMEnableEmissionID,
+ PMEnableScatteringID };
+
+ int m_method;
+ int m_intervals;
+ int m_samplesMin;
+ int m_samplesMax;
+ double m_confidence;
+ double m_variance;
+ double m_ratio;
+ int m_aaLevel;
+ double m_aaThreshold;
+ PMColor m_absorption;
+ PMColor m_emission;
+ int m_scatteringType;
+ PMColor m_scatteringColor;
+ double m_scatteringEccentricity;
+ double m_scatteringExtinction;
+
+ bool m_enableAbsorption;
+ bool m_enableEmission;
+ bool m_enableScattering;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmmediaedit.cpp b/kpovmodeler/pmmediaedit.cpp
new file mode 100644
index 00000000..2806eff8
--- /dev/null
+++ b/kpovmodeler/pmmediaedit.cpp
@@ -0,0 +1,370 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmediaedit.h"
+#include "pmmedia.h"
+#include "pmlineedits.h"
+#include "pmcoloredit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+
+PMMediaEdit::PMMediaEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMMediaEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+ QGridLayout* gl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Method:" ), this ) );
+ m_pMethodEdit = new QComboBox( this );
+ m_pMethodEdit->insertItem( i18n( "1 (Monte Carlo)" ) );
+ m_pMethodEdit->insertItem( i18n( "2 (Smooth)" ) );
+ m_pMethodEdit->insertItem( i18n( "3 (Adaptive sampling)" ) );
+ hl->addWidget( m_pMethodEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Intervals:" ), this ) );
+ m_pIntervalsEdit = new PMIntEdit( this );
+ m_pIntervalsEdit->setValidation( true, 1, false, 0 );
+ hl->addWidget( m_pIntervalsEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Samples" ), this ) );
+ hl->addWidget( new QLabel( i18n( "Min:" ), this ) );
+ m_pSamplesMinEdit = new PMIntEdit( this );
+ m_pSamplesMinEdit->setValidation( true, 1, false, 0 );
+ hl->addWidget( m_pSamplesMinEdit );
+ m_pSamplesMaxLabel = new QLabel( i18n( "Max:" ), this );
+ hl->addWidget( m_pSamplesMaxLabel );
+ m_pSamplesMaxEdit = new PMIntEdit( this );
+ hl->addWidget( m_pSamplesMaxEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 3, 2 );
+ gl->addWidget( new QLabel( i18n( "Confidence:" ), this ), 0, 0 );
+ m_pConfidenceEdit = new PMFloatEdit( this );
+ m_pConfidenceEdit->setValidation( true, 0, true, 1 );
+ gl->addWidget( m_pConfidenceEdit, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Variance:" ), this ), 1, 0 );
+ m_pVarianceEdit = new PMFloatEdit( this );
+ gl->addWidget( m_pVarianceEdit, 1, 1 );
+ gl->addWidget( new QLabel( i18n( "Ratio:" ), this ), 2, 0 );
+ m_pRatioEdit = new PMFloatEdit( this );
+ gl->addWidget( m_pRatioEdit, 2, 1 );
+ hl->addStretch( 1 );
+
+ m_pAAWidget = new QWidget( this );
+ hl = new QHBoxLayout( m_pAAWidget, KDialog::spacingHint( ) );
+ hl->addWidget( new QLabel( i18n( "Anti-aliasing" ), m_pAAWidget ) );
+ hl->addWidget( new QLabel( i18n( "Level:" ), m_pAAWidget ) );
+ m_pAALevelEdit = new PMIntEdit( m_pAAWidget );
+ m_pAALevelEdit->setValidation( true, 1, false, 0 );
+ hl->addWidget( m_pAALevelEdit );
+ hl->addWidget( new QLabel( i18n( "Threshold:" ), m_pAAWidget ) );
+ m_pAAThresholdEdit = new PMFloatEdit( m_pAAWidget );
+ m_pAAThresholdEdit->setValidation( true, 0.0, false, 0.0 );
+ hl->addWidget( m_pAAThresholdEdit );
+ hl->addStretch( 1 );
+ topLayout( )->addWidget( m_pAAWidget );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 2, 2 );
+ m_pEnableAbsorptionEdit = new QCheckBox( i18n( "Absorption" ), this );
+ gl->addMultiCellWidget( m_pEnableAbsorptionEdit, 0, 0, 0, 1 );
+ m_pAbsorptionEdit = new PMColorEdit( false, this );
+ m_pAbsorptionLabel = new QLabel( i18n( "Color:" ), this );
+ gl->addWidget( m_pAbsorptionLabel, 1, 0, AlignTop );
+ gl->addWidget( m_pAbsorptionEdit, 1, 1 );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 2, 2 );
+ m_pEnableEmissionEdit = new QCheckBox( i18n( "Emission" ), this );
+ gl->addMultiCellWidget( m_pEnableEmissionEdit, 0, 0, 0, 1 );
+ m_pEmissionEdit = new PMColorEdit( false, this );
+ m_pEmissionLabel = new QLabel( i18n( "Color:" ), this );
+ gl->addWidget( m_pEmissionLabel, 1, 0, AlignTop );
+ gl->addWidget( m_pEmissionEdit, 1, 1 );
+ hl->addStretch( 1 );
+
+ m_pEnableScatteringEdit = new QCheckBox( i18n( "Scattering" ), this );
+ topLayout( )->addWidget( m_pEnableScatteringEdit );
+ m_pScatteringWidget = new QWidget( this );
+ QVBoxLayout* vl = new QVBoxLayout( m_pScatteringWidget, KDialog::spacingHint( ) );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( new QLabel( i18n( "Type:" ), m_pScatteringWidget ) );
+ m_pScatteringTypeEdit = new QComboBox( m_pScatteringWidget );
+ m_pScatteringTypeEdit->insertItem( i18n( "Isotropic" ) );
+ m_pScatteringTypeEdit->insertItem( i18n( "Mie Haze" ) );
+ m_pScatteringTypeEdit->insertItem( i18n( "Mie Murky" ) );
+ m_pScatteringTypeEdit->insertItem( i18n( "Rayleigh" ) );
+ m_pScatteringTypeEdit->insertItem( i18n( "Henyey-Greenstein" ) );
+ hl->addWidget( m_pScatteringTypeEdit );
+ hl->addStretch( 1 );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( new QLabel( i18n( "Color:" ), m_pScatteringWidget ), 0, AlignTop );
+ m_pScatteringColorEdit = new PMColorEdit( false, m_pScatteringWidget );
+ hl->addWidget( m_pScatteringColorEdit );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 2, 2 );
+ m_pScatteringEccentricityLabel = new QLabel( i18n( "Eccentricity:" ), m_pScatteringWidget );
+ gl->addWidget( m_pScatteringEccentricityLabel, 0, 0 );
+ m_pScatteringEccentricityEdit = new PMFloatEdit( m_pScatteringWidget );
+ gl->addWidget( m_pScatteringEccentricityEdit, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Extinction:" ), m_pScatteringWidget ), 1, 0 );
+ m_pScatteringExtinctionEdit = new PMFloatEdit( m_pScatteringWidget );
+ gl->addWidget( m_pScatteringExtinctionEdit, 1, 1 );
+ hl->addStretch( 1 );
+ topLayout( )->addWidget( m_pScatteringWidget );
+
+ connect( m_pMethodEdit, SIGNAL( activated( int ) ), SLOT( slotMethodChanged( int ) ) );
+ connect( m_pIntervalsEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSamplesMinEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSamplesMaxEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pConfidenceEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pVarianceEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRatioEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAALevelEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAAThresholdEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAbsorptionEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEmissionEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnableAbsorptionEdit, SIGNAL( clicked( ) ), SLOT( slotAbsorptionClicked( ) ) );
+ connect( m_pEnableEmissionEdit, SIGNAL( clicked( ) ), SLOT( slotEmissionClicked( ) ) );
+ connect( m_pEnableScatteringEdit, SIGNAL( clicked( ) ), SLOT( slotScatteringClicked( ) ) );
+ connect( m_pScatteringTypeEdit, SIGNAL( activated( int ) ), SLOT( slotScatteringTypeChanged( int ) ) );
+ connect( m_pScatteringColorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pScatteringEccentricityEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pScatteringExtinctionEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMMediaEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Media" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMMedia* ) o;
+
+ m_pMethodEdit->setCurrentItem( m_pDisplayedObject->method( ) - 1 );
+ m_pMethodEdit->setEnabled( !readOnly );
+ m_pIntervalsEdit->setValue( m_pDisplayedObject->intervals( ) );
+ m_pIntervalsEdit->setReadOnly( readOnly );
+ m_pSamplesMinEdit->setValue( m_pDisplayedObject->samplesMin( ) );
+ m_pSamplesMinEdit->setReadOnly( readOnly );
+ m_pSamplesMaxEdit->setValue( m_pDisplayedObject->samplesMax( ) );
+ m_pSamplesMaxEdit->setReadOnly( readOnly );
+ m_pConfidenceEdit->setValue( m_pDisplayedObject->confidence( ) );
+ m_pConfidenceEdit->setReadOnly( readOnly );
+ m_pVarianceEdit->setValue( m_pDisplayedObject->variance( ) );
+ m_pVarianceEdit->setReadOnly( readOnly );
+ m_pRatioEdit->setValue( m_pDisplayedObject->ratio( ) );
+ m_pRatioEdit->setReadOnly( readOnly );
+ m_pAALevelEdit->setValue( m_pDisplayedObject->aaLevel( ) );
+ m_pAALevelEdit->setReadOnly( readOnly );
+ m_pAAThresholdEdit->setValue( m_pDisplayedObject->aaThreshold( ) );
+ m_pAAThresholdEdit->setReadOnly( readOnly );
+ m_pAbsorptionEdit->setColor( m_pDisplayedObject->absorption( ) );
+ m_pAbsorptionEdit->setReadOnly( readOnly );
+ m_pEmissionEdit->setColor( m_pDisplayedObject->emission( ) );
+ m_pEmissionEdit->setReadOnly( readOnly );
+ m_pEnableAbsorptionEdit->setChecked( m_pDisplayedObject->isAbsorptionEnabled( ) );
+ m_pEnableAbsorptionEdit->setEnabled( !readOnly );
+ m_pEnableEmissionEdit->setChecked( m_pDisplayedObject->isEmissionEnabled( ) );
+ m_pEnableEmissionEdit->setEnabled( !readOnly );
+ m_pEnableScatteringEdit->setChecked( m_pDisplayedObject->isScatteringEnabled( ) );
+ m_pEnableScatteringEdit->setEnabled( !readOnly );
+ m_pScatteringTypeEdit->setCurrentItem( m_pDisplayedObject->scatteringType( ) - 1 );
+ m_pScatteringTypeEdit->setEnabled( !readOnly );
+ m_pScatteringColorEdit->setColor( m_pDisplayedObject->scatteringColor( ) );
+ m_pScatteringColorEdit->setReadOnly( readOnly );
+ m_pScatteringEccentricityEdit->setValue( m_pDisplayedObject->scatteringEccentricity( ) );
+ m_pScatteringEccentricityEdit->setReadOnly( readOnly );
+ m_pScatteringExtinctionEdit->setValue( m_pDisplayedObject->scatteringExtinction( ) );
+ m_pScatteringExtinctionEdit->setReadOnly( readOnly );
+
+ slotMethodChanged( m_pMethodEdit->currentItem( ) );
+ slotAbsorptionClicked( );
+ slotEmissionClicked( );
+ slotScatteringClicked( );
+ slotScatteringTypeChanged( m_pScatteringTypeEdit->currentItem( ) );
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMMediaEdit: Can't display object\n";
+}
+
+void PMMediaEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setMethod( m_pMethodEdit->currentItem( ) + 1 );
+ m_pDisplayedObject->setIntervals( m_pIntervalsEdit->value( ) );
+ m_pDisplayedObject->setSamplesMin( m_pSamplesMinEdit->value( ) );
+ m_pDisplayedObject->setSamplesMax( m_pSamplesMaxEdit->value( ) );
+ m_pDisplayedObject->setConfidence( m_pConfidenceEdit->value( ) );
+ m_pDisplayedObject->setVariance( m_pVarianceEdit->value( ) );
+ m_pDisplayedObject->setRatio( m_pRatioEdit->value( ) );
+ m_pDisplayedObject->setAALevel( m_pAALevelEdit->value( ) );
+ m_pDisplayedObject->setAAThreshold( m_pAAThresholdEdit->value( ) );
+ m_pDisplayedObject->setAbsorption( m_pAbsorptionEdit->color( ) );
+ m_pDisplayedObject->setEmission( m_pEmissionEdit->color( ) );
+ m_pDisplayedObject->setScatteringType( m_pScatteringTypeEdit->currentItem( ) + 1 );
+ m_pDisplayedObject->setScatteringColor( m_pScatteringColorEdit->color( ) );
+ m_pDisplayedObject->setScatteringEccentricity( m_pScatteringEccentricityEdit->value( ) );
+ m_pDisplayedObject->setScatteringExtinction( m_pScatteringExtinctionEdit->value( ) );
+ m_pDisplayedObject->enableAbsorption( m_pEnableAbsorptionEdit->isChecked( ) );
+ m_pDisplayedObject->enableEmission( m_pEnableEmissionEdit->isChecked( ) );
+ m_pDisplayedObject->enableScattering( m_pEnableScatteringEdit->isChecked( ) );
+ }
+}
+
+bool PMMediaEdit::isDataValid( )
+{
+ if( !m_pIntervalsEdit->isDataValid( ) ) return false;
+ if( !m_pSamplesMinEdit->isDataValid( ) ) return false;
+ if( !m_pSamplesMaxEdit->isDataValid( ) ) return false;
+ if( !m_pConfidenceEdit->isDataValid( ) ) return false;
+ if( !m_pVarianceEdit->isDataValid( ) ) return false;
+ if( !m_pRatioEdit->isDataValid( ) ) return false;
+ if( !m_pAALevelEdit->isDataValid( ) ) return false;
+ if( !m_pAAThresholdEdit->isDataValid( ) ) return false;
+ if( !m_pAbsorptionEdit->isDataValid( ) ) return false;
+ if( !m_pEmissionEdit->isDataValid( ) ) return false;
+ if( !m_pScatteringColorEdit->isDataValid( ) ) return false;
+ if( !m_pScatteringEccentricityEdit->isDataValid( ) ) return false;
+ if( !m_pScatteringExtinctionEdit->isDataValid( ) ) return false;
+ if( m_pMethodEdit->currentItem( ) < 2 &&
+ m_pSamplesMaxEdit->value( ) < m_pSamplesMinEdit->value( ) )
+ {
+ KMessageBox::error( this, i18n( "Maximum number of samples lower than minimum number." ),
+ i18n( "Error" ) );
+ return false;
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMMediaEdit::slotMethodChanged( int c )
+{
+ if ( c == 2 )
+ {
+ m_pAAWidget->show( );
+ m_pSamplesMaxLabel->hide( );
+ m_pSamplesMaxEdit->hide( );
+ }
+ else
+ {
+ m_pAAWidget->hide( );
+ m_pSamplesMaxLabel->show( );
+ m_pSamplesMaxEdit->show( );
+ if ( m_pSamplesMaxEdit->value( ) < m_pSamplesMinEdit->value( ) )
+ m_pSamplesMaxEdit->setValue( m_pSamplesMinEdit->value( ) );
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMMediaEdit::slotAbsorptionClicked( )
+{
+ if( m_pEnableAbsorptionEdit->isChecked( ) )
+ {
+ m_pAbsorptionEdit->show( );
+ m_pAbsorptionLabel->show( );
+ }
+ else
+ {
+ m_pAbsorptionEdit->hide( );
+ m_pAbsorptionLabel->hide( );
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMMediaEdit::slotEmissionClicked( )
+{
+ if( m_pEnableEmissionEdit->isChecked( ) )
+ {
+ m_pEmissionEdit->show( );
+ m_pEmissionLabel->show( );
+ }
+ else
+ {
+ m_pEmissionEdit->hide( );
+ m_pEmissionLabel->hide( );
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMMediaEdit::slotScatteringClicked( )
+{
+ if( m_pEnableScatteringEdit->isChecked( ) )
+ {
+ m_pScatteringWidget->show( );
+ if( m_pScatteringTypeEdit->currentItem( ) == 4 )
+ {
+ m_pScatteringEccentricityLabel->show( );
+ m_pScatteringEccentricityEdit->show( );
+ }
+ else
+ {
+ m_pScatteringEccentricityLabel->hide( );
+ m_pScatteringEccentricityEdit->hide( );
+ }
+ }
+ else
+ m_pScatteringWidget->hide( );
+
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMMediaEdit::slotScatteringTypeChanged( int c )
+{
+ if( c == 4 )
+ {
+ m_pScatteringEccentricityLabel->show( );
+ m_pScatteringEccentricityEdit->show( );
+ }
+ else
+ {
+ m_pScatteringEccentricityLabel->hide( );
+ m_pScatteringEccentricityEdit->hide( );
+ }
+ m_pScatteringWidget->adjustSize( );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+#include "pmmediaedit.moc"
diff --git a/kpovmodeler/pmmediaedit.h b/kpovmodeler/pmmediaedit.h
new file mode 100644
index 00000000..866e706d
--- /dev/null
+++ b/kpovmodeler/pmmediaedit.h
@@ -0,0 +1,102 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMEDIAEDIT_H
+#define PMMEDIAEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMMedia;
+class PMIntEdit;
+class PMFloatEdit;
+class PMColorEdit;
+class QCheckBox;
+class QLabel;
+class QComboBox;
+
+/**
+ * Dialog edit class for @ref PMMedia
+ */
+class PMMediaEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMMediaEdit with parent and name
+ */
+ PMMediaEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotMethodChanged( int c );
+ void slotAbsorptionClicked( );
+ void slotEmissionClicked( );
+ void slotScatteringClicked( );
+ void slotScatteringTypeChanged( int c );
+
+private:
+ PMMedia* m_pDisplayedObject;
+
+ QComboBox* m_pMethodEdit;
+ PMIntEdit* m_pIntervalsEdit;
+ PMIntEdit* m_pSamplesMinEdit;
+ QLabel* m_pSamplesMaxLabel;
+ PMIntEdit* m_pSamplesMaxEdit;
+ PMFloatEdit* m_pConfidenceEdit;
+ PMFloatEdit* m_pVarianceEdit;
+ PMFloatEdit* m_pRatioEdit;
+
+ QWidget* m_pAAWidget;
+ PMIntEdit* m_pAALevelEdit;
+ PMFloatEdit* m_pAAThresholdEdit;
+
+ QCheckBox* m_pEnableAbsorptionEdit;
+ PMColorEdit* m_pAbsorptionEdit;
+ QLabel* m_pAbsorptionLabel;
+
+ QCheckBox* m_pEnableEmissionEdit;
+ PMColorEdit* m_pEmissionEdit;
+ QLabel* m_pEmissionLabel;
+
+ QCheckBox* m_pEnableScatteringEdit;
+ QWidget* m_pScatteringWidget;
+ QComboBox* m_pScatteringTypeEdit;
+ PMColorEdit* m_pScatteringColorEdit;
+ QLabel* m_pScatteringEccentricityLabel;
+ PMFloatEdit* m_pScatteringEccentricityEdit;
+ PMFloatEdit* m_pScatteringExtinctionEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmmemento.cpp b/kpovmodeler/pmmemento.cpp
new file mode 100644
index 00000000..84f52a6e
--- /dev/null
+++ b/kpovmodeler/pmmemento.cpp
@@ -0,0 +1,220 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmmemento.h"
+#include "pmdebug.h"
+
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, int data )
+ : PMVariant( data )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, unsigned int data )
+ : PMVariant( data )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, double data )
+ : PMVariant( data )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, bool data )
+ : PMVariant( data )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, PMThreeState data )
+ : PMVariant( data )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, const QString& data )
+ : PMVariant( data )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, const PMVector& data )
+ : PMVariant( data )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, const PMColor& data )
+ : PMVariant( data )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+PMMementoData::PMMementoData( PMMetaObject* classType, int vID, PMObject* obj )
+ : PMVariant( obj )
+{
+ m_objectType = classType;
+ m_valueID = vID;
+}
+
+PMMemento::PMMemento( PMObject* originator )
+{
+ m_data.setAutoDelete( true );
+ m_changedObjects.setAutoDelete( true );
+ m_pIDData = 0;
+ m_pOriginatorChange = 0;
+ m_pOriginator = originator;
+}
+
+PMMemento::~PMMemento( )
+{
+ m_data.clear( );
+ m_changedObjects.clear( );
+ // m_pOriginatorChange is in m_changedObjects and is already deleted!
+}
+
+PMMementoData* PMMemento::findData( PMMetaObject* classType, int vID ) const
+{
+ PMMementoDataIterator it( m_data );
+
+ for( ; it.current( ); ++it )
+ {
+ if( ( it.current( )->objectType( ) == classType ) &&
+ ( it.current( )->valueID( ) == vID ) )
+ return it.current( );
+ }
+ return 0;
+}
+
+void PMMemento::addData( PMMementoData* data )
+{
+ m_data.append( data );
+ addChange( PMCData );
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, const int data )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, data ) );
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, const unsigned int data )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, data ) );
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, const double data )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, data ) );
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, const bool data )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, data ) );
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, const PMThreeState data )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, data ) );
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, const QString& data )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, data ) );
+}
+
+void PMMemento::addIDChange( PMMetaObject* classType, int vID, const QString& data )
+{
+ if( !findData( classType, vID ) )
+ {
+ PMMementoData* d = new PMMementoData( classType, vID, data );
+ addData( d );
+ m_pIDData = d;
+ }
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, const PMVector& data )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, data ) );
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, const PMColor& data )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, data ) );
+}
+
+void PMMemento::addData( PMMetaObject* classType, int vID, PMObject* obj )
+{
+ if( !findData( classType, vID ) )
+ addData( new PMMementoData( classType, vID, obj ) );
+}
+
+QString PMMemento::oldID( ) const
+{
+ if( m_pIDData )
+ return m_pIDData->stringData( );
+ return QString::null;
+}
+
+void PMMemento::addChangedObject( PMObject* obj, int mode )
+{
+ PMObjectChangeListIterator it( m_changedObjects );
+ PMObjectChange* change = 0;
+
+ while( it.current( ) && !change )
+ {
+ if( it.current( )->object( ) == obj )
+ change = it.current( );
+ else
+ ++it;
+ }
+
+ if( change )
+ change->addMode( mode );
+ else
+ m_changedObjects.append( new PMObjectChange( obj, mode ) );
+}
+
+void PMMemento::addChange( int mode )
+{
+ if( !m_pOriginatorChange )
+ {
+ m_pOriginatorChange = new PMObjectChange( m_pOriginator, PMCData );
+ m_changedObjects.append( m_pOriginatorChange );
+ }
+ m_pOriginatorChange->addMode( mode );
+}
diff --git a/kpovmodeler/pmmemento.h b/kpovmodeler/pmmemento.h
new file mode 100644
index 00000000..a3ea9c98
--- /dev/null
+++ b/kpovmodeler/pmmemento.h
@@ -0,0 +1,318 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMOBJECTMEMENTO_H
+#define PMOBJECTMEMENTO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmvariant.h"
+#include "pmcommand.h"
+#include "pmmetaobject.h"
+#include <qstring.h>
+#include <qptrlist.h>
+
+/**
+ * Class used by @ref PMObjectMemento to store one value.
+ *
+ * Each piece of data has two IDs: The type of the povray class that stored
+ * the data and a unique ID within this class.
+ *
+ * @see PMMementoDataIterator
+ */
+
+class PMMementoData : public PMVariant
+{
+public:
+ /**
+ * Stores an integer
+ */
+ PMMementoData( PMMetaObject* classType, int vID, int data );
+ /**
+ * Stores an unsigned integer
+ */
+ PMMementoData( PMMetaObject* classType, int vID, unsigned int data );
+ /**
+ * Stores double
+ */
+ PMMementoData( PMMetaObject* classType, int vID, double data );
+ /**
+ * Stores a boolean
+ */
+ PMMementoData( PMMetaObject* classType, int vID, bool data );
+ /**
+ * Stores a @ref PMThreeState
+ */
+ PMMementoData( PMMetaObject* classType, int vID, PMThreeState data );
+ /**
+ * Stores a string
+ */
+ PMMementoData( PMMetaObject* classType, int vID, const QString& data );
+ /**
+ * Stores a @ref PMVector
+ */
+ PMMementoData( PMMetaObject* classType, int vID, const PMVector& data );
+ /**
+ * Stores a @ref PMColor
+ */
+ PMMementoData( PMMetaObject* classType, int vID, const PMColor& data );
+ /**
+ * Stores a pointer to a PMObject
+ */
+ PMMementoData( PMMetaObject* classType, int vID, PMObject* obj );
+
+ /**
+ * Returns the object type of the povray class that stored the data
+ */
+ PMMetaObject* objectType( ) const { return m_objectType; }
+ /**
+ * Returns the ID of the stored value
+ */
+ int valueID( ) const { return m_valueID; }
+
+private:
+ /**
+ * Class that stored the information
+ */
+ PMMetaObject* m_objectType;
+ /**
+ * The unique ID within the m_objectType
+ */
+ int m_valueID;
+};
+
+typedef QPtrList<PMMementoData> PMMementoDataList;
+
+
+/**
+ * Helper class to store information about changed objects in @ref PMMemento
+ */
+class PMObjectChange
+{
+public:
+ /**
+ * Creates change information for the object obj.
+ *
+ * mode is a bitwise combination of @ref PMChange constants.
+ */
+ PMObjectChange( PMObject* obj, int mode )
+ {
+ m_pObject = obj;
+ m_mode = mode;
+ }
+ PMObject* object( ) const { return m_pObject; }
+ int mode( ) const { return m_mode; }
+ void addMode( int mode ) { m_mode |= mode; }
+private:
+ PMObject* m_pObject;
+ int m_mode;
+};
+
+typedef QPtrList<PMObjectChange> PMObjectChangeList;
+typedef QPtrListIterator<PMObjectChange> PMObjectChangeListIterator;
+
+/**
+ * Class that stores the data of povray objects for undo/redo information
+ *
+ * This class should provide enough functionality for most objects. If not,
+ * subclass this class.
+ *
+ * All objects have to use the memento class of its base class or an inherited
+ * one.
+ *
+ * Only the changed attributes of an object are saved.
+ *
+ * See class @ref PMMementoData to see how values are stored.
+ */
+class PMMemento
+{
+ friend class PMMementoDataIterator;
+public:
+ /**
+ * Creates a memento for the object originator
+ */
+ PMMemento( PMObject* originator );
+ /**
+ * Deletes the memento
+ */
+ virtual ~PMMemento( );
+
+ /**
+ * Returns a pointer to the originator
+ */
+ PMObject* originator( ) const { return m_pOriginator; }
+ /**
+ * Returns a pointer to the memento data or 0 if this value is not
+ * stored
+ */
+ PMMementoData* findData( PMMetaObject* classType, int vID ) const;
+ /**
+ * Adds the data object to the list of stored data. The menento may not
+ * contain this information (objType and vID).
+ *
+ * The memento becomes the owner of this object.*/
+ void addData( PMMementoData* data );
+
+ /**
+ * Adds an integer data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, const int data );
+
+ /**
+ * Adds an unsigned data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, const unsigned int data );
+
+ /**
+ * Adds an double data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, const double data );
+
+ /**
+ * Adds an bool data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, const bool data );
+
+ /**
+ * Adds an @ref PMThreeState data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, const PMThreeState data );
+
+ /**
+ * Adds an @ref QString data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, const QString& data );
+
+ /**
+ * Adds an @ref PMVector data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, const PMVector& data );
+
+ /**
+ * Adds an @ref PMColor data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, const PMColor& data );
+
+ /**
+ * Adds an PMObject pointer data object. Will be ignored if the memento
+ * already contains this data
+ */
+ void addData( PMMetaObject* classType, int vID, PMObject* obj );
+
+ /**
+ * Call this to store an id change
+ */
+ void addIDChange( PMMetaObject* classType, int vID, const QString& data );
+
+ /**
+ * Returns true if the memento contains changed data
+ */
+ bool containsChanges( ) const { return ( m_changedObjects.count( ) > 0 ); }
+
+ /**
+ * Call this function, if you stored some data that changed
+ * the view structure of the originator
+ */
+ void setViewStructureChanged( ) { addChange( PMCViewStructure ); }
+ /**
+ * Call this function, if you stored some data that changed
+ * the name or pixmap of the originator
+ */
+ void setDescriptionChanged( ) { addChange( PMCDescription ); }
+
+ /**
+ * Returns true if the id of a @ref PMDeclare was changed
+ */
+ bool idChanged( ) const { return m_pIDData != 0; }
+ /**
+ * Returns the old id
+ */
+ QString oldID( ) const;
+ /**
+ * If one object is changed, other objects can be changed as well.
+ *
+ * For example, if the linked declare of an object link is changed,
+ * the old and new declare are changed as well (Remove the old link,
+ * add the new link).
+ *
+ * This function returns an iterator to the list of all changed objects.
+ * The first object is the originator.
+ */
+ PMObjectChangeListIterator changedObjects( )
+ { return PMObjectChangeListIterator( m_changedObjects ); }
+ /**
+ * Adds the object to the list of changed objects.
+ * Note that the originator is added automatically
+ */
+ void addChangedObject( PMObject* obj, int mode );
+protected:
+ /**
+ * Adds the change to the originator change object
+ */
+ void addChange( int mode );
+private:
+ /**
+ * The stored values
+ */
+ PMMementoDataList m_data;
+ /**
+ * Additional pointer to the memento data for id changes of
+ * @ref PMDeclare objects
+ */
+ PMMementoData* m_pIDData;
+ /**
+ * List of changes
+ */
+ QPtrList<PMObjectChange> m_changedObjects;
+ PMObjectChange* m_pOriginatorChange;
+ PMObject* m_pOriginator;
+};
+
+
+/**
+ * Iterator for memento data
+ */
+class PMMementoDataIterator : public QPtrListIterator<PMMementoData>
+{
+public:
+ PMMementoDataIterator( const PMMemento& m )
+ : QPtrListIterator<PMMementoData>( m.m_data )
+ {
+ }
+ PMMementoDataIterator( const PMMemento* m )
+ : QPtrListIterator<PMMementoData>( m->m_data )
+ {
+ }
+ PMMementoDataIterator( const PMMementoDataList& l )
+ : QPtrListIterator<PMMementoData>( l )
+ {
+ }
+};
+
+#endif
diff --git a/kpovmodeler/pmmesh.cpp b/kpovmodeler/pmmesh.cpp
new file mode 100644
index 00000000..571170a9
--- /dev/null
+++ b/kpovmodeler/pmmesh.cpp
@@ -0,0 +1,557 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmesh.h"
+
+#include <klocale.h>
+#include "pmxmlhelper.h"
+#include "pmmeshedit.h"
+#include "pmmemento.h"
+#include "pmtriangle.h"
+#include "pm3dcontrolpoint.h"
+#include "pmvectorcontrolpoint.h"
+
+const PMVector insideVectorDefault = PMVector( 0.0, 0.0, 0.0 );
+
+PMDefinePropertyClass( PMMesh, PMMeshProperty );
+
+class PMMeshMemento : public PMMemento
+{
+public:
+ /**
+ * Creates a memento for the object originator
+ */
+ PMMeshMemento( PMObject* originator ) : PMMemento( originator )
+ {
+ m_bTriangleMementosSaved = false;
+ m_triangleMementos.setAutoDelete( true );
+ }
+ /**
+ * Deletes the memento
+ */
+ virtual ~PMMeshMemento( )
+ {
+ m_triangleMementos.clear( );
+ }
+
+ /**
+ * Saves the triangles memento data
+ */
+ void setTriangleMementos( const QPtrList<PMMemento>& list )
+ {
+ if ( !m_bTriangleMementosSaved )
+ {
+ QPtrListIterator<PMMemento> Itr( list );
+ PMMemento* m;
+ while( ( m = Itr.current( ) ) != 0 )
+ {
+ m_triangleMementos.append( m );
+ ++Itr;
+ }
+
+ m_bTriangleMementosSaved = true;
+ addChange( PMCData );
+ }
+ }
+ /**
+ * Returns the triangles memento data
+ */
+ QPtrList<PMMemento> triangleMementos( ) const
+ {
+ if ( !m_bTriangleMementosSaved )
+ kdError( PMArea ) << "Triangles mementos not saved in PMMeshMemento::triangleMementos\n";
+ return m_triangleMementos;
+ }
+ /**
+ * Returns true if the triangle mementos have been saved
+ */
+ bool triangleMementosSaved( ) const { return m_bTriangleMementosSaved; }
+private:
+ QPtrList<PMMemento> m_triangleMementos;
+ bool m_bTriangleMementosSaved;
+};
+
+PMMetaObject* PMMesh::s_pMetaObject = 0;
+PMObject* createNewMesh( PMPart* part )
+{
+ return new PMMesh( part );
+}
+
+PMMesh::PMMesh( PMPart* part )
+ : Base( part )
+{
+ m_hierarchy = true;
+ m_enableInsideVector = false;
+ m_insideVector = insideVectorDefault;
+}
+
+PMMesh::PMMesh( const PMMesh& m )
+ : Base( m )
+{
+ m_hierarchy = m.m_hierarchy;
+ m_enableInsideVector = m.m_enableInsideVector;
+ m_insideVector = m.m_insideVector;
+}
+
+PMMesh::~PMMesh( )
+{
+}
+
+QString PMMesh::description( ) const
+{
+ return i18n( "mesh" );
+}
+
+void PMMesh::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "hierarchy", m_hierarchy );
+ e.setAttribute( "enable_inside_vector", m_enableInsideVector );
+ e.setAttribute( "inside_vector", m_insideVector.serializeXML( ) );
+ Base::serialize( e, doc );
+}
+
+void PMMesh::readAttributes( const PMXMLHelper& h )
+{
+ m_hierarchy = h.boolAttribute( "hierarchy", true );
+ m_enableInsideVector = h.boolAttribute( "enable_inside_vector", false );
+ m_insideVector = h.vectorAttribute( "inside_vector", insideVectorDefault );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMMesh::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Mesh", Base::metaObject( ), createNewMesh );
+
+ s_pMetaObject->addProperty(
+ new PMMeshProperty( "hierarchy", &PMMesh::setHierarchy, &PMMesh::hierarchy ) );
+ s_pMetaObject->addProperty(
+ new PMMeshProperty( "insideVectorEnabled", &PMMesh::enableInsideVector, &PMMesh::isInsideVectorEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMMeshProperty( "insideVector", &PMMesh::setInsideVector, &PMMesh::insideVector ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMMesh::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMMesh::setHierarchy( bool h )
+{
+ if( h != m_hierarchy )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHierarchyID, m_hierarchy );
+ m_hierarchy = h;
+ }
+}
+
+void PMMesh::enableInsideVector( bool eiv )
+{
+ if( eiv != m_enableInsideVector )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableInsideVectorID, m_enableInsideVector );
+ m_enableInsideVector = eiv;
+ }
+}
+
+void PMMesh::setInsideVector( const PMVector& iv )
+{
+ if( iv != m_insideVector )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMInsideVectorID, m_insideVector );
+ m_insideVector = iv;
+ }
+}
+
+PMDialogEditBase* PMMesh::editWidget( QWidget* parent ) const
+{
+ return new PMMeshEdit( parent );
+}
+
+void PMMesh::createMemento( )
+{
+ delete m_pMemento;
+ m_pMemento = new PMMeshMemento( this );
+}
+
+void PMMesh::restoreMemento( PMMemento* s )
+{
+ PMMeshMemento* m = ( PMMeshMemento * ) s;
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMHierarchyID:
+ setHierarchy( data->boolData( ) );
+ break;
+ case PMEnableInsideVectorID:
+ enableInsideVector( data->boolData( ) );
+ break;
+ case PMInsideVectorID:
+ setInsideVector( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMMesh::restoreMemento\n";
+ break;
+ }
+ }
+ }
+
+ if ( m->triangleMementosSaved( ) )
+ {
+ int numChildren = countChildren( );
+ PMMemento* tm;
+ QPtrList<PMMemento> list = m->triangleMementos( );
+ QPtrListIterator<PMMemento> Itr( list );
+ for ( int i = 0; i < numChildren && ( tm = Itr.current( ) ) != 0; ++i, ++Itr )
+ childAt( i )->restoreMemento( tm );
+ }
+
+ Base::restoreMemento( s );
+}
+
+void PMMesh::controlPoints( PMControlPointList& list )
+{
+ unsigned numChildren = countChildren();
+ PMTriangle *obj;
+ pointToPoint ptp;
+ bool found;
+ PMVector point, normal;
+ PMControlPoint* listP;
+ PM3DControlPoint* cp;
+ PMVectorControlPoint* vp;
+ int currentPoint = 0;
+ int firstNormal = numChildren * 3;
+ int currentNormal = firstNormal;
+
+ m_pointToPointList.clear( );
+ for ( unsigned i = 0; i < numChildren; ++i )
+ {
+ if ( childAt( i )->isA( "Triangle" ) )
+ {
+
+ obj = ( PMTriangle * ) childAt( i );
+ ptp.object = obj;
+ for ( unsigned j = 0; j < 3; ++j )
+ {
+ found = false;
+ ptp.pointID = j;
+ point = obj->point( j );
+
+ for( listP = list.first( ); listP; listP = list.next( ) )
+ {
+ if ( listP->id( ) < firstNormal && point == listP->position( ) )
+ {
+ found = true;
+ ptp.listID = listP->id( );
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ cp = new PM3DControlPoint( point, currentPoint,
+ i18n( "Mesh Point " + currentPoint ) );
+ list.append( cp );
+ ptp.listID = currentPoint++;
+ }
+
+ m_pointToPointList.append( ptp );
+
+ if ( obj->isSmoothTriangle( ) )
+ {
+ found = false;
+ ptp.pointID = j + 3;
+ normal = obj->normal( j );
+
+ for ( listP = list.first( ); listP; listP = list.next( ) )
+ {
+ if ( listP->id( ) >= firstNormal )
+ {
+ vp = ( PMVectorControlPoint* ) listP;
+ if ( vp->basePoint( ) == point &&
+ vp->vector( ) == normal )
+ {
+ found = true;
+ ptp.listID = listP->id( );
+ break;
+ }
+ }
+ }
+
+ if ( !found )
+ {
+ vp = new PMVectorControlPoint( point, normal, currentNormal,
+ i18n( "Mesh Normal " + currentNormal ) );
+ list.append( vp );
+ ptp.listID = currentNormal++;
+ }
+
+ m_pointToPointList.append( ptp );
+ }
+
+ }
+ }
+ }
+}
+
+void PMMesh::controlPointsChangedList( PMControlPointList& list, PMObjectList& objList )
+{
+ int numChildren = countChildren( );
+ PMControlPoint* p;
+ QValueList<pointToPoint>::ConstIterator ptpItr = m_pointToPointList.begin( );
+ QPtrList<PMMemento> mementoList;
+ PMTriangle *obj;
+ PMVector p0, p1, p2;
+ PM3DControlPoint* cp0, * cp1, * cp2;
+ bool bp0, bp1, bp2;
+ PMVector n0, n1, n2;
+ PMVectorControlPoint* cn0, * cn1, * cn2;
+ bool bn0, bn1, bn2;
+ PMVector triangleNormal;
+ double d, normalDirection = 1.0;
+ bool found, validNormal, validTriangles = true;
+ int listID, pointID, numCP;
+
+ // have to cache changed values because checking once changes them to false
+ QMemArray<bool> changed( list.count( ) );
+ p = list.first( );
+ for ( int i = 0; p; ++i, p = list.next( ) )
+ changed[i] = p->changed( );
+
+ for ( int i = 0; i < numChildren && validTriangles; ++i )
+ {
+ if ( childAt( i )->isA( "Triangle" ) )
+ {
+ obj = ( PMTriangle* )childAt( i );
+ obj->createMemento( );
+ objList.append( obj );
+ validNormal = false;
+
+ if ( obj->isSmoothTriangle( ) )
+ numCP = 6;
+ else
+ numCP = 3;
+
+ cp0 = cp1 = cp2 = 0;
+ cn0 = cn1 = cn2 = 0;
+
+ bp0 = bp1 = bp2 = bn0 = bn1 = bn2 = false;
+
+ for ( int j = 0; j < numCP; ++j, ++ptpItr )
+ {
+
+ listID = (*ptpItr).listID;
+ pointID = (*ptpItr).pointID;
+ found = false;
+ p = list.first( );
+ for ( int k = 0; p && !found; p = list.next( ), ++k )
+ {
+ if( listID == p->id( ) )
+ {
+ switch( pointID )
+ {
+ case 0:
+ cp0 = ( PM3DControlPoint* ) p;
+ p0 = cp0->point( );
+ bp0 = changed[ k ];
+ break;
+ case 1:
+ cp1 = ( PM3DControlPoint* ) p;
+ p1 = cp1->point( );
+ bp1 = changed[ k ];
+ break;
+ case 2:
+ cp2 = ( PM3DControlPoint* ) p;
+ p2 = cp2->point( );
+ bp2 = changed[ k ];
+ break;
+ case 3:
+ cn0 = ( PMVectorControlPoint* ) p;
+ n0 = cn0->vector( );
+ bn0 = changed[ k ];
+ break;
+ case 4:
+ cn1 = ( PMVectorControlPoint* ) p;
+ n1 = cn1->vector( );
+ bn1 = changed[ k ];
+ break;
+ case 5:
+ cn2 = ( PMVectorControlPoint* ) p;
+ n2 = cn2->vector( );
+ bn2 = changed[ k ];
+ break;
+ default:
+ break;
+ }
+ found = true;
+ }
+ }
+ }
+
+ if ( obj->isSmoothTriangle( ) )
+ {
+ triangleNormal = PMVector::cross( obj->point( 1 ) - obj->point( 0 ),
+ obj->point( 2 ) - obj->point( 0 ) );
+ normalDirection = PMVector::dot( triangleNormal, obj->normal( 0 ) );
+ if( approxZero( normalDirection ) )
+ normalDirection = PMVector::dot( triangleNormal, obj->normal( 1 ) );
+ if( approxZero( normalDirection ) )
+ normalDirection = PMVector::dot( triangleNormal, obj->normal( 2 ) );
+ if( normalDirection < 0 )
+ triangleNormal = -triangleNormal;
+ if( !approxZero( triangleNormal.abs( ) ) )
+ {
+ validNormal = true;
+ triangleNormal /= triangleNormal.abs( );
+ }
+ }
+
+ if ( bp0 )
+ {
+ if ( !( p0.approxEqual( p1 ) || p0.approxEqual( p2 ) ) )
+ obj->setPoint( 0, p0 );
+ else
+ {
+ validTriangles = false;
+ cp0->setPoint( obj->point( 0 ) );
+ break;
+ }
+ }
+
+ if ( bp1 )
+ {
+ if ( !( p1.approxEqual( p0 ) || p1.approxEqual( p2 ) ) )
+ obj->setPoint( 1, p1 );
+ else
+ {
+ validTriangles = false;
+ cp1->setPoint( obj->point( 1 ) );
+ break;
+ }
+ }
+
+ if ( bp2 )
+ {
+ if ( !( p2.approxEqual( p0 ) || p2.approxEqual( p1 ) ) )
+ obj->setPoint( 2, p2 );
+ else
+ {
+ validTriangles = false;
+ cp2->setPoint( obj->point( 2 ) );
+ break;
+ }
+ }
+
+ if ( obj->isSmoothTriangle( ) )
+ {
+ if ( bn0 )
+ {
+ if( validNormal )
+ {
+ d = PMVector::dot( triangleNormal, n0 );
+ if( d > 0 )
+ obj->setNormal( 0, n0 );
+ else
+ {
+ obj->setNormal( 0, n0 - ( d - 1e-5 ) * triangleNormal );
+ cn0->setVector( obj->normal( 0 ) );
+ }
+ }
+ else
+ cn0->setVector( obj->normal( 0 ) );
+ }
+
+ if ( bn1 )
+ {
+ if( validNormal )
+ {
+ d = PMVector::dot( triangleNormal, n1 );
+ if( d > 0 )
+ obj->setNormal( 1, n1 );
+ else
+ {
+ obj->setNormal( 1, n1 - ( d - 1e-5 ) * triangleNormal );
+ cn1->setVector( obj->normal( 1 ) );
+ }
+ }
+ else
+ cn1->setVector( obj->normal( 1 ) );
+ }
+
+ if ( bn2 )
+ {
+ if( validNormal )
+ {
+ d = PMVector::dot( triangleNormal, n2 );
+ if( d > 0 )
+ obj->setNormal( 2, n2 );
+ else
+ {
+ obj->setNormal( 2, n2 - ( d - 1e-5 ) * triangleNormal );
+ cn2->setVector( obj->normal( 2 ) );
+ }
+ }
+ else
+ cn2->setVector( obj->normal( 2 ) );
+ }
+ }
+
+ mementoList.append( obj->takeMemento( ) );
+
+ if ( !validTriangles )
+ {
+ PMMemento *tm;
+ for ( int j = i; j >= 0; --j )
+ {
+ if ( ( tm = mementoList.getLast( ) ) )
+ {
+ childAt( j )->restoreMemento( tm );
+ delete tm;
+ mementoList.removeLast( );
+ }
+ }
+ }
+ }
+ }
+
+ if ( validTriangles )
+ {
+ if ( m_pMemento )
+ ( ( PMMeshMemento * ) m_pMemento )->setTriangleMementos( mementoList );
+ objList.append( this );
+ setViewStructureChanged( );
+ }
+}
diff --git a/kpovmodeler/pmmesh.h b/kpovmodeler/pmmesh.h
new file mode 100644
index 00000000..4045d3ab
--- /dev/null
+++ b/kpovmodeler/pmmesh.h
@@ -0,0 +1,142 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMESH_H
+#define PMMESH_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+
+class PMTriangle;
+
+/**
+ * Class for povray mesh objects.
+ */
+class PMMesh : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMMesh object
+ */
+ PMMesh( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMMesh( const PMMesh& m );
+
+ /**
+ * deletes the PMMesh object
+ */
+ virtual ~PMMesh( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMMesh( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMMeshEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmmesh" ); }
+
+ /**
+ * Returns the hierarchy flag
+ */
+ bool hierarchy( ) const { return m_hierarchy; }
+ /**
+ * Sets the type of the csg
+ */
+ void setHierarchy( bool h );
+
+ /**
+ * Returns true if the inside vector is enabled
+ */
+ bool isInsideVectorEnabled( ) const { return m_enableInsideVector; }
+ /**
+ * Sets the inside vector flag
+ */
+ void enableInsideVector( bool eiv );
+
+ /**
+ * Returns the inside vector
+ */
+ PMVector insideVector( ) const { return m_insideVector; }
+ /**
+ * Sets the inside vector
+ */
+ void setInsideVector( const PMVector& iv );
+
+ /** */
+ virtual void createMemento( );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChangedList( PMControlPointList& list, PMObjectList& objList );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMMeshMementoID { PMHierarchyID, PMEnableInsideVectorID,
+ PMInsideVectorID };
+
+ bool m_hierarchy;
+ bool m_enableInsideVector;
+ PMVector m_insideVector;
+
+ static PMMetaObject* s_pMetaObject;
+
+ /**
+ * Point to point structure for changes with control points
+ */
+ struct pointToPoint {
+ PMTriangle *object;
+ int pointID;
+ int listID;
+ };
+
+ /**
+ * List of point to point structures
+ */
+ QValueList<pointToPoint> m_pointToPointList;
+};
+
+#endif
diff --git a/kpovmodeler/pmmeshedit.cpp b/kpovmodeler/pmmeshedit.cpp
new file mode 100644
index 00000000..0b0e2269
--- /dev/null
+++ b/kpovmodeler/pmmeshedit.cpp
@@ -0,0 +1,100 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmeshedit.h"
+#include "pmmesh.h"
+#include "pmvectoredit.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+
+#include <klocale.h>
+
+PMMeshEdit::PMMeshEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMMeshEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+ m_pHierarchy = new QCheckBox( i18n( "Hierarchy" ), this );
+ m_pEnableInsideVector = new QCheckBox( i18n( "Inside vector:" ), this );
+ m_pInsideVector = new PMVectorEdit( "x", "y", "z", this );
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( m_pHierarchy );
+ layout->addStretch( 1 );
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( m_pEnableInsideVector );
+ layout->addWidget( m_pInsideVector );
+ layout->addStretch( 1 );
+
+ connect( m_pHierarchy, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnableInsideVector, SIGNAL( clicked( ) ), SLOT( slotInsideVectorClicked( ) ) );
+ connect( m_pInsideVector, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMMeshEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Mesh" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMMesh* ) o;
+
+ m_pHierarchy->setChecked( m_pDisplayedObject->hierarchy( ) );
+ m_pHierarchy->setEnabled( !readOnly );
+ m_pEnableInsideVector->setChecked( m_pDisplayedObject->isInsideVectorEnabled( ) );
+ m_pEnableInsideVector->setEnabled( !readOnly );
+ m_pInsideVector->setVector( m_pDisplayedObject->insideVector( ) );
+ m_pInsideVector->setReadOnly( readOnly );
+ slotInsideVectorClicked( );
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMMeshEdit: Can't display object\n";
+}
+
+void PMMeshEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setHierarchy( m_pHierarchy->isChecked( ) );
+ m_pDisplayedObject->enableInsideVector( m_pEnableInsideVector->isChecked( ) );
+ m_pDisplayedObject->setInsideVector( m_pInsideVector->vector( ) );
+ }
+}
+
+bool PMMeshEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+void PMMeshEdit::slotInsideVectorClicked( )
+{
+ if( m_pEnableInsideVector->isChecked( ) )
+ m_pInsideVector->setEnabled( true );
+ else
+ m_pInsideVector->setEnabled( false );
+ emit dataChanged( );
+}
+
+#include "pmmeshedit.moc"
diff --git a/kpovmodeler/pmmeshedit.h b/kpovmodeler/pmmeshedit.h
new file mode 100644
index 00000000..1a778ac8
--- /dev/null
+++ b/kpovmodeler/pmmeshedit.h
@@ -0,0 +1,67 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMESHEDIT_H
+#define PMMESHEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMMesh;
+class QCheckBox;
+class PMVectorEdit;
+
+/**
+ * Dialog edit class for @ref PMMesh
+ */
+class PMMeshEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMMeshEdit with parent and name
+ */
+ PMMeshEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+protected slots:
+ void slotInsideVectorClicked( );
+private:
+ PMMesh* m_pDisplayedObject;
+
+ QCheckBox* m_pHierarchy;
+ QCheckBox* m_pEnableInsideVector;
+ PMVectorEdit* m_pInsideVector;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmmessage.cpp b/kpovmodeler/pmmessage.cpp
new file mode 100644
index 00000000..5587181f
--- /dev/null
+++ b/kpovmodeler/pmmessage.cpp
@@ -0,0 +1,43 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmmessage.h"
+
+PMMessage::PMMessage( )
+{
+ m_pObject = 0;
+}
+
+PMMessage::PMMessage( const QString& text, PMObject* object )
+{
+ m_sText = text;
+ m_pObject = object;
+}
+
+PMMessage::PMMessage( const PMMessage& m )
+{
+ m_sText = m.m_sText;
+ m_pObject = m.m_pObject;
+}
+
+PMMessage& PMMessage::operator=( const PMMessage& m )
+{
+ m_sText = m.m_sText;
+ m_pObject = m.m_pObject;
+ return *this;
+}
+
diff --git a/kpovmodeler/pmmessage.h b/kpovmodeler/pmmessage.h
new file mode 100644
index 00000000..1247ccb0
--- /dev/null
+++ b/kpovmodeler/pmmessage.h
@@ -0,0 +1,79 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMMESSAGE_H
+#define PMMESSAGE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+#include <qvaluelist.h>
+#include <qstring.h>
+
+/**
+ * Class for messages in the @ref PMErrorDialog
+ */
+class PMMessage
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMMessage( );
+ /**
+ * Creates a message with a text and optionally with
+ * a link to an object
+ */
+ PMMessage( const QString& text, PMObject* object = 0 );
+ /**
+ * Copy constructor
+ */
+ PMMessage( const PMMessage& m );
+ /**
+ * Assignment operator
+ */
+ PMMessage& operator=( const PMMessage& m );
+
+ /**
+ * Returns the message text
+ */
+ QString text( ) const { return m_sText; }
+ /**
+ * Sets the message text
+ */
+ void setText( const QString& text ) { m_sText = text; }
+ /**
+ * Returns the linked object or 0
+ */
+ PMObject* linkedObject( ) const { return m_pObject; }
+ /**
+ * Sets the linked object
+ */
+ void setLinkedObject( PMObject* o ) { m_pObject = o; }
+
+private:
+ QString m_sText;
+ PMObject* m_pObject;
+};
+
+typedef QValueList<PMMessage> PMMessageList;
+
+#endif
diff --git a/kpovmodeler/pmmetaobject.cpp b/kpovmodeler/pmmetaobject.cpp
new file mode 100644
index 00000000..a7e98b9b
--- /dev/null
+++ b/kpovmodeler/pmmetaobject.cpp
@@ -0,0 +1,95 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmmetaobject.h"
+
+PMPropertyBase::PMPropertyBase( const QString& name,
+ PMVariant::PMVariantDataType t,
+ bool readOnly, bool writeOnly )
+{
+ m_name = name;
+ m_type = t;
+ m_pEnumList = 0;
+ m_readOnly = readOnly;
+ m_writeOnly = writeOnly;
+}
+
+PMPropertyBase::PMPropertyBase( const PMPropertyBase& p )
+{
+ m_name = p.m_name;
+ m_type = p.m_type;
+ m_readOnly = p.m_readOnly;
+ m_writeOnly = p.m_writeOnly;
+
+ if( p.m_pEnumList )
+ m_pEnumList = new QStringList( *( p.m_pEnumList ) );
+ else
+ m_pEnumList = 0;
+}
+
+PMPropertyBase::~PMPropertyBase( )
+{
+ delete m_pEnumList;
+}
+
+bool PMPropertyBase::setProperty( PMObject* obj, const PMVariant& v )
+{
+ if( m_readOnly )
+ return false;
+ PMVariant cp = v;
+ if( cp.convertTo( m_type ) )
+ return setProtected( obj, cp );
+ return false;
+}
+
+PMVariant PMPropertyBase::getProperty( const PMObject* obj )
+{
+ if( m_writeOnly )
+ return PMVariant( );
+ return getProtected( obj );
+}
+
+PMMetaObject::PMMetaObject( const QString& className, PMMetaObject* superClass,
+ PMObjectFactoryMethod factory )
+{
+ m_className = className;
+ m_pSuperClass = superClass;
+ m_factory = factory;
+
+ // add the properties of the super class to the dictionary
+ if( m_pSuperClass )
+ m_propertiesDict = superClass->m_propertiesDict;
+}
+
+PMMetaObject::~PMMetaObject( )
+{
+ m_properties.setAutoDelete( true );
+ m_properties.clear( );
+}
+
+void PMMetaObject::addProperty( PMPropertyBase* p )
+{
+ m_properties.append( p );
+ m_propertiesDict.insert( p->name( ), p );
+}
+
+PMObject* PMMetaObject::newObject( PMPart* part ) const
+{
+ if( m_factory )
+ return m_factory( part );
+ return 0;
+}
diff --git a/kpovmodeler/pmmetaobject.h b/kpovmodeler/pmmetaobject.h
new file mode 100644
index 00000000..f8daf2eb
--- /dev/null
+++ b/kpovmodeler/pmmetaobject.h
@@ -0,0 +1,416 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMMETAOBJECT_H
+#define PMMETAOBJECT_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qptrlist.h>
+#include <qdict.h>
+#include "pmvariant.h"
+
+class PMPart;
+
+/**
+ * Base class for all properties
+ */
+class PMPropertyBase
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMPropertyBase( const QString& name, PMVariant::PMVariantDataType t,
+ bool readOnly = false, bool writeOnly = false );
+ /**
+ * Copy constructor
+ */
+ PMPropertyBase( const PMPropertyBase& p );
+ /**
+ * Destructor
+ */
+ virtual ~PMPropertyBase( );
+
+ /**
+ * Returns the properties name
+ */
+ QString name( ) const { return m_name; }
+ /**
+ * Returns the data type
+ */
+ PMVariant::PMVariantDataType type( ) const { return m_type; }
+
+ /**
+ * Sets the property.
+ *
+ * Returns true if successful.
+ *
+ * Makes a type check and calls @ref setProtected on success.
+ */
+ bool setProperty( PMObject* obj, const PMVariant& );
+
+ /**
+ * Returns the property value
+ */
+ PMVariant getProperty( const PMObject* obj );
+
+ /**
+ * Returns the number of dimensions for array properties
+ * or 0 otherwise
+ */
+ virtual int dimensions( ) const { return 0; }
+ /**
+ * Has to be reimplemented for array properties.
+ *
+ * The first parameter is the dimension, the second the index.
+ */
+ virtual void setIndex( int /*dimension*/, int /*index*/ ) { };
+ /**
+ * Has to be reimplemented for array properties.
+ *
+ * Returns the current size for the object and dimension.
+ */
+ virtual int size( PMObject*, int /*dimension*/ ) const { return 0; }
+
+ /**
+ * Returns true if the property is an enum
+ */
+ virtual bool isEnum( ) const { return false; }
+ /**
+ * Returns the list of enum values
+ */
+ virtual QStringList enumValues( ) const { return QStringList( ); }
+
+ /**
+ * Returns true if the property is read-only. False by default
+ */
+ bool isReadOnly( ) const { return m_readOnly; }
+ /**
+ * Returns true if the property is write-only. False by default
+ */
+ bool isWriteOnly( ) const { return m_writeOnly; }
+
+protected:
+ /**
+ * Reimplement this function to call the correct object method.
+ *
+ * The variant is already converted to the correct type.
+ */
+ virtual bool setProtected( PMObject* obj, const PMVariant& ) = 0;
+
+ /**
+ * Reimplement this function to call the correct object method.
+ */
+ virtual PMVariant getProtected( const PMObject* obj ) = 0;
+
+private:
+ PMVariant::PMVariantDataType m_type;
+ QString m_name;
+ QStringList* m_pEnumList;
+ bool m_readOnly;
+ bool m_writeOnly;
+};
+
+typedef QPtrList<PMPropertyBase> PMPropertyList;
+typedef QDict<PMPropertyBase> PMPropertyDict;
+typedef QDictIterator<PMPropertyBase> PMPropertyIterator;
+
+/**
+ * Macro that defines a property class for a PMObject class
+ *
+ * Example: PMDefinePropertyClass( PMBox, PMProperty ); defines
+ * a class PMProperty that can store pointer to member functions
+ * for PMBox objects.
+ *
+ * Use only in .cpp files.
+ */
+
+#define PMDefinePropertyClass( ObjectClass, PropertyClass ) \
+class PropertyClass : public PMPropertyBase \
+{ \
+public: \
+ typedef void ( ObjectClass::*SetIntPtr ) ( int ); \
+ typedef void ( ObjectClass::*SetUnsignedPtr ) ( unsigned ); \
+ typedef void ( ObjectClass::*SetDoublePtr ) ( double ); \
+ typedef void ( ObjectClass::*SetBoolPtr ) ( bool ); \
+ typedef void ( ObjectClass::*SetThreeStatePtr )( PMThreeState ); \
+ typedef void ( ObjectClass::*SetStringPtr ) ( const QString& ); \
+ typedef void ( ObjectClass::*SetVectorPtr ) ( const PMVector& ); \
+ typedef void ( ObjectClass::*SetColorPtr ) ( const PMColor& ); \
+ typedef void ( ObjectClass::*SetObjectPtr ) ( PMObject* ); \
+ \
+ typedef int ( ObjectClass::*GetIntPtr ) ( void ) const; \
+ typedef unsigned ( ObjectClass::*GetUnsignedPtr ) ( void ) const; \
+ typedef double ( ObjectClass::*GetDoublePtr ) ( void ) const; \
+ typedef bool ( ObjectClass::*GetBoolPtr ) ( void ) const; \
+ typedef PMThreeState ( ObjectClass::*GetThreeStatePtr ) ( void ) const; \
+ typedef QString ( ObjectClass::*GetStringPtr ) ( void ) const; \
+ typedef PMVector ( ObjectClass::*GetVectorPtr ) ( void ) const; \
+ typedef PMColor ( ObjectClass::*GetColorPtr ) ( void ) const; \
+ typedef PMObject* ( ObjectClass::*GetObjectPtr ) ( void ) const; \
+ \
+ PropertyClass( const QString& name, SetIntPtr setFktn, GetIntPtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::Integer, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setInt = setFktn; \
+ m_getFunction.getInt = getFktn; \
+ } \
+ PropertyClass( const QString& name, SetUnsignedPtr setFktn, GetUnsignedPtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::Unsigned, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setUnsigned = setFktn; \
+ m_getFunction.getUnsigned = getFktn; \
+ } \
+ PropertyClass( const QString& name, SetDoublePtr setFktn, GetDoublePtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::Double, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setDouble = setFktn; \
+ m_getFunction.getDouble = getFktn; \
+ } \
+ PropertyClass( const QString& name, SetBoolPtr setFktn, GetBoolPtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::Bool, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setBool = setFktn; \
+ m_getFunction.getBool = getFktn; \
+ } \
+ PropertyClass( const QString& name, SetThreeStatePtr setFktn, GetThreeStatePtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::ThreeState, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setThreeState = setFktn; \
+ m_getFunction.getThreeState = getFktn; \
+ } \
+ PropertyClass( const QString& name, SetStringPtr setFktn, GetStringPtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::String, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setString = setFktn; \
+ m_getFunction.getString = getFktn; \
+ } \
+ PropertyClass( const QString& name, SetVectorPtr setFktn, GetVectorPtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::Vector, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setVector = setFktn; \
+ m_getFunction.getVector = getFktn; \
+ } \
+ PropertyClass( const QString& name, SetColorPtr setFktn, GetColorPtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::Color, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setColor = setFktn; \
+ m_getFunction.getColor = getFktn; \
+ } \
+ PropertyClass( const QString& name, SetObjectPtr setFktn, GetObjectPtr getFktn ) \
+ : PMPropertyBase( name, PMVariant::ObjectPointer, \
+ setFktn == 0, getFktn == 0 ) \
+ { \
+ m_setFunction.setObject = setFktn; \
+ m_getFunction.getObject = getFktn; \
+ } \
+ \
+protected: \
+ bool setProtected( PMObject* obj, const PMVariant& v ) \
+ { \
+ ObjectClass* o = ( ObjectClass* ) obj; \
+ switch( type( ) ) \
+ { \
+ case PMVariant::Integer: \
+ ( o->*( m_setFunction.setInt ) )( v.intData( ) ); \
+ break; \
+ case PMVariant::Unsigned: \
+ ( o->*( m_setFunction.setUnsigned ) )( v.unsignedData( ) ); \
+ break; \
+ case PMVariant::Double: \
+ ( o->*( m_setFunction.setDouble ) )( v.doubleData( ) ); \
+ break; \
+ case PMVariant::Bool: \
+ ( o->*( m_setFunction.setBool ) )( v.boolData( ) ); \
+ break; \
+ case PMVariant::ThreeState: \
+ ( o->*( m_setFunction.setThreeState ) )( v.threeStateData( ) ); \
+ break; \
+ case PMVariant::String: \
+ ( o->*( m_setFunction.setString ) )( v.stringData( ) ); \
+ break; \
+ case PMVariant::Vector: \
+ ( o->*( m_setFunction.setVector ) )( v.vectorData( ) ); \
+ break; \
+ case PMVariant::Color: \
+ ( o->*( m_setFunction.setColor ) )( v.colorData( ) ); \
+ break; \
+ case PMVariant::ObjectPointer: \
+ ( o->*( m_setFunction.setObject ) )( v.objectData( ) ); \
+ break; \
+ case PMVariant::None: \
+ break; \
+ } \
+ return true; \
+ } \
+ \
+ PMVariant getProtected( const PMObject* obj ) \
+ { \
+ const ObjectClass* o = ( const ObjectClass* ) obj; \
+ PMVariant result; \
+ \
+ switch( type( ) ) \
+ { \
+ case PMVariant::Integer: \
+ result.setInt( ( o->*( m_getFunction.getInt ) )( ) ); \
+ break; \
+ case PMVariant::Unsigned: \
+ result.setUnsigned( ( o->*( m_getFunction.getUnsigned ) )( ) ); \
+ break; \
+ case PMVariant::Double: \
+ result.setDouble( ( o->*( m_getFunction.getDouble ) )( ) ); \
+ break; \
+ case PMVariant::Bool: \
+ result.setBool( ( o->*( m_getFunction.getBool ) )( ) ); \
+ break; \
+ case PMVariant::ThreeState: \
+ result.setThreeState( ( o->*( m_getFunction.getThreeState ) )( ) ); \
+ break; \
+ case PMVariant::String: \
+ result.setString( ( o->*( m_getFunction.getString ) )( ) ); \
+ break; \
+ case PMVariant::Vector: \
+ result.setVector( ( o->*( m_getFunction.getVector ) )( ) ); \
+ break; \
+ case PMVariant::Color: \
+ result.setColor( ( o->*( m_getFunction.getColor ) )( ) ); \
+ break; \
+ case PMVariant::ObjectPointer: \
+ result.setObject( ( o->*( m_getFunction.getObject ) )( ) ); \
+ break; \
+ case PMVariant::None: \
+ break; \
+ } \
+ return result; \
+ } \
+ \
+private: \
+ union \
+ { \
+ SetIntPtr setInt; \
+ SetUnsignedPtr setUnsigned; \
+ SetDoublePtr setDouble; \
+ SetBoolPtr setBool; \
+ SetThreeStatePtr setThreeState; \
+ SetStringPtr setString; \
+ SetVectorPtr setVector; \
+ SetColorPtr setColor; \
+ SetObjectPtr setObject; \
+ } m_setFunction; \
+ \
+ union \
+ { \
+ GetIntPtr getInt; \
+ GetUnsignedPtr getUnsigned; \
+ GetDoublePtr getDouble; \
+ GetBoolPtr getBool; \
+ GetThreeStatePtr getThreeState; \
+ GetStringPtr getString; \
+ GetVectorPtr getVector; \
+ GetColorPtr getColor; \
+ GetObjectPtr getObject; \
+ } m_getFunction; \
+}
+// no semicolon, put a semicolon after the macro!
+
+
+typedef PMObject* ( *PMObjectFactoryMethod ) ( PMPart* );
+
+/**
+ * Meta information object for the @ref PMObject class.
+ *
+ * Stores information (class name, inheritance hierarchy,
+ * object properties) for each class.
+ */
+class PMMetaObject
+{
+public:
+ /**
+ * Creates a PMMetaObject. The class name has to be the class name
+ * without the PM prefix.
+ *
+ * factoryMethod is a function pointer to a factory method
+ * with signature PMObject* theMethod( PMPart* ) that returns
+ * a new object of that type. factoryMethod may be 0 for
+ * abstract classes.
+ */
+ PMMetaObject( const QString& className, PMMetaObject* superClass = 0,
+ PMObjectFactoryMethod factoryMethod = 0 );
+ /**
+ * Destructor
+ */
+ ~PMMetaObject( );
+
+ /**
+ * Returns the class name
+ */
+ QString className( ) const { return m_className; }
+ /**
+ * Returns the meta object of the super class
+ */
+ PMMetaObject* superClass( ) const { return m_pSuperClass; }
+ /**
+ * Returns a new object instance
+ */
+ PMObject* newObject( PMPart* part ) const;
+ /**
+ * Returns true if the class is an abstract class
+ * (if no factory method was set in the constructor)
+ */
+ bool isAbstract( ) const { return m_factory == 0; }
+
+ /**
+ * Adds a property.
+ *
+ * The meta object becomes the owner of the property object
+ */
+ void addProperty( PMPropertyBase* p );
+ /**
+ * Returns an iterator to the properties
+ */
+ PMPropertyIterator properties( ) const
+ {
+ return PMPropertyIterator( m_propertiesDict );
+ }
+ /**
+ * Returns a property by name or 0 if a property with the name
+ * doesn't exist.
+ */
+ PMPropertyBase* property( const QString& name ) const
+ {
+ return m_propertiesDict.find( name );
+ }
+
+private:
+ QString m_className;
+ PMMetaObject* m_pSuperClass;
+ PMPropertyList m_properties;
+ PMPropertyDict m_propertiesDict;
+ PMObjectFactoryMethod m_factory;
+};
+
+#endif
diff --git a/kpovmodeler/pmmovecommand.cpp b/kpovmodeler/pmmovecommand.cpp
new file mode 100644
index 00000000..1d70f3e0
--- /dev/null
+++ b/kpovmodeler/pmmovecommand.cpp
@@ -0,0 +1,478 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmmovecommand.h"
+#include "pmobject.h"
+#include "pmpart.h"
+#include "pmcommandmanager.h"
+#include "pmdeclare.h"
+#include "pmerrorflags.h"
+#include "pmrecursiveobjectiterator.h"
+#include "pmmemento.h"
+#include "pmdebug.h"
+
+#include <klocale.h>
+#include <qptrdict.h>
+
+PMMoveCommand::PMMoveCommand( PMObject* obj, PMObject* parent, PMObject* after )
+ : PMCommand( i18n( "Move %1" ).arg( obj->description( ) ) )
+{
+ m_pParent = parent;
+ m_pAfter = after;
+
+ if( obj->parent( ) )
+ {
+ m_infoList.append( new PMDeleteInfo( obj ) );
+ }
+ else
+ {
+ // object has no parent!
+ // top level objects can't be moved, move all child items
+ PMObject* tmp;
+ for( tmp = obj->firstChild( ); tmp; tmp = tmp->nextSibling( ) )
+ m_infoList.append( new PMDeleteInfo( tmp ) );
+ }
+
+ m_executed = false;
+ m_firstExecution = true;
+}
+
+PMMoveCommand::PMMoveCommand( const PMObjectList& list, PMObject* parent,
+ PMObject* after )
+ : PMCommand( i18n( "Move Objects" ) )
+{
+ PMObjectListIterator it( list );
+
+ for( ; it.current( ); ++it )
+ {
+ if( it.current( )->parent( ) )
+ m_infoList.append( new PMDeleteInfo( it.current( ) ) );
+ else
+ {
+ // object has no parent!
+ // top level objects can't be moved, move all child items
+ PMObject* tmp;
+ for( tmp = it.current( )->firstChild( ); tmp; tmp = tmp->nextSibling( ) )
+ m_infoList.append( new PMDeleteInfo( tmp ) );
+ }
+ }
+
+ m_pParent = parent;
+ m_pAfter = after;
+ m_executed = false;
+ m_firstExecution = true;
+}
+
+PMMoveCommand::~PMMoveCommand( )
+{
+ if( m_executed )
+ {
+ m_insertErrors.setAutoDelete( true );
+ m_insertErrors.clear( );
+ }
+}
+
+void PMMoveCommand::execute( PMCommandManager* theManager )
+{
+ if( !m_executed )
+ {
+ // remove objects
+ PMDeleteInfoListIterator it( m_infoList );
+ PMObject* prev = m_pAfter;
+ PMObject* obj;
+ bool error = false;
+ PMDeleteInfo* info = 0;
+ PMObject* parent;
+
+ for( it.toLast( ); it.current( ); --it )
+ {
+ info = it.current( );
+ parent = info->parent( );
+ // signal has to be emitted before the item is removed
+ theManager->cmdObjectChanged( info->deletedObject( ), PMCRemove );
+ if( m_firstExecution )
+ if( parent->dataChangeOnInsertRemove( )
+ && !parent->mementoCreated( ) )
+ parent->createMemento( );
+ parent->takeChild( info->deletedObject( ) );
+ }
+
+ // insert at new position
+ if( m_firstExecution )
+ if( m_pParent->dataChangeOnInsertRemove( )
+ && !m_pParent->mementoCreated( ) )
+ m_pParent->createMemento( );
+
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ if( !it.current( )->insertError( ) )
+ {
+ obj = it.current( )->deletedObject( );
+
+ if( !prev )
+ {
+ if( m_pParent->canInsert( obj, 0 ) )
+ {
+ m_pParent->insertChild( obj, 0 );
+ prev = obj;
+ theManager->cmdObjectChanged( obj, PMCAdd );
+ }
+ else
+ error = true;
+ }
+ else
+ {
+ if( m_pParent->canInsert( obj, prev ) )
+ {
+ m_pParent->insertChildAfter( obj, prev );
+ prev = obj;
+ theManager->cmdObjectChanged( obj, PMCAdd );
+ }
+ else
+ error = true;
+ }
+
+ if( error )
+ {
+ m_insertErrors.append( it.current( )->deletedObject( ) );
+ it.current( )->setInsertError( );
+ theManager->cmdObjectChanged( obj, PMCAdd | PMCInsertError );
+ error = false;
+ }
+ }
+ }
+
+ if( m_firstExecution )
+ {
+ if( m_pParent->mementoCreated( ) )
+ m_dataChanges.append( m_pParent->takeMemento( ) );
+
+ for( it.toLast( ); it.current( ); --it )
+ {
+ info = it.current( );
+ parent = info->parent( );
+
+ if( parent->mementoCreated( ) )
+ m_dataChanges.append( parent->takeMemento( ) );
+ }
+ }
+
+ QPtrListIterator<PMMemento> mit( m_dataChanges );
+ for( ; mit.current( ); ++mit )
+ {
+ PMObjectChangeListIterator change = mit.current( )->changedObjects( );
+ for( ; change.current( ); ++change )
+ theManager->cmdObjectChanged( change.current( )->object( ),
+ change.current( )->mode( ) );
+ }
+
+ m_executed = true;
+ m_firstExecution = true;
+ }
+}
+
+void PMMoveCommand::undo( PMCommandManager* theManager )
+{
+ if( m_executed )
+ {
+ PMDeleteInfoListIterator it( m_infoList );
+ PMObject* obj;
+ for( it.toLast( ) ; it.current( ); --it )
+ {
+ // signal has to be emitted before the item is removed
+ obj = it.current( )->deletedObject( );
+ theManager->cmdObjectChanged( obj, PMCRemove );
+ if( obj->parent( ) )
+ obj->parent( )->takeChild( obj );
+ }
+
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ obj = it.current( )->deletedObject( );
+ if( it.current( )->prevSibling( ) )
+ it.current( )->parent( )
+ ->insertChildAfter( obj, it.current( )->prevSibling( ) );
+ else
+ it.current( )->parent( )->insertChild( obj, 0 );
+ theManager->cmdObjectChanged( obj, PMCAdd );
+ }
+
+ QPtrListIterator<PMMemento> mit( m_dataChanges );
+ for( ; mit.current( ); ++mit )
+ {
+ mit.current( )->originator( )->restoreMemento( mit.current( ) );
+ PMObjectChangeListIterator change = mit.current( )->changedObjects( );
+ for( ; change.current( ); ++change )
+ theManager->cmdObjectChanged( change.current( )->object( ),
+ change.current( )->mode( ) );
+ }
+
+ m_executed = false;
+ }
+}
+
+int PMMoveCommand::errorFlags( PMPart* )
+{
+ PMDeleteInfo* info;
+ PMDeclare* decl = 0;
+ PMObject* obj;
+ bool insideSelection;
+ bool ok = true;
+ bool declareInsertError = false;
+ bool error = false;
+ bool stop;
+
+ // dictionary of deleted objects
+ QPtrDict<bool> deletedObjects( 1009 );
+ deletedObjects.setAutoDelete( true );
+ QPtrDict<bool> objectsAfterInsertPosition( 1009 );
+ objectsAfterInsertPosition.setAutoDelete( true );
+ QPtrDict<bool> declaresBeforeInsertPosition( 199 );
+ declaresBeforeInsertPosition.setAutoDelete( true );
+
+
+ PMDeleteInfoListIterator it( m_infoList );
+ for( ; it.current( ); ++it )
+ deletedObjects.insert( it.current( )->deletedObject( ),
+ new bool( true ) );
+
+ // declares can only be moved, if all linked
+ // objects are moved as well or the insert position is before the first
+ // linked object and all declares can be inserted
+
+ info = m_infoList.last( );
+
+ while( info )
+ {
+ ok = true;
+ declareInsertError = false;
+
+ if( info->deletedObject( )->isA( "Declare" ) )
+ {
+ decl = ( PMDeclare* ) ( info->deletedObject( ) );
+
+ if( !m_pParent->canInsert( decl, m_pAfter ) )
+ {
+ declareInsertError = true;
+ ok = false;
+ }
+ else
+ {
+ PMObjectListIterator links = decl->linkedObjects( );
+
+ for( ; links.current( ) && ok; ++links )
+ {
+ insideSelection = false;
+ for( obj = links.current( ); obj && !insideSelection;
+ obj = obj->parent( ) )
+ {
+ if( deletedObjects.find( obj ) )
+ insideSelection = true;
+ }
+
+ if( insideSelection )
+ {
+ bool stop = false;
+ for( obj = links.current( ); obj && !stop; obj = obj->parent( ) )
+ {
+ if( deletedObjects.find( obj ) )
+ stop = true;
+ else
+ deletedObjects.insert( obj, new bool( true ) );
+ }
+ }
+ else
+ {
+ // link will not be moved
+ // check, if after insert position
+ // declares can only be inserted as childs of the scene
+
+ if( m_pAfter )
+ {
+ // insert point is not the first item
+ // find the top level parent item
+ stop = false;
+ obj = links.current( );
+ do
+ {
+ if( obj->parent( ) )
+ {
+ if( obj->parent( )->type( ) == "Scene" )
+ stop = true;
+ else
+ obj = obj->parent( );
+ }
+ else
+ stop = true; // error
+ }
+ while( !stop );
+
+ PMObject* topParent = obj;
+
+ // check if insert point is before the top level
+ // parent object
+
+ if( !objectsAfterInsertPosition.find( obj ) )
+ {
+ stop = false;
+ obj = obj->prevSibling( );
+ while( obj && !stop )
+ {
+ if( obj == m_pAfter )
+ stop = true;
+ else if( objectsAfterInsertPosition.find( obj ) )
+ stop = true;
+ else
+ obj = obj->prevSibling( );
+ }
+
+ if( stop )
+ objectsAfterInsertPosition.insert( topParent, new bool( true ) );
+ else
+ ok = false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if( !ok )
+ {
+ if( declareInsertError )
+ m_errors.prepend( i18n( "Can't insert the declare \"%1\" at that point." )
+ .arg( decl->id( ) ) );
+ else
+ m_errors.prepend( i18n( "The declare \"%1\" can't be moved behind linked objects." )
+ .arg( decl->id( ) ) );
+
+ PMDeleteInfo* tmp = info;
+ info = m_infoList.prev( );
+ deletedObjects.remove( tmp->deletedObject( ) );
+ m_infoList.removeRef( tmp );
+
+ error = true;
+ }
+ else
+ info = m_infoList.prev( );
+ }
+
+ // check if links are moved before the declare object
+
+ // find all declares bevore the insert position
+ if( m_pParent->type( ) == "Scene" )
+ obj = m_pAfter;
+ else
+ {
+ stop = false;
+ obj = m_pParent;
+ do
+ {
+ if( obj->parent( ) )
+ {
+ if( obj->parent( )->type( ) == "Scene" )
+ stop = true;
+ else
+ obj = obj->parent( );
+ }
+ else
+ stop = true; // error
+ }
+ while( !stop );
+
+ if( obj )
+ obj = obj->prevSibling( );
+ }
+
+ while( obj )
+ {
+ if( obj->isA( "Declare" ) )
+ declaresBeforeInsertPosition.insert( obj, new bool( true ) );
+ obj = obj->prevSibling( );
+ }
+
+ info = m_infoList.first( );
+ while( info )
+ {
+ ok = true;
+ PMRecursiveObjectIterator it( info->deletedObject( ) );
+ PMObject* linked = 0;
+
+ while( it.current( ) && ok )
+ {
+ linked = it.current( )->linkedObject( );
+
+ if( linked )
+ {
+ if( !deletedObjects.find( linked ) )
+ {
+ // Object is linked to a declare and the declare
+ // will not be moved.
+ // Check, if the insert point is after the declare
+
+ if( !declaresBeforeInsertPosition.find( linked ) )
+ ok = false;
+ }
+ }
+
+ if( ok )
+ ++it;
+ }
+
+ if( ok )
+ info = m_infoList.next( );
+ else
+ {
+ if( linked )
+ {
+ obj = info->deletedObject( );
+ QString name = obj->name( );
+ decl = ( PMDeclare* ) linked;
+
+ if( name.isEmpty( ) )
+ name = i18n( "(unnamed)" );
+ m_errors.append( i18n( "The %1 \"%2\" can't be moved because it "
+ "contains a link to the declare \"%3\" "
+ "and the insert point is not after "
+ "the declare." )
+ .arg( obj->description( ) ).arg( name )
+ .arg( decl->id( ) ) );
+ }
+ else
+ kdError( PMArea ) << "linked is 0 in PMMoveCommand::errorFlags\n";
+
+
+ PMDeleteInfo* tmp = info;
+ info = m_infoList.next( );
+ deletedObjects.remove( tmp->deletedObject( ) );
+ m_infoList.removeRef( tmp );
+
+ error = true;
+ }
+ }
+
+ if( error )
+ {
+ if( m_infoList.count( ) == 0 )
+ return PMEError | PMEFatal;
+ else
+ return PMEError;
+ }
+
+ return PMENone;
+}
diff --git a/kpovmodeler/pmmovecommand.h b/kpovmodeler/pmmovecommand.h
new file mode 100644
index 00000000..75250fd2
--- /dev/null
+++ b/kpovmodeler/pmmovecommand.h
@@ -0,0 +1,88 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMOVECOMMAND_H
+#define PMMOVECOMMAND_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcommand.h"
+#include "pmdeletecommand.h"
+
+class PMObject;
+class PMMemento;
+
+/**
+ * Command class for moving objects
+ */
+class PMMoveCommand : public PMCommand
+{
+public:
+ /**
+ * Command that moves one PMObject.
+ *
+ * The object obj will be inserted as child of parent after
+ * the object after.
+ *
+ * If after is 0, the object becomes the first child.
+ */
+ PMMoveCommand( PMObject* obj, PMObject* parent, PMObject* after );
+
+ /**
+ * Command that moves a list of new PMObjects.
+ * The objects don't have to be siblings of each other.
+ *
+ * The object in the list will be inserted as children of parent after
+ * the object after.
+ *
+ * If after is 0, the objects will be inserted as first children.
+ */
+ PMMoveCommand( const PMObjectList& list, PMObject* parent, PMObject* after );
+ /**
+ * Deletes the command.
+ */
+ virtual ~PMMoveCommand( );
+
+ /** */
+ virtual int errorFlags( PMPart* );
+
+protected:
+ /**
+ * Executes the command and stores undo information
+ */
+ virtual void execute( PMCommandManager* theManager );
+ /**
+ * Undo the command
+ */
+ virtual void undo( PMCommandManager* theManager );
+
+private:
+ PMObject* m_pParent;
+ PMObject* m_pAfter;
+
+ PMDeleteInfoList m_infoList;
+ PMObjectList m_insertErrors;
+ bool m_executed;
+ bool m_firstExecution;
+ QPtrList<PMMemento> m_dataChanges;
+};
+
+#endif
diff --git a/kpovmodeler/pmnamedobject.cpp b/kpovmodeler/pmnamedobject.cpp
new file mode 100644
index 00000000..d6d6ab09
--- /dev/null
+++ b/kpovmodeler/pmnamedobject.cpp
@@ -0,0 +1,111 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmnamedobject.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+
+PMDefinePropertyClass( PMNamedObject, PMNamedObjectProperty );
+
+PMMetaObject* PMNamedObject::s_pMetaObject = 0;
+
+PMNamedObject::PMNamedObject( PMPart* part )
+ : Base( part )
+{
+}
+
+PMNamedObject::PMNamedObject( const PMNamedObject& o )
+ : Base( o )
+{
+ m_name = o.m_name;
+}
+
+PMNamedObject::~PMNamedObject( )
+{
+}
+
+PMMetaObject* PMNamedObject::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "NamedObject", Base::metaObject( ) );
+ s_pMetaObject->addProperty(
+ new PMNamedObjectProperty( "name", &PMNamedObject::setName, &PMNamedObject::name ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMNamedObject::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMNamedObject::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "name", m_name );
+ Base::serialize( e, doc );
+}
+
+void PMNamedObject::readAttributes( const PMXMLHelper& h )
+{
+ m_name = h.stringAttribute( "name", "" );
+ Base::readAttributes( h );
+}
+
+void PMNamedObject::setName( const QString& newName )
+{
+ if( newName != m_name )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMNameID, m_name );
+ m_pMemento->setDescriptionChanged( );
+ }
+
+ m_name = newName;
+ }
+}
+
+void PMNamedObject::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMNameID:
+ setName( data->stringData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMNamedObject::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmnamedobject.h b/kpovmodeler/pmnamedobject.h
new file mode 100644
index 00000000..d4cdee2c
--- /dev/null
+++ b/kpovmodeler/pmnamedobject.h
@@ -0,0 +1,89 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMNAMEDOBJECT_H
+#define PMNAMEDOBJECT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcompositeobject.h"
+
+/**
+ * class for all objects with free choose-able names (all objects except
+ * include files, the scene and declares)
+ */
+
+class PMNamedObject : public PMCompositeObject
+{
+ typedef PMCompositeObject Base;
+public:
+ /**
+ * Creates an empty PMNamedObject
+ */
+ PMNamedObject( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMNamedObject( const PMNamedObject& o );
+ /**
+ * Deletes the object
+ */
+ ~PMNamedObject( );
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns the name of the object. This is the name that helps
+ * the user to identify a object (like "south_wall", "floor" ...) */
+ virtual QString name( ) const { return m_name; }
+ /**
+ * Sets the name of the object.
+ */
+ virtual void setName( const QString& newName );
+ /**
+ * Returns true if the object can have a name
+ */
+ virtual bool canHaveName( ) const { return true; }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMNamedObjectMementoID { PMNameID };
+
+ /**
+ * Name of the object
+ */
+ QString m_name;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmnamedobjectedit.cpp b/kpovmodeler/pmnamedobjectedit.cpp
new file mode 100644
index 00000000..35a6c96c
--- /dev/null
+++ b/kpovmodeler/pmnamedobjectedit.cpp
@@ -0,0 +1,81 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmnamedobjectedit.h"
+#include "pmnamedobject.h"
+
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+PMNamedObjectEdit::PMNamedObjectEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMNamedObjectEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout = new QHBoxLayout( topLayout( ) );
+ m_pNameEdit = new QLineEdit( this );
+ QLabel* label = new QLabel( i18n( "Name:" ), this );
+
+ layout->addWidget( label );
+ layout->addWidget( m_pNameEdit );
+
+ connect( m_pNameEdit, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotNameChanged( const QString& ) ) );
+}
+
+void PMNamedObjectEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "NamedObject" ) )
+ {
+ m_pDisplayedObject = ( PMNamedObject* ) o;
+ m_pNameEdit->setText( m_pDisplayedObject->name( ) );
+
+ m_pNameEdit->setReadOnly( m_pDisplayedObject->isReadOnly( ) );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMNamedObjectEdit: Can't display object\n";
+}
+
+void PMNamedObjectEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setName( m_pNameEdit->text( ) );
+ }
+}
+
+bool PMNamedObjectEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+void PMNamedObjectEdit::slotNameChanged( const QString& )
+{
+ emit dataChanged( );
+}
+#include "pmnamedobjectedit.moc"
diff --git a/kpovmodeler/pmnamedobjectedit.h b/kpovmodeler/pmnamedobjectedit.h
new file mode 100644
index 00000000..8d9dff40
--- /dev/null
+++ b/kpovmodeler/pmnamedobjectedit.h
@@ -0,0 +1,64 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMNAMEDOBJECTEDIT_H
+#define PMNAMEDOBJECTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMNamedObject;
+class QLineEdit;
+
+/**
+ * Dialog edit class for @ref PMNamedObject.
+ */
+class PMNamedObjectEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMNamedObjectEdit with parent and name
+ */
+ PMNamedObjectEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private slots:
+ void slotNameChanged( const QString& );
+private:
+ PMNamedObject* m_pDisplayedObject;
+ QLineEdit* m_pNameEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmnormal.cpp b/kpovmodeler/pmnormal.cpp
new file mode 100644
index 00000000..77fdddd1
--- /dev/null
+++ b/kpovmodeler/pmnormal.cpp
@@ -0,0 +1,189 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmnormal.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmnormaledit.h"
+#include "pmlistpattern.h"
+#include "pmpattern.h"
+
+#include <klocale.h>
+
+const double bumpSizeDefault = 0.0;
+const double accuracyDefault = 0.02;
+
+PMDefinePropertyClass( PMNormal, PMNormProperty );
+
+PMMetaObject* PMNormal::s_pMetaObject = 0;
+PMObject* createNewNormal( PMPart* part )
+{
+ return new PMNormal( part );
+}
+
+PMNormal::PMNormal( PMPart* part )
+ : Base( part )
+{
+ m_enableBumpSize = false;
+ m_bumpSize = bumpSizeDefault;
+ m_accuracy = accuracyDefault;
+ m_uvMapping = false;
+}
+
+PMNormal::PMNormal( const PMNormal& n )
+ : Base( n )
+{
+ m_enableBumpSize = n.m_enableBumpSize;
+ m_bumpSize = n.m_bumpSize;
+ m_accuracy = n.m_accuracy;
+ m_uvMapping = n.m_uvMapping;
+}
+
+PMNormal::~PMNormal( )
+{
+}
+
+PMMetaObject* PMNormal::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Normal", Base::metaObject( ),
+ createNewNormal );
+ s_pMetaObject->addProperty(
+ new PMNormProperty( "bumpSize", &PMNormal::setBumpSize, &PMNormal::bumpSize ) );
+ s_pMetaObject->addProperty(
+ new PMNormProperty( "bumpSizeEnabled", &PMNormal::enableBumpSize, &PMNormal::isBumpSizeEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMNormProperty( "accuracy", &PMNormal::setAccuracy, &PMNormal::accuracy ) );
+ s_pMetaObject->addProperty(
+ new PMNormProperty( "uvMapping", &PMNormal::setUVMapping, &PMNormal::uvMapping ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMNormal::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMNormal::description( ) const
+{
+ return i18n( "normal" );
+}
+
+void PMNormal::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ Base::serialize( e, doc );
+ e.setAttribute( "enable_bump_size", m_enableBumpSize );
+ e.setAttribute( "bump_size", m_bumpSize );
+ e.setAttribute( "accuracy", m_accuracy );
+ e.setAttribute( "uv_mapping", m_uvMapping );
+}
+
+void PMNormal::readAttributes( const PMXMLHelper& h )
+{
+ Base::readAttributes( h );
+ m_enableBumpSize = h.boolAttribute( "enable_bump_size", false );
+ m_bumpSize = h.doubleAttribute( "bump_size", bumpSizeDefault );
+ m_accuracy = h.doubleAttribute( "accuracy", accuracyDefault );
+ m_uvMapping = h.boolAttribute( "uv_mapping", false );
+}
+
+PMDialogEditBase* PMNormal::editWidget( QWidget* parent ) const
+{
+ return new PMNormalEdit( parent );
+}
+
+void PMNormal::enableBumpSize( bool c )
+{
+ if( c != m_enableBumpSize )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableBumpSizeID, m_enableBumpSize );
+ m_enableBumpSize = c;
+ }
+}
+
+void PMNormal::setBumpSize( double c )
+{
+ if( c != m_bumpSize )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBumpSizeID, m_bumpSize );
+ m_bumpSize = c;
+ }
+}
+
+void PMNormal::setAccuracy( double c )
+{
+ if( c!= m_accuracy )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAccuracyID, m_accuracy );
+ m_accuracy = c;
+ }
+}
+
+void PMNormal::setUVMapping( bool m )
+{
+ if( m != m_uvMapping )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUVMappingID, m_uvMapping );
+ m_uvMapping = m;
+ }
+}
+
+void PMNormal::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMEnableBumpSizeID:
+ enableBumpSize( data->boolData( ) );
+ break;
+ case PMBumpSizeID:
+ setBumpSize( data->doubleData( ) );
+ break;
+ case PMAccuracyID:
+ setAccuracy( data->doubleData( ) );
+ break;
+ case PMUVMappingID:
+ setUVMapping( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMNormal::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmnormal.h b/kpovmodeler/pmnormal.h
new file mode 100644
index 00000000..81ec0547
--- /dev/null
+++ b/kpovmodeler/pmnormal.h
@@ -0,0 +1,122 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMNORMAL_H
+#define PMNORMAL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+
+/**
+ * Class for povray normals
+ */
+class PMNormal : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMNormal
+ */
+ PMNormal( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMNormal( const PMNormal& n );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMNormal( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMNormal( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMNormalEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmnormal" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ /**
+ * Returns true if bump_size is enabled
+ */
+ bool isBumpSizeEnabled( ) const { return m_enableBumpSize; }
+ /**
+ * enables/disables bump_size
+ */
+ void enableBumpSize( bool c );
+ /**
+ * Returns the normal's bump size
+ */
+ double bumpSize( ) const { return m_bumpSize; }
+ /**
+ * Sets the normal's bump size
+ */
+ void setBumpSize( double c );
+ /**
+ * Returns the normal's accuracy
+ */
+ double accuracy( ) const { return m_accuracy; }
+ /**
+ * Sets the normal's accuracy
+ */
+ void setAccuracy( double c );
+ /**
+ * Returns the uv mapping flag
+ */
+ bool uvMapping( ) const { return m_uvMapping; }
+ /**
+ * Sets the uv mapping flag
+ */
+ void setUVMapping( bool m );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMNormalMementoID { PMEnableBumpSizeID, PMBumpSizeID, PMAccuracyID, PMUVMappingID };
+
+ bool m_enableBumpSize;
+ double m_bumpSize;
+ double m_accuracy;
+ bool m_uvMapping;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmnormaledit.cpp b/kpovmodeler/pmnormaledit.cpp
new file mode 100644
index 00000000..161f2b0b
--- /dev/null
+++ b/kpovmodeler/pmnormaledit.cpp
@@ -0,0 +1,118 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmnormaledit.h"
+#include "pmnormal.h"
+#include "pmlinkedit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+
+PMNormalEdit::PMNormalEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMNormalEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pBumpSizeCheck = new QCheckBox( i18n( "Bump size" ), this );
+ m_pBumpSizeEdit = new PMFloatEdit( this );
+ hl->addWidget( m_pBumpSizeCheck );
+ hl->addWidget( m_pBumpSizeEdit );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ QLabel* lbl = new QLabel( i18n( "Accuracy" ), this );
+ m_pAccuracy = new PMFloatEdit( this );
+ hl->addWidget( lbl );
+ hl->addWidget( m_pAccuracy );
+ hl->addStretch( 1 );
+
+ m_pUVMapping = new QCheckBox( i18n( "UV mapping" ), this );
+ topLayout( )->addWidget( m_pUVMapping );
+
+ connect( m_pBumpSizeCheck, SIGNAL( clicked( ) ), SLOT( slotBumpSizeClicked( )) );
+ connect( m_pBumpSizeEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( )) );
+ connect( m_pAccuracy, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pUVMapping, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMNormalEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Normal" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMNormal* )o;
+
+ m_pBumpSizeCheck->setChecked( m_pDisplayedObject->isBumpSizeEnabled( ) );
+ m_pBumpSizeCheck->setEnabled( !readOnly );
+ m_pBumpSizeEdit->setValue( m_pDisplayedObject->bumpSize( ) );
+ m_pBumpSizeEdit->setReadOnly( readOnly );
+ slotBumpSizeClicked( );
+ m_pAccuracy->setValue( m_pDisplayedObject->accuracy( ) );
+ m_pAccuracy->setReadOnly( readOnly );
+ m_pUVMapping->setChecked( m_pDisplayedObject->uvMapping() );
+ m_pUVMapping->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMNormalEdit: Can't display object\n";
+}
+
+void PMNormalEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->enableBumpSize( m_pBumpSizeCheck->isChecked( ) );
+ m_pDisplayedObject->setBumpSize( m_pBumpSizeEdit->value( ) );
+ m_pDisplayedObject->setAccuracy( m_pAccuracy->value( ) );
+ m_pDisplayedObject->setUVMapping( m_pUVMapping->isChecked() );
+ }
+}
+
+bool PMNormalEdit::isDataValid( )
+{
+ if( !m_pBumpSizeEdit->isDataValid( ) ) return false;
+ if( !m_pAccuracy->isDataValid( ) ) return false;
+
+ return Base::isDataValid( );
+}
+
+void PMNormalEdit::slotBumpSizeClicked( )
+{
+ if( m_pBumpSizeCheck->isChecked( ) )
+ m_pBumpSizeEdit->show( );
+ else
+ m_pBumpSizeEdit->hide( );
+ emit sizeChanged( );
+ emit dataChanged( );
+}
+
+#include "pmnormaledit.moc"
diff --git a/kpovmodeler/pmnormaledit.h b/kpovmodeler/pmnormaledit.h
new file mode 100644
index 00000000..631db778
--- /dev/null
+++ b/kpovmodeler/pmnormaledit.h
@@ -0,0 +1,70 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMNORMALEDIT_H
+#define PMNORMALEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMNormal;
+class QCheckBox;
+class PMFloatEdit;
+
+/**
+ * Dialog edit class for @ref PMNormal
+ */
+class PMNormalEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMNormalEdit with parent and name
+ */
+ PMNormalEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotBumpSizeClicked( );
+
+private:
+ PMNormal* m_pDisplayedObject;
+
+ QCheckBox* m_pBumpSizeCheck;
+ PMFloatEdit* m_pBumpSizeEdit;
+ PMFloatEdit* m_pAccuracy;
+ QCheckBox* m_pUVMapping;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmobject.cpp b/kpovmodeler/pmobject.cpp
new file mode 100644
index 00000000..d6bb94b3
--- /dev/null
+++ b/kpovmodeler/pmobject.cpp
@@ -0,0 +1,283 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmobject.h"
+#include "pmcontrolpoint.h"
+#include "pmdialogeditbase.h"
+#include "pmmemento.h"
+#include "pmprototypemanager.h"
+#include "pminsertrulesystem.h"
+#include "pmpart.h"
+
+PMDefinePropertyClass( PMObject, PMObjectProperty );
+
+PMMetaObject* PMObject::s_pMetaObject = 0;
+
+PMObject::PMObject( PMPart* part )
+{
+ m_pParent = 0;
+ m_selected = false;
+ m_pPrevSibling = 0;
+ m_pNextSibling = 0;
+ m_pMemento = 0;
+ m_readOnly = false;
+ m_pPart = part;
+
+ if( !m_pPart )
+ kdError( PMArea ) << "PMObject::PMObject: The part may not be null" << endl;
+}
+
+PMObject::PMObject( const PMObject& o )
+{
+ m_pParent = 0;
+ m_selected = false;
+ m_pPrevSibling = 0;
+ m_pNextSibling = 0;
+ m_pMemento = 0;
+ m_readOnly = false;
+ m_pPart = o.m_pPart;
+}
+
+PMObject::~PMObject( )
+{
+}
+
+PMMetaObject* PMObject::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Object", 0 );
+ s_pMetaObject->addProperty(
+ new PMObjectProperty( "readOnly", &PMObject::setReadOnly, &PMObject::isReadOnly ) );
+ s_pMetaObject->addProperty(
+ new PMObjectProperty( "numberOfChildren", 0, &PMObject::countChildren ) );
+ }
+ return s_pMetaObject;
+}
+
+PMObject* PMObject::newObject( ) const
+{
+ return metaObject( )->newObject( m_pPart );
+}
+
+bool PMObject::insertChildAfter( PMObject*, PMObject* )
+{
+ kdError( PMArea ) << "Tried to insert object into a non composite object" << "\n";
+ return false;
+}
+
+bool PMObject::insertChildBefore( PMObject*, PMObject* )
+{
+ kdError( PMArea ) << "Tried to insert object into a non composite object" << "\n";
+ return false;
+}
+
+void PMObject::setSelected( bool s )
+{
+ if( m_selected != s )
+ {
+ if( s )
+ {
+ if( isSelectable( ) )
+ {
+ m_selected = true;
+ if( m_pParent )
+ m_pParent->adjustSelectedChildren( 1 );
+ }
+ }
+ else
+ {
+ m_selected = false;
+ if( m_pParent )
+ m_pParent->adjustSelectedChildren( -1 );
+ }
+ }
+}
+
+bool PMObject::isSelectable( )
+{
+ bool is = true;
+ PMObject* o;
+
+ for( o = m_pParent; o && is; o = o->m_pParent )
+ if( o->isSelected( ) )
+ is = false;
+
+ return is;
+}
+
+bool PMObject::isReadOnly( ) const
+{
+ if( m_readOnly )
+ return true;
+ if( m_pParent )
+ return m_pParent->isReadOnly( );
+ return false;
+}
+
+bool PMObject::takeChild( PMObject* )
+{
+ kdError( PMArea ) << "Tried to remove object out of a non composite object" << "\n";
+ return false;
+}
+
+bool PMObject::takeChild( uint )
+{
+ kdError( PMArea ) << "Tried to remove object out of a non composite object" << "\n";
+ return false;
+}
+
+PMDialogEditBase* PMObject::editWidget( QWidget* parent ) const
+{
+ return new PMDialogEditBase( parent );
+// return 0;
+}
+
+void PMObject::createMemento( )
+{
+ if( m_pMemento )
+ delete m_pMemento;
+ m_pMemento = new PMMemento( this );
+}
+
+PMMemento* PMObject::takeMemento( )
+{
+ PMMemento* tmp = m_pMemento;
+ m_pMemento = 0;
+ return tmp;
+}
+
+void PMObject::restoreMemento( PMMemento* /* s */ )
+{
+ // nothing to be done at the moment
+}
+
+PMMatrix PMObject::transformedWith( ) const
+{
+ PMMatrix result = PMMatrix::identity( );
+ const PMObject* o = this;
+
+ if( o->firstChild( ) )
+ o = o->firstChild( );
+ else if( o->nextSibling( ) )
+ o = o->nextSibling( );
+ else
+ o = o->parent( );
+
+ while( o )
+ {
+ if( o->hasTransformationMatrix( ) )
+ result = o->transformationMatrix( ) * result;
+
+ if( o->nextSibling( ) )
+ o = o->nextSibling( );
+ else
+ o = o->parent( );
+ }
+
+ return result;
+}
+
+QDomElement PMObject::serialize( QDomDocument& doc ) const
+{
+ QDomElement e = doc.createElement( className( ).lower( ) );
+ serialize( e, doc );
+ return e;
+}
+
+void PMObject::readAttributes( const PMXMLHelper& )
+{
+}
+
+void PMObject::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+}
+
+bool PMObject::setProperty( const QString& name, const PMVariant& v )
+{
+ PMPropertyBase* p = metaObject( )->property( name );
+ if( !p )
+ return false;
+ return p->setProperty( this, v );
+}
+
+QStringList PMObject::properties( ) const
+{
+ QStringList lst;
+ PMPropertyIterator it = metaObject( )->properties( );
+
+ for( ; it.current( ); ++it )
+ lst.append( it.current( )->name( ) );
+
+ return lst;
+}
+
+PMVariant PMObject::property( const QString& name ) const
+{
+ PMPropertyBase* p = metaObject( )->property( name );
+ if( !p )
+ return PMVariant( );
+ return p->getProperty( this );
+}
+
+bool PMObject::isA( const QString& className ) const
+{
+ if( !m_pPart )
+ return false;
+ return m_pPart->prototypeManager( )->isA( metaObject( ), className );
+}
+
+QString PMObject::type( ) const
+{
+ return metaObject( )->className( );
+}
+
+bool PMObject::canInsert( const QString& className, const PMObject* after,
+ const PMObjectList* objectsBetween ) const
+{
+ if( !m_pPart )
+ return false;
+ return m_pPart->insertRuleSystem( )->canInsert( this, className, after, objectsBetween );
+}
+
+bool PMObject::canInsert( const PMObject* o, const PMObject* after,
+ const PMObjectList* objectsBetween ) const
+{
+ if( !m_pPart )
+ return false;
+ return m_pPart->insertRuleSystem( )->canInsert( this, o, after, objectsBetween );
+}
+
+int PMObject::canInsert( const PMObjectList& list, const PMObject* after ) const
+{
+ if( !m_pPart )
+ return false;
+ return m_pPart->insertRuleSystem( )->canInsert( this, list, after );
+}
+
+int PMObject::canInsert( const QStringList& classes, const PMObject* after ) const
+{
+ if( !m_pPart )
+ return false;
+ return m_pPart->insertRuleSystem( )->canInsert( this, classes, after );
+}
diff --git a/kpovmodeler/pmobject.h b/kpovmodeler/pmobject.h
new file mode 100644
index 00000000..0c11008b
--- /dev/null
+++ b/kpovmodeler/pmobject.h
@@ -0,0 +1,511 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMOBJECT_H
+#define PMOBJECT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qvaluelist.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <kdebug.h>
+#include <qdom.h>
+
+#include "pmmatrix.h"
+#include "pmcontrolpoint.h"
+#include "pmmetaobject.h"
+#include "pmdebug.h"
+
+class PMDialogEditBase;
+class PMMemento;
+class PMViewStructure;
+class PMXMLHelper;
+class PMDeclare;
+class PMObjectAction;
+class PMPart;
+
+class PMObject;
+typedef QPtrList<PMObject> PMObjectList;
+typedef QPtrListIterator<PMObject> PMObjectListIterator;
+
+/**
+ * Base class for all povray objects
+ *
+ * Used pattern: Composite
+ *
+ * All list/child functionality is disabled in this class. Objects that
+ * can have children has to be inherited from @ref PMCompositeObject.
+ */
+class PMObject
+{
+ friend class PMCompositeObject;
+public:
+ /**
+ * Creates an empty PMObject without parent.
+ */
+ PMObject( PMPart* part );
+ /**
+ * Copy constructor. All object pointers (parent, siblings) are set to 0!
+ */
+ PMObject( const PMObject& o );
+ /**
+ * Deletes the object and all children.
+ */
+ virtual ~PMObject( );
+
+ /**
+ * Returns a new object of that type
+ */
+ PMObject* newObject( ) const;
+ /**
+ * Returns a deep copy of the object
+ */
+ virtual PMObject* copy( ) const = 0;
+
+ /**
+ * Returns the meta object for the class
+ */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /**
+ * Returns true if the object is of type t or inherits the object
+ * class with type t
+ */
+ bool isA( const QString& className ) const;
+
+ /**
+ * Returns the class name (not i18n'ed, without the PM prefix)
+ */
+ QString type( ) const;
+ /**
+ * same as @ref type( )
+ */
+ QString className( ) const { return type( ); }
+ /**
+ * Returns the class name of the object (povray name).
+ * This is the name that is showed in dialogs and menus.
+ */
+ virtual QString description( ) const = 0;
+ /**
+ * Returns the name of the object. This is the name that helps
+ * the user to identify a object (like "south wall", "floor" ...)
+ */
+ virtual QString name( ) const { return QString::null; }
+ /**
+ * Returns true if the object can have a name
+ */
+ virtual bool canHaveName( ) const { return false; }
+ /**
+ * Returns true if the object should be exported for rendering
+ */
+ virtual bool exportPovray( ) const { return true; }
+
+ /**
+ * Returns a pointer to the parent object.
+ */
+ PMObject* parent( ) const { return m_pParent; }
+ /**
+ * Returns a pointer to the corresponding part
+ */
+ PMPart* part( ) const { return m_pPart; }
+
+ /**
+ * Returns true if an object with type className can be inserted
+ * as child after the object after.
+ *
+ * The parser uses the third parameter for top level objects. These objects
+ * have to be treated as if they are inserted after the object after.
+ */
+ bool canInsert( const QString& className, const PMObject* after,
+ const PMObjectList* objectsBetween = 0 ) const;
+ /**
+ * Returns true if the object o can be inserted as child after the object
+ * after.
+ *
+ * The parser uses the third parameter for top level objects. These objects
+ * have to be treated as if they are inserted after the object after.
+ */
+ bool canInsert( const PMObject* o, const PMObject* after,
+ const PMObjectList* objectsBetween = 0 ) const;
+ /**
+ * Returns the number of objects that can be inserted at that position
+ */
+ int canInsert( const PMObjectList& list, const PMObject* after ) const;
+ /**
+ * Returns the number of objects that can be inserted at that position
+ */
+ int canInsert( const QStringList& classes, const PMObject* after ) const;
+
+ /**
+ * Returns true if an insert or remove operation of children will
+ * change data inside this class
+ */
+ virtual bool dataChangeOnInsertRemove( ) const { return false; }
+
+ /**
+ * Returns a pointer to the first child. Null for this class
+ */
+ virtual PMObject* firstChild( ) const { return 0; }
+ /**
+ * Returns a pointer to the last child. Null for this class
+ */
+ virtual PMObject* lastChild( ) const { return 0; }
+ /**
+ * Returns a pointer to the child object at position index,
+ * or null if the index is out of range.
+ */
+ virtual PMObject* childAt( uint ) const { return 0; }
+ /**
+ * Returns the next sibling of that item
+ */
+ PMObject* nextSibling( ) const { return m_pNextSibling; }
+ /**
+ * Returns the previous sibling of that item
+ */
+ PMObject* prevSibling( ) const { return m_pPrevSibling; }
+
+ /**
+ * Returns true if the object contains the child object o
+ */
+ virtual bool containsChild( PMObject* ) const { return false; }
+ /**
+ * Returns the index of the child or -1 if not found
+ */
+ virtual int findChild( PMObject* ) { return -1; }
+ /**
+ * Inserts the object as child at index index.
+ * If i is -1, the object is appended.
+ * Returns true if successful
+ */
+ virtual bool insertChild( PMObject*, int )
+ {
+ kdError( PMArea ) << "Tried to insert object into a non composite object" << "\n";
+ return false;
+ }
+ /**
+ * Inserts the object as child after the child object after
+ */
+ virtual bool insertChildAfter( PMObject* object, PMObject* after );
+ /**
+ * Inserts the object as child before the child object before
+ */
+ virtual bool insertChildBefore( PMObject* object, PMObject* before );
+ /**
+ * Appends the object as last child. Returns true if successful
+ */
+ virtual bool appendChild( PMObject* )
+ {
+ kdError( PMArea ) << "Tried to insert object into a non composite object" << "\n";
+ return false;
+ }
+ /**
+ * Returns the number of children. 0 in this class
+ */
+ virtual int countChildren( ) const { return 0; }
+ /**
+ * Removes a child object. Does not delete it!
+ * Returns true if successful
+ */
+ virtual bool takeChild( PMObject* );
+ /**
+ * Removes a child object at index i. Does not delete it!
+ * Returns true if successful
+ */
+ virtual bool takeChild( uint );
+
+ /**
+ * Called when a child was removed. For classes that have to be informed
+ * when children are removed
+ */
+ virtual void childRemoved( PMObject* ) { };
+ /**
+ * Called when a child was added. For classes that have to be informed
+ * when children are added
+ */
+ virtual void childAdded( PMObject* ) { };
+
+ /**
+ * Returns true if the object needs auxiliary files.
+ */
+ virtual bool needsAuxiliaryFiles( ) const { return false; }
+ /**
+ * Returns a list of auxiliary files
+ */
+ virtual QStringList auxiliaryFiles( ) const { return QStringList( ); }
+
+ /**
+ * Returns true if the object has a (povray) transformation matrix.
+ * True for transformation objects.
+ */
+ virtual bool hasTransformationMatrix( ) const { return false; }
+ /**
+ * Returns the (povray) transformation of the object, if it has one,
+ * otherwise an identity matrix
+ */
+ virtual PMMatrix transformationMatrix( ) const
+ {
+ kdError( PMArea ) << "This object has no transformation matrix" << "\n";
+ return PMMatrix::identity( );
+ }
+ /**
+ * Returns the matrix, the object is transformed with
+ */
+ PMMatrix transformedWith( ) const;
+
+ /**
+ * Returns the view structure ( see @ref PMViewStructure ) of the object
+ * or 0, if it has none.
+ *
+ * The view structure will be created or updated if necessary.
+ */
+ virtual PMViewStructure* viewStructure( ) { return 0; }
+
+ /**
+ * Creates the control points and appends them to the list.
+ *
+ * The caller becomes the owner of the control points and has
+ * to delete them.
+ *
+ * Control points are the interface between the graphical views and the
+ * PMObject for graphical changes.
+ */
+ virtual void controlPoints( PMControlPointList& ) { }
+ /**
+ * Tells the object that the control points have changed
+ */
+ virtual void controlPointsChanged( PMControlPointList& ) { }
+ /**
+ * Tells the object that the control points have changed
+ *
+ * The object can add objects to the second parameter, if
+ * additional objects were changed during the graphical change,
+ * not only this object.
+ *
+ * If you leave the list empty, only this object was changed.
+ * If you add children or other objects to the list, add this object
+ * to the list, too, if it was changed!
+ *
+ * IMPORTANT: When you change additional objects, make sure that
+ * a memento is created for these objects (@ref mementoCreated,
+ * @ref createMemento) before changing data.
+ *
+ * Calls @ref controlPointsChanged by default.
+ */
+ virtual void controlPointsChangedList( PMControlPointList& list,
+ PMObjectList& /*changedObjects*/ )
+ {
+ controlPointsChanged( list );
+ }
+ /**
+ * Returns true if multiple control points can be selected
+ */
+ virtual bool multipleSelectControlPoints( ) const { return false; }
+
+ /**
+ * Each object can add actions to the context menu of the @ref PMGLView.
+ *
+ * Each time the user opens the context menu, this function is called.
+ * Add all supported actions to this list and call the base class.
+ *
+ * The default implementation adds no action.
+ *
+ * @see PMObjectAction
+ */
+ virtual void addObjectActions( const PMControlPointList&,
+ QPtrList<PMObjectAction>& ) { }
+
+ /**
+ * This member is called when the user selects an object action
+ * in the context menu.
+ *
+ * The arguments are the selected action, the list of control points,
+ * the 3D (!) positions of the control points (screen-x, screen-y and depth)
+ * in the active opengl view and the 2D mouse position.
+ */
+ virtual void objectActionCalled( const PMObjectAction*,
+ const PMControlPointList&,
+ const QPtrList<PMVector>&,
+ const PMVector& ) { };
+
+ /**
+ * Saves the object as kpovmodeler xml code.
+ */
+ QDomElement serialize( QDomDocument& doc ) const;
+ /**
+ * Adds the objects attributes and child objects to the element
+ */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const = 0;
+ /**
+ * Reads the attributes from the QDomElement
+ */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns the list of known properties
+ */
+ QStringList properties( ) const;
+
+ /**
+ * Sets a property and returns true if successful
+ */
+ bool setProperty( const QString&, const PMVariant& v );
+ /**
+ * Returns a property
+ */
+ PMVariant property( const QString& ) const;
+
+ /**
+ * Returns true if the object is selected
+ */
+ bool isSelected( ) { return m_selected; }
+ /**
+ * Sets this object to be selected if s is true and to not be selected
+ if s is false
+ */
+ void setSelected( bool s );
+ /**
+ * Returns true if this item can be selected. An item cannot be selected
+ * if a parent object is selected
+ */
+ bool isSelectable( );
+ /**
+ * Returns the number of selected child items. All selected items in
+ * any depth are counted
+ */
+ virtual int selectedChildren( ) const { return 0; }
+ /**
+ * Deselects recursively all child objects
+ */
+ virtual void deselectChildren( ) { };
+ /**
+ * Returns true if this object is read only
+ */
+ bool isReadOnly( ) const;
+ /**
+ * Makes this object read only, if yes == true. All children will
+ * be read only, too
+ */
+ void setReadOnly( bool yes = true ) { m_readOnly = yes; }
+
+ /**
+ * Creates a new edit widget that can display this object and
+ * returns a pointer to it.
+ *
+ * The widget will be created as a child of parent.
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const = 0;
+ /**
+ * Returns a pointer to the @ref PMDeclare object, that is linked to
+ * that object, or 0, if this object contains no link
+ */
+ virtual PMDeclare* linkedObject( ) const { return 0; }
+
+ /**
+ * Tells the object to create a memento object.
+ *
+ * By default a simple @ref PMMemento will be created.
+ * If the memento doesn't provide enough functionality, subclass the memento
+ * and reimplement this function.
+ *
+ * NOTE: The new memento has to inherit the memento used in the base class!
+ *
+ * If a memento was created, the object saves all changes its
+ * state. The memento is then used for undo/redo.
+ *
+ * First call this function, change attributes and then take the mementos
+ * with @ref takeMemento
+ *
+ * If you want to restore the old state, call @ref restoreMemento with
+ * the memento.
+ */
+ virtual void createMemento( );
+ /**
+ * Returns true if a memento was created
+ */
+ bool mementoCreated( ) const { return m_pMemento != 0; }
+ /**
+ * Takes the memento. The caller is responsible to delete the memento
+ */
+ PMMemento* takeMemento( );
+ /**
+ * Restores the state s
+ */
+ virtual void restoreMemento( PMMemento* s );
+
+ /**
+ * This function is called before the part is unloaded.
+ *
+ * Delete static pointer variables to clean up the memory.
+ *
+ * This method can be called multiple times when there are subclasses.
+ * Set the pointer to 0 after deleting an object!
+ */
+ virtual void cleanUp( ) const;
+
+protected:
+ /**
+ * Adds num to the number of selected objects in this object and all
+ * parent objects. num can be negative.
+ */
+ virtual void adjustSelectedChildren( int /*num*/ ) { };
+ /**
+ * The memento where the old status of the object should be stored
+ */
+ PMMemento* m_pMemento;
+private:
+ /**
+ * Pointer to the parent object. 0 if the object has no parent.
+ */
+ PMObject* m_pParent;
+ /**
+ * Pointer to the prev sibling. 0 if the object has no prev sibling.
+ */
+ PMObject* m_pPrevSibling;
+ /**
+ * Pointer to the next sibling. 0 if the object has no next sibling.
+ */
+ PMObject* m_pNextSibling;
+ /**
+ * true if this object is selected
+ */
+ bool m_selected;
+ /**
+ * true if this object is read only. All children will be read only, too
+ */
+ bool m_readOnly;
+ /**
+ * The meta object
+ */
+ static PMMetaObject* s_pMetaObject;
+ /**
+ * The corresponding part
+ */
+ PMPart* m_pPart;
+};
+
+#endif
diff --git a/kpovmodeler/pmobjectaction.h b/kpovmodeler/pmobjectaction.h
new file mode 100644
index 00000000..e9a843ce
--- /dev/null
+++ b/kpovmodeler/pmobjectaction.h
@@ -0,0 +1,100 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMOBJECTACTION_H
+#define PMOBJECTACTION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmvector.h"
+#include "pmcontrolpoint.h"
+#include "pmmetaobject.h"
+#include <qptrlist.h>
+#include <qstring.h>
+
+class KAction;
+
+/**
+ * Helper class for object action functions.
+ *
+ * Each object can define actions that are inserted into the context
+ * menu. This class stores informations of one action.
+ *
+ * The actionID has to be unique for each class.
+ *
+ * The member m_action is set later by the framework.
+ */
+class PMObjectAction
+{
+public:
+ /**
+ * Constructor
+ */
+ PMObjectAction( PMMetaObject* objectType, int actionID,
+ const QString& description, bool enabled = true )
+ {
+ m_class = objectType;
+ m_actionID = actionID;
+ m_description = description;
+ m_enabled = enabled;
+ m_menuID = -1;
+ }
+
+ /**
+ * Returns the class type for the action
+ */
+ PMMetaObject* objectType( ) const { return m_class; }
+ /**
+ * Returns the action ID
+ */
+ int actionID( ) const { return m_actionID; }
+ /**
+ * Returns the description
+ */
+ QString description( ) const { return m_description; }
+
+ /**
+ * Returns the enabled flag
+ */
+ bool isEnabled( ) const { return m_enabled; }
+ /**
+ * Sets the enabled flag
+ */
+ void setEnabled( bool enable ) { m_enabled = enable; }
+
+ /**
+ * Returns the menu id
+ */
+ int menuID( ) const { return m_menuID; }
+ /**
+ * Sets the menu id
+ */
+ void setMenuID( int id ) { m_menuID = id; }
+
+private:
+ PMMetaObject* m_class;
+ int m_actionID;
+ QString m_description;
+ bool m_enabled;
+ int m_menuID;
+};
+
+#endif
diff --git a/kpovmodeler/pmobjectdrag.cpp b/kpovmodeler/pmobjectdrag.cpp
new file mode 100644
index 00000000..6bebfc8e
--- /dev/null
+++ b/kpovmodeler/pmobjectdrag.cpp
@@ -0,0 +1,230 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmobjectdrag.h"
+#include "pmobject.h"
+#include "pmpart.h"
+#include "pmpovrayparser.h"
+#include "pmxmlparser.h"
+#include "pmxmlhelper.h"
+#include "pmdocumentformat.h"
+#include "pmiomanager.h"
+#include "pmserializer.h"
+
+#include <qbuffer.h>
+#include <string.h>
+
+const char* const c_kpmDocumentMimeFormat = "application/x-kpovmodeler";
+
+PMObjectDrag::PMObjectDrag( PMPart* part, PMObject* object, QWidget* dragSource,
+ const char* name )
+ : QDragObject( dragSource, name )
+{
+ QByteArray modelerData;
+
+ QTextStream s2( modelerData, IO_WriteOnly );
+ QDomDocument doc( "KPOVMODELER" );
+ QDomElement top = doc.createElement( "objects" );
+ doc.appendChild( top );
+ top.setAttribute( "majorFormat", c_majorDocumentFormat );
+ top.setAttribute( "minorFormat", c_minorDocumentFormat );
+
+ if( object->type( ) == "Scene" )
+ {
+ PMObject* o = object->firstChild( );
+ for( ; o; o = o->nextSibling( ) )
+ {
+ QDomElement e = o->serialize( doc );
+ top.appendChild( e );
+ }
+ }
+ else
+ {
+ QDomElement e = object->serialize( doc );
+ top.appendChild( e );
+ }
+ s2 << doc;
+
+ m_data.push_back( modelerData );
+ m_mimeTypes.push_back( c_kpmDocumentMimeFormat );
+
+ const QPtrList<PMIOFormat>& formats = part->ioManager( )->formats( );
+ QPtrListIterator<PMIOFormat> it( formats );
+ for( ; it.current( ); ++it )
+ {
+ if( it.current( )->services( ) & PMIOFormat::Export )
+ {
+ QByteArray data;
+ QBuffer buffer( data );
+ buffer.open( IO_WriteOnly );
+
+ PMSerializer* ser = it.current( )->newSerializer( &buffer );
+
+ if( ser )
+ {
+ ser->serialize( object );
+ ser->close( );
+ delete ser;
+ buffer.close( );
+
+ m_data.push_back( data );
+ m_mimeTypes.push_back( it.current( )->mimeType( ) );
+
+ kdDebug( PMArea ) << "Added mime type " << it.current( )->mimeType( )
+ << " " << data.size( ) << " bytes" << endl;
+ }
+ else
+ kdError( PMArea ) << "Format claims to support exporting, but doesn't provide a serializer" << endl;
+
+ buffer.close( );
+ }
+ }
+}
+
+PMObjectDrag::PMObjectDrag( PMPart* part, const PMObjectList& objList, QWidget* dragSource,
+ const char* name )
+ : QDragObject( dragSource, name )
+{
+ QByteArray modelerData;
+
+ QTextStream s2( modelerData, IO_WriteOnly );
+ QDomDocument doc( "KPOVMODELER" );
+ QDomElement top = doc.createElement( "objects" );
+ doc.appendChild( top );
+ top.setAttribute( "majorFormat", c_majorDocumentFormat );
+ top.setAttribute( "minorFormat", c_minorDocumentFormat );
+
+ PMObjectListIterator it( objList );
+ for( ; it.current( ); ++it )
+ {
+ if( it.current( )->type( ) == "Scene" )
+ {
+ PMObject* o = it.current( )->firstChild( );
+ for( ; o; o = o->nextSibling( ) )
+ {
+ QDomElement e = o->serialize( doc );
+ top.appendChild( e );
+ }
+ }
+ else
+ {
+ QDomElement e = it.current( )->serialize( doc );
+ top.appendChild( e );
+ }
+ }
+
+ s2 << doc;
+
+ m_data.push_back( modelerData );
+ m_mimeTypes.push_back( c_kpmDocumentMimeFormat );
+
+ const QPtrList<PMIOFormat>& formats = part->ioManager( )->formats( );
+ QPtrListIterator<PMIOFormat> fit( formats );
+ for( ; fit.current( ); ++fit )
+ {
+ if( fit.current( )->services( ) & PMIOFormat::Export )
+ {
+ QByteArray data;
+ QBuffer buffer( data );
+ buffer.open( IO_WriteOnly );
+
+ PMSerializer* ser = fit.current( )->newSerializer( &buffer );
+
+ if( ser )
+ {
+ ser->serializeList( objList );
+ ser->close( );
+ delete ser;
+ buffer.close( );
+
+ m_data.push_back( data );
+ m_mimeTypes.push_back( fit.current( )->mimeType( ) );
+
+ kdDebug( PMArea ) << "Added mime type " << fit.current( )->mimeType( )
+ << " " << data.size( ) << " bytes" << endl;
+ }
+ else
+ kdError( PMArea ) << "Format claims to support exporting, but doesn't provide a serializer" << endl;
+
+ buffer.close( );
+ }
+ }
+}
+
+PMObjectDrag::~PMObjectDrag( )
+{
+}
+
+QByteArray PMObjectDrag::encodedData( const char* format ) const
+{
+ QValueList<QByteArray>::ConstIterator dit;
+ QStringList::ConstIterator sit;
+
+ for( dit = m_data.begin( ), sit = m_mimeTypes.begin( );
+ dit != m_data.end( ) && sit != m_mimeTypes.end( ); ++dit, ++sit )
+ {
+ if( *sit == format )
+ return *dit;
+ }
+
+ QByteArray empty;
+ return empty;
+}
+
+const char* PMObjectDrag::format( int i /*=0*/ ) const
+{
+ if( i >= 0 && i < ( signed ) m_mimeTypes.size( ) )
+ return ( *m_mimeTypes.at( i ) ).latin1( );
+ return 0;
+}
+
+bool PMObjectDrag::canDecode( const QMimeSource* e, PMPart* part )
+{
+ if( e->provides( c_kpmDocumentMimeFormat ) )
+ return true;
+
+ const QPtrList<PMIOFormat>& formats = part->ioManager( )->formats( );
+ QPtrListIterator<PMIOFormat> fit( formats );
+ for( ; fit.current( ); ++fit )
+ if( fit.current( )->services( ) & PMIOFormat::Import &&
+ e->provides( fit.current( )->mimeType( ).latin1( ) ) )
+ return true;
+
+ return false;
+}
+
+PMParser* PMObjectDrag::newParser( const QMimeSource* e, PMPart* part )
+{
+ if( e->provides( c_kpmDocumentMimeFormat ) )
+ return new PMXMLParser( part, e->encodedData( c_kpmDocumentMimeFormat ) );
+
+ const QPtrList<PMIOFormat>& formats = part->ioManager( )->formats( );
+ QPtrListIterator<PMIOFormat> fit( formats );
+ for( ; fit.current( ); ++fit )
+ {
+ PMIOFormat* f = fit.current( );
+ QString str = f->mimeType( );
+ const char* lat = str.latin1( );
+ if( f->services( ) & PMIOFormat::Import && e->provides( lat ) )
+ return f->newParser( part, e->encodedData( lat ) );
+ }
+
+ return 0;
+}
+
+
diff --git a/kpovmodeler/pmobjectdrag.h b/kpovmodeler/pmobjectdrag.h
new file mode 100644
index 00000000..a8f4daf3
--- /dev/null
+++ b/kpovmodeler/pmobjectdrag.h
@@ -0,0 +1,81 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMOBJECTDRAG_H
+#define PMOBJECTDRAG_H
+
+#include <qdragobject.h>
+#include <qstringlist.h>
+
+#include "pmobject.h"
+class PMParser;
+class PMPart;
+
+/**
+ * Supports drag/drop and copy/paste of kpovmodeler objects
+ */
+
+class PMObjectDrag : public QDragObject
+{
+public:
+ /**
+ * Creates a drag object for one object
+ *
+ * The object drag will contain all formats that are supported
+ * by the part.
+ * @see PMIOManager
+ */
+ PMObjectDrag( PMPart* part, PMObject* object, QWidget* dragSource = 0,
+ const char* name = 0 );
+ /**
+ * Creates a drag object for all objects in objList
+ */
+ PMObjectDrag( PMPart* part, const PMObjectList& objList, QWidget* dragSource = 0,
+ const char* name = 0 );
+ /**
+ * Deletes the drag object
+ */
+ ~PMObjectDrag( );
+ /**
+ * Returns the encoded payload of this object, in the
+ * specified MIME format.
+ */
+ virtual QByteArray encodedData( const char* ) const;
+ /**
+ * Returns the ith format, or NULL.
+ */
+ virtual const char* format( int i = 0 ) const;
+ /**
+ * Returns true if the information in e can be decoded
+ */
+ static bool canDecode( const QMimeSource* e, PMPart* part );
+ /**
+ * Returns a pointer to a parser for this drag object or 0, if the data
+ * can't be decoded.
+ *
+ * The caller is responsible to delete the parser.
+ */
+ static PMParser* newParser( const QMimeSource* e, PMPart* part );
+
+private:
+ QValueList<QByteArray> m_data;
+ QStringList m_mimeTypes;
+};
+
+#endif
diff --git a/kpovmodeler/pmobjectlibrarysettings.cpp b/kpovmodeler/pmobjectlibrarysettings.cpp
new file mode 100644
index 00000000..ce80f77c
--- /dev/null
+++ b/kpovmodeler/pmobjectlibrarysettings.cpp
@@ -0,0 +1,189 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmobjectlibrarysettings.h"
+
+#include "pmlibrarymanager.h"
+#include "pmlibraryhandle.h"
+#include "pmlibraryhandleedit.h"
+#include "pmdebug.h"
+
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+
+PMObjectLibrarySettings::PMObjectLibrarySettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ QVBoxLayout* vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+
+ QGroupBox* gb = new QGroupBox( i18n( "Libraries" ), this );
+ vlayout->addWidget( gb );
+
+ QHBoxLayout* hlayout = new QHBoxLayout( gb, KDialog::marginHint( ) + 5, KDialog::spacingHint( ) );
+ m_pObjectLibraries = new QListBox( gb );
+ connect( m_pObjectLibraries, SIGNAL( selectionChanged( ) ), SLOT( slotObjectLibraryChanged( ) ) );
+ hlayout->addWidget( m_pObjectLibraries );
+ QVBoxLayout* gvl = new QVBoxLayout( hlayout );
+ m_pCreateObjectLibrary = new QPushButton( i18n( "Create..." ), gb );
+ connect( m_pCreateObjectLibrary, SIGNAL( clicked( ) ), SLOT( slotCreateObjectLibrary( ) ) );
+ gvl->addWidget( m_pCreateObjectLibrary );
+ m_pRemoveObjectLibrary = new QPushButton( i18n( "Remove" ), gb );
+ connect( m_pRemoveObjectLibrary, SIGNAL( clicked( ) ), SLOT( slotRemoveObjectLibrary( ) ) );
+ gvl->addWidget( m_pRemoveObjectLibrary );
+ m_pImportObjectLibrary = new QPushButton( i18n( "Import" ), gb );
+ connect( m_pImportObjectLibrary, SIGNAL( clicked( ) ), SLOT( slotImportObjectLibrary( ) ) );
+ gvl->addWidget( m_pImportObjectLibrary );
+ m_pModifyObjectLibrary = new QPushButton( i18n( "Properties" ), gb );
+ connect( m_pModifyObjectLibrary, SIGNAL( clicked( ) ), SLOT( slotModifyObjectLibrary( ) ) );
+ gvl->addWidget( m_pModifyObjectLibrary );
+ gvl->addStretch( 1 );
+
+ gb = new QGroupBox( i18n( "Library Details" ), this );
+ QGridLayout* grid = new QGridLayout( gb, 4, 2, KDialog::marginHint( ) + 5, KDialog::spacingHint( ) );
+ QLabel* lbl = new QLabel( i18n( "Path" ), gb );
+ grid->addWidget( lbl, 0, 0 );
+ lbl = new QLabel( i18n( "Author" ), gb );
+ grid->addWidget( lbl, 1, 0 );
+ lbl = new QLabel( i18n( "Description" ), gb );
+ grid->addWidget( lbl, 2, 0 );
+ m_pLibraryPath = new QLabel( "", gb );
+ m_pLibraryAuthor = new QLabel( "", gb );
+ m_pLibraryDescription = new QLabel( "", gb );
+ m_pReadOnlyText = new QLabel( "", gb );
+ grid->addWidget( m_pLibraryPath, 0, 1 );
+ grid->addWidget( m_pLibraryAuthor, 1, 1 );
+ grid->addWidget( m_pLibraryDescription, 2, 1 );
+ grid->addMultiCellWidget( m_pReadOnlyText, 3, 3, 0, 1 );
+ grid->setColStretch( 1, 1 );
+ vlayout->addWidget( gb );
+
+ vlayout->addStretch( 1 );
+}
+
+void PMObjectLibrarySettings::displaySettings( )
+{
+ m_pObjectLibraries->clear( );
+ m_pObjectLibraries->insertStringList( PMLibraryManager::theManager( )->availableLibraries( ) );
+}
+
+void PMObjectLibrarySettings::applySettings( )
+{
+}
+
+bool PMObjectLibrarySettings::validateData( )
+{
+ return true;
+}
+
+void PMObjectLibrarySettings::displayDefaults( )
+{
+}
+
+void PMObjectLibrarySettings::slotImportObjectLibrary( )
+{
+ // TODO
+}
+
+void PMObjectLibrarySettings::slotModifyObjectLibrary( )
+{
+ PMLibraryHandle* h = PMLibraryManager::theManager( )->getLibraryHandle( m_pObjectLibraries->currentText( ) );
+ if( h )
+ {
+ PMLibraryHandleEdit h_dlg( h, this );
+
+ if( h_dlg.exec( ) == QDialog::Accepted )
+ {
+ h->saveLibraryInfo( );
+ displaySettings( );
+ for( unsigned i = 0; i < m_pObjectLibraries->count( ); ++i )
+ {
+ if( m_pObjectLibraries->text( i ) == h->name( ) )
+ {
+ m_pObjectLibraries->setSelected( i, true );
+ break;
+ }
+ }
+ slotObjectLibraryChanged( );
+ }
+ }
+}
+
+void PMObjectLibrarySettings::slotRemoveObjectLibrary( )
+{
+ m_pObjectLibraries->removeItem( m_pObjectLibraries->currentItem( ) );
+}
+
+void PMObjectLibrarySettings::slotCreateObjectLibrary( )
+{
+ PMLibraryHandle h;
+ PMLibraryHandleEdit h_dlg( &h, this );
+ QString libfilename;
+
+ if( h_dlg.exec( ) == QDialog::Accepted )
+ {
+ libfilename = h.name( );
+ h.setPath( locateLocal( "appdata", "library/" ) + libfilename.stripWhiteSpace( ) + "/" );
+ // Create the new library
+ switch( h.createLibrary( ) )
+ {
+ case PMLibraryHandle::Ok:
+ PMLibraryManager::theManager( )->refresh( );
+ displaySettings( );
+ break;
+ case PMLibraryHandle::ExistingDir:
+ KMessageBox::error( this, i18n( "The folder already exists." ) );
+ break;
+ case PMLibraryHandle::CouldNotCreateDir:
+ KMessageBox::error( this, i18n( "Could not create the folder." ) );
+ break;
+ default:
+ kdError( PMArea ) << "Unexpected error in slotCreateObjectLibrary." << endl;
+ }
+ }
+}
+
+void PMObjectLibrarySettings::slotObjectLibraryChanged( )
+{
+ PMLibraryHandle* h = PMLibraryManager::theManager( )->getLibraryHandle( m_pObjectLibraries->currentText( ) );
+ if( h )
+ {
+ m_pLibraryPath->setText( h->path( ) );
+ m_pLibraryAuthor->setText( h->author( ) );
+ m_pLibraryDescription->setText( h->description( ) );
+ if( h->isReadOnly( ) )
+ m_pReadOnlyText->setText( i18n( "This library is not modifiable." ) );
+ else
+ m_pReadOnlyText->setText( i18n( "This library is modifiable." ) );
+ }
+ else
+ {
+ m_pLibraryPath->setText( "" );
+ m_pLibraryAuthor->setText( "" );
+ m_pLibraryDescription->setText( "" );
+ m_pReadOnlyText->setText( "" );
+ }
+}
+
+#include "pmobjectlibrarysettings.moc"
diff --git a/kpovmodeler/pmobjectlibrarysettings.h b/kpovmodeler/pmobjectlibrarysettings.h
new file mode 100644
index 00000000..1c4c9ab9
--- /dev/null
+++ b/kpovmodeler/pmobjectlibrarysettings.h
@@ -0,0 +1,78 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+ copyright : (C) 2003 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMOBJECTLIBRARYSETTINGS_H
+#define PMOBJECTLIBRARYSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+
+class QPushButton;
+class QListBox;
+
+/**
+ * Object library configuration dialog page
+ */
+class PMObjectLibrarySettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMObjectLibrarySettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void displayDefaults( );
+protected slots:
+ /** Called when the object library create button is clicked */
+ void slotCreateObjectLibrary( );
+ /** Called when the object library properties button is clicked */
+ void slotModifyObjectLibrary( );
+ /** Called when the object library remove button is clicked */
+ void slotRemoveObjectLibrary( );
+ /** Called when the object library import button is clicked */
+ void slotImportObjectLibrary( );
+ /** Called when the selected library is changed */
+ void slotObjectLibraryChanged( );
+private:
+ int m_objectLibraryIndex;
+ int m_selectionIndex;
+ QListBox* m_pObjectLibraries;
+ QPushButton* m_pCreateObjectLibrary;
+ QPushButton* m_pModifyObjectLibrary;
+ QPushButton* m_pRemoveObjectLibrary;
+ QPushButton* m_pImportObjectLibrary;
+
+ QLabel* m_pLibraryPath;
+ QLabel* m_pLibraryAuthor;
+ QLabel* m_pLibraryDescription;
+ QLabel* m_pReadOnlyText;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmobjectlink.cpp b/kpovmodeler/pmobjectlink.cpp
new file mode 100644
index 00000000..6596471d
--- /dev/null
+++ b/kpovmodeler/pmobjectlink.cpp
@@ -0,0 +1,197 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmobjectlink.h"
+#include "pmdeclare.h"
+#include "pmpart.h"
+#include "pmsymboltable.h"
+#include "pmobjectlinkedit.h"
+#include "pmparser.h"
+
+#include "pmmemento.h"
+#include "pmxmlhelper.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMObjectLink, PMObjectLinkProperty );
+
+PMMetaObject* PMObjectLink::s_pMetaObject = 0;
+PMObject* createNewObjectLink( PMPart* part )
+{
+ return new PMObjectLink( part );
+}
+
+PMObjectLink::PMObjectLink( PMPart* part )
+ : Base( part )
+{
+ m_pLinkedObject = 0;
+}
+
+PMObjectLink::PMObjectLink( const PMObjectLink& o )
+ : Base( o )
+{
+ m_pLinkedObject = 0;
+ setLinkedObject( o.m_pLinkedObject );
+}
+
+PMObjectLink::~PMObjectLink( )
+{
+}
+
+QString PMObjectLink::description( ) const
+{
+ return i18n( "object link" );
+}
+
+PMMetaObject* PMObjectLink::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "ObjectLink", Base::metaObject( ),
+ createNewObjectLink );
+ s_pMetaObject->addProperty(
+ new PMObjectLinkProperty( "linkedObject", &PMObjectLink::setLinkedObjectProperty,
+ &PMObjectLink::linkedObjectProperty ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMObjectLink::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+bool PMObjectLink::setLinkedObject( PMDeclare* obj )
+{
+ if( obj )
+ {
+ if( obj->declareType( ) == "GraphicalObject" ||
+ obj->declareType( ) == "Light" )
+ {
+ if( m_pLinkedObject != obj )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMLinkedObjectID,
+ m_pLinkedObject );
+ m_pMemento->setViewStructureChanged( );
+ }
+
+ if( m_pLinkedObject )
+ {
+ m_pLinkedObject->removeLinkedObject( this );
+ if( m_pMemento )
+ m_pMemento->addChangedObject( m_pLinkedObject, PMCData );
+ }
+ m_pLinkedObject = obj;
+ m_pLinkedObject->addLinkedObject( this );
+ if( m_pMemento )
+ m_pMemento->addChangedObject( m_pLinkedObject, PMCData );
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+ else
+ {
+ if( m_pLinkedObject != 0 )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMLinkedObjectID,
+ m_pLinkedObject );
+ m_pMemento->addChangedObject( m_pLinkedObject, PMCData );
+ }
+ m_pLinkedObject->removeLinkedObject( this );
+ m_pLinkedObject = 0;
+ }
+ return true;
+ }
+ return false;
+}
+
+void PMObjectLink::setLinkedObjectProperty( PMObject* o )
+{
+ if( o == 0 )
+ setLinkedObject( 0 );
+ else if( o->isA( "Declare" ) )
+ setLinkedObject( ( PMDeclare* ) o );
+}
+
+void PMObjectLink::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ if( m_pLinkedObject )
+ e.setAttribute( "prototype", m_pLinkedObject->id( ) );
+ Base::serialize( e, doc );
+}
+
+void PMObjectLink::readAttributes( const PMXMLHelper& h )
+{
+ QString id = h.stringAttribute( "prototype", "" );
+ if( !id.isEmpty( ) )
+ {
+ PMDeclare* link = h.parser( )->checkLink( id );
+ if( link )
+ {
+ if( link->type( ) == "Declare" )
+ {
+ m_pLinkedObject = ( PMDeclare* ) link;
+ m_pLinkedObject->addLinkedObject( this );
+ }
+ else
+ h.parser( )->printError( i18n( "Declare \"%1\" has wrong type." )
+ .arg( id ) );
+ }
+ }
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMObjectLink::editWidget( QWidget* parent ) const
+{
+ return new PMObjectLinkEdit( parent );
+}
+
+void PMObjectLink::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMLinkedObjectID:
+ setLinkedObject( ( PMDeclare* ) data->objectData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMObjectLink::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmobjectlink.h b/kpovmodeler/pmobjectlink.h
new file mode 100644
index 00000000..54eb4833
--- /dev/null
+++ b/kpovmodeler/pmobjectlink.h
@@ -0,0 +1,99 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMOBJECTLINK_H
+#define PMOBJECTLINK_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmdeclare.h"
+
+/**
+ * Class for links of graphical objects.
+ */
+class PMObjectLink : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMObjectLink
+ */
+ PMObjectLink( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMObjectLink( const PMObjectLink& ol );
+ /**
+ * deletes the PMObjectLink
+ */
+ virtual ~PMObjectLink( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMObjectLink( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual PMDeclare* linkedObject( ) const { return m_pLinkedObject; }
+ /**
+ * Sets the linked object. Returns true if successful
+ */
+ bool setLinkedObject( PMDeclare* o );
+
+ /**
+ * Method used by the properties framework
+ */
+ PMObject* linkedObjectProperty( ) const { return m_pLinkedObject; }
+ /**
+ * Method used by the properties framework
+ */
+ void setLinkedObjectProperty( PMObject* o );
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMObjectLinkEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmobjectlink" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMObjectLinkMementoID { PMLinkedObjectID };
+ PMDeclare* m_pLinkedObject;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmobjectlinkedit.cpp b/kpovmodeler/pmobjectlinkedit.cpp
new file mode 100644
index 00000000..935f8714
--- /dev/null
+++ b/kpovmodeler/pmobjectlinkedit.cpp
@@ -0,0 +1,74 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmobjectlinkedit.h"
+#include "pmobjectlink.h"
+#include "pmdeclare.h"
+#include "pmobjectselect.h"
+#include "pmlinkedit.h"
+
+#include <qlayout.h>
+
+PMObjectLinkEdit::PMObjectLinkEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMObjectLinkEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pLinkEdit = new PMLinkEdit( this );
+ QStringList l;
+ l.append( "GraphicalObject" );
+ l.append( "Light" );
+ m_pLinkEdit->setLinkPossibilities( l );
+ topLayout( )->addWidget( m_pLinkEdit );
+ connect( m_pLinkEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMObjectLinkEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "ObjectLink" ) )
+ {
+ m_pDisplayedObject = ( PMObjectLink* ) o;
+ m_pLinkEdit->setDisplayedObject( m_pDisplayedObject );
+ m_pLinkEdit->setReadOnly( m_pDisplayedObject->isReadOnly( ) );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMObjectLinkEdit: Can't display object\n";
+}
+
+void PMObjectLinkEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setLinkedObject( m_pLinkEdit->link( ) );
+ }
+}
+
+bool PMObjectLinkEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+#include "pmobjectlinkedit.moc"
diff --git a/kpovmodeler/pmobjectlinkedit.h b/kpovmodeler/pmobjectlinkedit.h
new file mode 100644
index 00000000..2f517951
--- /dev/null
+++ b/kpovmodeler/pmobjectlinkedit.h
@@ -0,0 +1,62 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMOBJECTLINKEDIT_H
+#define PMOBJECTLINKEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMObjectLink;
+class PMLinkEdit;
+
+/**
+ * Dialog edit class for @ref PMObjectLink.
+ */
+class PMObjectLinkEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMObjectLinkEdit with parent and name
+ */
+ PMObjectLinkEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMObjectLink* m_pDisplayedObject;
+ PMLinkEdit* m_pLinkEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmobjectselect.cpp b/kpovmodeler/pmobjectselect.cpp
new file mode 100644
index 00000000..fb9fa0ce
--- /dev/null
+++ b/kpovmodeler/pmobjectselect.cpp
@@ -0,0 +1,361 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmobjectselect.h"
+#include "pmfactory.h"
+#include <klocale.h>
+#include <kiconloader.h>
+
+PMListBoxObject::PMListBoxObject( QListBox* listbox, PMObject* obj,
+ QListBoxItem* after )
+ : QListBoxPixmap( listbox,
+ SmallIcon( obj->pixmap( ), PMFactory::instance( ) ),
+ checkName( obj->name( ) ), after )
+{
+ m_pObject = obj;
+}
+
+PMListBoxObject::PMListBoxObject( QListBox* listbox, PMObject* obj )
+ : QListBoxPixmap( listbox,
+ SmallIcon( obj->pixmap( ), PMFactory::instance( ) ),
+ checkName( obj->name( ) ) )
+{
+ m_pObject = obj;
+}
+
+PMListBoxObject::PMListBoxObject( PMObject* obj )
+ : QListBoxPixmap( SmallIcon( obj->pixmap( ), PMFactory::instance( ) ),
+ checkName( obj->name( ) ) )
+{
+ m_pObject = obj;
+}
+
+PMListBoxObject::PMListBoxObject( QListBox* listbox, PMObject* obj,
+ const QString& text, QListBoxItem* after )
+ : QListBoxPixmap( listbox,
+ SmallIcon( obj->pixmap( ), PMFactory::instance( ) ),
+ text, after )
+{
+ m_pObject = obj;
+}
+
+PMListBoxObject::PMListBoxObject( QListBox* listbox, PMObject* obj,
+ const QString& text )
+ : QListBoxPixmap( listbox,
+ SmallIcon( obj->pixmap( ), PMFactory::instance( ) ),
+ text )
+{
+ m_pObject = obj;
+}
+
+PMListBoxObject::PMListBoxObject( PMObject* obj, const QString& text )
+ : QListBoxPixmap( SmallIcon( obj->pixmap( ), PMFactory::instance( ) ),
+ text )
+{
+ m_pObject = obj;
+}
+
+QString PMListBoxObject::checkName( const QString& text )
+{
+ if( text.isEmpty( ) )
+ return i18n( "(unnamed)" );
+ return text;
+}
+
+PMListBoxObject::~PMListBoxObject( )
+{
+}
+
+
+QSize PMObjectSelect::s_size = QSize( 200, 300 );
+
+
+PMObjectSelect::PMObjectSelect( QWidget* parent, const char* name, bool modal )
+ : KDialogBase( parent, name, modal, i18n( "Choose Object" ), Ok | Cancel )
+{
+ m_pSelectedObject = 0;
+ m_pListBox = new QListBox( this );
+ setMainWidget( m_pListBox );
+ setInitialSize( s_size );
+
+ connect( m_pListBox, SIGNAL( highlighted( QListBoxItem* ) ),
+ SLOT( slotHighlighted( QListBoxItem* ) ) );
+ connect( m_pListBox, SIGNAL( selected( QListBoxItem* ) ),
+ SLOT( slotSelected( QListBoxItem* ) ) );
+ enableButtonOK( false );
+}
+
+PMObjectSelect::~PMObjectSelect( )
+{
+ s_size = size( );
+}
+
+void PMObjectSelect::addObject( PMObject* obj )
+{
+ m_pListBox->insertItem( new PMListBoxObject( obj ) );
+}
+
+int PMObjectSelect::selectObject( PMObject* link, const QString& t,
+ PMObject* & obj, QWidget* parent )
+{
+ PMObject* last = link;
+ PMObject* scene;
+ bool stop = false;
+ bool found = false;
+
+ do
+ {
+ scene = last->parent( );
+ if( scene )
+ {
+ if( scene->type( ) == "Scene" )
+ {
+ last = last->prevSibling( );
+ stop = true;
+ found = true;
+ }
+ else
+ last = last->parent( );
+ }
+ else
+ stop = true;
+ }
+ while( !stop );
+
+ if( found )
+ {
+ PMObjectSelect s( parent );
+
+ PMObject* o = scene->firstChild( );
+ bool l = false;
+
+ while( o && !l && last )
+ {
+ if( o->type( ) == t )
+ s.m_pListBox->insertItem( new PMListBoxObject( o ) );
+
+ if( o == last )
+ l = true;
+ else
+ o = o->nextSibling( );
+ }
+
+ int result = s.exec( );
+ if( result == Accepted )
+ obj = s.selectedObject( );
+
+ return result;
+ }
+ else
+ kdError( PMArea ) << "PMObjectSelect: Link does not seem to be correctly inserted in the scene.\n";
+ return Rejected;
+}
+
+int PMObjectSelect::selectObject( PMObject* link,
+ const QStringList& t,
+ PMObject* & obj, QWidget* parent )
+{
+ PMObject* last = link;
+ PMObject* scene;
+ bool stop = false;
+ bool found = false;
+
+ do
+ {
+ scene = last->parent( );
+ if( scene )
+ {
+ if( scene->type( ) == "Scene" )
+ {
+ last = last->prevSibling( );
+ stop = true;
+ found = true;
+ }
+ else
+ last = last->parent( );
+ }
+ else
+ stop = true;
+ }
+ while( !stop );
+
+ if( found )
+ {
+ PMObjectSelect s( parent );
+
+ PMObject* o = scene->firstChild( );
+ bool l = false;
+
+ while( o && !l && last )
+ {
+ if( t.findIndex( o->type( ) ) >= 0 )
+ s.m_pListBox->insertItem( new PMListBoxObject( o ) );
+
+ if( o == last )
+ l = true;
+ else
+ o = o->nextSibling( );
+ }
+
+ int result = s.exec( );
+ if( result == Accepted )
+ obj = s.selectedObject( );
+
+ return result;
+ }
+ else
+ kdError( PMArea ) << "PMObjectSelect: Link does not seem to be correctly inserted in the scene.\n";
+ return Rejected;
+}
+
+int PMObjectSelect::selectDeclare( PMObject* link, const QString& declareType,
+ PMObject* & obj, QWidget* parent )
+{
+ PMObject* last = link;
+ PMObject* scene;
+ bool stop = false;
+ bool found = false;
+
+ do
+ {
+ scene = last->parent( );
+ if( scene )
+ {
+ if( scene->type( ) == "Scene" )
+ {
+ last = last->prevSibling( );
+ stop = true;
+ found = true;
+ }
+ else
+ last = last->parent( );
+ }
+ else
+ stop = true;
+ }
+ while( !stop );
+
+ if( found )
+ {
+ PMObjectSelect s( parent );
+
+ PMObject* o = scene->firstChild( );
+ PMDeclare* decl;
+
+ bool l = false;
+
+ while( o && !l && last )
+ {
+ if( o->type( ) == "Declare" )
+ {
+ decl = ( PMDeclare* ) o;
+ if( decl->declareType( ) == declareType )
+ s.m_pListBox->insertItem( new PMListBoxObject( o ) );
+ }
+
+ if( o == last )
+ l = true;
+ else
+ o = o->nextSibling( );
+ }
+
+ int result = s.exec( );
+ if( result == Accepted )
+ obj = s.selectedObject( );
+
+ return result;
+ }
+ else
+ kdError( PMArea ) << "PMObjectSelect: Link does not seem to be correctly inserted in the scene.\n";
+ return Rejected;
+}
+
+int PMObjectSelect::selectDeclare( PMObject* link, const QStringList& declareTypes,
+ PMObject* & obj, QWidget* parent )
+{
+ PMObject* last = link;
+ PMObject* scene;
+ bool stop = false;
+ bool found = false;
+
+ do
+ {
+ scene = last->parent( );
+ if( scene )
+ {
+ if( scene->type( ) == "Scene" )
+ {
+ last = last->prevSibling( );
+ stop = true;
+ found = true;
+ }
+ else
+ last = last->parent( );
+ }
+ else
+ stop = true;
+ }
+ while( !stop );
+
+ if( found )
+ {
+ PMObjectSelect s( parent );
+
+ PMObject* o = scene->firstChild( );
+ PMDeclare* decl;
+
+ bool l = false;
+
+ while( o && !l && last )
+ {
+ if( o->type( ) == "Declare" )
+ {
+ decl = ( PMDeclare* ) o;
+ if( declareTypes.findIndex( decl->declareType( ) ) >= 0 )
+ s.m_pListBox->insertItem( new PMListBoxObject( o ) );
+ }
+
+ if( o == last )
+ l = true;
+ else
+ o = o->nextSibling( );
+ }
+
+ int result = s.exec( );
+ if( result == Accepted )
+ obj = s.selectedObject( );
+
+ return result;
+ }
+ else
+ kdError( PMArea ) << "PMObjectSelect: Link does not seem to be correctly inserted in the scene.\n";
+ return Rejected;
+}
+
+void PMObjectSelect::slotHighlighted( QListBoxItem* lbi )
+{
+ m_pSelectedObject = ( ( PMListBoxObject* ) lbi )->object( );
+ enableButtonOK( true );
+}
+
+void PMObjectSelect::slotSelected( QListBoxItem* lbi )
+{
+ m_pSelectedObject = ( ( PMListBoxObject* ) lbi )->object( );
+ enableButtonOK( true );
+ accept( );
+}
+#include "pmobjectselect.moc"
diff --git a/kpovmodeler/pmobjectselect.h b/kpovmodeler/pmobjectselect.h
new file mode 100644
index 00000000..c69af315
--- /dev/null
+++ b/kpovmodeler/pmobjectselect.h
@@ -0,0 +1,132 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMOBJECTSELECT_H
+#define PMOBJECTSELECT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+#include <qlistbox.h>
+#include <qsize.h>
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include "pmobject.h"
+#include "pmdeclare.h"
+
+/**
+ * QListBoxItem for @ref PMObject
+ */
+class PMListBoxObject : public QListBoxPixmap
+{
+public:
+ /**
+ * Constructs a list box item in listbox listbox showing the
+ * object obj. The item gets inserted after the item after
+ */
+ PMListBoxObject( QListBox* listbox, PMObject* obj, QListBoxItem* after );
+ /**
+ * Constructs a list box item in listbox listbox showing the object obj
+ */
+ PMListBoxObject( QListBox* listbox, PMObject* obj );
+ /**
+ * Constructs a list box item showing the object obj
+ */
+ PMListBoxObject( PMObject* obj );
+ /**
+ * Constructs a list box item in listbox listbox showing the
+ * text text. The item gets inserted after the item after
+ */
+ PMListBoxObject( QListBox* listbox, PMObject* obj, const QString& text,
+ QListBoxItem* after );
+ /**
+ * Constructs a list box item in listbox listbox showing the text text
+ */
+ PMListBoxObject( QListBox* listbox, PMObject* obj, const QString& text );
+ /**
+ * Constructs a list box item showing the text text
+ */
+ PMListBoxObject( PMObject* obj, const QString& text );
+ /**
+ * Deletes the item
+ */
+ ~PMListBoxObject( );
+
+ /**
+ * Returns a pointer to the object
+ */
+ PMObject* object( ) const { return m_pObject; }
+private:
+ static QString checkName( const QString& text );
+ PMObject* m_pObject;
+};
+
+/**
+ * A PMObject selection widget
+ */
+class PMObjectSelect : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a selection widget with parent and name
+ */
+ PMObjectSelect( QWidget* parent = 0, const char* name = 0,
+ bool modal = true );
+ /**
+ * Deletes the dialog
+ */
+ ~PMObjectSelect( );
+
+ /**
+ * Appends the object to the list of choosable objects
+ */
+ void addObject( PMObject* obj );
+
+ /**
+ * Returns the currently selected object
+ */
+ PMObject* selectedObject( ) const { return m_pSelectedObject; }
+
+ /**
+ * Create a modal dialog and let the user choose an declare object
+ * of type t.
+ *
+ * Only objects above the object link are listed.
+ */
+ static int selectObject( PMObject* link, const QString& t, PMObject* & obj,
+ QWidget* parent = 0 );
+ static int selectObject( PMObject* link, const QStringList& t,
+ PMObject* & obj, QWidget* parent = 0 );
+ static int selectDeclare( PMObject* link, const QString& declareType,
+ PMObject* & obj, QWidget* parent = 0 );
+ static int selectDeclare( PMObject* link, const QStringList& dt,
+ PMObject* & obj, QWidget* parent = 0 );
+
+protected slots:
+ void slotHighlighted( QListBoxItem* lbi );
+ void slotSelected( QListBoxItem* lbi );
+private:
+ QListBox* m_pListBox;
+ PMObject* m_pSelectedObject;
+ static QSize s_size;
+};
+
+#endif
diff --git a/kpovmodeler/pmobjectsettings.cpp b/kpovmodeler/pmobjectsettings.cpp
new file mode 100644
index 00000000..06aae64e
--- /dev/null
+++ b/kpovmodeler/pmobjectsettings.cpp
@@ -0,0 +1,550 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmobjectsettings.h"
+
+#include "pmlineedits.h"
+#include "pmrendermanager.h"
+#include "pmdefaults.h"
+
+#include "pmsphere.h"
+#include "pmcone.h"
+#include "pmcylinder.h"
+#include "pmtorus.h"
+#include "pmplane.h"
+#include "pmdisc.h"
+#include "pmblobsphere.h"
+#include "pmblobcylinder.h"
+#include "pmlathe.h"
+#include "pmsor.h"
+#include "pmprism.h"
+#include "pmsqe.h"
+#include "pmspheresweep.h"
+#include "pmheightfield.h"
+#include "pmtext.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMObjectSettings::PMObjectSettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ QHBoxLayout* hlayout;
+ QVBoxLayout* vlayout;
+ QVBoxLayout* gvl;
+ QGridLayout* grid;
+ QGroupBox* gb;
+
+ vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+
+ gb = new QGroupBox( i18n( "Subdivisions" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+ grid = new QGridLayout( gvl, 13, 3 );
+
+ grid->addWidget( new QLabel( i18n( "Sphere:" ), gb ), 0, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 0, 2 );
+ grid->addWidget( new QLabel( "u", gb ), 0, 1 );
+ m_pSphereUSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pSphereUSteps );
+ m_pSphereUSteps->setValidation( true, 2, true, 32 );
+ hlayout->addWidget( new QLabel( "v", gb ) );
+ m_pSphereVSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pSphereVSteps );
+ m_pSphereVSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Cylinder:" ), gb ), 1, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 1, 2 );
+ m_pCylinderSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pCylinderSteps );
+ m_pCylinderSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Cone:" ), gb ), 2, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 2, 2 );
+ m_pConeSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pConeSteps );
+ m_pConeSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Torus:" ), gb ), 3, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 3, 2 );
+ grid->addWidget( new QLabel( "u", gb ), 3, 1 );
+ m_pTorusUSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pTorusUSteps );
+ m_pTorusUSteps->setValidation( true, 2, true, 16 );
+ hlayout->addWidget( new QLabel( "v", gb ) );
+ m_pTorusVSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pTorusVSteps );
+ m_pTorusVSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Disc:" ), gb ), 4, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 4, 2 );
+ m_pDiscSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pDiscSteps );
+ m_pDiscSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Blob sphere:" ), gb ), 5, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 5, 2 );
+ grid->addWidget( new QLabel( "u", gb ), 5, 1 );
+ m_pBlobSphereUSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pBlobSphereUSteps );
+ m_pBlobSphereUSteps->setValidation( true, 2, true, 32 );
+ hlayout->addWidget( new QLabel( "v", gb ) );
+ m_pBlobSphereVSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pBlobSphereVSteps );
+ m_pBlobSphereVSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Blob cylinder:" ), gb ), 6, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 6, 2 );
+ grid->addWidget( new QLabel( "u", gb ), 6, 1 );
+ m_pBlobCylinderUSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pBlobCylinderUSteps );
+ m_pBlobCylinderUSteps->setValidation( true, 2, true, 32 );
+ hlayout->addWidget( new QLabel( "v", gb ) );
+ m_pBlobCylinderVSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pBlobCylinderVSteps );
+ m_pBlobCylinderVSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Lathe:" ), gb ), 7, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 7, 2 );
+ grid->addWidget( new QLabel( "u", gb ), 7, 1 );
+ m_pLatheUSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pLatheUSteps );
+ m_pLatheUSteps->setValidation( true, 1, true, 16 );
+ hlayout->addWidget( new QLabel( "v", gb ) );
+ m_pLatheRSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pLatheRSteps );
+ m_pLatheRSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Surface of revolution:" ), gb ), 8, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 8, 2 );
+ grid->addWidget( new QLabel( "u", gb ), 8, 1 );
+ m_pSorUSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pSorUSteps );
+ m_pSorUSteps->setValidation( true, 1, true, 16 );
+ hlayout->addWidget( new QLabel( "v", gb ) );
+ m_pSorRSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pSorRSteps );
+ m_pSorRSteps->setValidation( true, 4, true, 64 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Prism:" ), gb ), 9, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 9, 2 );
+ m_pPrismSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pPrismSteps );
+ m_pPrismSteps->setValidation( true, 1, true, 16 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Superquadric ellipsoid:" ), gb ), 10, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 10, 2 );
+ grid->addWidget( new QLabel( "u", gb ), 10, 1 );
+ m_pSqeUSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pSqeUSteps );
+ m_pSqeUSteps->setValidation( true, 2, true, 8 );
+ hlayout->addWidget( new QLabel( "v", gb ) );
+ m_pSqeVSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pSqeVSteps );
+ m_pSqeVSteps->setValidation( true, 2, true, 8 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Sphere sweep:" ), gb ), 11, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 11, 2 );
+ grid->addWidget( new QLabel( "r", gb ), 11, 1 );
+ m_pSphereSweepRSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pSphereSweepRSteps );
+ m_pSphereSweepRSteps->setValidation( true, 4, true, 64 );
+ hlayout->addWidget( new QLabel( "s", gb ) );
+ m_pSphereSweepSSteps = new PMIntEdit( gb );
+ hlayout->addWidget( m_pSphereSweepSSteps );
+ m_pSphereSweepSSteps->setValidation( true, 1, true, 16 );
+ hlayout->addStretch( 1 );
+
+ grid->addWidget( new QLabel( i18n( "Heightfield:" ), gb ), 12, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 12, 2 );
+ m_pHeightFieldVariance = new PMIntEdit( gb );
+ hlayout->addWidget( m_pHeightFieldVariance );
+ m_pHeightFieldVariance->setValidation( true, 1, true, 16 );
+ hlayout->addStretch( 1 );
+
+ gb = new QGroupBox( i18n( "Sizes" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+
+ grid = new QGridLayout( gvl, 1, 2 );
+
+ grid->addWidget( new QLabel( i18n( "Plane:" ), gb ), 0, 0 );
+ hlayout = new QHBoxLayout( );
+ grid->addLayout( hlayout, 0, 1 );
+ m_pPlaneSize = new PMFloatEdit( gb );
+ hlayout->addWidget( m_pPlaneSize );
+ m_pPlaneSize->setValidation( true, 0.1, false, 0.0 );
+ hlayout->addStretch( 1 );
+
+ gb = new QGroupBox( i18n( "Camera Views" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+
+ m_pHighDetailCameraViews = new QCheckBox( i18n( "High detail for enhanced projections" ), gb );
+ gvl->addWidget( m_pHighDetailCameraViews );
+
+ vlayout->addStretch( 1 );
+}
+
+void PMObjectSettings::displaySettings( )
+{
+ m_pSphereUSteps->setValue( PMSphere::uSteps( ) );
+ m_pSphereVSteps->setValue( PMSphere::vSteps( ) );
+ m_pCylinderSteps->setValue( PMCylinder::steps( ) );
+ m_pConeSteps->setValue( PMCone::steps( ) );
+ m_pTorusUSteps->setValue( PMTorus::uSteps( ) );
+ m_pTorusVSteps->setValue( PMTorus::vSteps( ) );
+ m_pDiscSteps->setValue( PMDisc::steps( ) );
+ m_pBlobSphereUSteps->setValue( PMBlobSphere::uSteps( ) );
+ m_pBlobSphereVSteps->setValue( PMBlobSphere::vSteps( ) );
+ m_pBlobCylinderUSteps->setValue( PMBlobCylinder::uSteps( ) );
+ m_pBlobCylinderVSteps->setValue( PMBlobCylinder::vSteps( ) );
+ m_pPlaneSize->setValue( PMPlane::planeSize( ) );
+ m_pLatheUSteps->setValue( PMLathe::sSteps( ) );
+ m_pLatheRSteps->setValue( PMLathe::rSteps( ) );
+ m_pSorUSteps->setValue( PMSurfaceOfRevolution::sSteps( ) );
+ m_pSorRSteps->setValue( PMSurfaceOfRevolution::rSteps( ) );
+ m_pPrismSteps->setValue( PMPrism::sSteps( ) );
+ m_pSqeUSteps->setValue( PMSuperquadricEllipsoid::uSteps( ) );
+ m_pSqeVSteps->setValue( PMSuperquadricEllipsoid::vSteps( ) );
+ m_pSphereSweepRSteps->setValue( PMSphereSweep::rSteps( ) );
+ m_pSphereSweepSSteps->setValue( PMSphereSweep::sSteps( ) );
+ m_pHeightFieldVariance->setValue( PMHeightField::variance( ) );
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ m_pHighDetailCameraViews->setChecked( rm->highDetailCameraViews( ) );
+}
+
+void PMObjectSettings::displayDefaults( )
+{
+ m_pSphereUSteps->setValue( c_defaultSphereUSteps );
+ m_pSphereVSteps->setValue( c_defaultSphereVSteps );
+ m_pCylinderSteps->setValue( c_defaultCylinderSteps );
+ m_pConeSteps->setValue( c_defaultConeSteps );
+ m_pTorusUSteps->setValue( c_defaultTorusUSteps );
+ m_pTorusVSteps->setValue( c_defaultTorusVSteps );
+ m_pDiscSteps->setValue( c_defaultDiscSteps );
+ m_pBlobSphereUSteps->setValue( c_defaultBlobSphereUSteps );
+ m_pBlobSphereVSteps->setValue( c_defaultBlobSphereVSteps );
+ m_pBlobCylinderUSteps->setValue( c_defaultBlobCylinderUSteps );
+ m_pBlobCylinderVSteps->setValue( c_defaultBlobCylinderVSteps );
+ m_pLatheUSteps->setValue( c_defaultLatheSSteps );
+ m_pLatheRSteps->setValue( c_defaultLatheRSteps );
+ m_pSorUSteps->setValue( c_defaultSurfaceOfRevolutionSSteps );
+ m_pSorRSteps->setValue( c_defaultSurfaceOfRevolutionRSteps );
+ m_pPrismSteps->setValue( c_defaultPrismSSteps );
+ m_pSqeUSteps->setValue( c_defaultSuperquadricEllipsoidUSteps );
+ m_pSqeVSteps->setValue( c_defaultSuperquadricEllipsoidVSteps );
+ m_pSphereSweepRSteps->setValue( c_defaultSphereSweepRSteps );
+ m_pSphereSweepSSteps->setValue( c_defaultSphereSweepSSteps );
+ m_pHeightFieldVariance->setValue( c_defaultHeightFieldVariance );
+ m_pPlaneSize->setValue( c_defaultPlaneSize );
+ m_pHighDetailCameraViews->setChecked( c_defaultHighDetailCameraView );
+}
+
+bool PMObjectSettings::validateData( )
+{
+ if( !m_pSphereUSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pSphereUSteps->setFocus( );
+ return false;
+ }
+ if( !m_pSphereVSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pSphereVSteps->setFocus( );
+ return false;
+ }
+ if( !m_pCylinderSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pCylinderSteps->setFocus( );
+ return false;
+ }
+ if( !m_pConeSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pConeSteps->setFocus( );
+ return false;
+ }
+ if( !m_pTorusUSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pTorusUSteps->setFocus( );
+ return false;
+ }
+ if( !m_pTorusVSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pTorusVSteps->setFocus( );
+ return false;
+ }
+ if( !m_pDiscSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pDiscSteps->setFocus( );
+ return false;
+ }
+ if( !m_pBlobSphereUSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pBlobSphereUSteps->setFocus( );
+ return false;
+ }
+ if( !m_pBlobSphereVSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pBlobSphereVSteps->setFocus( );
+ return false;
+ }
+ if( !m_pBlobCylinderUSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pBlobCylinderUSteps->setFocus( );
+ return false;
+ }
+ if( !m_pBlobCylinderVSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pBlobCylinderVSteps->setFocus( );
+ return false;
+ }
+ if( !m_pLatheUSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pLatheUSteps->setFocus( );
+ return false;
+ }
+ if( !m_pLatheRSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pLatheRSteps->setFocus( );
+ return false;
+ }
+ if( !m_pSorUSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pSorUSteps->setFocus( );
+ return false;
+ }
+ if( !m_pSorRSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pSorRSteps->setFocus( );
+ return false;
+ }
+ if( !m_pPrismSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pPrismSteps->setFocus( );
+ return false;
+ }
+ if( !m_pSqeUSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pSqeUSteps->setFocus( );
+ return false;
+ }
+ if( !m_pSqeVSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pSqeVSteps->setFocus( );
+ return false;
+ }
+ if( !m_pSphereSweepRSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pSphereSweepRSteps->setFocus( );
+ return false;
+ }
+ if( !m_pSphereSweepSSteps->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pSphereSweepSSteps->setFocus( );
+ return false;
+ }
+ if( !m_pHeightFieldVariance->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pHeightFieldVariance->setFocus( );
+ return false;
+ }
+ if( !m_pPlaneSize->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pPlaneSize->setFocus( );
+ return false;
+ }
+ return true;
+}
+
+void PMObjectSettings::applySettings( )
+{
+ bool repaint = false;
+
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ if( rm->highDetailCameraViews( ) != m_pHighDetailCameraViews->isChecked( ) )
+ {
+ rm->setHighDetailCameraViews( m_pHighDetailCameraViews->isChecked( ) );
+ repaint = true;
+ }
+ if( PMSphere::uSteps( ) != m_pSphereUSteps->value( ) )
+ {
+ PMSphere::setUSteps( m_pSphereUSteps->value( ) );
+ repaint = true;
+ }
+ if( PMSphere::vSteps( ) != m_pSphereVSteps->value( ) )
+ {
+ PMSphere::setVSteps( m_pSphereVSteps->value( ) );
+ repaint = true;
+ }
+ if( PMCylinder::steps( ) != m_pCylinderSteps->value( ) )
+ {
+ PMCylinder::setSteps( m_pCylinderSteps->value( ) );
+ repaint = true;
+ }
+ if( PMCone::steps( ) != m_pConeSteps->value( ) )
+ {
+ PMCone::setSteps( m_pConeSteps->value( ) );
+ repaint = true;
+ }
+ if( PMTorus::uSteps( ) != m_pTorusUSteps->value( ) )
+ {
+ PMTorus::setUSteps( m_pTorusUSteps->value( ) );
+ repaint = true;
+ }
+ if( PMTorus::vSteps( ) != m_pTorusVSteps->value( ) )
+ {
+ PMTorus::setVSteps( m_pTorusVSteps->value( ) );
+ repaint = true;
+ }
+ if( PMDisc::steps( ) != m_pDiscSteps->value( ) )
+ {
+ PMDisc::setSteps( m_pDiscSteps->value( ) );
+ repaint = true;
+ }
+ if( PMBlobSphere::uSteps( ) != m_pBlobSphereUSteps->value( ) )
+ {
+ PMBlobSphere::setUSteps( m_pBlobSphereUSteps->value( ) );
+ repaint = true;
+ }
+ if( PMBlobSphere::vSteps( ) != m_pBlobSphereVSteps->value( ) )
+ {
+ PMBlobSphere::setVSteps( m_pBlobSphereVSteps->value( ) );
+ repaint = true;
+ }
+ if( PMBlobCylinder::uSteps( ) != m_pBlobCylinderUSteps->value( ) )
+ {
+ PMBlobCylinder::setUSteps( m_pBlobCylinderUSteps->value( ) );
+ repaint = true;
+ }
+ if( PMBlobCylinder::vSteps( ) != m_pBlobCylinderVSteps->value( ) )
+ {
+ PMBlobCylinder::setVSteps( m_pBlobCylinderVSteps->value( ) );
+ repaint = true;
+ }
+ if( PMPlane::planeSize( ) != m_pPlaneSize->value( ) )
+ {
+ PMPlane::setPlaneSize( m_pPlaneSize->value( ) );
+ repaint = true;
+ }
+ if( PMLathe::sSteps( ) != m_pLatheUSteps->value( ) )
+ {
+ PMLathe::setSSteps( m_pLatheUSteps->value( ) );
+ repaint = true;
+ }
+ if( PMLathe::rSteps( ) != m_pLatheRSteps->value( ) )
+ {
+ PMLathe::setRSteps( m_pLatheRSteps->value( ) );
+ repaint = true;
+ }
+ if( PMSurfaceOfRevolution::sSteps( ) != m_pSorUSteps->value( ) )
+ {
+ PMSurfaceOfRevolution::setSSteps( m_pSorUSteps->value( ) );
+ repaint = true;
+ }
+ if( PMSurfaceOfRevolution::rSteps( ) != m_pSorRSteps->value( ) )
+ {
+ PMSurfaceOfRevolution::setRSteps( m_pSorRSteps->value( ) );
+ repaint = true;
+ }
+ if( PMPrism::sSteps( ) != m_pPrismSteps->value( ) )
+ {
+ PMPrism::setSSteps( m_pPrismSteps->value( ) );
+ repaint = true;
+ }
+ if( PMSuperquadricEllipsoid::uSteps( ) != m_pSqeUSteps->value( ) )
+ {
+ PMSuperquadricEllipsoid::setUSteps( m_pSqeUSteps->value( ) );
+ repaint = true;
+ }
+ if( PMSuperquadricEllipsoid::vSteps( ) != m_pSqeVSteps->value( ) )
+ {
+ PMSuperquadricEllipsoid::setVSteps( m_pSqeVSteps->value( ) );
+ repaint = true;
+ }
+ if( PMSphereSweep::rSteps( ) != m_pSphereSweepRSteps->value( ) )
+ {
+ PMSphereSweep::setRSteps( m_pSphereSweepRSteps->value( ) );
+ repaint = true;
+ }
+ if( PMSphereSweep::sSteps( ) != m_pSphereSweepSSteps->value( ) )
+ {
+ PMSphereSweep::setSSteps( m_pSphereSweepSSteps->value( ) );
+ repaint = true;
+ }
+ if( PMHeightField::variance( ) != m_pHeightFieldVariance->value( ) )
+ {
+ PMHeightField::setVariance( m_pHeightFieldVariance->value( ) );
+ repaint = true;
+ }
+ if( repaint )
+ emit repaintViews( );
+}
+
+#include "pmobjectsettings.moc"
diff --git a/kpovmodeler/pmobjectsettings.h b/kpovmodeler/pmobjectsettings.h
new file mode 100644
index 00000000..716631c0
--- /dev/null
+++ b/kpovmodeler/pmobjectsettings.h
@@ -0,0 +1,78 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMOBJECTSETTINGS_H
+#define PMOBJECTSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+
+class PMIntEdit;
+class PMFloatEdit;
+class QCheckBox;
+
+/**
+ * Object details configuration dialog page
+ */
+class PMObjectSettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMObjectSettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual void displayDefaults( );
+
+private:
+ PMIntEdit* m_pSphereUSteps;
+ PMIntEdit* m_pSphereVSteps;
+ PMIntEdit* m_pCylinderSteps;
+ PMIntEdit* m_pConeSteps;
+ PMIntEdit* m_pTorusUSteps;
+ PMIntEdit* m_pTorusVSteps;
+ PMFloatEdit* m_pPlaneSize;
+ PMIntEdit* m_pDiscSteps;
+ PMIntEdit* m_pBlobSphereUSteps;
+ PMIntEdit* m_pBlobSphereVSteps;
+ PMIntEdit* m_pBlobCylinderUSteps;
+ PMIntEdit* m_pBlobCylinderVSteps;
+ PMIntEdit* m_pLatheUSteps;
+ PMIntEdit* m_pLatheRSteps;
+ PMIntEdit* m_pSorUSteps;
+ PMIntEdit* m_pSorRSteps;
+ PMIntEdit* m_pPrismSteps;
+ PMIntEdit* m_pSqeUSteps;
+ PMIntEdit* m_pSqeVSteps;
+ PMIntEdit* m_pSphereSweepRSteps;
+ PMIntEdit* m_pSphereSweepSSteps;
+ PMIntEdit* m_pHeightFieldVariance;
+ QCheckBox* m_pHighDetailCameraViews;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmopenglsettings.cpp b/kpovmodeler/pmopenglsettings.cpp
new file mode 100644
index 00000000..64f3ac9c
--- /dev/null
+++ b/kpovmodeler/pmopenglsettings.cpp
@@ -0,0 +1,59 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmopenglsettings.h"
+
+#include "pmglview.h"
+#include "pmdefaults.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+PMOpenGLSettings::PMOpenGLSettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ QVBoxLayout* vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+
+ m_pDirect = new QCheckBox( i18n( "Direct rendering" ), this );
+ vlayout->addWidget( new QLabel( i18n( "Changes take only effect after a restart!" ), this ) );
+ vlayout->addWidget( m_pDirect );
+ vlayout->addStretch( 1 );
+}
+
+void PMOpenGLSettings::displaySettings( )
+{
+ m_pDirect->setChecked( PMGLView::isDirectRenderingEnabled( ) );
+}
+
+void PMOpenGLSettings::displayDefaults( )
+{
+ m_pDirect->setChecked( true );
+}
+
+bool PMOpenGLSettings::validateData( )
+{
+ return true;
+}
+
+void PMOpenGLSettings::applySettings( )
+{
+ PMGLView::enableDirectRendering( m_pDirect->isChecked( ) );
+}
+
+#include "pmopenglsettings.moc"
diff --git a/kpovmodeler/pmopenglsettings.h b/kpovmodeler/pmopenglsettings.h
new file mode 100644
index 00000000..d893a6b0
--- /dev/null
+++ b/kpovmodeler/pmopenglsettings.h
@@ -0,0 +1,54 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMOPENGLSETTINGS_H
+#define PMOPENGLSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+
+class QCheckBox;
+
+/**
+ * OpenGL configuration dialog page
+ */
+class PMOpenGLSettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMOpenGLSettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual void displayDefaults( );
+
+private:
+ QCheckBox* m_pDirect;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmoutputdevice.cpp b/kpovmodeler/pmoutputdevice.cpp
new file mode 100644
index 00000000..5feb8ec2
--- /dev/null
+++ b/kpovmodeler/pmoutputdevice.cpp
@@ -0,0 +1,203 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmoutputdevice.h"
+#include "pmpovrayformat.h"
+#include <qtextstream.h>
+#include <klocale.h>
+
+unsigned int PMOutputDevice::s_indentOffset = 3;
+bool PMOutputDevice::s_bracketBehindType = true;
+
+PMOutputDevice::PMOutputDevice( QIODevice* dev, PMPovrayFormat* format )
+ : PMSerializer( dev ), m_stream( dev )
+{
+ m_pFormat = format;
+ m_indentation = 0;
+ m_lastWasComment = false;
+ m_pendingNewLine = false;
+ m_objectSeparation = false;
+}
+
+PMOutputDevice::~PMOutputDevice( )
+{
+}
+
+QString PMOutputDevice::description( ) const
+{
+ return QString( "POV-Ray" );
+}
+
+void PMOutputDevice::callSerialization( const PMObject* o, const PMMetaObject* mo )
+{
+ if( !mo )
+ return;
+
+ const PMPovraySerializeMethodInfo* info =
+ m_pFormat->serializationMethod( mo->className( ) );
+
+ if( info )
+ info->call( o, mo, this );
+ else
+ {
+ if( mo == o->metaObject( ) )
+ {
+ printError( i18n( "The object \"%1\" doesn't support %2." )
+ .arg( o->description( ) ).arg( description( ) ) );
+ }
+ else
+ {
+ printError( i18n( "The class \"%1\" doesn't support %2." )
+ .arg( o->description( ) ).arg( mo->className( ) ) );
+ }
+ }
+}
+
+void PMOutputDevice::serialize( PMObject* o )
+{
+ callSerialization( o, o->metaObject( ) );
+}
+
+void PMOutputDevice::close( )
+{
+// m_stream << ( char ) 0;
+}
+
+void PMOutputDevice::objectBegin( const QString& type )
+{
+ if( m_pendingNewLine )
+ newLine( );
+ if( m_objectSeparation )
+ newLine( );
+ m_stream << type;
+ if( s_bracketBehindType )
+ m_stream << " ";
+ else
+ newLine( );
+
+ m_stream << "{";
+ m_indentation++;
+ m_indentString.fill( ' ', s_indentOffset * m_indentation );
+ m_pendingNewLine = true;
+ m_objectSeparation = false;
+}
+
+void PMOutputDevice::declareBegin( const QString& id )
+{
+ if( m_pendingNewLine )
+ newLine( );
+ if( m_objectSeparation )
+ newLine( );
+ m_stream << "#declare " << id << " = ";
+
+ m_objectSeparation = false;
+}
+
+void PMOutputDevice::objectEnd( )
+{
+ m_indentation--;
+ m_indentString.fill( ' ', s_indentOffset * m_indentation );
+ newLine( );
+ m_stream << "}";
+ m_pendingNewLine = true;
+ m_objectSeparation = true;
+}
+
+void PMOutputDevice::writeLine( const QString& str )
+{
+ if( m_pendingNewLine )
+ newLine( );
+ m_stream << str;
+ m_pendingNewLine = true;
+ m_objectSeparation = true;
+}
+
+void PMOutputDevice::write( const QString& str )
+{
+ if( m_pendingNewLine )
+ newLine( );
+ m_stream << str;
+ m_objectSeparation = false;
+}
+
+void PMOutputDevice::newLine( )
+{
+ m_lastWasComment = false;
+ m_pendingNewLine = false;
+ m_stream << '\n' << m_indentString;
+}
+
+void PMOutputDevice::writeComment( const QString& text )
+{
+ QString s( text );
+ QTextStream str( &s, IO_ReadOnly );
+
+ bool lwc = m_lastWasComment;
+ if( m_pendingNewLine )
+ newLine( );
+ if( lwc )
+ newLine( );
+ if( m_objectSeparation )
+ newLine( );
+ if( str.atEnd( ) )
+ writeLine( "//" );
+ else
+ while( !str.atEnd( ) )
+ writeLine( QString( "// " ) + str.readLine( ) );
+ m_lastWasComment = true;
+ m_objectSeparation = false;
+}
+
+void PMOutputDevice::writeSemicolon( )
+{
+ // does not change m_pendingNewLine!
+ m_stream << ';';
+}
+
+void PMOutputDevice::writeName( const QString& name )
+{
+ if( !name.isEmpty( ) )
+ writeLine( QString( "//*PMName " ) + name );
+}
+
+QString PMOutputDevice::escapeAndQuoteString( const QString& s )
+{
+ QString result = "\"";
+ QString tmp = s;
+ QTextStream stream( &tmp, IO_ReadOnly );
+ QChar current, last;
+
+ while( !stream.atEnd( ) )
+ {
+ stream >> current ;
+ // not escaped quotation mark
+ if( ( current == '"' ) && ( last != '\\' ) )
+ result += '\\';
+ result += current;
+ // correctly quoted backslash
+ if( ( last == '\\' ) && ( current == '\\' ) )
+ current = QChar( 0 ); // clear the last char
+ last = current;
+ }
+ // backslash at the end
+ if( last == '\\' )
+ result += '\\';
+ result += '"';
+
+ return result;
+}
diff --git a/kpovmodeler/pmoutputdevice.h b/kpovmodeler/pmoutputdevice.h
new file mode 100644
index 00000000..25b3c58b
--- /dev/null
+++ b/kpovmodeler/pmoutputdevice.h
@@ -0,0 +1,159 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMOUTPUTDEVICE_H
+#define PMOUTPUTDEVICE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmserializer.h"
+
+#include <qstring.h>
+
+class QTextStream;
+class PMPovrayFormat;
+
+/**
+ * Output class for povray code.
+ *
+ * The class @ref PMPovrayFormat or a base class has factory methods
+ * to create an instance of this class. The output device uses the
+ * registered serialization methods of this povray format to serialize
+ * objects.
+ *
+ * This class handles the indentation and position of brackets
+ */
+
+class PMOutputDevice : public PMSerializer
+{
+public:
+ /**
+ * Creates an PMOutputDevice that serializes the povray code
+ * to the device
+ */
+ PMOutputDevice( QIODevice* dev, PMPovrayFormat* format );
+ /** */
+ virtual ~PMOutputDevice( );
+
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual void serialize( PMObject* o );
+ /** */
+ virtual void close( );
+
+ /**
+ * Writes the povray object type, an open bracket to the text stream
+ * and indents the next lines
+ */
+ void objectBegin( const QString& type );
+ /**
+ * Begins a declare with the identifier id
+ */
+ void declareBegin( const QString& id );
+ /**
+ * Writes an closing bracket to the text stream
+ * and decreases the indentation
+ */
+ void objectEnd( );
+ /**
+ * Writes a single line to the text stream. Don't include
+ * newlines in the string or indentation will not work properly.
+ *
+ * Adds a newline before the string.
+ */
+ void writeLine( const QString& str );
+ /**
+ * Writes the string to the text stream
+ */
+ void write( const QString& str );
+ /**
+ * Writes a new line to the text stream and indents the next line.
+ */
+ void newLine( );
+ /**
+ * Writes a comment string to the text stream
+ */
+ void writeComment( const QString& text );
+ /**
+ * Writes a semicolon after a call to objectEnd( )
+ */
+ void writeSemicolon( );
+ /**
+ * Writes a special name comment to the text stream, if the
+ * name is not empty
+ */
+ void writeName( const QString& name );
+
+ /**
+ * Returns the basic indentation offset
+ */
+ static unsigned int indentationOffset( ) { return s_indentOffset; }
+ /**
+ * Sets the basic indentation offset
+ */
+ static void setIndentationOffset( unsigned int offset )
+ { s_indentOffset = offset; }
+
+ /**
+ * If set to true, the open bracket after an object begin will be
+ * written behind the object type, otherwise in a new line.
+ */
+ static void setBracketBehindType( bool yes ) { s_bracketBehindType = yes; }
+ /**
+ * Returns true if the open bracket after an object begin will be
+ * written behind the object type
+ */
+ static bool bracketBehindType( ) { return s_bracketBehindType; }
+
+ /**
+ * Correctly escapes the string and puts quotation marks at the begin
+ * and end of the string.
+ *
+ * Escapes only not escaped characters. "\"" and "\\" in the string
+ * are not escaped.
+ */
+ static QString escapeAndQuoteString( const QString& s );
+
+ /**
+ * Calls the serialization method for the object o and class
+ * given by the meta object.
+ *
+ * If no method for this class was registered in the corresponding
+ * @ref PMPovrayFormat, an error is added the message list.
+ */
+ void callSerialization( const PMObject* o, const PMMetaObject* mo );
+
+private:
+ static unsigned int s_indentOffset;
+ static bool s_bracketBehindType;
+
+ PMPovrayFormat* m_pFormat;
+ unsigned int m_indentation;
+ QString m_indentString;
+ QTextStream m_stream;
+ bool m_lastWasComment;
+ bool m_pendingNewLine;
+ bool m_objectSeparation;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmpalettevalue.cpp b/kpovmodeler/pmpalettevalue.cpp
new file mode 100644
index 00000000..f2b26fff
--- /dev/null
+++ b/kpovmodeler/pmpalettevalue.cpp
@@ -0,0 +1,81 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpalettevalue.h"
+
+PMPaletteValue::PMPaletteValue( )
+{
+ m_index = 0;
+ m_value = 0.0;
+}
+
+PMPaletteValue::PMPaletteValue( int idx, double value )
+{
+ m_index = idx;
+ m_value = value;
+}
+
+void PMPaletteValue::setIndex( int idx )
+{
+ m_index = idx;
+}
+
+void PMPaletteValue::setValue( double value )
+{
+ m_value = value;
+}
+
+void PMPaletteValue::serialize( QDomElement& e, QDomDocument& /* doc */ ) const
+{
+ e.setAttribute( "index", m_index );
+ e.setAttribute( "value", m_value );
+}
+
+void PMPaletteValue::readAttributes( const QDomElement& h )
+{
+ QString str;
+ bool ok;
+
+ str = h.attribute( "index" );
+ if( str.isNull( ) )
+ m_index = 0;
+ else
+ {
+ m_index = str.toInt( &ok );
+ if( !ok ) m_index = 0;
+ }
+
+ str = h.attribute( "value" );
+ if( str.isNull( ) )
+ m_value = 0;
+ else
+ {
+ m_value = str.toDouble( &ok );
+ if( !ok ) m_value = 0;
+ }
+}
+
+bool PMPaletteValue::operator==( const PMPaletteValue& p ) const
+{
+ return ( m_index == p.m_index && m_value == p.m_value );
+}
+
+bool PMPaletteValue::operator!=( const PMPaletteValue& p ) const
+{
+ return ( m_index != p.m_index || m_value != p.m_value );
+}
diff --git a/kpovmodeler/pmpalettevalue.h b/kpovmodeler/pmpalettevalue.h
new file mode 100644
index 00000000..05f9712a
--- /dev/null
+++ b/kpovmodeler/pmpalettevalue.h
@@ -0,0 +1,78 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPALETTEVALUE_H
+#define PMPALETTEVALUE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+
+/**
+ * Class for pallete values used for filter and transmit in image maps.
+ */
+class PMPaletteValue
+{
+public:
+ /** */
+ PMPaletteValue();
+ /** */
+ PMPaletteValue( int idx, double value );
+ /**
+ * Returns the index of the palette entry.
+ */
+ int index( ) const { return m_index; }
+ /**
+ * Returns the value of the palette entry.
+ */
+ double value( ) const { return m_value; }
+ /**
+ * Sets the index of the palette entry.
+ */
+ void setIndex( int idx );
+ /**
+ * Sets the value of the palette entry.
+ */
+ void setValue( double val );
+ /**
+ * Serializes the palette entry into a XML document.
+ */
+ void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /**
+ * Reads the palette entry from a XML document.
+ */
+ void readAttributes( const QDomElement& h );
+
+ /**
+ * Returns true if both values have the same index and value
+ */
+ bool operator== ( const PMPaletteValue& p) const;
+ /**
+ * Returns false if both values have the same index and value
+ */
+ bool operator!= ( const PMPaletteValue& p) const;
+
+private:
+ int m_index;
+ double m_value;
+};
+
+#endif
diff --git a/kpovmodeler/pmpalettevalueedit.cpp b/kpovmodeler/pmpalettevalueedit.cpp
new file mode 100644
index 00000000..ae6ea653
--- /dev/null
+++ b/kpovmodeler/pmpalettevalueedit.cpp
@@ -0,0 +1,99 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpalettevalueedit.h"
+#include "pmpalettevalue.h"
+#include "pmlineedits.h"
+#include "pmdebug.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <ktabctl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+
+PMPaletteValueEdit::PMPaletteValueEdit( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ QLabel* lbl;
+ QHBoxLayout* layout;
+
+ m_pIndexEdit = new PMIntEdit( this );
+ m_pValueEdit = new PMFloatEdit( this );
+
+ layout = new QHBoxLayout( this );
+ lbl = new QLabel( i18n( "Index" ), this );
+ layout->addWidget( lbl );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ layout->addWidget( m_pIndexEdit );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ lbl = new QLabel( i18n( "Value" ), this );
+ layout->addWidget( lbl );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ layout->addWidget( m_pValueEdit );
+
+ connect( m_pIndexEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pValueEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMPaletteValueEdit::setIndex( int idx )
+{
+ m_pIndexEdit->setValue( idx );
+}
+
+void PMPaletteValueEdit::setValue( double val )
+{
+ m_pValueEdit->setValue( val );
+}
+
+int PMPaletteValueEdit::index( )
+{
+ return m_pIndexEdit->value( );
+}
+
+double PMPaletteValueEdit::value( )
+{
+ return m_pValueEdit->value( );
+}
+
+void PMPaletteValueEdit::setReadOnly( bool yes )
+{
+ m_pIndexEdit->setReadOnly( yes );
+ m_pValueEdit->setReadOnly( yes );
+}
+
+void PMPaletteValueEdit::setEnabled( bool yes )
+{
+ m_pIndexEdit->setEnabled( yes );
+ m_pValueEdit->setEnabled( yes );
+}
+
+bool PMPaletteValueEdit::isDataValid( )
+{
+ return ( m_pIndexEdit->isDataValid( ) && m_pValueEdit->isDataValid( ) );
+}
+
+#include "pmpalettevalueedit.moc"
diff --git a/kpovmodeler/pmpalettevalueedit.h b/kpovmodeler/pmpalettevalueedit.h
new file mode 100644
index 00000000..c5795cd9
--- /dev/null
+++ b/kpovmodeler/pmpalettevalueedit.h
@@ -0,0 +1,67 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPALETTEVALUEEDIT_H
+#define PMPALETTEVALUEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMFloatEdit;
+class PMIntEdit;
+
+/**
+ * Dialog edit class for @ref PMPaletteValue.
+ */
+class PMPaletteValueEdit: public QWidget
+{
+ Q_OBJECT
+public:
+ /** */
+ PMPaletteValueEdit( QWidget* parent, const char* name = 0 );
+ /** */
+ void setIndex( int idx );
+ /** */
+ int index( );
+ /** */
+ void setValue( double val );
+ /** */
+ double value( );
+ /**
+ * Returns true is both fields are valid numbers
+ */
+ bool isDataValid( );
+ /** */
+ void setReadOnly( bool yes = true );
+ /** */
+ virtual void setEnabled( bool yes );
+
+signals:
+ /** */
+ void dataChanged( );
+
+private:
+ PMIntEdit* m_pIndexEdit;
+ PMFloatEdit* m_pValueEdit;
+};
+
+#endif
diff --git a/kpovmodeler/pmpalettevaluememento.cpp b/kpovmodeler/pmpalettevaluememento.cpp
new file mode 100644
index 00000000..6db9b922
--- /dev/null
+++ b/kpovmodeler/pmpalettevaluememento.cpp
@@ -0,0 +1,84 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpalettevaluememento.h"
+#include "pmdebug.h"
+
+PMPaletteValueMemento::PMPaletteValueMemento( PMObject* originator )
+ : PMMemento( originator )
+{
+ m_bFilterPaletteValuesSaved = false;
+ m_bTransmitPaletteValuesSaved = false;
+}
+
+PMPaletteValueMemento::~PMPaletteValueMemento( )
+{
+}
+
+void PMPaletteValueMemento::setFilterPaletteValues( const QValueList<PMPaletteValue>& v )
+{
+ if( !m_bFilterPaletteValuesSaved )
+ {
+ // Direct assignment does not work with Qt 2.3.x
+ // The list will be changed later in a graphical
+ // change because QValueList::detach( ) is called
+ // too late!
+ // Copy the list by hand.
+
+ QValueList<PMPaletteValue>::ConstIterator it = v.begin( );
+ for( ; it != v.end( ); ++it )
+ m_filterPaletteValues.append( *it );
+
+ m_bFilterPaletteValuesSaved = true;
+ addChange( PMCData );
+ }
+}
+
+QValueList<PMPaletteValue> PMPaletteValueMemento::filterPaletteValues( ) const
+{
+ if( !m_bFilterPaletteValuesSaved )
+ kdError( PMArea ) << "Filter palette values not saved in PMPaletteValueMemento::filterPaletteValues\n";
+
+ return m_filterPaletteValues;
+}
+
+void PMPaletteValueMemento::setTransmitPaletteValues( const QValueList<PMPaletteValue>& v )
+{
+ if( !m_bTransmitPaletteValuesSaved )
+ {
+ // Direct assignment does not work with Qt 2.3.x
+ // The list will be changed later in a graphical
+ // change because QValueList::detach( ) is called
+ // too late!
+ // Copy the list by hand.
+
+ QValueList<PMPaletteValue>::ConstIterator it = v.begin( );
+ for( ; it != v.end( ); ++it )
+ m_transmitPaletteValues.append( *it );
+
+ m_bTransmitPaletteValuesSaved = true;
+ addChange( PMCData );
+ }
+}
+
+QValueList<PMPaletteValue> PMPaletteValueMemento::transmitPaletteValues( ) const
+{
+ if( !m_bTransmitPaletteValuesSaved )
+ kdError( PMArea ) << "Transmit palette values not saved in PMPaletteValueMemento::transmitPaletteValues\n";
+
+ return m_transmitPaletteValues;
+}
diff --git a/kpovmodeler/pmpalettevaluememento.h b/kpovmodeler/pmpalettevaluememento.h
new file mode 100644
index 00000000..0ac1242e
--- /dev/null
+++ b/kpovmodeler/pmpalettevaluememento.h
@@ -0,0 +1,85 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Passos Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPALETTEVALUEMEMENTO_H
+#define PMPALETTEVALUEMEMENTO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmmemento.h"
+#include "pmpalettevalue.h"
+#include <qvaluelist.h>
+
+
+/**
+ * Memento for @ref PMImageMap
+ */
+class PMPaletteValueMemento : public PMMemento
+{
+public:
+ /**
+ * Creates a memento for the object originator
+ */
+ PMPaletteValueMemento( PMObject* originator );
+ /**
+ * Deletes the memento
+ */
+ virtual ~PMPaletteValueMemento( );
+
+ /**
+ * Saves the filter palette values
+ */
+ void setFilterPaletteValues( const QValueList<PMPaletteValue>& v );
+ /**
+ * Returns the filter palette values
+ */
+ QValueList<PMPaletteValue> filterPaletteValues( ) const;
+ /**
+ * Returns true if the filter palette values were saved
+ */
+ bool filterPaletteValuesSaved( ) const { return m_bFilterPaletteValuesSaved; }
+ /**
+ * Saves the transmit palette values
+ */
+ void setTransmitPaletteValues( const QValueList<PMPaletteValue>& v );
+ /**
+ * Returns the transmit palette values
+ */
+ QValueList<PMPaletteValue> transmitPaletteValues( ) const;
+ /**
+ * Returns true if the transmit palette values were saved
+ */
+ bool transmitPaletteValuesSaved( ) const { return m_bTransmitPaletteValuesSaved; }
+
+private:
+ /**
+ * The stored values for filter
+ */
+ QValueList<PMPaletteValue> m_filterPaletteValues;
+ bool m_bFilterPaletteValuesSaved;
+ /**
+ * The stored values for transmit
+ */
+ QValueList<PMPaletteValue> m_transmitPaletteValues;
+ bool m_bTransmitPaletteValuesSaved;
+};
+
+#endif
diff --git a/kpovmodeler/pmparser.cpp b/kpovmodeler/pmparser.cpp
new file mode 100644
index 00000000..7a252c88
--- /dev/null
+++ b/kpovmodeler/pmparser.cpp
@@ -0,0 +1,433 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmparser.h"
+
+#include <qstring.h>
+#include <qbuffer.h>
+#include <klocale.h>
+
+#include "pmpart.h"
+#include "pmdeclare.h"
+#include "pmerrorflags.h"
+#include "pmrecursiveobjectiterator.h"
+#include "pmdebug.h"
+
+unsigned int PMParser::s_maxErrors = 30;
+unsigned int PMParser::s_maxWarnings = 50;
+
+
+PMParser::PMParser( PMPart* part, QIODevice* dev )
+ : m_okDeclares( 101 )
+{
+ m_pPart = part;
+ m_pDevice = dev;
+ m_bDeviceCreated = false;
+
+ init( );
+}
+
+PMParser::PMParser( PMPart* part, const QByteArray& array )
+ : m_okDeclares( 101 )
+{
+ m_pPart = part;
+ QBuffer* buffer = new QBuffer( array );
+ buffer->open( IO_ReadOnly );
+ m_pDevice = buffer;
+ m_bDeviceCreated = true;
+
+ init( );
+}
+
+void PMParser::init( )
+{
+ m_okDeclares.setAutoDelete( true );
+ m_pLocalST.setAutoDelete( true );
+
+ m_lineNum = -1;
+ m_pResultList = 0;
+ m_errors = 0;
+ m_warnings = 0;
+ m_bFatalError = false;
+ m_shownMessages = 0;
+ m_messages.clear( );
+
+ m_pTopParent = 0;
+ m_renamedObjectSymbols.clear( );
+ m_okDeclares.clear( );
+ m_pNextCheckDeclare = 0;
+}
+
+PMParser::~PMParser( )
+{
+ if( m_bDeviceCreated )
+ delete m_pDevice;
+}
+
+void PMParser::printMessage( const PMPMessage messageNum )
+{
+ if( !( m_shownMessages & messageNum ) )
+ {
+ m_shownMessages |= messageNum;
+
+ switch( messageNum )
+ {
+ case PMMClockDefault:
+ printWarning( i18n( "Using the default value of 0.0 for clock" ) );
+ break;
+ case PMMClockDeltaDefault:
+ printWarning( i18n( "Using the default value of 1.0 for clock_delta" ) );
+ break;
+ case PMMSpecialRawComment:
+ m_messages += PMMessage( i18n( "Note: The full povray syntax is not supported yet. "
+ "If you want to add unsupported povray code to the "
+ "scene, you can put this code between the two "
+ "special comments \"//*PMRawBegin\" and "
+ "\"//*PMRawEnd\"." ) );
+ break;
+ }
+ }
+}
+
+void PMParser::printMessage( const QString& type, const QString& msg )
+{
+ if( m_lineNum >= 0 )
+ m_messages += PMMessage( i18n( "Line %1: " ).arg( m_lineNum ) + type + ": " + msg );
+ else
+ m_messages += PMMessage( type + ": " + msg );
+}
+
+void PMParser::printError( const QString& msg )
+{
+ if( m_errors < s_maxErrors )
+ {
+ printMessage( i18n( "Error" ), msg );
+ m_errors++;
+ }
+ else if( m_errors == s_maxErrors )
+ {
+ m_messages += PMMessage( i18n( "Maximum of %1 errors reached." )
+ .arg( s_maxErrors ) );
+ m_errors++;
+ }
+}
+
+void PMParser::printWarning( const QString& msg )
+{
+ if( m_warnings < s_maxWarnings )
+ {
+ printMessage( i18n( "Warning" ), msg );
+ m_warnings++;
+ }
+ else if( m_warnings == s_maxWarnings )
+ {
+ m_messages += PMMessage( i18n( "Maximum of %1 warnings reached." )
+ .arg( s_maxWarnings ) );
+ m_warnings++;
+ }
+}
+
+void PMParser::printExpected( const char c, const char* sValue )
+{
+ printError( i18n( "'%1' expected, found token '%2' instead." )
+ .arg( c ).arg( sValue ) );
+}
+
+void PMParser::printExpected( const QString& str, const char* sValue )
+{
+ printError( i18n( "'%1' expected, found token '%2' instead." )
+ .arg( str ).arg( sValue ) );
+}
+
+void PMParser::printUnexpected( const QString& str )
+{
+ printError( i18n( "Unexpected token '%1'." ).arg( str ) );
+}
+
+void PMParser::printInfo( const QString& msg )
+{
+ printMessage( i18n( "Info" ), msg );
+}
+
+int PMParser::errorFlags( ) const
+{
+ int result = 0;
+ if( errors( ) )
+ result |= PMEError;
+ if( warnings( ) )
+ result |= PMEWarning;
+ if( fatal( ) )
+ result |= PMEFatal;
+ return result;
+}
+
+
+void PMParser::parse( PMObjectList* list, PMObject* parent,
+ PMObject* after )
+{
+ m_pResultList = list;
+ m_pTopParent = parent;
+ m_pAfter = after;
+
+ // find first item, that can be a declare and can be used as link
+ // for parsed objects.
+ if( parent )
+ {
+ if( parent->type( ) == "Scene" )
+ {
+ if( after )
+ m_pNextCheckDeclare = after;
+ else
+ m_pNextCheckDeclare = 0;
+ }
+ else
+ {
+ PMObject* obj = parent;
+ bool stop = false;
+
+ // go to parents, until the parent is the scene
+ // (declares can only be inserted as top level objects)
+ do
+ {
+ if( obj->parent( ) )
+ {
+ if( obj->parent( )->type( ) == "Scene" )
+ stop = true;
+ else
+ obj = obj->parent( );
+ }
+ else
+ {
+ obj = 0;
+ stop = true;
+ }
+ }
+ while( obj && !stop );
+
+ // now obj is the top level parent of the object, where parsed objects
+ // will be inserted
+ if( obj )
+ m_pNextCheckDeclare = obj->prevSibling( );
+ else
+ m_pNextCheckDeclare = 0;
+ }
+ }
+
+ topParse( );
+
+ QPtrListIterator<PMSymbol> it( m_renamedObjectSymbols );
+ for( ; it.current( ); ++it )
+ it.current( )->setRenamedSymbol( 0 );
+ m_renamedObjectSymbols.clear( );
+ m_pLocalST.clear( );
+
+ if( ( errors( ) || warnings( ) ) && m_pResultList->isEmpty( ) )
+ setFatalError( );
+}
+
+bool PMParser::insertChild( PMObject* child, PMObject* parent )
+{
+ bool inserted = false;
+
+ if( parent )
+ {
+ if( parent->canInsert( child, parent->lastChild( ) ) )
+ {
+ parent->appendChild( child );
+ inserted = true;
+ }
+ else
+ {
+ printError( i18n( "Can't insert %1 into %2." )
+ .arg( child->description( ) )
+ .arg( parent->description( ) ) );
+ }
+ }
+ else
+ {
+ if( m_pTopParent )
+ {
+ if( m_pTopParent->canInsert( child, m_pAfter, m_pResultList ) )
+ {
+ m_pResultList->append( child );
+ inserted = true;
+ }
+ else
+ {
+ printError( i18n( "Can't insert %1 into %2." )
+ .arg( child->description( ) )
+ .arg( m_pTopParent->description( ) ) );
+ }
+ }
+ else
+ {
+ // these lines should not be executed
+ // m_pTopParent may not be null
+ m_pResultList->append( child );
+ inserted = true;
+ }
+ }
+
+ if( !inserted )
+ {
+ // insert error
+ // remove all links
+ PMRecursiveObjectIterator rit( child );
+ PMDeclare* decl = 0;
+
+ for( ; rit.current( ); ++rit )
+ {
+ decl = rit.current( )->linkedObject( );
+ if( decl )
+ decl->removeLinkedObject( rit.current( ) );
+ }
+ }
+
+ return inserted;
+}
+
+void PMParser::checkID( PMDeclare* decl )
+{
+ PMSymbolTable* st = m_pPart->symbolTable( );
+ PMSymbol* s = m_pLocalST.find( decl->id( ) );
+ if( !s )
+ s = st->find( decl->id( ) );
+
+ if( s )
+ {
+ PMSymbol* newSym = st->findNewID( s->id( ) + "_", decl );
+ s->setRenamedSymbol( newSym );
+ // Symbol can be inserted multiple times
+ // Faster than searching for s and inserting s
+ // if the list does not contain it.
+ m_renamedObjectSymbols.append( s );
+
+ if( m_pTopParent )
+ m_pLocalST.insert( decl->id( ), newSym ); // paste/drop
+ else
+ st->insert( decl->id( ), newSym ); // load file
+ }
+ else
+ {
+ s = new PMSymbol( decl->id( ), decl );
+ if( m_pTopParent )
+ m_pLocalST.insert( decl->id( ), s ); // paste/drop
+ else
+ st->insert( decl->id( ), s ); // load file
+ m_okDeclares.insert( decl->id( ), new bool( true ) );
+ }
+}
+
+void PMParser::checkID( const QString& id, const PMValue& v )
+{
+ PMSymbolTable* st = m_pPart->symbolTable( );
+ PMSymbol* s = m_pLocalST.find( id );
+
+ if( s )
+ {
+ PMSymbol* newSym = new PMSymbol( st->findNewID( id + "_" ), v );
+ s->setRenamedSymbol( newSym );
+ // Symbol can be inserted multiple times
+ // Faster than searching for s and inserting s
+ // if the list does not contain it.
+ m_renamedObjectSymbols.append( s );
+
+ if( m_pTopParent )
+ m_pLocalST.insert( id, newSym ); // paste/drop
+
+ // values are never inserted into the parts symbol table
+ // else
+ // st->insert( decl->id( ), newSym ); // load file
+ }
+ else
+ {
+ s = new PMSymbol( id, v );
+ if( m_pTopParent )
+ m_pLocalST.insert( id, s ); // paste/drop
+
+ // values are never inserted into the parts symbol table
+ // else
+ // st->insert( decl->id( ), s ); // load file
+
+ m_okDeclares.insert( id, new bool( true ) );
+ }
+}
+
+PMDeclare* PMParser::checkLink( const QString& id )
+{
+ PMSymbolTable* t = m_pPart->symbolTable( );
+ bool ok = false;
+
+ // is object declared?
+ PMSymbol* s = m_pLocalST.find( id );
+ if( !s )
+ s = t->find( id );
+
+ if( !s )
+ printError( i18n( "Undefined object \"%1\"." ).arg( id ) );
+ else if( s->type( ) != PMSymbol::Object )
+ printError( i18n( "Undefined object \"%1\"." ).arg( id ) );
+ else
+ {
+ // the object is declared
+ // is the id already in m_okDeclares
+ bool* lok = m_okDeclares.find( id );
+ if( lok )
+ ok = true;
+ else
+ {
+ // the id is not in m_okDeclares
+ PMObject* obj = s->object( );
+ while( m_pNextCheckDeclare && !ok )
+ {
+ if( m_pNextCheckDeclare->isA( "Declare" ) )
+ {
+ PMDeclare* decl = ( PMDeclare* ) m_pNextCheckDeclare;
+ m_okDeclares.insert( decl->id( ), new bool( true ) );
+ }
+ if( m_pNextCheckDeclare == obj )
+ ok = true;
+
+ m_pNextCheckDeclare = m_pNextCheckDeclare->prevSibling( );
+ }
+ }
+
+ if( !ok )
+ printError( i18n( "Object \"%1\" is undefined at that point." )
+ .arg( id ) );
+ }
+
+ if( ok )
+ {
+ while( s->renamedSymbol( ) )
+ s = s->renamedSymbol( );
+
+ return s->object( );
+ }
+
+ return 0;
+}
+
+PMSymbol* PMParser::getSymbol( const QString& id ) const
+{
+ PMSymbol* s = m_pLocalST.find( id );
+ if( !s )
+ s = m_pPart->symbolTable( )->find( id );
+ return s;
+}
+
diff --git a/kpovmodeler/pmparser.h b/kpovmodeler/pmparser.h
new file mode 100644
index 00000000..48250798
--- /dev/null
+++ b/kpovmodeler/pmparser.h
@@ -0,0 +1,299 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPARSER_H
+#define PMPARSER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kurl.h>
+#include <qcstring.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qptrdict.h>
+#include <qptrlist.h>
+
+#include "pmobject.h"
+#include "pmsymboltable.h"
+#include "pmvalue.h"
+#include "pmerrordialog.h"
+
+class QTextStream;
+class QIODevice;
+
+class PMScanner;
+class PMPart;
+class PMSymbolTable;
+
+enum PMPMessage { PMMClockDefault = 1, PMMClockDeltaDefault = 2,
+ PMMSpecialRawComment = 4 };
+
+/**
+ * Base class for kpovmodeler parsers.
+ */
+class PMParser
+{
+public:
+ /**
+ * Parser that parses the device
+ */
+ PMParser( PMPart* part, QIODevice* device );
+ /**
+ * Parser that parses the byte array
+ */
+ PMParser( PMPart* part, const QByteArray& array );
+ /**
+ * Deletes the parser
+ */
+ virtual ~PMParser( );
+
+ /**
+ * Quickly scans the top level objects. Appends all top level object
+ * types to the list.
+ */
+ virtual void quickParse( QStringList& /*list*/ ) { };
+ /**
+ * Returns true, if the parser can quickly scan the top level objects.
+ */
+ virtual bool canQuickParse( ) const { return false; }
+
+ /**
+ * Parses the device.
+ *
+ * Appends all parsed objects to the list.
+ *
+ * parent is the object where the parsed objects will be inserted as
+ * children behind the object after. These parameters are used to check
+ * the consistency of declares and links.
+ *
+ * Set parent and after to 0 if and only if a document is parsed/opened.
+ */
+ void parse( PMObjectList* list, PMObject* parent,
+ PMObject* after );
+
+ /**
+ * Returns the messages of the parser
+ */
+ PMMessageList messages( ) const { return m_messages; }
+ /**
+ * Returns true if there were errors during parsing
+ */
+ bool errors( ) const { return m_errors > 0; }
+ /**
+ * Returns true if there were warnings during parsing
+ */
+ bool warnings( ) const { return m_warnings > 0; }
+ /**
+ * Returns true, if a fatal error occurred or no object could be
+ * successfully parsed and it doesn't make sense to continue
+ */
+ bool fatal( ) const { return m_bFatalError; }
+ /**
+ * Returns a bitwise combination of @ref PMErrorFlags constants
+ */
+ int errorFlags( ) const;
+
+ /**
+ * returns the maximum number of errors
+ */
+ static unsigned maxErrors( ) { return s_maxErrors; }
+ /**
+ * sets the maximum number of errors to m
+ */
+ static void setMaxErrors( unsigned m ) { s_maxErrors = m; }
+ /**
+ * returns the maximum number of warnings
+ */
+ static unsigned maxWarnings( ) { return s_maxWarnings; }
+ /**
+ * sets the maximum number of warnings to m
+ */
+ static void setMaxWarnings( unsigned m ) { s_maxWarnings = m; }
+
+ /**
+ * Adds an error to the message string
+ */
+ void printError( const QString& msg );
+ /**
+ * Adds the error "'<str>' expected, found <token> instead" to the message string
+ */
+ void printExpected( const QString& str, const char* token );
+ /**
+ * Adds the error "'<c>' expected" to the message string
+ */
+ void printExpected( const char c, const char* token );
+ /**
+ * Adds the error "Unexpected token '<str>', found <token> instead" to the message string
+ */
+ void printUnexpected( const QString& str );
+ /**
+ * Adds a warning to the message string
+ */
+ void printWarning( const QString& msg );
+ /**
+ * Adds an info to the message string
+ */
+ void printInfo( const QString& msg );
+ /**
+ * Adds the message to the message string. Type is "error", "warning",
+ * "info" or "scanner error"
+ */
+ void printMessage( const QString& type, const QString& msg );
+ /**
+ * Prints a messages that should only reported once
+ */
+ void printMessage( const PMPMessage messageNum );
+
+ /**
+ * Sets the fatal error flag
+ */
+ void setFatalError( ) { m_bFatalError = true; }
+
+ /**
+ * Sets the current line number
+ */
+ void setCurrentLine( int lineNumber ) { m_lineNum = lineNumber; }
+
+ /**
+ * Returns the declare object with id, if it exists and is declared at
+ * the current parse position, otherwise 0
+ */
+ PMDeclare* checkLink( const QString& id );
+ /**
+ * Checks the id of the declare. If there is already a declare with
+ * the same id, the id of the object is renamed.
+ *
+ * Inserts the object into the symbol table.*/
+ void checkID( PMDeclare* obj );
+ /**
+ * Checks the id of the value declare (constant, vector or color).
+ * If there is already a declare with
+ * the same id, the id of the value is renamed.
+ *
+ * Inserts the object into the symbol table.*/
+ void checkID( const QString& id, const PMValue& v );
+ /**
+ * Returns the symbol with id id or 0 if the id is undeclared
+ */
+ PMSymbol* getSymbol( const QString& id ) const;
+ /**
+ * Tries to insert obj as child of parent. If parent is 0, the object
+ * will be inserted in the list of top level objects.
+ *
+ * Returns true if the object could be inserted.
+ */
+ bool insertChild( PMObject* obj, PMObject* parent );
+
+protected:
+ /**
+ * Top level parse function.
+ *
+ * Overwrite this function in a specific parser.
+ */
+ virtual void topParse( ) = 0;
+
+protected:
+ /**
+ * Pointer to the part
+ */
+ PMPart* m_pPart;
+ /**
+ * parent object where the parsed top level objects
+ * will be inserted _later_ (not from the parser) as children
+ */
+ const PMObject* m_pTopParent;
+ const PMObject* m_pAfter;
+ /**
+ * The list where the parsed objects are stored
+ */
+ PMObjectList* m_pResultList;
+ /**
+ * The QIODevice
+ */
+ QIODevice* m_pDevice;
+ /**
+ * True, if the device was created by the parser
+ */
+ bool m_bDeviceCreated;
+
+private:
+ /**
+ * Initializes the parser
+ */
+ void init( );
+
+ /**
+ * The parser output (errors, warnings...)
+ */
+ PMMessageList m_messages;
+ /**
+ * A dictionary object -> message
+ */
+ QPtrDict< QPtrList<PMMessage> > m_messageDict;
+ /**
+ * Number of warnings during parsing
+ */
+ unsigned int m_warnings;
+ /**
+ * Number of errors during parsing
+ */
+ unsigned int m_errors;
+ /**
+ * Flag for fatal errors
+ */
+ bool m_bFatalError;
+
+ /**
+ * maximum number of errors
+ */
+ static unsigned int s_maxErrors;
+ /**
+ * maximum number of warnings
+ */
+ static unsigned int s_maxWarnings;
+ /**
+ * Already shown warnings or errors, that are reported only once
+ */
+ int m_shownMessages;
+ /**
+ * The current line number
+ */
+ int m_lineNum;
+ /**
+ * List of renamed declares
+ */
+ QPtrList<PMSymbol> m_renamedObjectSymbols;
+ /**
+ * Dictionary of symbol names, that can be linked
+ */
+ QDict<bool> m_okDeclares;
+ PMObject* m_pNextCheckDeclare;
+ /**
+ * Symbol table used during parsing. The symbol table of the part
+ * will not be changed.
+ */
+ PMSymbolTable m_pLocalST;
+};
+
+
+
+#endif
diff --git a/kpovmodeler/pmpart.cpp b/kpovmodeler/pmpart.cpp
new file mode 100644
index 00000000..c87f4719
--- /dev/null
+++ b/kpovmodeler/pmpart.cpp
@@ -0,0 +1,2884 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+// include files for QT
+#include <qapplication.h>
+#include <qdir.h>
+#include <qstrlist.h>
+#include <qclipboard.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qmessagebox.h>
+#include <qcombobox.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <qdatetime.h>
+#include <qstringlist.h>
+
+// include files for KDE
+#include <kiconloader.h>
+#include <kconfig.h>
+#include <kstdaction.h>
+#include <kaction.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <kfilterdev.h>
+#include <kfiledialog.h>
+
+// application specific includes
+#include "pmpart.h"
+#include "pmshell.h"
+#include "pmview.h"
+#include "pmglview.h"
+#include "pmallcommands.h"
+#include "pmpovraywidget.h"
+#include "pmpovrayrenderwidget.h"
+
+#include "pmallobjects.h"
+#include "pmcommandmanager.h"
+#include "pmobjectdrag.h"
+#include "pmxmlparser.h"
+#include "pmpovrayparser.h"
+#include "pmerrordialog.h"
+#include "pmsettingsdialog.h"
+#include "pminserterrordialog.h"
+#include "pminsertpopup.h"
+
+#include "pmpovray35format.h"
+#include "pmserializer.h"
+
+#include "pmfactory.h"
+#include "pmdefaults.h"
+#include "pmsymboltable.h"
+
+#include "pmrendermodesdialog.h"
+#include "pmrendermode.h"
+#include "pmpovrayoutputwidget.h"
+#include "pmrendermanager.h"
+#include "pmdialogeditbase.h"
+#include "pmdocumentationmap.h"
+#include "pmlibrarymanager.h"
+#include "pmlibraryhandleedit.h"
+#include "pmlibraryobject.h"
+#include "pmlibrarybrowser.h"
+#include "pmlibraryobjectsearch.h"
+#include "pmscene.h"
+
+#include "pmpluginmanager.h"
+#include "pminsertrulesystem.h"
+#include "pmprototypemanager.h"
+#include "pmiomanager.h"
+
+#include "pmactions.h"
+#include "pmrecursiveobjectiterator.h"
+
+#include "pmerrorflags.h"
+
+#include "pmfiledialog.h"
+
+#ifdef PMEnableSimpleProfiling
+QTime PMDebugTime;
+#endif
+
+//#define KPM_WITH_OBJECT_LIBRARY
+
+PMPart::PMPart( QWidget* parentWidget, const char* widgetName,
+ QObject* parent, const char* name, bool readwrite,
+ PMShell* shell )
+ : DCOPObject( "PMPartIface" ),
+ KParts::ReadWritePart( parent, name ),
+ m_commandManager( this )
+{
+ setPluginLoadingMode( LoadPlugins );
+ setInstance( PMFactory::instance( ), false );
+ m_pExtension = new PMBrowserExtension( this );
+
+ m_pActiveObject = 0;
+ m_canDecode = false;
+ m_pScene = 0;
+ m_pNewSelection = 0;
+ m_sortedListUpToDate = false;
+ m_numAddedObjects = 0;
+ m_numInsertErrors = 0;
+ m_pSymbolTable = 0;
+ m_bCameraListUpToDate = true;
+ m_updateNewObjectActions = false;
+ m_pPovrayWidget = 0;
+ m_pView = 0;
+ m_pShell = shell;
+ m_controlPoints.setAutoDelete( true );
+ m_onlyCopyPaste = true;
+
+ // call inits to invoke all other construction parts
+ setReadWrite( readwrite );
+
+ if( isReadWrite( ) )
+ setXMLFile( "kpovmodelerui.rc" );
+ else
+ setXMLFile( "kpovmodelerbrowser.rc" );
+
+ m_pPrototypeManager = new PMPrototypeManager( this );
+ m_pInsertRuleSystem = new PMInsertRuleSystem( this );
+ m_pIOManager = new PMIOManager( this );
+ m_pInsertRuleSystem->loadRules( "baseinsertrules.xml" );
+
+ initActions( );
+ initDocument( );
+ initView( parentWidget, widgetName );
+
+ restoreConfig( instance( )->config( ) );
+
+ connect( qApp->clipboard( ), SIGNAL( dataChanged( ) ),
+ SLOT( slotClipboardDataChanged( ) ) );
+ slotClipboardDataChanged( );
+ connect( &m_commandManager, SIGNAL( updateUndoRedo( const QString&, const QString& ) ),
+ SLOT( slotUpdateUndoRedo( const QString&, const QString& ) ) );
+ connect( &m_commandManager, SIGNAL( objectChanged( PMObject*, const int, QObject* ) ),
+ SLOT( slotObjectChanged( PMObject*, const int, QObject* ) ) );
+ connect( &m_commandManager, SIGNAL( idChanged( PMObject*, const QString& ) ),
+ SLOT( slotIDChanged( PMObject*, const QString& ) ) );
+
+ PMPluginManager::theManager( )->registerPart( this );
+
+ emit refresh( );
+ slotObjectChanged( m_pScene, PMCNewSelection, this );
+}
+
+PMPart::PMPart( QWidget* /*parentWidget*/, const char* /*widgetName*/,
+ QObject* parent, const char* name, bool readwrite,
+ bool /*onlyCutPaste*/, PMShell* shell )
+ : DCOPObject( "LibraryBrowserIface" ),
+ KParts::ReadWritePart( parent, name ),
+ m_commandManager( this )
+{
+ setPluginLoadingMode( LoadPlugins );
+ setInstance( PMFactory::instance( ), false );
+
+ m_pActiveObject = 0;
+ m_canDecode = false;
+ m_pNewSelection = 0;
+ m_sortedListUpToDate = false;
+ m_numAddedObjects = 0;
+ m_numInsertErrors = 0;
+ m_pSymbolTable = 0;
+ m_bCameraListUpToDate = true;
+ m_updateNewObjectActions = false;
+ m_pPovrayWidget = 0;
+ m_pView = 0;
+ m_pShell = shell;
+ m_pScene = new PMScene( this );
+ m_onlyCopyPaste = true;
+
+ // call inits to invoke all other construction parts
+ setReadWrite( readwrite );
+
+ if( isReadWrite( ) )
+ setXMLFile( "kpovmodelerui.rc" );
+ else
+ setXMLFile( "kpovmodelerbrowser.rc" );
+
+ m_pPrototypeManager = new PMPrototypeManager( this );
+ m_pInsertRuleSystem = new PMInsertRuleSystem( this );
+ m_pIOManager = new PMIOManager( this );
+ m_pInsertRuleSystem->loadRules( "baseinsertrules.xml" );
+ m_pSymbolTable = new PMSymbolTable( );
+
+ initCopyPasteActions( );
+
+ connect( &m_commandManager, SIGNAL( objectChanged( PMObject*, const int, QObject* ) ),
+ SLOT( slotObjectChanged( PMObject*, const int, QObject* ) ) );
+
+ PMPluginManager::theManager( )->registerPart( this );
+
+ emit refresh( );
+}
+
+PMPart::~PMPart( )
+{
+ delete m_pExtension;
+ deleteContents( );
+ delete m_pSymbolTable;
+ delete m_pPovrayWidget;
+ PMPluginManager::theManager( )->removePart( this );
+}
+
+void PMPart::initCopyPasteActions( )
+{
+ // setup edit menu
+ m_pCutAction = KStdAction::cut( this, SLOT( slotEditCut( ) ), actionCollection( ) );
+ m_pCopyAction = KStdAction::copy( this, SLOT( slotEditCopy( ) ), actionCollection( ) );
+ m_pPasteAction = KStdAction::paste( this, SLOT( slotEditPaste( ) ), actionCollection( ) );
+
+ m_pDeleteAction =
+ new KAction( i18n( "Delete" ), "edittrash", Qt::Key_Delete,
+ this, SLOT( slotEditDelete( ) ),
+ actionCollection( ), "edit_delete" );
+
+ m_pCutAction->setEnabled( false );
+ m_pCopyAction->setEnabled( false );
+ m_pPasteAction->setEnabled( false );
+ m_pDeleteAction->setEnabled( false );
+
+}
+
+void PMPart::initActions( )
+{
+ // file menu
+ m_pImportAction = new KAction( i18n( "Import..." ), 0, this,
+ SLOT( slotFileImport( ) ), actionCollection( ),
+ "file_import" );
+ m_pExportAction = new KAction( i18n( "&Export..." ), 0, this,
+ SLOT( slotFileExport( ) ), actionCollection( ),
+ "file_export" );
+
+ initCopyPasteActions( );
+ m_onlyCopyPaste = false;
+
+ m_pRenderComboAction = new PMComboAction( i18n( "Render Modes" ), 0, this, SLOT( slotRenderMode( int ) ),
+ actionCollection( ), "view_render_combo" );
+ m_pRenderComboAction->setMinimumWidth( 250 );
+ connect( m_pRenderComboAction, SIGNAL( plugged( ) ),
+ SLOT( slotRenderModeActionPlugged( ) ) );
+ m_pRenderAction = new KAction( i18n( "Render" ), "pmrender", 0, this, SLOT( slotRender( ) ),
+ actionCollection( ), "view_render" );
+ m_pRenderSettingsAction = new KAction( i18n( "Render Modes..." ), "pmrendersettings", 0, this, SLOT( slotRenderSettings( ) ),
+ actionCollection( ), "view_render_settings" );
+ m_pViewRenderWindowAction = new KAction( i18n( "Render Window" ), 0, this, SLOT( slotViewRenderWindow( ) ),
+ actionCollection( ), "view_render_window" );
+ m_pVisibilityLabelAction = new PMLabelAction( i18n( "Visibility level:" ) + QString( " " ), actionCollection( ), "view_visibility_label" );
+ m_pVisibilityLevelAction = new PMSpinBoxAction( i18n( "Visibility Level" ),
+ 0, this, SLOT( slotVisibilityLevelChanged( int ) ),
+ actionCollection( ), "view_visibility_level" );
+ connect( m_pVisibilityLevelAction, SIGNAL( plugged( ) ),
+ SLOT( slotVisibilityActionPlugged( ) ) );
+
+ m_pGlobalDetailLabelAction = new PMLabelAction( i18n( "Global detail:" ) + QString( " " ), actionCollection( ), "global_detail_label" );
+ m_pGlobalDetailAction = new KSelectAction( i18n("Global Detail Level"), KShortcut(), actionCollection(), "global_detail_level" );
+ QStringList strList;
+ strList.append( i18n( "Very Low" ) );
+ strList.append( i18n( "Low" ) );
+ strList.append( i18n( "Medium" ) );
+ strList.append( i18n( "High" ) );
+ strList.append( i18n( "Very High" ) );
+ m_pGlobalDetailAction->setItems( strList );
+ connect( m_pGlobalDetailAction, SIGNAL( activated( int ) ), SLOT( slotGlobalDetailLevelChanged( int ) ) );
+
+ // new objects
+ if( isReadWrite( ) )
+ {
+ m_pNewGlobalSettingsAction = new KAction( i18n( "Global Settings" ), "pmglobalsettings", 0, this, SLOT( slotNewGlobalSettings( ) ),
+ actionCollection( ), "new_globalsettings" );
+ m_readWriteActions.append( m_pNewGlobalSettingsAction );
+ m_pNewSkySphereAction = new KAction( i18n( "Sky Sphere" ), "pmskysphere", 0, this, SLOT( slotNewSkySphere( ) ),
+ actionCollection( ), "new_skysphere" );
+ m_readWriteActions.append( m_pNewSkySphereAction );
+ m_pNewRainbowAction = new KAction( i18n( "Rainbow" ), "pmrainbow", 0, this, SLOT( slotNewRainbow( ) ),
+ actionCollection( ), "new_rainbow" );
+ m_readWriteActions.append( m_pNewRainbowAction );
+ m_pNewFogAction = new KAction( i18n( "Fog" ), "pmfog", 0, this, SLOT( slotNewFog( ) ),
+ actionCollection( ), "new_fog" );
+ m_readWriteActions.append( m_pNewFogAction );
+ m_pNewInteriorAction = new KAction( i18n( "Interior" ), "pminterior", 0, this, SLOT( slotNewInterior( ) ),
+ actionCollection( ), "new_interior" );
+ m_readWriteActions.append( m_pNewInteriorAction );
+ m_pNewMediaAction = new KAction( i18n( "Media" ), "pmmedia", 0, this, SLOT( slotNewMedia( ) ),
+ actionCollection( ), "new_media" );
+ m_readWriteActions.append( m_pNewMediaAction );
+ m_pNewDensityAction = new KAction( i18n( "Density" ), "pmdensity", 0, this, SLOT( slotNewDensity( ) ),
+ actionCollection( ), "new_density" );
+ m_readWriteActions.append( m_pNewDensityAction );
+ m_pNewMaterialAction = new KAction( i18n( "Material" ), "pmmaterial", 0, this, SLOT( slotNewMaterial( ) ),
+ actionCollection( ), "new_material" );
+ m_readWriteActions.append( m_pNewMaterialAction );
+ m_pNewBoxAction = new KAction( i18n( "Box" ), "pmbox", 0, this, SLOT( slotNewBox( ) ),
+ actionCollection( ), "new_box" );
+ m_readWriteActions.append( m_pNewBoxAction );
+ m_pNewSphereAction = new KAction( i18n( "Sphere" ), "pmsphere", 0, this, SLOT( slotNewSphere( ) ),
+ actionCollection( ), "new_sphere" );
+ m_readWriteActions.append( m_pNewSphereAction );
+ m_pNewCylinderAction = new KAction( i18n( "Cylinder" ), "pmcylinder", 0, this, SLOT( slotNewCylinder( ) ),
+ actionCollection( ), "new_cylinder" );
+ m_readWriteActions.append( m_pNewCylinderAction );
+ m_pNewConeAction = new KAction( i18n( "Cone" ), "pmcone", 0, this, SLOT( slotNewCone( ) ),
+ actionCollection( ), "new_cone" );
+ m_readWriteActions.append( m_pNewConeAction );
+ m_pNewTorusAction = new KAction( i18n( "Torus" ), "pmtorus", 0, this, SLOT( slotNewTorus( ) ),
+ actionCollection( ), "new_torus" );
+ m_readWriteActions.append( m_pNewTorusAction );
+
+ m_pNewLatheAction = new KAction( i18n( "Lathe" ), "pmlathe", 0, this, SLOT( slotNewLathe( ) ),
+ actionCollection( ), "new_lathe" );
+ m_readWriteActions.append( m_pNewLatheAction );
+ m_pNewPrismAction = new KAction( i18n( "Prism" ), "pmprism", 0, this, SLOT( slotNewPrism( ) ),
+ actionCollection( ), "new_prism" );
+ m_readWriteActions.append( m_pNewPrismAction );
+ m_pNewSurfaceOfRevolutionAction = new KAction( i18n( "Surface of Revolution" ), "pmsor", 0, this, SLOT( slotNewSurfaceOfRevolution( ) ),
+ actionCollection( ), "new_surfaceofrevolution" );
+ m_readWriteActions.append( m_pNewSurfaceOfRevolutionAction );
+ m_pNewSuperquadricEllipsoidAction = new KAction( i18n( "Superquadric Ellipsoid" ), "pmsqe", 0, this, SLOT( slotNewSuperquadricEllipsoid( ) ),
+ actionCollection( ), "new_superquadricellipsoid" );
+ m_readWriteActions.append( m_pNewSuperquadricEllipsoidAction );
+
+ m_pNewJuliaFractalAction = new KAction( i18n( "Julia Fractal" ), "pmjuliafractal", 0, this, SLOT( slotNewJuliaFractal( ) ),
+ actionCollection( ), "new_juliafractal" );
+ m_readWriteActions.append( m_pNewJuliaFractalAction );
+ m_pNewHeightFieldAction = new KAction( i18n( "Height Field" ), "pmheightfield", 0, this, SLOT( slotNewHeightField( ) ),
+ actionCollection( ), "new_heightfield" );
+ m_readWriteActions.append( m_pNewHeightFieldAction );
+ m_pNewTextAction = new KAction( i18n( "Text" ), "pmtext", 0, this, SLOT( slotNewText( ) ),
+ actionCollection( ), "new_text" );
+ m_readWriteActions.append( m_pNewTextAction );
+
+ m_pNewBlobAction = new KAction( i18n( "Blob" ), "pmblob", 0, this, SLOT( slotNewBlob( ) ),
+ actionCollection( ), "new_blob" );
+ m_readWriteActions.append( m_pNewBlobAction );
+ m_pNewBlobSphereAction = new KAction( i18n( "Blob Sphere" ), "pmblobsphere", 0, this, SLOT( slotNewBlobSphere( ) ),
+ actionCollection( ), "new_blobsphere" );
+ m_readWriteActions.append( m_pNewBlobSphereAction );
+ m_pNewBlobCylinderAction = new KAction( i18n( "Blob Cylinder" ), "pmblobcylinder", 0, this, SLOT( slotNewBlobCylinder( ) ),
+ actionCollection( ), "new_blobcylinder" );
+ m_readWriteActions.append( m_pNewBlobCylinderAction );
+
+ m_pNewPlaneAction = new KAction( i18n( "Plane" ), "pmplane", 0, this, SLOT( slotNewPlane( ) ),
+ actionCollection( ), "new_plane" );
+ m_readWriteActions.append( m_pNewPlaneAction );
+ m_pNewPolynomAction = new KAction( i18n( "Polynom" ), "pmpolynom", 0, this, SLOT( slotNewPolynom( ) ),
+ actionCollection( ), "new_polynom" );
+ m_readWriteActions.append( m_pNewPolynomAction );
+
+ m_pNewDeclareAction = new KAction( i18n( "Declaration" ), "pmdeclare", 0, this, SLOT( slotNewDeclare( ) ),
+ actionCollection( ), "new_declare" );
+ m_readWriteActions.append( m_pNewDeclareAction );
+ m_pNewObjectLinkAction = new KAction( i18n( "Object Link" ), "pmobjectlink", 0, this, SLOT( slotNewObjectLink( ) ),
+ actionCollection( ), "new_objectlink" );
+ m_readWriteActions.append( m_pNewObjectLinkAction );
+
+ m_pNewUnionAction = new KAction( i18n( "Union" ), "pmunion", 0, this, SLOT( slotNewUnion( ) ),
+ actionCollection( ), "new_union" );
+ m_readWriteActions.append( m_pNewUnionAction );
+ m_pNewIntersectionAction = new KAction( i18n( "Intersection" ), "pmintersection", 0, this, SLOT( slotNewIntersection( ) ),
+ actionCollection( ), "new_intersection" );
+ m_readWriteActions.append( m_pNewIntersectionAction );
+ m_pNewDifferenceAction = new KAction( i18n( "Difference" ), "pmdifference", 0, this, SLOT( slotNewDifference( ) ),
+ actionCollection( ), "new_difference" );
+ m_readWriteActions.append( m_pNewDifferenceAction );
+ m_pNewMergeAction = new KAction( i18n( "Merge" ), "pmmerge", 0, this, SLOT( slotNewMerge( ) ),
+ actionCollection( ), "new_merge" );
+ m_readWriteActions.append( m_pNewMergeAction );
+
+ m_pNewBoundedByAction = new KAction( i18n( "Bounded By" ), "pmboundedby", 0, this, SLOT( slotNewBoundedBy( ) ),
+ actionCollection( ), "new_boundedby" );
+ m_readWriteActions.append( m_pNewBoundedByAction );
+ m_pNewClippedByAction = new KAction( i18n( "Clipped By" ), "pmclippedby", 0, this, SLOT( slotNewClippedBy( ) ),
+ actionCollection( ), "new_clippedby" );
+ m_readWriteActions.append( m_pNewClippedByAction );
+
+ m_pNewLightAction = new KAction( i18n( "Light" ), "pmlight", 0, this, SLOT( slotNewLight( ) ),
+ actionCollection( ), "new_light" );
+ m_readWriteActions.append( m_pNewLightAction );
+ m_pNewLooksLikeAction = new KAction( i18n( "Looks Like" ), "pmlookslike", 0, this, SLOT( slotNewLooksLike( ) ),
+ actionCollection( ), "new_lookslike" );
+ m_readWriteActions.append( m_pNewLooksLikeAction );
+ m_pNewProjectedThroughAction = new KAction( i18n( "Projected Through" ), "pmprojectedthrough", 0, this, SLOT( slotNewProjectedThrough( ) ),
+ actionCollection( ), "new_projectedthrough" );
+ m_readWriteActions.append( m_pNewProjectedThroughAction );
+
+ m_pNewBicubicPatchAction = new KAction( i18n( "Bicubic Patch" ), "pmbicubicpatch", 0, this, SLOT( slotNewBicubicPatch( ) ),
+ actionCollection( ), "new_bicubicpatch" );
+ m_readWriteActions.append( m_pNewBicubicPatchAction );
+ m_pNewDiscAction = new KAction( i18n( "Disc" ), "pmdisc", 0, this, SLOT( slotNewDisc( ) ),
+ actionCollection( ), "new_disc" );
+ m_readWriteActions.append( m_pNewDiscAction );
+ m_pNewTriangleAction = new KAction( i18n( "Triangle" ), "pmtriangle", 0, this, SLOT( slotNewTriangle( ) ),
+ actionCollection( ), "new_triangle" );
+ m_readWriteActions.append( m_pNewTriangleAction );
+
+
+ m_pNewCameraAction = new KAction( i18n( "Camera" ), "pmcamera", 0, this, SLOT( slotNewCamera( ) ),
+ actionCollection( ), "new_camera" );
+ m_readWriteActions.append( m_pNewCameraAction );
+
+ m_pNewTextureAction = new KAction( i18n( "Texture" ), "pmtexture", 0, this, SLOT( slotNewTexture( ) ),
+ actionCollection( ), "new_texture" );
+ m_readWriteActions.append( m_pNewTextureAction );
+
+ m_pNewPigmentAction = new KAction( i18n( "Pigment" ), "pmpigment", 0, this, SLOT( slotNewPigment( ) ),
+ actionCollection( ), "new_pigment" );
+ m_readWriteActions.append( m_pNewPigmentAction );
+ m_pNewNormalAction = new KAction( i18n( "Normal" ), "pmnormal", 0, this, SLOT( slotNewNormal( ) ),
+ actionCollection( ), "new_normal" );
+ m_readWriteActions.append( m_pNewNormalAction );
+ m_pNewSolidColorAction = new KAction( i18n( "Solid Color" ), "pmsolidcolor", 0, this, SLOT( slotNewSolidColor( ) ),
+ actionCollection( ), "new_solidcolor" );
+ m_readWriteActions.append( m_pNewSolidColorAction );
+
+ m_pNewTextureListAction = new KAction( i18n( "Texture List" ), "pmtexturelist", 0, this, SLOT( slotNewTextureList( ) ),
+ actionCollection( ), "new_texturelist" );
+ m_readWriteActions.append( m_pNewTextureListAction );
+ m_pNewColorListAction = new KAction( i18n( "Color List" ), "pmcolorlist", 0, this, SLOT( slotNewColorList( ) ),
+ actionCollection( ), "new_colorlist" );
+ m_readWriteActions.append( m_pNewColorListAction );
+ m_pNewPigmentListAction = new KAction( i18n( "Pigment List" ), "pmpigmentlist", 0, this, SLOT( slotNewPigmentList( ) ),
+ actionCollection( ), "new_pigmentlist" );
+ m_readWriteActions.append( m_pNewPigmentListAction );
+ m_pNewNormalListAction = new KAction( i18n( "Normal List" ), "pmnormallist", 0, this, SLOT( slotNewNormalList( ) ),
+ actionCollection( ), "new_normallist" );
+ m_readWriteActions.append( m_pNewNormalListAction );
+ m_pNewDensityListAction = new KAction( i18n( "Density List" ), "pmdensitylist", 0, this, SLOT( slotNewDensityList( ) ),
+ actionCollection( ), "new_densitylist" );
+ m_readWriteActions.append( m_pNewDensityListAction );
+
+ m_pNewFinishAction = new KAction( i18n( "Finish" ), "pmfinish", 0, this, SLOT( slotNewFinish( ) ),
+ actionCollection( ), "new_finish" );
+ m_readWriteActions.append( m_pNewFinishAction );
+
+ m_pNewPatternAction = new KAction( i18n( "Pattern" ), "pmpattern", 0, this, SLOT( slotNewPattern( ) ),
+ actionCollection( ), "new_pattern" );
+ m_readWriteActions.append( m_pNewPatternAction );
+ m_pNewBlendMapModifiersAction = new KAction( i18n( "Blend Map Modifiers" ), "pmblendmapmodifiers", 0, this, SLOT( slotNewBlendMapModifiers( ) ),
+ actionCollection( ), "new_blendmapmodifiers" );
+ m_readWriteActions.append( m_pNewBlendMapModifiersAction );
+ m_pNewTextureMapAction = new KAction( i18n( "Texture Map" ), "pmtexturemap", 0, this, SLOT( slotNewTextureMap( ) ),
+ actionCollection( ), "new_texturemap" );
+ m_readWriteActions.append( m_pNewTextureMapAction );
+ m_pNewMaterialMapAction = new KAction( i18n( "Material Map" ), "pmmaterialmap", 0, this, SLOT( slotNewMaterialMap( ) ),
+ actionCollection( ), "new_materialmap" );
+ m_readWriteActions.append( m_pNewMaterialMapAction );
+ m_pNewPigmentMapAction = new KAction( i18n( "Pigment Map" ), "pmpigmentmap", 0, this, SLOT( slotNewPigmentMap( ) ),
+ actionCollection( ), "new_pigmentmap" );
+ m_readWriteActions.append( m_pNewPigmentMapAction );
+ m_pNewColorMapAction = new KAction( i18n( "Color Map" ), "pmcolormap", 0, this, SLOT( slotNewColorMap( ) ),
+ actionCollection( ), "new_colormap" );
+ m_readWriteActions.append( m_pNewColorMapAction );
+ m_pNewNormalMapAction = new KAction( i18n( "Normal Map" ), "pmnormalmap", 0, this, SLOT( slotNewNormalMap( ) ),
+ actionCollection( ), "new_normalmap" );
+ m_readWriteActions.append( m_pNewNormalMapAction );
+ m_pNewBumpMapAction = new KAction( i18n( "Bump Map" ), "pmbumpmap", 0, this, SLOT( slotNewBumpMap( ) ),
+ actionCollection( ), "new_bumpmap" );
+ m_readWriteActions.append( m_pNewBumpMapAction );
+ m_pNewSlopeMapAction = new KAction( i18n( "Slope Map" ), "pmslopemap", 0, this, SLOT( slotNewSlopeMap( ) ),
+ actionCollection( ), "new_slopemap" );
+ m_readWriteActions.append( m_pNewSlopeMapAction );
+ m_pNewDensityMapAction = new KAction( i18n( "Density Map" ), "pmdensitymap", 0, this, SLOT( slotNewDensityMap( ) ),
+ actionCollection( ), "new_densitymap" );
+ m_readWriteActions.append( m_pNewDensityMapAction );
+ m_pNewSlopeAction = new KAction( i18n( "Slope" ), "pmslope", 0, this, SLOT( slotNewSlope( ) ),
+ actionCollection( ), "new_slope" );
+ m_readWriteActions.append( m_pNewSlopeAction );
+
+ m_pNewWarpAction = new KAction( i18n( "Warp" ), "pmwarp", 0, this, SLOT( slotNewWarp( ) ),
+ actionCollection( ), "new_warp" );
+ m_readWriteActions.append( m_pNewWarpAction );
+ m_pNewImageMapAction = new KAction( i18n( "Image Map" ), "pmimagemap", 0, this, SLOT( slotNewImageMap( ) ),
+ actionCollection( ), "new_imagemap" );
+ m_readWriteActions.append( m_pNewImageMapAction );
+ m_pNewQuickColorAction = new KAction( i18n( "QuickColor" ), "pmquickcolor", 0, this, SLOT( slotNewQuickColor( ) ),
+ actionCollection( ), "new_quickcolor" );
+ m_readWriteActions.append( m_pNewQuickColorAction );
+
+ m_pNewTranslateAction = new KAction( i18n( "Translate" ), "pmtranslate", 0, this, SLOT( slotNewTranslate( ) ),
+ actionCollection( ), "new_translate" );
+ m_readWriteActions.append( m_pNewTranslateAction );
+ m_pNewScaleAction = new KAction( i18n( "Scale" ), "pmscale", 0, this, SLOT( slotNewScale( ) ),
+ actionCollection( ), "new_scale" );
+ m_readWriteActions.append( m_pNewScaleAction );
+ m_pNewRotateAction = new KAction( i18n( "Rotate" ), "pmrotate", 0, this, SLOT( slotNewRotate( ) ),
+ actionCollection( ), "new_rotate" );
+ m_readWriteActions.append( m_pNewRotateAction );
+ m_pNewMatrixAction = new KAction( i18n( "Matrix" ), "pmmatrix", 0, this, SLOT( slotNewMatrix( ) ),
+ actionCollection( ), "new_povraymatrix" );
+ m_readWriteActions.append( m_pNewMatrixAction );
+
+ m_pNewCommentAction = new KAction( i18n( "Comment" ), "pmcomment", 0, this, SLOT( slotNewComment( ) ),
+ actionCollection( ), "new_comment" );
+ m_readWriteActions.append( m_pNewCommentAction );
+ m_pNewRawAction = new KAction( i18n( "Raw Povray" ), "pmraw", 0, this, SLOT( slotNewRaw( ) ),
+ actionCollection( ), "new_raw" );
+ m_readWriteActions.append( m_pNewRawAction );
+
+ // POV-Ray 3.5 objects
+ m_pNewIsoSurfaceAction = new KAction( i18n( "Iso Surface" ), "pmisosurface", 0, this, SLOT( slotNewIsoSurface( ) ),
+ actionCollection( ), "new_isosurface" );
+ m_readWriteActions.append( m_pNewIsoSurfaceAction );
+ m_pNewRadiosityAction = new KAction( i18n( "Radiosity" ), "pmradiosity", 0, this, SLOT( slotNewRadiosity( ) ),
+ actionCollection( ), "new_radiosity" );
+ m_readWriteActions.append( m_pNewRadiosityAction );
+ m_pNewGlobalPhotonsAction = new KAction( i18n( "Global Photons" ), "pmglobalphotons", 0, this, SLOT( slotNewGlobalPhotons( ) ),
+ actionCollection( ), "new_globalphotons" );
+ m_readWriteActions.append( m_pNewGlobalPhotonsAction );
+ m_pNewPhotonsAction = new KAction( i18n( "Photons" ), "pmphotons", 0, this, SLOT( slotNewPhotons( ) ),
+ actionCollection( ), "new_photons" );
+ m_readWriteActions.append( m_pNewPhotonsAction );
+ m_pNewLightGroupAction = new KAction( i18n( "Light Group" ), "pmlightgroup", 0, this, SLOT( slotNewLightGroup( ) ),
+ actionCollection( ), "new_lightgroup" );
+ m_readWriteActions.append( m_pNewLightGroupAction );
+ m_pNewInteriorTextureAction = new KAction( i18n( "Interior Texture" ), "pminteriortexture", 0, this, SLOT( slotNewInteriorTexture( ) ),
+ actionCollection( ), "new_interiortexture" );
+ m_readWriteActions.append( m_pNewInteriorTextureAction );
+ m_pNewSphereSweepAction = new KAction( i18n( "Sphere Sweep" ), "pmspheresweep", 0, this, SLOT( slotNewSphereSweep( ) ),
+ actionCollection( ), "new_spheresweep" );
+ m_readWriteActions.append( m_pNewSphereSweepAction );
+ m_pNewMeshAction = new KAction( i18n( "Mesh" ), "pmmesh", 0, this, SLOT( slotNewMesh( ) ),
+ actionCollection( ), "new_mesh" );
+ m_readWriteActions.append( m_pNewMeshAction );
+
+#ifdef KPM_WITH_OBJECT_LIBRARY
+ m_pSearchLibraryObjectAction = new KAction( i18n( "Search Object" ), "pmsearchlibrary", 0, this, SLOT( slotSearchLibraryObject( ) ),
+ actionCollection( ), "search_library_object" );
+ m_readWriteActions.append( m_pSearchLibraryObjectAction );
+#endif
+
+ m_pUndoAction = KStdAction::undo( this, SLOT( slotEditUndo( ) ), actionCollection( ) );
+ m_pRedoAction = KStdAction::redo( this, SLOT( slotEditRedo( ) ), actionCollection( ) );
+ m_pUndoAction->setEnabled( false );
+ m_pRedoAction->setEnabled( false );
+ }
+ else
+ {
+ m_pNewGlobalSettingsAction = 0;
+ m_pNewSkySphereAction = 0;
+ m_pNewRainbowAction = 0;
+ m_pNewFogAction = 0;
+
+ m_pNewInteriorAction = 0;
+ m_pNewMediaAction = 0;
+ m_pNewDensityAction = 0;
+ m_pNewMaterialAction = 0;
+ m_pNewBoxAction = 0;
+ m_pNewSphereAction = 0;
+ m_pNewCylinderAction = 0;
+ m_pNewConeAction = 0;
+ m_pNewTorusAction = 0;
+ m_pNewLatheAction = 0;
+ m_pNewPrismAction = 0;
+ m_pNewSurfaceOfRevolutionAction = 0;
+ m_pNewSuperquadricEllipsoidAction = 0;
+ m_pNewJuliaFractalAction = 0;
+ m_pNewHeightFieldAction = 0;
+ m_pNewTextAction = 0;
+
+ m_pNewBlobAction = 0;
+ m_pNewBlobSphereAction = 0;
+ m_pNewBlobCylinderAction = 0;
+
+ m_pNewPlaneAction = 0;
+ m_pNewPolynomAction = 0;
+
+ m_pNewDeclareAction = 0;
+ m_pNewObjectLinkAction = 0;
+
+ m_pNewDiscAction = 0;
+ m_pNewBicubicPatchAction = 0;
+ m_pNewTriangleAction = 0;
+
+ m_pNewUnionAction = 0;
+ m_pNewDifferenceAction = 0;
+ m_pNewIntersectionAction = 0;
+ m_pNewMergeAction = 0;
+
+ m_pNewBoundedByAction = 0;
+ m_pNewClippedByAction = 0;
+
+ m_pNewLightAction = 0;
+ m_pNewLooksLikeAction = 0;
+ m_pNewProjectedThroughAction = 0;
+
+ m_pNewCameraAction = 0;
+
+ m_pNewTextureAction = 0;
+ m_pNewPigmentAction = 0;
+ m_pNewNormalAction = 0;
+ m_pNewSolidColorAction = 0;
+ m_pNewFinishAction = 0;
+ m_pNewTextureListAction = 0;
+ m_pNewColorListAction = 0;
+ m_pNewPigmentListAction = 0;
+ m_pNewNormalListAction = 0;
+ m_pNewDensityListAction = 0;
+
+ m_pNewPatternAction = 0;
+ m_pNewBlendMapModifiersAction = 0;
+ m_pNewTextureMapAction = 0;
+ m_pNewMaterialMapAction = 0;
+ m_pNewPigmentMapAction = 0;
+ m_pNewColorMapAction = 0;
+ m_pNewNormalMapAction = 0;
+ m_pNewBumpMapAction = 0;
+ m_pNewSlopeMapAction = 0;
+ m_pNewDensityMapAction = 0;
+
+ m_pNewWarpAction = 0;
+ m_pNewImageMapAction = 0;
+ m_pNewSlopeAction = 0;
+
+ m_pNewTranslateAction = 0;
+ m_pNewScaleAction = 0;
+ m_pNewRotateAction = 0;
+ m_pNewMatrixAction = 0;
+ m_pNewCommentAction = 0;
+ m_pNewRawAction = 0;
+
+ m_pNewIsoSurfaceAction = 0;
+ m_pNewRadiosityAction = 0;
+ m_pNewGlobalPhotonsAction = 0;
+ m_pNewPhotonsAction = 0;
+ m_pNewLightGroupAction = 0;
+ m_pNewInteriorTextureAction = 0;
+ m_pNewSphereSweepAction = 0;
+ m_pNewMeshAction = 0;
+
+ // POV-Ray
+
+ m_pUndoAction = 0;
+ m_pRedoAction = 0;
+ }
+}
+
+void PMPart::updateNewObjectActions( )
+{
+ if( isReadWrite( ) && !m_onlyCopyPaste )
+ {
+ QPtrListIterator<PMMetaObject> it =
+ m_pPrototypeManager->prototypeIterator( );
+ KAction* action;
+ bool enable;
+ bool readWriteParent = false;
+
+ if( m_pActiveObject )
+ if( m_pActiveObject->parent( ) )
+ if( !m_pActiveObject->parent( )->isReadOnly( ) )
+ readWriteParent = true;
+
+ for( ; it.current( ); ++it )
+ {
+ // get the action object for that type of PMObject
+ // action names are "new_" + povray name
+ // (like new_box, new_sphere ...)
+
+ QString actionName = "new_" + it.current( )->className( ).lower( );
+ action = actionCollection( )->action( actionName.latin1( ) );
+ if( action )
+ {
+ if( m_pActiveObject )
+ {
+ QString insertName = it.current( )->className( );
+ enable = m_pActiveObject->canInsert( insertName, 0 );
+ if( !enable )
+ if( m_pActiveObject->lastChild( ) )
+ enable = m_pActiveObject->canInsert( insertName, m_pActiveObject->lastChild( ) );
+ if( !enable )
+ if( readWriteParent )
+ enable |= m_pActiveObject->parent( )->canInsert( insertName, m_pActiveObject );
+ }
+ else
+ enable = false;
+ action->setEnabled( enable );
+ }
+ }
+ // special treatment for csg actions
+ if( m_pActiveObject )
+ {
+ enable = m_pActiveObject->canInsert( QString( "CSG" ), 0 );
+ if( !enable )
+ if( m_pActiveObject->lastChild( ) )
+ enable = m_pActiveObject->canInsert( QString( "CSG" ), m_pActiveObject->lastChild( ) );
+ if( !enable )
+ if( readWriteParent )
+ enable = m_pActiveObject->parent( )->canInsert( QString( "CSG" ), m_pActiveObject );
+ }
+ else
+ enable = false;
+ m_pNewUnionAction->setEnabled( enable );
+ m_pNewIntersectionAction->setEnabled( enable );
+ m_pNewDifferenceAction->setEnabled( enable );
+ m_pNewMergeAction->setEnabled( enable );
+ }
+ m_updateNewObjectActions = false;
+}
+
+void PMPart::disableReadWriteActions( )
+{
+ QPtrListIterator<KAction> it( m_readWriteActions);
+ for( ; it.current( ); ++it )
+ it.current( )->setEnabled( false );
+}
+
+void PMPart::initDocument( )
+{
+ newDocument( );
+}
+
+void PMPart::initView( QWidget* parent, const char* name )
+{
+ if( !m_pShell )
+ {
+ // a part inside konqueror
+ // simple layout
+ m_pView = new PMView( this, parent, name );
+ m_pView->show( );
+ setWidget( m_pView );
+ }
+ else
+ {
+ // inside a PMShell
+ // the shell will create the view
+ }
+}
+
+void PMPart::saveConfig( KConfig* cfg )
+{
+ if( m_pView )
+ m_pView->saveConfig( cfg );
+ PMErrorDialog::saveConfig( cfg );
+ PMRenderModesDialog::saveConfig( cfg );
+ PMRenderModeDialog::saveConfig( cfg );
+ PMPovrayOutputWidget::saveConfig( cfg );
+ PMRenderManager::theManager( )->saveConfig( cfg );
+ PMGLView::saveConfig( cfg );
+ PMDialogEditBase::saveConfig( cfg );
+ PMControlPoint::saveConfig( cfg );
+ PMPovrayRenderWidget::saveConfig( cfg );
+ PMSettingsDialog::saveConfig( cfg );
+ PMLibraryHandleEdit::saveConfig( cfg );
+ PMDocumentationMap::theMap( )->saveConfig( cfg );
+ PMLibraryManager::theManager( )->saveConfig(cfg );
+
+ cfg->setGroup( "Rendering" );
+ cfg->writeEntry( "SphereUSteps", PMSphere::uSteps( ) );
+ cfg->writeEntry( "SphereVSteps", PMSphere::vSteps( ) );
+ cfg->writeEntry( "CylinderSteps", PMCylinder::steps( ) );
+ cfg->writeEntry( "ConeSteps", PMCone::steps( ) );
+ cfg->writeEntry( "DiscSteps", PMDisc::steps( ) );
+ cfg->writeEntry( "BlobSphereUSteps", PMBlobSphere::uSteps( ) );
+ cfg->writeEntry( "BlobSphereVSteps", PMBlobSphere::vSteps( ) );
+ cfg->writeEntry( "BlobCylinderUSteps", PMBlobCylinder::uSteps( ) );
+ cfg->writeEntry( "BlobCylinderVSteps", PMBlobCylinder::vSteps( ) );
+ cfg->writeEntry( "TorusUSteps", PMTorus::uSteps( ) );
+ cfg->writeEntry( "TorusVSteps", PMTorus::vSteps( ) );
+ cfg->writeEntry( "LatheSSteps", PMLathe::sSteps( ) );
+ cfg->writeEntry( "LatheRSteps", PMLathe::rSteps( ) );
+ cfg->writeEntry( "SorSSteps", PMSurfaceOfRevolution::sSteps( ) );
+ cfg->writeEntry( "SorRSteps", PMSurfaceOfRevolution::rSteps( ) );
+ cfg->writeEntry( "PrismSSteps", PMPrism::sSteps( ) );
+ cfg->writeEntry( "PlaneSize", PMPlane::planeSize( ) );
+ cfg->writeEntry( "SqeUSteps", PMSuperquadricEllipsoid::uSteps( ) );
+ cfg->writeEntry( "SqeVSteps", PMSuperquadricEllipsoid::vSteps( ) );
+ cfg->writeEntry( "SphereSweepRSteps", PMSphereSweep::rSteps( ) );
+ cfg->writeEntry( "SphereSweepSSteps", PMSphereSweep::sSteps( ) );
+ cfg->writeEntry( "HeightFieldVariance", PMHeightField::variance( ) );
+ cfg->writeEntry( "GlobalDetailLevel", PMDetailObject::globalDetailLevel( ) );
+
+ cfg->writeEntry( "DirectRendering", PMGLView::isDirectRenderingEnabled( ) );
+}
+
+void PMPart::restoreConfig( KConfig* cfg )
+{
+ if( m_pView )
+ m_pView->restoreConfig( cfg );
+ PMErrorDialog::restoreConfig( cfg );
+ PMRenderModesDialog::restoreConfig( cfg );
+ PMRenderModeDialog::restoreConfig( cfg );
+ PMPovrayOutputWidget::restoreConfig( cfg );
+ PMRenderManager::theManager( )->restoreConfig( cfg );
+ PMGLView::restoreConfig( cfg );
+ PMDialogEditBase::restoreConfig( cfg );
+ PMControlPoint::restoreConfig( cfg );
+ PMPovrayRenderWidget::restoreConfig( cfg );
+ PMSettingsDialog::restoreConfig( cfg );
+ PMLibraryHandleEdit::restoreConfig( cfg );
+ PMDocumentationMap::theMap( )->restoreConfig( cfg );
+ PMLibraryManager::theManager( )->restoreConfig(cfg );
+
+ cfg->setGroup( "Rendering" );
+ PMSphere::setUSteps( cfg->readNumEntry( "SphereUSteps", c_defaultSphereUSteps ) );
+ PMSphere::setVSteps( cfg->readNumEntry( "SphereVSteps", c_defaultSphereVSteps ) );
+ PMCylinder::setSteps( cfg->readNumEntry( "CylinderSteps", c_defaultCylinderSteps ) );
+ PMCone::setSteps( cfg->readNumEntry( "ConeSteps", c_defaultConeSteps ) );
+ PMTorus::setUSteps( cfg->readNumEntry( "TorusUSteps", c_defaultTorusUSteps ) );
+ PMTorus::setVSteps( cfg->readNumEntry( "TorusVSteps", c_defaultTorusVSteps ) );
+ PMLathe::setSSteps( cfg->readNumEntry( "LatheSSteps", c_defaultLatheSSteps ) );
+ PMLathe::setRSteps( cfg->readNumEntry( "LatheRSteps", c_defaultLatheRSteps ) );
+ PMSurfaceOfRevolution::setSSteps( cfg->readNumEntry( "SorSSteps", c_defaultSurfaceOfRevolutionSSteps ) );
+ PMSurfaceOfRevolution::setRSteps( cfg->readNumEntry( "SorRSteps", c_defaultSurfaceOfRevolutionRSteps ) );
+ PMPrism::setSSteps( cfg->readNumEntry( "PrismSSteps", c_defaultPrismSSteps ) );
+ PMPlane::setPlaneSize( cfg->readDoubleNumEntry( "PlaneSize", c_defaultPlaneSize ) );
+ PMDisc::setSteps( cfg->readNumEntry( "DiscSteps", c_defaultDiscSteps ) );
+ PMBlobSphere::setUSteps( cfg->readNumEntry( "BlobSphereUSteps", c_defaultBlobSphereUSteps ) );
+ PMBlobSphere::setVSteps( cfg->readNumEntry( "BlobSphereVSteps", c_defaultBlobSphereVSteps ) );
+ PMBlobCylinder::setUSteps( cfg->readNumEntry( "BlobCylinderUSteps", c_defaultBlobCylinderUSteps ) );
+ PMBlobCylinder::setVSteps( cfg->readNumEntry( "BlobCylinderVSteps", c_defaultBlobCylinderVSteps ) );
+ PMSuperquadricEllipsoid::setUSteps( cfg->readNumEntry( "SqeUSteps", c_defaultSuperquadricEllipsoidUSteps ) );
+ PMSuperquadricEllipsoid::setVSteps( cfg->readNumEntry( "SqeVSteps", c_defaultSuperquadricEllipsoidVSteps ) );
+ PMSphereSweep::setRSteps( cfg->readNumEntry( "SphereSweepRSteps", c_defaultSphereSweepRSteps ) );
+ PMSphereSweep::setSSteps( cfg->readNumEntry( "SphereSweepSSteps", c_defaultSphereSweepSSteps ) );
+ PMHeightField::setVariance( cfg->readNumEntry( "HeightFieldVariance", c_defaultHeightFieldVariance ) );
+ PMDetailObject::setGlobalDetailLevel( cfg->readNumEntry( "GlobalDetailLevel", c_defaultDetailObjectGlobalDetailLevel ) );
+ m_pGlobalDetailAction->setCurrentItem( PMDetailObject::globalDetailLevel( ) - 1 );
+
+ if( PMGLView::isDirectRenderingEnabled( ) ) // otherwise it was disabled with a command line switch
+ PMGLView::enableDirectRendering( cfg->readBoolEntry( "DirectRendering", true ) );
+}
+
+bool PMPart::openFile( )
+{
+ QIODevice* dev = KFilterDev::deviceForFile( m_file, "application/x-gzip" );
+ bool success = true;
+ PMObjectList list;
+
+ deleteContents( );
+
+ setModified( false );
+
+ if( dev && dev->open( IO_ReadOnly ) )
+ {
+ PMXMLParser parser( this, dev );
+
+ parser.parse( &list, 0, 0 );
+
+ if( parser.errors( ) || parser.warnings( ) )
+ {
+ PMErrorDialog dlg( parser.messages( ), parser.errorFlags( ) );
+ // still try to insert the correct parsed objects?
+ success = ( dlg.exec( ) == QDialog::Accepted );
+ }
+ if( success )
+ {
+ PMObject* obj = list.first( );
+ if( obj )
+ {
+ if( obj->type( ) == "Scene" )
+ m_pScene = ( PMScene* ) obj;
+ else
+ success = false;
+ }
+ else
+ success = false;
+ }
+ }
+ else
+ success = false;
+
+ if( !success )
+ {
+ m_url = KURL( );
+ newDocument( );
+ }
+
+ m_pScene->setReadOnly( !isReadWrite( ) );
+ if( !isReadWrite( ) )
+ disableReadWriteActions( );
+ m_bCameraListUpToDate = false;
+
+ emit refresh( );
+ updateRenderModes( );
+ updateVisibilityLevel( );
+ slotObjectChanged( m_pScene, PMCNewSelection, this );
+
+ if( dev )
+ delete dev;
+
+ return success;
+}
+
+bool PMPart::saveFile( )
+{
+ bool success = false;
+
+ QIODevice* dev = KFilterDev::deviceForFile( m_file, "application/x-gzip" );
+ if( dev && dev->open( IO_WriteOnly ) )
+ {
+ QDomDocument doc( "KPOVMODELER" );
+ QDomElement e = ( ( PMObject* )m_pScene)->serialize( doc );
+ doc.appendChild( e );
+
+ QTextStream str( dev );
+ str << doc;
+ dev->close( );
+ setModified( false );
+ success = true;
+ }
+
+ if( dev )
+ delete dev;
+
+ return success;
+}
+
+bool PMPart::exportPovray( const KURL& url )
+{
+ KTempFile* tempFile = 0;
+ QFile* file = 0;
+ bool ok = true;
+
+ if( !url.isValid( ) )
+ return false;
+
+ if( url.isLocalFile( ) )
+ {
+ // Local file
+ file = new QFile( url.path( ) );
+ if( !file->open( IO_WriteOnly ) )
+ ok = false;
+ }
+ else
+ {
+ // Remote file
+ // provide a temp file
+ tempFile = new KTempFile( );
+ if( tempFile->status( ) != 0 )
+ ok = false;
+ else
+ file = tempFile->file( );
+ }
+
+ if( ok )
+ {
+ PMPovray35Format format;
+ PMSerializer* dev = format.newSerializer( file );
+ dev->serialize( m_pScene );
+ delete dev;
+
+ if( tempFile )
+ {
+ tempFile->close( );
+ ok = KIO::NetAccess::upload( tempFile->name( ), url, (QWidget*) 0 );
+ tempFile->unlink( );
+ file = 0;
+ }
+ else
+ file->close( );
+ }
+
+ delete file;
+ delete tempFile;
+
+ return ok;
+}
+
+QString PMPart::activeObjectName( )
+{
+ QString result = "";
+ PMObject* tmpObj;
+ PMObject* testSib;
+ int idx = 0;
+
+ tmpObj = activeObject( );
+ while( tmpObj != m_pScene && tmpObj )
+ {
+ // count previous siblings of the same type (for array like entries)
+ testSib = tmpObj;
+ while( ( testSib = testSib->prevSibling( ) ) )
+ if( testSib->type( ) == tmpObj->type( ) )
+ idx++;
+
+ // prepend to result
+ if( idx != 0 )
+ result = tmpObj->type( ) + "[" + QString::number( idx ) + "]/" + result;
+ else
+ result = tmpObj->type( ) + "/" + result;
+
+ // go up in the scene
+ tmpObj = tmpObj->parent( );
+ idx = 0;
+ }
+
+ // Make the object name an absolute name
+ result = "/" + result;
+
+ return result;
+}
+
+bool PMPart::setActiveObject( const QString& name )
+{
+ PMObject* tmpObj;
+ PMObject* tmpSibling;
+ int pos, siblingIndex, objIndex, firstBracket, lastBracket;
+ QString objPath;
+ QString pathElem;
+
+ // check if it's a absolute object name
+ if( name[0] == '/' )
+ {
+ tmpObj = m_pScene;
+ objPath = name.mid( 1 ); // clear that first character
+ }
+ else
+ tmpObj = activeObject( );
+
+ // get the first element
+ pos = objPath.find( '/' );
+ if( pos != -1 )
+ {
+ pathElem = objPath.mid( 0, pos );
+ objPath = objPath.mid( pos + 1 );
+ }
+ else
+ {
+ pathElem = objPath;
+ objPath = QString::null;
+ }
+
+ while( !pathElem.isNull( ) )
+ {
+ if( !pathElem.isEmpty( ) )
+ {
+ // Special treatment for brackets
+ firstBracket = pathElem.find( '[' );
+ if( firstBracket != -1 )
+ {
+ lastBracket = pathElem.findRev( ']' );
+ objIndex = pathElem.mid( firstBracket + 1, lastBracket - firstBracket - 1).toInt( );
+ pathElem = pathElem.left( firstBracket );
+ }
+ else
+ objIndex = 0;
+
+ // Iterate the children for this element. We stop when there are no more siblings
+ // or the object is of the correct type and it's index count is also correct
+ siblingIndex = 0;
+ tmpSibling = tmpObj->firstChild( );
+ for( ; tmpSibling && ( tmpSibling->type( ) != pathElem || siblingIndex != objIndex );
+ tmpSibling = tmpSibling->nextSibling( ) )
+ {
+ // Found an object of the type we are looking for
+ if( tmpSibling->type( ) == pathElem )
+ siblingIndex++;
+ }
+ if( tmpSibling )
+ tmpObj = tmpSibling;
+ else
+ // No correct sibling
+ return false;
+
+ }
+
+ // Get the next element
+ pos = objPath.find( '/' );
+ if( pos != -1 )
+ {
+ pathElem = objPath.mid( 0, pos );
+ objPath = objPath.mid( pos + 1 );
+ }
+ else
+ {
+ pathElem = objPath;
+ objPath = QString::null;
+ }
+ }
+ if( tmpObj )
+ {
+ slotObjectChanged( tmpObj, PMCNewSelection, this );
+ return true;
+ }
+ else
+ return false;
+}
+
+QStringList PMPart::getProperties( )
+{
+ PMObject* curObj = activeObject( );
+
+ // Ensure that there is an active object
+ if( !curObj )
+ return QStringList( );
+
+ return curObj->properties( );
+}
+
+bool PMPart::setProperty( const QString& name, const PMVariant& value )
+{
+ PMObject* curObj = activeObject( );
+
+ // Ensure that there is an active object
+ if( !curObj )
+ return false;
+
+ curObj->setProperty( name, value );
+ slotObjectChanged( curObj, PMCNewSelection, this );
+ return true;
+}
+
+bool PMPart::setProperty( const QString& name, const QString& value )
+{
+ PMObject* curObj = activeObject( );
+ PMVariant variant;
+
+ // Ensure that there is an active object
+ if( !curObj )
+ return false;
+
+ variant.fromString( curObj->property( name ).dataType( ), value );
+ curObj->setProperty( name, variant );
+ slotObjectChanged( curObj, PMCNewSelection, this );
+ return true;
+}
+
+const PMVariant PMPart::getProperty( const QString& name )
+{
+ PMObject* curObj = activeObject( );
+
+ // Ensure that there is an active object
+ if( !curObj )
+ return PMVariant( );
+
+ return curObj->property( name );
+}
+
+const QString PMPart::getPropertyStr( const QString& name )
+{
+ PMObject* curObj = activeObject( );
+
+ // Ensure that there is an active object
+ if( !curObj )
+ return PMVariant( ).asString( );
+
+ return curObj->property( name ).asString( );
+}
+
+const PMObjectList& PMPart::selectedObjects( )
+{
+ uint numObjects = m_selectedObjects.count( );
+ uint numOrdered = 0;
+ bool stop = false;
+
+ PMObject* tmp;
+ QPtrStack<PMObject> stack;
+
+ if( !m_sortedListUpToDate )
+ {
+ m_sortedSelectedObjects.clear( );
+
+ if( numObjects == 1 )
+ m_sortedSelectedObjects.append( m_selectedObjects.first( ) );
+ else if( numObjects > 1 )
+ {
+ tmp = m_pScene;
+ do
+ {
+ if( !tmp )
+ {
+ if( !stack.isEmpty( ) )
+ {
+ tmp = stack.pop( );
+ if( tmp == m_pScene )
+ stop = true;
+ else
+ tmp = tmp->nextSibling( );
+ }
+ else
+ stop = true;
+ }
+ else if( tmp->isSelected( ) )
+ {
+ m_sortedSelectedObjects.append( tmp );
+ numOrdered++;
+ tmp = tmp->nextSibling( );
+ }
+ else if( tmp->selectedChildren( ) > 0 )
+ {
+ stack.push( tmp );
+ tmp = tmp->firstChild( );
+ }
+ else
+ {
+ tmp = tmp->nextSibling( );
+ }
+ }
+ while( !stop && ( numOrdered < numObjects ) );
+ }
+ m_sortedListUpToDate = true;
+ }
+
+ return m_sortedSelectedObjects;
+}
+
+int PMPart::whereToInsert( PMObject* obj, const PMObjectList& list )
+{
+ // if you change this function, change
+ // whereToInsert( PMObject* obj, const QStringList& ), too
+
+ int canInsertAsFirstChild = 0;
+ int canInsertAsLastChild = 0;
+ int canInsertAsSibling = 0;
+
+ int insertAs = 0;
+ int insertPossibilities = 0;
+
+ if( !obj->isReadOnly( ) )
+ {
+ canInsertAsFirstChild = obj->canInsert( list, 0 );
+ if( obj->lastChild( ) )
+ canInsertAsLastChild = obj->canInsert( list, obj->lastChild( ) );
+
+ if( canInsertAsFirstChild > 0 )
+ {
+ // some objects can be inserted as child
+ insertAs |= PMInsertPopup::PMIFirstChild;
+ insertPossibilities++;
+ }
+ if( canInsertAsLastChild > 0 )
+ {
+ insertAs |= PMInsertPopup::PMILastChild;
+ insertPossibilities++;
+ }
+ }
+
+ if( obj->parent( ) )
+ {
+ PMObject* p = obj->parent( );
+ if( !p->isReadOnly( ) )
+ {
+ canInsertAsSibling = p->canInsert( list, obj );
+ if( canInsertAsSibling > 0 )
+ {
+ // some objects can be inserted as siblings
+ insertAs |= PMInsertPopup::PMISibling;
+ insertPossibilities++;
+ }
+ }
+ }
+
+ if( insertPossibilities > 1 )
+ {
+ int count = ( int ) list.count( );
+ // more than one possibilities, ask user
+ insertAs = PMInsertPopup::choosePlace(
+ widget( ), count > 1, insertAs,
+ canInsertAsFirstChild == count,
+ canInsertAsLastChild == count,
+ canInsertAsSibling == count );
+ }
+ else if( insertPossibilities == 0 )
+ insertAs = PMInsertPopup::PMIFirstChild;
+ return insertAs;
+}
+
+int PMPart::whereToInsert( PMObject* obj, const QStringList& list )
+{
+ // if you change this function, change
+ // whereToInsert( PMObject* obj, const PMObjectList ), too
+
+ int canInsertAsFirstChild = 0;
+ int canInsertAsLastChild = 0;
+ int canInsertAsSibling = 0;
+
+ int insertAs = 0;
+ int insertPossibilities = 0;
+
+ if( !obj->isReadOnly( ) )
+ {
+ canInsertAsFirstChild = obj->canInsert( list, 0 );
+ if( obj->lastChild( ) )
+ canInsertAsLastChild = obj->canInsert( list, obj->lastChild( ) );
+
+ if( canInsertAsFirstChild > 0 )
+ {
+ // some objects can be inserted as child
+ insertAs |= PMInsertPopup::PMIFirstChild;
+ insertPossibilities++;
+ }
+ if( canInsertAsLastChild > 0 )
+ {
+ insertAs |= PMInsertPopup::PMILastChild;
+ insertPossibilities++;
+ }
+ }
+
+ if( obj->parent( ) )
+ {
+ PMObject* p = obj->parent( );
+ if( !p->isReadOnly( ) )
+ {
+ canInsertAsSibling = p->canInsert( list, obj );
+ if( canInsertAsSibling > 0 )
+ {
+ // some objects can be inserted as siblings
+ insertAs |= PMInsertPopup::PMISibling;
+ insertPossibilities++;
+ }
+ }
+ }
+
+ if( insertPossibilities > 1 )
+ {
+ int count = ( int ) list.count( );
+ // more than one possibilities, ask user
+ insertAs = PMInsertPopup::choosePlace(
+ widget( ), count > 1, insertAs,
+ canInsertAsFirstChild == count,
+ canInsertAsLastChild == count,
+ canInsertAsSibling == count );
+ }
+ else if( insertPossibilities == 0 )
+ insertAs = PMInsertPopup::PMIFirstChild;
+ return insertAs;
+}
+
+int PMPart::whereToInsert( PMObject* obj )
+{
+ int insertAs = 0;
+ int insertPossibilities = 0;
+
+ if( obj->parent( ) )
+ {
+ insertAs |= PMInsertPopup::PMISibling;
+ insertPossibilities++;
+ }
+ if( obj->isA( "CompositeObject" ) )
+ {
+ insertAs |= PMInsertPopup::PMIFirstChild;
+ insertPossibilities++;
+ if( obj->firstChild( ) )
+ {
+ insertAs |= PMInsertPopup::PMILastChild;
+ insertPossibilities++;
+ }
+ }
+ if( insertAs && ( insertPossibilities > 1 ) )
+ insertAs = PMInsertPopup::choosePlace( widget( ), true, insertAs );
+
+ return insertAs;
+}
+
+void PMPart::slotFileImport( )
+{
+ QString fileName;
+ PMIOFormat* selectedFormat = 0;
+
+ fileName = PMFileDialog::getImportFileName( 0, this, selectedFormat );
+
+ if( !fileName.isEmpty( ) && selectedFormat )
+ {
+ QFile file( fileName );
+ if( file.open( IO_ReadOnly ) )
+ {
+ PMParser* newParser = selectedFormat->newParser( this, &file );
+ if( newParser )
+ {
+ if( m_pActiveObject )
+ insertFromParser( i18n( "Import %1" ).arg( selectedFormat->description( ) ),
+ newParser, m_pActiveObject );
+ else
+ insertFromParser( i18n( "Import %1" ).arg( selectedFormat->description( ) ),
+ newParser, m_pScene );
+ delete newParser;
+ }
+ }
+ else
+ {
+ KMessageBox::error( 0, tr( "Couldn't open the selected file\n"
+ "Permission denied!" ) );
+ }
+ }
+}
+
+void PMPart::slotFileExport( )
+{
+ emit aboutToSave( );
+
+ QString fileName, filter;
+ PMIOFormat* selectedFormat = 0;
+
+ fileName = PMFileDialog::getExportFileName( 0, this, selectedFormat, filter );
+
+ if( !fileName.isEmpty( ) && selectedFormat )
+ {
+ QByteArray baData;
+ QBuffer buffer( baData );
+ buffer.open( IO_WriteOnly );
+
+ PMSerializer* newSer = selectedFormat->newSerializer( &buffer );
+ if( newSer )
+ {
+ newSer->serialize( m_pScene );
+ newSer->close( );
+ bool success = !( newSer->warnings( ) || newSer->errors( ) );
+
+ if( !success )
+ {
+ // there were errors, display them
+ PMErrorDialog dlg( newSer->messages( ), newSer->errorFlags( ) );
+ // still try to export?
+ success = ( dlg.exec( ) == QDialog::Accepted );
+ }
+ if( success )
+ {
+ QFileInfo info( fileName );
+ if( info.extension( ).isEmpty( ) )
+ fileName += filter.right( filter.length( ) - 1 ); // remove '*'
+
+ QFile file( fileName );
+ if( file.open( IO_WriteOnly ) )
+ {
+ file.writeBlock( baData );
+ file.close( );
+ }
+ else
+ {
+ KMessageBox::error( 0, tr( "Couldn't export to the selected file\n"
+ "Permission denied!" ) );
+ }
+ }
+
+ delete newSer;
+ }
+ }
+}
+
+void PMPart::slotEditCut( )
+{
+ emit setStatusBarText( i18n( "Cutting selection..." ) );
+
+ const PMObjectList& sortedList = selectedObjects( );
+
+ if( sortedList.count( ) > 0 )
+ {
+ QApplication::clipboard( )->setData( new PMObjectDrag( this, sortedList ) );
+ removeSelection( i18n( "Cut" ) );
+ }
+
+ emit setStatusBarText( "" );
+}
+
+void PMPart::slotEditDelete( )
+{
+ emit setStatusBarText( i18n( "Deleting selection..." ) );
+
+ removeSelection( i18n( "Delete" ) );
+
+ emit setStatusBarText( "" );
+}
+
+void PMPart::slotEditCopy( )
+{
+ emit setStatusBarText( i18n( "Copying selection to clipboard..." ) );
+ const PMObjectList& sortedList = selectedObjects( );
+
+ if( sortedList.count( ) > 0 )
+ QApplication::clipboard( )->setData( new PMObjectDrag( this, sortedList ) );
+
+ emit setStatusBarText( "" );
+}
+
+bool PMPart::dragMoveSelectionTo( PMObject* obj )
+{
+ if( obj == 0 )
+ {
+ return removeSelection( i18n( "Drag" ) );
+ }
+ else
+ {
+ const PMObjectList& sortedList = selectedObjects( );
+ PMMoveCommand* command = 0;
+ int insertAs = whereToInsert( obj, sortedList );
+
+ if( insertAs > 0 )
+ {
+ PMObject* hlp;
+ bool stop;
+
+ switch( insertAs )
+ {
+ case PMInsertPopup::PMIFirstChild:
+ command = new PMMoveCommand( sortedList, obj, 0 );
+ break;
+ case PMInsertPopup::PMILastChild:
+ hlp = obj->lastChild( );
+ stop = false;
+
+ while( hlp && !stop )
+ {
+ if( hlp->isSelected( ) )
+ hlp = hlp->prevSibling( );
+ else
+ stop = true;
+ }
+ command = new PMMoveCommand( sortedList, obj, hlp );
+ break;
+ case PMInsertPopup::PMISibling:
+ command = new PMMoveCommand( sortedList, obj->parent( ), obj );
+ break;
+ }
+ }
+ if( command )
+ {
+ command->setText( i18n( "Drag" ) );
+ return executeCommand( command );
+ }
+ }
+ return false;
+}
+
+bool PMPart::removeSelection( const QString& type )
+{
+ PMDeleteCommand* cmd = 0;
+ const PMObjectList& sortedList = selectedObjects( );
+
+ if( sortedList.count( ) > 0 )
+ {
+ cmd = new PMDeleteCommand( sortedList );
+ cmd->setText( type );
+ return executeCommand( cmd );
+ }
+ return false;
+}
+
+bool PMPart::drop( PMObject* obj, QMimeSource* mime )
+{
+ return pasteOrDrop( i18n( "Drop" ), mime, obj );
+}
+
+void PMPart::slotEditPaste( )
+{
+ emit setStatusBarText( i18n( "Inserting clipboard contents..." ) );
+
+ pasteOrDrop( i18n( "Paste" ), qApp->clipboard( )->data( ),
+ m_pActiveObject );
+
+ emit setStatusBarText( "" );
+}
+
+bool PMPart::pasteOrDrop( const QString& type, QMimeSource* mime, PMObject* obj )
+{
+ bool success = false;
+
+ if( mime && obj)
+ {
+ PMParser* parser = PMObjectDrag::newParser( mime, this );
+
+ if( parser )
+ success = insertFromParser( type, parser, obj );
+ }
+ return success;
+}
+
+bool PMPart::insertFromParser( const QString& type, PMParser* parser,
+ PMObject* obj )
+{
+ PMObjectList list;
+ bool success = true;
+ int insertAs = 0;
+ PMAddCommand* command = 0;
+
+ // try to parse
+ if( parser->canQuickParse( ) )
+ {
+ QStringList types;
+ parser->quickParse( types );
+
+ success = !( parser->warnings( ) || parser->errors( ) );
+
+ if( !success )
+ {
+ // there were errors, display them
+ PMErrorDialog dlg( parser->messages( ), parser->errorFlags( ) );
+ // still try to insert the correct parsed objects?
+ success = ( dlg.exec( ) == QDialog::Accepted );
+ }
+ if( success && ( types.count( ) > 0 ) )
+ insertAs = whereToInsert( obj, types );
+ }
+ else
+ insertAs = whereToInsert( obj );
+
+ if( success && insertAs )
+ {
+ PMObject* parent = 0;
+ PMObject* after = 0;
+
+ switch( insertAs )
+ {
+ case PMInsertPopup::PMIFirstChild:
+ parent = obj;
+ after = 0;
+ break;
+ case PMInsertPopup::PMILastChild:
+ parent = obj;
+ after = obj->lastChild( );
+ break;
+ case PMInsertPopup::PMISibling:
+ parent = obj->parent( );
+ after = obj;
+ break;
+ default:
+ parent = obj;
+ after = 0;
+ break;
+ }
+
+ parser->parse( &list, parent, after );
+ success = !( parser->warnings( ) || parser->errors( ) );
+
+ if( !success )
+ {
+ // there were errors, display them
+ PMErrorDialog dlg( parser->messages( ), parser->errorFlags( ) );
+ // still try to insert the correct parsed objects?
+ success = ( dlg.exec( ) == QDialog::Accepted );
+ }
+
+ if( list.count( ) > 0 )
+ {
+ if( success )
+ {
+ // parsing was successful
+ command = new PMAddCommand( list, parent, after );
+
+ command->setText( type );
+ success = executeCommand( command );
+ }
+ else
+ {
+ // parsed objects will not be inserted
+ // remove all links
+ PMObjectListIterator it( list );
+ PMDeclare* decl = 0;
+
+ for( ; it.current( ); ++it )
+ {
+ PMRecursiveObjectIterator rit( it.current( ) );
+ for( ; rit.current( ); ++rit )
+ {
+ decl = rit.current( )->linkedObject( );
+ if( decl )
+ decl->removeLinkedObject( rit.current( ) );
+ }
+ }
+ }
+ }
+ }
+ if( !command )
+ {
+ // delete all parsed objects
+ list.setAutoDelete( true );
+ list.clear( );
+ }
+
+ return success && insertAs;
+}
+
+void PMPart::slotEditUndo( )
+{
+ emit setStatusBarText( i18n( "Undo last change..." ) );
+ m_pNewSelection = 0;
+ m_updateNewObjectActions = false;
+
+ m_commandManager.undo( );
+
+ if( m_pNewSelection )
+ slotObjectChanged( m_pNewSelection, PMCNewSelection, this );
+ if( !isModified( ) )
+ setModified( true );
+ if( m_updateNewObjectActions )
+ updateNewObjectActions( );
+
+ emit setStatusBarText( "" );
+}
+
+void PMPart::slotEditRedo( )
+{
+ emit setStatusBarText( i18n( "Redo last change..." ) );
+ m_pNewSelection = 0;
+ m_updateNewObjectActions = false;
+
+ m_commandManager.redo( );
+ if( m_pNewSelection )
+ slotObjectChanged( m_pNewSelection, PMCNewSelection, this );
+ if( !isModified( ) )
+ setModified( true );
+ if( m_updateNewObjectActions )
+ updateNewObjectActions( );
+
+ emit setStatusBarText( "" );
+}
+
+bool PMPart::executeCommand( PMCommand* cmd )
+{
+ m_pNewSelection = 0;
+ m_numAddedObjects = 0;
+ m_numInsertErrors = 0;
+ m_insertErrorDetails.clear( );
+ m_updateNewObjectActions = false;
+
+ if( isReadWrite( ) && cmd )
+ {
+ bool execute = true;
+ int flags = cmd->errorFlags( this );
+
+ if( flags )
+ {
+ PMErrorDialog dlg( cmd->messages( ), flags );
+ execute = ( dlg.exec( ) == QDialog::Accepted );
+ }
+
+ if( execute )
+ {
+ m_commandManager.execute( cmd );
+ if( m_pNewSelection )
+ slotObjectChanged( m_pNewSelection, PMCNewSelection, this );
+ if( !isModified( ) )
+ setModified( true );
+
+ if( m_numInsertErrors > 0 )
+ {
+ m_insertErrorDetails.sort( );
+ PMInsertErrorDialog dlg( m_numAddedObjects, m_numInsertErrors,
+ m_insertErrorDetails );
+ dlg.exec( );
+ }
+ if( m_updateNewObjectActions )
+ updateNewObjectActions( );
+
+ return true;
+ }
+ }
+
+ delete cmd;
+ return false;
+}
+
+void PMPart::slotObjectChanged( PMObject* obj, const int m,
+ QObject* sender )
+{
+ int mode = m;
+ bool selectionChanged = false;
+ bool changeControlPoints = false;
+ PMObject* oldActive = m_pActiveObject;
+
+ if( mode & PMCNewSelection )
+ {
+ if( !obj )
+ {
+ clearSelection( );
+ selectionChanged = true;
+ m_pActiveObject = 0;
+ }
+ else
+ {
+ clearSelection( );
+ obj->setSelected( true );
+ m_selectedObjects.append( obj );
+ selectionChanged = true;
+ m_pActiveObject = obj;
+ }
+ }
+ else if( ( mode & PMCSelected ) && !obj->isSelected( ) )
+ {
+ if( obj->isSelectable( ) )
+ {
+ if( obj->selectedChildren( ) > 0 )
+ {
+ QPtrStack<PMObject> stack;
+ PMObject* tmp = obj->firstChild( );
+ bool stop = false;
+
+ do
+ {
+ if( !tmp )
+ {
+ if( !stack.isEmpty( ) )
+ {
+ tmp = stack.pop( );
+ if( tmp == obj )
+ stop = true;
+ else
+ tmp = tmp->nextSibling( );
+ }
+ else
+ stop = true;
+ }
+ else if( tmp->isSelected( ) )
+ {
+ tmp->setSelected( false );
+ m_selectedObjects.removeRef( tmp );
+ emit objectChanged( tmp, PMCDeselected, this );
+ tmp = tmp->nextSibling( );
+ }
+ else if( tmp->selectedChildren( ) > 0 )
+ {
+ stack.push( tmp );
+ tmp = tmp->firstChild( );
+ }
+ else
+ {
+ tmp = tmp->nextSibling( );
+ }
+ }
+ while( !stop );
+ }
+
+ obj->setSelected( true );
+ m_selectedObjects.append( obj );
+ selectionChanged = true;
+ m_sortedListUpToDate = false;
+ m_sortedSelectedObjects.clear( );
+ m_pActiveObject = 0;
+ }
+ else
+ {
+ kdError( PMArea ) << "(PMPart::slotObjectChanged) object is not selectable!" << "\n";
+ mode = mode & ( ~( PMCSelected | PMCNewSelection ) );
+ }
+ }
+ else if( mode & PMCDeselected )
+ {
+ // no problems here
+ m_selectedObjects.removeRef( obj );
+ obj->setSelected( false );
+ m_sortedListUpToDate = false;
+ m_sortedSelectedObjects.clear( );
+ selectionChanged = true;
+ m_pActiveObject = 0;
+ }
+
+ if( mode & PMCRemove )
+ {
+ if( obj->parent( ) )
+ if( obj->parent( ) == m_pActiveObject )
+ m_updateNewObjectActions = true;
+ if( m_pNewSelection == obj )
+ {
+ if( obj->nextSibling( ) )
+ m_pNewSelection = obj->nextSibling( );
+ else if( obj->prevSibling( ) )
+ m_pNewSelection = obj->nextSibling( );
+ else if( obj->parent( ) )
+ m_pNewSelection = obj->parent( );
+ else
+ m_pNewSelection = 0;
+ }
+ if( m_selectedObjects.containsRef( obj ) )
+ {
+ m_selectedObjects.removeRef( obj );
+ if( m_selectedObjects.isEmpty( ) )
+ {
+ if( obj->nextSibling( ) )
+ m_pNewSelection = obj->nextSibling( );
+ else if( obj->prevSibling( ) )
+ m_pNewSelection = obj->prevSibling( );
+ else if( obj->parent( ) )
+ m_pNewSelection = obj->parent( );
+ else
+ m_pNewSelection = 0;
+ }
+ m_sortedListUpToDate = false;
+ m_sortedSelectedObjects.clear( );
+ selectionChanged = true;
+ }
+ if( m_pActiveObject == obj )
+ m_pActiveObject = 0;
+
+ if( obj->isA( "Declare" ) )
+ {
+ PMDeclare* decl = ( PMDeclare* ) obj;
+ m_pSymbolTable->remove( decl->id( ) );
+ }
+
+ if( obj->type( ) == "Camera" )
+ m_cameras.removeRef( ( PMCamera* ) obj );
+ }
+
+ if( mode & PMCAdd )
+ {
+ if( !( mode & PMCInsertError ) )
+ {
+ m_pNewSelection = obj;
+ if( obj->isA( "Declare" ) )
+ {
+ PMDeclare* decl = ( PMDeclare* ) obj;
+ PMSymbol* s = m_pSymbolTable->find( decl->id( ) );
+ if( !s )
+ m_pSymbolTable->insert( decl->id( ),
+ new PMSymbol( decl->id( ), decl ) );
+ }
+ if( obj->type( ) == "Camera" )
+ m_bCameraListUpToDate = false;
+ }
+ if( obj->parent( ) )
+ if( obj->parent( ) == m_pActiveObject )
+ m_updateNewObjectActions = true;
+ m_numAddedObjects++;
+ }
+
+ if( mode & PMCData )
+ {
+ m_updateNewObjectActions = true;
+ }
+
+ if( mode & PMCViewStructure )
+ {
+ changeControlPoints = true;
+ }
+
+ if( mode & PMCInsertError )
+ {
+ m_numInsertErrors++;
+ QString detail;
+ detail = obj->description( ) + QString( " " ) + obj->name( );
+ m_insertErrorDetails.append( detail );
+
+ if( obj->isA( "Declare" ) )
+ {
+ PMDeclare* decl = ( PMDeclare* ) obj;
+ m_pSymbolTable->remove( decl->id( ) );
+ }
+ }
+
+ if( selectionChanged )
+ {
+ m_sortedListUpToDate = false;
+ m_sortedSelectedObjects.clear( );
+
+ int c = m_selectedObjects.count( );
+
+ if( m_pScene->isSelected( ) )
+ c = m_pScene->countChildren( );
+
+ m_pCopyAction->setEnabled( c > 0 );
+
+ if( isReadWrite( ) )
+ {
+ m_pCutAction->setEnabled( c > 0 );
+ m_pDeleteAction->setEnabled( c > 0 );
+ m_pPasteAction->setEnabled( m_pActiveObject && m_canDecode );
+ updateNewObjectActions( );
+ }
+ }
+
+ if( ( oldActive != m_pActiveObject ) || changeControlPoints )
+ {
+ updateControlPoints( oldActive );
+ emit objectChanged( m_pActiveObject, PMCNewControlPoints, this );
+ mode |= ( PMCNewControlPoints | PMCControlPointSelection );
+ }
+
+ emit objectChanged( obj, mode, sender );
+}
+
+void PMPart::slotIDChanged( PMObject* obj, const QString& oldID )
+{
+ if( obj->isA( "Declare" ) )
+ {
+ PMDeclare* d = ( PMDeclare* ) obj;
+ PMSymbol* s = m_pSymbolTable->find( oldID );
+ if( s )
+ {
+ if( s->type( ) == PMSymbol::Object )
+ {
+ if( s->object( ) == obj )
+ {
+ m_pSymbolTable->take( oldID );
+ s->setId( d->id( ) );
+ m_pSymbolTable->insert( s->id( ), s );
+ }
+ else
+ kdError( PMArea ) << "PMPart::slotIDChanged: Symbol "
+ << oldID << " points to wrong object.\n";
+ }
+ else
+ kdError( PMArea ) << "PMPart::slotIDChanged: Symbol "
+ << oldID << " has wrong type.\n";
+ }
+ else
+ kdError( PMArea ) << "PMPart::slotIDChanged: Symbol "
+ << oldID << " not found.\n";
+ }
+}
+
+void PMPart::slotNewObject( PMObject* newObject, int insertAs )
+{
+ PMObjectList list;
+ list.append( newObject );
+ PMCommand* command = 0;
+
+ if( m_pActiveObject )
+ {
+ // If no position was specified ask the user
+ if( insertAs <= 0 )
+ insertAs = whereToInsert( m_pActiveObject, list );
+ // If either through a parameter or by user action a position was selected
+ if( insertAs > 0 )
+ {
+ // insert the object in the position indicated
+ switch( insertAs )
+ {
+ case PMInsertPopup::PMIFirstChild:
+ command = new PMAddCommand( list, m_pActiveObject, 0 );
+ break;
+ case PMInsertPopup::PMILastChild:
+ command = new PMAddCommand( list, m_pActiveObject,
+ m_pActiveObject->lastChild( ) );
+ break;
+ case PMInsertPopup::PMISibling:
+ command = new PMAddCommand( list,
+ m_pActiveObject->parent( ),
+ m_pActiveObject );
+ break;
+ default:
+ command = new PMAddCommand( list, m_pActiveObject, 0 );
+ break;
+ }
+ executeCommand( command );
+ }
+ else
+ {
+ list.clear( );
+ delete newObject;
+ }
+ }
+ else
+ {
+ list.clear( );
+ delete newObject;
+ }
+}
+
+void PMPart::slotNewObject( const QString& type )
+{
+ PMObject* newObject = m_pPrototypeManager->newObject( type );
+ if( newObject )
+ slotNewObject( newObject );
+}
+
+void PMPart::slotNewObject( const QString& type, const QString& pos )
+{
+ PMObject* newObject = m_pPrototypeManager->newObject( type );
+ if( newObject )
+ {
+ if( pos == "FirstChild" )
+ slotNewObject( newObject, PMInsertPopup::PMIFirstChild );
+ else if( pos == "LastChild" )
+ slotNewObject( newObject, PMInsertPopup::PMILastChild );
+ else if( pos == "Sibling" )
+ slotNewObject( newObject, PMInsertPopup::PMISibling );
+ else
+ slotNewObject( newObject );
+ }
+}
+
+QStringList PMPart::getObjectTypes( )
+{
+ QStringList result;
+ QPtrListIterator<PMMetaObject> it = m_pPrototypeManager->prototypeIterator( );
+
+ for( ; it.current( ); ++it )
+ {
+ result.append( it.current( )->className( ) );
+ }
+ return result;
+}
+
+void PMPart::slotNewTransformedObject( PMObject* o )
+{
+ if( o )
+ {
+ if( o->canInsert( QString( "Scale" ), o->lastChild( ) ) )
+ o->appendChild( new PMScale( this ) );
+ if( o->canInsert( QString( "Rotate" ), o->lastChild( ) ) )
+ o->appendChild( new PMRotate( this ) );
+ if( o->canInsert( QString( "Translate" ), o->lastChild( ) ) )
+ o->appendChild( new PMTranslate( this ) );
+ slotNewObject( o );
+ }
+}
+
+void PMPart::slotNewGlobalSettings( )
+{
+ slotNewObject( new PMGlobalSettings( this ) );
+}
+
+void PMPart::slotNewSkySphere( )
+{
+ slotNewObject( new PMSkySphere( this ) );
+}
+
+void PMPart::slotNewRainbow( )
+{
+ slotNewObject( new PMRainbow( this ) );
+}
+
+void PMPart::slotNewFog( )
+{
+ slotNewObject( new PMFog( this ) );
+}
+
+void PMPart::slotNewInterior( )
+{
+ slotNewObject( new PMInterior( this ) );
+}
+
+void PMPart::slotNewMedia( )
+{
+ slotNewObject( new PMMedia( this ) );
+}
+
+void PMPart::slotNewDensity( )
+{
+ slotNewObject( new PMDensity( this ) );
+}
+
+void PMPart::slotNewMaterial( )
+{
+ slotNewObject( new PMMaterial( this ) );
+}
+
+void PMPart::slotNewBox( )
+{
+ slotNewTransformedObject( new PMBox( this ) );
+}
+
+void PMPart::slotNewSphere( )
+{
+ slotNewTransformedObject( new PMSphere( this ) );
+}
+
+void PMPart::slotNewCylinder( )
+{
+ slotNewTransformedObject( new PMCylinder( this ) );
+}
+
+void PMPart::slotNewPlane( )
+{
+ slotNewTransformedObject( new PMPlane( this ) );
+}
+
+void PMPart::slotNewPolynom( )
+{
+ slotNewTransformedObject( new PMPolynom( this ) );
+}
+
+void PMPart::slotNewCone( )
+{
+ slotNewTransformedObject( new PMCone( this ) );
+}
+
+void PMPart::slotNewTorus( )
+{
+ slotNewTransformedObject( new PMTorus( this ) );
+}
+
+void PMPart::slotNewLathe( )
+{
+ slotNewTransformedObject( new PMLathe( this ) );
+}
+
+void PMPart::slotNewPrism( )
+{
+ slotNewTransformedObject( new PMPrism( this ) );
+}
+
+void PMPart::slotNewSurfaceOfRevolution( )
+{
+ slotNewTransformedObject( new PMSurfaceOfRevolution( this ) );
+}
+
+void PMPart::slotNewSuperquadricEllipsoid( )
+{
+ slotNewTransformedObject( new PMSuperquadricEllipsoid( this ) );
+}
+
+void PMPart::slotNewJuliaFractal( )
+{
+ slotNewTransformedObject( new PMJuliaFractal( this ) );
+}
+
+void PMPart::slotNewHeightField( )
+{
+ slotNewTransformedObject( new PMHeightField( this ) );
+}
+
+void PMPart::slotNewText( )
+{
+ slotNewTransformedObject( new PMText( this ) );
+}
+
+void PMPart::slotNewBlob( )
+{
+ slotNewTransformedObject( new PMBlob( this ) );
+}
+
+void PMPart::slotNewBlobSphere( )
+{
+ slotNewObject( new PMBlobSphere( this ) );
+}
+
+void PMPart::slotNewBlobCylinder( )
+{
+ slotNewObject( new PMBlobCylinder( this ) );
+}
+
+void PMPart::slotNewDeclare( )
+{
+ PMDeclare* obj = new PMDeclare( this );
+ m_pSymbolTable->findNewID( i18n( "Declare" ), obj );
+ slotNewObject( obj );
+}
+
+void PMPart::slotNewObjectLink( )
+{
+ slotNewTransformedObject( new PMObjectLink( this ) );
+}
+
+void PMPart::slotNewUnion( )
+{
+ slotNewObject( new PMCSG( this, PMCSG::CSGUnion ) );
+}
+
+void PMPart::slotNewDifference( )
+{
+ slotNewObject( new PMCSG( this, PMCSG::CSGDifference ) );
+}
+
+void PMPart::slotNewIntersection( )
+{
+ slotNewObject( new PMCSG( this, PMCSG::CSGIntersection ) );
+}
+
+void PMPart::slotNewMerge( )
+{
+ slotNewObject( new PMCSG( this, PMCSG::CSGMerge ) );
+}
+
+void PMPart::slotNewBoundedBy( )
+{
+ slotNewObject( new PMBoundedBy( this ) );
+}
+
+void PMPart::slotNewClippedBy( )
+{
+ slotNewObject( new PMClippedBy( this ) );
+}
+
+void PMPart::slotNewLight( )
+{
+ slotNewObject( new PMLight( this ) );
+}
+
+void PMPart::slotNewLooksLike( )
+{
+ slotNewObject( new PMLooksLike( this ) );
+}
+
+void PMPart::slotNewProjectedThrough( )
+{
+ slotNewObject( new PMProjectedThrough( this ) );
+}
+
+void PMPart::slotNewDisc( )
+{
+ slotNewTransformedObject( new PMDisc( this ) );
+}
+
+void PMPart::slotNewBicubicPatch( )
+{
+ slotNewTransformedObject( new PMBicubicPatch( this ) );
+}
+
+void PMPart::slotNewTriangle( )
+{
+ slotNewObject( new PMTriangle( this ) );
+}
+
+void PMPart::slotNewCamera( )
+{
+ PMCamera* c = new PMCamera( this );
+ c->setAngle( 45.0 );
+ c->setLocation( PMVector( 5.0, 5.0, -5.0 ) );
+ c->setLookAt( PMVector( 0.0, 0.0, 0.0 ) );
+
+ slotNewObject( c );
+}
+
+void PMPart::slotNewTexture( )
+{
+ slotNewObject( new PMTexture( this ) );
+}
+
+void PMPart::slotNewPigment( )
+{
+ slotNewObject( new PMPigment( this ) );
+}
+
+void PMPart::slotNewNormal( )
+{
+ slotNewObject( new PMNormal( this ) );
+}
+
+void PMPart::slotNewSolidColor( )
+{
+ slotNewObject( new PMSolidColor( this ) );
+}
+
+void PMPart::slotNewTextureList( )
+{
+ slotNewObject( new PMTextureList( this ) );
+}
+
+void PMPart::slotNewColorList( )
+{
+ slotNewObject( new PMColorList( this ) );
+}
+
+void PMPart::slotNewPigmentList( )
+{
+ slotNewObject( new PMPigmentList( this ) );
+}
+
+void PMPart::slotNewNormalList( )
+{
+ slotNewObject( new PMNormalList( this ) );
+}
+
+void PMPart::slotNewDensityList( )
+{
+ slotNewObject( new PMDensityList( this ) );
+}
+
+void PMPart::slotNewFinish( )
+{
+ slotNewObject( new PMFinish( this ) );
+}
+
+void PMPart::slotNewWarp( )
+{
+ slotNewObject( new PMWarp( this ) );
+}
+
+void PMPart::slotNewImageMap( )
+{
+ slotNewObject( new PMImageMap( this ) );
+}
+
+void PMPart::slotNewPattern( )
+{
+ slotNewObject( new PMPattern( this ) );
+}
+
+void PMPart::slotNewBlendMapModifiers( )
+{
+ slotNewObject( new PMBlendMapModifiers( this ) );
+}
+
+void PMPart::slotNewTextureMap( )
+{
+ slotNewObject( new PMTextureMap( this ) );
+}
+
+void PMPart::slotNewMaterialMap( )
+{
+ slotNewObject( new PMMaterialMap( this ) );
+}
+
+void PMPart::slotNewColorMap( )
+{
+ slotNewObject( new PMColorMap( this ) );
+}
+
+void PMPart::slotNewPigmentMap( )
+{
+ slotNewObject( new PMPigmentMap( this ) );
+}
+
+void PMPart::slotNewNormalMap( )
+{
+ slotNewObject( new PMNormalMap( this ) );
+}
+
+void PMPart::slotNewBumpMap( )
+{
+ slotNewObject( new PMBumpMap( this ) );
+}
+
+void PMPart::slotNewSlopeMap( )
+{
+ slotNewObject( new PMSlopeMap( this ) );
+}
+
+void PMPart::slotNewDensityMap( )
+{
+ slotNewObject( new PMDensityMap( this ) );
+}
+
+void PMPart::slotNewSlope( )
+{
+ slotNewObject( new PMSlope( this ) );
+}
+
+void PMPart::slotNewQuickColor( )
+{
+ slotNewObject( new PMQuickColor( this ) );
+}
+
+void PMPart::slotNewTranslate( )
+{
+ slotNewObject( new PMTranslate( this ) );
+}
+
+void PMPart::slotNewScale( )
+{
+ slotNewObject( new PMScale( this ) );
+}
+
+void PMPart::slotNewRotate( )
+{
+ slotNewObject( new PMRotate( this ) );
+}
+
+void PMPart::slotNewMatrix( )
+{
+ slotNewObject( new PMPovrayMatrix( this ) );
+}
+
+void PMPart::slotNewComment( )
+{
+ slotNewObject( new PMComment( this ) );
+}
+
+void PMPart::slotNewRaw( )
+{
+ slotNewObject( new PMRaw( this ) );
+}
+
+// POV-Ray 3.5 objects
+
+void PMPart::slotNewIsoSurface( )
+{
+ slotNewObject( new PMIsoSurface( this ) );
+}
+
+void PMPart::slotNewRadiosity( )
+{
+ slotNewObject( new PMRadiosity( this ) );
+}
+
+void PMPart::slotNewGlobalPhotons( )
+{
+ slotNewObject( new PMGlobalPhotons( this ) );
+}
+
+void PMPart::slotNewPhotons( )
+{
+ slotNewObject( new PMPhotons( this ) );
+}
+
+void PMPart::slotNewLightGroup( )
+{
+ slotNewObject( new PMLightGroup( this ) );
+}
+
+void PMPart::slotNewInteriorTexture( )
+{
+ slotNewObject( new PMInteriorTexture( this ) );
+}
+
+void PMPart::slotNewSphereSweep( )
+{
+ slotNewObject( new PMSphereSweep( this ) );
+}
+
+void PMPart::slotNewMesh( )
+{
+ slotNewObject( new PMMesh( this ) );
+}
+
+void PMPart::slotSearchLibraryObject( )
+{
+ PMLibraryObjectSearch* aux = new PMLibraryObjectSearch( NULL );
+ aux->show( );
+}
+
+void PMPart::slotClipboardDataChanged( )
+{
+ if( isReadWrite( ) )
+ {
+ m_canDecode = PMObjectDrag::canDecode( qApp->clipboard( )->data( ), this );
+ m_pPasteAction->setEnabled( m_canDecode && m_pActiveObject );
+ }
+ else
+ m_pPasteAction->setEnabled( false );
+}
+
+void PMPart::clearSelection( )
+{
+ PMObjectListIterator it( m_selectedObjects );
+
+ if( it.current( ) )
+ {
+ if( it.current( )->nextSibling( ) )
+ m_pNewSelection = it.current( )->nextSibling( );
+ else if( it.current( )->prevSibling( ) )
+ m_pNewSelection = it.current( )->prevSibling( );
+ else if( it.current( )->parent( ) )
+ m_pNewSelection = it.current( )->parent( );
+
+ for( ; it.current( ); ++it )
+ {
+ it.current( )->setSelected( false );
+ if( m_pNewSelection == it.current( ) )
+ {
+ if( it.current( )->nextSibling( ) )
+ m_pNewSelection = it.current( )->nextSibling( );
+ else if( it.current( )->prevSibling( ) )
+ m_pNewSelection = it.current( )->prevSibling( );
+ else if( it.current( )->parent( ) )
+ m_pNewSelection = it.current( )->parent( );
+ }
+ }
+ }
+
+ m_selectedObjects.clear( );
+ m_sortedListUpToDate = true;
+}
+
+bool PMPart::newDocument( )
+{
+ deleteContents( );
+ setModified( false );
+
+ m_pScene = new PMScene( this );
+
+ PMGlobalSettings* gs = new PMGlobalSettings( this );
+ gs->setAssumedGamma( 1.5 );
+ m_pScene->appendChild( gs );
+
+ PMBox* b = new PMBox( this );
+ m_pScene->appendChild( b );
+ PMPigment* p = new PMPigment( this );
+ b->appendChild( p );
+ PMSolidColor* c = new PMSolidColor( this );
+ c->setColor( PMColor( 0.3, 1.0, 0.3 ) );
+ p->appendChild( c );
+ PMScale* s = new PMScale( this );
+ b->appendChild( s );
+ PMRotate* r = new PMRotate( this );
+ b->appendChild( r );
+ PMTranslate* t = new PMTranslate( this );
+ t->setTranslation( PMVector( 0, 0.5, 0 ) );
+ b->appendChild( t );
+
+ PMLight* l = new PMLight( this );
+ l->setLocation( PMVector( 4.0, 5.0, -5.0 ) );
+ m_pScene->appendChild( l );
+ PMCamera* ca = new PMCamera( this );
+ ca->setAngle( 45.0 );
+ ca->setLocation( PMVector( 5.0, 5.0, -5.0 ) );
+ ca->setLookAt( PMVector( 0.0, 0.0, 0.0 ) );
+ m_pScene->appendChild( ca );
+ m_bCameraListUpToDate = false;
+
+ m_pScene->setReadOnly( !isReadWrite( ) );
+ PMRenderMode* mode = new PMRenderMode( );
+ mode->setDescription( i18n( "Default" ) );
+ m_pScene->renderModes( )->append( mode );
+
+ emit refresh( );
+ updateRenderModes( );
+ updateVisibilityLevel( );
+ slotObjectChanged( m_pScene, PMCNewSelection, this );
+
+ return true;
+}
+
+void PMPart::closeDocument( )
+{
+ m_url = KURL( );
+}
+
+void PMPart::deleteContents( )
+{
+ emit clear( );
+ if( isReadWrite( ) )
+ m_commandManager.clear( );
+ m_selectedObjects.clear( );
+ m_sortedSelectedObjects.clear( );
+ m_sortedListUpToDate = true;
+ m_pActiveObject = 0;
+ m_pNewSelection = 0;
+
+ if( m_pScene )
+ {
+ delete m_pScene;
+ m_pScene = 0;
+ }
+ if( m_pSymbolTable )
+ delete m_pSymbolTable;
+
+ m_pSymbolTable = new PMSymbolTable( );
+ m_cameras.clear( );
+ m_bCameraListUpToDate = true;
+}
+
+void PMPart::slotUpdateUndoRedo( const QString& undo, const QString& redo )
+{
+ if( isReadWrite( ) )
+ {
+ if( m_pUndoAction )
+ {
+ if( undo.isNull( ) )
+ {
+ m_pUndoAction->setText( i18n( "Undo" ) );
+ m_pUndoAction->setEnabled( false );
+ }
+ else
+ {
+ m_pUndoAction->setText( i18n( "Undo" ) + " " + undo );
+ m_pUndoAction->setEnabled( true );
+ }
+ }
+ if( m_pRedoAction )
+ {
+ if( redo.isNull( ) )
+ {
+ m_pRedoAction->setText( i18n( "Redo" ) );
+ m_pRedoAction->setEnabled( false );
+ }
+ else
+ {
+ m_pRedoAction->setText( i18n( "Redo" ) + " " + redo );
+ m_pRedoAction->setEnabled( true );
+ }
+ }
+ }
+}
+
+void PMPart::setScene( PMScene* scene )
+{
+ deleteContents( );
+ m_pScene = scene;
+ emit refresh( );
+ slotObjectChanged( m_pScene, PMCNewSelection, this );
+}
+
+void PMPart::setModified( )
+{
+ KParts::ReadWritePart::setModified( );
+ emit modified( );
+}
+
+void PMPart::setModified( bool m )
+{
+ KParts::ReadWritePart::setModified( m );
+ emit modified( );
+}
+
+PMCamera* PMPart::firstCamera( )
+{
+ if( !m_bCameraListUpToDate )
+ updateCameraList( );
+ return m_cameras.first( );
+}
+
+QPtrListIterator<PMCamera> PMPart::cameras( )
+{
+ if( !m_bCameraListUpToDate )
+ updateCameraList( );
+ return QPtrListIterator<PMCamera>( m_cameras );
+}
+
+void PMPart::updateCameraList( )
+{
+ m_cameras.clear( );
+ PMObject* obj;
+ for( obj = m_pScene->firstChild( ); obj; obj = obj->nextSibling( ) )
+ if( obj->type( ) == "Camera" )
+ m_cameras.append( ( PMCamera* ) obj );
+ m_bCameraListUpToDate = true;
+}
+
+void PMPart::slotRender( )
+{
+ PMRenderMode* m = m_pScene->renderModes( )->current( );
+ if( m )
+ {
+ emit aboutToRender( );
+
+ QByteArray a;
+ QBuffer buffer( a );
+ buffer.open( IO_WriteOnly );
+ PMPovray35Format format;
+ PMSerializer* dev = format.newSerializer( &buffer );
+ dev->serialize( m_pScene );
+ delete dev;
+
+ if( !m_pPovrayWidget )
+ m_pPovrayWidget = new PMPovrayWidget( );
+ if( m_pPovrayWidget->render( a, *m, url( ) ) )
+ {
+ m_pPovrayWidget->show( );
+ m_pPovrayWidget->raise( );
+ }
+ }
+}
+
+void PMPart::slotRenderSettings( )
+{
+ PMRenderModesDialog dlg( m_pScene->renderModes( ), widget( ) );
+ int result = dlg.exec( );
+
+ if( result == QDialog::Accepted )
+ {
+ if( isReadWrite( ) )
+ setModified( true );
+ updateRenderModes( );
+ }
+}
+
+void PMPart::slotViewRenderWindow( )
+{
+ if( !m_pPovrayWidget )
+ m_pPovrayWidget = new PMPovrayWidget( );
+ m_pPovrayWidget->show( );
+ m_pPovrayWidget->raise( );
+}
+
+void PMPart::slotRenderMode( int index )
+{
+ PMRenderModeList* list = m_pScene->renderModes( );
+ list->at( index );
+ emit activeRenderModeChanged( );
+}
+
+void PMPart::updateRenderModes( )
+{
+ if( m_pScene )
+ {
+ PMRenderModeList* list = m_pScene->renderModes( );
+ PMRenderModeListIterator it( *list );
+
+ QComboBox* box = m_pRenderComboAction->combo( );
+ if( box )
+ {
+ bool b = box->signalsBlocked( );
+ box->blockSignals( true );
+ box->clear( );
+
+ for( ; it.current( ); ++it )
+ box->insertItem( it.current( )->description( ) );
+ box->setCurrentItem( list->at( ) );
+ box->updateGeometry( );
+
+ box->blockSignals( b );
+ }
+ emit activeRenderModeChanged( );
+ }
+}
+
+void PMPart::slotRenderModeActionPlugged( )
+{
+ updateRenderModes( );
+// connect( m_pRenderComboAction->combo( ), SIGNAL( activated( int ) ),
+// SLOT( slotRenderMode( int ) ) );
+}
+
+void PMPart::slotVisibilityLevelChanged( int l )
+{
+ if( m_pScene->visibilityLevel( ) != l )
+ {
+ m_pScene->setVisibilityLevel( l );
+ if( isReadWrite( ) )
+ setModified( true );
+ emit objectChanged( m_pScene, PMCViewStructure, this );
+ }
+}
+
+void PMPart::slotVisibilityActionPlugged( )
+{
+ if( m_pVisibilityLevelAction )
+ {
+ QSpinBox* box = m_pVisibilityLevelAction->spinBox( );
+ if( box )
+ {
+ box->setMinValue( -1000 );
+ box->setMaxValue( 1000 );
+ updateVisibilityLevel( );
+ }
+ }
+}
+
+void PMPart::updateVisibilityLevel( )
+{
+ if( m_pVisibilityLevelAction )
+ {
+ QSpinBox* box = m_pVisibilityLevelAction->spinBox( );
+ if( box && m_pScene )
+ {
+ bool sb = box->signalsBlocked( );
+ box->blockSignals( true );
+ box->setValue( m_pScene->visibilityLevel( ) );
+ box->blockSignals( sb );
+ }
+ }
+}
+
+void PMPart::slotGlobalDetailLevelChanged( int level )
+{
+ PMDetailObject::setGlobalDetailLevel( level + 1 );
+ emit objectChanged( m_pScene, PMCViewStructure, this );
+}
+
+void PMPart::updateControlPoints( PMObject* oldActive )
+{
+ PMControlPointList newCPs;
+
+ if( m_pActiveObject )
+ {
+ m_pActiveObject->controlPoints( newCPs );
+
+ if( m_pActiveObject == oldActive )
+ {
+ // check if the control points are the same
+ bool same = true;
+ PMControlPointListIterator oit( m_controlPoints );
+ PMControlPointListIterator nit( newCPs );
+ while( same && oit.current( ) && nit.current( ) )
+ {
+ if( oit.current( )->id( ) != nit.current( )->id( ) )
+ same = false;
+ ++oit;
+ ++nit;
+ }
+ if( oit.current( ) || nit.current( ) )
+ same = false;
+ if( same )
+ {
+ // set the old selection
+ oit.toFirst( );
+ nit.toFirst( );
+ while( oit.current( ) && nit.current( ) )
+ {
+ nit.current( )->setSelected( oit.current( )->selected( ) );
+ ++oit;
+ ++nit;
+ }
+ }
+ }
+ }
+
+ m_controlPoints.clear( );
+ m_controlPoints = newCPs;
+
+}
+
+void PMPart::slotAboutToSave( )
+{
+ emit aboutToSave( );
+}
+
+#include "pmpart.moc"
diff --git a/kpovmodeler/pmpart.h b/kpovmodeler/pmpart.h
new file mode 100644
index 00000000..e0ebcd06
--- /dev/null
+++ b/kpovmodeler/pmpart.h
@@ -0,0 +1,1041 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPART_H
+#define PMPART_H
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kapplication.h>
+#include <kaccel.h>
+#include <kurl.h>
+#include <kparts/part.h>
+#include <kparts/browserextension.h>
+#include <qstringlist.h>
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include "pmobject.h"
+#include "pmcommandmanager.h"
+#include "pmpartiface.h"
+
+class PMView;
+class PMShell;
+class PMObjectDrag;
+class PMScene;
+class PMCamera;
+class PMPovrayWidget;
+class PMParser;
+
+class PMBrowserExtension;
+class PMSymbolTable;
+class PMDeclare;
+
+class PMPrototypeManager;
+class PMInsertRuleSystem;
+class PMIOManager;
+
+class QMimeSource;
+class KAction;
+class KSelectAction;
+class PMComboAction;
+class PMSpinBoxAction;
+class PMLabelAction;
+class KProcess;
+
+/**
+ * The part for kpovmodeler (povray document)
+ */
+class PMPart : public KParts::ReadWritePart, virtual public PMPartIface
+{
+ Q_OBJECT
+public:
+ /**
+ * construtor of PMPart, calls all init functions to create the
+ * application.
+ */
+ PMPart( QWidget* parentWidget, const char* widgetName,
+ QObject* parent, const char* name, bool readWrite,
+ PMShell* shell = 0 );
+
+ /**
+ * construtor of PMPart, calls all init functions to create the
+ * application. It does not create the main widget.
+ */
+ PMPart( QWidget* parentWidget, const char* widgetName,
+ QObject* parent, const char* name, bool readWrite,
+ bool onlyCutPaste, PMShell* shell = 0 );
+
+ /**
+ * Destructor
+ */
+ ~PMPart( );
+ /**
+ * deletes the document's contents
+ */
+ void deleteContents( );
+ /**
+ * initializes the document generally
+ */
+ bool newDocument( );
+ /**
+ * closes the actual document
+ */
+ void closeDocument( );
+ /**
+ * Exports the scene as povray code
+ */
+ bool exportPovray( const KURL& url );
+
+ /**
+ * returns the toplevel object
+ */
+ PMScene* scene( ) const { return m_pScene; }
+ /**
+ * Returns a pointer to the shell if there is one
+ */
+ PMShell* shell( ) const { return m_pShell; }
+ /**
+ * saves settings
+ */
+ void saveConfig( KConfig* cfg );
+ /**
+ * loads settings
+ */
+ void restoreConfig( KConfig* cfg );
+
+ /**
+ * Updates the sorted list of selected objects if necessary and
+ * returns a reference to the list.
+ */
+ const PMObjectList& selectedObjects( );
+
+ /**
+ * Executes the command cmd.
+ *
+ * All changes to the document have to be made
+ * with @ref PMCommand objects for undo/redo. Each slot that changes the
+ * document creates a PMCommand object and calls this function.
+ *
+ * If this function returns false, the command was not executed
+ * and the command object was deleted.
+ */
+ bool executeCommand( PMCommand* cmd );
+ /**
+ * Checks, where the objects in list can be inserted, as child
+ * or as sibling of obj and asks the user if there is more than one
+ * possibility
+ *
+ * Returns PMIFirstChild, PMILastChild, PMISibling or 0, if the objects
+ * should not be inserted.*/
+ int whereToInsert( PMObject* obj, const PMObjectList& list );
+ /**
+ * Checks, where the objects in list can be inserted, as child
+ * or as sibling of obj and asks the user if there is more than one
+ * possibility
+ *
+ * Returns PMIFirstChild, PMILastChild, PMISibling or 0, if the objects
+ * should not be inserted.*/
+ int whereToInsert( PMObject* obj, const QStringList& list );
+ /**
+ * Asks the user, where to insert new objects.
+ *
+ * Returns PMIFirstChild, PMILastChild, PMISibling or 0, if the objects
+ * should not be inserted.*/
+ int whereToInsert( PMObject* obj );
+
+ /**
+ * Returns the symbol table of this document
+ */
+ PMSymbolTable* symbolTable( ) const { return m_pSymbolTable; }
+ /**
+ * Returns the first camera
+ */
+ PMCamera* firstCamera( );
+ /**
+ * Returns an iterator to the list of cameras
+ */
+ QPtrListIterator<PMCamera> cameras( );
+ /**
+ * The active object
+ */
+ PMObject* activeObject( ) const { return m_pActiveObject; }
+ /**
+ * The active object's name
+ */
+ virtual QString activeObjectName( );
+ /**
+ * Set the active object
+ */
+ virtual bool setActiveObject( const QString& name );
+ /**
+ * Get the valid properties of the currently active object
+ */
+ virtual QStringList getProperties( );
+ /**
+ * set a property on the active object
+ */
+ virtual bool setProperty( const QString& name, const PMVariant& value );
+ /**
+ * set a property on the active object
+ */
+ virtual bool setProperty( const QString& name, const QString& value );
+ /**
+ * get a property on the active object
+ */
+ virtual const PMVariant getProperty( const QString& name );
+ /**
+ * get a property on the active object
+ */
+ virtual const QString getPropertyStr( const QString& name );
+ /**
+ * List of control points of the active object
+ */
+ PMControlPointList activeControlPoints( ) const { return m_controlPoints; }
+
+ /**
+ * Called when the user moves some objects in the tree view.
+ * If obj is 0, the user moved the objects to another document (remove)
+ *
+ * Returns true if successful.
+ */
+ bool dragMoveSelectionTo( PMObject* obj );
+ /**
+ * Called when the user drags some objects onto the tree view
+ *
+ * Returns true if successful.
+ */
+ bool drop( PMObject* obj, QMimeSource* e );
+ /**
+ * Tries to parse the data and insert the parsed objects
+ * as child or siblings of object obj
+ *
+ * Type is the actions description for the undo/redo menu.
+ */
+ bool insertFromParser( const QString& type, PMParser* parser, PMObject* obj );
+
+ /**
+ * Returns a pointer to the prototype manager
+ */
+ PMPrototypeManager* prototypeManager( ) const { return m_pPrototypeManager; }
+ /**
+ * Returns a pointer to the insert rules system
+ */
+ PMInsertRuleSystem* insertRuleSystem( ) const { return m_pInsertRuleSystem; }
+ /**
+ * Returns a pointer to the IO formats manager for this part
+ */
+ PMIOManager* ioManager( ) const { return m_pIOManager; }
+
+public slots:
+ /**
+ * Opens the import file dialog
+ */
+ void slotFileImport( );
+ /**
+ * Opens the export file dialog
+ */
+ void slotFileExport( );
+
+ /**
+ * puts the marked text/object into the clipboard and removes the objects
+ */
+ void slotEditCut( );
+ /**
+ * removes the selected object
+ */
+ void slotEditDelete( );
+ /**
+ * puts the marked text/object into the clipboard
+ */
+ void slotEditCopy( );
+ /**
+ * paste the clipboard into the document
+ */
+ void slotEditPaste( );
+ /**
+ * undoes the last change
+ */
+ void slotEditUndo( );
+ /**
+ * redoes the last undone command
+ */
+ void slotEditRedo( );
+
+ /**
+ * Called when an object is changed.
+ * Mode is a bit combination of @ref PMChange constants
+ */
+ void slotObjectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Called when an id is changed
+ */
+ void slotIDChanged( PMObject* obj, const QString& oldID );
+
+ /**
+ * Inserts a new PMObject of type type
+ */
+ void slotNewObject( const QString& type );
+ /**
+ * Inserts a new PMObject of type type at position pos.
+ * pos can be one of:
+ * FirstChild
+ * LastChild
+ * Sibling
+ */
+ void slotNewObject( const QString& type, const QString& pos );
+ /**
+ * Inserts the new PMObject. The object will be deleted if it can't be
+ * inserted or the user aborts the action
+ */
+ void slotNewObject( PMObject* newObject, int insertAs = 0 );
+
+ /**
+ * List the known object types
+ */
+ virtual QStringList getObjectTypes( );
+
+ /**
+ * Adds transformations to the object and calls slotNewObject
+ * for it
+ */
+ void slotNewTransformedObject( PMObject* o );
+
+ /**
+ * Inserts a new PMGlobalSettings
+ */
+ void slotNewGlobalSettings( );
+ /**
+ * Inserts a new PMSkySphere
+ */
+ void slotNewSkySphere( );
+ /**
+ * Inserts a new PMRainbow
+ */
+ void slotNewRainbow( );
+ /**
+ * Inserts a new PMFog
+ */
+ void slotNewFog( );
+ /**
+ * Inserts a new PMInterior
+ */
+ void slotNewInterior( );
+ /**
+ * Inserts a new PMMedia
+ */
+ void slotNewMedia( );
+ /**
+ * Inserts a new PMDensity
+ */
+ void slotNewDensity( );
+ /**
+ * Inserts a new PMMaterial
+ */
+ void slotNewMaterial( );
+ /**
+ * Inserts a new PMBox
+ */
+ void slotNewBox( );
+ /**
+ * Inserts a new PMSphere
+ */
+ void slotNewSphere( );
+ /**
+ * Inserts a new PMCylinder
+ */
+ void slotNewCylinder( );
+ /**
+ * Inserts a new PMCone
+ */
+ void slotNewCone( );
+ /**
+ * Inserts a new PMTorus
+ */
+ void slotNewTorus( );
+ /**
+ * Inserts a new PMLathe
+ */
+ void slotNewLathe( );
+ /**
+ * Inserts a new PMPrism
+ */
+ void slotNewPrism( );
+ /**
+ * Inserts a new PMSurfaceOfRevolution
+ */
+ void slotNewSurfaceOfRevolution( );
+ /**
+ * Inserts a new PMSuperquadricEllipsoid
+ */
+ void slotNewSuperquadricEllipsoid( );
+ /**
+ * Inserts a new PMJuliaFractal
+ */
+ void slotNewJuliaFractal( );
+ /**
+ * Inserts a new PMHeightField
+ */
+ void slotNewHeightField( );
+ /**
+ * Inserts a new text object
+ */
+ void slotNewText( );
+
+ /**
+ * Inserts a new PMBlob
+ */
+ void slotNewBlob( );
+ /**
+ * Inserts a new PMBlobSphere
+ */
+ void slotNewBlobSphere( );
+ /**
+ * Inserts a new PMBlobCylinder
+ */
+ void slotNewBlobCylinder( );
+
+ /**
+ * Inserts a new PMPlane
+ */
+ void slotNewPlane( );
+ /**
+ * Inserts a new PMPolynom
+ */
+ void slotNewPolynom( );
+ /**
+ * Inserts a new PMDeclare
+ */
+ void slotNewDeclare( );
+ /**
+ * Inserts a new PMObjectLink
+ */
+ void slotNewObjectLink( );
+
+ /**
+ * Inserts a new PMCSG ( union )
+ */
+ void slotNewUnion( );
+ /**
+ * Inserts a new PMCSG ( intersection )
+ */
+ void slotNewIntersection( );
+ /**
+ * Inserts a new PMCSG ( difference )
+ */
+ void slotNewDifference( );
+ /**
+ * Inserts a new PMCSG ( merge )
+ */
+ void slotNewMerge( );
+
+ /**
+ * Inserts a new PMDisc
+ */
+ void slotNewDisc( );
+ /**
+ * Inserts a new PMBicubicPatch
+ */
+ void slotNewBicubicPatch( );
+ /**
+ * Inserts a new PMTriangle
+ */
+ void slotNewTriangle( );
+
+ /**
+ * Inserts a new PMBoundedBy
+ */
+ void slotNewBoundedBy( );
+ /**
+ * Inserts a new PMClippedBy
+ */
+ void slotNewClippedBy( );
+
+ /**
+ * Inserts a new PMLight object
+ */
+ void slotNewLight( );
+ /**
+ * Inserts a new PMLooksLike object
+ */
+ void slotNewLooksLike( );
+ /**
+ * Inserts a new PMProjectedThrough object
+ */
+ void slotNewProjectedThrough( );
+
+ /**
+ * Inserts a new PMCamera
+ */
+ void slotNewCamera( );
+
+ /**
+ * Inserts a new PMTexture
+ */
+ void slotNewTexture( );
+ /**
+ * Inserts a new PMPigment
+ */
+ void slotNewPigment( );
+ /**
+ * Inserts a new PMNormal
+ */
+ void slotNewNormal( );
+ /**
+ * Inserts a new PMSolidColor
+ */
+ void slotNewSolidColor( );
+ /**
+ * Inserts a new PMTextureList
+ */
+ void slotNewTextureList( );
+ /**
+ * Inserts a new PMColorList
+ */
+ void slotNewColorList( );
+ /**
+ * Inserts a new PMPigmentList
+ */
+ void slotNewPigmentList( );
+ /**
+ * Inserts a new PMNormalList
+ */
+ void slotNewNormalList( );
+ /**
+ * Inserts a new PMDensityList
+ */
+ void slotNewDensityList( );
+ /**
+ * Inserts a new PMFinish
+ */
+ void slotNewFinish( );
+ /**
+ * Inserts a new PMPattern
+ */
+ void slotNewPattern( );
+ /**
+ * Inserts a new PMBlendMapModifiers
+ */
+ void slotNewBlendMapModifiers( );
+ /**
+ * Inserts a new PMTextureMap
+ */
+ void slotNewTextureMap( );
+ /**
+ * Inserts a new PMMaterialMap
+ */
+ void slotNewMaterialMap( );
+ /**
+ * Inserts a new PMColorMap
+ */
+ void slotNewColorMap( );
+ /**
+ * Inserts a new PMPigmentMap
+ */
+ void slotNewPigmentMap( );
+ /**
+ * Inserts a new PMNormalMap
+ */
+ void slotNewNormalMap( );
+ /**
+ * Inserts a new PMBumpMap
+ */
+ void slotNewBumpMap( );
+ /**
+ * Inserts a new PMSlopeMap
+ */
+ void slotNewSlopeMap( );
+ /**
+ * Inserts a new PMDensityMap
+ */
+ void slotNewDensityMap( );
+ /**
+ * Inserts a new PMSlope
+ */
+ void slotNewSlope( );
+ /**
+ * Inserts a new PMWarp
+ */
+ void slotNewWarp( );
+ /**
+ * Inserts a new PMImageMap
+ */
+ void slotNewImageMap( );
+ /**
+ * Inserts a new PMQuickColor
+ */
+ void slotNewQuickColor( );
+
+ /**
+ * Inserts a new PMTranslate
+ */
+ void slotNewTranslate( );
+ /**
+ * Inserts a new PMRotate
+ */
+ void slotNewRotate( );
+ /**
+ * Inserts a new PMScale
+ */
+ void slotNewScale( );
+ /**
+ * Inserts a new PMPovrayMatrix
+ */
+ void slotNewMatrix( );
+ /**
+ * Inserts a new PMComment
+ */
+ void slotNewComment( );
+ /**
+ * Inserts a new PMRaw
+ */
+ void slotNewRaw( );
+
+ // POV-Ray 3.5 objects
+ /**
+ * Inserts a new PMIsoSurfate
+ */
+ void slotNewIsoSurface( );
+ /**
+ * Inserts a new PMRadiosity
+ */
+ void slotNewRadiosity( );
+ /**
+ * Inserts a new PMGlobalPhotons
+ */
+ void slotNewGlobalPhotons( );
+ /**
+ * Inserts a new PMPhotons
+ */
+ void slotNewPhotons( );
+ /**
+ * Inserts a new PMLightGroup
+ */
+ void slotNewLightGroup( );
+ /**
+ * Inserts a new PMInteriorTexture
+ */
+ void slotNewInteriorTexture( );
+ /**
+ * Inserts a new PMSphereSweep
+ */
+ void slotNewSphereSweep( );
+ /**
+ * Inserts a new PMMesh
+ */
+ void slotNewMesh( );
+
+
+ /**
+ * Called when the clipboard contents changed
+ */
+ void slotClipboardDataChanged( );
+ /**
+ * updates the undo/redo menu items
+ */
+ void slotUpdateUndoRedo( const QString& undo, const QString& redo );
+
+ /**
+ * Starts rendering with povray
+ */
+ virtual void slotRender( );
+ /**
+ * Opens the render settings
+ */
+ void slotRenderSettings( );
+ /**
+ * Called when a render mode is selected
+ */
+ void slotRenderMode( int index );
+ /**
+ * Called when the render modes combo action is plugged into the toolbar
+ */
+ void slotRenderModeActionPlugged( );
+ /**
+ * Shows the render window
+ */
+ void slotViewRenderWindow( );
+ /**
+ * Called when the visibility level has changed
+ */
+ void slotVisibilityLevelChanged( int );
+ /**
+ * Called when the visibility level action is plugged into the toolbar
+ */
+ void slotVisibilityActionPlugged( );
+ /**
+ * Called when the global detail level has changed
+ */
+ void slotGlobalDetailLevelChanged( int level );
+
+ /**
+ * Opens the search library object dialog
+ */
+ void slotSearchLibraryObject( );
+
+ /** */
+ virtual void setModified( );
+ /** */
+ virtual void setModified( bool modified );
+
+ /** Set the scene object. Must be used with extreme care. */
+ void setScene( PMScene* scene );
+
+ /**
+ * Emits the aboutToSave signal
+ */
+ void slotAboutToSave( );
+
+signals:
+ /**
+ * Signal that is emitted when an object is changed.
+ * Mode is a bit combination of @ref PMChange constants.
+ */
+ void objectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Signal that is emitted when the views have to be refreshed.
+ * Usually on newDocument or openDocument
+ */
+ void refresh( );
+ /**
+ * Emitted when all views should delete all data
+ */
+ void clear( );
+ /**
+ * Emitted, when the modified flag changes
+ */
+ void modified( );
+ /**
+ * Emitted when the mouse is over a control point
+ */
+ void controlPointMessage( const QString& msg );
+ /**
+ * Emitted when the active render mode has changed
+ */
+ void activeRenderModeChanged( );
+ /**
+ * Emitted before the scene is rendered.
+ *
+ * Views should ask the user to save pending changes.
+ */
+ void aboutToRender( );
+ /**
+ * Emitted before the scene is saved or exported
+ *
+ * Views should ask the user to save pending changes.
+ */
+ void aboutToSave( );
+
+protected:
+ /**
+ * reimplemented from @ref KParts::ReadOnlyPart
+ */
+ virtual bool openFile( );
+ /**
+ * reimplemented from @ref KParts::ReadOnlyPart
+ */
+ virtual bool saveFile( );
+ /**
+ * Inits all actions
+ */
+ void initActions( );
+ /**
+ * Inits only actions related to copy&paste.
+ * Required by the library browser.
+ */
+ void initCopyPasteActions( );
+
+ /**
+ * creates the widget of the part instance and sets
+ * it as the view
+ */
+ void initView( QWidget* parent, const char* name );
+ /**
+ * initializes the documents contents
+ */
+ void initDocument( );
+ /**
+ * clears the selection
+ */
+ void clearSelection( );
+
+private:
+ /**
+ * Disables all actions, that modify the part
+ */
+ void disableReadWriteActions( );
+ /**
+ * Updates all "new object" actions
+ */
+ void updateNewObjectActions( );
+ /**
+ * Finds a free id of the format <prefix><number>.
+ *
+ * Adds the object to the symbol table.
+ *
+ * Returns the number.
+ */
+ unsigned int findNewID( const QString& prefix, unsigned int firstNumber,
+ PMDeclare* obj );
+ /**
+ * Updates the list of cameras
+ */
+ void updateCameraList( );
+
+ /**
+ * Generic drop/paste function
+ */
+ bool pasteOrDrop( const QString& type, QMimeSource* mime, PMObject* obj );
+ /**
+ * Generic cut/delete/remove function
+ */
+ bool removeSelection( const QString& type );
+ /**
+ * Updates the render mode combo action
+ */
+ void updateRenderModes( );
+ /**
+ * Updates the visibility level action
+ */
+ void updateVisibilityLevel( );
+ /**
+ * Updates the control point list
+ */
+ void updateControlPoints( PMObject* oldActive );
+
+ PMView* m_pView;
+ PMShell* m_pShell;
+ PMBrowserExtension* m_pExtension;
+
+ /**
+ * the selected objects, unsorted!
+ */
+ PMObjectList m_selectedObjects;
+ /**
+ * the selected objects, sorted. This list is only created if necessary.
+ */
+ PMObjectList m_sortedSelectedObjects;
+ /**
+ * true if the list m_sortedSelectedObjects is up to date
+ */
+ bool m_sortedListUpToDate;
+ /**
+ * the active object
+ */
+ PMObject* m_pActiveObject;
+ /**
+ * the new selection after a command was executed
+ */
+ PMObject* m_pNewSelection;
+ /**
+ * List of all cameras
+ */
+ QPtrList<PMCamera> m_cameras;
+ /**
+ * true if the m_cameras list is up to date
+ */
+ bool m_bCameraListUpToDate;
+ /**
+ * true if the clipboard data can be decoded
+ */
+ bool m_canDecode;
+ /**
+ * Commands stack for undo and redo
+ */
+ PMCommandManager m_commandManager;
+ /**
+ * The povray scene, top level object
+ */
+ PMScene* m_pScene;
+ /**
+ * Number of added objects during the last executed command
+ */
+ unsigned int m_numAddedObjects;
+ /**
+ * Number of insert errors during the last executed command
+ */
+ unsigned int m_numInsertErrors;
+ /**
+ * Details of insert errors
+ */
+ QStringList m_insertErrorDetails;
+ /**
+ * The symbol table for this document
+ */
+ PMSymbolTable* m_pSymbolTable;
+ /**
+ * The povray render window
+ */
+ PMPovrayWidget* m_pPovrayWidget;
+ /**
+ * true if the new object actions have to be updated
+ */
+ bool m_updateNewObjectActions;
+ /**
+ * Control points of the active object
+ */
+ PMControlPointList m_controlPoints;
+ /**
+ * true if only copy'n'paste actions are available
+ */
+ bool m_onlyCopyPaste;
+
+ // the actions
+ KAction* m_pImportAction;
+ KAction* m_pExportAction;
+
+ KAction* m_pCutAction;
+ KAction* m_pCopyAction;
+ KAction* m_pPasteAction;
+ KAction* m_pUndoAction;
+ KAction* m_pRedoAction;
+ KAction* m_pDeleteAction;
+
+ KAction* m_pNewGlobalSettingsAction;
+ KAction* m_pNewSkySphereAction;
+ KAction* m_pNewRainbowAction;
+ KAction* m_pNewFogAction;
+ KAction* m_pNewInteriorAction;
+ KAction* m_pNewMediaAction;
+ KAction* m_pNewDensityAction;
+ KAction* m_pNewMaterialAction;
+ KAction* m_pNewBoxAction;
+ KAction* m_pNewSphereAction;
+ KAction* m_pNewCylinderAction;
+ KAction* m_pNewConeAction;
+ KAction* m_pNewTorusAction;
+ KAction* m_pNewLatheAction;
+ KAction* m_pNewPrismAction;
+ KAction* m_pNewSurfaceOfRevolutionAction;
+ KAction* m_pNewSuperquadricEllipsoidAction;
+ KAction* m_pNewJuliaFractalAction;
+ KAction* m_pNewHeightFieldAction;
+ KAction* m_pNewTextAction;
+
+ KAction* m_pNewBlobAction;
+ KAction* m_pNewBlobSphereAction;
+ KAction* m_pNewBlobCylinderAction;
+
+ KAction* m_pNewPlaneAction;
+ KAction* m_pNewPolynomAction;
+
+ KAction* m_pNewDeclareAction;
+ KAction* m_pNewObjectLinkAction;
+
+ KAction* m_pNewUnionAction;
+ KAction* m_pNewDifferenceAction;
+ KAction* m_pNewIntersectionAction;
+ KAction* m_pNewMergeAction;
+
+ KAction* m_pNewBoundedByAction;
+ KAction* m_pNewClippedByAction;
+
+ KAction* m_pNewBicubicPatchAction;
+ KAction* m_pNewDiscAction;
+ KAction* m_pNewTriangleAction;
+
+ KAction* m_pNewLightAction;
+ KAction* m_pNewLooksLikeAction;
+ KAction* m_pNewProjectedThroughAction;
+
+ KAction* m_pNewCameraAction;
+
+ KAction* m_pNewTextureAction;
+ KAction* m_pNewPigmentAction;
+ KAction* m_pNewNormalAction;
+ KAction* m_pNewSolidColorAction;
+ KAction* m_pNewTextureListAction;
+ KAction* m_pNewColorListAction;
+ KAction* m_pNewPigmentListAction;
+ KAction* m_pNewNormalListAction;
+ KAction* m_pNewDensityListAction;
+ KAction* m_pNewFinishAction;
+ KAction* m_pNewPatternAction;
+ KAction* m_pNewBlendMapModifiersAction;
+ KAction* m_pNewTextureMapAction;
+ KAction* m_pNewMaterialMapAction;
+ KAction* m_pNewPigmentMapAction;
+ KAction* m_pNewColorMapAction;
+ KAction* m_pNewNormalMapAction;
+ KAction* m_pNewBumpMapAction;
+ KAction* m_pNewSlopeMapAction;
+ KAction* m_pNewDensityMapAction;
+ KAction* m_pNewSlopeAction;
+ KAction* m_pNewWarpAction;
+ KAction* m_pNewImageMapAction;
+ KAction* m_pNewQuickColorAction;
+
+ KAction* m_pNewTranslateAction;
+ KAction* m_pNewScaleAction;
+ KAction* m_pNewRotateAction;
+ KAction* m_pNewMatrixAction;
+
+ KAction* m_pNewCommentAction;
+ KAction* m_pNewRawAction;
+
+ // POV-Ray 3.5 objects
+ KAction* m_pNewIsoSurfaceAction;
+ KAction* m_pNewRadiosityAction;
+ KAction* m_pNewGlobalPhotonsAction;
+ KAction* m_pNewPhotonsAction;
+ KAction* m_pNewLightGroupAction;
+ KAction* m_pNewInteriorTextureAction;
+ KAction* m_pNewSphereSweepAction;
+ KAction* m_pNewMeshAction;
+
+ KAction* m_pSearchLibraryObjectAction;
+
+ PMComboAction* m_pRenderComboAction;
+ KAction* m_pRenderSettingsAction;
+ KAction* m_pViewRenderWindowAction;
+ KAction* m_pRenderAction;
+ PMSpinBoxAction* m_pVisibilityLevelAction;
+ PMLabelAction* m_pVisibilityLabelAction;
+ KSelectAction* m_pGlobalDetailAction;
+ PMLabelAction* m_pGlobalDetailLabelAction;
+
+ QPtrList<KAction> m_readWriteActions;
+
+ PMPrototypeManager* m_pPrototypeManager;
+ PMInsertRuleSystem* m_pInsertRuleSystem;
+ PMIOManager* m_pIOManager;
+};
+
+class PMBrowserExtension : public KParts::BrowserExtension
+{
+ Q_OBJECT
+ friend class PMPart;
+public:
+ PMBrowserExtension( PMPart* parent )
+ : KParts::BrowserExtension( parent, "PMBrowserExtension" )
+ {
+ KGlobal::locale()->insertCatalogue("kpovmodeler");
+ }
+
+ virtual ~PMBrowserExtension( )
+ {
+ }
+};
+
+#endif
diff --git a/kpovmodeler/pmpartiface.h b/kpovmodeler/pmpartiface.h
new file mode 100644
index 00000000..a1fe495e
--- /dev/null
+++ b/kpovmodeler/pmpartiface.h
@@ -0,0 +1,119 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2004 by Luis Carvalho
+ email : lpassos@oninetspeed.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPARTIFACE_H
+#define PMPARTIFACE_H
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dcopobject.h>
+
+#include "pmvariant.h"
+
+/**
+ * DCOP Interface for kpovmodeler
+ */
+class PMPartIface : virtual public DCOPObject
+{
+ K_DCOP
+
+k_dcop:
+ /**
+ * deletes the document's contents
+ */
+ virtual void deleteContents( ) = 0;
+ /**
+ * initializes the document generally
+ */
+ virtual bool newDocument( ) = 0;
+ /**
+ * closes the actual document
+ */
+ virtual void closeDocument( ) = 0;
+ /**
+ * Inserts a new PMObject of type type
+ */
+ virtual void slotNewObject( const QString& type, const QString& pos ) = 0;
+ /**
+ * initializes the documents contents
+ */
+ virtual void initDocument( ) = 0;
+ /**
+ * clears the selection
+ */
+ virtual void clearSelection( ) = 0;
+ /**
+ * puts the marked text/object into the clipboard and removes the objects
+ */
+ virtual void slotEditCut( ) = 0;
+ /**
+ * removes the selected object
+ */
+ virtual void slotEditDelete( ) = 0;
+ /**
+ * puts the marked text/object into the clipboard
+ */
+ virtual void slotEditCopy( ) = 0;
+ /**
+ * paste the clipboard into the document
+ */
+ virtual void slotEditPaste( ) = 0;
+ /**
+ * render the current scene
+ */
+ virtual void slotRender( ) = 0;
+ /**
+ * returns the currently selected object
+ */
+ virtual QString activeObjectName( ) = 0;
+ /**
+ * set the current selected object.
+ * returns true if successful or false otherwise
+ */
+ virtual bool setActiveObject( const QString& name ) = 0;
+ /**
+ * Get known properties of the currently active object
+ */
+ virtual QStringList getProperties( ) = 0;
+ /**
+ * set a property on the currently active object
+ */
+ virtual bool setProperty( const QString& property, const PMVariant& value ) = 0;
+ /**
+ * set a property on the currently active object
+ */
+ virtual bool setProperty( const QString& property, const QString& value ) = 0;
+ /**
+ * Get the value of the given property
+ */
+ virtual const PMVariant getProperty( const QString& property ) = 0;
+ /**
+ * Get the value of the given property
+ */
+ virtual const QString getPropertyStr( const QString& property ) = 0;
+ /**
+ * Get a list of known object types.
+ */
+ virtual QStringList getObjectTypes( ) = 0;
+};
+
+#endif
diff --git a/kpovmodeler/pmpattern.cpp b/kpovmodeler/pmpattern.cpp
new file mode 100644
index 00000000..c9377f84
--- /dev/null
+++ b/kpovmodeler/pmpattern.cpp
@@ -0,0 +1,1126 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpatternedit.h"
+#include "pmpattern.h"
+
+#include "pmxmlhelper.h"
+#include "pmlistpatternedit.h"
+#include "pmcompositeobject.h"
+#include "pmmemento.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+const PMPattern::PMPatternType patternTypeDefault = PMPattern::PatternAgate;
+const double agateTurbulenceDefault = 0.5;
+const PMVector crackleFormDefault = PMVector( -1.0, 1.0, 0.0 );
+const int crackleMetricDefault = 2;
+const double crackleOffsetDefault = 0.0;
+const bool crackleSolidDefault = false;
+const QString densityFileDefault = QString( "" );
+const int densityInterpolateDefault = 0;
+const PMVector gradientDefault = PMVector( 1.0, 1.0, 1.0 );
+const PMVector juliaComplexDefault = PMVector( 0.353, 0.288 );
+const bool fractalMagnetDefault = false;
+const int fractalMagnetTypeDefault = 1;
+const int maxIterationsDefault = 10;
+const int fractalExponentDefault = 2;
+const int fractalExtTypeDefault = 1;
+const double fractalExtFactorDefault = 1.0;
+const int fractalIntTypeDefault = 0;
+const double fractalIntFactorDefault = 1.0;
+const double quiltControl0Default = 1.0;
+const double quiltControl1Default = 1.0;
+const PMVector slopeDirectionDefault = PMVector( 0.0, -1.0, 0.0 );
+const double slopeLoSlopeDefault = 0.0;
+const double slopeHiSlopeDefault = 1.0;
+const bool slopeAltFlagDefault = false;
+const PMVector slopeAltitudeDefault = PMVector( 0.0, 1.0, 0.0 );
+const double slopeLoAltDefault = 0.0;
+const double slopeHiAltDefault = 1.0;
+const int spiralNumberArmsDefault = 0;
+const PMPattern::PMNoiseType noiseGeneratorDefault = PMPattern::GlobalSetting;
+const QString noiseGeneratorDefaultText = QString( "global_setting" );
+const bool turbulenceDefault = false;
+const PMVector valueVectorDefault = PMVector( 0.0, 0.0, 0.0 );
+const int octavesDefault = 6;
+const double omegaDefault = 0.5;
+const double lambdaDefault = 2.0;
+const double depthDefault = 0.0;
+
+PMDefinePropertyClass( PMPattern, PMPatternProperty );
+PMDefineEnumPropertyClass( PMPattern, PMPattern::PMPatternType,
+ PMPatternTypeProperty );
+PMDefineEnumPropertyClass( PMPattern, PMPattern::PMNoiseType,
+ PMNoiseProperty );
+
+PMMetaObject* PMPattern::s_pMetaObject = 0;
+PMObject* createNewPattern( PMPart* part )
+{
+ return new PMPattern( part );
+}
+
+PMPattern::PMPattern( PMPart* part )
+ : Base( part )
+{
+ m_patternType = patternTypeDefault;
+
+ m_agateTurbulence = agateTurbulenceDefault;
+
+ m_crackleForm = crackleFormDefault;
+ m_crackleMetric = crackleMetricDefault;
+ m_crackleOffset = crackleOffsetDefault;
+ m_crackleSolid = crackleSolidDefault;
+
+ m_densityFile = densityFileDefault;
+ m_densityInterpolate = densityInterpolateDefault;
+
+ m_gradient = gradientDefault;
+
+ m_juliaComplex = juliaComplexDefault;
+ m_fractalMagnet = fractalMagnetDefault;
+ m_fractalMagnetType = fractalMagnetTypeDefault;
+ m_maxIterations = maxIterationsDefault;
+ m_fractalExponent = fractalExponentDefault;
+ m_fractalExtType = fractalExtTypeDefault;
+ m_fractalExtFactor = fractalExtFactorDefault;
+ m_fractalIntType = fractalIntTypeDefault;
+ m_fractalIntFactor = fractalIntFactorDefault;
+
+ m_quiltControl0 = quiltControl0Default;
+ m_quiltControl1 = quiltControl1Default;
+
+ m_slopeDirection = slopeDirectionDefault;
+ m_slopeLoSlope = slopeLoSlopeDefault;
+ m_slopeHiSlope = slopeHiSlopeDefault;
+ m_slopeAltFlag = slopeAltFlagDefault;
+ m_slopeAltitude = slopeAltitudeDefault;
+ m_slopeLoAlt = slopeLoAltDefault;
+ m_slopeHiAlt = slopeHiAltDefault;
+
+ m_spiralNumberArms = spiralNumberArmsDefault;
+
+ m_noiseGenerator = noiseGeneratorDefault;
+
+ m_enableTurbulence = turbulenceDefault;
+ m_valueVector = valueVectorDefault;
+ m_octaves = octavesDefault;
+ m_omega = omegaDefault;
+ m_lambda = lambdaDefault;
+
+ m_depth = depthDefault;
+}
+
+PMPattern::PMPattern( const PMPattern& p )
+ : Base( p )
+{
+ m_patternType = p.m_patternType;
+
+ m_agateTurbulence = p.m_agateTurbulence;
+
+ m_crackleForm = p.m_crackleForm;
+ m_crackleMetric = p.m_crackleMetric;
+ m_crackleOffset = p.m_crackleOffset;
+ m_crackleSolid = p.m_crackleSolid;
+
+ m_densityFile = p.m_densityFile;
+ m_densityInterpolate = p.m_densityInterpolate;
+
+ m_gradient = p.m_gradient;
+
+ m_juliaComplex = p.m_juliaComplex;
+ m_fractalMagnet = p.m_fractalMagnet;
+ m_fractalMagnetType = p.m_fractalMagnetType;
+ m_maxIterations = p.m_maxIterations;
+ m_fractalExponent = p.m_fractalExponent;
+ m_fractalExtType = p.m_fractalExtType;
+ m_fractalExtFactor = p.m_fractalExtFactor;
+ m_fractalIntType = p.m_fractalIntType;
+ m_fractalIntFactor = p.m_fractalIntFactor;
+
+ m_quiltControl0 = p.m_quiltControl0;
+ m_quiltControl1 = p.m_quiltControl1;
+
+ m_slopeDirection = p.m_slopeDirection;
+ m_slopeLoSlope = p.m_slopeLoSlope;
+ m_slopeHiSlope = p.m_slopeHiSlope;
+ m_slopeAltFlag = p.m_slopeAltFlag;
+ m_slopeAltitude = p.m_slopeAltitude;
+ m_slopeLoAlt = p.m_slopeLoAlt;
+ m_slopeHiAlt = p.m_slopeHiAlt;
+
+ m_spiralNumberArms = p.m_spiralNumberArms;
+
+ m_noiseGenerator = p.m_noiseGenerator;
+
+ m_enableTurbulence = p.m_enableTurbulence;
+ m_valueVector = p.m_valueVector;
+ m_octaves = p.m_octaves;
+ m_omega = p.m_omega;
+ m_lambda = p.m_lambda;
+
+ m_depth = p.m_depth;
+}
+
+PMPattern::~PMPattern( )
+{
+}
+
+void PMPattern::serialize( QDomElement& e, QDomDocument& ) const
+{
+ switch( m_patternType )
+ {
+ case PatternAgate:
+ e.setAttribute( "patterntype", "agate" );
+ break;
+ case PatternAverage:
+ e.setAttribute( "patterntype", "average" );
+ break;
+ case PatternBoxed:
+ e.setAttribute( "patterntype", "boxed" );
+ break;
+ case PatternBozo:
+ e.setAttribute( "patterntype", "bozo" );
+ break;
+ case PatternBumps:
+ e.setAttribute( "patterntype", "bumps" );
+ break;
+ case PatternCells:
+ e.setAttribute( "patterntype", "cells" );
+ break;
+ case PatternCrackle:
+ e.setAttribute( "patterntype", "crackle" );
+ break;
+ case PatternCylindrical:
+ e.setAttribute( "patterntype", "cylindrical" );
+ break;
+ case PatternDensity:
+ e.setAttribute( "patterntype", "density" );
+ break;
+ case PatternDents:
+ e.setAttribute( "patterntype", "dents" );
+ break;
+ case PatternGradient:
+ e.setAttribute( "patterntype", "gradient" );
+ break;
+ case PatternGranite:
+ e.setAttribute( "patterntype", "granite" );
+ break;
+ case PatternJulia:
+ e.setAttribute( "patterntype", "julia" );
+ break;
+ case PatternLeopard:
+ e.setAttribute( "patterntype", "leopard" );
+ break;
+ case PatternMandel:
+ e.setAttribute( "patterntype", "mandel" );
+ break;
+ case PatternMarble:
+ e.setAttribute( "patterntype", "marble" );
+ break;
+ case PatternOnion:
+ e.setAttribute( "patterntype", "onion" );
+ break;
+ case PatternPlanar:
+ e.setAttribute( "patterntype", "planar" );
+ break;
+ case PatternQuilted:
+ e.setAttribute( "patterntype", "quilted" );
+ break;
+ case PatternRadial:
+ e.setAttribute( "patterntype", "radial" );
+ break;
+ case PatternRipples:
+ e.setAttribute( "patterntype", "ripples" );
+ break;
+ case PatternSlope:
+ e.setAttribute( "patterntype", "slope" );
+ break;
+ case PatternSpherical:
+ e.setAttribute( "patterntype", "spherical" );
+ break;
+ case PatternSpiral1:
+ e.setAttribute( "patterntype", "spiral1" );
+ break;
+ case PatternSpiral2:
+ e.setAttribute( "patterntype", "spiral2" );
+ break;
+ case PatternSpotted:
+ e.setAttribute( "patterntype", "spotted" );
+ break;
+ case PatternWaves:
+ e.setAttribute( "patterntype", "waves" );
+ break;
+ case PatternWood:
+ e.setAttribute( "patterntype", "wood" );
+ break;
+ case PatternWrinkles:
+ e.setAttribute( "patterntype", "wrinkles" );
+ break;
+ }
+
+ e.setAttribute( "agateturbulence", m_agateTurbulence );
+
+ e.setAttribute( "crackleform", m_crackleForm.serializeXML( ) );
+ e.setAttribute( "cracklemetric", m_crackleMetric );
+ e.setAttribute( "crackleoffset", m_crackleOffset );
+ e.setAttribute( "cracklesolid", m_crackleSolid );
+
+ e.setAttribute( "densityinterpolate", m_densityInterpolate );
+ e.setAttribute( "densityfile", m_densityFile );
+
+ e.setAttribute( "gradient", m_gradient.serializeXML( ) );
+
+ e.setAttribute( "juliacomplex", m_juliaComplex.serializeXML( ) );
+ e.setAttribute( "fractalmagnet", m_fractalMagnet );
+ e.setAttribute( "fractalmagnettype", m_fractalMagnetType );
+ e.setAttribute( "maxiterations", m_maxIterations );
+ e.setAttribute( "fractalexponent", m_fractalExponent );
+ e.setAttribute( "fractalexttype", m_fractalExtType );
+ e.setAttribute( "fractalextfactor", m_fractalExtFactor );
+ e.setAttribute( "fractalinttype", m_fractalIntType );
+ e.setAttribute( "fractalintfactor", m_fractalIntFactor );
+
+ e.setAttribute( "quiltcontrol0", m_quiltControl0 );
+ e.setAttribute( "quiltcontrol1", m_quiltControl1 );
+
+ e.setAttribute( "slopedirection", m_slopeDirection.serializeXML( ) );
+ e.setAttribute( "slopeloslope", m_slopeLoSlope );
+ e.setAttribute( "slopehislope", m_slopeHiSlope );
+ e.setAttribute( "slopealtflag", m_slopeAltFlag );
+ e.setAttribute( "slopealtitude", m_slopeAltitude.serializeXML( ) );
+ e.setAttribute( "slopeloalt", m_slopeLoAlt );
+ e.setAttribute( "slopehialt", m_slopeHiAlt );
+
+ e.setAttribute( "spiralnumberarms", m_spiralNumberArms );
+ switch ( m_noiseGenerator )
+ {
+ case GlobalSetting:
+ e.setAttribute( "noise_generator", "global_setting" );
+ break;
+ case Original:
+ e.setAttribute( "noise_generator", "original" );
+ break;
+ case RangeCorrected:
+ e.setAttribute( "noise_generator", "range_corrected" );
+ break;
+ case Perlin:
+ e.setAttribute( "noise_generator", "perlin" );
+ break;
+ }
+
+ e.setAttribute( "enable_turbulence", m_enableTurbulence );
+ e.setAttribute( "turbulence", m_valueVector.serializeXML( ) );
+ e.setAttribute( "octaves", m_octaves );
+ e.setAttribute( "omega", m_omega );
+ e.setAttribute( "lambda", m_lambda );
+
+ e.setAttribute( "depth", m_depth );
+}
+
+void PMPattern::readAttributes( const PMXMLHelper& h )
+{
+ QString str = h.stringAttribute( "patterntype", "agate" );
+
+ if( str == "agate" )
+ m_patternType = PatternAgate;
+ else if( str == "average" )
+ m_patternType = PatternAverage;
+ else if( str == "boxed" )
+ m_patternType = PatternBoxed;
+ else if( str == "bozo" )
+ m_patternType = PatternBozo;
+ else if( str == "bumps" )
+ m_patternType = PatternBumps;
+ else if( str == "cells" )
+ m_patternType = PatternCells;
+ else if( str == "crackle" )
+ m_patternType = PatternCrackle;
+ else if( str == "cylindrical" )
+ m_patternType = PatternCylindrical;
+ else if( str == "density" )
+ m_patternType = PatternDensity;
+ else if( str == "dents" )
+ m_patternType = PatternDents;
+ else if( str == "gradient" )
+ m_patternType = PatternGradient;
+ else if( str == "granite" )
+ m_patternType = PatternGranite;
+ else if( str == "julia" )
+ m_patternType = PatternJulia;
+ else if( str == "leopard" )
+ m_patternType = PatternLeopard;
+ else if( str == "mandel" )
+ m_patternType = PatternMandel;
+ else if( str == "marble" )
+ m_patternType = PatternMarble;
+ else if( str == "onion" )
+ m_patternType = PatternOnion;
+ else if( str == "planar" )
+ m_patternType = PatternPlanar;
+ else if( str == "quilted" )
+ m_patternType = PatternQuilted;
+ else if( str == "radial" )
+ m_patternType = PatternRadial;
+ else if( str == "ripples" )
+ m_patternType = PatternRipples;
+ else if( str == "slope" )
+ m_patternType = PatternSlope;
+ else if( str == "spherical" )
+ m_patternType = PatternSpherical;
+ else if( str == "spiral1" )
+ m_patternType = PatternSpiral1;
+ else if( str == "spiral2" )
+ m_patternType = PatternSpiral2;
+ else if( str == "spotted" )
+ m_patternType = PatternSpotted;
+ else if( str == "waves" )
+ m_patternType = PatternWaves;
+ else if( str == "wood" )
+ m_patternType = PatternWood;
+ else if( str == "wrinkles" )
+ m_patternType = PatternWrinkles;
+
+ m_agateTurbulence = h.doubleAttribute( "agateturbulence", agateTurbulenceDefault );
+
+ m_crackleForm = h.vectorAttribute( "crackleform", crackleFormDefault );
+ m_crackleMetric = h.intAttribute( "cracklemetric", crackleMetricDefault );
+ m_crackleOffset = h.doubleAttribute( "crackleoffset", crackleOffsetDefault );
+ m_crackleSolid = h.boolAttribute( "cracklesolid", crackleSolidDefault );
+
+ m_densityInterpolate = h.intAttribute( "densityinterpolate", densityInterpolateDefault );
+ m_densityFile = h.stringAttribute( "densityfile", densityFileDefault );
+
+ m_gradient = h.vectorAttribute( "gradient", gradientDefault );
+
+ m_juliaComplex = h.vectorAttribute( "juliacomplex", juliaComplexDefault );
+ m_fractalMagnet = h.boolAttribute( "fractalmagnet", fractalMagnetDefault );
+ m_fractalMagnetType = h.intAttribute( "fractalmagnettype", fractalMagnetTypeDefault );
+ m_maxIterations = h.intAttribute( "maxiterations", maxIterationsDefault );
+ m_fractalExponent = h.intAttribute( "fractalexponent", fractalExponentDefault );
+ m_fractalExtType = h.intAttribute( "fractalexttype", fractalExtTypeDefault );
+ m_fractalExtFactor = h.doubleAttribute( "fractalextfactor", fractalExtFactorDefault );
+ m_fractalIntType = h.intAttribute( "fractalinttype", fractalIntTypeDefault );
+ m_fractalIntFactor = h.doubleAttribute( "fractalintfactor", fractalIntFactorDefault );
+
+ m_quiltControl0 = h.doubleAttribute( "quiltcontrol0", quiltControl0Default );
+ m_quiltControl1 = h.doubleAttribute( "quiltcontrol1", quiltControl1Default );
+
+ m_slopeDirection = h.vectorAttribute( "slopedirection", slopeDirectionDefault );
+ m_slopeLoSlope = h.doubleAttribute( "slopeloslope", slopeLoSlopeDefault );
+ m_slopeHiSlope = h.doubleAttribute( "slopehislope", slopeHiSlopeDefault );
+ m_slopeAltFlag = h.boolAttribute( "slopealtflag", slopeAltFlagDefault );
+ m_slopeAltitude = h.vectorAttribute( "slopealtitude", slopeAltitudeDefault );
+ m_slopeLoAlt = h.doubleAttribute( "slopeloalt", slopeLoAltDefault );
+ m_slopeHiAlt = h.doubleAttribute( "slopehialt", slopeHiAltDefault );
+
+ m_spiralNumberArms = h.intAttribute( "spiralnumberarms", spiralNumberArmsDefault );
+
+ str = h.stringAttribute( "noise_generator", noiseGeneratorDefaultText );
+ if ( str == "original" )
+ m_noiseGenerator = Original;
+ else if ( str == "range_corrected" )
+ m_noiseGenerator = RangeCorrected;
+ else if ( str == "perlin" )
+ m_noiseGenerator = Perlin;
+ else
+ m_noiseGenerator = GlobalSetting;
+
+ m_enableTurbulence = h.boolAttribute( "enable_turbulence" , false );
+ m_valueVector = h.vectorAttribute( "turbulence", valueVectorDefault );
+ m_octaves = h.intAttribute( "octaves", octavesDefault );
+ m_omega = h.doubleAttribute( "omega", omegaDefault );
+ m_lambda = h.doubleAttribute( "lambda", lambdaDefault );
+
+ m_depth = h.doubleAttribute( "depth", depthDefault );
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMPattern::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Pattern", Base::metaObject( ),
+ createNewPattern );
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "agateTurbulence", &PMPattern::setAgateTurbulence, &PMPattern::agateTurbulence ) );
+
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "densityFile", &PMPattern::setDensityFile, &PMPattern::densityFile ) );
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "densityInterpolate", &PMPattern::setDensityInterpolate, &PMPattern::densityInterpolate ) );
+
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "gradient", &PMPattern::setGradient, &PMPattern::gradient ) );
+
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "maxIterations", &PMPattern::setMaxIterations, &PMPattern::maxIterations ) );
+
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "quiltControl0", &PMPattern::setQuiltControl0, &PMPattern::quiltControl0 ) );
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "quiltControl1", &PMPattern::setQuiltControl1, &PMPattern::quiltControl1 ) );
+
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "spiralNumberArms", &PMPattern::setSpiralNumberArms, &PMPattern::spiralNumberArms ) );
+
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "turbulence", &PMPattern::enableTurbulence, &PMPattern::isTurbulenceEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "valueVector", &PMPattern::setValueVector, &PMPattern::valueVector ) );
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "octaves", &PMPattern::setOctaves, &PMPattern::octaves ) );
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "omega", &PMPattern::setOmega, &PMPattern::omega ) );
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "lambda", &PMPattern::setLambda, &PMPattern::lambda ) );
+
+ s_pMetaObject->addProperty(
+ new PMPatternProperty( "depth", &PMPattern::setDepth, &PMPattern::depth ) );
+
+ PMPatternTypeProperty* p = new PMPatternTypeProperty(
+ "patternType", &PMPattern::setPatternType, &PMPattern::patternType );
+ p->addEnumValue( "Agate", PatternAgate );
+ p->addEnumValue( "Average", PatternAverage );
+ p->addEnumValue( "Boxed", PatternBoxed );
+ p->addEnumValue( "Bozo", PatternBozo );
+ p->addEnumValue( "Bumps", PatternBumps );
+ p->addEnumValue( "Cells", PatternCells );
+ p->addEnumValue( "Crackle", PatternCrackle );
+ p->addEnumValue( "Cylindrical", PatternCylindrical );
+ p->addEnumValue( "Density", PatternDensity );
+ p->addEnumValue( "Dents", PatternDents );
+ p->addEnumValue( "Gradient", PatternGradient );
+ p->addEnumValue( "Granite", PatternGranite );
+ p->addEnumValue( "Julia", PatternJulia );
+ p->addEnumValue( "Leopard", PatternLeopard );
+ p->addEnumValue( "Mandel", PatternMandel );
+ p->addEnumValue( "Marble", PatternMarble );
+ p->addEnumValue( "Onion", PatternOnion );
+ p->addEnumValue( "Planar", PatternPlanar );
+ p->addEnumValue( "Quilted", PatternQuilted );
+ p->addEnumValue( "Radial", PatternRadial );
+ p->addEnumValue( "Ripples", PatternRipples );
+ p->addEnumValue( "Slope", PatternSlope );
+ p->addEnumValue( "Spherical", PatternSpherical );
+ p->addEnumValue( "Spiral1", PatternSpiral1 );
+ p->addEnumValue( "Spiral2", PatternSpiral2 );
+ p->addEnumValue( "Spotted", PatternSpotted );
+ p->addEnumValue( "Waves", PatternWaves );
+ p->addEnumValue( "Wood", PatternWood );
+ p->addEnumValue( "Wrinkles", PatternWrinkles );
+ s_pMetaObject->addProperty( p );
+
+ PMNoiseProperty* p2 = new PMNoiseProperty(
+ "noiseGenerator", &PMPattern::setNoiseGenerator, &PMPattern::noiseGenerator );
+ p2->addEnumValue( "GlobalSetting", GlobalSetting );
+ p2->addEnumValue( "Original", Original );
+ p2->addEnumValue( "RangeCorrected", RangeCorrected );
+ p2->addEnumValue( "Perlin", Perlin );
+ s_pMetaObject->addProperty( p2 );
+ }
+ return s_pMetaObject;
+}
+
+void PMPattern::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMPattern::description( ) const
+{
+ return i18n( "pattern" );
+}
+
+void PMPattern::setPatternType( PMPatternType c )
+{
+ if( c != m_patternType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPatternTypeID, m_patternType );
+ m_patternType = c;
+ }
+}
+
+void PMPattern::setAgateTurbulence( double c )
+{
+ if( c != m_agateTurbulence )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAgateTurbulenceID, m_agateTurbulence );
+ m_agateTurbulence = c;
+ }
+}
+
+void PMPattern::setCrackleForm( const PMVector& v )
+{
+ if ( v != m_crackleForm )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCrackleFormID, m_crackleForm );
+ m_crackleForm = v;
+ }
+}
+
+void PMPattern::setCrackleMetric( int c )
+{
+ if ( c < 1 )
+ {
+ kdError( PMArea ) << "new metric is < 1 in PMPattern::setCrackleMetric\n";
+ c = 1;
+ }
+
+ if ( c != m_crackleMetric )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCrackleMetricID, m_crackleMetric );
+ m_crackleMetric = c;
+ }
+}
+
+void PMPattern::setCrackleOffset( double c )
+{
+ if ( c != m_crackleOffset )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCrackleOffsetID, m_crackleOffset );
+ m_crackleOffset = c;
+ }
+}
+
+void PMPattern::setCrackleSolid( bool c )
+{
+ if ( c != m_crackleSolid )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCrackleSolidID, m_crackleSolid );
+ m_crackleSolid = c;
+ }
+}
+
+void PMPattern::setDensityInterpolate( int c )
+{
+ if( c != m_densityInterpolate )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDensityInterpolateID, m_densityInterpolate );
+ m_densityInterpolate = c;
+ }
+}
+
+void PMPattern::setDensityFile( const QString& s )
+{
+ if( s != m_densityFile )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDensityFileID, m_densityFile );
+ m_densityFile = s;
+ }
+}
+
+void PMPattern::setGradient( const PMVector& v )
+{
+ if( v != m_gradient )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMGradientID, m_gradient );
+ m_gradient = v;
+ }
+}
+
+void PMPattern::setJuliaComplex( const PMVector& v )
+{
+ if ( v != m_juliaComplex )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMJuliaComplexID, m_juliaComplex );
+ m_juliaComplex = v;
+ }
+}
+
+void PMPattern::setFractalMagnet( bool c )
+{
+ if ( c != m_fractalMagnet )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFractalMagnetID, m_fractalMagnet );
+ m_fractalMagnet = c;
+ }
+}
+
+void PMPattern::setFractalMagnetType( int c )
+{
+ if ( c < 1 )
+ {
+ kdError( PMArea ) << "Magnet type < 1 in PMPattern::setFractalMagnetType\n";
+ c = 1;
+ }
+
+ if ( c > 2 )
+ {
+ kdError( PMArea ) << "Magnet type > 2 in PMPattern::setFractalMagnetType\n";
+ c = 2;
+ }
+
+ if ( c != m_fractalMagnetType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFractalMagnetTypeID, m_fractalMagnetType );
+ m_fractalMagnetType = c;
+ }
+}
+
+void PMPattern::setMaxIterations( int c )
+{
+ if( c != m_maxIterations )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMaxIterationsID, m_maxIterations );
+ m_maxIterations = c;
+ }
+}
+
+void PMPattern::setFractalExponent( int c )
+{
+ if ( c < 2 )
+ {
+ kdError( PMArea ) << "Exponent < 2 in PMPattern::setFractalExponent\n";
+ c = 2;
+ }
+
+ if ( c > 33 )
+ {
+ kdError( PMArea ) << "Exponent > 33 in PMPattern::setFractalExponent\n";
+ c = 33;
+ }
+
+ if ( c != m_fractalExponent )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFractalExponentID, m_fractalExponent );
+ m_fractalExponent = c;
+ }
+}
+
+void PMPattern::setFractalExtType( int c )
+{
+ if ( c < 0 )
+ {
+ kdError( PMArea ) << "Exterior Type < 0 in PMPattern::setFractalExtType\n";
+ c = 0;
+ }
+
+ if ( c > 6 )
+ {
+ kdError( PMArea ) << "Exterior Type > 6 in PMPattern::setFractalExtType\n";
+ c = 6;
+ }
+
+ if ( c != m_fractalExtType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFractalExtTypeID, m_fractalExtType );
+ m_fractalExtType = c;
+ }
+}
+
+void PMPattern::setFractalExtFactor( double c )
+{
+ if ( c != m_fractalExtFactor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFractalExtFactorID, m_fractalExtFactor );
+ m_fractalExtFactor = c;
+ }
+}
+
+void PMPattern::setFractalIntType( int c )
+{
+ if ( c < 0 )
+ {
+ kdError( PMArea ) << "Interior Type < 0 in PMPattern::setFractalIntType\n";
+ c = 0;
+ }
+
+ if ( c > 6 )
+ {
+ kdError( PMArea ) << "Interior Type > 6 in PMPattern::setFractalIntType\n";
+ c = 6;
+ }
+
+ if ( c != m_fractalIntType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFractalIntTypeID, m_fractalIntType );
+ m_fractalIntType = c;
+ }
+}
+
+void PMPattern::setFractalIntFactor( double c )
+{
+ if ( c != m_fractalIntFactor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFractalIntFactorID, m_fractalIntFactor );
+ m_fractalIntFactor = c;
+ }
+}
+
+void PMPattern::setQuiltControl0( double c )
+{
+ if( c != m_quiltControl0 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMQuiltControl0ID, m_quiltControl0 );
+ m_quiltControl0 = c;
+ }
+}
+
+void PMPattern::setQuiltControl1( double c )
+{
+ if( c != m_quiltControl1 )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMQuiltControl1ID, m_quiltControl1 );
+ m_quiltControl1 = c;
+ }
+}
+
+void PMPattern::setSlopeDirection( const PMVector& v )
+{
+ if ( v != m_slopeDirection )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSlopeDirectionID, m_slopeDirection );
+ m_slopeDirection = v;
+ }
+}
+
+void PMPattern::setSlopeLoSlope( double c )
+{
+ if ( c < 0.0 )
+ {
+ kdError( PMArea ) << "Low slope < 0.0 in PMPattern::setSlopeLoSlope\n";
+ c = 0.0;
+ }
+
+ if ( c > 1.0 )
+ {
+ kdError( PMArea ) << "Low slope > 1.0 in PMPattern::setSlopeLoSlope\n";
+ c = 1.0;
+ }
+
+ if ( c != m_slopeLoSlope )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSlopeLoSlopeID, m_slopeLoSlope );
+ m_slopeLoSlope = c;
+ }
+}
+
+void PMPattern::setSlopeHiSlope( double c )
+{
+ if ( c < 0.0 )
+ {
+ kdError( PMArea ) << "High slope < 0.0 in PMPattern::setSlopeHiSlope\n";
+ c = 0.0;
+ }
+
+ if ( c > 1.0 )
+ {
+ kdError( PMArea ) << "High slope > 1.0 in PMPattern::setSlopeHiSlope\n";
+ c = 1.0;
+ }
+
+ if ( c != m_slopeHiSlope )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSlopeHiSlopeID, m_slopeHiSlope );
+ m_slopeHiSlope = c;
+ }
+}
+
+void PMPattern::setSlopeAltFlag( bool c )
+{
+ if ( c != m_slopeAltFlag )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSlopeAltFlagID, m_slopeAltFlag );
+ m_slopeAltFlag = c;
+ }
+}
+
+void PMPattern::setSlopeAltitude( const PMVector& v )
+{
+ if ( v != m_slopeAltitude )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSlopeAltitudeID, m_slopeAltitude );
+ m_slopeAltitude = v;
+ }
+}
+
+void PMPattern::setSlopeLoAlt( double c )
+{
+ if ( c != m_slopeLoAlt )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSlopeLoAltID, m_slopeLoAlt );
+ m_slopeLoAlt = c;
+ }
+}
+
+void PMPattern::setSlopeHiAlt( double c )
+{
+ if ( c != m_slopeHiAlt )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSlopeHiAltID, m_slopeHiAlt );
+ m_slopeHiAlt = c;
+ }
+}
+
+void PMPattern::setSpiralNumberArms( int c )
+{
+ if( c != m_spiralNumberArms )
+ {
+ if(m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSpiralNumberArmsID, m_spiralNumberArms );
+ m_spiralNumberArms = c;
+ }
+}
+
+void PMPattern::setNoiseGenerator( PMNoiseType c )
+{
+ if( c != m_noiseGenerator )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNoiseGeneratorID, m_noiseGenerator );
+ m_noiseGenerator = c;
+ }
+}
+
+void PMPattern::enableTurbulence( bool c )
+{
+ if( c != m_enableTurbulence )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableTurbulenceID, m_enableTurbulence );
+ m_enableTurbulence = c;
+ }
+}
+
+void PMPattern::setValueVector( const PMVector& c )
+{
+ if( c != m_valueVector )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMValueVectorID, m_valueVector );
+ m_valueVector = c;
+ }
+}
+
+void PMPattern::setOctaves( const int c )
+{
+ if( c != m_octaves )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOctavesID, m_octaves );
+ m_octaves = c;
+ }
+}
+
+void PMPattern::setOmega( const double c )
+{
+ if( c != m_omega )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOmegaID, m_omega );
+ m_omega = c;
+ }
+}
+
+void PMPattern::setLambda( const double c )
+{
+ if( c != m_lambda )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLambdaID, m_lambda );
+ m_lambda = c;
+ }
+}
+
+void PMPattern::setDepth( const double c )
+{
+ if( c != m_depth )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDepthID, m_depth );
+ m_depth = c;
+ }
+}
+
+PMDialogEditBase* PMPattern::editWidget( QWidget* parent ) const
+{
+ return new PMPatternEdit( parent );
+}
+
+void PMPattern::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMPatternTypeID:
+ setPatternType( ( PMPatternType )data->intData( ) );
+ break;
+
+ case PMAgateTurbulenceID:
+ setAgateTurbulence( data->doubleData( ) );
+ break;
+
+ case PMCrackleFormID:
+ setCrackleForm( data->vectorData( ) );
+ break;
+ case PMCrackleMetricID:
+ setCrackleMetric( data->intData( ) );
+ break;
+ case PMCrackleOffsetID:
+ setCrackleOffset( data->doubleData( ) );
+ break;
+ case PMCrackleSolidID:
+ setCrackleSolid( data->boolData( ) );
+ break;
+
+ case PMDensityInterpolateID:
+ setDensityInterpolate( data->intData( ) );
+ break;
+ case PMDensityFileID:
+ setDensityFile( data->stringData( ) );
+ break;
+
+ case PMGradientID:
+ setGradient( data->vectorData( ) );
+ break;
+
+ case PMJuliaComplexID:
+ setJuliaComplex( data->vectorData( ) );
+ break;
+ case PMFractalMagnetID:
+ setFractalMagnet( data->boolData( ) );
+ break;
+ case PMFractalMagnetTypeID:
+ setFractalMagnetType( data->intData( ) );
+ break;
+ case PMMaxIterationsID:
+ setMaxIterations( data->intData( ) );
+ break;
+ case PMFractalExponentID:
+ setFractalExponent( data->intData( ) );
+ break;
+ case PMFractalExtTypeID:
+ setFractalExtType( data->intData( ) );
+ break;
+ case PMFractalExtFactorID:
+ setFractalExtFactor( data->doubleData( ) );
+ break;
+ case PMFractalIntTypeID:
+ setFractalIntType( data->intData( ) );
+ break;
+ case PMFractalIntFactorID:
+ setFractalIntFactor( data->doubleData( ) );
+ break;
+
+ case PMQuiltControl0ID:
+ setQuiltControl0( data->doubleData( ) );
+ break;
+ case PMQuiltControl1ID:
+ setQuiltControl1( data->doubleData( ) );
+ break;
+
+ case PMSlopeDirectionID:
+ setSlopeDirection( data->vectorData( ) );
+ break;
+ case PMSlopeLoSlopeID:
+ setSlopeLoSlope( data->doubleData( ) );
+ break;
+ case PMSlopeHiSlopeID:
+ setSlopeHiSlope( data->doubleData( ) );
+ break;
+ case PMSlopeAltFlagID:
+ setSlopeAltFlag( data->boolData( ) );
+ break;
+ case PMSlopeAltitudeID:
+ setSlopeAltitude( data->boolData( ) );
+ break;
+ case PMSlopeLoAltID:
+ setSlopeLoAlt( data->intData( ) );
+ break;
+ case PMSlopeHiAltID:
+ setSlopeHiAlt( data->intData( ) );
+ break;
+
+ case PMSpiralNumberArmsID:
+ setSpiralNumberArms( data->intData( ) );
+ break;
+
+ case PMNoiseGeneratorID:
+ setNoiseGenerator( ( PMNoiseType ) ( data->intData( ) ) );
+ break;
+
+ case PMEnableTurbulenceID:
+ enableTurbulence( data->boolData( ) );
+ break;
+ case PMValueVectorID:
+ setValueVector( data->vectorData( ) );
+ break;
+ case PMOctavesID:
+ setOctaves( data->intData( ) );
+ break;
+ case PMOmegaID:
+ setOmega( data->doubleData( ) );
+ break;
+ case PMLambdaID:
+ setLambda( data->doubleData( ) );
+ break;
+
+ case PMDepthID:
+ setDepth( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMPattern::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmpattern.h b/kpovmodeler/pmpattern.h
new file mode 100644
index 00000000..69001a41
--- /dev/null
+++ b/kpovmodeler/pmpattern.h
@@ -0,0 +1,449 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPATTERN_H
+#define PMPATTERN_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+#include "pmvector.h"
+#include "pmcolor.h"
+
+#include <qvaluelist.h>
+#include <qvaluestack.h>
+
+/**
+ * Class for povray patterns.
+ */
+class PMPattern : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * The type of the pattern
+ */
+ enum PMPatternType { PatternAgate, PatternAverage, PatternBoxed,
+ PatternBozo, PatternBumps, PatternCells,
+ PatternCrackle, PatternCylindrical, PatternDensity,
+ PatternDents, PatternGradient, PatternGranite,
+ PatternJulia, PatternLeopard, PatternMandel,
+ PatternMarble, PatternOnion, PatternPlanar,
+ PatternQuilted, PatternRadial, PatternRipples,
+ PatternSlope, PatternSpherical, PatternSpiral1,
+ PatternSpiral2, PatternSpotted, PatternWaves,
+ PatternWood, PatternWrinkles };
+ /**
+ * The noise generators
+ */
+ enum PMNoiseType { GlobalSetting, Original, RangeCorrected, Perlin };
+ /**
+ * Creates a PMPattern
+ */
+ PMPattern( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPattern( const PMPattern& p );
+ /**
+ * deletes the PMPattern
+ */
+ virtual ~PMPattern( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPattern( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmpattern" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMPatternEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+
+ /**
+ * Gets the pattern type
+ */
+ PMPatternType patternType( ) const { return m_patternType; }
+ /**
+ * Gets the agate Turbulence*/
+ double agateTurbulence( ) const { return m_agateTurbulence; }
+ /**
+ * Gets the crackle form
+ */
+ PMVector crackleForm( ) const { return m_crackleForm; }
+ /**
+ * Gets the crackle metric
+ */
+ int crackleMetric( ) const { return m_crackleMetric; }
+ /**
+ * Gets the crackle offset
+ */
+ double crackleOffset( ) const { return m_crackleOffset; }
+ /**
+ * Gets the crackle solid flag
+ */
+ bool crackleSolid( ) const { return m_crackleSolid; }
+ /**
+ * Gets the desity file name
+ */
+ QString densityFile( ) const { return m_densityFile; }
+ /**
+ * Gets the density interpolation
+ */
+ int densityInterpolate( ) const { return m_densityInterpolate; }
+ /**
+ * Gets the gradint vector
+ */
+ PMVector gradient( ) const { return m_gradient; }
+ /**
+ * Returns the Complex number for Julia Fractals
+ */
+ PMVector juliaComplex( ) const { return m_juliaComplex; }
+ /**
+ * Returns true if where using tha magnet types of fractals
+ */
+ bool fractalMagnet( ) const { return m_fractalMagnet; }
+ /**
+ * Returns the magnet type of a fractal
+ */
+ int fractalMagnetType( ) const { return m_fractalMagnetType; }
+ /**
+ * Gets the number of Iterations for fractals
+ */
+ int maxIterations( ) const { return m_maxIterations; }
+ /**
+ * Returns the exponent of a fractal
+ */
+ int fractalExponent( ) const { return m_fractalExponent; }
+ /**
+ * Returns the exterior type of a fractal
+ */
+ int fractalExtType( ) const { return m_fractalExtType; }
+ /**
+ * Return the exterior factor of a fractal
+ */
+ double fractalExtFactor( ) const { return m_fractalExtFactor; }
+ /**
+ * Returns the interior type of a fractal
+ */
+ int fractalIntType( ) const { return m_fractalIntType; }
+ /**
+ * Returns the interior factor of a fractal
+ */
+ double fractalIntFactor( ) const { return m_fractalIntFactor; }
+ /**
+ * Gets control0 for Quilt
+ */
+ double quiltControl0( ) const { return m_quiltControl0; }
+ /**
+ * Gets control1 for Quilt
+ */
+ double quiltControl1( ) const { return m_quiltControl1; }
+ /**
+ * Returns the slope direction
+ */
+ PMVector slopeDirection( ) const { return m_slopeDirection; }
+ /**
+ * Returns the low slope value
+ */
+ double slopeLoSlope( ) const { return m_slopeLoSlope; }
+ /**
+ * Returns the high slope value
+ */
+ double slopeHiSlope( ) const { return m_slopeHiSlope; }
+ /**
+ * Returns the slopes altitude flag
+ */
+ bool slopeAltFlag( ) const { return m_slopeAltFlag; }
+ /**
+ * Returns the altitude for the slope
+ */
+ PMVector slopeAltitude( ) const { return m_slopeAltitude; }
+ /**
+ * Returns the low altitude for slope
+ */
+ double slopeLoAltitude( ) const { return m_slopeLoAlt; }
+ /**
+ * Returns the high altitude for slope
+ */
+ double slopeHiAltitude( ) const { return m_slopeHiAlt; }
+ /**
+ * Gets the number of arms in spiral types 1 and 2
+ */
+ int spiralNumberArms( ) const { return m_spiralNumberArms; }
+ /**
+ * Returns the noise generator
+ */
+ PMNoiseType noiseGenerator( ) const { return m_noiseGenerator; };
+ /**
+ * Returns whether turbulence is enabled
+ */
+ bool isTurbulenceEnabled( ) const { return m_enableTurbulence; }
+ /**
+ * Gets the Turbulence vector
+ */
+ PMVector valueVector( ) const { return m_valueVector; }
+ /**
+ * Gets the turbulence octaves
+ */
+ int octaves( ) const { return m_octaves; }
+ /**
+ * Gets the turbulence omega
+ */
+ double omega( ) const { return m_omega; }
+ /**
+ * Gets the turbulence lambda
+ */
+ double lambda( ) const { return m_lambda; }
+ /**
+ * Returns depth (only has meaning inside a normal)
+ */
+ double depth( ) const { return m_depth; }
+
+ /**
+ * Sets the pattern type
+ */
+ void setPatternType( PMPatternType l );
+ /**
+ * Sets agate turbulence
+ */
+ void setAgateTurbulence( double c );
+ /**
+ * Sets the crackle form
+ */
+ void setCrackleForm( const PMVector& v );
+ /**
+ * Sets the crackle metric
+ */
+ void setCrackleMetric( int c );
+ /**
+ * Sets the crackle offset
+ */
+ void setCrackleOffset( double c );
+ /**
+ * Sets the crackle solid flag
+ */
+ void setCrackleSolid( bool c );
+ /**
+ * Sets the Density File Name
+ */
+ void setDensityFile( const QString& v );
+ /**
+ * Sets the density interpolation
+ */
+ void setDensityInterpolate( int c );
+ /**
+ * sets gradient vector
+ */
+ void setGradient( const PMVector& v );
+ /**
+ * Sets the complex number for Julia
+ */
+ void setJuliaComplex( const PMVector& v );
+ /**
+ * Sets if where using magnet types of fractals
+ */
+ void setFractalMagnet( bool c );
+ /**
+ * Sets the magnet type of a fractal
+ */
+ void setFractalMagnetType( int c );
+ /**
+ * Sets the maximum iterations for fractals
+ */
+ void setMaxIterations( int c );
+ /**
+ * Sets the exponent for fractals
+ */
+ void setFractalExponent( int c );
+ /**
+ * Sets the exterior type of fractals
+ */
+ void setFractalExtType( int c );
+ /**
+ * Sets the exterior factor of fractals
+ */
+ void setFractalExtFactor( double c );
+ /**
+ * Sets the interior type of fractals
+ */
+ void setFractalIntType( int c );
+ /**
+ * Sets the interior factor of fractals
+ */
+ void setFractalIntFactor( double c );
+ /**
+ * Sets quilt control 0
+ */
+ void setQuiltControl0( double c );
+ /**
+ * Sets quite control 1
+ */
+ void setQuiltControl1( double c );
+ /**
+ * Sets the slope direction
+ */
+ void setSlopeDirection( const PMVector& v );
+ /**
+ * Sets the low slope value
+ */
+ void setSlopeLoSlope( double c );
+ /**
+ * Sets the high slope value
+ */
+ void setSlopeHiSlope( double c );
+ /**
+ * Sets the slopes altitude flag
+ */
+ void setSlopeAltFlag( bool c );
+ /**
+ * Sets the slopes alititude direction
+ */
+ void setSlopeAltitude( const PMVector& v );
+ /**
+ * Sets the slopes low altitude
+ */
+ void setSlopeLoAlt( double c );
+ /**
+ * Sets the slopes high altitude
+ */
+ void setSlopeHiAlt( double c );
+ /**
+ * Sets the number of spiral arms
+ */
+ void setSpiralNumberArms( int c );
+ /**
+ * Sets noise generator
+ */
+ void setNoiseGenerator( PMNoiseType c );
+ /**
+ * Enables turbulence
+ */
+ void enableTurbulence( bool c );
+ /**
+ * sets the turbulence vector
+ */
+ void setValueVector( const PMVector& v );
+ /**
+ * Sets the turbulence octaves
+ */
+ void setOctaves( int c );
+ /**
+ * Sets the turblence omega
+ */
+ void setOmega( double c );
+ /**
+ * Sets the turbulence Lambda
+ */
+ void setLambda( double c );
+ /**
+ * Sets the depth value (only inside normals)
+ */
+ void setDepth( double c );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMPatternMementoID { PMPatternTypeID, PMAgateTurbulenceID, PMCrackleFormID,
+ PMCrackleMetricID, PMCrackleOffsetID, PMCrackleSolidID,
+ PMDensityFileID, PMDensityInterpolateID, PMGradientID,
+ PMJuliaComplexID, PMFractalMagnetID, PMFractalMagnetTypeID,
+ PMMaxIterationsID, PMFractalExponentID, PMFractalExtTypeID,
+ PMFractalExtFactorID, PMFractalIntTypeID, PMFractalIntFactorID,
+ PMQuiltControl0ID, PMQuiltControl1ID, PMSlopeDirectionID,
+ PMSlopeLoSlopeID, PMSlopeHiSlopeID, PMSlopeAltFlagID,
+ PMSlopeAltitudeID, PMSlopeLoAltID, PMSlopeHiAltID,
+ PMSpiralNumberArmsID, PMNoiseGeneratorID, PMEnableTurbulenceID,
+ PMValueVectorID, PMOctavesID, PMOmegaID, PMLambdaID, PMDepthID };
+ /**
+ * Pattern type
+ */
+ PMPatternType m_patternType;
+
+ // Extra values for Individual Patterns
+ // Agate
+ double m_agateTurbulence;
+ // crackle
+ PMVector m_crackleForm;
+ int m_crackleMetric;
+ double m_crackleOffset;
+ bool m_crackleSolid;
+ // density
+ QString m_densityFile;
+ int m_densityInterpolate;
+ // gradient
+ PMVector m_gradient;
+ // Julia
+ PMVector m_juliaComplex;
+ // Fractal patterns Mandel and Julia
+ bool m_fractalMagnet;
+ int m_fractalMagnetType;
+ int m_maxIterations;
+ int m_fractalExponent;
+ int m_fractalExtType;
+ double m_fractalExtFactor;
+ int m_fractalIntType;
+ double m_fractalIntFactor;
+ // quilt
+ double m_quiltControl0;
+ double m_quiltControl1;
+ // slope
+ PMVector m_slopeDirection;
+ double m_slopeLoSlope;
+ double m_slopeHiSlope;
+ bool m_slopeAltFlag;
+ PMVector m_slopeAltitude;
+ double m_slopeLoAlt;
+ double m_slopeHiAlt;
+ // Spiral
+ int m_spiralNumberArms;
+
+ // noise generator type for Bozo, Bumps, Granite and Wrinkles.
+ PMNoiseType m_noiseGenerator;
+
+ // Turbulence available for all patterns
+ bool m_enableTurbulence;
+ PMVector m_valueVector;
+ int m_octaves;
+ double m_omega;
+ double m_lambda;
+ // depth when used with Normal
+ double m_depth;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmpatternedit.cpp b/kpovmodeler/pmpatternedit.cpp
new file mode 100644
index 00000000..1f9647c2
--- /dev/null
+++ b/kpovmodeler/pmpatternedit.cpp
@@ -0,0 +1,1073 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpatternedit.h"
+#include "pmpattern.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmvector.h"
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <ktabctl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+
+PMPatternEdit::PMPatternEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMPatternEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QGridLayout* layout;
+ QHBoxLayout* hl;
+ QVBoxLayout* vl;
+ QGridLayout* gl;
+
+ layout = new QGridLayout( topLayout( ), 12, 2 );
+ hl = new QHBoxLayout( KDialog::spacingHint( ) );
+ hl->addWidget( new QLabel( i18n( "Type:" ), this ) );
+ m_pTypeCombo = new QComboBox( false, this );
+ m_pTypeCombo->insertItem( i18n( "Agate" ) );
+ m_pTypeCombo->insertItem( i18n( "Average" ) );
+ m_pTypeCombo->insertItem( i18n( "Boxed" ) );
+ m_pTypeCombo->insertItem( i18n( "Bozo" ) );
+ m_pTypeCombo->insertItem( i18n( "Bumps" ) );
+ m_pTypeCombo->insertItem( i18n( "Cells" ) );
+ m_pTypeCombo->insertItem( i18n( "Crackle" ) );
+ m_pTypeCombo->insertItem( i18n( "Cylindrical" ) );
+ m_pTypeCombo->insertItem( i18n( "Density File" ) );
+ m_pTypeCombo->insertItem( i18n( "Dents" ) );
+ m_pTypeCombo->insertItem( i18n( "Gradient" ) );
+ m_pTypeCombo->insertItem( i18n( "Granite" ) );
+ m_pTypeCombo->insertItem( i18n( "Julia" ) );
+ m_pTypeCombo->insertItem( i18n( "Leopard" ) );
+ m_pTypeCombo->insertItem( i18n( "Mandel" ) );
+ m_pTypeCombo->insertItem( i18n( "Marble" ) );
+ m_pTypeCombo->insertItem( i18n( "Onion" ) );
+ m_pTypeCombo->insertItem( i18n( "Planar" ) );
+ m_pTypeCombo->insertItem( i18n( "Quilt" ) );
+ m_pTypeCombo->insertItem( i18n( "Radial" ) );
+ m_pTypeCombo->insertItem( i18n( "Ripples" ) );
+ m_pTypeCombo->insertItem( i18n( "Slope" ) );
+ m_pTypeCombo->insertItem( i18n( "Spherical" ) );
+ m_pTypeCombo->insertItem( i18n( "Spiral1" ) );
+ m_pTypeCombo->insertItem( i18n( "Spiral2" ) );
+ m_pTypeCombo->insertItem( i18n( "Spotted" ) );
+ m_pTypeCombo->insertItem( i18n( "Waves" ) );
+ m_pTypeCombo->insertItem( i18n( "Wood" ) );
+ m_pTypeCombo->insertItem( i18n( "Wrinkles" ) );
+ hl->addWidget( m_pTypeCombo );
+ hl->addStretch( 1 );
+ layout->addMultiCellLayout( hl, 0, 0, 0, 1 );
+
+ m_pAgateTurbulenceLabel = new QLabel( i18n( "Turbulence:" ), this );
+ layout->addWidget( m_pAgateTurbulenceLabel, 1, 0 );
+ m_pAgateTurbulenceEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pAgateTurbulenceEdit, 1, 1, AlignLeft );
+
+ m_pCrackleWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pCrackleWidget, 0, KDialog::spacingHint( ) );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( new QLabel( i18n( "Form:" ), m_pCrackleWidget ) );
+ m_pCrackleForm = new PMVectorEdit( "x", "y", "z", m_pCrackleWidget );
+ hl->addWidget( m_pCrackleForm );
+ hl->addStretch( 1 );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 3, 2 );
+ gl->addWidget( new QLabel( i18n( "Metric:" ), m_pCrackleWidget ), 0, 0 );
+ m_pCrackleMetric = new PMIntEdit( m_pCrackleWidget );
+ m_pCrackleMetric->setValidation( true, 1, false, 0 );
+ gl->addWidget( m_pCrackleMetric, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Offset:" ), m_pCrackleWidget ), 1, 0 );
+ m_pCrackleOffset = new PMFloatEdit( m_pCrackleWidget );
+ gl->addWidget( m_pCrackleOffset, 1, 1 );
+ m_pCrackleSolid = new QCheckBox( i18n( "Solid:" ), m_pCrackleWidget );
+ gl->addMultiCellWidget( m_pCrackleSolid, 2, 2, 0, 1 );
+ hl->addStretch( 1 );
+ layout->addMultiCellWidget( m_pCrackleWidget, 2, 2, 0, 1 );
+
+ m_pDensityWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pDensityWidget, 0, KDialog::spacingHint( ) );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( new QLabel( i18n( "File:" ), m_pDensityWidget ) );
+ m_pDensityFile = new QLineEdit( m_pDensityWidget );
+ hl->addWidget( m_pDensityFile, 1 );
+ m_pDensityFileBrowse = new QPushButton( m_pDensityWidget );
+ m_pDensityFileBrowse->setPixmap( SmallIcon( "fileopen" ) );
+ hl->addWidget( m_pDensityFileBrowse );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( new QLabel( i18n( "Interpolation:" ), m_pDensityWidget ) );
+ m_pDensityInterpolate = new QComboBox( false, m_pDensityWidget );
+ m_pDensityInterpolate->insertItem( i18n( "None" ) );
+ m_pDensityInterpolate->insertItem( i18n( "Trilinear" ) );
+ hl->addWidget( m_pDensityInterpolate );
+ hl->addStretch( 1 );
+ layout->addMultiCellWidget( m_pDensityWidget, 3, 3, 0, 1 );
+
+ m_pGradientLabel = new QLabel( i18n( "Gradient:" ), this );
+ layout->addWidget( m_pGradientLabel, 4, 0 );
+ m_pGradientEdit = new PMVectorEdit( "x", "y", "z", this );
+ layout->addWidget( m_pGradientEdit, 4, 1 );
+
+ m_pJuliaComplexLabel = new QLabel( i18n( "Complex number:" ), this );
+ layout->addWidget( m_pJuliaComplexLabel, 5, 0 );
+ m_pJuliaComplex = new PMVectorEdit( "Real", "Imaginary", this );
+ layout->addWidget( m_pJuliaComplex, 5, 1 );
+
+ m_pFractalWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pFractalWidget, 0, KDialog::spacingHint( ) );
+ hl = new QHBoxLayout( vl );
+ m_pFractalMagnet = new QCheckBox( i18n( "Magnet" ), m_pFractalWidget );
+ hl->addWidget( m_pFractalMagnet );
+ m_pFractalMagnetType = new QComboBox( false, m_pFractalWidget );
+ m_pFractalMagnetType->insertItem( i18n( "Type 1" ) );
+ m_pFractalMagnetType->insertItem( i18n( "Type 2" ) );
+ hl->addWidget( m_pFractalMagnetType );
+ hl->addStretch( 1 );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Maximum iterations:" ), m_pFractalWidget ), 0, 0 );
+ m_pMaxIterationsEdit = new PMIntEdit( m_pFractalWidget );
+ m_pMaxIterationsEdit->setValidation( true, 1, false, 0 );
+ gl->addWidget( m_pMaxIterationsEdit, 0, 1 );
+ m_pFractalExponentLabel = new QLabel( i18n( "Exponent:" ), m_pFractalWidget );
+ gl->addWidget( m_pFractalExponentLabel, 1, 0 );
+ m_pFractalExponent = new PMIntEdit( m_pFractalWidget );
+ m_pFractalExponent->setValidation( true, 2, true, 33 );
+ gl->addWidget( m_pFractalExponent, 1, 1 );
+ hl->addStretch( 1 );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 2, 4 );
+ gl->addWidget( new QLabel( i18n( "Exterior type:" ), m_pFractalWidget ), 0, 0 );
+ m_pFractalExtType = new QComboBox( false, m_pFractalWidget );
+ m_pFractalExtType->insertItem( i18n( "0: Returns Just 1" ) );
+ m_pFractalExtType->insertItem( i18n( "1: Iterations Until Bailout" ) );
+ m_pFractalExtType->insertItem( i18n( "2: Real Part" ) );
+ m_pFractalExtType->insertItem( i18n( "3: Imaginary Part" ) );
+ m_pFractalExtType->insertItem( i18n( "4: Squared Real Part" ) );
+ m_pFractalExtType->insertItem( i18n( "5: Squared Imaginary Part" ) );
+ m_pFractalExtType->insertItem( i18n( "6: Absolute Value" ) );
+ gl->addWidget( m_pFractalExtType, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Factor:" ), m_pFractalWidget ), 0, 2 );
+ m_pFractalExtFactor = new PMFloatEdit( m_pFractalWidget );
+ gl->addWidget( m_pFractalExtFactor, 0, 3 );
+ gl->addWidget( new QLabel( i18n( "Interior type:" ), m_pFractalWidget ), 1, 0 );
+ m_pFractalIntType = new QComboBox( false, m_pFractalWidget );
+ m_pFractalIntType->insertItem( i18n( "0: Returns Just 1" ) );
+ m_pFractalIntType->insertItem( i18n( "1: Absolute Value Smallest" ) );
+ m_pFractalIntType->insertItem( i18n( "2: Real Part" ) );
+ m_pFractalIntType->insertItem( i18n( "3: Imaginary Part" ) );
+ m_pFractalIntType->insertItem( i18n( "4: Squared Real Part" ) );
+ m_pFractalIntType->insertItem( i18n( "5: Squared Imaginary Part" ) );
+ m_pFractalIntType->insertItem( i18n( "6: Absolute Value Last" ) );
+ gl->addWidget( m_pFractalIntType, 1, 1 );
+ gl->addWidget( new QLabel( i18n( "Factor:" ), m_pFractalWidget ), 1, 2 );
+ m_pFractalIntFactor = new PMFloatEdit( m_pFractalWidget );
+ gl->addWidget( m_pFractalIntFactor, 1, 3 );
+ hl->addStretch( 1 );
+ layout->addMultiCellWidget( m_pFractalWidget, 6, 6, 0, 1 );
+
+ m_pQuiltControlsLabel = new QLabel( i18n( "Quilt controls:" ), this );
+ m_pQuiltControl0Edit = new PMFloatEdit( this );
+ m_pQuiltControl1Edit = new PMFloatEdit( this );
+ hl = new QHBoxLayout( );
+ hl->addWidget( m_pQuiltControl0Edit );
+ hl->addWidget( m_pQuiltControl1Edit );
+ hl->addStretch( 1 );
+ layout->addWidget( m_pQuiltControlsLabel, 7, 0 );
+ layout->addLayout( hl, 7, 1 );
+
+ m_pSlopeWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pSlopeWidget, 0, KDialog::spacingHint( ) );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( new QLabel( i18n( "Direction:" ), m_pSlopeWidget ) );
+ m_pSlopeDirection = new PMVectorEdit( "x", "y", "z", m_pSlopeWidget );
+ hl->addWidget( m_pSlopeDirection );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Low slope:" ), m_pSlopeWidget ), 0, 0 );
+ m_pSlopeLoSlope = new PMFloatEdit( m_pSlopeWidget );
+ m_pSlopeLoSlope->setValidation( true, 0.0, true, 1.0 );
+ gl->addWidget( m_pSlopeLoSlope, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "High slope:" ), m_pSlopeWidget ), 1, 0 );
+ m_pSlopeHiSlope = new PMFloatEdit( m_pSlopeWidget );
+ m_pSlopeHiSlope->setValidation( true, 0.0, true, 1.0 );
+ gl->addWidget( m_pSlopeHiSlope, 1, 1 );
+ hl->addStretch( 1 );
+ hl = new QHBoxLayout( vl );
+ m_pSlopeAltFlag = new QCheckBox( i18n( "Altitiude" ), m_pSlopeWidget );
+ hl->addWidget( m_pSlopeAltFlag );
+ m_pSlopeAltitude = new PMVectorEdit( "x", "y", "z", m_pSlopeWidget );
+ hl->addWidget( m_pSlopeAltitude );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 2, 2 );
+ m_pSlopeLoAltLabel = new QLabel( i18n( "Low altitude:" ), m_pSlopeWidget );
+ gl->addWidget( m_pSlopeLoAltLabel, 0, 0 );
+ m_pSlopeLoAlt = new PMFloatEdit( m_pSlopeWidget );
+ gl->addWidget( m_pSlopeLoAlt, 0, 1 );
+ m_pSlopeHiAltLabel = new QLabel( i18n( "High altitude:" ), m_pSlopeWidget );
+ gl->addWidget( m_pSlopeHiAltLabel, 1, 0 );
+ m_pSlopeHiAlt = new PMFloatEdit( m_pSlopeWidget );
+ gl->addWidget( m_pSlopeHiAlt, 1, 1 );
+ hl->addStretch( 1 );
+ layout->addMultiCellWidget( m_pSlopeWidget, 8, 8, 0, 1 );
+
+ m_pSpiralNumberLabel = new QLabel( i18n( "Spiral number:" ), this );
+ m_pSpiralNumberEdit = new PMIntEdit( this );
+ layout->addWidget( m_pSpiralNumberLabel, 9, 0 );
+ layout->addWidget( m_pSpiralNumberEdit, 9, 1, AlignLeft );
+
+ m_pDepthLabel = new QLabel( i18n( "Depth:" ), this );
+ m_pDepthEdit = new PMFloatEdit( this );
+ layout->addWidget( m_pDepthLabel, 10, 0 );
+ layout->addWidget( m_pDepthEdit, 10, 1, AlignLeft );
+
+ m_pNoiseGeneratorLabel = new QLabel( i18n( "Noise generator:" ), this );
+ m_pNoiseGenerator = new QComboBox( false, this );
+ m_pNoiseGenerator->insertItem( i18n( "Use Global Setting" ) );
+ m_pNoiseGenerator->insertItem( i18n( "Original" ) );
+ m_pNoiseGenerator->insertItem( i18n( "Range Corrected" ) );
+ m_pNoiseGenerator->insertItem( i18n( "Perlin" ) );
+ layout->addWidget( m_pNoiseGeneratorLabel, 11, 0 );
+ layout->addWidget( m_pNoiseGenerator, 11, 1 );
+
+ m_pEnableTurbulenceEdit = new QCheckBox( i18n( "Turbulence" ), this );
+ topLayout( )->addWidget( m_pEnableTurbulenceEdit );
+ m_pTurbulenceWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pTurbulenceWidget, 0, KDialog::spacingHint( ) );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( new QLabel( i18n( "Value:" ), m_pTurbulenceWidget ) );
+ m_pValueVectorEdit = new PMVectorEdit( "x", "y", "z", m_pTurbulenceWidget );
+ hl->addWidget( m_pValueVectorEdit );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 3, 2 );
+ gl->addWidget( new QLabel( i18n( "Octaves:" ), m_pTurbulenceWidget ), 0, 0 );
+ m_pOctavesEdit = new PMIntEdit( m_pTurbulenceWidget );
+ gl->addWidget( m_pOctavesEdit, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Omega:" ), m_pTurbulenceWidget ), 1, 0 );
+ m_pOmegaEdit = new PMFloatEdit( m_pTurbulenceWidget );
+ gl->addWidget( m_pOmegaEdit, 1, 1 );
+ gl->addWidget( new QLabel( i18n( "Lambda:" ), m_pTurbulenceWidget ), 2, 0 );
+ m_pLambdaEdit = new PMFloatEdit( m_pTurbulenceWidget );
+ gl->addWidget( m_pLambdaEdit, 2, 1 );
+ hl->addStretch( 1 );
+ topLayout( )->addWidget( m_pTurbulenceWidget );
+
+ /* connect all signals to slots/signals */
+ connect( m_pTypeCombo, SIGNAL( activated( int ) ), SLOT( slotComboChanged( int ) ) );
+
+ connect( m_pAgateTurbulenceEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pCrackleForm, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCrackleMetric, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCrackleOffset, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCrackleSolid, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pDensityInterpolate, SIGNAL( activated( int ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDensityFile, SIGNAL( textChanged( const QString& ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDensityFileBrowse, SIGNAL( clicked( ) ), SLOT( slotDensityFileBrowseClicked( ) ) );
+
+ connect( m_pGradientEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pJuliaComplex, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFractalMagnet, SIGNAL( clicked( ) ), SLOT( slotFractalMagnetClicked( ) ) );
+ connect( m_pFractalMagnetType, SIGNAL( activated( int ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMaxIterationsEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFractalExponent, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFractalExtType, SIGNAL( activated( int ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFractalExtFactor, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFractalIntType, SIGNAL( activated( int ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFractalIntFactor, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pQuiltControl0Edit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pQuiltControl1Edit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pSlopeDirection, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSlopeLoSlope, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSlopeHiSlope, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSlopeAltFlag, SIGNAL( clicked( ) ), SLOT( slotSlopeAltFlagClicked( ) ) );
+ connect( m_pSlopeAltitude, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSlopeLoAlt, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSlopeHiAlt, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pSpiralNumberEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pNoiseGenerator, SIGNAL( activated( int ) ), SIGNAL( dataChanged( ) ) );
+
+ connect( m_pEnableTurbulenceEdit, SIGNAL( clicked( ) ), SLOT( slotTurbulenceClicked( ) ) );
+ connect( m_pValueVectorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOctavesEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOmegaEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pLambdaEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDepthEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMPatternEdit::displayObject( PMObject* o )
+{
+ QString str;
+ bool readOnly;
+
+ if( o->isA( "Pattern" ) )
+ {
+ m_pDisplayedObject = ( PMPattern* ) o;
+ readOnly = m_pDisplayedObject->isReadOnly( );
+
+ switch( m_pDisplayedObject->patternType( ) )
+ {
+ case PMPattern::PatternAgate:
+ setPatternType( 0 );
+ break;
+ case PMPattern::PatternAverage:
+ setPatternType( 1 );
+ break;
+ case PMPattern::PatternBoxed:
+ setPatternType( 2 );
+ break;
+ case PMPattern::PatternBozo:
+ setPatternType( 3 );
+ break;
+ case PMPattern::PatternBumps:
+ setPatternType( 4 );
+ break;
+ case PMPattern::PatternCells:
+ setPatternType( 5 );
+ break;
+ case PMPattern::PatternCrackle:
+ setPatternType( 6 );
+ break;
+ case PMPattern::PatternCylindrical:
+ setPatternType( 7 );
+ break;
+ case PMPattern::PatternDensity:
+ setPatternType( 8 );
+ break;
+ case PMPattern::PatternDents:
+ setPatternType( 9 );
+ break;
+ case PMPattern::PatternGradient:
+ setPatternType( 10 );
+ break;
+ case PMPattern::PatternGranite:
+ setPatternType( 11 );
+ break;
+ case PMPattern::PatternJulia:
+ setPatternType( 12 );
+ break;
+ case PMPattern::PatternLeopard:
+ setPatternType( 13 );
+ break;
+ case PMPattern::PatternMandel:
+ setPatternType( 14 );
+ break;
+ case PMPattern::PatternMarble:
+ setPatternType( 15 );
+ break;
+ case PMPattern::PatternOnion:
+ setPatternType( 16 );
+ break;
+ case PMPattern::PatternPlanar:
+ setPatternType( 17 );
+ break;
+ case PMPattern::PatternQuilted:
+ setPatternType( 18 );
+ break;
+ case PMPattern::PatternRadial:
+ setPatternType( 19 );
+ break;
+ case PMPattern::PatternRipples:
+ setPatternType( 20 );
+ break;
+ case PMPattern::PatternSlope:
+ setPatternType( 21 );
+ break;
+ case PMPattern::PatternSpherical:
+ setPatternType( 22 );
+ break;
+ case PMPattern::PatternSpiral1:
+ setPatternType( 23 );
+ break;
+ case PMPattern::PatternSpiral2:
+ setPatternType( 24 );
+ break;
+ case PMPattern::PatternSpotted:
+ setPatternType( 25 );
+ break;
+ case PMPattern::PatternWaves:
+ setPatternType( 26 );
+ break;
+ case PMPattern::PatternWood:
+ setPatternType( 27 );
+ break;
+ case PMPattern::PatternWrinkles:
+ setPatternType( 28 );
+ break;
+ }
+ m_pTypeCombo->setEnabled( !readOnly );
+
+ m_pAgateTurbulenceEdit->setValue( m_pDisplayedObject->agateTurbulence( ) );
+ m_pAgateTurbulenceEdit->setReadOnly( readOnly );
+
+ m_pCrackleForm->setVector( m_pDisplayedObject->crackleForm( ) );
+ m_pCrackleForm->setReadOnly( readOnly );
+ m_pCrackleMetric->setValue( m_pDisplayedObject->crackleMetric( ) );
+ m_pCrackleMetric->setReadOnly( readOnly );
+ m_pCrackleOffset->setValue( m_pDisplayedObject->crackleOffset( ) );
+ m_pCrackleOffset->setReadOnly( readOnly );
+ m_pCrackleSolid->setChecked( m_pDisplayedObject->crackleSolid( ) );
+ m_pCrackleSolid->setEnabled( !readOnly );
+
+ m_pDensityFile->setText( m_pDisplayedObject->densityFile( ) );
+ m_pDensityFile->setEnabled( !readOnly );
+ m_pDensityInterpolate->setCurrentItem( m_pDisplayedObject->densityInterpolate( ) );
+ m_pDensityInterpolate->setEnabled( !readOnly );
+
+ m_pGradientEdit->setVector( m_pDisplayedObject->gradient( ) );
+ m_pGradientEdit->setReadOnly( readOnly );
+
+ m_pJuliaComplex->setVector( m_pDisplayedObject->juliaComplex( ) );
+ m_pJuliaComplex->setReadOnly( readOnly );
+ m_pFractalMagnet->setChecked( m_pDisplayedObject->fractalMagnet( ) );
+ m_pFractalMagnet->setEnabled( !readOnly );
+ m_pFractalMagnetType->setCurrentItem( m_pDisplayedObject->fractalMagnetType( ) - 1 );
+ m_pFractalMagnetType->setEnabled( !readOnly );
+ m_pMaxIterationsEdit->setValue( m_pDisplayedObject->maxIterations( ) );
+ m_pMaxIterationsEdit->setReadOnly( readOnly );
+ m_pFractalExponent->setValue( m_pDisplayedObject->fractalExponent( ) );
+ m_pFractalExponent->setReadOnly( readOnly );
+ m_pFractalExtType->setCurrentItem( m_pDisplayedObject->fractalExtType( ) );
+ m_pFractalExtType->setEnabled( !readOnly );
+ m_pFractalExtFactor->setValue( m_pDisplayedObject->fractalExtFactor( ) );
+ m_pFractalExtFactor->setReadOnly( readOnly );
+ m_pFractalIntType->setCurrentItem( m_pDisplayedObject->fractalIntType( ) );
+ m_pFractalIntType->setEnabled( !readOnly );
+ m_pFractalIntFactor->setValue( m_pDisplayedObject->fractalIntFactor( ) );
+ m_pFractalIntFactor->setReadOnly( readOnly );
+
+ m_pQuiltControl0Edit->setValue( m_pDisplayedObject->quiltControl0( ) );
+ m_pQuiltControl0Edit->setReadOnly( readOnly );
+ m_pQuiltControl1Edit->setValue( m_pDisplayedObject->quiltControl1( ) );
+ m_pQuiltControl1Edit->setReadOnly( readOnly );
+
+ m_pSlopeDirection->setVector( m_pDisplayedObject->slopeDirection( ) );
+ m_pSlopeDirection->setReadOnly( readOnly );
+ m_pSlopeLoSlope->setValue( m_pDisplayedObject->slopeLoSlope( ) );
+ m_pSlopeLoSlope->setReadOnly( readOnly );
+ m_pSlopeHiSlope->setValue( m_pDisplayedObject->slopeHiSlope( ) );
+ m_pSlopeHiSlope->setReadOnly( readOnly );
+ m_pSlopeAltFlag->setChecked( m_pDisplayedObject->slopeAltFlag( ) );
+ m_pSlopeAltFlag->setEnabled( !readOnly );
+ m_pSlopeAltitude->setVector( m_pDisplayedObject->slopeAltitude( ) );
+ m_pSlopeAltitude->setReadOnly( readOnly );
+ m_pSlopeLoAlt->setValue( m_pDisplayedObject->slopeLoAltitude( ) );
+ m_pSlopeLoAlt->setReadOnly( readOnly );
+ m_pSlopeHiAlt->setValue( m_pDisplayedObject->slopeHiAltitude( ) );
+ m_pSlopeHiAlt->setReadOnly( readOnly );
+
+ m_pSpiralNumberEdit->setValue( m_pDisplayedObject->spiralNumberArms( ) );
+ m_pSpiralNumberEdit->setReadOnly( readOnly );
+
+ m_pNoiseGenerator->setCurrentItem( m_pDisplayedObject->noiseGenerator( ) );
+ m_pNoiseGenerator->setEnabled( !readOnly );
+
+ m_pEnableTurbulenceEdit->setChecked( m_pDisplayedObject->isTurbulenceEnabled( ) );
+ m_pEnableTurbulenceEdit->setEnabled( !readOnly );
+ m_pValueVectorEdit->setVector( m_pDisplayedObject->valueVector( ) );
+ m_pValueVectorEdit->setReadOnly( readOnly );
+ m_pOctavesEdit->setValue( m_pDisplayedObject->octaves( ) );
+ m_pOctavesEdit->setReadOnly( readOnly );
+ m_pOmegaEdit->setValue( m_pDisplayedObject->omega( ) );
+ m_pOmegaEdit->setReadOnly( readOnly );
+ m_pLambdaEdit->setValue( m_pDisplayedObject->lambda( ) );
+ m_pLambdaEdit->setReadOnly( readOnly );
+
+ if( o->parent( ) && ( o->parent( )->type( ) == "Normal" ) )
+ {
+ m_pDepthEdit->setValue( m_pDisplayedObject->depth( ) );
+ m_pDepthEdit->setReadOnly( readOnly );
+ m_pDepthEdit->show( );
+ m_pDepthLabel->show( );
+ emit sizeChanged( );
+ }
+ else
+ {
+ m_pDepthEdit->hide( );
+ m_pDepthLabel->hide( );
+ emit sizeChanged( );
+ }
+
+ slotFractalMagnetClicked( );
+ slotSlopeAltFlagClicked( );
+ slotTurbulenceClicked( );
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMPatternEdit: Can't display object\n";
+}
+
+void PMPatternEdit::setPatternType( int i )
+{
+ m_pTypeCombo->setCurrentItem( i );
+ slotComboChanged( i );
+}
+
+void PMPatternEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ switch( m_pTypeCombo->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternAgate );
+ m_pDisplayedObject->setAgateTurbulence( m_pAgateTurbulenceEdit->value( ) );
+ break;
+ case 1:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternAverage );
+ break;
+ case 2:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternBoxed );
+ break;
+ case 3:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternBozo );
+ m_pDisplayedObject->setNoiseGenerator(
+ ( PMPattern::PMNoiseType ) m_pNoiseGenerator->currentItem( ) );
+ break;
+ case 4:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternBumps );
+ m_pDisplayedObject->setNoiseGenerator(
+ ( PMPattern::PMNoiseType ) m_pNoiseGenerator->currentItem( ) );
+ break;
+ case 5:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternCells );
+ break;
+ case 6:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternCrackle );
+ m_pDisplayedObject->setCrackleForm( m_pCrackleForm->vector( ) );
+ m_pDisplayedObject->setCrackleMetric( m_pCrackleMetric->value( ) );
+ m_pDisplayedObject->setCrackleOffset( m_pCrackleOffset->value( ) );
+ m_pDisplayedObject->setCrackleSolid( m_pCrackleSolid->isChecked( ) );
+ break;
+ case 7:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternCylindrical );
+ break;
+ case 8:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternDensity );
+ m_pDisplayedObject->setDensityFile( m_pDensityFile->text( ) );
+ m_pDisplayedObject->setDensityInterpolate( m_pDensityInterpolate->currentItem( ) );
+ break;
+ case 9:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternDents );
+ break;
+ case 10:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternGradient );
+ m_pDisplayedObject->setGradient( m_pGradientEdit->vector( ) );
+ break;
+ case 11:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternGranite );
+ m_pDisplayedObject->setNoiseGenerator(
+ ( PMPattern::PMNoiseType ) m_pNoiseGenerator->currentItem( ) );
+ break;
+ case 12:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternJulia );
+ m_pDisplayedObject->setJuliaComplex( m_pJuliaComplex->vector( ) );
+ m_pDisplayedObject->setFractalMagnet( m_pFractalMagnet->isChecked( ) );
+ m_pDisplayedObject->setFractalMagnetType( m_pFractalMagnetType->currentItem( ) + 1 );
+ m_pDisplayedObject->setMaxIterations( m_pMaxIterationsEdit->value( ) );
+ m_pDisplayedObject->setFractalExponent( m_pFractalExponent->value( ) );
+ m_pDisplayedObject->setFractalExtType( m_pFractalExtType->currentItem( ) );
+ m_pDisplayedObject->setFractalExtFactor( m_pFractalExtFactor->value( ) );
+ m_pDisplayedObject->setFractalIntType( m_pFractalIntType->currentItem( ) );
+ m_pDisplayedObject->setFractalIntFactor( m_pFractalIntFactor->value( ) );
+ break;
+ case 13:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternLeopard );
+ break;
+ case 14:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternMandel );
+ m_pDisplayedObject->setFractalMagnet( m_pFractalMagnet->isChecked( ) );
+ m_pDisplayedObject->setFractalMagnetType( m_pFractalMagnetType->currentItem( ) + 1 );
+ m_pDisplayedObject->setMaxIterations( m_pMaxIterationsEdit->value( ) );
+ m_pDisplayedObject->setFractalExponent( m_pFractalExponent->value( ) );
+ m_pDisplayedObject->setFractalExtType( m_pFractalExtType->currentItem( ) );
+ m_pDisplayedObject->setFractalExtFactor( m_pFractalExtFactor->value( ) );
+ m_pDisplayedObject->setFractalIntType( m_pFractalIntType->currentItem( ) );
+ m_pDisplayedObject->setFractalIntFactor( m_pFractalIntFactor->value( ) );
+ break;
+ case 15:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternMarble );
+ break;
+ case 16:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternOnion );
+ break;
+ case 17:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternPlanar );
+ break;
+ case 18:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternQuilted );
+ m_pDisplayedObject->setQuiltControl0( m_pQuiltControl0Edit->value( ) );
+ m_pDisplayedObject->setQuiltControl1( m_pQuiltControl1Edit->value( ) );
+ break;
+ case 19:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternRadial );
+ break;
+ case 20:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternRipples );
+ break;
+ case 21:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternSlope );
+ m_pDisplayedObject->setSlopeDirection( m_pSlopeDirection->vector( ) );
+ m_pDisplayedObject->setSlopeLoSlope( m_pSlopeLoSlope->value( ) );
+ m_pDisplayedObject->setSlopeHiSlope( m_pSlopeHiSlope->value( ) );
+ m_pDisplayedObject->setSlopeAltFlag( m_pSlopeAltFlag->isChecked( ) );
+ m_pDisplayedObject->setSlopeAltitude( m_pSlopeAltitude->vector( ) );
+ m_pDisplayedObject->setSlopeLoAlt( m_pSlopeLoAlt->value( ) );
+ m_pDisplayedObject->setSlopeHiAlt( m_pSlopeHiAlt->value( ) );
+ break;
+ case 22:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternSpherical );
+ break;
+ case 23:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternSpiral1 );
+ m_pDisplayedObject->setSpiralNumberArms( m_pSpiralNumberEdit->value( ) );
+ break;
+ case 24:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternSpiral2 );
+ m_pDisplayedObject->setSpiralNumberArms( m_pSpiralNumberEdit->value( ) );
+ break;
+ case 25:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternSpotted );
+ break;
+ case 26:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternWaves );
+ break;
+ case 27:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternWood );
+ break;
+ case 28:
+ m_pDisplayedObject->setPatternType( PMPattern::PatternWrinkles );
+ m_pDisplayedObject->setNoiseGenerator(
+ ( PMPattern::PMNoiseType ) m_pNoiseGenerator->currentItem( ) );
+ break;
+ }
+ m_pDisplayedObject->enableTurbulence( m_pEnableTurbulenceEdit->isChecked( ) );
+ m_pDisplayedObject->setValueVector( m_pValueVectorEdit->vector( ) );
+ m_pDisplayedObject->setOctaves( m_pOctavesEdit->value( ) );
+ m_pDisplayedObject->setOmega( m_pOmegaEdit->value( ) );
+ m_pDisplayedObject->setLambda( m_pLambdaEdit->value( ) );
+
+ if( m_pDisplayedObject->parent( ) &&
+ ( m_pDisplayedObject->parent( )->type( ) == "Normal" ) )
+ m_pDisplayedObject->setDepth( m_pDepthEdit->value( ) );
+ }
+}
+
+bool PMPatternEdit::isDataValid( )
+{
+ switch( m_pTypeCombo->currentItem( ) )
+ {
+ case 0: // Agate
+ if( !m_pAgateTurbulenceEdit->isDataValid( ) )
+ return false;
+ break;
+ case 6: // Crackle
+ if ( !m_pCrackleMetric->isDataValid( ) )
+ return false;
+ break;
+ case 10: // Gradient
+ if( !m_pGradientEdit->isDataValid( ) )
+ return false;
+ break;
+ case 12: // Julia
+ case 14: // Mandel
+ if ( !m_pMaxIterationsEdit->isDataValid( ) )
+ return false;
+ if ( !m_pFractalExponent->isDataValid( ) )
+ return false;
+ break;
+ case 18: // Quilt
+ if( !m_pQuiltControl0Edit->isDataValid( ) )
+ return false;
+ if( !m_pQuiltControl1Edit->isDataValid( ) )
+ return false;
+ break;
+ case 21: // Slope
+ if( !m_pSlopeLoSlope->isDataValid( ) )
+ return false;
+ if( !m_pSlopeHiSlope->isDataValid( ) )
+ return false;
+ break;
+ case 23: // Spiral1
+ case 24: // Spiral2
+ if( !m_pSpiralNumberEdit->isDataValid( ) )
+ return false;
+ break;
+ default:
+ break;
+ }
+ if( m_pEnableTurbulenceEdit->isChecked( ) ) {
+ if( !m_pValueVectorEdit->isDataValid( ) ) return false;
+ if( !m_pOctavesEdit->isDataValid( ) ) return false;
+ if( !m_pOmegaEdit->isDataValid( ) ) return false;
+ if( !m_pLambdaEdit->isDataValid( ) ) return false;
+ }
+ if( m_pDisplayedObject->parent( ) &&
+ m_pDisplayedObject->parent( )->type( ) == "Normal" &&
+ !m_pDepthEdit->isDataValid( ) )
+ return false;
+
+ return Base::isDataValid( );
+}
+
+void PMPatternEdit::slotComboChanged( int c )
+{
+ switch( c )
+ {
+ case 0: /* Agate */
+ m_pAgateTurbulenceEdit->show( );
+ m_pAgateTurbulenceLabel->show( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 3: /* Bozo */
+ case 4: /* Bumps */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->show( );
+ m_pNoiseGenerator->show( );
+ break;
+ case 6: /* Crackle */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->show( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 8: /* Density File */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->show( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 10: /* Gradient */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->show( );
+ m_pGradientLabel->show( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 11: /* Granite */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->show( );
+ m_pNoiseGenerator->show( );
+ break;
+ case 12: /* Julia */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->show( );
+ m_pJuliaComplex->show( );
+ m_pFractalWidget->show( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 14: /* Mandel */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->show( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 18: /* Quilted */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->show( );
+ m_pQuiltControl0Edit->show( );
+ m_pQuiltControl1Edit->show( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 21: /* Slope */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->show( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 23: /* Spiral1 */
+ case 24: /* Spiral2 */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->show( );
+ m_pSpiralNumberLabel->show( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ case 28: /* Wrinkles */
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->show( );
+ m_pNoiseGenerator->show( );
+ break;
+ default:
+ m_pAgateTurbulenceEdit->hide( );
+ m_pAgateTurbulenceLabel->hide( );
+ m_pCrackleWidget->hide( );
+ m_pDensityWidget->hide( );
+ m_pGradientEdit->hide( );
+ m_pGradientLabel->hide( );
+ m_pJuliaComplexLabel->hide( );
+ m_pJuliaComplex->hide( );
+ m_pFractalWidget->hide( );
+ m_pQuiltControlsLabel->hide( );
+ m_pQuiltControl0Edit->hide( );
+ m_pQuiltControl1Edit->hide( );
+ m_pSlopeWidget->hide( );
+ m_pSpiralNumberEdit->hide( );
+ m_pSpiralNumberLabel->hide( );
+ m_pNoiseGeneratorLabel->hide( );
+ m_pNoiseGenerator->hide( );
+ break;
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMPatternEdit::slotDensityFileBrowseClicked( )
+{
+ QString str = KFileDialog::getOpenFileName( QString::null, QString::null );
+
+ if( !str.isEmpty() )
+ {
+ m_pDensityFile->setText( str );
+ emit dataChanged( );
+ }
+}
+
+void PMPatternEdit::slotFractalMagnetClicked( )
+{
+ if ( m_pFractalMagnet->isChecked( ) )
+ {
+ m_pFractalMagnetType->show( );
+ m_pFractalExponentLabel->hide( );
+ m_pFractalExponent->hide( );
+ }
+ else
+ {
+ m_pFractalMagnetType->hide( );
+ m_pFractalExponentLabel->show( );
+ m_pFractalExponent->show( );
+ }
+ m_pFractalWidget->adjustSize( );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMPatternEdit::slotSlopeAltFlagClicked( )
+{
+ if ( m_pSlopeAltFlag->isChecked( ) )
+ {
+ m_pSlopeAltitude->show( );
+ m_pSlopeLoAltLabel->show( );
+ m_pSlopeLoAlt->show( );
+ m_pSlopeHiAltLabel->show( );
+ m_pSlopeHiAlt->show( );
+ }
+ else
+ {
+ m_pSlopeAltitude->hide( );
+ m_pSlopeLoAltLabel->hide( );
+ m_pSlopeLoAlt->hide( );
+ m_pSlopeHiAltLabel->hide( );
+ m_pSlopeHiAlt->hide( );
+ }
+ m_pSlopeWidget->adjustSize( );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMPatternEdit::slotTurbulenceClicked( )
+{
+ if(m_pEnableTurbulenceEdit->isChecked( ) )
+ m_pTurbulenceWidget->show( );
+ else
+ m_pTurbulenceWidget->hide( );
+
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+#include "pmpatternedit.moc"
diff --git a/kpovmodeler/pmpatternedit.h b/kpovmodeler/pmpatternedit.h
new file mode 100644
index 00000000..9f36ccf4
--- /dev/null
+++ b/kpovmodeler/pmpatternedit.h
@@ -0,0 +1,164 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPATTERNEDIT_H
+#define PMPATTERNEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMPattern;
+class PMVectorEdit;
+class QComboBox;
+class PMFloatEdit;
+class PMIntEdit;
+class QLabel;
+class QCheckBox;
+class QWidget;
+class QLineEdit;
+class QPushButton;
+
+/**
+ * Dialog edit class for @ref PMPattern.
+ */
+class PMPatternEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMPatternEdit with parent and name
+ */
+ PMPatternEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * Slot called whenever a new pattern type is selected.
+ */
+ void slotComboChanged( int c );
+ /**
+ * Slot called when the browse button is pressed for selection of the
+ * density file
+ */
+ void slotDensityFileBrowseClicked( );
+ /**
+ * Slot called when fractal magnet clicked
+ */
+ void slotFractalMagnetClicked( );
+ /**
+ * Slot called when the slope altitude flag is clicked
+ */
+ void slotSlopeAltFlagClicked( );
+ /**
+ * Slot called when turbulence is activated/deactivated.
+ */
+ void slotTurbulenceClicked( );
+
+private:
+ /**
+ * Set's the combo box and enables/disables widgets.
+ */
+ void setPatternType( int i );
+ /**
+ * m_noDepth is false is the editor must show the depth field
+ */
+ bool m_noDepth;
+ PMPattern* m_pDisplayedObject;
+ QComboBox* m_pTypeCombo;
+
+ QLabel* m_pAgateTurbulenceLabel;
+ PMFloatEdit* m_pAgateTurbulenceEdit;
+
+ QWidget* m_pCrackleWidget;
+ PMVectorEdit* m_pCrackleForm;
+ PMIntEdit* m_pCrackleMetric;
+ PMFloatEdit* m_pCrackleOffset;
+ QCheckBox* m_pCrackleSolid;
+
+ QWidget* m_pDensityWidget;
+ QComboBox* m_pDensityInterpolate;
+ QLineEdit* m_pDensityFile;
+ QPushButton* m_pDensityFileBrowse;
+
+ QLabel* m_pGradientLabel;
+ PMVectorEdit* m_pGradientEdit;
+
+ QLabel* m_pJuliaComplexLabel;
+ PMVectorEdit* m_pJuliaComplex;
+ QWidget* m_pFractalWidget;
+ QCheckBox* m_pFractalMagnet;
+ QComboBox* m_pFractalMagnetType;
+ PMIntEdit* m_pMaxIterationsEdit;
+ QLabel* m_pFractalExponentLabel;
+ PMIntEdit* m_pFractalExponent;
+ QComboBox* m_pFractalExtType;
+ PMFloatEdit* m_pFractalExtFactor;
+ QComboBox* m_pFractalIntType;
+ PMFloatEdit* m_pFractalIntFactor;
+
+ QLabel* m_pQuiltControlsLabel;
+ PMFloatEdit* m_pQuiltControl0Edit;
+ PMFloatEdit* m_pQuiltControl1Edit;
+
+ QWidget* m_pSlopeWidget;
+ PMVectorEdit* m_pSlopeDirection;
+ PMFloatEdit* m_pSlopeLoSlope;
+ PMFloatEdit* m_pSlopeHiSlope;
+ QCheckBox* m_pSlopeAltFlag;
+ PMVectorEdit* m_pSlopeAltitude;
+ QLabel* m_pSlopeLoAltLabel;
+ PMFloatEdit* m_pSlopeLoAlt;
+ QLabel* m_pSlopeHiAltLabel;
+ PMFloatEdit* m_pSlopeHiAlt;
+
+ QLabel* m_pSpiralNumberLabel;
+ PMIntEdit* m_pSpiralNumberEdit;
+
+ QLabel* m_pNoiseGeneratorLabel;
+ QComboBox* m_pNoiseGenerator;
+
+ QCheckBox* m_pEnableTurbulenceEdit;
+ QWidget* m_pTurbulenceWidget;
+ PMVectorEdit* m_pValueVectorEdit;
+ PMIntEdit* m_pOctavesEdit;
+ PMFloatEdit* m_pOmegaEdit;
+ PMFloatEdit* m_pLambdaEdit;
+
+ QLabel* m_pDepthLabel;
+ PMFloatEdit* m_pDepthEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmphotons.cpp b/kpovmodeler/pmphotons.cpp
new file mode 100644
index 00000000..8297e3be
--- /dev/null
+++ b/kpovmodeler/pmphotons.cpp
@@ -0,0 +1,240 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmphotons.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmphotonsedit.h"
+
+#include <klocale.h>
+
+const double spacingMultiDefault = 1.0;
+
+PMDefinePropertyClass( PMPhotons, PMPhotonsProperty );
+
+PMMetaObject* PMPhotons::s_pMetaObject = 0;
+PMObject* createNewPhotons( PMPart* part )
+{
+ return new PMPhotons( part );
+}
+
+PMPhotons::PMPhotons( PMPart* part ) : Base( part )
+{
+ m_target = true;
+ m_spacingMulti = spacingMultiDefault;
+ m_refraction = false;
+ m_reflection = false;
+ m_collect = true;
+ m_passThrough = false;
+ m_areaLight = false;
+}
+
+PMPhotons::PMPhotons( const PMPhotons& p )
+ : Base( p )
+{
+ m_target = p.m_target;
+ m_spacingMulti = p.m_spacingMulti;
+ m_refraction = p.m_refraction;
+ m_reflection = p.m_reflection;
+ m_collect = p.m_collect;
+ m_passThrough = p.m_passThrough;
+ m_areaLight = p.m_areaLight;
+}
+
+PMPhotons::~PMPhotons( )
+{
+}
+
+PMMetaObject* PMPhotons::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Photons", Base::metaObject( ),
+ createNewPhotons );
+
+ s_pMetaObject->addProperty( new PMPhotonsProperty( "target",
+ &PMPhotons::setTarget, &PMPhotons::target ) );
+ s_pMetaObject->addProperty( new PMPhotonsProperty( "spacingMulti",
+ &PMPhotons::setSpacingMulti, &PMPhotons::spacingMulti ) );
+ s_pMetaObject->addProperty( new PMPhotonsProperty( "refraction",
+ &PMPhotons::setRefraction, &PMPhotons::refraction ) );
+ s_pMetaObject->addProperty( new PMPhotonsProperty( "reflection",
+ &PMPhotons::setReflection, &PMPhotons::reflection ) );
+ s_pMetaObject->addProperty( new PMPhotonsProperty( "collect",
+ &PMPhotons::setCollect, &PMPhotons::collect ) );
+ s_pMetaObject->addProperty( new PMPhotonsProperty( "passThrough",
+ &PMPhotons::setPassThrough, &PMPhotons::passThrough ) );
+ s_pMetaObject->addProperty( new PMPhotonsProperty( "areaLight",
+ &PMPhotons::setAreaLight, &PMPhotons::areaLight ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMPhotons::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMPhotons::description( ) const
+{
+ return i18n( "photons" );
+}
+
+void PMPhotons::serialize( QDomElement& e, QDomDocument& ) const
+{
+ e.setAttribute( "target", m_target );
+ e.setAttribute( "spacing_multi", m_spacingMulti );
+ e.setAttribute( "refraction", m_refraction );
+ e.setAttribute( "reflection", m_reflection );
+ e.setAttribute( "collect", m_collect );
+ e.setAttribute( "pass_through", m_passThrough );
+ e.setAttribute( "area_light", m_areaLight );
+}
+
+void PMPhotons::readAttributes( const PMXMLHelper& h )
+{
+ m_target = h.boolAttribute( "target", true );
+ m_spacingMulti = h.doubleAttribute( "spacing_multi", spacingMultiDefault );
+ m_refraction = h.boolAttribute( "refraction", false );
+ m_reflection = h.boolAttribute( "reflection", false );
+ m_collect = h.boolAttribute( "collect", true );
+ m_passThrough = h.boolAttribute( "pass_through", false );
+ m_areaLight = h.boolAttribute( "area_light", false );
+}
+
+void PMPhotons::setTarget( bool t )
+{
+ if( t != m_target )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMTargetID, m_target );
+ m_target = t;
+ }
+}
+
+void PMPhotons::setSpacingMulti( double sm )
+{
+ if ( sm != m_spacingMulti )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSpacingMultiID, m_spacingMulti );
+ m_spacingMulti = sm;
+ }
+}
+
+void PMPhotons::setRefraction( bool r )
+{
+ if ( r != m_refraction )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRefractionID, m_refraction );
+ m_refraction = r;
+ }
+}
+
+void PMPhotons::setReflection( bool r )
+{
+ if ( r != m_reflection )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMReflectionID, m_reflection);
+ m_reflection = r;
+ }
+}
+
+void PMPhotons::setCollect( bool c )
+{
+ if ( c != m_collect )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCollectID, m_collect );
+ m_collect = c;
+ }
+}
+
+void PMPhotons::setPassThrough( bool pt )
+{
+ if ( pt != m_passThrough )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPassThroughID, m_passThrough );
+ m_passThrough = pt;
+ }
+}
+
+void PMPhotons::setAreaLight( bool al )
+{
+ if ( al != m_areaLight )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAreaLightID, m_areaLight );
+ m_areaLight = al;
+ }
+}
+
+PMDialogEditBase* PMPhotons::editWidget( QWidget* parent ) const
+{
+ return new PMPhotonsEdit( parent );
+}
+
+void PMPhotons::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMTargetID:
+ setTarget( data->boolData( ) );
+ break;
+ case PMSpacingMultiID:
+ setSpacingMulti( data->doubleData( ) );
+ break;
+ case PMRefractionID:
+ setRefraction( data->boolData( ) );
+ break;
+ case PMReflectionID:
+ setReflection( data->boolData( ) );
+ break;
+ case PMCollectID:
+ setCollect( data->boolData( ) );
+ break;
+ case PMPassThroughID:
+ setPassThrough( data->boolData( ) );
+ break;
+ case PMAreaLightID:
+ setAreaLight( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMRadiosity::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmphotons.h b/kpovmodeler/pmphotons.h
new file mode 100644
index 00000000..14ce9f6f
--- /dev/null
+++ b/kpovmodeler/pmphotons.h
@@ -0,0 +1,160 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPHOTONS_H
+#define PMPHOTONS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+/**
+ * Class for Photons settings.
+ */
+
+class PMPhotons : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates a PMPhotons
+ */
+ PMPhotons( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPhotons( const PMPhotons& p );
+ /**
+ * deletes the PMPhotons
+ */
+ virtual ~PMPhotons( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPhotons( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMPhotonsEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmphotons" ); }
+
+ /**
+ * Returns the target flag
+ */
+ bool target( ) const { return m_target; }
+ /**
+ * Sets the target flag
+ */
+ void setTarget( bool t );
+
+ /**
+ * Returns the spacing multiplier
+ */
+ double spacingMulti( ) const { return m_spacingMulti; }
+ /**
+ * Sets the spacing multipler
+ */
+ void setSpacingMulti( double sm );
+
+ /**
+ * Returns the refraction flag
+ */
+ bool refraction( ) const { return m_refraction; }
+ /**
+ * Sets the refraction flag
+ */
+ void setRefraction( bool r );
+
+ /**
+ * Returns the reflection flag
+ */
+ bool reflection( ) const { return m_reflection; }
+ /**
+ * Sets the reflection flag
+ */
+ void setReflection( bool r );
+
+ /**
+ * Returns the collect flag
+ */
+ bool collect( ) const { return m_collect; }
+ /**
+ * Sets the collect flag
+ */
+ void setCollect( bool c );
+
+ /**
+ * Returns the pass through flag
+ */
+ bool passThrough( ) const { return m_passThrough; }
+ /**
+ * Sets the pass through flag
+ */
+ void setPassThrough( bool pt );
+
+ /**
+ * Returns the area light flag
+ */
+ bool areaLight( ) const { return m_areaLight; }
+ /**
+ * Sets the area light flag
+ */
+ void setAreaLight( bool al );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMPhotonsMementoID{ PMTargetID, PMSpacingMultiID, PMRefractionID,
+ PMReflectionID, PMCollectID, PMPassThroughID,
+ PMAreaLightID };
+
+ bool m_target;
+ double m_spacingMulti;
+ bool m_refraction;
+ bool m_reflection;
+ bool m_collect;
+ bool m_passThrough;
+ bool m_areaLight;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmphotonsedit.cpp b/kpovmodeler/pmphotonsedit.cpp
new file mode 100644
index 00000000..21f5d106
--- /dev/null
+++ b/kpovmodeler/pmphotonsedit.cpp
@@ -0,0 +1,160 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmphotonsedit.h"
+#include "pmphotons.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+
+
+PMPhotonsEdit::PMPhotonsEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMPhotonsEdit::createTopWidgets( )
+{
+ QGridLayout* gl;
+ QHBoxLayout* hl;
+
+ Base::createTopWidgets( );
+
+ m_pLayoutWidget = new QWidget( this );
+ m_pTarget = new QCheckBox( i18n( "Target" ), m_pLayoutWidget );
+ m_pSpacingMultiLabel = new QLabel( i18n( "Spacing multiplier:" ), m_pLayoutWidget );
+ m_pSpacingMulti = new PMFloatEdit( m_pLayoutWidget );
+ m_pSpacingMulti->setValidation( true, 0, false, 0 );
+
+ m_pRefraction = new QCheckBox( i18n( "Refraction" ), this );
+ m_pReflection = new QCheckBox( i18n( "Reflection" ), this );
+ m_pCollect = new QCheckBox( i18n( "Collect" ), this );
+ m_pPassThrough = new QCheckBox( i18n( "Pass through" ), this );
+ m_pAreaLight = new QCheckBox( i18n( "Area light" ), this );
+
+ hl = new QHBoxLayout( m_pLayoutWidget, 0, KDialog::spacingHint( ) );
+ gl = new QGridLayout( hl, 2, 2 );
+ gl->addMultiCellWidget( m_pTarget, 0, 0, 0, 1 );
+ gl->addWidget( m_pSpacingMultiLabel, 1, 0 );
+ gl->addWidget( m_pSpacingMulti, 1, 1 );
+ hl->addStretch( 1 );
+ topLayout( )->addWidget( m_pLayoutWidget );
+
+ gl = new QGridLayout( topLayout( ), 2, 2 );
+ gl->addWidget( m_pRefraction, 0, 0 );
+ gl->addWidget( m_pReflection, 0, 1 );
+ gl->addWidget( m_pCollect, 1, 0 );
+ gl->addWidget( m_pPassThrough, 1, 1 );
+ gl->addWidget( m_pAreaLight, 1, 0 );
+
+ connect( m_pTarget, SIGNAL( clicked( ) ), SLOT( slotTargetClicked( ) ) );
+ connect( m_pSpacingMulti, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRefraction, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pReflection, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCollect, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPassThrough, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAreaLight, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMPhotonsEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Photons" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMPhotons* ) o;
+
+ if ( o->parent( ) && ( o->parent( )->isA( "Light" ) ) )
+ {
+ m_pLayoutWidget->hide( );
+ m_pCollect->hide( );
+ m_pPassThrough->hide( );
+ m_pAreaLight->show( );
+ }
+ else
+ {
+ m_pLayoutWidget->show( );
+ m_pCollect->show( );
+ m_pPassThrough->show( );
+ m_pAreaLight->hide( );
+ }
+
+ m_pTarget->setChecked( m_pDisplayedObject->target( ) );
+ m_pTarget->setEnabled( !readOnly );
+ m_pSpacingMulti->setValue( m_pDisplayedObject->spacingMulti( ) );
+ m_pSpacingMulti->setReadOnly( readOnly );
+ m_pRefraction->setChecked( m_pDisplayedObject->refraction( ) );
+ m_pRefraction->setEnabled( !readOnly );
+ m_pReflection->setChecked( m_pDisplayedObject->reflection( ) );
+ m_pReflection->setEnabled( !readOnly );
+ m_pCollect->setChecked( m_pDisplayedObject->collect( ) );
+ m_pCollect->setEnabled( !readOnly );
+ m_pPassThrough->setChecked( m_pDisplayedObject->passThrough( ) );
+ m_pPassThrough->setEnabled( !readOnly );
+ m_pAreaLight->setChecked( m_pDisplayedObject->areaLight( ) );
+ m_pAreaLight->setEnabled( !readOnly );
+
+ slotTargetClicked( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMPhotonsEdit: Can't display object\n";
+}
+
+void PMPhotonsEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setTarget( m_pTarget->isChecked( ) );
+ m_pDisplayedObject->setSpacingMulti( m_pSpacingMulti->value( ) );
+ m_pDisplayedObject->setRefraction( m_pRefraction->isChecked( ) );
+ m_pDisplayedObject->setReflection( m_pReflection->isChecked( ) );
+ m_pDisplayedObject->setCollect( m_pCollect->isChecked( ) );
+ m_pDisplayedObject->setPassThrough( m_pPassThrough->isChecked( ) );
+ m_pDisplayedObject->setAreaLight( m_pAreaLight->isChecked( ) );
+ }
+}
+
+bool PMPhotonsEdit::isDataValid( )
+{
+ if( !m_pSpacingMulti->isDataValid( ) ) return false;
+
+ return Base::isDataValid( );
+}
+
+void PMPhotonsEdit::slotTargetClicked( )
+{
+ if ( m_pTarget->isChecked( ) && m_pTarget->isEnabled( ) )
+ {
+ m_pSpacingMulti->setEnabled( true );
+ }
+ else
+ {
+ m_pSpacingMulti->setEnabled( false );
+ }
+ emit dataChanged( );
+}
+
+#include "pmphotonsedit.moc"
diff --git a/kpovmodeler/pmphotonsedit.h b/kpovmodeler/pmphotonsedit.h
new file mode 100644
index 00000000..d40e84cf
--- /dev/null
+++ b/kpovmodeler/pmphotonsedit.h
@@ -0,0 +1,79 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPHOTONSEDIT_H
+#define PMPHOTONSEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMPhotons;
+class PMFloatEdit;
+class QCheckBox;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMPhotons.
+ */
+class PMPhotonsEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMPhotonsEdit with parent and name
+ */
+ PMPhotonsEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * Slot Called whenever target is clicked
+ */
+ void slotTargetClicked( );
+
+private:
+ PMPhotons* m_pDisplayedObject;
+
+ QWidget* m_pLayoutWidget;
+ QCheckBox* m_pTarget;
+ PMFloatEdit* m_pSpacingMulti;
+ QLabel* m_pSpacingMultiLabel;
+ QCheckBox* m_pRefraction;
+ QCheckBox* m_pReflection;
+ QCheckBox* m_pCollect;
+ QCheckBox* m_pPassThrough;
+ QCheckBox* m_pAreaLight;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmpigment.cpp b/kpovmodeler/pmpigment.cpp
new file mode 100644
index 00000000..39e5a4e3
--- /dev/null
+++ b/kpovmodeler/pmpigment.cpp
@@ -0,0 +1,124 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpigment.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmpigmentedit.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMPigment, PMPigmentProperty );
+
+PMMetaObject* PMPigment::s_pMetaObject = 0;
+PMObject* createNewPigment( PMPart* part )
+{
+ return new PMPigment( part );
+}
+
+PMPigment::PMPigment( PMPart* part ) : Base( part )
+{
+ m_uvMapping = false;
+}
+
+PMPigment::PMPigment( const PMPigment& p ) : Base( p )
+{
+ m_uvMapping = p.m_uvMapping;
+}
+
+PMPigment::~PMPigment( )
+{
+}
+
+PMMetaObject* PMPigment::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Pigment", Base::metaObject( ),
+ createNewPigment );
+ s_pMetaObject->addProperty(
+ new PMPigmentProperty( "uvMapping", &PMPigment::setUVMapping, &PMPigment::uvMapping ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMPigment::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMPigment::description( ) const
+{
+ return i18n( "pigment" );
+}
+
+PMDialogEditBase* PMPigment::editWidget( QWidget* parent ) const
+{
+ return new PMPigmentEdit( parent );
+}
+
+void PMPigment::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "uv_mapping", m_uvMapping );
+ Base::serialize( e, doc );
+}
+
+void PMPigment::readAttributes( const PMXMLHelper& h )
+{
+ m_uvMapping = h.boolAttribute( "uv_mapping", false );
+ Base::readAttributes( h );
+}
+
+void PMPigment::setUVMapping( bool m )
+{
+ if( m != m_uvMapping )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUVMappingID, m_uvMapping );
+ m_uvMapping = m;
+ }
+}
+
+void PMPigment::restoreMemento( PMMemento *s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMUVMappingID:
+ setUVMapping( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMPigment::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmpigment.h b/kpovmodeler/pmpigment.h
new file mode 100644
index 00000000..3f465e0e
--- /dev/null
+++ b/kpovmodeler/pmpigment.h
@@ -0,0 +1,95 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPIGMENT_H
+#define PMPIGMENT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+
+/**
+ * Class for povray pigments
+ */
+class PMPigment : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMPigment
+ */
+ PMPigment( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPigment( const PMPigment& );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMPigment( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPigment( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMPigmentEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmpigment" ); }
+
+ /**
+ * Returns the uv mapping flag
+ */
+ bool uvMapping() const { return m_uvMapping; }
+ /**
+ * Sets the uv maaping flag
+ */
+ void setUVMapping( bool m );
+
+ /** */
+ virtual void restoreMemento( PMMemento *s );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMPigmentMementoID { PMUVMappingID };
+
+ bool m_uvMapping;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmpigmentedit.cpp b/kpovmodeler/pmpigmentedit.cpp
new file mode 100644
index 00000000..939f18cf
--- /dev/null
+++ b/kpovmodeler/pmpigmentedit.cpp
@@ -0,0 +1,68 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpigmentedit.h"
+#include "pmpigment.h"
+#include "pmlinkedit.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+
+PMPigmentEdit::PMPigmentEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMPigmentEdit::createTopWidgets()
+{
+ Base::createTopWidgets();
+ m_pUVMapping = new QCheckBox( i18n( "UV mapping" ), this );
+ topLayout( )->addWidget( m_pUVMapping );
+
+ connect( m_pUVMapping, SIGNAL( clicked() ), SIGNAL( dataChanged() ) );
+}
+
+void PMPigmentEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Pigment" ) )
+ {
+ m_pDisplayedObject = ( PMPigment* ) o;
+ bool readOnly = m_pDisplayedObject->isReadOnly( );
+
+ m_pUVMapping->setChecked( m_pDisplayedObject->uvMapping() );
+ m_pUVMapping->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMPigmentEdit: Can't display object\n";
+}
+
+void PMPigmentEdit::saveContents()
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents();
+ m_pDisplayedObject->setUVMapping( m_pUVMapping->isChecked() );
+ }
+}
+
+#include "pmpigmentedit.moc"
diff --git a/kpovmodeler/pmpigmentedit.h b/kpovmodeler/pmpigmentedit.h
new file mode 100644
index 00000000..7a3960a2
--- /dev/null
+++ b/kpovmodeler/pmpigmentedit.h
@@ -0,0 +1,60 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPIGMENTEDIT_H
+#define PMPIGMENTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMPigment;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMPigment
+ */
+class PMPigmentEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMPigmentEdit with parent and name
+ */
+ PMPigmentEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMPigment* m_pDisplayedObject;
+ QCheckBox* m_pUVMapping;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmplane.cpp b/kpovmodeler/pmplane.cpp
new file mode 100644
index 00000000..171df53f
--- /dev/null
+++ b/kpovmodeler/pmplane.cpp
@@ -0,0 +1,276 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmplane.h"
+
+#include "pmxmlhelper.h"
+#include "pmboxedit.h"
+#include "pmmemento.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmplanenormalcontrolpoint.h"
+#include "pmdefaults.h"
+
+#include <klocale.h>
+
+#include "pmplaneedit.h"
+
+const double defaultPlaneDistance = 0;
+const PMVector defaultPlaneNormal = PMVector ( 0.0, 1.0, 0.0 );
+
+/** default plane structure */
+PMViewStructure* PMPlane::s_pDefaultViewStructure = 0;
+double PMPlane::s_planeSize = c_defaultPlaneSize;
+int PMPlane::s_parameterKey = 0;
+
+PMDefinePropertyClass( PMPlane, PMPlaneProperty );
+
+PMMetaObject* PMPlane::s_pMetaObject = 0;
+PMObject* createNewPlane( PMPart* part )
+{
+ return new PMPlane( part );
+}
+
+PMPlane::PMPlane( PMPart* part )
+ : Base( part )
+{
+ m_normal = defaultPlaneNormal;
+ m_distance = defaultPlaneDistance;
+}
+
+PMPlane::PMPlane( const PMPlane& p )
+ : Base( p )
+{
+ m_normal = p.m_normal;
+ m_distance = p.m_distance;
+}
+
+PMPlane::~PMPlane( )
+{
+}
+
+QString PMPlane::description( ) const
+{
+ return i18n( "plane" );
+}
+
+void PMPlane::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "normal", m_normal.serializeXML( ) );
+ e.setAttribute( "distance", m_distance );
+ Base::serialize( e, doc );
+}
+
+void PMPlane::readAttributes( const PMXMLHelper& h )
+{
+ m_normal = h.vectorAttribute( "normal", defaultPlaneNormal );
+ m_distance = h.doubleAttribute( "distance", defaultPlaneDistance );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMPlane::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Plane", Base::metaObject( ),
+ createNewPlane );
+ s_pMetaObject->addProperty(
+ new PMPlaneProperty( "normal", &PMPlane::setNormal, &PMPlane::normal ) );
+ s_pMetaObject->addProperty(
+ new PMPlaneProperty( "distance", &PMPlane::setDistance, &PMPlane::distance ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMPlane::setNormal( const PMVector& p )
+{
+
+ if( p != m_normal )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMNormalID, m_normal );
+ }
+ m_normal = p;
+ m_normal.resize( 3 );
+
+ setViewStructureChanged( );
+ }
+}
+
+void PMPlane::setDistance( double distance )
+{
+ if( m_distance != distance )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMDistanceID, m_distance );
+ }
+ m_distance = distance;
+
+ setViewStructureChanged( );
+ }
+}
+
+PMDialogEditBase* PMPlane::editWidget( QWidget* parent ) const
+{
+ return new PMPlaneEdit( parent );
+}
+
+void PMPlane::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMNormalID:
+ setNormal( data->vectorData( ) );
+ break;
+ case PMDistanceID:
+ setDistance( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMPlane::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+bool PMPlane::isDefault( )
+{
+ if( ( m_normal == defaultPlaneNormal ) && ( m_distance == defaultPlaneDistance ) )
+ return true;
+ return false;
+}
+
+void PMPlane::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure ( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+ createPoints( m_pViewStructure->points( ), m_normal, m_distance );
+}
+
+PMViewStructure* PMPlane::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure )
+ {
+ s_pDefaultViewStructure = new PMViewStructure( 4, 4 );
+ PMLineArray& lines = s_pDefaultViewStructure->lines( );
+
+ createPoints( s_pDefaultViewStructure->points( ), defaultPlaneNormal,defaultPlaneDistance );
+
+ lines[0] = PMLine( 0 , 1 );
+ lines[1] = PMLine( 1 , 2 );
+ lines[2] = PMLine( 2 , 3 );
+ lines[3] = PMLine( 3 , 0 );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMPlane::createPoints( PMPointArray& points, const PMVector& normal, double distance )
+{
+ PMVector dir = normal;
+ if( approxZero( dir.abs( ) ) )
+ dir = PMVector( 0.0, 1.0, 0.0 );
+
+ PMVector base = dir * distance;
+ PMMatrix rotation = PMMatrix::rotation( dir, M_PI / 4.0 );
+
+ PMVector endPoint1 = rotation * dir.orthogonal( ) * s_planeSize * sqrt( 2.0 ) * 0.5;
+ PMVector endPoint2 = rotation * ( rotation * endPoint1 );
+
+ points[0] = base + endPoint1;
+ points[1] = base + endPoint2;
+ points[2] = base - endPoint1;
+ points[3] = base - endPoint2;
+}
+
+void PMPlane::controlPoints( PMControlPointList & list )
+{
+ PMDistanceControlPoint* d;
+ d = new PMDistanceControlPoint( PMVector( 0, 0, 0 ), m_normal, m_distance,
+ PMDistanceID, i18n( "Distance" ) );
+ list.append( new PMPlaneNormalControlPoint( d, m_normal, PMNormalID,
+ i18n( "Normal" ) ) );
+ list.append( d );
+}
+
+
+void PMPlane::controlPointsChanged( PMControlPointList & list )
+{
+ PMControlPoint* p;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMNormalID:
+ setNormal( ( ( PMPlaneNormalControlPoint *) p)->normal( ) );
+ setDistance( ( ( PMPlaneNormalControlPoint *) p)->distance( ) );
+ break;
+ case PMDistanceID:
+ setDistance( ( ( PMDistanceControlPoint *) p )->distance( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMPlane::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+}
+
+void PMPlane::setPlaneSize( double size )
+{
+ if( size >= 0.1 )
+ {
+ s_planeSize = size;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMPlane::setPlaneSize: Size must be greater than 0.1\n";
+ s_parameterKey++;
+}
+
+void PMPlane::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmplane.h b/kpovmodeler/pmplane.h
new file mode 100644
index 00000000..34829ade
--- /dev/null
+++ b/kpovmodeler/pmplane.h
@@ -0,0 +1,148 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPLANE_H
+#define PMPLANE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include "pmviewstructure.h"
+
+/**
+ * Class for povray plane
+ */
+
+class PMPlane : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates a plane
+ */
+ PMPlane( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPlane( const PMPlane& p );
+
+ /**
+ * Deletes the plane
+ */
+ virtual ~PMPlane( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPlane( *this ); }
+
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMPlaneEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmplane" ); }
+
+ /**
+ * Return the normal
+ */
+ PMVector normal( ) const { return m_normal; }
+ /**
+ * Sets normal
+ */
+ void setNormal( const PMVector& p );
+ /**
+ * Return the distance
+ */
+ double distance( ) const { return m_distance; }
+ /**
+ * Sets the distance
+ */
+ void setDistance( double distance );
+
+ /**
+ * Sets the plane size (view structure)
+ */
+ static void setPlaneSize( double size );
+ /**
+ * Returns the plane size (view structure)
+ */
+ static double planeSize( ) { return s_planeSize; };
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey; }
+
+private:
+ /**
+ * Creates the points for the view structure
+ */
+ static void createPoints( PMPointArray& points, const PMVector& normal , double distance );
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMPlaneMementoID { PMNormalID, PMDistanceID };
+ /**
+ * normal of plane
+ */
+ PMVector m_normal;
+ /**
+ * distance from origin
+ */
+ double m_distance;
+ /**
+ * The default view structure. It can be shared between planes
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static double s_planeSize;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmplaneedit.cpp b/kpovmodeler/pmplaneedit.cpp
new file mode 100644
index 00000000..62e7e08e
--- /dev/null
+++ b/kpovmodeler/pmplaneedit.cpp
@@ -0,0 +1,124 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmplaneedit.h"
+#include "pmplane.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+PMPlaneEdit::PMPlaneEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMPlaneEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+
+ m_pNormal = new PMVectorEdit( "x", "y", "z", this );
+ m_pDistance = new PMFloatEdit( this );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Normal:" ), this ) );
+ layout->addWidget( m_pNormal );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Distance:" ), this ) );
+ layout->addWidget( m_pDistance );
+ layout->addStretch( 1 );
+
+ QPushButton* nb = new QPushButton( i18n( "Normalize" ), this );
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( nb );
+ layout->addStretch( 1 );
+
+ connect( m_pNormal, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDistance, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( nb, SIGNAL( clicked( ) ), SLOT( slotNormalize( ) ) );
+}
+
+void PMPlaneEdit::slotNormalize( )
+{
+ PMVector normal = m_pNormal->vector( );
+ double distance = m_pDistance->value( );
+ double l = normal.abs( );
+ if( !approxZero( l ) )
+ {
+ m_pNormal->setVector( normal / l );
+ m_pDistance->setValue( distance * l );
+ }
+}
+
+void PMPlaneEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Plane" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMPlane* ) o;
+
+ m_pNormal->setVector( m_pDisplayedObject->normal( ) );
+ m_pDistance->setValue( m_pDisplayedObject->distance( ) );
+
+ m_pNormal->setReadOnly( readOnly );
+ m_pDistance->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMPlaneEdit: Can't display object\n";
+}
+
+void PMPlaneEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setNormal( m_pNormal->vector( ) );
+ m_pDisplayedObject->setDistance( m_pDistance->value( ) );
+ }
+}
+
+bool PMPlaneEdit::isDataValid( )
+{
+ if( m_pNormal->isDataValid( ) )
+ {
+ if( approxZero( m_pNormal->vector( ).abs( ) ) )
+ {
+ KMessageBox::error( this, i18n( "The normal vector may not be a "
+ "null vector." ),
+ i18n( "Error" ) );
+ return false;
+
+ }
+ if( m_pDistance->isDataValid( ) )
+ return Base::isDataValid( );
+ }
+ return false;
+}
+
+#include "pmplaneedit.moc"
diff --git a/kpovmodeler/pmplaneedit.h b/kpovmodeler/pmplaneedit.h
new file mode 100644
index 00000000..97a07467
--- /dev/null
+++ b/kpovmodeler/pmplaneedit.h
@@ -0,0 +1,66 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorinaez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPLANEEDIT_H
+#define PMPLANEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMVectorEdit;
+class PMFloatEdit;
+class PMPlane;
+class QCheckBox;
+
+class PMPlaneEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMPlaneEdit with parent and name
+ */
+ PMPlaneEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /**
+ * Normalizes the vector
+ */
+ void slotNormalize( );
+
+private:
+ PMPlane* m_pDisplayedObject;
+ PMVectorEdit* m_pNormal;
+ PMFloatEdit* m_pDistance;
+};
+#endif
diff --git a/kpovmodeler/pmplanenormalcontrolpoint.cpp b/kpovmodeler/pmplanenormalcontrolpoint.cpp
new file mode 100644
index 00000000..f28c035e
--- /dev/null
+++ b/kpovmodeler/pmplanenormalcontrolpoint.cpp
@@ -0,0 +1,93 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmplanenormalcontrolpoint.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmmath.h"
+#include <math.h>
+
+PMPlaneNormalControlPoint::PMPlaneNormalControlPoint( PMDistanceControlPoint* d,
+ const PMVector& normal, int id,
+ const QString& description )
+ : PMControlPoint( id, description )
+{
+ m_normal = normal;
+ m_pDistancePoint = d;
+}
+
+PMVector PMPlaneNormalControlPoint::position( ) const
+{
+ return m_normal * ( m_pDistancePoint->distance( ) + 1.0 );
+}
+
+PMVector PMPlaneNormalControlPoint::extraLineStart( ) const
+{
+ return m_normal * m_pDistancePoint->distance( );
+}
+
+PMVector PMPlaneNormalControlPoint::extraLineEnd( ) const
+{
+ return position( );
+}
+
+void PMPlaneNormalControlPoint::graphicalChangeStarted( )
+{
+ m_originalNormal = m_normal;
+ m_originalDistance = m_pDistancePoint->distance( );
+}
+
+void PMPlaneNormalControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& /*viewNormal*/,
+ const PMVector& endPoint )
+{
+ PMVector p = m_originalNormal * ( m_originalDistance + 1 )
+ + endPoint - startPoint;
+ double pabs = p.abs( );
+
+ if( !approxZero( pabs ) )
+ {
+ PMVector np = p / pabs;
+ double nd = m_originalNormal.abs( ) * m_originalDistance;
+ PMVector normal = p - np * fabs( nd );
+ double nl = normal.abs( );
+
+ if( !approxZero( nl ) )
+ {
+ if( ( m_originalDistance * ( pabs - fabs( nd ) ) ) < 0 )
+ nd = -nd;
+ nd /= nl;
+ m_pDistancePoint->setDistance( nd );
+ m_pDistancePoint->setDirection( normal );
+ m_normal = normal;
+ }
+ }
+}
+
+double PMPlaneNormalControlPoint::distance( ) const
+{
+ return m_pDistancePoint->distance( );
+}
+
+void PMPlaneNormalControlPoint::snapToGrid( )
+{
+ int i;
+ double d = moveGrid( );
+ if( !approxZero( d ) )
+ for( i = 0; i < 3; i++ )
+ m_normal[i] = rint( m_normal[i] / d ) * d;
+ setChanged( );
+}
diff --git a/kpovmodeler/pmplanenormalcontrolpoint.h b/kpovmodeler/pmplanenormalcontrolpoint.h
new file mode 100644
index 00000000..0faf10b8
--- /dev/null
+++ b/kpovmodeler/pmplanenormalcontrolpoint.h
@@ -0,0 +1,92 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPLANENORMALCONTROLPOINT_H
+#define PMPLANENORMALCONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcontrolpoint.h"
+
+class PMDistanceControlPoint;
+
+/**
+ * Control points for the plane normal
+ */
+class PMPlaneNormalControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Creates a PMPlaneNormalControlPoint with id.
+ *
+ * If the control point is change, the distance control point
+ * is changed, too!
+ */
+ PMPlaneNormalControlPoint( PMDistanceControlPoint* d, const PMVector& normal,
+ int id, const QString& description );
+ /**
+ * Deletes the PMPlaneNormalControlPoint
+ */
+ virtual ~PMPlaneNormalControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const;
+
+ /**
+ * Sets the normal vector
+ */
+ void setNormal( PMVector newNormal ) { m_normal = newNormal; }
+ /**
+ * Returns the normal vector
+ */
+ PMVector normal( ) const { return m_normal; }
+ /**
+ * Returns the distance
+ */
+ double distance( ) const;
+
+ /** */
+ virtual bool hasExtraLine( ) const { return true; }
+ /**
+ * Returns the start point of the extra line
+ */
+ virtual PMVector extraLineStart( ) const;
+ /**
+ * Returns the end point of the extra line
+ */
+ virtual PMVector extraLineEnd( ) const;
+
+ /** */
+ virtual void snapToGrid( );
+
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ PMVector m_normal, m_originalNormal;
+ double m_originalDistance;
+ PMDistanceControlPoint* m_pDistancePoint;
+};
+
+#endif
diff --git a/kpovmodeler/pmpluginmanager.cpp b/kpovmodeler/pmpluginmanager.cpp
new file mode 100644
index 00000000..0921f79d
--- /dev/null
+++ b/kpovmodeler/pmpluginmanager.cpp
@@ -0,0 +1,115 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpluginmanager.h"
+#include "pmpart.h"
+#include "pmshell.h"
+#include "pmfactory.h"
+#include "pmdebug.h"
+
+#include <qmap.h>
+#include <qapplication.h>
+
+#include <kparts/plugin.h>
+#include <kxmlguifactory.h>
+#include <kconfig.h>
+
+PMPluginManager* PMPluginManager::s_pInstance = 0;
+KStaticDeleter<PMPluginManager> PMPluginManager::s_staticDeleter;
+
+using namespace KParts;
+
+// workaround for protected Plugin::pluginInfos
+class PMPluginWorkaround : public Plugin
+{
+public:
+ PMPluginWorkaround( ) : Plugin( 0, 0 ) { };
+ static QValueList<Plugin::PluginInfo> installedPlugins( const KInstance* instance )
+ {
+ return pluginInfos( instance );
+ }
+};
+
+PMPluginManager::PMPluginManager( )
+{
+ // find installed plugins
+ KConfigGroup cfgGroup( PMFactory::instance( )->config( ),
+ "KParts Plugins" );
+ QValueList<Plugin::PluginInfo> plugins
+ = PMPluginWorkaround::installedPlugins( PMFactory::instance( ) );
+ QValueList<Plugin::PluginInfo>::ConstIterator pIt = plugins.begin( );
+ QValueList<Plugin::PluginInfo>::ConstIterator pEnd = plugins.end( );
+
+ for( ; pIt != pEnd; ++pIt )
+ {
+ QDomElement docElem = ( *pIt ).m_document.documentElement( );
+ QString name = docElem.attribute( "name" );
+ QString description = docElem.attribute( "description" );
+ if( !description.isEmpty( ) )
+ description = i18n( description.latin1( ) );
+ bool enabled = cfgGroup.readBoolEntry( name + "Enabled", false );
+ m_plugins.append( new PMPluginInfo( name, description, enabled ) );
+ }
+}
+
+PMPluginManager::~PMPluginManager( )
+{
+ m_plugins.setAutoDelete( true );
+ m_plugins.clear( );
+}
+
+PMPluginManager* PMPluginManager::theManager( )
+{
+ if( !s_pInstance )
+ s_staticDeleter.setObject( s_pInstance, new PMPluginManager( ) );
+ return s_pInstance;
+}
+
+void PMPluginManager::registerPart( PMPart* p )
+{
+ if( !m_parts.containsRef( p ) )
+ {
+ m_parts.append( p );
+ Plugin::loadPlugins( p, p, PMFactory::instance( ), false );
+ }
+}
+
+void PMPluginManager::removePart( PMPart* p )
+{
+ m_parts.removeRef( p );
+}
+
+void PMPluginManager::updatePlugins( )
+{
+ KConfigGroup cfgGroup( PMFactory::instance( )->config( ),
+ "KParts Plugins" );
+ QPtrListIterator<PMPluginInfo> pit( m_plugins );
+ for( ; *pit; ++pit )
+ cfgGroup.writeEntry( ( *pit )->name( ) + "Enabled",
+ ( *pit )->enabled( ) );
+ cfgGroup.sync( );
+
+ QPtrListIterator<PMPart> it( m_parts );
+ for( ; *it; ++it )
+ {
+ Plugin::loadPlugins( *it, *it, PMFactory::instance( ), false );
+ PMShell* shell = ( *it )->shell( );
+ if( shell )
+ shell->updateGUI( );
+ // TODO find a solution to update the gui without using the shell
+ }
+}
diff --git a/kpovmodeler/pmpluginmanager.h b/kpovmodeler/pmpluginmanager.h
new file mode 100644
index 00000000..9424e014
--- /dev/null
+++ b/kpovmodeler/pmpluginmanager.h
@@ -0,0 +1,113 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPLUGINMANAGER_H
+#define PMPLUGINMANAGER_H
+
+#include <kstaticdeleter.h>
+
+#include <qstring.h>
+#include <qptrlist.h>
+
+class PMPart;
+
+/**
+ * Plugin info for one plugin
+ */
+class PMPluginInfo
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMPluginInfo( const QString& name, const QString& description,
+ bool enabled )
+ {
+ m_name = name;
+ m_description = description;
+ m_enabled = enabled;
+ }
+ /**
+ * Returns the plugin name
+ */
+ QString name( ) const { return m_name; }
+ /**
+ * Returns the plugin description (i18n'ed)
+ */
+ QString description( ) const { return m_description; }
+ /**
+ * Returns true if the plugin is enabled
+ */
+ bool enabled( ) const { return m_enabled; }
+ /**
+ * Enables/disables the plugin
+ */
+ void enable( bool en ) { m_enabled = en; }
+private:
+ QString m_name, m_description;
+ bool m_enabled;
+};
+
+/**
+ * Manager class for plugins.
+ *
+ * Stores a list of available plugins and loads and unloads plugins.
+ */
+class PMPluginManager
+{
+public:
+ /**
+ * Destructor
+ */
+ ~PMPluginManager( );
+ /**
+ * Returns the instance (singleton)
+ */
+ static PMPluginManager* theManager( );
+
+ /**
+ * Registers a part instance and loads the plugins for that part
+ */
+ void registerPart( PMPart* p );
+ /**
+ * Removes a part instance
+ */
+ void removePart( PMPart* p );
+
+ /**
+ * Returns a list of available plugins
+ */
+ QPtrList<PMPluginInfo> plugins( ) const { return m_plugins; }
+ /**
+ * Loads and unloads plugins for all parts when plugins were activated or
+ * deactivated
+ */
+ void updatePlugins( );
+private:
+ /**
+ * Constructor
+ */
+ PMPluginManager( );
+
+ QPtrList<PMPluginInfo> m_plugins;
+ QPtrList<PMPart> m_parts;
+
+ static PMPluginManager* s_pInstance;
+ static KStaticDeleter<PMPluginManager> s_staticDeleter;
+};
+
+#endif
diff --git a/kpovmodeler/pmpluginsettings.cpp b/kpovmodeler/pmpluginsettings.cpp
new file mode 100644
index 00000000..6b6611f2
--- /dev/null
+++ b/kpovmodeler/pmpluginsettings.cpp
@@ -0,0 +1,150 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpluginsettings.h"
+
+#include "pmpluginmanager.h"
+
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+
+class PMPluginListViewItem : public QListViewItem
+{
+public:
+ PMPluginListViewItem( QListView* parent, PMPluginInfo* info )
+ : QListViewItem( parent, info->name( ), info->description( ) )
+ {
+ m_info = info;
+ m_enabled = info->enabled( );
+ setStatus( );
+ }
+ void toggleStatus( )
+ {
+ m_enabled = !m_enabled;
+ setStatus( );
+ }
+ void setStatus( )
+ {
+ if( m_enabled )
+ setText( 2, i18n( "loaded" ) );
+ else
+ setText( 2, i18n( "deactivated" ) );
+ }
+ PMPluginInfo* m_info;
+ bool m_enabled;
+};
+
+PMPluginSettings::PMPluginSettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ QVBoxLayout* vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+
+ QGroupBox* gb = new QGroupBox( i18n( "Installed Plugins" ), this );
+ vlayout->addWidget( gb );
+
+ QVBoxLayout* gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+
+ m_pPluginsList = new QListView( gb );
+ connect( m_pPluginsList, SIGNAL( selectionChanged( ) ),
+ SLOT( slotSelectionChanged( ) ) );
+ m_pPluginsList->addColumn( i18n( "Name" ) );
+ m_pPluginsList->addColumn( i18n( "Description" ) );
+ m_pPluginsList->addColumn( i18n( "Status" ) );
+ gvl->addWidget( m_pPluginsList, 1 );
+
+ QHBoxLayout* hl = new QHBoxLayout( gvl );
+ m_pToggle = new QPushButton( i18n( "Load" ), gb );
+ m_pToggle->setEnabled( false );
+ connect( m_pToggle, SIGNAL( clicked( ) ), SLOT( slotToggle( ) ) );
+ hl->addWidget( m_pToggle );
+ hl->addStretch( 1 );
+
+ vlayout->addStretch( 1 );
+}
+
+void PMPluginSettings::displaySettings( )
+{
+ QPtrList<PMPluginInfo> plugins = PMPluginManager::theManager( )->plugins( );
+ QPtrListIterator<PMPluginInfo> it( plugins );
+
+ m_pPluginsList->clear( );
+ for( ; *it; ++it )
+ new PMPluginListViewItem( m_pPluginsList, *it );
+}
+
+void PMPluginSettings::applySettings( )
+{
+ bool changes = false;
+ PMPluginListViewItem* item =
+ ( PMPluginListViewItem* ) m_pPluginsList->firstChild( );
+ for( ; item; item = ( PMPluginListViewItem* ) item->nextSibling( ) )
+ {
+ if( item->m_enabled != item->m_info->enabled( ) )
+ {
+ item->m_info->enable( item->m_enabled );
+ changes = true;
+ }
+ }
+ if( changes )
+ PMPluginManager::theManager( )->updatePlugins( );
+}
+
+bool PMPluginSettings::validateData( )
+{
+ return true;
+}
+
+void PMPluginSettings::displayDefaults( )
+{
+}
+
+void PMPluginSettings::slotToggle( )
+{
+ PMPluginListViewItem* item =
+ ( PMPluginListViewItem* ) m_pPluginsList->currentItem( );
+ if( item )
+ {
+ item->toggleStatus( );
+
+ if( item->m_enabled )
+ m_pToggle->setText( i18n( "Deactivate" ) );
+ else
+ m_pToggle->setText( i18n( "Load" ) );
+ }
+}
+
+void PMPluginSettings::slotSelectionChanged( )
+{
+ PMPluginListViewItem* item =
+ ( PMPluginListViewItem* ) m_pPluginsList->currentItem( );
+ if( item )
+ {
+ m_pToggle->setEnabled( true );
+ if( item->m_enabled )
+ m_pToggle->setText( i18n( "Deactivate" ) );
+ else
+ m_pToggle->setText( i18n( "Load" ) );
+ }
+ else
+ m_pToggle->setEnabled( false );
+}
+
+#include "pmpluginsettings.moc"
diff --git a/kpovmodeler/pmpluginsettings.h b/kpovmodeler/pmpluginsettings.h
new file mode 100644
index 00000000..1ee9191a
--- /dev/null
+++ b/kpovmodeler/pmpluginsettings.h
@@ -0,0 +1,62 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPLUGINSETTINGS_H
+#define PMPLUGINSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+
+class QFrame;
+class QListView;
+class QPushButton;
+
+/**
+ * Plugins configuration dialog page
+ */
+class PMPluginSettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMPluginSettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void displayDefaults( );
+
+protected slots:
+ void slotToggle( );
+ void slotSelectionChanged( );
+
+private:
+ QFrame* m_pPluginOptions;
+ QListView* m_pPluginsList;
+ QPushButton* m_pToggle;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmpoint.cpp b/kpovmodeler/pmpoint.cpp
new file mode 100644
index 00000000..2933030e
--- /dev/null
+++ b/kpovmodeler/pmpoint.cpp
@@ -0,0 +1,98 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpoint.h"
+#include "pmvector.h"
+#include "pmmatrix.h"
+#include "pmmath.h"
+
+
+PMPoint::PMPoint( )
+{
+ m_coord[0] = 0;
+ m_coord[1] = 0;
+ m_coord[2] = 0;
+}
+
+PMPoint::PMPoint( GLdouble x, GLdouble y, GLdouble z )
+{
+ m_coord[0] = x;
+ m_coord[1] = y;
+ m_coord[2] = z;
+}
+
+PMPoint::PMPoint( const PMVector& v )
+{
+ if( v.size( ) == 3 )
+ {
+ m_coord[0] = v[0];
+ m_coord[1] = v[1];
+ m_coord[2] = v[2];
+ }
+ else
+ {
+ m_coord[0] = 0;
+ m_coord[1] = 0;
+ m_coord[2] = 0;
+ }
+}
+
+PMPoint::PMPoint( const PMPoint& p )
+{
+ m_coord[0] = p.m_coord[0];
+ m_coord[1] = p.m_coord[1];
+ m_coord[2] = p.m_coord[2];
+}
+
+PMPoint& PMPoint::operator= ( const PMPoint& p )
+{
+ m_coord[0] = p.m_coord[0];
+ m_coord[1] = p.m_coord[1];
+ m_coord[2] = p.m_coord[2];
+
+ return *this;
+}
+
+void PMPoint::transform( const PMMatrix& m )
+{
+ (*this) = m * (*this);
+}
+
+PMPoint operator* ( const PMMatrix& m, const PMPoint& p )
+{
+ PMPoint result;
+ int c, i;
+ // for homogenous coordinates
+ double u;
+
+ for( c = 0; c < 3; c++ )
+ {
+ result.m_coord[c] = 0.0;
+ for( i = 0; i < 4; i++ )
+ result.m_coord[c] += m[i][c] * ( i<3 ? p[i] : 1.0 );
+ }
+
+ u = 0.0;
+ for( i = 0; i < 4; i++ )
+ u += m[i][3] * ( i<3 ? p[i] : 1.0 );
+ if( !approxZero( u ) )
+ for( i = 0; i < 3; i++ )
+ result.m_coord[i] /= u;
+
+ return result;
+}
diff --git a/kpovmodeler/pmpoint.h b/kpovmodeler/pmpoint.h
new file mode 100644
index 00000000..729d60c0
--- /dev/null
+++ b/kpovmodeler/pmpoint.h
@@ -0,0 +1,122 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPOINT_H
+#define PMPOINT_H
+
+#include "GL/gl.h"
+#include <qmemarray.h>
+
+class PMVector;
+class PMMatrix;
+
+/**
+ * Class for 3d points.
+ *
+ * Used in @ref PMViewStructure.
+ *
+ * Optimized for rendering with opengl
+ */
+
+class PMPoint
+{
+public:
+ /**
+ * Creates a point with coordinates [0,0,0]
+ */
+ PMPoint( );
+ /**
+ * Creates a point with coordinates [x,y,z]
+ */
+ PMPoint( GLdouble x, GLdouble y, GLdouble z );
+ /**
+ * Creates a point from a vector. The size of the vector has to be 3
+ */
+ PMPoint( const PMVector& v );
+ /**
+ * Copy constructor
+ */
+ PMPoint( const PMPoint& p );
+
+ /**
+ * Returns a reference to a coordinate, 0:x, 1:y, 2:z
+ */
+ GLdouble& operator[] ( int index ) { return m_coord[index];}
+ /**
+ * Returns a reference to a coordinate, 0:x, 1:y, 2:z
+ */
+ const GLdouble& operator[] ( int index ) const { return m_coord[index];}
+
+ /**
+ * Returns the x coordinate
+ */
+ GLdouble x( ) const { return m_coord[0]; }
+ /**
+ * Returns the y coordinate
+ */
+ GLdouble y( ) const { return m_coord[1]; }
+ /**
+ * Returns the z coordinate
+ */
+ GLdouble z( ) const { return m_coord[2]; }
+
+ /**
+ * Sets the x coordinate
+ */
+ void setX( const GLdouble newx ) { m_coord[0] = newx; }
+ /**
+ * Sets the y coordinate
+ */
+ void setY( const GLdouble newy ) { m_coord[1] = newy; }
+ /**
+ * Sets the z coordinate
+ */
+ void setZ( const GLdouble newz ) { m_coord[2] = newz; }
+
+ /**
+ * Transforms the point p with the matrix m
+ * @see transform
+ */
+ friend PMPoint operator* ( const PMMatrix& m, const PMPoint& p );
+ /**
+ * Assigns c to the point
+ */
+ PMPoint& operator= ( const PMPoint& c );
+ /**
+ * Transforms the point with the matrix m. Same as p = m * p
+ *
+ * size must be 3!
+ */
+ void transform( const PMMatrix& m );
+
+private:
+ /**
+ * The coords. THIS MEMBER HAS TO BE THE FIRST AND ONLY ONE
+ * (for rendering with OpenGL)!
+ */
+ GLdouble m_coord[3];
+};
+
+/**
+ * @ref QMemArray of PMPoints
+ */
+typedef QMemArray<PMPoint> PMPointArray;
+
+
+#endif
diff --git a/kpovmodeler/pmpolynom.cpp b/kpovmodeler/pmpolynom.cpp
new file mode 100644
index 00000000..93555a58
--- /dev/null
+++ b/kpovmodeler/pmpolynom.cpp
@@ -0,0 +1,238 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpolynom.h"
+#include "pmpolynomedit.h"
+
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+const double c_defaultCoefficients[10] =
+{ // Hyperboloid_Y
+ 1.0, 0.0, 0.0,
+ 0.0, -1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ -1.0
+};
+const int c_defaultOrder = 2;
+const bool c_defaultSturm = true;
+const int c_polynomSize[8] = { 0, 0, 10, 20, 35, 56, 84, 120 };
+
+PMDefinePropertyClass( PMPolynom, PMPolynomProperty );
+
+class PMCoefficientProperty : public PMPropertyBase
+{
+public:
+ PMCoefficientProperty( )
+ : PMPropertyBase( "coefficients", PMVariant::Double )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ m_index = index;
+ }
+ virtual int size( PMObject* object, int /*dimension*/ ) const
+ {
+ return c_polynomSize[ ( ( PMPolynom* ) object )->polynomOrder( ) ];
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& var )
+ {
+ PMPolynom* p = ( PMPolynom* ) obj;
+ PMVector v = p->coefficients( );
+ v[m_index] = var.doubleData( );
+ p->setCoefficients( v );
+
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ PMPolynom* p = ( PMPolynom* ) obj;
+ return PMVariant( p->coefficients( )[m_index] );
+ }
+
+private:
+ int m_index;
+};
+
+PMMetaObject* PMPolynom::s_pMetaObject = 0;
+PMObject* createNewPolynom( PMPart* part )
+{
+ return new PMPolynom( part );
+}
+
+PMPolynom::PMPolynom( PMPart* part )
+ : Base( part )
+{
+ int i;
+ m_order = c_defaultOrder;
+ m_coefficients = PMVector( 10 );
+ for( i = 0; i < 10; i++ )
+ m_coefficients[i] = c_defaultCoefficients[i];
+ m_sturm = c_defaultSturm;
+}
+
+PMPolynom::PMPolynom( const PMPolynom& p )
+ : Base( p )
+{
+ m_order = p.m_order;
+ m_coefficients = p.m_coefficients;
+ m_sturm = p.m_sturm;
+}
+
+PMPolynom::~PMPolynom( )
+{
+}
+
+QString PMPolynom::description( ) const
+{
+ if( m_order == 2 )
+ return i18n( "quadric" );
+ else if( m_order == 3 )
+ return i18n( "cubic" );
+ else if( m_order == 4 )
+ return i18n( "quartic" );
+ return i18n( "polynom" );
+}
+
+void PMPolynom::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "order", m_order );
+ e.setAttribute( "coefficients", m_coefficients.serializeXML( ) );
+ e.setAttribute( "sturm", m_sturm );
+ Base::serialize( e, doc );
+}
+
+void PMPolynom::readAttributes( const PMXMLHelper& h )
+{
+ m_order = h.intAttribute( "order", c_defaultOrder );
+ m_coefficients = h.vectorAttribute( "coefficients", m_coefficients );
+ m_sturm = h.boolAttribute( "sturm", c_defaultSturm );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMPolynom::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Polynom", Base::metaObject( ),
+ createNewPolynom );
+ s_pMetaObject->addProperty(
+ new PMPolynomProperty( "polynomOrder", &PMPolynom::setPolynomOrder,
+ &PMPolynom::polynomOrder ) );
+ s_pMetaObject->addProperty(
+ new PMPolynomProperty( "sturm", &PMPolynom::setSturm,
+ &PMPolynom::sturm ) );
+
+ s_pMetaObject->addProperty( new PMCoefficientProperty( ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMPolynom::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+PMDialogEditBase* PMPolynom::editWidget( QWidget* parent ) const
+{
+ return new PMPolynomEdit( parent );
+}
+
+void PMPolynom::setPolynomOrder( int o )
+{
+ if( ( o < 2 ) || ( o > 7 ) )
+ {
+ kdError( PMArea ) << "Invalid order in PMPolynom::setPolynomOrder\n";
+ o = 2;
+ }
+ if( o != m_order )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMOrderID, m_order );
+ if( ( o <= 4 ) || ( m_order <= 4 ) )
+ m_pMemento->setDescriptionChanged( );
+ }
+ m_order = o;
+ }
+}
+
+void PMPolynom::setCoefficients( const PMVector& c )
+{
+ if( c.size( ) != ( unsigned ) c_polynomSize[m_order] )
+ kdError( PMArea ) << "Wrong vector size in PMPolynom::setCoefficients\n";
+
+ if( c != m_coefficients )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCoefficientsID, m_coefficients );
+ m_coefficients = c;
+ m_coefficients.resize( c_polynomSize[m_order] );
+ //setViewStructureChanged( );
+ }
+}
+
+void PMPolynom::setSturm( bool s )
+{
+ if( m_sturm != s )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSturmID, m_sturm );
+ m_sturm = s;
+ }
+}
+
+void PMPolynom::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMOrderID:
+ setPolynomOrder( data->intData( ) );
+ break;
+ case PMCoefficientsID:
+ setCoefficients( data->vectorData( ) );
+ break;
+ case PMSturmID:
+ setSturm( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMPolynom::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmpolynom.h b/kpovmodeler/pmpolynom.h
new file mode 100644
index 00000000..dc59be67
--- /dev/null
+++ b/kpovmodeler/pmpolynom.h
@@ -0,0 +1,105 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPOLYNOM_H
+#define PMPOLYNOM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+
+/**
+ * Class for povray polynoms.
+ */
+
+class PMPolynom : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMPolynom
+ */
+ PMPolynom( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPolynom( const PMPolynom& p );
+ /**
+ * deletes the PMPolynom
+ */
+ virtual ~PMPolynom( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPolynom( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmpolynom" ); }
+ /**
+ * Returns a new @ref PMPolynomEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ /** */
+ int polynomOrder( ) const { return m_order; }
+ /**
+ * Sets the polynom order
+ */
+ void setPolynomOrder( int order );
+ /**
+ * Returns the coefficients.
+ */
+ PMVector coefficients( ) const { return m_coefficients; }
+ /**
+ * Sets the coefficients.
+ */
+ void setCoefficients( const PMVector& p );
+ /**
+ * Returns the sturm flag
+ */
+ bool sturm( ) const { return m_sturm; }
+ /**
+ * Sets the sturm flag
+ */
+ void setSturm( bool s );
+private:
+ enum PMPolynomMementoID { PMOrderID, PMCoefficientsID, PMSturmID };
+ int m_order;
+ PMVector m_coefficients;
+ bool m_sturm;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmpolynomedit.cpp b/kpovmodeler/pmpolynomedit.cpp
new file mode 100644
index 00000000..b236a8c6
--- /dev/null
+++ b/kpovmodeler/pmpolynomedit.cpp
@@ -0,0 +1,255 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpolynomedit.h"
+#include "pmpolynom.h"
+#include "pmpolynomexponents.h"
+#include "pmlineedits.h"
+#include "pmformulalabel.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kdialog.h>
+
+PMPolynomEdit::PMPolynomEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+ m_currentOrder = 0;
+ m_readOnly = false;
+}
+
+void PMPolynomEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Order" ), this ) );
+ m_pOrder = new QSpinBox( 2, 7, 1, this );
+ hl->addWidget( m_pOrder );
+ hl->addStretch( 1 );
+ connect( m_pOrder, SIGNAL( valueChanged( int ) ), SLOT( slotOrderChanged( int ) ) );
+
+ topLayout( )->addWidget( new QLabel( i18n( "Formula:" ), this ) );
+ m_pPolyWidget = new QWidget( this );
+ topLayout( )->addWidget( m_pPolyWidget );
+ m_pSturm = new QCheckBox( i18n( "Sturm" ), this );
+ topLayout( )->addWidget( m_pSturm );
+ connect( m_pSturm, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMPolynomEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Polynom" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_readOnly = readOnly;
+ m_pDisplayedObject = ( PMPolynom* ) o;
+
+ displayCoefficients( m_pDisplayedObject->coefficients( ),
+ m_pDisplayedObject->polynomOrder( ),
+ m_pDisplayedObject->polynomOrder( ) );
+
+ m_pSturm->setChecked( m_pDisplayedObject->sturm( ) );
+ m_pSturm->setEnabled( !readOnly );
+ if( m_pDisplayedObject->polynomOrder( ) == 2 )
+ m_pSturm->hide( );
+ else
+ m_pSturm->show( );
+
+ bool sb = m_pOrder->signalsBlocked( );
+ m_pOrder->blockSignals( true );
+ m_pOrder->setValue( m_pDisplayedObject->polynomOrder( ) );
+ m_pOrder->blockSignals( sb );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMPolynomEdit: Can't display object\n";
+}
+
+void PMPolynomEdit::displayCoefficients( const PMVector& co, int cOrder,
+ int dOrder )
+{
+ QValueList<PMPolynomExponents>& polynom
+ = PMPolynomExponents::polynom( dOrder );
+
+ if( dOrder != m_currentOrder )
+ {
+ if( m_currentOrder > 0 )
+ {
+ if( m_pPolyWidget->layout( ) )
+ delete m_pPolyWidget->layout( );
+
+ m_labels.setAutoDelete( true );
+ m_labels.clear( );
+ m_labels.setAutoDelete( false );
+ m_edits.setAutoDelete( true );
+ m_edits.clear( );
+ m_edits.setAutoDelete( false );
+ }
+
+ int nedit = polynom.count( );
+ int nr = ( nedit + 2 ) / 3;
+ int i;
+
+ QGridLayout* gl = new QGridLayout( m_pPolyWidget, nr * 2 - 1, 9, 0 );
+ QLabel* l = 0;
+ PMFloatEdit* edit;
+ PMFormulaLabel* fl;
+
+ QValueList<PMPolynomExponents>::ConstIterator it = polynom.begin( );
+ QString text;
+ int row, col;
+ QString plus( "+" );
+
+ for( i = 0; it != polynom.end( ); i++, ++it )
+ {
+ row = ( i / 3 ) * 2;
+ col = ( i % 3 ) * 3;
+
+ if( i != 0 )
+ {
+ l = new QLabel( plus, m_pPolyWidget );
+ m_labels.append( l );
+ gl->addWidget( l, row, col );
+ l->show( );
+ }
+
+ edit = new PMFloatEdit( m_pPolyWidget );
+ connect( edit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ m_edits.append( edit );
+ gl->addWidget( edit, row, col + 1 );
+ edit->show( );
+ edit->setReadOnly( m_readOnly );
+
+ fl = new PMFormulaLabel( *it, m_pPolyWidget );
+
+ m_labels.append( fl );
+ gl->addWidget( fl, row, col + 2 );
+ fl->show( );
+ }
+ for( i = 0; i < ( nr - 1 ); i++ )
+ gl->addRowSpacing( i * 2 + 1, KDialog::spacingHint( ) );
+
+ emit sizeChanged( );
+ }
+ m_currentOrder = dOrder;
+
+
+ if( dOrder == cOrder )
+ {
+ QPtrListIterator<PMFloatEdit> eit( m_edits );
+ int i;
+ for( i = 0; *eit; ++eit, ++i )
+ ( *eit )->setValue( co[i] );
+ }
+ else if( dOrder > cOrder )
+ {
+ QValueList<PMPolynomExponents>::ConstIterator dit = polynom.begin( );
+ QValueList<PMPolynomExponents>& cpoly
+ = PMPolynomExponents::polynom( cOrder );
+ QValueList<PMPolynomExponents>::ConstIterator cit = cpoly.begin( );
+ QPtrListIterator<PMFloatEdit> eit( m_edits );
+ int i = 0;
+
+ for( ; ( dit != polynom.end( ) ) && ( cit != cpoly.end( ) ); ++dit, ++eit )
+ {
+ if( *dit == *cit )
+ {
+ ( *eit )->setValue( co[i] );
+ i++;
+ cit++;
+ }
+ else
+ ( *eit )->setValue( 0.0 );
+ }
+ if( ( dit != polynom.end( ) ) || ( cit != cpoly.end( ) ) )
+ kdError( PMArea ) << "displayExponents is buggy!\n";
+ }
+ else // dOrder < cOrder
+ {
+ QValueList<PMPolynomExponents>::ConstIterator dit = polynom.begin( );
+ QValueList<PMPolynomExponents>& cpoly
+ = PMPolynomExponents::polynom( cOrder );
+ QValueList<PMPolynomExponents>::ConstIterator cit = cpoly.begin( );
+ QPtrListIterator<PMFloatEdit> eit( m_edits );
+ int i = 0;
+
+ for( ; ( dit != polynom.end( ) ) && ( cit != cpoly.end( ) ); ++cit, ++i )
+ {
+ if( *dit == *cit )
+ {
+ ( *eit )->setValue( co[i] );
+ ++eit;
+ ++dit;
+ }
+ }
+ if( ( dit != polynom.end( ) ) || ( cit != cpoly.end( ) ) )
+ kdError( PMArea ) << "displayExponents is buggy!\n";
+ }
+}
+
+PMVector PMPolynomEdit::coefficients( ) const
+{
+ QPtrListIterator<PMFloatEdit> eit( m_edits );
+ int num = m_edits.count( );
+ PMVector v( num );
+ int i;
+
+ for( i = 0 ; *eit; ++eit, ++i )
+ v[i] = ( *eit )->value( );
+ return v;
+}
+
+void PMPolynomEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ m_pDisplayedObject->setPolynomOrder( m_pOrder->value( ) );
+ m_pDisplayedObject->setCoefficients( coefficients( ) );
+
+ Base::saveContents( );
+
+ m_pDisplayedObject->setSturm( m_pSturm->isChecked( ) );
+ }
+}
+
+bool PMPolynomEdit::isDataValid( )
+{
+ QPtrListIterator<PMFloatEdit> eit( m_edits );
+ for( ; *eit; ++eit )
+ if( !( *eit )->isDataValid( ) )
+ return false;
+ return Base::isDataValid( );
+}
+
+void PMPolynomEdit::slotOrderChanged( int order )
+{
+ if( order == 2 )
+ m_pSturm->hide( );
+ else
+ m_pSturm->show( );
+
+ displayCoefficients( coefficients( ), m_currentOrder, order );
+}
+
+#include "pmpolynomedit.moc"
diff --git a/kpovmodeler/pmpolynomedit.h b/kpovmodeler/pmpolynomedit.h
new file mode 100644
index 00000000..6ffb05b4
--- /dev/null
+++ b/kpovmodeler/pmpolynomedit.h
@@ -0,0 +1,80 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPOLYNOMEDIT_H
+#define PMPOLYNOMEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+#include <qptrlist.h>
+
+class PMPolynom;
+class PMFloatEdit;
+class PMFormulaLabel;
+class QSpinBox;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMPolynom
+ */
+class PMPolynomEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMPolynomEdit with parent and name
+ */
+ PMPolynomEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotOrderChanged( int );
+
+private:
+ void displayCoefficients( const PMVector& co, int cOrder, int dOrder );
+ PMVector coefficients( ) const;
+
+ PMPolynom* m_pDisplayedObject;
+
+ int m_currentOrder;
+
+ QWidget* m_pPolyWidget;
+ QPtrList<QWidget> m_labels;
+ QPtrList<PMFloatEdit> m_edits;
+ QCheckBox* m_pSturm;
+ QSpinBox* m_pOrder;
+ bool m_readOnly;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmpolynomexponents.cpp b/kpovmodeler/pmpolynomexponents.cpp
new file mode 100644
index 00000000..fdda7bdf
--- /dev/null
+++ b/kpovmodeler/pmpolynomexponents.cpp
@@ -0,0 +1,71 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpolynomexponents.h"
+#include "pmdebug.h"
+
+bool PMPolynomExponents::m_created[6] = { false, false, false,
+ false, false, false };
+QValueList<PMPolynomExponents> PMPolynomExponents::m_lists[6];
+
+PMPolynomExponents operator+ ( const PMPolynomExponents& p1,
+ const PMPolynomExponents& p2 )
+{
+ return PMPolynomExponents( p1.m_exponents[0] + p2.m_exponents[0],
+ p1.m_exponents[1] + p2.m_exponents[1],
+ p1.m_exponents[2] + p2.m_exponents[2] );
+}
+
+QValueList<PMPolynomExponents>& PMPolynomExponents::polynom( int n )
+{
+ if( ( n < 2 ) || ( n > 7 ) )
+ {
+ n = 2;
+ kdError( PMArea ) << "Wrong polynom order in PMPolynomExponents::polynom( )\n";
+ }
+
+ if( !m_created[n-2] )
+ {
+ m_lists[n-2] = recPolynom( PMPolynomExponents( 0, 0, 0 ), 0, n, 0 );
+ m_created[n-2] = true;
+// kdDebug( PMArea ) << "Polynom n: " << n << " size: " << m_lists[n-2].count( ) << endl;
+ }
+
+ return m_lists[n-2];
+}
+
+QValueList<PMPolynomExponents>
+PMPolynomExponents::recPolynom( const PMPolynomExponents& base,
+ int xyz, int n, int rem )
+{
+ QValueList<PMPolynomExponents> res;
+
+ if( n >= 0 )
+ {
+ if( ( ( rem + n ) == 0 ) || ( xyz > 2 ) )
+ res.append( base );
+ else
+ {
+ PMPolynomExponents newBase = base;
+ newBase.setExponent( xyz, n );
+ res += recPolynom( newBase, xyz + 1, rem, 0 );
+ res += recPolynom( base, xyz, n - 1, rem + 1 );
+ }
+ }
+
+ return res;
+}
diff --git a/kpovmodeler/pmpolynomexponents.h b/kpovmodeler/pmpolynomexponents.h
new file mode 100644
index 00000000..6f1812ba
--- /dev/null
+++ b/kpovmodeler/pmpolynomexponents.h
@@ -0,0 +1,129 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPOLYNOMEXPONENTS_H
+#define PMPOLYNOMEXPONENTS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qptrlist.h>
+#include <qvaluelist.h>
+
+/**
+ * Helper class for the @ref PMPolynomBaseEdit widget
+ */
+class PMPolynomExponents
+{
+public:
+ /**
+ * All exponents are initialized with 0
+ */
+ PMPolynomExponents( )
+ {
+ m_exponents[0] = m_exponents[1] = m_exponents[2] = 0;
+ }
+ /**
+ * The exponents are initialized with x, y, z
+ */
+ PMPolynomExponents( int x, int y, int z )
+ {
+ m_exponents[0] = x;
+ m_exponents[1] = y;
+ m_exponents[2] = z;
+ }
+
+ /**
+ * Returns the ith exponent
+ */
+ int exponent( int i ) const { return m_exponents[i]; }
+ /**
+ * Sets the ith exponent
+ */
+ void setExponent( int i, int exp ) { m_exponents[i] = exp; }
+
+ /**
+ * Returns the x exponent
+ */
+ int xExponent( ) const { return m_exponents[0]; }
+ /**
+ * Sets the x exponent
+ */
+ void setXExponent( int exp ) { m_exponents[0] = exp; }
+ /**
+ * Returns the y exponent
+ */
+ int yExponent( ) const { return m_exponents[1]; }
+ /**
+ * Sets the y exponent
+ */
+ void setYExponent( int exp ) { m_exponents[1] = exp; }
+ /**
+ * Returns the z exponent
+ */
+ int zExponent( ) const { return m_exponents[2]; }
+ /**
+ * Sets the z exponent
+ */
+ void setZExponent( int exp ) { m_exponents[2] = exp; }
+
+ bool operator== ( const PMPolynomExponents& e ) const
+ {
+ return ( m_exponents[0] == e.m_exponents[0] ) &&
+ ( m_exponents[1] == e.m_exponents[1] ) &&
+ ( m_exponents[2] == e.m_exponents[2] );
+ }
+ bool operator!= ( const PMPolynomExponents& e ) const
+ {
+ return !( *this == e );
+ }
+ PMPolynomExponents& operator= ( const PMPolynomExponents& p )
+ {
+ m_exponents[0] = p.m_exponents[0];
+ m_exponents[1] = p.m_exponents[1];
+ m_exponents[2] = p.m_exponents[2];
+ return *this;
+ }
+ friend PMPolynomExponents operator+ ( const PMPolynomExponents& p1,
+ const PMPolynomExponents& p2 );
+
+ /**
+ * Returns the sum of the exponents
+ */
+ int sum( ) const { return m_exponents[0] + m_exponents[1] + m_exponents[2]; }
+
+private:
+ int m_exponents[3];
+
+ // static stuff
+public:
+ /**
+ * Returns the exponents for a polynom with order n ( 2 <= n <= 7 )
+ */
+ static QValueList<PMPolynomExponents>& polynom( int n );
+
+private:
+ static QValueList<PMPolynomExponents> //...
+ recPolynom( const PMPolynomExponents& base, int xyz, int n, int rem );
+ static bool m_created[6];
+ static QValueList<PMPolynomExponents> m_lists[6];
+};
+
+#endif
diff --git a/kpovmodeler/pmpovray31format.cpp b/kpovmodeler/pmpovray31format.cpp
new file mode 100644
index 00000000..417dd177
--- /dev/null
+++ b/kpovmodeler/pmpovray31format.cpp
@@ -0,0 +1,153 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovray31format.h"
+#include "pmpovray31serialization.h"
+
+#include "pmpovrayparser.h"
+#include "pmoutputdevice.h"
+
+#include <klocale.h>
+
+PMPovray31Format::PMPovray31Format( )
+ : PMPovrayFormat( )
+{
+ registerMethod( "BicubicPatch", PMPov31SerBicubicPatch );
+ registerMethod( "BlendMapModifiers", PMPov31SerBlendMapModifiers );
+ registerMethod( "Blob", PMPov31SerBlob );
+ registerMethod( "BlobCylinder", PMPov31SerBlobCylinder );
+ registerMethod( "BlobSphere", PMPov31SerBlobSphere );
+ registerMethod( "BoundedBy", PMPov31SerBoundedBy );
+ registerMethod( "Box", PMPov31SerBox );
+ registerMethod( "BumpMap", PMPov31SerBumpMap );
+ registerMethod( "Camera", PMPov31SerCamera );
+ registerMethod( "ClippedBy", PMPov31SerClippedBy );
+ registerMethod( "Comment", PMPov31SerComment );
+ registerMethod( "CompositeObject", PMPov31SerCompositeObject );
+ registerMethod( "Cone", PMPov31SerCone );
+ registerMethod( "CSG", PMPov31SerCSG );
+ registerMethod( "Cylinder", PMPov31SerCylinder );
+ registerMethod( "Declare", PMPov31SerDeclare );
+ registerMethod( "Density", PMPov31SerDensity );
+ registerMethod( "Disc", PMPov31SerDisc );
+ registerMethod( "Finish", PMPov31SerFinish );
+ registerMethod( "Fog", PMPov31SerFog );
+ registerMethod( "GlobalSettings", PMPov31SerGlobalSettings );
+ registerMethod( "GraphicalObject", PMPov31SerGraphicalObject );
+ registerMethod( "HeightField", PMPov31SerHeightField );
+ registerMethod( "ImageMap", PMPov31SerImageMap );
+ registerMethod( "Interior", PMPov31SerInterior );
+ registerMethod( "JuliaFractal", PMPov31SerJuliaFractal );
+ registerMethod( "Lathe", PMPov31SerLathe );
+ registerMethod( "Light", PMPov31SerLight );
+ registerMethod( "ListPattern", PMPov31SerListPattern );
+ registerMethod( "TextureList", PMPov31SerTextureList );
+ registerMethod( "PigmentList", PMPov31SerPigmentList );
+ registerMethod( "ColorList", PMPov31SerColorList );
+ registerMethod( "DensityList", PMPov31SerDensityList );
+ registerMethod( "NormalList", PMPov31SerNormalList );
+ registerMethod( "LooksLike", PMPov31SerLooksLike );
+ registerMethod( "Material", PMPov31SerMaterial );
+ registerMethod( "MaterialMap", PMPov31SerMaterialMap );
+ registerMethod( "Media", PMPov31SerMedia );
+ registerMethod( "NamedObject", PMPov31SerNamedObject );
+ registerMethod( "Normal", PMPov31SerNormal );
+ registerMethod( "ObjectLink", PMPov31SerObjectLink );
+ registerMethod( "Pattern", PMPov31SerPattern );
+ registerMethod( "Pigment", PMPov31SerPigment );
+ registerMethod( "Plane", PMPov31SerPlane );
+ registerMethod( "Polynom", PMPov31SerPolynom );
+ registerMethod( "PovrayMatrix", PMPov31SerPovrayMatrix );
+ registerMethod( "Prism", PMPov31SerPrism );
+ registerMethod( "QuickColor", PMPov31SerQuickColor );
+ registerMethod( "Rainbow", PMPov31SerRainbow );
+ registerMethod( "Raw", PMPov31SerRaw );
+ registerMethod( "Rotate", PMPov31SerRotate );
+ registerMethod( "Scale", PMPov31SerScale );
+ registerMethod( "Scene", PMPov31SerScene );
+ registerMethod( "SkySphere", PMPov31SerSkySphere );
+ registerMethod( "Slope", PMPov31SerSlope );
+ registerMethod( "SolidColor", PMPov31SerSolidColor );
+ registerMethod( "SolidObject", PMPov31SerSolidObject );
+ registerMethod( "SurfaceOfRevolution", PMPov31SerSurfaceOfRevolution );
+ registerMethod( "Sphere", PMPov31SerSphere );
+ registerMethod( "SuperquadricEllipsoid", PMPov31SerSuperquadricEllipsoid );
+ registerMethod( "Text", PMPov31SerText );
+ registerMethod( "Texture", PMPov31SerTexture );
+ registerMethod( "TextureBase", PMPov31SerTextureBase );
+ registerMethod( "TextureMapBase", PMPov31SerTextureMapBase );
+ registerMethod( "TextureMap", PMPov31SerTextureMap );
+ registerMethod( "PigmentMap", PMPov31SerPigmentMap );
+ registerMethod( "ColorMap", PMPov31SerColorMap );
+ registerMethod( "NormalMap", PMPov31SerNormalMap );
+ registerMethod( "SlopeMap", PMPov31SerSlopeMap );
+ registerMethod( "DensityMap", PMPov31SerDensityMap );
+ registerMethod( "Torus", PMPov31SerTorus );
+ registerMethod( "Translate", PMPov31SerTranslate );
+ registerMethod( "Triangle", PMPov31SerTriangle );
+ registerMethod( "Warp", PMPov31SerWarp );
+ registerMethod( "DetailObject", PMPov31SerDetailObject );
+}
+
+
+PMPovray31Format::~PMPovray31Format( )
+{
+
+}
+
+PMParser* PMPovray31Format::newParser( PMPart* part, QIODevice* dev ) const
+{
+ return new PMPovrayParser( part, dev );
+}
+
+PMParser* PMPovray31Format::newParser( PMPart* part, const QByteArray& data ) const
+{
+ return new PMPovrayParser( part, data );
+}
+
+PMSerializer* PMPovray31Format::newSerializer( QIODevice* dev )
+{
+ return new PMOutputDevice( dev, this );
+}
+
+PMRenderer* PMPovray31Format::newRenderer( PMPart* ) const
+{
+ // TODO
+ return 0;
+}
+
+QString PMPovray31Format::mimeType( ) const
+{
+ return QString( "text/plain" );
+}
+
+QStringList PMPovray31Format::importPatterns( ) const
+{
+ QStringList result;
+ result.push_back( QString( "*.pov *.inc|" )
+ + i18n( "POV-Ray 3.1 Files (*.pov, *.inc)" ) );
+ return result;
+}
+
+QStringList PMPovray31Format::exportPatterns( ) const
+{
+ QStringList result;
+ result.push_back( QString( "*.pov|" ) + i18n( "POV-Ray 3.1 Files (*.pov)" ) );
+ result.push_back( QString( "*.ini|" ) + i18n( "POV-Ray 3.1 Include Files (*.ini)" ) );
+ return result;
+
+}
diff --git a/kpovmodeler/pmpovray31format.h b/kpovmodeler/pmpovray31format.h
new file mode 100644
index 00000000..a0e3453e
--- /dev/null
+++ b/kpovmodeler/pmpovray31format.h
@@ -0,0 +1,64 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAY31_FORMAT_H
+#define PMPOVRAY31_FORMAT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmpovrayformat.h"
+
+/**
+ * Description class for POV-Ray 3.1
+ */
+class PMPovray31Format : public PMPovrayFormat
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMPovray31Format( );
+ /**
+ * Destructor
+ */
+ virtual ~PMPovray31Format( );
+
+ /** */
+ virtual QString name( ) const { return "povray31"; };
+ /** */
+ virtual QString description( ) const { return "POV-Ray 3.1"; }
+ /** */
+ virtual int services( ) const { return AllServices; }
+ /** */
+ virtual PMParser* newParser( PMPart*, QIODevice* ) const;
+ /** */
+ virtual PMParser* newParser( PMPart*, const QByteArray& ) const;
+ /** */
+ virtual PMSerializer* newSerializer( QIODevice* );
+ /** */
+ virtual PMRenderer* newRenderer( PMPart* ) const;
+ /** */
+ virtual QString mimeType( ) const;
+ /** */
+ virtual QStringList importPatterns( ) const;
+ /** */
+ virtual QStringList exportPatterns( ) const;
+};
+
+#endif
diff --git a/kpovmodeler/pmpovray31serialization.cpp b/kpovmodeler/pmpovray31serialization.cpp
new file mode 100644
index 00000000..dd4b7603
--- /dev/null
+++ b/kpovmodeler/pmpovray31serialization.cpp
@@ -0,0 +1,2199 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovray31serialization.h"
+#include "pmoutputdevice.h"
+#include "pmallobjects.h"
+
+const double c_defaultPatchFlatness = 0;
+
+void PMPov31SerBicubicPatch( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMBicubicPatch* o = ( PMBicubicPatch* ) object;
+
+ int u, v;
+ QString str, line;
+ dev->objectBegin( "bicubic_patch" );
+
+ dev->writeName( object->name( ) );
+
+ str.setNum( o->patchType( ) );
+ dev->writeLine( "type " + str );
+ if( !approx( o->flatness( ), c_defaultPatchFlatness ) )
+ {
+ str.setNum( o->flatness( ) );
+ dev->writeLine( "flatness " + str );
+ }
+ str.setNum( o->uSteps( ) );
+ dev->writeLine( "u_steps " + str );
+ str.setNum( o->vSteps( ) );
+ dev->writeLine( "v_steps " + str );
+
+ for( v = 0; v < 4; v++ )
+ {
+ line = o->controlPoint( v*4 ).serialize( );
+ for( u = 1; u < 4; u++ )
+ line += QString( ", " ) + o->controlPoint( u+4*v ).serialize( );
+ if( v != 3 )
+ line += ",";
+ dev->writeLine( line );
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerBlendMapModifiers( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMBlendMapModifiers* o = ( PMBlendMapModifiers* ) object;
+
+ QString str;
+
+ if( o->isFrequencyEnabled( ) )
+ {
+ str.setNum( o->frequency( ) );
+ dev->writeLine( "frequency " + str );
+ }
+
+ if( o->isPhaseEnabled( ) )
+ {
+ str.setNum( o->phase( ) );
+ dev->writeLine( "phase " + str );
+ }
+
+ if( o->isWaveFormEnabled( ) )
+ {
+ switch( o->waveFormType( ) )
+ {
+ case PMBlendMapModifiers::RampWave:
+ dev->writeLine( "ramp_wave" );
+ break;
+ case PMBlendMapModifiers::TriangleWave:
+ dev->writeLine( "triangle_wave" );
+ break;
+ case PMBlendMapModifiers::SineWave:
+ dev->writeLine( "sine_wave" );
+ break;
+ case PMBlendMapModifiers::ScallopWave:
+ dev->writeLine( "scallop_wave" );
+ break;
+ case PMBlendMapModifiers::CubicWave:
+ dev->writeLine( "cubic_wave" );
+ break;
+ case PMBlendMapModifiers::PolyWave:
+ str.setNum( o->waveFormExponent( ) );
+ dev->writeLine( "poly_wave " + str );
+ break;
+ }
+ }
+}
+
+void PMPov31SerBlob( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMBlob* o = ( PMBlob* ) object;
+
+ dev->objectBegin( "blob" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( QString( "threshold %1" ).arg( o->threshold( ) ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->sturm( ) )
+ dev->writeLine( "sturm" );
+ if( o->hierarchy( ) )
+ dev->writeLine( "hierarchy" );
+
+ dev->objectEnd( );
+}
+
+void PMPov31SerBlobCylinder( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMBlobCylinder* o = ( PMBlobCylinder* ) object;
+
+ dev->objectBegin( "cylinder" );
+
+ dev->writeName( object->name( ) );
+ QString str1;
+ str1.setNum( o->radius( ) );
+ dev->writeLine( o->end1( ).serialize( ) + ", " + o->end2( ).serialize( )
+ + ", " + str1 + "," );
+ dev->writeLine( QString( "strength %1" ).arg( o->strength( ) ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerBlobSphere( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMBlobSphere* o = ( PMBlobSphere* ) object;
+
+ dev->objectBegin( "sphere" );
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->centre( ).serialize( ) + QString( ", %1," ).arg( o->radius( ) ) );
+ dev->writeLine( QString( "strength %1" ).arg( o->strength( ) ) );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerBoundedBy( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMBoundedBy* o = ( PMBoundedBy* ) object;
+
+ dev->objectBegin( "bounded_by" );
+ if( o->clippedBy( ) )
+ dev->writeLine( "clipped_by" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerBox( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMBox* o = ( PMBox* ) object;
+
+ dev->objectBegin( "box" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->corner1( ).serialize( ) + ", " + o->corner2( ).serialize( ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerBumpMap( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMBumpMap* o = ( PMBumpMap* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "bump_map" );
+
+ switch( o->bitmapType( ) )
+ {
+ case PMBumpMap::BitmapGif:
+ dev->writeLine( "gif" );
+ break;
+ case PMBumpMap::BitmapTga:
+ dev->writeLine( "tga" );
+ break;
+ case PMBumpMap::BitmapIff:
+ dev->writeLine( "iff" );
+ break;
+ case PMBumpMap::BitmapPpm:
+ dev->writeLine( "ppm" );
+ break;
+ case PMBumpMap::BitmapPgm:
+ dev->writeLine( "pgm" );
+ break;
+ case PMBumpMap::BitmapPng:
+ dev->writeLine( "png" );
+ break;
+ case PMBumpMap::BitmapJpeg:
+ dev->writeLine( "jpeg" );
+ break;
+ case PMBumpMap::BitmapTiff:
+ dev->writeLine( "tiff" );
+ break;
+ case PMBumpMap::BitmapSys:
+ dev->writeLine( "sys" );
+ break;
+ }
+
+ dev->writeLine( "\"" + o->bitmapFile( ) + "\"" );
+
+ if( o->isOnceEnabled( ) )
+ dev->writeLine( "once" );
+
+ switch( o->mapType( ) )
+ {
+ case PMBumpMap::MapPlanar:
+ dev->writeLine( "map_type 0" );
+ break;
+ case PMBumpMap::MapSpherical:
+ dev->writeLine( "map_type 1" );
+ break;
+ case PMBumpMap::MapCylindrical:
+ dev->writeLine( "map_type 2" );
+ break;
+ case PMBumpMap::MapToroidal:
+ dev->writeLine( "map_type 5" );
+ break;
+ }
+ switch( o->interpolateType( ) )
+ {
+ case PMBumpMap::InterpolateBilinear:
+ dev->writeLine( "interpolate 2" );
+ break;
+ case PMBumpMap::InterpolateNormalized:
+ dev->writeLine( "interpolate 4" );
+ break;
+ default:
+ break;
+ }
+
+ if( o->isUseIndexEnabled( ) )
+ dev->writeLine( "use_index" );
+
+ if( o->bumpSize( ) )
+ {
+ str1.setNum( o->bumpSize( ) );
+ dev->writeLine( "bump_size " + str1 );
+ }
+
+ dev->objectEnd( );
+}
+
+void PMPov31SerCamera( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMCamera* o = ( PMCamera* ) object;
+
+ dev->objectBegin( "camera" );
+ QString str;
+
+ dev->writeName( object->name( ) );
+
+ if( o->cameraType( ) == PMCamera::Cylinder )
+ {
+ str.setNum( o->cylinderType( ) );
+ dev->writeLine( "cylinder " + str );
+ }
+ else
+ dev->writeLine( o->cameraTypeToString( o->cameraType( ) ) );
+
+ dev->writeLine( "location " + o->location( ).serialize( ) );
+ dev->writeLine( "sky " + o->sky( ).serialize( ) );
+ dev->writeLine( "direction " + o->direction( ).serialize( ) );
+ dev->writeLine( "right " + o->right( ).serialize( ) );
+ dev->writeLine( "up " + o->up( ).serialize( ) );
+ dev->writeLine( "look_at " + o->lookAt( ).serialize( ) );
+
+ if( ( o->cameraType( ) != PMCamera::Orthographic ) &&
+ ( o->cameraType( ) != PMCamera::Omnimax ) &&
+ ( o->cameraType( ) != PMCamera::Panoramic ) && o->isAngleEnabled( ) )
+ {
+ str.setNum( o->angle( ) );
+ dev->writeLine( "angle " + str );
+ }
+ if( o->isFocalBlurEnabled( ) && ( o->cameraType( ) == PMCamera::Perspective ) )
+ {
+ str.setNum( o->aperture( ) );
+ dev->writeLine( "aperture " + str );
+ str.setNum( o->blurSamples( ) );
+ dev->writeLine( "blur_samples " + str );
+ dev->writeLine( "focal_point " + o->focalPoint( ).serialize( ) );
+ str.setNum( o->confidence( ) );
+ dev->writeLine( "confidence " + str );
+ str.setNum( o->variance( ) );
+ dev->writeLine( "variance " + str );
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerClippedBy( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMClippedBy* o = ( PMClippedBy* ) object;
+
+ dev->objectBegin( "clipped_by" );
+ if( o->boundedBy( ) )
+ dev->writeLine( "bounded_by" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerComment( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMComment* o = ( PMComment* ) object;
+
+ dev->writeComment( o->text( ) );
+}
+
+void PMPov31SerCompositeObject( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMCompositeObject* o = ( PMCompositeObject* ) object;
+
+ PMObject* tmp;
+
+ for( tmp = o->firstChild( ); tmp; tmp = tmp->nextSibling( ) )
+ if( tmp->exportPovray( ) )
+ dev->serialize( tmp );
+}
+
+void PMPov31SerCone( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMCone* o = ( PMCone* ) object;
+
+ dev->objectBegin( "cone" );
+
+ dev->writeName( object->name( ) );
+ QString str1;
+ str1.setNum( o->radius1( ) );
+ dev->writeLine( o->end1( ).serialize( ) + ", " + str1 + "," );
+ str1.setNum( o->radius2( ) );
+ dev->writeLine( o->end2( ).serialize( ) + ", " + str1 );
+ if( o->open( ) )
+ dev->writeLine( QString( "open" ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerCSG( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMCSG* o = ( PMCSG* ) object;
+
+ switch( o->csgType( ) )
+ {
+ case PMCSG::CSGUnion:
+ dev->objectBegin( "union" );
+ break;
+ case PMCSG::CSGIntersection:
+ dev->objectBegin( "intersection" );
+ break;
+ case PMCSG::CSGDifference:
+ dev->objectBegin( "difference" );
+ break;
+ case PMCSG::CSGMerge:
+ dev->objectBegin( "merge" );
+ break;
+ }
+
+ dev->writeName( object->name( ) );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerCylinder( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMCylinder* o = ( PMCylinder* ) object;
+
+ dev->objectBegin( "cylinder" );
+
+ dev->writeName( object->name( ) );
+ QString str1;
+ str1.setNum( o->radius( ) );
+ dev->writeLine( o->end1( ).serialize( ) + ", " + o->end2( ).serialize( )
+ + ", " + str1 );
+ if( o->open( ) )
+ dev->writeLine( QString( "open" ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerDeclare( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMDeclare* o = ( PMDeclare* ) object;
+
+ if( o->firstChild( ) )
+ {
+ dev->declareBegin( o->id( ) );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ }
+}
+
+void PMPov31SerDensity( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ bool bObject = true;
+ if( object->parent( ) )
+ if( object->parent( )->type( ) == "DensityMap" )
+ bObject = false;
+
+ if( bObject )
+ dev->objectBegin( "density" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ if( bObject )
+ dev->objectEnd( );
+}
+
+void PMPov31SerDisc( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMDisc* o = ( PMDisc* ) object;
+
+ dev->objectBegin( "disc" );
+
+ dev->writeName( object->name( ) );
+ QString str1, str2;
+ str1.setNum( o->radius( ) );
+ if( o->radius( ) != 0.0 )
+ {
+ str2.setNum( o->holeRadius( ) );
+ dev->writeLine( o->center( ).serialize( ) + "," + o->normal( ).serialize( ) + ", " + str1 + "," + str2 );
+ }
+ else
+ {
+ dev->writeLine( o->center( ).serialize( ) + "," + o->normal( ).serialize( ) + ", " + str1 );
+ }
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerFinish( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMFinish* o = ( PMFinish* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "finish" );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->isAmbientEnabled( ) )
+ dev->writeLine( "ambient " + o->ambientColor( ).serialize( ) );
+ if( o->isDiffuseEnabled( ) )
+ {
+ str1.setNum( o->diffuse( ) );
+ dev->writeLine( "diffuse " + str1 );
+ }
+ if( o->isBrillianceEnabled( ) )
+ {
+ str1.setNum( o->brilliance( ) );
+ dev->writeLine( "brilliance " + str1 );
+ }
+ if( o->isPhongEnabled( ) )
+ {
+ str1.setNum( o->phong( ) );
+ dev->writeLine( "phong " + str1 );
+ }
+ if( o->isPhongSizeEnabled( ) )
+ {
+ str1.setNum( o->phongSize( ) );
+ dev->writeLine( "phong_size " + str1 );
+ }
+ if( o->isMetallicEnabled( ) )
+ {
+ str1.setNum( o->metallic( ) );
+ dev->writeLine( "metallic " + str1 );
+ }
+ if( o->isSpecularEnabled( ) )
+ {
+ str1.setNum( o->specular( ) );
+ dev->writeLine( "specular " + str1 );
+ }
+ if( o->isRoughnessEnabled( ) )
+ {
+ str1.setNum( o->roughness( ) );
+ dev->writeLine( "roughness " + str1 );
+ }
+ if( o->isReflectionEnabled( ) )
+ {
+ dev->writeLine( "reflection " + o->reflectionColor( ).serialize( ) );
+ }
+ if( o->isExponentEnabled( ) )
+ {
+ str1.setNum( o->reflectionExponent( ) );
+ dev->writeLine( "reflection_exponent " + str1 );
+ }
+ if( o->irid( ) )
+ {
+ str1.setNum( o->iridAmount( ) );
+ dev->writeLine( "irid { " + str1 );
+ str1.setNum( o->iridThickness( ) );
+ dev->writeLine( "thickness " + str1 );
+ str1.setNum( o->iridTurbulence( ) );
+ dev->writeLine( "turbulence " + str1 + " } " );
+ }
+ if( o->isCrandEnabled( ) )
+ {
+ str1.setNum( o->crand( ) );
+ dev->writeLine( "crand " + str1 );
+ }
+ dev->objectEnd( );
+}
+
+const int c_defaultFogOctaves = 6;
+const double c_defaultFogLambda = 2.0;
+const double c_defaultFogOmega = 0.5;
+const double c_defaultFogTurbDepth = 0.5;
+
+void PMPov31SerFog( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMFog* o = ( PMFog* ) object;
+
+ QString str;
+
+ dev->objectBegin( "fog" );
+
+ // Serialize the name of this object
+ dev->writeName( object->name( ) );
+
+ // Serialize a possible link
+ if( o->linkedObject( ) )
+ {
+ if( o->linkedObject( )->firstChild( ) )
+ dev->writeLine( o->linkedObject( )->id( ) );
+ else
+ {
+ QString text;
+ text = o->name( );
+ if( text.isEmpty( ) )
+ text = o->description( );
+
+ dev->writeComment( QString( "No prototype for %1" ).arg( text ) );
+ }
+ }
+
+ str.setNum( o->fogType( ) );
+ dev->writeLine( "fog_type " + str );
+
+ str.setNum( o->distance( ) );
+ dev->writeLine( "distance " + str );
+ dev->writeLine( " " + o->color( ).serialize( ) + " " );
+ if( o->isTurbulenceEnabled( ) )
+ {
+ dev->writeLine( "turbulence " + o->valueVector( ).serialize( ) );
+ if( o->octaves( ) != c_defaultFogOctaves )
+ {
+ str.setNum(o->octaves( ));
+ dev->writeLine( "octaves " + str );
+ }
+ if( o->omega( ) != c_defaultFogOmega )
+ {
+ str.setNum(o->omega( ));
+ dev->writeLine( "omega " + str );
+ }
+ if( o->lambda( ) != c_defaultFogLambda )
+ {
+ str.setNum(o->lambda( ));
+ dev->writeLine( "lambda " + str );
+ }
+ if( o->depth( ) != c_defaultFogTurbDepth )
+ {
+ str.setNum(o->depth( ));
+ dev->writeLine( "turb_depth " + str );
+ }
+ }
+ if( o->fogType( ) == 2 )
+ {
+ // Serialize ground fog variables
+ str.setNum( o->fogOffset( ) );
+ dev->writeLine( "fog_offset " + str );
+ str.setNum( o->fogAlt( ) );
+ dev->writeLine( "fog_alt " + str );
+ dev->writeLine( "up " + o->up( ).serialize( ) );
+ }
+ // Serialize the children of this object
+ dev->callSerialization( object, object->metaObject( )->superClass( )->superClass( ) );
+ dev->objectEnd( );
+}
+
+const double c_defaultGlobalSettingsAdcBailout = 1.0 / 255.0;
+const PMColor c_defaultGlobalSettingsAmbientLight = PMColor( 1.0, 1.0, 1.0, 0.0, 0.0 );
+const double c_defaultGlobalSettingsAssumedGamma = 0.0;
+const bool c_defaultGlobalSettingsHfGray16 = false;
+const PMColor c_defaultGlobalSettingsIridWaveLength = PMColor( 0.25, 0.18, 0.14, 0.0, 0.0 );
+const int c_defaultGlobalSettingsMaxIntersections = 0; // ???
+const int c_defaultGlobalSettingsMaxTraceLevel = 0; // ???
+const int c_defaultGlobalSettingsNumberWaves = 10;
+const bool c_defaultGlobalSettingsRadiosity = false;
+const double c_defaultGlobalSettingsBrightness = 1.0;
+const int c_defaultGlobalSettingsCount = 35;
+const double c_defaultGlobalSettingsDistanceMaximum = 0; // ???
+const double c_defaultGlobalSettingsErrorBound = 1.8;
+const double c_defaultGlobalSettingsGrayThreshold = 0.0;
+const double c_defaultGlobalSettingsLowErrorFactor = 0.5;
+const double c_defaultGlobalSettingsMinimumReuse = 0.015;
+const int c_defaultGlobalSettingsNearestCount = 5;
+const int c_defaultGlobalSettingsRecursionLimit = 2;
+
+void PMPov31SerGlobalSettings( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMGlobalSettings* o = ( PMGlobalSettings* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "global_settings" );
+
+ if( o->adcBailout( ) != c_defaultGlobalSettingsAdcBailout )
+ {
+ str1.setNum( o->adcBailout( ) );
+ dev->writeLine( "adc_bailout " + str1 );
+ }
+ if( o->ambientLight( ) != c_defaultGlobalSettingsAmbientLight )
+ dev->writeLine( "ambient_light " + o->ambientLight( ).serialize( ) );
+ if( o->assumedGamma( ) != c_defaultGlobalSettingsAssumedGamma )
+ {
+ str1.setNum( o->assumedGamma( ) );
+ dev->writeLine( "assumed_gamma " + str1 );
+ }
+ if( o->hfGray16( ) != c_defaultGlobalSettingsHfGray16 )
+ {
+ if( o->hfGray16( ) )
+ dev->writeLine( "hf_gray_16 on" );
+ else
+ dev->writeLine( "hf_gray_16 off" );
+ }
+ if( o->iridWaveLength( ) != c_defaultGlobalSettingsIridWaveLength )
+ dev->writeLine( "irid_wavelength " + o->iridWaveLength( ).serialize( ) );
+ if( o->maxTraceLevel( ) != c_defaultGlobalSettingsMaxTraceLevel )
+ {
+ str1.setNum( o->maxTraceLevel( ) );
+ dev->writeLine( "max_trace_level " + str1 );
+ }
+ if( o->maxIntersections( ) != c_defaultGlobalSettingsMaxIntersections )
+ {
+ str1.setNum( o->maxIntersections( ) );
+ dev->writeLine( "max_intersections " + str1 );
+ }
+ if( o->numberWaves( ) != c_defaultGlobalSettingsNumberWaves )
+ {
+ str1.setNum( o->numberWaves( ) );
+ dev->writeLine( "number_of_waves " + str1 );
+ }
+ if( o->isRadiosityEnabled( ) )
+ {
+ dev->objectBegin( "radiosity" );
+ if( o->brightness( ) != c_defaultGlobalSettingsBrightness )
+ {
+ str1.setNum( o->brightness( ) );
+ dev->writeLine( "brightness " + str1 );
+ }
+ if( o->count( ) != c_defaultGlobalSettingsCount )
+ {
+ str1.setNum( o->count( ) );
+ dev->writeLine( "count " + str1 );
+ }
+ if( o->distanceMaximum( ) != c_defaultGlobalSettingsDistanceMaximum )
+ {
+ str1.setNum( o->distanceMaximum( ) );
+ dev->writeLine( "distance_maximum " + str1 );
+ }
+ if( o->errorBound( ) != c_defaultGlobalSettingsErrorBound )
+ {
+ str1.setNum( o->errorBound( ) );
+ dev->writeLine( "error_bound " + str1 );
+ }
+ if( o->grayThreshold( ) != c_defaultGlobalSettingsGrayThreshold )
+ {
+ str1.setNum( o->grayThreshold( ) );
+ dev->writeLine( "gray_threshold " + str1 );
+ }
+ if( o->lowErrorFactor( ) != c_defaultGlobalSettingsLowErrorFactor )
+ {
+ str1.setNum( o->lowErrorFactor( ) );
+ dev->writeLine( "low_error_factor " + str1 );
+ }
+ if( o->minimumReuse( ) != c_defaultGlobalSettingsMinimumReuse )
+ {
+ str1.setNum( o->minimumReuse( ) );
+ dev->writeLine( "minimuo->reuse( ) " + str1 );
+ }
+ if( o->nearestCount( ) != c_defaultGlobalSettingsNearestCount )
+ {
+ str1.setNum( o->nearestCount( ) );
+ dev->writeLine( "nearest_count " + str1 );
+ }
+ if( o->recursionLimit( ) != c_defaultGlobalSettingsRecursionLimit )
+ {
+ str1.setNum( o->recursionLimit( ) );
+ dev->writeLine( "recursion_limit " + str1 );
+ }
+ dev->objectEnd( );
+ }
+ dev->objectEnd( );
+}
+
+void PMPov31SerGraphicalObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMGraphicalObject* o = ( PMGraphicalObject* ) object;
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ if( o->noShadow( ) )
+ dev->writeLine( "no_shadow" );
+}
+
+void PMPov31SerHeightField( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMHeightField* o = ( PMHeightField* ) object;
+
+ dev->objectBegin( "height_field" );
+
+ dev->writeName( object->name( ) );
+
+ dev->writeLine( o->typeToString( o->heightFieldType( ) ) + " \"" + o->fileName( ) + "\"" );
+ if( o->waterLevel( ) > 0.0 )
+ dev->writeLine( QString( "water_level %1" ).arg( o->waterLevel( ) ) );
+ if( !o->hierarchy( ) )
+ dev->writeLine( "hierarchy off" );
+ if( o->smooth( ) )
+ dev->writeLine( "smooth" );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerImageMap( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMImageMap* o = ( PMImageMap* ) object;
+
+ typedef QValueList<PMPaletteValue> PMPaletteValueList;
+ PMPaletteValueList values;
+ PMPaletteValueList::ConstIterator tmpPalette;
+ QString str1, str2;
+
+ dev->objectBegin( "image_map" );
+
+ switch( o->bitmapType( ) )
+ {
+ case PMImageMap::BitmapGif:
+ dev->writeLine( "gif" );
+ break;
+ case PMImageMap::BitmapTga:
+ dev->writeLine( "tga" );
+ break;
+ case PMImageMap::BitmapIff:
+ dev->writeLine( "iff" );
+ break;
+ case PMImageMap::BitmapPpm:
+ dev->writeLine( "ppm" );
+ break;
+ case PMImageMap::BitmapPgm:
+ dev->writeLine( "pgm" );
+ break;
+ case PMImageMap::BitmapPng:
+ dev->writeLine( "png" );
+ break;
+ case PMImageMap::BitmapJpeg:
+ dev->writeLine( "jpeg" );
+ break;
+ case PMImageMap::BitmapTiff:
+ dev->writeLine( "tiff" );
+ break;
+ case PMImageMap::BitmapSys:
+ dev->writeLine( "sys" );
+ break;
+ }
+
+ dev->writeLine( "\"" + o->bitmapFile( ) + "\"" );
+
+ values = o->filters( );
+ for( tmpPalette = values.begin( ); tmpPalette != values.end( ); ++tmpPalette )
+ {
+ str1.setNum( ( *tmpPalette ).index( ) );
+ str2.setNum( ( *tmpPalette ).value( ) );
+ dev->writeLine( "filter " + str1 + ", " + str2 );
+ }
+
+ values = o->transmits( );
+ for( tmpPalette = values.begin( ); tmpPalette != values.end( ); ++tmpPalette )
+ {
+ str1.setNum( ( *tmpPalette ).index( ) );
+ str2.setNum( ( *tmpPalette ).value( ) );
+ dev->writeLine( "transmit " + str1 + ", " + str2 );
+ }
+
+ if( o->isFilterAllEnabled( ) )
+ {
+ str1.setNum( o->filterAll( ) );
+ dev->writeLine( "filter all " + str1 );
+ }
+
+ if( o->isTransmitAllEnabled( ) )
+ {
+ str1.setNum( o->transmitAll( ) );
+ dev->writeLine( "transmit all " + str1 );
+ }
+
+ if( o->isOnceEnabled( ) )
+ dev->writeLine( "once" );
+
+ switch( o->mapType( ) )
+ {
+ case PMImageMap::MapPlanar:
+ dev->writeLine( "map_type 0" );
+ break;
+ case PMImageMap::MapSpherical:
+ dev->writeLine( "map_type 1" );
+ break;
+ case PMImageMap::MapCylindrical:
+ dev->writeLine( "map_type 2" );
+ break;
+ case PMImageMap::MapToroidal:
+ dev->writeLine( "map_type 5" );
+ break;
+ }
+ switch( o->interpolateType( ) )
+ {
+ case PMImageMap::InterpolateBilinear:
+ dev->writeLine( "interpolate 2" );
+ break;
+ case PMImageMap::InterpolateNormalized:
+ dev->writeLine( "interpolate 4" );
+ break;
+ default:
+ break;
+ }
+
+ dev->objectEnd( );
+}
+
+void PMPov31SerInterior( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMInterior* o = ( PMInterior* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "interior" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->isIorEnabled( ) )
+ {
+ str1.setNum( o->ior( ) );
+ dev->writeLine( "ior " + str1 );
+ }
+ if( o->isCausticsEnabled( ) )
+ {
+ str1.setNum( o->caustics( ) );
+ dev->writeLine( "caustics " + str1 );
+ }
+ if( o->isFadeDistanceEnabled( ) )
+ {
+ str1.setNum( o->fadeDistance( ) );
+ dev->writeLine( "fade_distance " + str1 );
+ }
+ if( o->isFadeDistanceEnabled( ) )
+ {
+ str1.setNum( o->fadeDistance( ) );
+ dev->writeLine( "fade_distance " + str1 );
+ }
+ dev->objectEnd( );
+}
+
+void PMPov31SerJuliaFractal( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMJuliaFractal* o = ( PMJuliaFractal* ) object;
+
+ dev->objectBegin( "julia_fractal" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->juliaParameter( ).serialize( ) );
+ dev->writeLine( o->algebraTypeToString( o->algebraType( ) ) );
+
+ if( o->functionType( ) == PMJuliaFractal::FTpwr )
+ dev->writeLine( QString( "pwr(%1, %2)" ).arg( o->exponent( )[0] ).
+ arg( o->exponent( )[1] ) );
+ else
+ dev->writeLine( o->functionTypeToString( o->functionType( ) ) );
+
+ dev->writeLine( QString( "max_iteration %1" ).arg( o->maximumIterations( ) ) );
+ dev->writeLine( QString( "precision %1" ).arg( o->precision( ) ) );
+ dev->writeLine( QString( "slice %1, %2" ).arg( o->sliceNormal( ).serialize( ) )
+ .arg( o->sliceDistance( ) ) );
+
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerLathe( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMLathe* o = ( PMLathe* ) object;
+
+ dev->objectBegin( "lathe" );
+
+ dev->writeName( object->name( ) );
+
+ switch( o->splineType( ) )
+ {
+ case PMLathe::LinearSpline:
+ dev->writeLine( "linear_spline" );
+ break;
+ case PMLathe::QuadraticSpline:
+ dev->writeLine( "quadratic_spline" );
+ break;
+ case PMLathe::CubicSpline:
+ dev->writeLine( "cubic_spline" );
+ break;
+ case PMLathe::BezierSpline:
+ dev->writeLine( "bezier_spline" );
+ break;
+ }
+
+ int num = o->points( ).count( );
+ dev->writeLine( QString( "%1," ).arg( num ) );
+
+ bool first = true;
+ QValueList<PMVector> points = o->points( );
+ QValueList<PMVector>::ConstIterator it = points.begin( );
+ for( ; it != points.end( ); ++it )
+ {
+ if( !first )
+ dev->write( ", " );
+ dev->write( ( *it ).serialize( ) );
+ first = false;
+ }
+ dev->writeLine( "" );
+
+ if( o->sturm( ) )
+ dev->writeLine( "sturm" );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+const double c_defaultLightTightness = 10;
+const int c_defaultLightAdaptive = 0;
+
+void PMPov31SerLight( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMLight* o = ( PMLight* ) object;
+
+ dev->objectBegin( QString( "light_source" ) );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->location( ).serialize( ) + ", " + o->color( ).serialize( ) );
+
+ if( o->lightType( ) == PMLight::SpotLight )
+ dev->writeLine( QString( "spotlight" ) );
+ else if( o->lightType( ) == PMLight::CylinderLight )
+ dev->writeLine( QString( "cylinder" ) );
+ else if( o->lightType( ) == PMLight::ShadowlessLight )
+ dev->writeLine( QString( "shadowless" ) );
+
+ if( ( o->lightType( ) == PMLight::SpotLight ) ||
+ ( o->lightType( ) == PMLight::CylinderLight ) )
+ {
+ dev->writeLine( QString( "radius %1" ).arg( o->radius( ) ) );
+ dev->writeLine( QString( "falloff %1" ).arg( o->falloff( ) ) );
+ if( o->tightness( ) != c_defaultLightTightness )
+ dev->writeLine( QString( "tightness %1" ).arg( o->tightness( ) ) );
+ dev->writeLine( QString( "point_at " ) + o->pointAt( ).serialize( ) );
+ }
+
+ if( o->isAreaLight( ) )
+ {
+ dev->writeLine( QString( "area_light " ) + o->axis1( ).serialize( )
+ + QString( ", " ) + o->axis2( ).serialize( )
+ + QString( ", %1, %2" ).arg( o->size1( ) ).arg( o->size2( ) ) );
+ if( o->adaptive( ) != c_defaultLightAdaptive )
+ dev->writeLine( QString( "adaptive %1" ).arg( o->adaptive( ) ) );
+ if( o->jitter( ) )
+ dev->writeLine( QString( "jitter" ) );
+ }
+
+ if( o->fading( ) )
+ {
+ dev->writeLine( QString( "fade_distance %1" ).arg( o->fadeDistance( ) ) );
+ dev->writeLine( QString( "fade_power %1" ).arg( o->fadePower( ) ) );
+ }
+
+ if( !o->mediaInteraction( ) )
+ dev->writeLine( QString( "media_interaction off" ) );
+ if( !o->mediaAttenuation( ) )
+ dev->writeLine( QString( "media_attenuation off" ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerListPattern( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMListPattern* o = ( PMListPattern* ) object;
+
+ QString str1;
+
+ switch( o->listType( ) )
+ {
+ case PMListPattern::ListPatternBrick:
+ dev->writeLine( "brick" );
+ break;
+ case PMListPattern::ListPatternChecker:
+ dev->writeLine( "checker " );
+ break;
+ case PMListPattern::ListPatternHexagon:
+ dev->writeLine( "hexagon " );
+ break;
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->listType( ) == PMListPattern::ListPatternBrick )
+ {
+ dev->writeLine( "brick_size " +
+ o->brickSize( ).serialize( ) );
+ str1.setNum( o->mortar( ) );
+ dev->writeLine( "mortar " + str1 );
+ }
+}
+
+void PMPov31SerTextureList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->callSerialization( object, metaObject->superClass( ) );
+}
+
+void PMPov31SerPigmentList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->callSerialization( object, metaObject->superClass( ) );
+}
+
+void PMPov31SerColorList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->callSerialization( object, metaObject->superClass( ) );
+}
+
+void PMPov31SerDensityList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->callSerialization( object, metaObject->superClass( ) );
+}
+
+void PMPov31SerNormalList( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMNormalList* o = ( PMNormalList* ) object;
+
+ QString str1;
+
+ switch( o->listType( ) )
+ {
+ case PMNormalList::ListPatternBrick:
+ dev->writeLine( "brick " );
+ break;
+ case PMNormalList::ListPatternChecker:
+ dev->writeLine( "checker " );
+ break;
+ case PMNormalList::ListPatternHexagon:
+ dev->writeLine( "hexagon " );
+ break;
+ }
+ if( o->depth( ) )
+ {
+ str1.setNum( o->depth( ) );
+ dev->writeLine( str1 );
+ }
+ if( o->listType( ) == PMNormalList::ListPatternBrick )
+ {
+ dev->writeLine( "brick_size " +
+ o->brickSize( ).serialize( ) );
+ str1.setNum( o->mortar( ) );
+ dev->writeLine( "mortar " + str1 );
+ }
+}
+
+void PMPov31SerLooksLike( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "looks_like" );
+ dev->writeName( object->name( ) );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerMaterial( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "material" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerMaterialMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMMaterialMap* o = ( PMMaterialMap* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "material_map" );
+
+ switch( o->bitmapType( ) )
+ {
+ case PMMaterialMap::BitmapGif:
+ dev->writeLine( "gif" );
+ break;
+ case PMMaterialMap::BitmapTga:
+ dev->writeLine( "tga" );
+ break;
+ case PMMaterialMap::BitmapIff:
+ dev->writeLine( "iff" );
+ break;
+ case PMMaterialMap::BitmapPpm:
+ dev->writeLine( "ppm" );
+ break;
+ case PMMaterialMap::BitmapPgm:
+ dev->writeLine( "pgm" );
+ break;
+ case PMMaterialMap::BitmapPng:
+ dev->writeLine( "png" );
+ break;
+ case PMMaterialMap::BitmapJpeg:
+ dev->writeLine( "jpeg" );
+ break;
+ case PMMaterialMap::BitmapTiff:
+ dev->writeLine( "tiff" );
+ break;
+ case PMMaterialMap::BitmapSys:
+ dev->writeLine( "sys" );
+ break;
+ }
+
+ dev->writeLine( "\"" + o->bitmapFile( ) + "\"" );
+
+ if( o->isOnceEnabled( ) )
+ dev->writeLine( "once" );
+
+ switch( o->mapType( ) )
+ {
+ case PMMaterialMap::MapPlanar:
+ dev->writeLine( "map_type 0" );
+ break;
+ case PMMaterialMap::MapSpherical:
+ dev->writeLine( "map_type 1" );
+ break;
+ case PMMaterialMap::MapCylindrical:
+ dev->writeLine( "map_type 2" );
+ break;
+ case PMMaterialMap::MapToroidal:
+ dev->writeLine( "map_type 5" );
+ break;
+ }
+ switch( o->interpolateType( ) )
+ {
+ case PMMaterialMap::InterpolateBilinear:
+ dev->writeLine( "interpolate 2" );
+ break;
+ case PMMaterialMap::InterpolateNormalized:
+ dev->writeLine( "interpolate 4" );
+ break;
+ default:
+ break;
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ dev->objectEnd( );
+}
+
+const int c_defaultMediaIntervals = 10;
+const int c_defaultMediaSamplesMin = 1;
+const int c_defaultMediaSamplesMax = 1;
+const double c_defaultMediaConfidence = 0.9;
+const double c_defaultMediaVariance = 0.0078125;
+const double c_defaultMediaRatio = 0.9;
+const double c_defaultMediaScatteringEccentricity = 0;
+const double c_defaultMediaScatteringExtinction = 1.0;
+
+void PMPov31SerMedia( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMMedia* o = ( PMMedia* ) object;
+
+ QString str1;
+ QString str2;
+
+ dev->objectBegin( "media" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ if( o->intervals( ) != c_defaultMediaIntervals )
+ {
+ str1.setNum( o->intervals( ) );
+ dev->writeLine( "intervals " + str1 );
+ }
+ if( o->samplesMin( ) != c_defaultMediaSamplesMin ||
+ o->samplesMax( ) != c_defaultMediaSamplesMax )
+ {
+ str1.setNum( o->samplesMin( ) );
+ str2.setNum( o->samplesMax( ) );
+ dev->writeLine( "samples " + str1 + "," + str2 );
+ }
+ if( o->confidence( ) != c_defaultMediaConfidence )
+ {
+ str1.setNum( o->confidence( ) );
+ dev->writeLine( "confidence " + str1 );
+ }
+ if( o->variance( ) != c_defaultMediaVariance )
+ {
+ str1.setNum( o->variance( ) );
+ dev->writeLine( "variance " + str1 );
+ }
+ if( o->ratio( ) != c_defaultMediaRatio )
+ {
+ str1.setNum( o->ratio( ) );
+ dev->writeLine( "ratio " + str1 );
+ }
+ if( o->isAbsorptionEnabled( ) )
+ {
+ dev->writeLine( "absorption " + o->absorption( ).serialize( ) );
+ }
+ if( o->isEmissionEnabled( ) )
+ {
+ dev->writeLine( "emission " + o->emission( ).serialize( ) );
+ }
+ if( o->isScatteringEnabled( ) )
+ {
+ dev->objectBegin( "scattering" );
+ str1.setNum( o->scatteringType( ) );
+ dev->writeLine( str1 + ", " + o->scatteringColor( ).serialize( ) );
+ if( o->scatteringType( ) == 5 && o->scatteringEccentricity( )
+ != c_defaultMediaScatteringEccentricity )
+ {
+ str1.setNum( o->scatteringEccentricity( ) );
+ dev->writeLine( "eccentricity " + str1 );
+ }
+ if( o->scatteringExtinction( ) != c_defaultMediaScatteringExtinction )
+ {
+ str1.setNum( o->scatteringExtinction( ) );
+ dev->writeLine( "extinction " + str1 );
+ }
+ dev->objectEnd( );
+ }
+ dev->objectEnd( );
+}
+
+void PMPov31SerNamedObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->callSerialization( object, metaObject->superClass( ) );
+}
+
+void PMPov31SerNormal( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMNormal* o = ( PMNormal* ) object;
+
+ QString str1;
+ bool bObject = true;
+
+ if( o->parent( ) )
+ if( o->parent( )->type( ) == "NormalMap" )
+ bObject = false;
+
+ if( bObject )
+ dev->objectBegin( "normal" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ if( o->isBumpSizeEnabled( ) )
+ {
+ str1.setNum( o->bumpSize( ) );
+ dev->writeLine( "bump_size " + str1 );
+ }
+ if( bObject )
+ dev->objectEnd( );
+}
+
+void PMPov31SerObjectLink( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMObjectLink* o = ( PMObjectLink* ) object;
+
+ bool writeComment = true;
+ if( o->linkedObject( ) )
+ {
+ if( o->linkedObject( )->firstChild( ) )
+ {
+ dev->objectBegin( "object" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->linkedObject( )->id( ) );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ writeComment = false;
+
+ dev->objectEnd( );
+ }
+ }
+ if( writeComment )
+ {
+ QString text;
+ text = o->name( );
+ if( text.isEmpty( ) )
+ text = o->description( );
+
+ dev->writeComment( QString( "No prototype for %1" ).arg( text ) );
+ }
+}
+
+const int c_defaultPatternOctaves = 6;
+const double c_defaultPatternOmega = 0.5;
+const double c_defaultPatternLambda = 2.0;
+
+void PMPov31SerPattern( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMPattern* o = ( PMPattern* ) object;
+
+ QString str;
+
+ // pattern type
+ switch( o->patternType( ) )
+ {
+ case PMPattern::PatternAgate:
+ dev->writeLine( "agate" );
+ break;
+ case PMPattern::PatternAverage:
+ dev->writeLine( "average" );
+ break;
+ case PMPattern::PatternBoxed:
+ dev->writeLine( "boxed" );
+ break;
+ case PMPattern::PatternBozo:
+ dev->writeLine( "bozo" );
+ break;
+ case PMPattern::PatternBumps:
+ dev->writeLine( "bumps" );
+ break;
+ case PMPattern::PatternCrackle:
+ dev->writeLine( "crackle" );
+ break;
+ case PMPattern::PatternCylindrical:
+ dev->writeLine( "cylindrical" );
+ break;
+ case PMPattern::PatternDensity:
+ dev->writeLine( "density_file df3 \"" + o->densityFile( ) + "\"");
+ break;
+ case PMPattern::PatternDents:
+ dev->writeLine( "dents" );
+ break;
+ case PMPattern::PatternGradient:
+ dev->writeLine( "gradient " + o->gradient( ).serialize( ) );
+ break;
+ case PMPattern::PatternGranite:
+ dev->writeLine( "granite" );
+ break;
+ case PMPattern::PatternLeopard:
+ dev->writeLine( "leopard" );
+ break;
+ case PMPattern::PatternMandel:
+ str.setNum( o->maxIterations( ) );
+ dev->writeLine( "mandel " + str );
+ break;
+ case PMPattern::PatternMarble:
+ dev->writeLine( "marble" );
+ break;
+ case PMPattern::PatternOnion:
+ dev->writeLine( "onion" );
+ break;
+ case PMPattern::PatternPlanar:
+ dev->writeLine( "planar" );
+ break;
+ case PMPattern::PatternQuilted:
+ dev->writeLine( "quilted" );
+ break;
+ case PMPattern::PatternRadial:
+ dev->writeLine( "radial" );
+ break;
+ case PMPattern::PatternRipples:
+ dev->writeLine( "ripples" );
+ break;
+ case PMPattern::PatternSpherical:
+ dev->writeLine( "spherical" );
+ break;
+ case PMPattern::PatternSpiral1:
+ str.setNum( o->spiralNumberArms( ) );
+ dev->writeLine( "spiral1 " + str );
+ break;
+ case PMPattern::PatternSpiral2:
+ str.setNum( o->spiralNumberArms( ) );
+ dev->writeLine( "spiral2 " + str );
+ break;
+ case PMPattern::PatternSpotted:
+ dev->writeLine( "spotted" );
+ break;
+ case PMPattern::PatternWaves:
+ dev->writeLine( "waves" );
+ break;
+ case PMPattern::PatternWood:
+ dev->writeLine( "wood" );
+ break;
+ case PMPattern::PatternWrinkles:
+ dev->writeLine( "wrinkles" );
+ break;
+ default:
+ break;
+ }
+ // depth
+ if( o->parent( ) )
+ {
+ if( o->depth( ) && o->parent( )->type( ) == "Normal" )
+ {
+ str.setNum( o->depth( ) );
+ dev->writeLine( str );
+ }
+ }
+ // modifiers
+ switch( o->patternType( ) )
+ {
+ case PMPattern::PatternAgate:
+ str.setNum( o->agateTurbulence( ) );
+ dev->writeLine( "agate_turb " + str );
+ break;
+ case PMPattern::PatternDensity:
+ str.setNum( o->densityInterpolate( ) );
+ dev->writeLine( "interpolate " + str );
+ break;
+ case PMPattern::PatternQuilted:
+ str.setNum( o->quiltControl0( ) );
+ dev->writeLine( "control0 " + str );
+ str.setNum( o->quiltControl1( ) );
+ dev->writeLine( "control1 " + str );
+ break;
+ default:
+ break;
+ }
+ if( o->isTurbulenceEnabled( ) )
+ {
+ dev->writeLine( "turbulence " + o->valueVector( ).serialize( ) );
+ if( o->octaves( ) != c_defaultPatternOctaves )
+ {
+ str.setNum( o->octaves( ) );
+ dev->writeLine( "octaves " + str );
+ }
+ if( o->omega( ) != c_defaultPatternOmega )
+ {
+ str.setNum( o->omega( ) );
+ dev->writeLine( "omega " + str );
+ }
+ if( o->lambda( ) != c_defaultPatternLambda )
+ {
+ str.setNum( o->lambda( ) );
+ dev->writeLine( "lambda " + str );
+ }
+ }
+}
+
+void PMPov31SerPigment( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMPigment* o = ( PMPigment* ) object;
+
+ bool bObject = true;
+ if( o->parent( ) )
+ if( o->parent( )->type( ) == "PigmentMap" )
+ bObject = false;
+
+ if( bObject )
+ dev->objectBegin( "pigment" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ if( bObject )
+ dev->objectEnd( );
+}
+
+void PMPov31SerPlane( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMPlane* o = ( PMPlane* ) object;
+
+ dev->objectBegin( "plane" );
+
+ dev->writeName( object->name( ) );
+ QString str1;
+ str1.setNum( o->distance( ) );
+ dev->writeLine( o->normal( ).serialize( ) + ", " + str1 );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerPolynom( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMPolynom* o = ( PMPolynom* ) object;
+ PMVector coefficients = o->coefficients( );
+
+ if( o->polynomOrder( ) == 2 )
+ dev->objectBegin( "quadric" );
+ else if( o->polynomOrder( ) == 3 )
+ dev->objectBegin( "cubic" );
+ else if( o->polynomOrder( ) == 4 )
+ dev->objectBegin( "quartic" );
+ else
+ dev->objectBegin( "poly" );
+
+ dev->writeName( object->name( ) );
+
+ if( o->polynomOrder( ) == 2 )
+ {
+ dev->writeLine( QString( "<%1, %2, %3>," ).arg( coefficients[0] )
+ .arg( coefficients[4] ).arg( coefficients[7] ) );
+ dev->writeLine( QString( "<%1, %2, %3>," ).arg( coefficients[1] )
+ .arg( coefficients[2] ).arg( coefficients[5] ) );
+ dev->writeLine( QString( "<%1, %2, %3>, %4" ).arg( coefficients[3] )
+ .arg( coefficients[6] ).arg( coefficients[8] )
+ .arg( coefficients[9] ) );
+ }
+ else
+ {
+ if( o->polynomOrder( ) > 4 )
+ dev->writeLine( QString( "%1," ).arg( o->polynomOrder( ) ) );
+
+ int size = coefficients.size( );
+
+ int i;
+ QString hlp;
+
+ dev->write( "<" );
+ for( i = 0; i < size; i++ )
+ {
+ hlp.setNum( coefficients[i] );
+ dev->write( hlp );
+
+ if( i != ( size - 1 ) )
+ {
+ dev->write( ", " );
+ if( ( ( i + 1 ) % 5 ) == 0 )
+ dev->writeLine( "" );
+ }
+ }
+ dev->writeLine( ">" );
+ if( o->sturm( ) )
+ dev->writeLine( "sturm" );
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerPovrayMatrix( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMPovrayMatrix* o = ( PMPovrayMatrix* ) object;
+
+ dev->writeLine( QString( "matrix < %1, %2, %3," ).arg( o->values( )[0] )
+ .arg( o->values( )[1] ).arg( o->values( )[2] ) );
+ dev->writeLine( QString( " %1, %2, %3," ).arg( o->values( )[3] )
+ .arg( o->values( )[4] ).arg( o->values( )[5] ) );
+ dev->writeLine( QString( " %1, %2, %3," ).arg( o->values( )[6] )
+ .arg( o->values( )[7] ).arg( o->values( )[8] ) );
+ dev->writeLine( QString( " %1, %2, %3 >" ).arg( o->values( )[9] )
+ .arg( o->values( )[10] ).arg( o->values( )[11] ) );
+}
+
+void PMPov31SerPrism( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMPrism* o = ( PMPrism* ) object;
+
+ dev->objectBegin( "prism" );
+
+ dev->writeName( object->name( ) );
+
+ switch( o->splineType( ) )
+ {
+ case PMPrism::LinearSpline:
+ dev->writeLine( "linear_spline" );
+ break;
+ case PMPrism::QuadraticSpline:
+ dev->writeLine( "quadratic_spline" );
+ break;
+ case PMPrism::CubicSpline:
+ dev->writeLine( "cubic_spline" );
+ break;
+ case PMPrism::BezierSpline:
+ dev->writeLine( "bezier_spline" );
+ break;
+ }
+ switch( o->sweepType( ) )
+ {
+ case PMPrism::LinearSweep:
+ dev->writeLine( "linear_sweep" );
+ break;
+ case PMPrism::ConicSweep:
+ dev->writeLine( "conic_sweep" );
+ break;
+ }
+ dev->writeLine( QString( "%1, %2," ).arg( o->height1( ) ).arg( o->height2( ) ) );
+
+ // count number of points
+ QValueList< QValueList<PMVector> > points = o->points( );
+ QValueList< QValueList<PMVector> >::ConstIterator spit = points.begin( );
+ int lines = 0;
+ for( ; spit != points.end( ); ++spit )
+ {
+ if( o->splineType( ) != PMPrism::BezierSpline )
+ lines += ( *spit ).count( ) + 1;
+ else
+ lines += ( *spit ).count( ) / 3 * 4;
+ }
+ dev->writeLine( QString( "%1," ).arg( lines ) );
+
+ for( spit = points.begin( ); spit != points.end( ); ++spit )
+ {
+ bool first = true;
+
+ QValueList<PMVector> fullPoints = o->expandedPoints( *spit );
+ QValueList<PMVector>::ConstIterator it = fullPoints.begin( );
+
+ for( ; it != fullPoints.end( ); ++it )
+ {
+ if( !first )
+ dev->write( ", " );
+ dev->write( ( *it ).serialize( ) );
+ first = false;
+ }
+ QValueList< QValueList<PMVector> >::ConstIterator spit2 = spit;
+ spit2++;
+ if( spit2 != points.end( ) )
+ dev->write( "," );
+ dev->writeLine( "" );
+ }
+
+ if( o->open( ) )
+ dev->writeLine( "open" );
+ if( o->sturm( ) )
+ dev->writeLine( "sturm" );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerQuickColor( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMQuickColor* o = ( PMQuickColor* ) object;
+
+ dev->writeLine( "quick_color " + o->color( ).serialize( ) );
+}
+
+void PMPov31SerRainbow( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMRainbow* o = ( PMRainbow* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "rainbow" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->isDirectionEnabled( ) )
+ dev->writeLine( "direction " + o->direction( ).serialize( ) );
+ if( o->isAngleEnabled( ) )
+ {
+ str1.setNum( o->angle( ) );
+ dev->writeLine( "angle " + str1 );
+ }
+ if( o->isWidthEnabled( ) )
+ {
+ str1.setNum( o->width( ) );
+ dev->writeLine( "width " + str1 );
+ }
+ if( o->isDistanceEnabled( ) )
+ {
+ str1.setNum( o->distance( ) );
+ dev->writeLine( "distance " + str1 );
+ }
+ if( o->isJitterEnabled( ) )
+ {
+ str1.setNum( o->jitter( ) );
+ dev->writeLine( "jitter " + str1 );
+ }
+ if( o->isUpEnabled( ) )
+ dev->writeLine( "up " + o->up( ).serialize( ) );
+ if( o->isArcAngleEnabled( ) )
+ {
+ str1.setNum( o->arcAngle( ) );
+ dev->writeLine( "arc_angle " + str1 );
+ }
+ if( o->isFalloffAngleEnabled( ) )
+ {
+ str1.setNum( o->falloffAngle( ) );
+ dev->writeLine( "falloff_angle " + str1 );
+ }
+ dev->objectEnd( );
+}
+
+void PMPov31SerRaw( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMRaw* o = ( PMRaw* ) object;
+
+ dev->writeLine( "//*PMRawBegin" );
+
+ QString tmp = o->code( );
+ QTextStream str( &tmp, IO_ReadOnly );
+ while( !str.atEnd( ) )
+ dev->writeLine( str.readLine( ) );
+
+ dev->writeLine( "//*PMRawEnd" );
+}
+
+void PMPov31SerRotate( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMRotate* o = ( PMRotate* ) object;
+ PMVector rotate = o->rotation( );
+
+ QString vector;
+ QTextStream str( &vector, IO_WriteOnly );
+ int i;
+ bool z[3];
+
+ for( i = 0; i < 3; i++ )
+ z[i] = approxZero( rotate[i] );
+ if( !z[0] && z[1] && z[2] )
+ {
+ str << "x*";
+ i = 0;
+ }
+ else if( z[0] && !z[1] && z[2] )
+ {
+ str << "y*";
+ i = 1;
+ }
+ else if( z[0] && z[1] && !z[2] )
+ {
+ str << "z*";
+ i = 2;
+ }
+
+ if( i < 3 )
+ {
+ if( rotate[i] > 0 )
+ str << rotate[i];
+ else
+ str << "(" << rotate[i] << ")";
+ }
+ else
+ {
+ str << '<';
+ for( i = 0; i < 3; i++ )
+ {
+ if( i > 0 )
+ str << ", ";
+ str << rotate[i];
+ }
+ str << '>';
+ }
+
+ dev->writeLine( "rotate " + vector );
+}
+
+void PMPov31SerScale( const PMObject* object, const PMMetaObject* , PMOutputDevice* dev )
+{
+ PMScale* o = ( PMScale* ) object;
+ PMVector scale = o->scale( );
+
+ if( approx( scale[0], scale[1] ) &&
+ approx( scale[1], scale[2] ) )
+ dev->writeLine( QString( "scale %1" ).arg( scale[0] ) );
+ else
+ dev->writeLine( "scale " + scale.serialize( ) );
+}
+
+void PMPov31SerScene( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->callSerialization( object, metaObject->superClass( ) );
+}
+
+void PMPov31SerSkySphere( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "sky_sphere" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerSlope( const PMObject* object, const PMMetaObject* , PMOutputDevice* dev )
+{
+ PMSlope* o = ( PMSlope* ) object;
+
+ QString str1,str2;
+
+ str1.setNum(o->height( ));
+ str2.setNum(o->slope( ));
+
+ dev->writeLine( "<" + str1 + ", " + str2 + ">" );
+}
+
+void PMPov31SerSolidColor( const PMObject* object, const PMMetaObject* , PMOutputDevice* dev )
+{
+ PMSolidColor* o = ( PMSolidColor* ) object;
+
+ dev->writeLine( o->color( ).serialize( true ) );
+}
+
+void PMPov31SerSolidObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMSolidObject* o = ( PMSolidObject* ) object;
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ switch( o->hollow( ) )
+ {
+ case PMTrue:
+ dev->writeLine( "hollow" );
+ break;
+ case PMFalse:
+ dev->writeLine( "hollow false" );
+ break;
+ case PMUnspecified:
+ break;
+ }
+ if( o->inverse( ) )
+ dev->writeLine( "inverse" );
+}
+
+void PMPov31SerSurfaceOfRevolution( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMSurfaceOfRevolution* o = ( PMSurfaceOfRevolution* ) object;
+
+ dev->objectBegin( "sor" );
+
+ dev->writeName( object->name( ) );
+
+ int num = o->points( ).count( );
+ dev->writeLine( QString( "%1," ).arg( num ) );
+
+ bool first = true;
+ QValueList<PMVector> points = o->points( );
+ QValueList<PMVector>::ConstIterator it = points.begin( );
+ for( ; it != points.end( ); ++it )
+ {
+ if( !first )
+ dev->write( ", " );
+ dev->write( ( *it ).serialize( ) );
+ first = false;
+ }
+ dev->writeLine( "" );
+
+ if( o->open( ) )
+ dev->writeLine( "open" );
+ if( o->sturm( ) )
+ dev->writeLine( "sturm" );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerSphere( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMSphere* o = ( PMSphere* ) object;
+
+ dev->objectBegin( "sphere" );
+ dev->writeName( object->name( ) );
+ QString str;
+ str.setNum( o->radius( ) );
+ dev->writeLine( o->centre( ).serialize( ) + ", " + str );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerSuperquadricEllipsoid( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMSuperquadricEllipsoid* o = ( PMSuperquadricEllipsoid* ) object;
+
+ dev->objectBegin( "superellipsoid" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( QString( "<%1, %2>" ).arg( o->eastWestExponent( ) )
+ .arg( o->northSouthExponent( ) ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerText( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMText* o = ( PMText* ) object;
+
+ dev->objectBegin( "text" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( QString( "ttf \"" ) + o->font( ) + "\"" );
+ dev->writeLine( PMOutputDevice::escapeAndQuoteString( o->text( ) ) );
+ dev->writeLine( QString( "%1, " ).arg( o->thickness( ) )
+ + o->offset( ).serialize( ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerTexture( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMTexture* o = ( PMTexture* ) object;
+
+ bool bObject = true;
+ if( o->parent( ) )
+ if( o->parent( )->type( ) == "TextureMap" )
+ bObject = false;
+
+ if( bObject )
+ dev->objectBegin( "texture" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ if( bObject )
+ dev->objectEnd( );
+}
+
+void PMPov31SerTextureBase( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMTextureBase* o = ( PMTextureBase* ) object;
+
+ dev->writeName( object->name( ) );
+
+ PMDeclare* linkedObject = o->linkedObject( );
+
+ if( linkedObject)
+ {
+ if( linkedObject->firstChild( ) )
+ dev->writeLine( linkedObject->id( ) );
+ else
+ {
+ QString text;
+ text = o->name( );
+ if( text.isEmpty( ) )
+ text = o->description( );
+
+ dev->writeComment( QString( "No prototype for %1" ).arg( text ) );
+ }
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+}
+
+void PMPov31SerTextureMapBase( const PMObject* object, const PMMetaObject* , PMOutputDevice* dev )
+{
+ PMTextureMapBase* o = ( PMTextureMapBase* ) object;
+
+ QValueList<double> mapValues = o->mapValues( );
+ QValueList<double>::ConstIterator it = mapValues.begin( );
+ PMObject* c = o->firstChild( );
+ double value = 0.0;
+
+ /* Take care of a possible link */
+ if( o->linkedObject( ) )
+ {
+ if( o->linkedObject( )->firstChild( ) )
+ dev->writeLine( o->linkedObject( )->id( ) );
+ else
+ {
+ QString text;
+ text = o->name( );
+ if( text.isEmpty( ) )
+ text = o->description( );
+
+ dev->writeComment( QString( "No prototype for %1" ).arg( text ) );
+ }
+ }
+
+ /* Serialize the map */
+ for( ; c; c = c->nextSibling( ) )
+ {
+ if( c->type( ) == o->mapType( ) )
+ {
+ value = 1.0;
+ if( it != mapValues.end( ) )
+ value = *it;
+ dev->write( QString( "[ %1 " ).arg( value ) );
+ dev->serialize( c );
+ dev->writeLine( "]" );
+ ++it;
+ }
+ }
+}
+
+void PMPov31SerTextureMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "texture_map" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerPigmentMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "pigment_map" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerColorMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "color_map" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerNormalMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "normal_map" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerSlopeMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "slope_map" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerDensityMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "density_map" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerTorus( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMTorus* o = ( PMTorus* ) object;
+
+ dev->objectBegin( "torus" );
+ dev->writeName( object->name( ) );
+ QString strMinor;
+ QString strMajor;
+ strMinor.setNum( o->minorRadius( ) );
+ strMajor.setNum( o->majorRadius( ) );
+
+ dev->writeLine(strMajor + ", " + strMinor);
+ if( o->sturm( ) )
+ dev->writeLine( QString( "sturm" ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov31SerTranslate( const PMObject* object, const PMMetaObject* , PMOutputDevice* dev )
+{
+ PMTranslate* o = ( PMTranslate* ) object;
+
+ QString vector;
+ QTextStream str( &vector, IO_WriteOnly );
+ int i;
+ bool z[3];
+ PMVector move = o->translation( );
+
+ for( i = 0; i < 3; i++ )
+ z[i] = approxZero( move[i] );
+ if( !z[0] && z[1] && z[2] )
+ {
+ str << "x*";
+ i = 0;
+ }
+ else if( z[0] && !z[1] && z[2] )
+ {
+ str << "y*";
+ i = 1;
+ }
+ else if( z[0] && z[1] && !z[2] )
+ {
+ str << "z*";
+ i = 2;
+ }
+
+ if( i < 3 )
+ {
+ if( move[i] > 0 )
+ str << move[i];
+ else
+ str << "(" << move[i] << ")";
+ }
+ else
+ {
+ str << '<';
+ for( i = 0; i < 3; i++ )
+ {
+ if( i > 0 )
+ str << ", ";
+ str << move[i];
+ }
+ str << '>';
+ }
+
+ dev->writeLine( "translate " + vector );
+}
+
+void PMPov31SerTriangle( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMTriangle* o = ( PMTriangle* ) object;
+
+ if( o->isSmoothTriangle( ) )
+ {
+ dev->objectBegin( "smooth_triangle" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->point( 0 ).serialize( ) + ", " + o->normal( 0 ).serialize( ) + "," );
+ dev->writeLine( o->point( 1 ).serialize( ) + ", " + o->normal( 1 ).serialize( ) + "," );
+ dev->writeLine( o->point( 2 ).serialize( ) + ", " + o->normal( 2 ).serialize( ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+ }
+ else
+ {
+ dev->objectBegin( "triangle" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->point( 0 ).serialize( ) + ", " + o->point( 1 ).serialize( )
+ + ", " + o->point( 2 ).serialize( ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+ }
+}
+
+
+const PMVector c_warpDirectionDefault = PMVector( 1.0, 0.0, 0.0 );
+const PMVector c_warpOffsetDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector c_warpFlipDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector c_warpLocationDefault = PMVector( 0.0, 0.0, 0.0 );
+const double c_warpRadiusDefault = 0;
+const double c_warpStrengthDefault = 0;
+const double c_warpFalloffDefault = 0;
+const bool c_warpInverseDefault = false;
+const PMVector c_warpRepeatDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector c_warpTurbulenceDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector c_warpValueVectorDefault = PMVector( 0.0, 0.0, 0.0 );
+const int c_warpOctavesDefault = 6;
+const double c_warpOmegaDefault = 0.5;
+const double c_warpLambdaDefault = 2.0;
+
+void PMPov31SerWarp( const PMObject* object, const PMMetaObject* , PMOutputDevice* dev )
+{
+ PMWarp* o = ( PMWarp* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "warp" );
+ switch( o->warpType( ) )
+ {
+ case PMWarp::Repeat:
+ dev->writeLine( "repeat" );
+ dev->writeLine( o->direction( ).serialize( ) );
+ dev->writeLine( "offset " + o->offset( ).serialize( ) );
+ dev->writeLine( "flip " + o->flip( ).serialize( ) );
+ break;
+ case PMWarp::BlackHole:
+ dev->writeLine( "black_hole" );
+ dev->writeLine( o->location( ).serialize( ) );
+ str1.setNum(o->radius( ));
+ dev->writeLine( ", " + str1 );
+ if( o->strength( ) != c_warpStrengthDefault )
+ {
+ str1.setNum( o->strength( ));
+ dev->writeLine( "strength " + str1 );
+ }
+ if( o->falloff( ) != c_warpFalloffDefault )
+ {
+ str1.setNum( o->falloff( ));
+ dev->writeLine( "falloff " + str1 );
+ }
+ if( o->inverse( ) != c_warpInverseDefault )
+ {
+ if( o->inverse( ) ) dev->writeLine( "inverse" );
+ }
+ if( o->repeat( ) != c_warpRepeatDefault )
+ {
+ dev->writeLine( "repeat " + o->repeat( ).serialize( ) );
+ }
+ if( o->turbulence( ) != c_warpTurbulenceDefault )
+ {
+ dev->writeLine( "turbulence " + o->turbulence( ).serialize( ) );
+ }
+ break;
+ case PMWarp::Turbulence:
+ dev->writeLine( "turbulence " + o->valueVector( ).serialize( ) );
+ if( o->octaves( ) != c_warpOctavesDefault )
+ {
+ str1.setNum(o->octaves( ));
+ dev->writeLine( "octaves " + str1 );
+ }
+ if( o->omega( ) != c_warpOmegaDefault )
+ {
+ str1.setNum( o->omega( ) );
+ dev->writeLine( "omega " + str1 );
+ }
+ if( o->lambda( ) != c_warpLambdaDefault )
+ {
+ str1.setNum( o->lambda( ) );
+ dev->writeLine( "lambda " + str1 );
+ }
+ break;
+ default:
+ break;
+ }
+ dev->objectEnd( );
+}
+
+void PMPov31SerDetailObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->callSerialization( object, metaObject->superClass( ) );
+}
diff --git a/kpovmodeler/pmpovray31serialization.h b/kpovmodeler/pmpovray31serialization.h
new file mode 100644
index 00000000..5c48c0cd
--- /dev/null
+++ b/kpovmodeler/pmpovray31serialization.h
@@ -0,0 +1,103 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAY31_SERIALIZATION_H
+#define PMPOVRAY31_SERIALIZATION_H
+
+class PMObject;
+class PMMetaObject;
+class PMOutputDevice;
+
+// serialization methods for POV-Ray 3.1
+
+void PMPov31SerBicubicPatch( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerBlendMapModifiers( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerBlob( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerBlobCylinder( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerBlobSphere( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerBoundedBy( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerBox( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerBumpMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerCamera( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerClippedBy( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerComment( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerCompositeObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerCone( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerCSG( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerCylinder( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerDeclare( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerDensity( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerDisc( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerFinish( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerFog( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerGlobalSettings( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerGraphicalObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerHeightField( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerImageMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerInterior( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerJuliaFractal( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerLathe( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerLight( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerListPattern( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerTextureList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerPigmentList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerColorList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerDensityList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerNormalList( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerLooksLike( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerMaterial( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerMaterialMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerMedia( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerNamedObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerNormal( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerObjectLink( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerPattern( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerPigment( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerPlane( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerPolynom( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerPovrayMatrix( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerPrism( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerQuickColor( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerRainbow( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerRaw( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerRotate( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerScale( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerScene( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerSkySphere( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerSlope( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerSolidColor( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerSolidObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerSurfaceOfRevolution( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerSphere( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerSuperquadricEllipsoid( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerText( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerTexture( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerTextureBase( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerTextureMapBase( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerTextureMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerPigmentMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerColorMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerNormalMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerSlopeMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerDensityMap( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerTorus( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerTranslate( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerTriangle( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerWarp( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov31SerDetailObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+
+#endif
diff --git a/kpovmodeler/pmpovray35format.cpp b/kpovmodeler/pmpovray35format.cpp
new file mode 100644
index 00000000..c00b1d65
--- /dev/null
+++ b/kpovmodeler/pmpovray35format.cpp
@@ -0,0 +1,100 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovray35format.h"
+#include "pmpovray35serialization.h"
+
+#include "pmpovrayparser.h"
+#include "pmoutputdevice.h"
+
+#include <klocale.h>
+
+PMPovray35Format::PMPovray35Format( )
+ : PMPovray31Format( )
+{
+ registerMethod( "IsoSurface", PMPov35SerIsoSurface );
+ registerMethod( "Light", PMPov35SerLight );
+ registerMethod( "ProjectedThrough", PMPov35SerProjectedThrough );
+ registerMethod( "GlobalSettings", PMPov35SerGlobalSettings );
+ registerMethod( "Radiosity", PMPov35SerRadiosity );
+ registerMethod( "GlobalPhotons", PMPov35SerGlobalPhotons );
+ registerMethod( "Photons", PMPov35SerPhotons );
+ registerMethod( "Interior", PMPov35SerInterior );
+ registerMethod( "LightGroup", PMPov35SerLightGroup );
+ registerMethod( "Pattern", PMPov35SerPattern );
+ registerMethod( "Normal", PMPov35SerNormal );
+ registerMethod( "InteriorTexture", PMPov35SerInteriorTexture );
+ registerMethod( "Warp", PMPov35SerWarp );
+ registerMethod( "SphereSweep", PMPov35SerSphereSweep );
+ registerMethod( "Finish", PMPov35SerFinish );
+ registerMethod( "Mesh", PMPov35SerMesh );
+ registerMethod( "Media", PMPov35SerMedia );
+ registerMethod( "GraphicalObject", PMPov35SerGraphicalObject );
+ registerMethod( "Pigment", PMPov35SerPigment );
+ registerMethod( "Texture", PMPov35SerTexture );
+ registerMethod( "BicubicPatch", PMPov35SerBicubicPatch );
+ registerMethod( "Triangle", PMPov35SerTriangle );
+}
+
+
+PMPovray35Format::~PMPovray35Format( )
+{
+
+}
+
+PMParser* PMPovray35Format::newParser( PMPart* part, QIODevice* dev ) const
+{
+ return new PMPovrayParser( part, dev );
+}
+
+PMParser* PMPovray35Format::newParser( PMPart* part, const QByteArray& data ) const
+{
+ return new PMPovrayParser( part, data );
+}
+
+PMSerializer* PMPovray35Format::newSerializer( QIODevice* dev )
+{
+ return new PMOutputDevice( dev, this );
+}
+
+PMRenderer* PMPovray35Format::newRenderer( PMPart* ) const
+{
+ // TODO
+ return 0;
+}
+
+QString PMPovray35Format::mimeType( ) const
+{
+ return QString( "text/plain" );
+}
+
+QStringList PMPovray35Format::importPatterns( ) const
+{
+ QStringList result;
+ result.push_back( QString( "*.pov *.inc|" )
+ + i18n( "POV-Ray 3.5 Files (*.pov, *.inc)" ) );
+ return result;
+}
+
+QStringList PMPovray35Format::exportPatterns( ) const
+{
+ QStringList result;
+ result.push_back( QString( "*.pov|" ) + i18n( "POV-Ray 3.5 Files (*.pov)" ) );
+ result.push_back( QString( "*.ini|" ) + i18n( "POV-Ray 3.5 Include Files (*.ini)" ) );
+ return result;
+
+}
diff --git a/kpovmodeler/pmpovray35format.h b/kpovmodeler/pmpovray35format.h
new file mode 100644
index 00000000..117d0375
--- /dev/null
+++ b/kpovmodeler/pmpovray35format.h
@@ -0,0 +1,64 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAY35_FORMAT_H
+#define PMPOVRAY35_FORMAT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmpovray31format.h"
+
+/**
+ * Description class for POV-Ray 3.5
+ */
+class PMPovray35Format : public PMPovray31Format
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMPovray35Format( );
+ /**
+ * Destructor
+ */
+ virtual ~PMPovray35Format( );
+
+ /** */
+ virtual QString name( ) const { return "povray35"; };
+ /** */
+ virtual QString description( ) const { return "POV-Ray 3.5"; }
+ /** */
+ virtual int services( ) const { return AllServices; }
+ /** */
+ virtual PMParser* newParser( PMPart*, QIODevice* ) const;
+ /** */
+ virtual PMParser* newParser( PMPart*, const QByteArray& ) const;
+ /** */
+ virtual PMSerializer* newSerializer( QIODevice* );
+ /** */
+ virtual PMRenderer* newRenderer( PMPart* ) const;
+ /** */
+ virtual QString mimeType( ) const;
+ /** */
+ virtual QStringList importPatterns( ) const;
+ /** */
+ virtual QStringList exportPatterns( ) const;
+};
+
+#endif
diff --git a/kpovmodeler/pmpovray35serialization.cpp b/kpovmodeler/pmpovray35serialization.cpp
new file mode 100644
index 00000000..2c3a88e0
--- /dev/null
+++ b/kpovmodeler/pmpovray35serialization.cpp
@@ -0,0 +1,1471 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovray35serialization.h"
+#include "pmoutputdevice.h"
+
+#include "pmisosurface.h"
+#include "pmlight.h"
+#include "pmprojectedthrough.h"
+#include "pmglobalsettings.h"
+#include "pmradiosity.h"
+#include "pmglobalphotons.h"
+#include "pmphotons.h"
+#include "pminterior.h"
+#include "pmlightgroup.h"
+#include "pmpattern.h"
+#include "pmnormal.h"
+#include "pminteriortexture.h"
+#include "pmwarp.h"
+#include "pmspheresweep.h"
+#include "pmfinish.h"
+#include "pmmesh.h"
+#include "pmmedia.h"
+#include "pmgraphicalobject.h"
+#include "pmpigment.h"
+#include "pmtexture.h"
+#include "pmbicubicpatch.h"
+#include "pmtriangle.h"
+
+const PMIsoSurface::ContainedByType c_defaultIsoContainedBy = PMIsoSurface::Box;
+const PMVector c_defaultIsoCorner1 = PMVector( -1, -1, -1 );
+const PMVector c_defaultIsoCorner2 = PMVector( 1, 1, 1 );
+const PMVector c_defaultIsoCenter = PMVector( 0, 0, 0 );
+const double c_defaultIsoRadius = 1;
+
+const double c_defaultIsoThreshold = 0.0;
+const double c_defaultIsoAccuracy = 0.001;
+const double c_defaultIsoMaxGradient = 1.1;
+const bool c_defaultIsoEvaluate = false;
+const double c_defaultIsoEvaluate0 = 5;
+const double c_defaultIsoEvaluate1 = 1.2;
+const double c_defaultIsoEvaluate2 = 0.95;
+const double c_defaultIsoOpen = false;
+const int c_defaultIsoMaxTrace = 1;
+const bool c_defaultIsoAllIntersections = false;
+
+void PMPov35SerIsoSurface( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMIsoSurface* o = ( PMIsoSurface* ) object;
+ QString str;
+
+ dev->objectBegin( "isosurface" );
+ dev->writeName( object->name( ) );
+
+ if( o->containedBy( ) == PMIsoSurface::Box )
+ {
+ dev->writeLine( QString( "function { " ) + o->function( ) + " }" );
+
+ if( o->corner1( ) != c_defaultIsoCorner1 ||
+ o->corner2( ) != c_defaultIsoCorner2 )
+ {
+ dev->writeLine( QString( "contained_by { box { " ) +
+ o->corner1( ).serialize( ) + ", " +
+ o->corner2( ).serialize( ) + " } }" );
+ }
+ }
+ else
+ {
+ str.setNum( o->radius( ) );
+ dev->writeLine( QString( "contained_by { sphere { " ) +
+ o->center( ).serialize( ) + ", " + str + " } }" );
+ }
+
+ if( !approx( o->threshold( ), c_defaultIsoThreshold ) )
+ {
+ str.setNum( o->threshold( ) );
+ dev->writeLine( "threshold " + str );
+ }
+ if( !approx( o->accuracy( ), c_defaultIsoAccuracy ) )
+ {
+ str.setNum( o->accuracy( ) );
+ dev->writeLine( "accuracy " + str );
+ }
+ if( !approx( o->maxGradient( ), c_defaultIsoMaxGradient ) )
+ {
+ str.setNum( o->maxGradient( ) );
+ dev->writeLine( "max_gradient " + str );
+ }
+ if( o->evaluate( ) )
+ {
+ str = QString( "%1, %2, %3" ).arg( o->evaluateValue( 0 ) )
+ .arg( o->evaluateValue( 1 ) ).arg( o->evaluateValue( 2 ) );
+ dev->writeLine( "evaluate " + str );
+ }
+ if( o->allIntersections( ) )
+ dev->writeLine( "all_intersections" );
+ else
+ {
+ str.setNum( o->maxTrace( ) );
+ dev->writeLine( "max_trace " + str );
+ }
+ if( o->open( ) )
+ dev->writeLine( "open" );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+const double c_defaultLightTightness = 10;
+const int c_defaultLightAdaptive = 0;
+
+void PMPov35SerLight( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMLight* o = ( PMLight* ) object;
+
+ dev->objectBegin( QString( "light_source" ) );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->location( ).serialize( ) + ", " + o->color( ).serialize( ) );
+
+ if( o->lightType( ) == PMLight::SpotLight )
+ dev->writeLine( QString( "spotlight" ) );
+ else if( o->lightType( ) == PMLight::CylinderLight )
+ dev->writeLine( QString( "cylinder" ) );
+ else if( o->lightType( ) == PMLight::ShadowlessLight )
+ dev->writeLine( QString( "shadowless" ) );
+
+ if( o->parallel( ) )
+ dev->writeLine( QString( "parallel" ) );
+
+ if( ( o->lightType( ) == PMLight::SpotLight ) ||
+ ( o->lightType( ) == PMLight::CylinderLight ) )
+ {
+ dev->writeLine( QString( "radius %1" ).arg( o->radius( ) ) );
+ dev->writeLine( QString( "falloff %1" ).arg( o->falloff( ) ) );
+ if( o->tightness( ) != c_defaultLightTightness )
+ dev->writeLine( QString( "tightness %1" ).arg( o->tightness( ) ) );
+ dev->writeLine( QString( "point_at " ) + o->pointAt( ).serialize( ) );
+ }
+
+ if( o->isAreaLight( ) )
+ {
+ dev->writeLine( QString( "area_light " ) + o->axis1( ).serialize( )
+ + QString( ", " ) + o->axis2( ).serialize( )
+ + QString( ", %1, %2" ).arg( o->size1( ) ).arg( o->size2( ) ) );
+ if( o->adaptive( ) != c_defaultLightAdaptive )
+ dev->writeLine( QString( "adaptive %1" ).arg( o->adaptive( ) ) );
+ if( o->jitter( ) )
+ dev->writeLine( QString( "jitter" ) );
+ if ( o->areaType( ) == PMLight::Circular )
+ dev->writeLine( QString( "circular" ) );
+ if ( o->orient( ) )
+ dev->writeLine( QString( "orient" ) );
+ }
+
+ if( o->fading( ) )
+ {
+ dev->writeLine( QString( "fade_distance %1" ).arg( o->fadeDistance( ) ) );
+ dev->writeLine( QString( "fade_power %1" ).arg( o->fadePower( ) ) );
+ }
+
+ if( !o->mediaInteraction( ) )
+ dev->writeLine( QString( "media_interaction off" ) );
+ if( !o->mediaAttenuation( ) )
+ dev->writeLine( QString( "media_attenuation off" ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov35SerProjectedThrough( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "projected_through" );
+ dev->writeName( object->name( ) );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+const double c_defaultGlobalSettingsAdcBailout = 1.0 / 255.0;
+const PMColor c_defaultGlobalSettingsAmbientLight = PMColor( 1.0, 1.0, 1.0, 0.0, 0.0 );
+const double c_defaultGlobalSettingsAssumedGamma = 0.0;
+const bool c_defaultGlobalSettingsHfGray16 = false;
+const PMColor c_defaultGlobalSettingsIridWaveLength = PMColor( 0.25, 0.18, 0.14, 0.0, 0.0 );
+const int c_defaultGlobalSettingsMaxIntersections = 0; // ???
+const int c_defaultGlobalSettingsMaxTraceLevel = 0; // ???
+const int c_defaultGlobalSettingsNumberWaves = 10;
+const bool c_defaultGlobalSettingsRadiosity = false;
+const double c_defaultGlobalSettingsBrightness = 1.0;
+const int c_defaultGlobalSettingsCount = 35;
+const double c_defaultGlobalSettingsDistanceMaximum = 0; // ???
+const double c_defaultGlobalSettingsErrorBound = 1.8;
+const double c_defaultGlobalSettingsGrayThreshold = 0.0;
+const double c_defaultGlobalSettingsLowErrorFactor = 0.5;
+const double c_defaultGlobalSettingsMinimumReuse = 0.015;
+const int c_defaultGlobalSettingsNearestCount = 5;
+const int c_defaultGlobalSettingsRecursionLimit = 2;
+
+void PMPov35SerGlobalSettings( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMGlobalSettings* o = ( PMGlobalSettings* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "global_settings" );
+
+ if( o->adcBailout( ) != c_defaultGlobalSettingsAdcBailout )
+ {
+ str1.setNum( o->adcBailout( ) );
+ dev->writeLine( "adc_bailout " + str1 );
+ }
+ if( o->ambientLight( ) != c_defaultGlobalSettingsAmbientLight )
+ dev->writeLine( "ambient_light " + o->ambientLight( ).serialize( ) );
+ if( o->assumedGamma( ) != c_defaultGlobalSettingsAssumedGamma )
+ {
+ str1.setNum( o->assumedGamma( ) );
+ dev->writeLine( "assumed_gamma " + str1 );
+ }
+ if( o->hfGray16( ) != c_defaultGlobalSettingsHfGray16 )
+ {
+ if( o->hfGray16( ) )
+ dev->writeLine( "hf_gray_16 on" );
+ else
+ dev->writeLine( "hf_gray_16 off" );
+ }
+ if( o->iridWaveLength( ) != c_defaultGlobalSettingsIridWaveLength )
+ dev->writeLine( "irid_wavelength " + o->iridWaveLength( ).serialize( ) );
+ if( o->maxTraceLevel( ) != c_defaultGlobalSettingsMaxTraceLevel )
+ {
+ str1.setNum( o->maxTraceLevel( ) );
+ dev->writeLine( "max_trace_level " + str1 );
+ }
+ if( o->maxIntersections( ) != c_defaultGlobalSettingsMaxIntersections )
+ {
+ str1.setNum( o->maxIntersections( ) );
+ dev->writeLine( "max_intersections " + str1 );
+ }
+ if( o->numberWaves( ) != c_defaultGlobalSettingsNumberWaves )
+ {
+ str1.setNum( o->numberWaves( ) );
+ dev->writeLine( "number_of_waves " + str1 );
+ }
+ if ( o->noiseGenerator( ) == PMGlobalSettings::Original )
+ dev->writeLine( QString( "noise_generator 1" ) );
+ else if ( o->noiseGenerator( ) == PMGlobalSettings::RangeCorrected )
+ dev->writeLine( QString( "noise_generator 2" ) );
+ else
+ dev->writeLine( QString( "noise_generator 3" ) );
+ if( o->isRadiosityEnabled( ) )
+ {
+ dev->objectBegin( "radiosity" );
+ if( o->brightness( ) != c_defaultGlobalSettingsBrightness )
+ {
+ str1.setNum( o->brightness( ) );
+ dev->writeLine( "brightness " + str1 );
+ }
+ if( o->count( ) != c_defaultGlobalSettingsCount )
+ {
+ str1.setNum( o->count( ) );
+ dev->writeLine( "count " + str1 );
+ }
+ if( o->distanceMaximum( ) != c_defaultGlobalSettingsDistanceMaximum )
+ {
+ str1.setNum( o->distanceMaximum( ) );
+ dev->writeLine( "distance_maximum " + str1 );
+ }
+ if( o->errorBound( ) != c_defaultGlobalSettingsErrorBound )
+ {
+ str1.setNum( o->errorBound( ) );
+ dev->writeLine( "error_bound " + str1 );
+ }
+ if( o->grayThreshold( ) != c_defaultGlobalSettingsGrayThreshold )
+ {
+ str1.setNum( o->grayThreshold( ) );
+ dev->writeLine( "gray_threshold " + str1 );
+ }
+ if( o->lowErrorFactor( ) != c_defaultGlobalSettingsLowErrorFactor )
+ {
+ str1.setNum( o->lowErrorFactor( ) );
+ dev->writeLine( "low_error_factor " + str1 );
+ }
+ if( o->minimumReuse( ) != c_defaultGlobalSettingsMinimumReuse )
+ {
+ str1.setNum( o->minimumReuse( ) );
+ dev->writeLine( "minimuo->reuse( ) " + str1 );
+ }
+ if( o->nearestCount( ) != c_defaultGlobalSettingsNearestCount )
+ {
+ str1.setNum( o->nearestCount( ) );
+ dev->writeLine( "nearest_count " + str1 );
+ }
+ if( o->recursionLimit( ) != c_defaultGlobalSettingsRecursionLimit )
+ {
+ str1.setNum( o->recursionLimit( ) );
+ dev->writeLine( "recursion_limit " + str1 );
+ }
+ dev->objectEnd( );
+ }
+ else
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+const double c_defaultRadiosityAdcBailout = 0.01;
+const double c_defaultRadiosityBrightness = 1.0;
+const int c_defaultRadiosityCount = 35;
+const double c_defaultRadiosityErrorBound = 1.8;
+const double c_defaultRadiosityGrayThreshold = 0.0;
+const double c_defaultRadiosityLowErrorFactor = 0.5;
+const double c_defaultRadiosityMaxSample = -1.0;
+const double c_defaultRadiosityMinimumReuse = 0.015;
+const int c_defaultRadiosityNearestCount = 5;
+const double c_defaultRadiosityPretraceStart = 0.08;
+const double c_defaultRadiosityPretraceEnd = 0.04;
+const int c_defaultRadiosityRecursionLimit = 2;
+
+void PMPov35SerRadiosity( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMRadiosity* o = ( PMRadiosity* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "radiosity" );
+
+ if( o->adcBailout( ) != c_defaultRadiosityAdcBailout )
+ {
+ str1.setNum( o->adcBailout( ) );
+ dev->writeLine( "adc_bailout " + str1 );
+ }
+
+ if( !o->alwaysSample( ) )
+ dev->writeLine( "always_sample off" );
+
+ if( o->brightness( ) != c_defaultRadiosityBrightness )
+ {
+ str1.setNum( o->brightness( ) );
+ dev->writeLine( "brightness " + str1 );
+ }
+
+ if( o->count( ) != c_defaultRadiosityCount )
+ {
+ str1.setNum( o->count( ) );
+ dev->writeLine( "count " + str1 );
+ }
+
+ if( o->errorBound( ) != c_defaultRadiosityErrorBound )
+ {
+ str1.setNum( o->errorBound( ) );
+ dev->writeLine( "error_bound " + str1 );
+ }
+
+ if( o->grayThreshold( ) != c_defaultRadiosityGrayThreshold )
+ {
+ str1.setNum( o->grayThreshold( ) );
+ dev->writeLine( "gray_threshold " + str1 );
+ }
+
+ if( o->lowErrorFactor( ) != c_defaultRadiosityLowErrorFactor )
+ {
+ str1.setNum( o->lowErrorFactor( ) );
+ dev->writeLine( "low_error_factor " + str1 );
+ }
+
+ if( o->maxSample( ) != c_defaultRadiosityMaxSample )
+ {
+ str1.setNum( o->maxSample( ) );
+ dev->writeLine( "max_sample " + str1 );
+ }
+
+ if( o->media( ) )
+ dev->writeLine( "media on" );
+
+ if( o->minimumReuse( ) != c_defaultRadiosityMinimumReuse )
+ {
+ str1.setNum( o->minimumReuse( ) );
+ dev->writeLine( "minimum_reuse " + str1 );
+ }
+ if( o->nearestCount( ) != c_defaultRadiosityNearestCount )
+ {
+ str1.setNum( o->nearestCount( ) );
+ dev->writeLine( "nearest_count " + str1 );
+ }
+
+ if( o->normal( ) )
+ dev->writeLine( "normal on" );
+
+ if( o->pretraceStart( ) != c_defaultRadiosityPretraceStart )
+ {
+ str1.setNum( o->pretraceStart( ) );
+ dev->writeLine( "pretrace_start " + str1 );
+ }
+
+ if( o->pretraceEnd( ) != c_defaultRadiosityPretraceEnd )
+ {
+ str1.setNum( o->pretraceEnd( ) );
+ dev->writeLine( "pretrace_end " + str1 );
+ }
+
+ if( o->recursionLimit( ) != c_defaultGlobalSettingsRecursionLimit )
+ {
+ str1.setNum( o->recursionLimit( ) );
+ dev->writeLine( "recursion_limit " + str1 );
+ }
+ dev->objectEnd( );
+}
+
+const int c_defaultGlobalPhotonsGatherMin = 20;
+const int c_defaultGlobalPhotonsGatherMax = 100;
+const int c_defaultGlobalPhotonsMediaMaxSteps = 0;
+const double c_defaultGlobalPhotonsMediaFactor = 1.0;
+const double c_defaultGlobalPhotonsJitter = 0.4;
+const double c_defaultGlobalPhotonsAutostop = 0.0;
+const double c_defaultGlobalPhotonsExpandIncrease = 0.2;
+const int c_defaultGlobalPhotonsExpandMin = 40;
+const double c_defaultGlobalPhotonsRadiusGather = 0.0;
+const double c_defaultGlobalPhotonsRadiusGatherMulti = 1.0;
+const double c_defaultGlobalPhotonsRadiusMedia = 0.0;
+const double c_defaultGlobalPhotonsRadiusMediaMulti = 1.0;
+
+void PMPov35SerGlobalPhotons( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMGlobalPhotons* o = ( PMGlobalPhotons* ) object;
+
+ QString str1, str2;
+
+ dev->objectBegin( "photons" );
+
+ if ( o->numberType( ) == PMGlobalPhotons::Spacing )
+ {
+ str1.setNum( o->spacing( ) );
+ dev->writeLine( "spacing " + str1 );
+ }
+ else
+ {
+ str1.setNum( o->count( ) );
+ dev->writeLine( "count " + str1 );
+ }
+
+ if ( o->gatherMin( ) != c_defaultGlobalPhotonsGatherMin ||
+ o->gatherMax( ) != c_defaultGlobalPhotonsGatherMax )
+ {
+ str1.setNum( o->gatherMin( ) );
+ str2.setNum( o->gatherMax( ) );
+ dev->writeLine( "gather " + str1 + ", " + str2 );
+ }
+
+ if ( o->mediaMaxSteps( ) != c_defaultGlobalPhotonsMediaMaxSteps )
+ {
+ str1.setNum( o->mediaMaxSteps( ) );
+ if ( o->mediaFactor( ) != c_defaultGlobalPhotonsMediaFactor )
+ {
+ str2.setNum( o->mediaFactor( ) );
+ dev->writeLine( "media " + str1 + ", " + str2 );
+ }
+ else
+ dev->writeLine( "media " + str1 );
+ }
+
+ if ( o->jitter( ) != c_defaultGlobalPhotonsJitter )
+ {
+ str1.setNum( o->jitter( ) );
+ dev->writeLine( "jitter " + str1 );
+ }
+
+ if ( !o->maxTraceLevelGlobal( ) )
+ {
+ str1.setNum( o->maxTraceLevel( ) );
+ dev->writeLine( "max_trace_level " + str1 );
+ }
+
+ if ( !o->adcBailoutGlobal( ) )
+ {
+ str1.setNum( o->adcBailout( ) );
+ dev->writeLine( "adc_bailout " + str1 );
+ }
+
+ if ( o->autostop( ) != c_defaultGlobalPhotonsAutostop )
+ {
+ str1.setNum( o->autostop( ) );
+ dev->writeLine( "autostop " + str1 );
+ }
+
+ if ( o->expandIncrease( ) != c_defaultGlobalPhotonsExpandIncrease ||
+ o->expandMin( ) != c_defaultGlobalPhotonsExpandMin )
+ {
+ str1.setNum( o->expandIncrease( ) );
+ str2.setNum( o->expandMin( ) );
+ dev->writeLine( "expand_thresholds " + str1 + ", " + str2 );
+ }
+
+ if ( o->radiusGather( ) != c_defaultGlobalPhotonsRadiusGather ||
+ o->radiusGatherMulti( ) != c_defaultGlobalPhotonsRadiusGatherMulti ||
+ o->radiusMedia( ) != c_defaultGlobalPhotonsRadiusMedia ||
+ o->radiusMediaMulti( ) != c_defaultGlobalPhotonsRadiusMediaMulti )
+ {
+ QString str3, str4;
+ str1.setNum( o->radiusGather( ) );
+ str2.setNum( o->radiusGatherMulti( ) );
+ str3.setNum( o->radiusMedia( ) );
+ str4.setNum( o->radiusMediaMulti( ) );
+ dev->writeLine( "radius " + str1 + ", " + str2 + ", " + str3 + ", " + str4 );
+ }
+ dev->objectEnd( );
+}
+
+const double c_defaultPhotonsSpacingMulti = 1.0;
+
+void PMPov35SerPhotons( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMPhotons* o = ( PMPhotons* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "photons" );
+
+ if( o->parent( ) && ( o->parent( )->type( ) == "Light" ) )
+ {
+ if( o->refraction( ) )
+ dev->writeLine( QString( "refraction on" ) );
+ if( o->reflection( ) )
+ dev->writeLine( QString( "reflection on" ) );
+ if( o->areaLight( ) )
+ dev->writeLine( QString( "area_light" ) );
+ }
+ else
+ {
+ if( o->target( ) )
+ {
+ if( o->spacingMulti( ) != c_defaultPhotonsSpacingMulti )
+ {
+ str1.setNum( o->spacingMulti( ) );
+ dev->writeLine( "target " + str1 );
+ }
+ else
+ dev->writeLine( QString( "target" ) );
+ }
+ if( o->refraction( ) )
+ dev->writeLine( QString( "refraction on" ) );
+ if( o->reflection( ) )
+ dev->writeLine( QString( "reflection on" ) );
+ if( !o->collect( ) )
+ dev->writeLine( QString( "collect off" ) );
+ if( o->passThrough( ) )
+ dev->writeLine( QString( "pass_through" ) );
+ }
+ dev->objectEnd( );
+}
+
+void PMPov35SerInterior( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMInterior* o = ( PMInterior* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "interior" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->isIorEnabled( ) )
+ {
+ str1.setNum( o->ior( ) );
+ dev->writeLine( "ior " + str1 );
+ }
+ if( o->isCausticsEnabled( ) )
+ {
+ str1.setNum( o->caustics( ) );
+ dev->writeLine( "caustics " + str1 );
+ }
+ if ( o->isDispersionEnabled( ) )
+ {
+ str1.setNum( o->dispersion( ) );
+ dev->writeLine( "dispersion " + str1 );
+ }
+ if ( o->isDispSamplesEnabled( ) )
+ {
+ str1.setNum( o->dispSamples( ) );
+ dev->writeLine( "dispersion_samples " + str1 );
+ }
+ if( o->isFadeDistanceEnabled( ) )
+ {
+ str1.setNum( o->fadeDistance( ) );
+ dev->writeLine( "fade_distance " + str1 );
+ }
+ if( o->isFadePowerEnabled( ) )
+ {
+ str1.setNum( o->fadePower( ) );
+ dev->writeLine( "fade_power " + str1 );
+ }
+ dev->objectEnd( );
+}
+
+void PMPov35SerLightGroup( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMLightGroup* o = ( PMLightGroup* ) object;
+
+ dev->objectBegin( "light_group" );
+
+ dev->writeName( object->name( ) );
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if ( o->globalLights( ) )
+ dev->writeLine( "global_lights on" );
+ else
+ dev->writeLine( "global_lights off" );
+
+ dev->objectEnd( );
+}
+
+const PMVector c_defaultPatternCrackleForm = PMVector( -1.0, 1.0, 0.0 );
+const int c_defaultPatternCrackleMetric = 2;
+const double c_defaultPatternCrackleOffset = 0.0;
+const bool c_defaultPatternCrackleSolid = false;
+const int c_defaultPatternFractalExponent = 2;
+const int c_defaultPatternFractalExtType = 1;
+const double c_defaultPatternFractalExtFactor = 1.0;
+const int c_defaultPatternFractalIntType = 0;
+const double c_defaultPatternFractalIntFactor = 1.0;
+const double c_defaultPatternSlopeLoSlope = 0.0;
+const double c_defaultPatternSlopeHiSlope = 1.0;
+const double c_defaultPatternSlopeLoAlt = 0.0;
+const double c_defaultPatternSlopeHiAlt = 1.0;
+const int c_defaultPatternOctaves = 6;
+const double c_defaultPatternOmega = 0.5;
+const double c_defaultPatternLambda = 2.0;
+
+void PMPov35SerPattern( const PMObject* object, const PMMetaObject*, PMOutputDevice* dev )
+{
+ PMPattern* o = ( PMPattern* ) object;
+
+ QString str, str2;
+
+ // pattern type
+ switch( o->patternType( ) )
+ {
+ case PMPattern::PatternAgate:
+ dev->writeLine( "agate" );
+ break;
+ case PMPattern::PatternAverage:
+ dev->writeLine( "average" );
+ break;
+ case PMPattern::PatternBoxed:
+ dev->writeLine( "boxed" );
+ break;
+ case PMPattern::PatternBozo:
+ dev->writeLine( "bozo" );
+ break;
+ case PMPattern::PatternBumps:
+ dev->writeLine( "bumps" );
+ break;
+ case PMPattern::PatternCells:
+ dev->writeLine( "cells" );
+ break;
+ case PMPattern::PatternCrackle:
+ dev->writeLine( "crackle" );
+ break;
+ case PMPattern::PatternCylindrical:
+ dev->writeLine( "cylindrical" );
+ break;
+ case PMPattern::PatternDensity:
+ dev->writeLine( "density_file df3 \"" + o->densityFile( ) + "\"");
+ break;
+ case PMPattern::PatternDents:
+ dev->writeLine( "dents" );
+ break;
+ case PMPattern::PatternGradient:
+ dev->writeLine( "gradient " + o->gradient( ).serialize( ) );
+ break;
+ case PMPattern::PatternGranite:
+ dev->writeLine( "granite" );
+ break;
+ case PMPattern::PatternJulia:
+ if( o->fractalMagnet( ) )
+ {
+ str.setNum( o->fractalMagnetType( ) );
+ str = "magnet " + str + " ";
+ }
+ else
+ str = "";
+
+ str2.setNum( o->maxIterations( ) );
+ str = str + "julia " + o->juliaComplex( ).serialize( ) + ", " + str2;
+ dev->writeLine( str );
+ break;
+ case PMPattern::PatternLeopard:
+ dev->writeLine( "leopard" );
+ break;
+ case PMPattern::PatternMandel:
+ if( o->fractalMagnet( ) )
+ {
+ str.setNum( o->fractalMagnetType( ) );
+ str = "magnet " + str + " ";
+ }
+ else
+ str = "";
+
+ str2.setNum( o->maxIterations( ) );
+ dev->writeLine( str + "mandel " + str2 );
+ break;
+ case PMPattern::PatternMarble:
+ dev->writeLine( "marble" );
+ break;
+ case PMPattern::PatternOnion:
+ dev->writeLine( "onion" );
+ break;
+ case PMPattern::PatternPlanar:
+ dev->writeLine( "planar" );
+ break;
+ case PMPattern::PatternQuilted:
+ dev->writeLine( "quilted" );
+ break;
+ case PMPattern::PatternRadial:
+ dev->writeLine( "radial" );
+ break;
+ case PMPattern::PatternRipples:
+ dev->writeLine( "ripples" );
+ break;
+ case PMPattern::PatternSlope:
+ dev->objectBegin( "slope" );
+ dev->write( o->slopeDirection( ).serialize( ) );
+ if ( o->slopeLoSlope( ) != c_defaultPatternSlopeLoSlope ||
+ o->slopeHiSlope( ) != c_defaultPatternSlopeHiSlope )
+ {
+ str.setNum( o->slopeLoSlope( ) );
+ str2.setNum( o->slopeHiSlope( ) );
+ dev->writeLine( ", " + str + ", " + str2 );
+ }
+ else
+ dev->writeLine( "" );
+
+ if ( o->slopeAltFlag( ) )
+ {
+ dev->write( "altitude " + o->slopeAltitude( ).serialize( ) );
+ if ( o->slopeLoAltitude( ) != c_defaultPatternSlopeLoAlt ||
+ o->slopeHiAltitude( ) != c_defaultPatternSlopeHiAlt )
+ {
+ str.setNum( o->slopeLoAltitude( ) );
+ str2.setNum( o->slopeHiAltitude( ) );
+ dev->writeLine( ", " + str + ", " + str2 );
+ }
+ else
+ dev->writeLine( "" );
+ }
+ dev->objectEnd( );
+ break;
+ case PMPattern::PatternSpherical:
+ dev->writeLine( "spherical" );
+ break;
+ case PMPattern::PatternSpiral1:
+ str.setNum( o->spiralNumberArms( ) );
+ dev->writeLine( "spiral1 " + str );
+ break;
+ case PMPattern::PatternSpiral2:
+ str.setNum( o->spiralNumberArms( ) );
+ dev->writeLine( "spiral2 " + str );
+ break;
+ case PMPattern::PatternSpotted:
+ dev->writeLine( "spotted" );
+ break;
+ case PMPattern::PatternWaves:
+ dev->writeLine( "waves" );
+ break;
+ case PMPattern::PatternWood:
+ dev->writeLine( "wood" );
+ break;
+ case PMPattern::PatternWrinkles:
+ dev->writeLine( "wrinkles" );
+ break;
+ }
+ // depth
+ if( o->parent( ) )
+ {
+ if( o->depth( ) && o->parent( )->type( ) == "Normal" )
+ {
+ str.setNum( o->depth( ) );
+ dev->writeLine( str );
+ }
+ }
+ // modifiers
+ switch( o->patternType( ) )
+ {
+ case PMPattern::PatternAgate:
+ str.setNum( o->agateTurbulence( ) );
+ dev->writeLine( "agate_turb " + str );
+ break;
+ case PMPattern::PatternCrackle:
+ if ( o->crackleForm( ) != c_defaultPatternCrackleForm )
+ dev->writeLine( "form " + o->crackleForm( ).serialize( ) );
+ if ( o->crackleMetric( ) != c_defaultPatternCrackleMetric )
+ {
+ str.setNum( o->crackleMetric( ) );
+ dev->writeLine( "metric " + str );
+ }
+ if ( o->crackleOffset( ) != c_defaultPatternCrackleOffset )
+ {
+ str.setNum( o->crackleOffset( ) );
+ dev->writeLine( "offset " + str );
+ }
+ if ( o->crackleSolid( ) )
+ dev->writeLine( "solid" );
+ break;
+ case PMPattern::PatternDensity:
+ str.setNum( o->densityInterpolate( ) );
+ dev->writeLine( "interpolate " + str );
+ break;
+ case PMPattern::PatternJulia:
+ case PMPattern::PatternMandel:
+ if ( !o->fractalMagnet( ) && o->fractalExponent( ) != c_defaultPatternFractalExponent )
+ {
+ str.setNum( o->fractalExponent( ) );
+ dev->writeLine( "exponent " + str );
+ }
+ if ( o->fractalExtType( ) != c_defaultPatternFractalExtType ||
+ o->fractalExtFactor( ) != c_defaultPatternFractalExtFactor )
+ {
+ str.setNum( o->fractalExtType( ) );
+ str2.setNum( o->fractalExtFactor( ) );
+ dev->writeLine( "exterior " + str + ", " + str2 );
+ }
+ if ( o->fractalIntType( ) != c_defaultPatternFractalIntType ||
+ o->fractalIntFactor( ) != c_defaultPatternFractalIntFactor )
+ {
+ str.setNum( o->fractalIntType( ) );
+ str2.setNum( o->fractalIntFactor( ) );
+ dev->writeLine( "interior " + str + ", " + str2 );
+ }
+ break;
+ case PMPattern::PatternQuilted:
+ str.setNum( o->quiltControl0( ) );
+ dev->writeLine( "control0 " + str );
+ str.setNum( o->quiltControl1( ) );
+ dev->writeLine( "control1 " + str );
+ break;
+ case PMPattern::PatternBozo:
+ case PMPattern::PatternBumps:
+ case PMPattern::PatternGranite:
+ case PMPattern::PatternWrinkles:
+ switch( o->noiseGenerator( ) )
+ {
+ case PMPattern::Original:
+ dev->writeLine( QString( "noise_generator 1" ) );
+ break;
+ case PMPattern::RangeCorrected:
+ dev->writeLine( QString( "noise_generator 2" ) );
+ break;
+ case PMPattern::Perlin:
+ dev->writeLine( QString( "noise_generator 3" ) );
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if( o->isTurbulenceEnabled( ) )
+ {
+ dev->writeLine( "turbulence " + o->valueVector( ).serialize( ) );
+ if( o->octaves( ) != c_defaultPatternOctaves )
+ {
+ str.setNum( o->octaves( ) );
+ dev->writeLine( "octaves " + str );
+ }
+ if( o->omega( ) != c_defaultPatternOmega )
+ {
+ str.setNum( o->omega( ) );
+ dev->writeLine( "omega " + str );
+ }
+ if( o->lambda( ) != c_defaultPatternLambda )
+ {
+ str.setNum( o->lambda( ) );
+ dev->writeLine( "lambda " + str );
+ }
+ }
+}
+
+const double c_defaultNormalAccuracy = 0.02;
+
+void PMPov35SerNormal( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMNormal* o = ( PMNormal* ) object;
+
+ QString str1;
+ bool bObject = true;
+
+ if( o->parent( ) )
+ {
+ if( o->parent( )->type( ) == "NormalMap" )
+ bObject = false;
+ }
+
+ if( bObject )
+ {
+ dev->objectBegin( "normal" );
+ if ( o->uvMapping() )
+ dev->writeLine( "uv_mapping" );
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->isBumpSizeEnabled( ) )
+ {
+ str1.setNum( o->bumpSize( ) );
+ dev->writeLine( "bump_size " + str1 );
+ }
+
+ if( o->accuracy( ) != c_defaultNormalAccuracy )
+ {
+ str1.setNum( o->accuracy( ) );
+ dev->writeLine( "accuracy " + str1 );
+ }
+
+ if( bObject )
+ dev->objectEnd( );
+}
+
+void PMPov35SerInteriorTexture( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ dev->objectBegin( "interior_texture" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+const PMVector c_warpDirectionDefault = PMVector( 1.0, 0.0, 0.0 );
+const PMVector c_warpOffsetDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector c_warpFlipDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector c_warpLocationDefault = PMVector( 0.0, 0.0, 0.0 );
+const double c_warpRadiusDefault = 0;
+const double c_warpStrengthDefault = 0;
+const double c_warpFalloffDefault = 0;
+const bool c_warpInverseDefault = false;
+const PMVector c_warpRepeatDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector c_warpTurbulenceDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector c_warpValueVectorDefault = PMVector( 0.0, 0.0, 0.0 );
+const int c_warpOctavesDefault = 6;
+const double c_warpOmegaDefault = 0.5;
+const double c_warpLambdaDefault = 2.0;
+const PMVector c_warpOrientationDefault = PMVector( 0.0, 0.0, 1.0 );
+const double c_warpDistExpDefault = 0.0;
+const double c_warpMajorRadiusDefault = 1.0;
+
+void PMPov35SerWarp( const PMObject* object, const PMMetaObject* , PMOutputDevice* dev )
+{
+ PMWarp* o = ( PMWarp* ) object;
+
+ QString str1, str2;
+
+ dev->objectBegin( "warp" );
+ switch( o->warpType( ) )
+ {
+ case PMWarp::Repeat:
+ dev->writeLine( "repeat" );
+ dev->writeLine( o->direction( ).serialize( ) );
+ dev->writeLine( "offset " + o->offset( ).serialize( ) );
+ dev->writeLine( "flip " + o->flip( ).serialize( ) );
+ break;
+ case PMWarp::BlackHole:
+ dev->writeLine( "black_hole" );
+ dev->writeLine( o->location( ).serialize( ) );
+ str1.setNum(o->radius( ));
+ dev->writeLine( ", " + str1 );
+ if( o->strength( ) != c_warpStrengthDefault )
+ {
+ str1.setNum( o->strength( ));
+ dev->writeLine( "strength " + str1 );
+ }
+ if( o->falloff( ) != c_warpFalloffDefault )
+ {
+ str1.setNum( o->falloff( ));
+ dev->writeLine( "falloff " + str1 );
+ }
+ if( o->inverse( ) != c_warpInverseDefault )
+ {
+ if( o->inverse( ) ) dev->writeLine( "inverse" );
+ }
+ if( o->repeat( ) != c_warpRepeatDefault )
+ {
+ dev->writeLine( "repeat " + o->repeat( ).serialize( ) );
+ }
+ if( o->turbulence( ) != c_warpTurbulenceDefault )
+ {
+ dev->writeLine( "turbulence " + o->turbulence( ).serialize( ) );
+ }
+ break;
+ case PMWarp::Turbulence:
+ dev->writeLine( "turbulence " + o->valueVector( ).serialize( ) );
+ if( o->octaves( ) != c_warpOctavesDefault )
+ {
+ str1.setNum(o->octaves( ));
+ dev->writeLine( "octaves " + str1 );
+ }
+ if( o->omega( ) != c_warpOmegaDefault )
+ {
+ str1.setNum( o->omega( ) );
+ dev->writeLine( "omega " + str1 );
+ }
+ if( o->lambda( ) != c_warpLambdaDefault )
+ {
+ str1.setNum( o->lambda( ) );
+ dev->writeLine( "lambda " + str1 );
+ }
+ break;
+ case PMWarp::Cylindrical:
+ dev->writeLine( "cylindrical " + o->orientation( ).serialize( ) );
+ if ( o->distExp( ) != c_warpDistExpDefault )
+ {
+ str1.setNum( o->distExp( ) );
+ dev->writeLine( "dist_exp " + str1 );
+ }
+ break;
+ case PMWarp::Spherical:
+ dev->writeLine( "spherical " + o->orientation( ).serialize( ) );
+ if ( o->distExp( ) != c_warpDistExpDefault )
+ {
+ str1.setNum( o->distExp( ) );
+ dev->writeLine( "dist_exp " + str1 );
+ }
+ break;
+ case PMWarp::Toroidal:
+ dev->writeLine( "torodial " + o->orientation( ).serialize( ) );
+ if ( o->distExp( ) != c_warpDistExpDefault )
+ {
+ str1.setNum( o->distExp( ) );
+ dev->writeLine( "dist_exp " + str1 );
+ }
+ if ( o->majorRadius( ) != c_warpMajorRadiusDefault )
+ {
+ str1.setNum( o->majorRadius( ) );
+ dev->writeLine( "major_radius " + str1 );
+ }
+ break;
+ case PMWarp::Planar:
+ str1 = "planar " + o->orientation( ).serialize( );
+ if ( o->distExp( ) != c_warpDistExpDefault )
+ {
+ str2.setNum( o->distExp( ) );
+ dev->writeLine( str1 + ", " + str2 );
+ }
+ else
+ dev->writeLine( str1 );
+ break;
+ }
+
+ dev->objectEnd( );
+}
+
+const double c_sphereSweepToleranceDefault = 1e-6;
+
+void PMPov35SerSphereSweep( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMSphereSweep* o = ( PMSphereSweep* ) object;
+
+ QString str1;
+ int numSpheres;
+ QValueList<PMVector> points;
+ QValueList<double> radii;
+
+ dev->objectBegin( "sphere_sweep" );
+
+ switch( o->splineType( ) )
+ {
+ case PMSphereSweep::LinearSpline:
+ dev->writeLine( QString( "linear_spline," ) );
+ break;
+ case PMSphereSweep::BSpline:
+ dev->writeLine( QString( "b_spline," ) );
+ break;
+ case PMSphereSweep::CubicSpline:
+ dev->writeLine( QString( "cubic_spline," ) );
+ break;
+ }
+
+ numSpheres = o->numberOfPoints( );
+ str1.setNum( numSpheres );
+ dev->writeLine( str1 + "," );
+ points = o->points( );
+ radii = o->radii( );
+
+ for ( int i = 0; i < numSpheres; ++i )
+ {
+ str1.setNum( radii[i] );
+ dev->writeLine( points[i].serialize( ) + "," + str1 );
+ }
+
+ if ( o->tolerance( ) != c_sphereSweepToleranceDefault )
+ {
+ str1.setNum( o->tolerance( ) );
+ dev->writeLine( "tolerance " + str1 );
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov35SerFinish( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMFinish* o = ( PMFinish* ) object;
+
+ QString str1;
+
+ dev->objectBegin( "finish" );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->isAmbientEnabled( ) )
+ dev->writeLine( "ambient " + o->ambientColor( ).serialize( ) );
+
+ if( o->isDiffuseEnabled( ) )
+ {
+ str1.setNum( o->diffuse( ) );
+ dev->writeLine( "diffuse " + str1 );
+ }
+
+ if( o->isBrillianceEnabled( ) )
+ {
+ str1.setNum( o->brilliance( ) );
+ dev->writeLine( "brilliance " + str1 );
+ }
+
+ if( o->isPhongEnabled( ) )
+ {
+ str1.setNum( o->phong( ) );
+ dev->writeLine( "phong " + str1 );
+ }
+
+ if( o->isPhongSizeEnabled( ) )
+ {
+ str1.setNum( o->phongSize( ) );
+ dev->writeLine( "phong_size " + str1 );
+ }
+
+ if( o->isMetallicEnabled( ) )
+ {
+ str1.setNum( o->metallic( ) );
+ dev->writeLine( "metallic " + str1 );
+ }
+
+ if( o->isSpecularEnabled( ) )
+ {
+ str1.setNum( o->specular( ) );
+ dev->writeLine( "specular " + str1 );
+ }
+
+ if( o->isRoughnessEnabled( ) )
+ {
+ str1.setNum( o->roughness( ) );
+ dev->writeLine( "roughness " + str1 );
+ }
+
+ if( o->isCrandEnabled( ) )
+ {
+ str1.setNum( o->crand( ) );
+ dev->writeLine( "crand " + str1 );
+ }
+
+ if( o->conserveEnergy( ) )
+ dev->writeLine( "conserve_energy" );
+
+ if( o->irid( ) )
+ {
+ str1.setNum( o->iridAmount( ) );
+ dev->writeLine( "irid { " + str1 );
+ str1.setNum( o->iridThickness( ) );
+ dev->writeLine( "thickness " + str1 );
+ str1.setNum( o->iridTurbulence( ) );
+ dev->writeLine( "turbulence " + str1 + " } " );
+ }
+
+ if( o->isReflectionEnabled( ) )
+ {
+ dev->objectBegin( "reflection" );
+
+ if ( o->isReflectionMinEnabled( ) )
+ {
+ dev->writeLine( o->reflectionMinColor( ).serialize( ) + ", " +
+ o->reflectionColor( ).serialize( ) );
+ }
+ else
+ dev->writeLine( o->reflectionColor( ).serialize( ) );
+
+ if ( o->reflectionFresnel( ) )
+ dev->writeLine( "fresnel" );
+
+ if ( o->isRefFalloffEnabled( ) )
+ {
+ str1.setNum( o->reflectionFalloff( ) );
+ dev->writeLine( "falloff " + str1 );
+ }
+
+ if ( o->isRefExponentEnabled( ) )
+ {
+ str1.setNum( o->reflectionExponent( ) );
+ dev->writeLine( "exponent " + str1 );
+ }
+
+ if ( o->isRefMetallicEnabled( ) )
+ {
+ str1.setNum( o->reflectionMetallic( ) );
+ dev->writeLine( "metallic " + str1 );
+ }
+
+ dev->objectEnd( );
+ }
+
+ dev->objectEnd( );
+}
+
+void PMPov35SerMesh( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMMesh* o = ( PMMesh* ) object;
+
+ dev->objectBegin( "mesh" );
+
+ if( o->isInsideVectorEnabled( ) )
+ dev->writeLine( "inside_vector " + o->insideVector( ).serialize( ) );
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( !o->hierarchy( ) )
+ dev->writeLine( "hierarchy off" );
+
+ dev->objectEnd( );
+}
+
+const int c_defaultMediaMethod = 1;
+const int c_defaultMediaIntervals = 10;
+const int c_defaultMediaSamplesMin = 1;
+const int c_defaultMediaSamplesMax = 1;
+const double c_defaultMediaConfidence = 0.9;
+const double c_defaultMediaVariance = 0.0078125;
+const double c_defaultMediaRatio = 0.9;
+const int c_defaultMediaAALevel = 4;
+const double c_defaultMediaAAThreshold = 0.1;
+const double c_defaultMediaScatteringEccentricity = 0;
+const double c_defaultMediaScatteringExtinction = 1.0;
+
+void PMPov35SerMedia( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMMedia* o = ( PMMedia* ) object;
+
+ QString str1;
+ QString str2;
+
+ dev->objectBegin( "media" );
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->method( ) != c_defaultMediaMethod )
+ {
+ str1.setNum( o->method( ) );
+ dev->writeLine( "method " + str1 );
+ }
+ if( o->intervals( ) != c_defaultMediaIntervals )
+ {
+ str1.setNum( o->intervals( ) );
+ dev->writeLine( "intervals " + str1 );
+ }
+ if( o->samplesMin( ) != c_defaultMediaSamplesMin ||
+ o->samplesMax( ) != c_defaultMediaSamplesMax )
+ {
+ str1.setNum( o->samplesMin( ) );
+ str2.setNum( o->samplesMax( ) );
+ if ( o->method( ) < 3 )
+ dev->writeLine( "samples " + str1 + "," + str2 );
+ else
+ dev->writeLine( "samples " + str1 );
+ }
+ if( o->confidence( ) != c_defaultMediaConfidence )
+ {
+ str1.setNum( o->confidence( ) );
+ dev->writeLine( "confidence " + str1 );
+ }
+ if( o->variance( ) != c_defaultMediaVariance )
+ {
+ str1.setNum( o->variance( ) );
+ dev->writeLine( "variance " + str1 );
+ }
+ if( o->ratio( ) != c_defaultMediaRatio )
+ {
+ str1.setNum( o->ratio( ) );
+ dev->writeLine( "ratio " + str1 );
+ }
+ if ( o->method( ) == 3 )
+ {
+ if ( o->aaLevel( ) != c_defaultMediaAALevel )
+ {
+ str1.setNum( o->aaLevel( ) );
+ dev->writeLine( "aa_level " + str1 );
+ }
+ if ( o->aaThreshold( ) != c_defaultMediaAAThreshold )
+ {
+ str1.setNum( o->aaThreshold( ) );
+ dev->writeLine( "aa_threshold " + str1 );
+ }
+ }
+ if( o->isAbsorptionEnabled( ) )
+ {
+ dev->writeLine( "absorption " + o->absorption( ).serialize( ) );
+ }
+ if( o->isEmissionEnabled( ) )
+ {
+ dev->writeLine( "emission " + o->emission( ).serialize( ) );
+ }
+ if( o->isScatteringEnabled( ) )
+ {
+ dev->objectBegin( "scattering" );
+ str1.setNum( o->scatteringType( ) );
+ dev->writeLine( str1 + ", " + o->scatteringColor( ).serialize( ) );
+ if( o->scatteringType( ) == 5 && o->scatteringEccentricity( )
+ != c_defaultMediaScatteringEccentricity )
+ {
+ str1.setNum( o->scatteringEccentricity( ) );
+ dev->writeLine( "eccentricity " + str1 );
+ }
+ if( o->scatteringExtinction( ) != c_defaultMediaScatteringExtinction )
+ {
+ str1.setNum( o->scatteringExtinction( ) );
+ dev->writeLine( "extinction " + str1 );
+ }
+ dev->objectEnd( );
+ }
+ dev->objectEnd( );
+}
+
+void PMPov35SerGraphicalObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMGraphicalObject* o = ( PMGraphicalObject* ) object;
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+
+ if( o->noShadow( ) )
+ dev->writeLine( "no_shadow" );
+
+ if( o->noImage( ) )
+ dev->writeLine( "no_image" );
+
+ if( o->noReflection( ) )
+ dev->writeLine( "no_reflection" );
+
+ if( o->doubleIlluminate( ) )
+ dev->writeLine( "double_illuminate" );
+}
+
+void PMPov35SerPigment( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMPigment* o = ( PMPigment* ) object;
+
+ bool bObject = true;
+ if( o->parent( ) )
+ if( o->parent( )->type( ) == "PigmentMap" )
+ bObject = false;
+
+ if( bObject )
+ {
+ dev->objectBegin( "pigment" );
+ if ( o->uvMapping() )
+ dev->writeLine( "uv_mapping" );
+ }
+ dev->callSerialization( object, metaObject->superClass( ) );
+ if( bObject )
+ dev->objectEnd( );
+}
+
+void PMPov35SerTexture( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMTexture* o = ( PMTexture* ) object;
+
+ bool bObject = true;
+ if( o->parent( ) )
+ if( o->parent( )->type( ) == "TextureMap" )
+ bObject = false;
+
+ if( bObject )
+ {
+ dev->objectBegin( "texture" );
+ if ( o->uvMapping() )
+ dev->writeLine( "uv_mapping" );
+ }
+ dev->callSerialization( object, metaObject->superClass( ) );
+ if( bObject )
+ dev->objectEnd( );
+}
+
+const double c_defaultPatchFlatness = 0;
+
+void PMPov35SerBicubicPatch( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMBicubicPatch* o = ( PMBicubicPatch* ) object;
+
+ int u, v;
+ QString str, line;
+ dev->objectBegin( "bicubic_patch" );
+
+ dev->writeName( object->name( ) );
+
+ str.setNum( o->patchType( ) );
+ dev->writeLine( "type " + str );
+ if( !approx( o->flatness( ), c_defaultPatchFlatness ) )
+ {
+ str.setNum( o->flatness( ) );
+ dev->writeLine( "flatness " + str );
+ }
+ str.setNum( o->uSteps( ) );
+ dev->writeLine( "u_steps " + str );
+ str.setNum( o->vSteps( ) );
+ dev->writeLine( "v_steps " + str );
+
+ if( o->isUVEnabled( ) )
+ {
+ dev->writeLine( "uv_vectors " + o->uvVector( 0 ).serialize( ) +
+ " " + o->uvVector( 1 ).serialize( ) +
+ " " + o->uvVector( 2 ).serialize( ) +
+ " " + o->uvVector( 3 ).serialize( ) );
+ }
+
+ for( v = 0; v < 4; v++ )
+ {
+ line = o->controlPoint( v*4 ).serialize( );
+ for( u = 1; u < 4; u++ )
+ line += QString( ", " ) + o->controlPoint( u+4*v ).serialize( );
+ if( v != 3 )
+ line += ",";
+ dev->writeLine( line );
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
+
+void PMPov35SerTriangle( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev )
+{
+ PMTriangle* o = ( PMTriangle* ) object;
+
+ if( o->isSmoothTriangle( ) )
+ {
+ dev->objectBegin( "smooth_triangle" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->point( 0 ).serialize( ) + ", " + o->normal( 0 ).serialize( ) + "," );
+ dev->writeLine( o->point( 1 ).serialize( ) + ", " + o->normal( 1 ).serialize( ) + "," );
+ dev->writeLine( o->point( 2 ).serialize( ) + ", " + o->normal( 2 ).serialize( ) );
+ }
+ else
+ {
+ dev->objectBegin( "triangle" );
+
+ dev->writeName( object->name( ) );
+ dev->writeLine( o->point( 0 ).serialize( ) + ", " + o->point( 1 ).serialize( )
+ + ", " + o->point( 2 ).serialize( ) );
+ }
+
+ if( o->isUVEnabled( ) )
+ {
+ dev->writeLine( "uv_vectors " + o->uvVector( 0 ).serialize( ) +
+ " " + o->uvVector( 1 ).serialize( ) +
+ " " + o->uvVector( 2 ).serialize( ) );
+ }
+
+ dev->callSerialization( object, metaObject->superClass( ) );
+ dev->objectEnd( );
+}
diff --git a/kpovmodeler/pmpovray35serialization.h b/kpovmodeler/pmpovray35serialization.h
new file mode 100644
index 00000000..4e511d55
--- /dev/null
+++ b/kpovmodeler/pmpovray35serialization.h
@@ -0,0 +1,49 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAY35_SERIALIZATION_H
+#define PMPOVRAY35_SERIALIZATION_H
+
+class PMObject;
+class PMMetaObject;
+class PMOutputDevice;
+
+// serialization methods for POV-Ray 3.5
+
+void PMPov35SerIsoSurface( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerLight( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerProjectedThrough( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerGlobalSettings( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerRadiosity( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerGlobalPhotons( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerPhotons( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerInterior( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerLightGroup( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerPattern( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerNormal( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerInteriorTexture( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerWarp( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerSphereSweep( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerFinish( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerMesh( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerMedia( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerGraphicalObject( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerPigment( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerTexture( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerBicubicPatch( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+void PMPov35SerTriangle( const PMObject* object, const PMMetaObject* metaObject, PMOutputDevice* dev );
+#endif
diff --git a/kpovmodeler/pmpovrayformat.cpp b/kpovmodeler/pmpovrayformat.cpp
new file mode 100644
index 00000000..a2c48c80
--- /dev/null
+++ b/kpovmodeler/pmpovrayformat.cpp
@@ -0,0 +1,52 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovrayformat.h"
+#include "pmdebug.h"
+
+PMPovrayFormat::PMPovrayFormat( )
+{
+ m_methodDict.setAutoDelete( true );
+}
+
+
+PMPovrayFormat::~PMPovrayFormat( )
+{
+
+}
+
+void PMPovrayFormat::registerMethod( const QString& className,
+ PMPovraySerializeMethod method )
+{
+ PMPovraySerializeMethodInfo* info = m_methodDict.find( className );
+ if( info )
+ kdWarning( PMArea ) << "Serialization method for " << className
+ << " shadows old implementation" << endl;
+ info = new PMPovraySerializeMethodInfo( method );
+ m_methodDict.insert( className, info );
+}
+
+void PMPovrayFormat::removeMethod( const QString& className )
+{
+ m_methodDict.remove( className );
+}
+
+const PMPovraySerializeMethodInfo* PMPovrayFormat::serializationMethod(
+ const QString& className )
+{
+ return m_methodDict.find( className );
+}
diff --git a/kpovmodeler/pmpovrayformat.h b/kpovmodeler/pmpovrayformat.h
new file mode 100644
index 00000000..398cae42
--- /dev/null
+++ b/kpovmodeler/pmpovrayformat.h
@@ -0,0 +1,94 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAY_FORMAT_H
+#define PMPOVRAY_FORMAT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmiomanager.h"
+#include "pmoutputdevice.h"
+
+typedef void ( *PMPovraySerializeMethod ) ( const PMObject*, const PMMetaObject*,
+ PMOutputDevice* );
+/**
+ * Helper class for @ref PMOutputDevice and @ref PMPovrayFormatBase
+ */
+class PMPovraySerializeMethodInfo
+{
+public:
+ PMPovraySerializeMethodInfo( )
+ {
+ m_method = 0;
+ }
+ PMPovraySerializeMethodInfo( PMPovraySerializeMethod m )
+ {
+ m_method = m;
+ }
+ PMPovraySerializeMethod method( ) const { return m_method; }
+ void call( const PMObject* o, const PMMetaObject* mo, PMOutputDevice* ser ) const
+ {
+ if( m_method )
+ m_method( o, mo, ser );
+ }
+private:
+ PMPovraySerializeMethod m_method;
+};
+
+/**
+ * Base class for all POV-Ray formats which use a PMOutputDevice
+ * for serialization.
+ *
+ * Plugins can register new serialization methods with @ref registerMethod
+ */
+class PMPovrayFormat : public PMIOFormat
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMPovrayFormat( );
+ /**
+ * Destructor
+ */
+ virtual ~PMPovrayFormat( );
+
+ /**
+ * Registers the serialization method for the class className
+ */
+ void registerMethod( const QString& className, PMPovraySerializeMethod method );
+ /**
+ * Removes a registered serialization method
+ */
+ void removeMethod( const QString& className );
+ /**
+ * Returns the serialization methods info for the given object type
+ * or 0 if there is none.
+ */
+ const PMPovraySerializeMethodInfo* serializationMethod(
+ const QString& className );
+
+private:
+ /**
+ * Dict class name -> serialization method
+ */
+ QDict<PMPovraySerializeMethodInfo> m_methodDict;
+};
+
+#endif
diff --git a/kpovmodeler/pmpovraymatrix.cpp b/kpovmodeler/pmpovraymatrix.cpp
new file mode 100644
index 00000000..4100d46a
--- /dev/null
+++ b/kpovmodeler/pmpovraymatrix.cpp
@@ -0,0 +1,152 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpovraymatrix.h"
+#include "pmpovraymatrixedit.h"
+
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMPovrayMatrix, PMPovrayMatrixProperty );
+
+PMMetaObject* PMPovrayMatrix::s_pMetaObject = 0;
+PMObject* createNewPovrayMatrix( PMPart* part )
+{
+ return new PMPovrayMatrix( part );
+}
+
+PMPovrayMatrix::PMPovrayMatrix( PMPart* part )
+ : Base( part )
+{
+ m_values = PMVector( 12 );
+ m_values[0] = 1.0;
+ m_values[4] = 1.0;
+ m_values[8] = 1.0;
+}
+
+PMPovrayMatrix::PMPovrayMatrix( const PMPovrayMatrix& m )
+ : Base( m )
+{
+ m_values = m.m_values;
+}
+
+PMPovrayMatrix::~PMPovrayMatrix( )
+{
+}
+
+QString PMPovrayMatrix::description( ) const
+{
+ return i18n( "matrix" );
+}
+
+void PMPovrayMatrix::serialize( QDomElement& e, QDomDocument& /*doc*/ ) const
+{
+ e.setAttribute( "value", m_values.serializeXML( ) );
+}
+
+void PMPovrayMatrix::readAttributes( const PMXMLHelper& h )
+{
+ PMVector d = PMVector( 12 );
+ d[0] = 1.0;
+ d[4] = 1.0;
+ d[8] = 1.0;
+
+ m_values = h.vectorAttribute( "value", d );
+ m_values.resize( 12 );
+}
+
+PMMetaObject* PMPovrayMatrix::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "PovrayMatrix", Base::metaObject( ),
+ createNewPovrayMatrix );
+ s_pMetaObject->addProperty(
+ new PMPovrayMatrixProperty( "values", &PMPovrayMatrix::setValues, &PMPovrayMatrix::values ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMPovrayMatrix::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMPovrayMatrix::setValues( const PMVector& v )
+{
+ if( v != m_values )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMMatrixID, m_values );
+ m_pMemento->setViewStructureChanged( );
+ }
+ m_values = v;
+ m_values.resize( 12 );
+ }
+}
+
+PMDialogEditBase* PMPovrayMatrix::editWidget( QWidget* parent ) const
+{
+ return new PMPovrayMatrixEdit( parent );
+}
+
+void PMPovrayMatrix::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMMatrixID:
+ setValues( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMPovrayMatrix::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+PMMatrix PMPovrayMatrix::transformationMatrix( ) const
+{
+ PMMatrix m;
+ int l, c;
+
+ for( l = 0; l < 4; l++ )
+ for( c = 0; c < 3; c++ )
+ m[l][c] = m_values[l*3+c];
+ m[3][3] = 1.0;
+
+ return m;
+}
+
diff --git a/kpovmodeler/pmpovraymatrix.h b/kpovmodeler/pmpovraymatrix.h
new file mode 100644
index 00000000..25a1e03b
--- /dev/null
+++ b/kpovmodeler/pmpovraymatrix.h
@@ -0,0 +1,97 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPOVRAYMATRIX_H
+#define PMPOVRAYMATRIX_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+/**
+ * Class for povray matrix transformations.
+ */
+
+class PMPovrayMatrix : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates an identity matrix
+ */
+ PMPovrayMatrix( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPovrayMatrix( const PMPovrayMatrix& m );
+ /**
+ * deletes the object
+ */
+ virtual ~PMPovrayMatrix( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPovrayMatrix( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMPovrayMatrixEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmmatrix" ); }
+
+ /**
+ * Returns the matrix values.
+ */
+ PMVector values( ) const { return m_values; }
+ /**
+ * Sets the matrix values. Has to be a vector with size 12.
+ */
+ void setValues( const PMVector& v );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual bool hasTransformationMatrix( ) const { return true; }
+ /** */
+ virtual PMMatrix transformationMatrix( ) const;
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMMatrixMementoID { PMMatrixID };
+ PMVector m_values;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmpovraymatrixedit.cpp b/kpovmodeler/pmpovraymatrixedit.cpp
new file mode 100644
index 00000000..0d78c226
--- /dev/null
+++ b/kpovmodeler/pmpovraymatrixedit.cpp
@@ -0,0 +1,102 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpovraymatrixedit.h"
+#include "pmpovraymatrix.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMPovrayMatrixEdit::PMPovrayMatrixEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMPovrayMatrixEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ int i, r, c;
+ QGridLayout* gl = new QGridLayout( topLayout( ), 4, 4 );
+
+ for( i = 0; i < 12; i++ )
+ {
+ m_pValue[i] = new PMFloatEdit( this );
+ connect( m_pValue[i], SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ }
+
+ for( r = 0; r < 4; r++ )
+ for( c = 0; c < 3; c++ )
+ gl->addWidget( m_pValue[r*3+c], r, c );
+ gl->addWidget( new QLabel( "0.0", this ), 0, 3 );
+ gl->addWidget( new QLabel( "0.0", this ), 1, 3 );
+ gl->addWidget( new QLabel( "0.0", this ), 2, 3 );
+ gl->addWidget( new QLabel( "1.0", this ), 3, 3 );
+}
+
+void PMPovrayMatrixEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "PovrayMatrix" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ int i;
+ m_pDisplayedObject = ( PMPovrayMatrix* ) o;
+ PMVector v = m_pDisplayedObject->values( );
+
+ for( i = 0; i < 12; i++ )
+ {
+ m_pValue[i]->setValue( v[i] );
+ m_pValue[i]->setReadOnly( readOnly );
+ }
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMPovrayMatrixEdit: Can't display object\n";
+}
+
+void PMPovrayMatrixEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ PMVector v( 12 );
+ int i;
+
+ for( i = 0; i < 12; i++ )
+ v[i] = m_pValue[i]->value( );
+ m_pDisplayedObject->setValues( v );
+ }
+}
+
+bool PMPovrayMatrixEdit::isDataValid( )
+{
+ int i;
+
+ for( i = 0; i < 12; i++ )
+ if( !m_pValue[i]->isDataValid( ) )
+ return false;
+
+ return Base::isDataValid( );
+}
+
+#include "pmpovraymatrixedit.moc"
diff --git a/kpovmodeler/pmpovraymatrixedit.h b/kpovmodeler/pmpovraymatrixedit.h
new file mode 100644
index 00000000..2dbd41ae
--- /dev/null
+++ b/kpovmodeler/pmpovraymatrixedit.h
@@ -0,0 +1,62 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPOVRAYMATRIXEDIT_H
+#define PMPOVRAYMATRIXEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMPovrayMatrix;
+class PMFloatEdit;
+
+/**
+ * Dialog edit class for @ref PMPovrayMatrix
+ */
+class PMPovrayMatrixEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMPovrayMatrixEdit with parent and name
+ */
+ PMPovrayMatrixEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMPovrayMatrix* m_pDisplayedObject;
+ PMFloatEdit* m_pValue[12];
+};
+
+
+#endif
diff --git a/kpovmodeler/pmpovrayoutputwidget.cpp b/kpovmodeler/pmpovrayoutputwidget.cpp
new file mode 100644
index 00000000..b0d4ca73
--- /dev/null
+++ b/kpovmodeler/pmpovrayoutputwidget.cpp
@@ -0,0 +1,115 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovrayoutputwidget.h"
+
+#include <qtextedit.h>
+#include <qlayout.h>
+
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+#include "pmdebug.h"
+
+QSize PMPovrayOutputWidget::s_size = QSize( 400, 400 );
+
+PMPovrayOutputWidget::PMPovrayOutputWidget( QWidget* parent, const char* name )
+ : KDialog( parent, name )
+{
+ QVBoxLayout* topLayout = new QVBoxLayout( this, KDialog::marginHint( ), KDialog::spacingHint( ) );
+
+ m_pTextView = new QTextEdit( this );
+ topLayout->addWidget( m_pTextView, 1 );
+ m_pTextView->setFont( KGlobalSettings::fixedFont( ) );
+ m_pTextView->setTextFormat( Qt::PlainText );
+ m_pTextView->setReadOnly( true );
+
+ QHBoxLayout* buttonLayout = new QHBoxLayout( topLayout );
+ buttonLayout->addStretch( 1 );
+ QPushButton* closeButton = new KPushButton( KStdGuiItem::close(), this );
+ buttonLayout->addWidget( closeButton );
+ closeButton->setDefault( true );
+ connect( closeButton, SIGNAL( clicked( ) ), SLOT( hide( ) ) );
+
+ setCaption( i18n( "Povray Output" ) );
+ resize( s_size );
+
+ m_startOfLastLine = 0;
+}
+
+PMPovrayOutputWidget::~PMPovrayOutputWidget( )
+{
+}
+
+void PMPovrayOutputWidget::slotClear( )
+{
+ m_output = QString::null;
+ m_startOfLastLine = 0;
+ m_pTextView->clear( );
+}
+
+void PMPovrayOutputWidget::slotText( const QString& output )
+{
+ unsigned int i;
+
+ for( i = 0; i < output.length( ); i++ )
+ {
+ QChar c = output[i];
+ if( c == '\r' )
+ m_output.truncate( m_startOfLastLine );
+ else if( c == '\n' )
+ {
+ m_output += c;
+ m_startOfLastLine = m_output.length( );
+ //kdDebug( PMArea ) << m_startOfLastLine << endl;
+ }
+ else if( c.isPrint( ) )
+ m_output += c;
+ }
+
+ m_pTextView->setText( m_output );
+}
+
+void PMPovrayOutputWidget::slotClose( )
+{
+ hide( );
+}
+
+
+void PMPovrayOutputWidget::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+ cfg->writeEntry( "PovrayOutputWidgetSize", s_size );
+}
+
+void PMPovrayOutputWidget::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+
+ QSize defaultSize( 500, 400 );
+ s_size = cfg->readSizeEntry( "PovrayOutputWidgetSize", &defaultSize );
+}
+
+void PMPovrayOutputWidget::resizeEvent( QResizeEvent* ev )
+{
+ s_size = ev->size( );
+}
+
+#include "pmpovrayoutputwidget.moc"
diff --git a/kpovmodeler/pmpovrayoutputwidget.h b/kpovmodeler/pmpovrayoutputwidget.h
new file mode 100644
index 00000000..faac7352
--- /dev/null
+++ b/kpovmodeler/pmpovrayoutputwidget.h
@@ -0,0 +1,77 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAYOUTPUTWIDGET_H
+#define PMPOVRAYOUTPUTWIDGET_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <kdialog.h>
+class QTextEdit;
+class KConfig;
+
+/**
+ * Widget to display the povray text output
+ */
+class PMPovrayOutputWidget : public KDialog
+{
+ Q_OBJECT
+public:
+ /**
+ * Standard constructor
+ */
+ PMPovrayOutputWidget( QWidget* parent = 0, const char* name = 0 );
+ /**
+ * Destructor
+ */
+ ~PMPovrayOutputWidget( );
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+
+public slots:
+ /**
+ * Clears the text
+ */
+ void slotClear( );
+ /**
+ * Adds the text to the output
+ */
+ void slotText( const QString& output );
+
+protected slots:
+ /**
+ * Called when the close button is clicked
+ */
+ void slotClose( );
+
+protected:
+ virtual void resizeEvent( QResizeEvent* ev );
+
+private:
+ QTextEdit* m_pTextView;
+ int m_startOfLastLine;
+ QString m_output;
+ static QSize s_size;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmpovrayparser.cpp b/kpovmodeler/pmpovrayparser.cpp
new file mode 100644
index 00000000..88bd8393
--- /dev/null
+++ b/kpovmodeler/pmpovrayparser.cpp
@@ -0,0 +1,7213 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmpovrayparser.h"
+
+#include <klocale.h>
+#include <qvaluelist.h>
+
+#include "pmpart.h"
+#include "pmscanner.h"
+#include "pmtokens.h"
+
+#include "pmcolor.h"
+#include "pmallobjects.h"
+#include "pmprototypemanager.h"
+#include "pmxmlhelper.h"
+
+
+PMPovrayParser::PMPovrayParser( PMPart* part, QIODevice* dev )
+ : PMParser( part, dev )
+{
+ init( );
+}
+
+PMPovrayParser::PMPovrayParser( PMPart* part, const QByteArray& array )
+ : PMParser( part, array )
+{
+ init( );
+}
+
+PMPovrayParser::~PMPovrayParser( )
+{
+ if( m_pScanner )
+ delete m_pScanner;
+}
+
+void PMPovrayParser::init( )
+{
+ m_pScanner = new PMScanner( m_pDevice );
+ m_consumedTokens = 0;
+ m_skippedComments.setAutoDelete( true );
+ m_bLastPMCommentEmpty = true;
+}
+
+
+void PMPovrayParser::nextToken( )
+{
+ m_token = m_pScanner->nextToken( );
+ m_consumedTokens++;
+ setCurrentLine( m_pScanner->currentLine( ) );
+
+ if( ( m_token == SCANNER_ERROR_TOK ) || ( m_token == COMMENT_TOK )
+ || ( m_token == LINE_COMMENT_TOK ) || ( m_token == PMNAME_TOK ) )
+ {
+ // create the objects (string) only if necessary
+ PMComment* c;
+ int lastCommentLine = -2;
+ QString commentText;
+
+ while( ( m_token == SCANNER_ERROR_TOK ) || ( m_token == COMMENT_TOK )
+ || ( m_token == LINE_COMMENT_TOK ) || ( m_token == PMNAME_TOK ) )
+ {
+ switch( m_token )
+ {
+ case SCANNER_ERROR_TOK:
+ printError( m_pScanner->error( ) );
+ lastCommentLine = -2;
+ break;
+ case LINE_COMMENT_TOK:
+ commentText = m_pScanner->sValue( );
+ if( lastCommentLine == ( m_pScanner->currentLine( ) - 1 ) )
+ {
+ c = m_skippedComments.last( );
+ if( c )
+ c->setText( c->text( ) + '\n' + commentText );
+ else
+ {
+ c = new PMComment( m_pPart, commentText );
+ m_skippedComments.append( c );
+ }
+ }
+ else
+ {
+ c = new PMComment( m_pPart, m_pScanner->sValue( ) );
+ m_skippedComments.append( c );
+ }
+ lastCommentLine = m_pScanner->currentLine( );
+ break;
+ case COMMENT_TOK:
+ c = new PMComment( m_pPart, m_pScanner->sValue( ) );
+ m_skippedComments.append( c );
+ lastCommentLine = -2;
+ break;
+ case PMNAME_TOK:
+ // Special comment
+ m_lastPMComment = m_pScanner->sValue( );
+ m_bLastPMCommentEmpty = false;
+ lastCommentLine = -2;
+ break;
+ default:
+ lastCommentLine = -2;
+ break;
+ }
+
+ m_token = m_pScanner->nextToken( );
+ m_consumedTokens++;
+ }
+ }
+}
+
+bool PMPovrayParser::isTrue( ) const
+{
+ if( ( m_token == ON_TOK ) || ( m_token == TRUE_TOK ) || ( m_token == YES_TOK ) )
+ return true;
+ return false;
+}
+
+bool PMPovrayParser::isFalse( ) const
+{
+ if( ( m_token == OFF_TOK ) || ( m_token == FALSE_TOK ) || ( m_token == NO_TOK ) )
+ return true;
+ return false;
+}
+
+void PMPovrayParser::topParse( )
+{
+ nextToken( );
+
+ do
+ {
+ if( !parseChildObjects( 0 ) )
+ m_token = EOF_TOK;
+ if( m_token != EOF_TOK )
+ {
+ printUnexpected( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+ }
+ while( m_token != EOF_TOK );
+
+ if( errors( ) || warnings( ) )
+ printMessage( PMMSpecialRawComment );
+}
+
+bool PMPovrayParser::parseBool( )
+{
+ if( isFalse( ) )
+ {
+ nextToken( );
+ return false;
+ }
+ if( isTrue( ) )
+ {
+ nextToken( );
+ return true;
+ }
+
+ PMValue v;
+
+ if( parseNumericExpression( v, true ) )
+ {
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ return v.floatValue( ) > 0.0;
+ break;
+ case PMVVector:
+ return ( v.vector( ) )[0] > 0.0;
+ break;
+ default:
+ printError( i18n( "Boolean expression expected" ) );
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool PMPovrayParser::parseChildObjects( PMCompositeObject* parent,
+ int max /* = -1 */ )
+{
+ PMObject* child = 0;
+ bool finished = false;
+ bool error = false;
+ bool noChild = false;
+ int numParsed = 0;
+
+ do
+ {
+ if( !m_bLastPMCommentEmpty && parent )
+ {
+ if( parent->isA( "NamedObject" ) )
+ ( ( PMNamedObject* ) parent )->setName( m_lastPMComment );
+ m_bLastPMCommentEmpty = true;
+ }
+ if( m_skippedComments.count( ) > 0 )
+ child = m_skippedComments.take( 0 );
+ else
+ {
+ child = 0;
+ noChild = false;
+
+ // some objects
+ switch( m_token )
+ {
+ case UNION_TOK:
+ case DIFFERENCE_TOK:
+ case INTERSECTION_TOK:
+ case MERGE_TOK:
+ child = new PMCSG( m_pPart );
+ error = !parseCSG( ( PMCSG* ) child );
+ break;
+ case BOX_TOK:
+ child = new PMBox( m_pPart );
+ error = !parseBox( ( PMBox* ) child );
+ break;
+ case SPHERE_TOK:
+ if( ( parent && ( parent->type( ) == "Blob" ) )
+ || ( !parent && m_pTopParent
+ && ( m_pTopParent->type( ) == "Blob" ) ) )
+ {
+ child = new PMBlobSphere( m_pPart );
+ error = !parseBlobSphere( ( PMBlobSphere* ) child );
+ }
+ else
+ {
+ child = new PMSphere( m_pPart );
+ error = !parseSphere( ( PMSphere* ) child );
+ }
+ break;
+ case CYLINDER_TOK:
+ if( ( parent && ( parent->type( ) == "Blob" ) )
+ || ( !parent && m_pTopParent
+ && ( m_pTopParent->type( ) == "Blob" ) ) )
+ {
+ child = new PMBlobCylinder( m_pPart );
+ error = !parseBlobCylinder( ( PMBlobCylinder* ) child );
+ }
+ else
+ {
+ child = new PMCylinder( m_pPart );
+ error = !parseCylinder( ( PMCylinder* ) child );
+ }
+ break;
+ case CONE_TOK:
+ child = new PMCone( m_pPart );
+ error = !parseCone( ( PMCone* ) child );
+ break;
+ case TORUS_TOK:
+ child = new PMTorus( m_pPart );
+ error = !parseTorus( ( PMTorus* ) child );
+ break;
+ case BLOB_TOK:
+ child = new PMBlob( m_pPart );
+ error = !parseBlob( ( PMBlob* ) child );
+ break;
+ case COMPONENT_TOK:
+ child = new PMBlobSphere( m_pPart );
+ error = !parseBlobComponent( ( PMBlobSphere* ) child );
+ break;
+ case HEIGHT_FIELD_TOK:
+ child = new PMHeightField( m_pPart );
+ error = !parseHeightField( ( PMHeightField* ) child );
+ break;
+ case TEXT_TOK:
+ child = new PMText( m_pPart );
+ error = !parseText( ( PMText* ) child );
+ break;
+ case JULIA_FRACTAL_TOK:
+ child = new PMJuliaFractal( m_pPart );
+ error = !parseJuliaFractal( ( PMJuliaFractal* ) child );
+ break;
+ case PLANE_TOK:
+ child = new PMPlane( m_pPart );
+ error = !parsePlane( ( PMPlane* ) child );
+ break;
+ case QUADRIC_TOK:
+ case CUBIC_TOK:
+ case QUARTIC_TOK:
+ case POLY_TOK:
+ child = new PMPolynom( m_pPart );
+ error = !parsePolynom( ( PMPolynom* ) child );
+ break;
+ case BICUBIC_PATCH_TOK:
+ child = new PMBicubicPatch( m_pPart );
+ error = !parseBicubicPatch( ( PMBicubicPatch* ) child );
+ break;
+ case DISC_TOK:
+ child = new PMDisc( m_pPart );
+ error = !parseDisc( ( PMDisc* ) child );
+ break;
+ case TRIANGLE_TOK:
+ case SMOOTH_TRIANGLE_TOK:
+ child = new PMTriangle( m_pPart );
+ error = !parseTriangle( ( PMTriangle* ) child );
+ break;
+ case LATHE_TOK:
+ child = new PMLathe( m_pPart );
+ error = !parseLathe( ( PMLathe* ) child );
+ break;
+ case PRISM_TOK:
+ child = new PMPrism( m_pPart );
+ error = !parsePrism( ( PMPrism* ) child );
+ break;
+ case SOR_TOK:
+ child = new PMSurfaceOfRevolution( m_pPart );
+ error = !parseSor( ( PMSurfaceOfRevolution* ) child );
+ break;
+ case SUPERELLIPSOID_TOK:
+ child = new PMSuperquadricEllipsoid( m_pPart );
+ error = !parseSqe( ( PMSuperquadricEllipsoid* ) child );
+ break;
+ case CAMERA_TOK:
+ child = new PMCamera( m_pPart );
+ error = !parseCamera( ( PMCamera* ) child );
+ break;
+ case LIGHT_SOURCE_TOK:
+ child = new PMLight( m_pPart );
+ error = !parseLight( ( PMLight* ) child );
+ break;
+ case LOOKS_LIKE_TOK:
+ child = new PMLooksLike( m_pPart );
+ error = !parseLooksLike( ( PMLooksLike* ) child );
+ break;
+ case PROJECTED_THROUGH_TOK:
+ child = new PMProjectedThrough( m_pPart );
+ error = !parseProjectedThrough( ( PMProjectedThrough* ) child );
+ break;
+ case TEXTURE_TOK:
+ child = new PMTexture( m_pPart );
+ error = !parseTexture( ( PMTexture* ) child );
+ break;
+ case AGATE_TOK:
+ case AVERAGE_TOK:
+ case BOXED_TOK:
+ case BOZO_TOK:
+ case BUMPS_TOK:
+ case CELLS_TOK:
+ case CRACKLE_TOK:
+ case CYLINDRICAL_TOK:
+ case DENTS_TOK:
+ case DENSITY_FILE_TOK:
+ case GRADIENT_TOK:
+ case GRANITE_TOK:
+ case JULIA_TOK:
+ case LEOPARD_TOK:
+ case MAGNET_TOK:
+ case MANDEL_TOK:
+ case MARBLE_TOK:
+ case ONION_TOK:
+ case PLANAR_TOK:
+ case QUILTED_TOK:
+ case RADIAL_TOK:
+ case RIPPLES_TOK:
+ case SLOPE_TOK:
+ case SPHERICAL_TOK:
+ case SPIRAL1_TOK:
+ case SPIRAL2_TOK:
+ case SPOTTED_TOK:
+ case WOOD_TOK:
+ case WAVES_TOK:
+ case WRINKLES_TOK:
+ child = new PMPattern( m_pPart );
+ {
+ bool normal = true;
+ if( parent && ( parent->type( ) != "Normal" ) )
+ normal = false;
+ error = !parsePattern( ( PMPattern* ) child, normal );
+ }
+ break;
+ case TURBULENCE_TOK:
+ // Search for a PMPattern in the object's children
+ child = parent->firstChild( );
+ while( child && !child->isA( "Pattern" ) )
+ child = child->nextSibling( );
+ if( child )
+ {
+ error = !parsePattern( ( PMPattern* ) child );
+ child = 0;
+ noChild = true;
+ }
+ else
+ {
+ printError( i18n( "Found turbulence without a pattern." ) );
+ error = true;
+ }
+ break;
+ case FREQUENCY_TOK:
+ case PHASE_TOK:
+ case RAMP_WAVE_TOK:
+ case TRIANGLE_WAVE_TOK:
+ case SINE_WAVE_TOK:
+ case SCALLOP_WAVE_TOK:
+ case CUBIC_WAVE_TOK:
+ case POLY_WAVE_TOK:
+ // Search for a PMBlendMapModifiers in the object's children
+ child = parent->firstChild( );
+ while( child && !child->isA( "BlendMapModifiers" ) )
+ child = child->nextSibling( );
+ if( child )
+ {
+ error = !parseBlendMapModifiers( ( PMBlendMapModifiers* ) child );
+ child = 0;
+ noChild = 0;
+ }
+ else
+ {
+ child = new PMBlendMapModifiers( m_pPart );
+ error = !parseBlendMapModifiers( ( PMBlendMapModifiers* ) child );
+ }
+ break;
+ case WARP_TOK:
+ child = new PMWarp( m_pPart );
+ error = !parseWarp( ( PMWarp* ) child );
+ break;
+ case PIGMENT_TOK:
+ child = new PMPigment( m_pPart );
+ error = !parsePigment( ( PMPigment* ) child );
+ break;
+ case NORMAL_TOK:
+ child = new PMNormal( m_pPart );
+ error = !parseNormal( ( PMNormal* ) child );
+ break;
+ case NORMAL_MAP_TOK:
+ child = new PMNormalMap( m_pPart );
+ error = !parseNormalMap( ( PMNormalMap* ) child );
+ break;
+ case BUMP_MAP_TOK:
+ child = new PMBumpMap( m_pPart );
+ error = !parseBumpMap( ( PMBumpMap* ) child );
+ break;
+ case SLOPE_MAP_TOK:
+ child = new PMSlopeMap( m_pPart );
+ error = !parseSlopeMap( ( PMSlopeMap* ) child );
+ break;
+ case DENSITY_MAP_TOK:
+ child = new PMDensityMap( m_pPart );
+ error = !parseDensityMap( ( PMDensityMap* ) child );
+ break;
+ case TEXTURE_MAP_TOK:
+ child = new PMTextureMap( m_pPart );
+ error = !parseTextureMap( ( PMTextureMap* ) child );
+ break;
+ case MATERIAL_MAP_TOK:
+ child = new PMMaterialMap( m_pPart );
+ error = !parseMaterialMap( ( PMMaterialMap* ) child );
+ break;
+ case PIGMENT_MAP_TOK:
+ child = new PMPigmentMap( m_pPart );
+ error = !parsePigmentMap( ( PMPigmentMap* ) child );
+ break;
+ case COLOR_MAP_TOK:
+ case COLOUR_MAP_TOK:
+ child = new PMColorMap( m_pPart );
+ error = !parseColorMap( ( PMColorMap* ) child );
+ break;
+ case CHECKER_TOK:
+ case HEXAGON_TOK:
+ case BRICK_TOK:
+ {
+ bool normal = false;
+ double depth = 0.0;
+ int expect = 0;
+ PMListPattern::PMListType type = PMListPattern::ListPatternChecker;
+
+ if( parent && parent->type( ) == "Normal" )
+ normal = true;
+ else if( m_pTopParent && m_pTopParent->type( ) == "Normal" )
+ normal = true;
+
+ switch( m_token )
+ {
+ case CHECKER_TOK:
+ type = PMListPattern::ListPatternChecker;
+ expect = 2;
+ break;
+ case HEXAGON_TOK:
+ type = PMListPattern::ListPatternHexagon;
+ expect = 3;
+ break;
+ case BRICK_TOK:
+ type = PMListPattern::ListPatternBrick;
+ expect = 2;
+ break;
+ }
+ nextToken( );
+
+ if( normal )
+ {
+ child = new PMNormalList( m_pPart );
+ if( parseFloat( depth, true ) )
+ ( ( PMNormalList* ) child )->setDepth( depth );
+
+ if( m_token == NORMAL_TOK )
+ error = !parseNormalList( ( PMNormalList* ) child, expect );
+ }
+ else
+ {
+ switch( m_token )
+ {
+ case COLOR_TOK:
+ case COLOUR_TOK:
+ case RGB_TOK:
+ case RGBT_TOK:
+ case RGBF_TOK:
+ case RGBFT_TOK:
+ case RED_TOK:
+ case GREEN_TOK:
+ case BLUE_TOK:
+ case TRANSMIT_TOK:
+ case FILTER_TOK:
+ case ID_TOK:
+ child = new PMColorList( m_pPart );
+ error = !parseColorList( ( PMColorList* ) child, expect );
+ break;
+ case PIGMENT_TOK:
+ child = new PMPigmentList( m_pPart );
+ error = !parsePigmentList( ( PMPigmentList* ) child, expect );
+ break;
+ case TEXTURE_TOK:
+ child = new PMTextureList( m_pPart );
+ error = !parseTextureList( ( PMTextureList* ) child, expect );
+ break;
+ case NORMAL_TOK:
+ child = new PMNormalList( m_pPart );
+ error = !parseNormalList( ( PMNormalList* ) child, expect );
+ break;
+ case DENSITY_TOK:
+ child = new PMDensityList( m_pPart );
+ error = !parseDensityList( ( PMDensityList* ) child, expect );
+ break;
+ default:
+ printError( i18n( "Invalid list member." ) );
+ error = true;
+ }
+ }
+
+ if( child )
+ {
+ ( ( PMListPattern* ) child )->setListType( type );
+
+ int oldConsumed;
+ double num = 0;
+ PMVector vector;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case MORTAR_TOK:
+ nextToken( );
+ if( !parseFloat( num ) )
+ return false;
+ ( ( PMListPattern* ) child )->setMortar( num );
+ break;
+ case BRICK_SIZE_TOK:
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ ( ( PMListPattern* ) child )->setBrickSize( vector );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+ }
+ break;
+ }
+ case IMAGE_MAP_TOK:
+ child = new PMImageMap( m_pPart );
+ error = !parseImageMap( ( PMImageMap* ) child );
+ break;
+ case FINISH_TOK:
+ child = new PMFinish( m_pPart );
+ error = !parseFinish( ( PMFinish* ) child );
+ break;
+ case INTERIOR_TOK:
+ child = new PMInterior( m_pPart );
+ error = !parseInterior( ( PMInterior* ) child );
+ break;
+ case MEDIA_TOK:
+ child = new PMMedia( m_pPart );
+ error = !parseMedia( ( PMMedia* ) child );
+ break;
+ case DENSITY_TOK:
+ child = new PMDensity( m_pPart );
+ error = !parseDensity( ( PMDensity* ) child );
+ break;
+ case MATERIAL_TOK:
+ child = new PMMaterial( m_pPart );
+ error = !parseMaterial( ( PMMaterial* ) child );
+ break;
+ case SKY_SPHERE_TOK:
+ child = new PMSkySphere( m_pPart );
+ error = !parseSkySphere( ( PMSkySphere* ) child );
+ break;
+ case RAINBOW_TOK:
+ child = new PMRainbow( m_pPart );
+ error = !parseRainbow( ( PMRainbow* ) child );
+ break;
+ case FOG_TOK:
+ child = new PMFog( m_pPart );
+ error = !parseFog( ( PMFog* ) child );
+ break;
+ case GLOBAL_SETTINGS_TOK:
+ child = new PMGlobalSettings( m_pPart );
+ error = !parseGlobalSettings( ( PMGlobalSettings* ) child );
+ break;
+ case SCALE_TOK:
+ child = new PMScale( m_pPart );
+ error = !parseScale( ( PMScale* ) child );
+ break;
+ case ROTATE_TOK:
+ child = new PMRotate( m_pPart );
+ error = !parseRotate( ( PMRotate* ) child );
+ break;
+ case TRANSLATE_TOK:
+ child = new PMTranslate( m_pPart );
+ error = !parseTranslate( ( PMTranslate* ) child );
+ break;
+ case MATRIX_TOK:
+ child = new PMPovrayMatrix( m_pPart );
+ error = !parseMatrix( ( PMPovrayMatrix* ) child );
+ break;
+ case BOUNDED_BY_TOK:
+ if( parent && ( parent->type( ) == "ClippedBy" ) )
+ finished = true;
+ else
+ {
+ child = new PMBoundedBy( m_pPart );
+ error = !parseBoundedBy( ( PMBoundedBy* ) child );
+ }
+ break;
+ case CLIPPED_BY_TOK:
+ if( parent && ( parent->type( ) == "BoundedBy" ) )
+ finished = true;
+ else
+ {
+ child = new PMClippedBy( m_pPart );
+ error = !parseClippedBy( ( PMClippedBy* ) child );
+ }
+ break;
+ case ISOSURFACE_TOK:
+ child = new PMIsoSurface( m_pPart );
+ error = !parseIsoSurface( ( PMIsoSurface* ) child );
+ break;
+ case RADIOSITY_TOK:
+ child = new PMRadiosity( m_pPart );
+ error = !parseRadiosity( ( PMRadiosity* ) child );
+ break;
+ case PHOTONS_TOK:
+ if ( parent && ( parent->type( ) == "GlobalSettings" ) )
+ {
+ child = new PMGlobalPhotons( m_pPart );
+ error = !parseGlobalPhotons( ( PMGlobalPhotons* ) child );
+ }
+ else
+ {
+ child = new PMPhotons( m_pPart );
+ error =!parsePhotons( ( PMPhotons* ) child );
+ }
+ break;
+ case LIGHT_GROUP_TOK:
+ child = new PMLightGroup( m_pPart );
+ error = !parseLightGroup( ( PMLightGroup* ) child );
+ break;
+ case INTERIOR_TEXTURE_TOK:
+ child = new PMInteriorTexture( m_pPart );
+ error = !parseInteriorTexture( ( PMInteriorTexture* ) child );
+ break;
+ case SPHERE_SWEEP_TOK:
+ child = new PMSphereSweep( m_pPart );
+ error = !parseSphereSweep( ( PMSphereSweep* ) child );
+ break;
+ case MESH_TOK:
+ child = new PMMesh( m_pPart );
+ error = !parseMesh( ( PMMesh* ) child );
+ break;
+ case DECLARE_TOK:
+ nextToken( );
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ nextToken( );
+
+ if( !parseToken( '=' ) )
+ error = true;
+ else
+ {
+ PMValue v;
+ switch( m_token )
+ {
+ case OBJECT_TOK:
+ // finite solid
+ case BLOB_TOK:
+ case BOX_TOK:
+ case CONE_TOK:
+ case CYLINDER_TOK:
+ case HEIGHT_FIELD_TOK:
+ case JULIA_FRACTAL_TOK:
+ case LATHE_TOK:
+ case PRISM_TOK:
+ case SPHERE_TOK:
+ case SUPERELLIPSOID_TOK:
+ case SOR_TOK:
+ case TEXT_TOK:
+ case TORUS_TOK:
+ case ISOSURFACE_TOK:
+ case SPHERE_SWEEP_TOK:
+ // finite patch
+ case BICUBIC_PATCH_TOK:
+ case DISC_TOK:
+ case MESH_TOK:
+ case POLYGON_TOK:
+ case TRIANGLE_TOK:
+ case SMOOTH_TRIANGLE_TOK:
+ // infinite solid
+ case PLANE_TOK:
+ case QUADRIC_TOK:
+ case CUBIC_TOK:
+ case QUARTIC_TOK:
+ case POLY_TOK:
+ // csg
+ case UNION_TOK:
+ case INTERSECTION_TOK:
+ case DIFFERENCE_TOK:
+ case MERGE_TOK:
+ // textures
+ case TEXTURE_TOK:
+ case INTERIOR_TEXTURE_TOK:
+ case PIGMENT_TOK:
+ case NORMAL_TOK:
+ case FINISH_TOK:
+ case TEXTURE_MAP_TOK:
+ case PIGMENT_MAP_TOK:
+ case COLOR_MAP_TOK:
+ case COLOUR_MAP_TOK:
+ case NORMAL_MAP_TOK:
+ case SLOPE_MAP_TOK:
+ case DENSITY_MAP_TOK:
+ case INTERIOR_TOK:
+ case MEDIA_TOK:
+ case DENSITY_TOK:
+ case MATERIAL_TOK:
+ case SKY_SPHERE_TOK:
+ case RAINBOW_TOK:
+ case FOG_TOK:
+ // misc
+ case LIGHT_SOURCE_TOK:
+ case LIGHT_GROUP_TOK:
+ child = new PMDeclare( m_pPart );
+ error = !parseDeclare( ( PMDeclare* ) child );
+ break;
+ default:
+ // constant, vector or color declare?
+ if( parseNumericExpression( v ) )
+ {
+ checkID( id, v );
+ noChild = true;
+ }
+ else
+ error = true;
+ break;
+ }
+ }
+
+ if( child )
+ if( child->isA( "Declare" ) )
+ ( ( PMDeclare* ) child )->setID( id );
+ if( m_token == ';' )
+ nextToken( );
+ }
+ else
+ printExpected( i18n( "identifier" ), m_pScanner->sValue( ) );
+ break;
+ case OBJECT_TOK:
+ error = !parseObject( parent );
+ noChild = true;
+ break;
+ case RAW_POVRAY_TOK:
+ child = new PMRaw( m_pPart, m_pScanner->sValue( ) );
+ error = false;
+ nextToken( );
+ break;
+ default:
+ finished = true;
+ break;
+ }
+ }
+ if( !finished && !child && !noChild )
+ error = true;
+ if( child )
+ {
+ if( !insertChild( child, parent ) )
+ {
+ delete child;
+ child = 0;
+ }
+ else if( child->isA( "Declare" ) )
+ checkID( ( PMDeclare* ) child );
+ numParsed ++;
+ if( ( max > 0 ) && ( numParsed >= max ) )
+ finished = true;
+ }
+ }
+ while( !finished && !error );
+
+ return finished;
+}
+
+bool PMPovrayParser::parseToken( int t, const QString& tokenName )
+{
+ if( t == ',' )
+ {
+ // do not require commas any more.
+ if( m_token == ',' )
+ nextToken( );
+ return true;
+ }
+ else if( m_token == t )
+ {
+ nextToken( );
+ return true;
+ }
+
+ if( tokenName.isNull() )
+ printExpected( ( char ) t, m_pScanner->sValue( ) );
+ else
+ printExpected( tokenName, m_pScanner->sValue( ) );
+ return false;
+}
+
+bool PMPovrayParser::parseNumericItem( PMValue& v, bool checkForBool /*=false*/ )
+{
+ bool finishColor = false;
+ PMVector cv( 0 );
+ PMVector vec( 0 );
+ PMValue hv;
+ PMSymbol* s;
+ int i;
+
+ switch( m_token )
+ {
+ case X_TOK:
+ v.setVector( PMVector( 1.0, 0.0, 0.0 ) );
+ nextToken( );
+ break;
+ case Y_TOK:
+ v.setVector( PMVector( 0.0, 1.0, 0.0 ) );
+ nextToken( );
+ break;
+ case Z_TOK:
+ v.setVector( PMVector( 0.0, 0.0, 1.0 ) );
+ nextToken( );
+ break;
+ case T_TOK:
+ v.setVector( PMVector( 0.0, 0.0, 0.0, 1.0 ) );
+ nextToken( );
+ break;
+ case U_TOK:
+ v.setVector( PMVector( 1.0, 0.0 ) );
+ nextToken( );
+ break;
+ case V_TOK:
+ v.setVector( PMVector( 0.0, 1.0 ) );
+ nextToken( );
+ break;
+ case PI_TOK:
+ v.setFloat( 3.1415926535897932384626 );
+ nextToken( );
+ break;
+ case CLOCK_TOK:
+ printMessage( PMMClockDefault );
+ v.setFloat( 0.0 );
+ break;
+ case CLOCK_DELTA_TOK:
+ printMessage( PMMClockDeltaDefault );
+ v.setFloat( 1.0 );
+ break;
+ case FLOAT_TOK:
+ v.setFloat( m_pScanner->fValue( ) );
+ nextToken( );
+ break;
+ case INTEGER_TOK:
+ v.setFloat( ( double ) m_pScanner->iValue( ) );
+ nextToken( );
+ break;
+ case ON_TOK:
+ case TRUE_TOK:
+ case YES_TOK:
+ v.setFloat( 1.0 );
+ nextToken( );
+ break;
+ case OFF_TOK:
+ case FALSE_TOK:
+ case NO_TOK:
+ v.setFloat( 0.0 );
+ nextToken( );
+ break;
+ case '(':
+ nextToken( );
+ if( !parseNumericExpression( v ) )
+ return false;
+ if( !parseToken( ')' ) )
+ return false;
+ break;
+ case '-':
+ nextToken( );
+ if( !parseNumericItem( v ) )
+ return false;
+ if( v.type( ) == PMVFloat )
+ v.setFloat( -v.floatValue( ) );
+ else
+ v.setVector( -v.vector( ) );
+ break;
+ case '+':
+ nextToken( );
+ if( !parseNumericItem( v ) )
+ return false;
+ break;
+ case '<':
+ if( !parseVectorLiteral( vec ) )
+ return false;
+ v.setVector( vec );
+ break;
+ case COLOR_TOK:
+ case COLOUR_TOK:
+ nextToken( );
+ case RGB_TOK:
+ case RGBT_TOK:
+ case RGBF_TOK:
+ case RGBFT_TOK:
+ case RED_TOK:
+ case GREEN_TOK:
+ case BLUE_TOK:
+ case TRANSMIT_TOK:
+ case FILTER_TOK:
+ cv.resize( 5 );
+ cv = 0.0;
+ finishColor = true;
+ break;
+ case ID_TOK:
+ s = getSymbol( m_pScanner->sValue( ) );
+ if( s )
+ {
+ nextToken( );
+ if( s->type( ) == PMSymbol::Value )
+ v = s->value( );
+ else
+ {
+ printError( i18n( "Float, color or vector identifier expected." ) );
+ return false;
+ }
+ }
+ else
+ {
+ printError( i18n( "Undefined identifier \"%1\"." )
+ .arg( m_pScanner->sValue( ) ) );
+ nextToken( );
+ }
+ break;
+ default:
+ if( !checkForBool )
+ printUnexpected( m_pScanner->sValue( ) );
+ return false;
+ break;
+ }
+
+ if( !finishColor )
+ {
+ if( m_token == '.' )
+ {
+ int index = -1;
+ nextToken( );
+
+ switch( m_token )
+ {
+ case X_TOK:
+ case RED_TOK:
+ case U_TOK:
+ index = 0;
+ break;
+ case Y_TOK:
+ case GREEN_TOK:
+ case V_TOK:
+ index = 1;
+ break;
+ case Z_TOK:
+ case BLUE_TOK:
+ index = 2;
+ break;
+ case T_TOK:
+ case FILTER_TOK:
+ index = 3;
+ break;
+ case TRANSMIT_TOK:
+ index = 4;
+ break;
+ default:
+ break;
+ }
+ if( index >= 0 )
+ {
+ nextToken( );
+ if( v.type( ) == PMVFloat )
+ {
+ if( index != 0 )
+ index = -1;
+ }
+ else
+ {
+ PMVector vec;
+ if( v.type( ) == PMVVector )
+ vec = v.vector( );
+ else
+ vec = v.color( );
+
+ if( ( ( unsigned ) index ) < vec.size( ) )
+ v.setFloat( vec[index] );
+ else
+ index = -1;
+ }
+ }
+ if( index == -1 )
+ {
+ printError( i18n( "Bad operands for period operator." ) );
+ return false;
+ }
+ }
+ }
+
+ while( finishColor )
+ {
+ switch( m_token )
+ {
+ case RGB_TOK:
+ nextToken( );
+ if( !parseNumericExpression( hv ) )
+ return false;
+ switch( hv.type( ) )
+ {
+ case PMVFloat:
+ cv[0] = hv.floatValue( );
+ cv[1] = hv.floatValue( );
+ cv[2] = hv.floatValue( );
+ break;
+ case PMVVector:
+ vec = hv.vector( );
+ vec.resize( 3 );
+ cv[0] = vec[0];
+ cv[1] = vec[1];
+ cv[2] = vec[2];
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ break;
+ }
+ break;
+ case RGBT_TOK:
+ nextToken( );
+ if( !parseNumericExpression( hv ) )
+ return false;
+ switch( hv.type( ) )
+ {
+ case PMVFloat:
+ cv[0] = hv.floatValue( );
+ cv[1] = hv.floatValue( );
+ cv[2] = hv.floatValue( );
+ cv[4] = hv.floatValue( );
+ break;
+ case PMVVector:
+ vec = hv.vector( );
+ vec.resize( 4 );
+ cv[0] = vec[0];
+ cv[1] = vec[1];
+ cv[2] = vec[2];
+ cv[4] = vec[3];
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ break;
+ }
+ break;
+ case RGBF_TOK:
+ nextToken( );
+ if( !parseNumericExpression( hv ) )
+ return false;
+ switch( hv.type( ) )
+ {
+ case PMVFloat:
+ cv[0] = hv.floatValue( );
+ cv[1] = hv.floatValue( );
+ cv[2] = hv.floatValue( );
+ cv[3] = hv.floatValue( );
+ break;
+ case PMVVector:
+ vec = hv.vector( );
+ vec.resize( 4 );
+ cv[0] = vec[0];
+ cv[1] = vec[1];
+ cv[2] = vec[2];
+ cv[3] = vec[3];
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ break;
+ }
+ break;
+ case RGBFT_TOK:
+ nextToken( );
+ if( !parseNumericExpression( hv ) )
+ return false;
+ switch( hv.type( ) )
+ {
+ case PMVFloat:
+ cv = hv.floatValue( );
+ break;
+ case PMVVector:
+ vec = hv.vector( );
+ vec.resize( 5 );
+ cv = vec;
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ break;
+ }
+ break;
+ case RED_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[0] = hv.floatValue( );
+ break;
+ case GREEN_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[1] = hv.floatValue( );
+ break;
+ case BLUE_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[2] = hv.floatValue( );
+ break;
+ case FILTER_TOK:
+ case ALPHA_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[3] = hv.floatValue( );
+ break;
+ case TRANSMIT_TOK:
+ nextToken( );
+ parseNumericExpression( hv );
+ if( hv.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ break;
+ }
+ cv[4] = hv.floatValue( );
+ break;
+ case ID_TOK:
+ if( parseNumericItem( hv ) )
+ {
+ if( hv.type( ) == PMVFloat )
+ {
+ for( i = 0; i < 5; i++ )
+ cv[i] = hv.floatValue( );
+ }
+ else if( hv.type( ) == PMVVector )
+ {
+ cv = hv.vector( );
+ cv.resize( 5 );
+ }
+ else
+ cv = hv.color( );
+ }
+ break;
+ default:
+ finishColor = false;
+ v.setColor( cv );
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool PMPovrayParser::parseVectorLiteral( PMVector& p )
+{
+ PMValue v;
+
+ if( !parseToken( '<' ) )
+ return false;
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ if( v.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ return false;
+ }
+
+ p.resize( 1 );
+ p[0] = v.floatValue( );
+
+ while( m_token != '>' )
+ {
+ // many old scenes do not use a comma between values
+ if( m_token == ',' )
+ nextToken( );
+ // parseToken( ',' );
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ if( v.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ return false;
+ }
+
+ p.resize( p.size( ) + 1 );
+ p[p.size( ) - 1] = v.floatValue( );
+ }
+
+ /** old code
+ while( m_token == ',' )
+ {
+ nextToken( );
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ if( v.type( ) != PMVFloat )
+ {
+ printError( i18n( "Float expression expected" ) );
+ return false;
+ }
+
+ p.resize( p.size( ) + 1 );
+ p[p.size( ) - 1] = v.floatValue( );
+ }
+ */
+
+ if( !parseToken( '>' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseNumericExpression( PMValue& v, bool checkForBool /*=false*/ )
+{
+ bool end = false;
+ PMValue v2;
+ PMVector hv( 0 );
+
+ if( !parseNumericItem( v, checkForBool ) )
+ return false;
+
+ do
+ {
+ switch( m_token )
+ {
+ case '*':
+ nextToken( );
+ if( !parseNumericItem( v2 ) )
+ break;
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setFloat( v.floatValue( ) * v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v2.vector( ) * v.floatValue( ) );
+ break;
+ case PMVColor:
+ v.setColor( v2.color( ) * v.floatValue( ) );
+ break;
+ }
+ break;
+ case PMVVector:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setVector( v.vector( ) * v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v.vector( ) * v2.vector( ) );
+ break;
+ case PMVColor:
+ if( v.vector( ).size( ) == 5 )
+ v.setColor( v.vector( ) * v2.color( ) );
+ else
+ printError( i18n( "You can't multiply a vector with a color" ) );
+ break;
+ }
+ break;
+ case PMVColor:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setColor( v.color( ) * v2.floatValue( ) );
+ break;
+ case PMVVector:
+ if( v2.vector( ).size( ) == 5 )
+ v.setColor( v2.vector( ) * v.color( ) );
+ else
+ printError( i18n( "You can't multiply a vector with a color" ) );
+ break;
+ case PMVColor:
+ v.setColor( v.color( ) * v2.color( ) );
+ break;
+ }
+ break;
+ }
+ break;
+ case '/':
+ nextToken( );
+ if( !parseNumericItem( v2 ) )
+ break;
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setFloat( v.floatValue( ) / v2.floatValue( ) );
+ break;
+ case PMVVector:
+ hv.resize( v2.vector( ).size( ) );
+ hv = v.floatValue( );
+ v.setVector( hv / v2.vector( ) );
+ break;
+ case PMVColor:
+ hv.resize( 5 );
+ hv = v.floatValue( );
+ v.setColor( hv / v.floatValue( ) );
+ break;
+ }
+ break;
+ case PMVVector:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setVector( v.vector( ) / v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v.vector( ) / v2.vector( ) );
+ break;
+ case PMVColor:
+ if( v.vector( ).size( ) == 5 )
+ v.setColor( v.vector( ) / v2.color( ) );
+ else
+ printError( i18n( "You can't divide a vector by a color" ) );
+ break;
+ }
+ break;
+ case PMVColor:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setColor( v.color( ) / v2.floatValue( ) );
+ break;
+ case PMVVector:
+ if( v2.vector( ).size( ) == 5 )
+ v.setColor( v2.vector( ) / v.color( ) );
+ else
+ printError( i18n( "You can't divide a color by a vector" ) );
+ break;
+ case PMVColor:
+ v.setColor( v.color( ) / v2.color( ) );
+ break;
+ }
+ break;
+ }
+ break;
+ case '+':
+ nextToken( );
+ if( !parseNumericExpression( v2 ) )
+ break;
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setFloat( v.floatValue( ) + v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v2.vector( ) + v.floatValue( ) );
+ break;
+ case PMVColor:
+ v.setColor( v2.color( ) + v.floatValue( ) );
+ break;
+ }
+ break;
+ case PMVVector:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setVector( v.vector( ) + v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v.vector( ) + v2.vector( ) );
+ break;
+ case PMVColor:
+ if( v.vector( ).size( ) == 5 )
+ v.setColor( v.vector( ) + v2.color( ) );
+ else
+ printError( i18n( "You can't add a vector and a color" ) );
+ break;
+ }
+ break;
+ case PMVColor:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setColor( v.color( ) + v2.floatValue( ) );
+ break;
+ case PMVVector:
+ if( v2.vector( ).size( ) == 5 )
+ v.setColor( v2.vector( ) + v.color( ) );
+ else
+ printError( i18n( "You can't add a vector with a color" ) );
+ break;
+ case PMVColor:
+ v.setColor( v.color( ) + v2.color( ) );
+ break;
+ }
+ break;
+ }
+ break;
+ case '-':
+ nextToken( );
+ if( !parseNumericExpression( v2 ) )
+ break;
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setFloat( v.floatValue( ) - v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v2.vector( ) - v.floatValue( ) );
+ break;
+ case PMVColor:
+ v.setColor( v2.color( ) - v.floatValue( ) );
+ break;
+ }
+ break;
+ case PMVVector:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setVector( v.vector( ) - v2.floatValue( ) );
+ break;
+ case PMVVector:
+ v.setVector( v.vector( ) - v2.vector( ) );
+ break;
+ case PMVColor:
+ if( v.vector( ).size( ) == 5 )
+ v.setColor( v.vector( ) - v2.color( ) );
+ else
+ printError( i18n( "You can't subtract a vector and a color" ) );
+ break;
+ }
+ break;
+ case PMVColor:
+ switch( v2.type( ) )
+ {
+ case PMVFloat:
+ v.setColor( v.color( ) - v2.floatValue( ) );
+ break;
+ case PMVVector:
+ if( v2.vector( ).size( ) == 5 )
+ v.setColor( v2.vector( ) - v.color( ) );
+ else
+ printError( i18n( "You can't subtract a vector and a color" ) );
+ break;
+ case PMVColor:
+ v.setColor( v.color( ) - v2.color( ) );
+ break;
+ }
+ break;
+ }
+ break;
+ default:
+ end = true;
+ break;
+ }
+ }
+ while( !end );
+
+ return true;
+}
+
+bool PMPovrayParser::parseVector( PMVector& vector, unsigned int size )
+{
+ PMValue v;
+ unsigned int i;
+
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ vector.resize( size );
+ for( i = 0; i < size; i++ )
+ vector[i] = v.floatValue( );
+ break;
+ case PMVVector:
+ vector = v.vector( );
+ vector.resize( size );
+ break;
+ default:
+ printError( i18n( "Float or vector expression expected" ) );
+ return false;
+ }
+ return true;
+}
+
+bool PMPovrayParser::parseFloat( double& d, bool suppressError )
+{
+ PMValue v;
+
+ if( !parseNumericExpression( v, suppressError ) )
+ return false;
+
+ switch( v.type( ) )
+ {
+ case PMVFloat:
+ d = v.floatValue( );
+ break;
+ case PMVVector:
+ d = ( v.vector( ) )[0];
+ break;
+ default:
+ printError( i18n( "Float expression expected" ) );
+ return false;
+ }
+ return true;
+}
+
+bool PMPovrayParser::parseInt( int& i )
+{
+ double d;
+
+ if( !parseFloat( d ) )
+ return false;
+
+ i = ( int ) ( d + 0.5 );
+ return true;
+}
+
+bool PMPovrayParser::parseColor( PMColor& c )
+{
+ PMValue v;
+
+ if( !parseNumericExpression( v ) )
+ return false;
+
+ if( v.type( ) == PMVColor )
+ c = PMColor( v.color( ) );
+ else if( v.type( ) == PMVVector )
+ {
+ if( v.vector( ).size( ) == 5 )
+ c = PMColor( v.vector( ) );
+ else
+ {
+ printError( i18n( "Color expression expected" ) );
+ return false;
+ }
+ }
+ else if( v.type( ) == PMVFloat )
+ {
+ double d = v.floatValue( );
+ c = PMColor( d, d, d, d, d );
+ }
+ else
+ {
+ printError( i18n( "Color expression expected" ) );
+ return false;
+ }
+
+ return true;
+}
+
+bool PMPovrayParser::parseObjectModifiers( PMGraphicalObject* o )
+{
+ bool finished = false;
+
+ PMSolidObject* so = 0;
+ if( o->isA( "SolidObject" ) )
+ so = ( PMSolidObject* ) o;
+
+ do
+ {
+ finished = true;
+ switch( m_token )
+ {
+ case NO_SHADOW_TOK:
+ o->setNoShadow( true );
+ nextToken( );
+ finished = false;
+ break;
+ case NO_IMAGE_TOK:
+ o->setNoImage( true );
+ nextToken( );
+ finished = false;
+ break;
+ case NO_REFLECTION_TOK:
+ o->setNoReflection( true );
+ nextToken( );
+ finished = false;
+ break;
+ case DOUBLE_ILLUMINATE_TOK:
+ o->setDoubleIlluminate( true );
+ nextToken( );
+ finished = false;
+ break;
+ default:
+ break;
+ }
+ if( so )
+ {
+ switch( m_token )
+ {
+ case HOLLOW_TOK:
+ so->setHollow( PMTrue );
+ nextToken( );
+ if( isTrue( ) )
+ nextToken( );
+ else if( isFalse( ) )
+ {
+ nextToken( );
+ so->setHollow( PMFalse );
+ }
+ finished = false;
+ break;
+ case INVERSE_TOK:
+ so->setInverse( true );
+ nextToken( );
+ finished = false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ while( !finished );
+ return true;
+}
+
+bool PMPovrayParser::parseCSG( PMCSG* pNewCSG )
+{
+ int oldConsumed;
+
+ switch( m_token )
+ {
+ case UNION_TOK:
+ pNewCSG->setCSGType( PMCSG::CSGUnion );
+ break;
+ case INTERSECTION_TOK:
+ pNewCSG->setCSGType( PMCSG::CSGIntersection );
+ break;
+ case DIFFERENCE_TOK:
+ pNewCSG->setCSGType( PMCSG::CSGDifference );
+ break;
+ case MERGE_TOK:
+ pNewCSG->setCSGType( PMCSG::CSGMerge );
+ break;
+ default:
+ printUnexpected( m_pScanner->sValue( ) );
+ return false;
+ break;
+ }
+ nextToken( );
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewCSG );
+ parseObjectModifiers( pNewCSG );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBox( PMBox* pNewBox )
+{
+ PMVector vector;
+
+ int oldConsumed;
+
+ if( !parseToken( BOX_TOK, "box" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBox->setCorner1( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBox->setCorner2( vector );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewBox );
+ parseObjectModifiers( pNewBox );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSphere( PMSphere* pNewSphere )
+{
+ PMVector vector;
+ double radius;
+
+ int oldConsumed;
+
+ if( !parseToken( SPHERE_TOK, "sphere" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewSphere->setCentre( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewSphere->setRadius( radius );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewSphere );
+ parseObjectModifiers( pNewSphere );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseCylinder( PMCylinder* pNewCyl )
+{
+ PMVector vector;
+ double radius;
+ int oldConsumed;
+
+ if( !parseToken( CYLINDER_TOK, "cylinder" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewCyl->setEnd1( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewCyl->setEnd2( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat(radius) )
+ return false;
+ pNewCyl->setRadius( radius );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewCyl );
+ parseObjectModifiers( pNewCyl );
+ switch( m_token )
+ {
+ case OPEN_TOK:
+ nextToken( );
+ pNewCyl->setOpen( true );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseCone( PMCone* pNewCone )
+{
+ PMVector vector;
+ double radius;
+ int oldConsumed;
+
+ if( !parseToken( CONE_TOK, "cone" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewCone->setEnd1( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( radius ) )
+ return false;
+ pNewCone->setRadius1( radius );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseVector( vector ) )
+ return false;
+ pNewCone->setEnd2( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( radius ) )
+ return false;
+ pNewCone->setRadius2( radius );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewCone );
+ parseObjectModifiers( pNewCone );
+ switch( m_token )
+ {
+ case OPEN_TOK:
+ nextToken( );
+ pNewCone->setOpen( true );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+
+}
+
+bool PMPovrayParser::parseTorus( PMTorus* pNewTorus )
+{
+ double radius;
+ int oldConsumed;
+
+ if( !parseToken( TORUS_TOK, "torus" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewTorus->setMajorRadius( radius );
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( radius ) )
+ return false;
+ pNewTorus->setMinorRadius( radius );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewTorus );
+ parseObjectModifiers( pNewTorus );
+ switch( m_token )
+ {
+ case STURM_TOK:
+ nextToken( );
+ pNewTorus->setSturm( true );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlob( PMBlob* pNewBlob )
+{
+ PMVector vector;
+ double threshold;
+ int oldConsumed;
+
+ if( !parseToken( BLOB_TOK, "blob" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ pNewBlob->setThreshold( 1.0 );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case STURM_TOK:
+ nextToken( );
+ pNewBlob->setSturm( true );
+ break;
+ case HIERARCHY_TOK:
+ pNewBlob->setHierarchy( true );
+ nextToken( );
+ if( isTrue( ) )
+ nextToken( );
+ else if( isFalse( ) )
+ {
+ nextToken( );
+ pNewBlob->setHierarchy( false );
+ }
+ break;
+ case THRESHOLD_TOK:
+ nextToken( );
+ if( parseFloat( threshold ) )
+ {
+ if( threshold <= 0 )
+ printError( i18n( "The threshold value has to be positive" ) );
+ else
+ pNewBlob->setThreshold( threshold );
+ }
+ break;
+ }
+
+ parseChildObjects( pNewBlob );
+ parseObjectModifiers( pNewBlob );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlobSphere( PMBlobSphere* pNewBlobSphere )
+{
+ PMVector vector;
+ double radius;
+ double strength;
+
+ int oldConsumed;
+
+ if( !parseToken( SPHERE_TOK, "sphere" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBlobSphere->setCentre( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewBlobSphere->setRadius( radius );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( m_token == STRENGTH_TOK )
+ nextToken( );
+
+ if( !parseFloat( strength ) )
+ return false;
+ pNewBlobSphere->setStrength( strength );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewBlobSphere );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlobComponent( PMBlobSphere* pNewBlobSphere )
+{
+ PMVector vector;
+ double radius;
+ double strength;
+
+ if( !parseToken( COMPONENT_TOK, "component" ) )
+ return false;
+
+ if( !parseFloat( strength ) )
+ return false;
+ pNewBlobSphere->setStrength( strength );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewBlobSphere->setRadius( radius );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBlobSphere->setCentre( vector );
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlobCylinder( PMBlobCylinder* pNewBlobCylinder )
+{
+ PMVector vector;
+ double radius;
+ double strength;
+ int oldConsumed;
+
+ if( !parseToken( CYLINDER_TOK, "cylinder" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBlobCylinder->setEnd1( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewBlobCylinder->setEnd2( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( !parseFloat( radius ) )
+ return false;
+ pNewBlobCylinder->setRadius( radius );
+
+ if( !parseToken( ',' ) )
+ return false;
+
+ if( m_token == STRENGTH_TOK )
+ nextToken( );
+
+ if( !parseFloat( strength ) )
+ return false;
+ pNewBlobCylinder->setStrength( strength );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewBlobCylinder );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseHeightField( PMHeightField* pNewHeightField )
+{
+ int oldConsumed;
+ double wl;
+
+ if( !parseToken( HEIGHT_FIELD_TOK, "height_field" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ switch( m_token )
+ {
+ case GIF_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFgif );
+ nextToken( );
+ break;
+ case TGA_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFtga );
+ nextToken( );
+ break;
+ case POT_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFpot );
+ nextToken( );
+ break;
+ case PNG_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFpng );
+ nextToken( );
+ break;
+ case PGM_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFpgm );
+ nextToken( );
+ break;
+ case PPM_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFppm );
+ nextToken( );
+ break;
+ case SYS_TOK:
+ pNewHeightField->setHeightFieldType( PMHeightField::HFsys );
+ nextToken( );
+ break;
+ default:
+ printExpected( i18n( "height field type" ), m_pScanner->sValue( ) );
+ return false;
+ }
+ if( m_token != STRING_TOK )
+ {
+ printExpected( i18n( "height field file" ), m_pScanner->sValue( ) );
+ return false;
+ }
+ else
+ {
+ pNewHeightField->setFileName( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case SMOOTH_TOK:
+ nextToken( );
+ pNewHeightField->setSmooth( true );
+ if( isTrue( ) )
+ nextToken( );
+ else if( isFalse( ) )
+ {
+ nextToken( );
+ pNewHeightField->setSmooth( false );
+ }
+ break;
+ case HIERARCHY_TOK:
+ pNewHeightField->setHierarchy( true );
+ nextToken( );
+ if( isTrue( ) )
+ nextToken( );
+ else if( isFalse( ) )
+ {
+ nextToken( );
+ pNewHeightField->setHierarchy( false );
+ }
+ break;
+ case WATER_LEVEL_TOK:
+ nextToken( );
+ if( parseFloat( wl ) )
+ {
+ if( ( wl < 0.0 ) || ( wl > 1.0 ) )
+ printError( i18n( "The water level has to be between 0 and 1" ) );
+ else
+ pNewHeightField->setWaterLevel( wl );
+ }
+ break;
+ }
+
+ parseChildObjects( pNewHeightField );
+ parseObjectModifiers( pNewHeightField );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseText( PMText* pNewText )
+{
+ int oldConsumed;
+ double thickness;
+ PMVector offset;
+
+ if( !parseToken( TEXT_TOK, "text" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseToken( TTF_TOK, "ttf" ) )
+ return false;
+
+ if( m_token != STRING_TOK )
+ {
+ printExpected( i18n( "font file name" ), m_pScanner->sValue( ) );
+ return false;
+ }
+ else
+ {
+ pNewText->setFont( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+ if( m_token != STRING_TOK )
+ {
+ printExpected( i18n( "string of text" ), m_pScanner->sValue( ) );
+ return false;
+ }
+ else
+ {
+ pNewText->setText( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ if( !parseFloat( thickness ) )
+ return false;
+ pNewText->setThickness( thickness );
+
+ parseToken( ',' );
+
+ if( parseVector( offset, 2 ) )
+ pNewText->setOffset( offset );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewText );
+ parseObjectModifiers( pNewText );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseJuliaFractal( PMJuliaFractal* pNewFractal )
+{
+ int oldConsumed;
+ double d;
+ int i;
+ PMVector v( 4 ), v2( 2 );
+
+ if( !parseToken( JULIA_FRACTAL_TOK, "julia_fractal" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( v, 4 ) )
+ return false;
+ pNewFractal->setJuliaParameter( v );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case QUATERNION_TOK:
+ pNewFractal->setAlgebraType( PMJuliaFractal::Quaternion );
+ nextToken( );
+ break;
+ case HYPERCOMPLEX_TOK:
+ pNewFractal->setAlgebraType( PMJuliaFractal::Hypercomplex );
+ nextToken( );
+ break;
+ case SQR_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTsqr );
+ nextToken( );
+ break;
+ case CUBE_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTcube );
+ nextToken( );
+ break;
+ case EXP_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTexp );
+ nextToken( );
+ break;
+ case RECIPROCAL_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTreciprocal );
+ nextToken( );
+ break;
+ case SIN_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTsin );
+ nextToken( );
+ break;
+ case ASIN_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTasin );
+ nextToken( );
+ break;
+ case SINH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTsinh );
+ nextToken( );
+ break;
+ case ASINH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTasinh );
+ nextToken( );
+ break;
+ case COS_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTcos );
+ nextToken( );
+ break;
+ case ACOS_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTacos );
+ nextToken( );
+ break;
+ case COSH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTcosh );
+ nextToken( );
+ break;
+ case ACOSH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTacosh );
+ nextToken( );
+ break;
+ case TAN_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTtan );
+ nextToken( );
+ break;
+ case ATAN_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTatan );
+ nextToken( );
+ break;
+ case TANH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTtanh );
+ nextToken( );
+ break;
+ case ATANH_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTatanh );
+ nextToken( );
+ break;
+ case LOG_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTlog );
+ nextToken( );
+ break;
+ case PWR_TOK:
+ pNewFractal->setFunctionType( PMJuliaFractal::FTpwr );
+ nextToken( );
+ if( !parseToken( '(' ) )
+ return false;
+ if( !parseFloat( v2[0] ) )
+ return false;
+ parseToken( ',' );
+ if( !parseFloat( v2[1] ) )
+ return false;
+ if( !parseToken( ')' ) )
+ return false;
+ pNewFractal->setExponent( v2 );
+ break;
+ case MAX_ITERATION_TOK:
+ nextToken( );
+ if( !parseInt( i ) )
+ return false;
+ if( i <= 0 )
+ {
+ printWarning( i18n( "Maximum iterations are less than 1, fixed" ) );
+ i = 1;
+ }
+ pNewFractal->setMaximumIterations( i );
+ break;
+ case PRECISION_TOK:
+ nextToken( );
+ if( !parseFloat( d ) )
+ return false;
+ if( d < 1.0 )
+ {
+ printWarning( i18n( "Precision is less than 1.0, fixed" ) );
+ d = 1.0;
+ }
+ pNewFractal->setPrecision( d );
+ break;
+ case SLICE_TOK:
+ nextToken( );
+ if( !parseVector( v, 4 ) )
+ return false;
+ pNewFractal->setSliceNormal( v );
+ parseToken( ',' );
+ if( !parseFloat( d ) )
+ return false;
+ pNewFractal->setSliceDistance( d );
+ break;
+ }
+
+ parseChildObjects( pNewFractal );
+ parseObjectModifiers( pNewFractal );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePlane( PMPlane* pNewPlane )
+{
+ double dist;
+ PMVector vector;
+ int oldConsumed;
+
+ if( !parseToken( PLANE_TOK, "plane" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewPlane->setNormal( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( dist ) )
+ return false;
+ pNewPlane->setDistance( dist );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewPlane );
+ parseObjectModifiers( pNewPlane );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+const int c_polynomSize[8] = { 0, 0, 10, 20, 35, 56, 84, 120 };
+
+bool PMPovrayParser::parsePolynom( PMPolynom* pNewPoly )
+{
+ PMVector vector;
+ double d;
+ PMVector c;
+ int oldConsumed;
+ int order = 2;
+ int type = m_token;
+
+ pNewPoly->setSturm( false );
+
+ if( ( m_token == QUADRIC_TOK ) || ( m_token == CUBIC_TOK ) ||
+ ( m_token == QUARTIC_TOK ) || ( m_token == POLY_TOK ) )
+ {
+ nextToken( );
+ if( !parseToken( '{' ) )
+ return false;
+ }
+ else
+ printExpected( "poly", m_pScanner->sValue( ) );
+
+ if( type == QUADRIC_TOK )
+ {
+ c = PMVector( 10 );
+ pNewPoly->setPolynomOrder( 2 );
+
+ // parse the quadric coefficients
+ if( !parseVectorLiteral( vector ) )
+ return false;
+ vector.resize( 3 );
+ c[0] = vector[0];
+ c[4] = vector[1];
+ c[7] = vector[2];
+ parseToken( ',' );
+
+ if( !parseVectorLiteral( vector ) )
+ return false;
+ vector.resize( 3 );
+ c[1] = vector[0];
+ c[2] = vector[1];
+ c[5] = vector[2];
+ parseToken( ',' );
+
+ if( !parseVectorLiteral( vector ) )
+ return false;
+ vector.resize( 3 );
+ c[3] = vector[0];
+ c[6] = vector[1];
+ c[8] = vector[2];
+ parseToken( ',' );
+
+ if( !parseFloat( d ) )
+ return false;
+ c[9] = d;
+
+ pNewPoly->setCoefficients( c );
+ }
+ else
+ {
+ if( type == CUBIC_TOK )
+ order = 3;
+ else if( type == QUARTIC_TOK )
+ order = 4;
+ else
+ {
+ if( !parseInt( order ) )
+ return false;
+ if( ( order < 2 ) || ( order > 7 ) )
+ {
+ printError( i18n( "The polynom order has to be between 2 and 7 inclusive" ) );
+ return false;
+ }
+ parseToken( ',' );
+ }
+
+ pNewPoly->setPolynomOrder( order );
+
+ if( !parseVectorLiteral( vector ) )
+ return false;
+
+ if( vector.size( ) != ( unsigned ) c_polynomSize[order] )
+ {
+ printError( i18n( "%1 coefficients are needed for a polynom with order %2" )
+ .arg( c_polynomSize[order] ).arg( order ) );
+ vector.resize( c_polynomSize[order] );
+ }
+ pNewPoly->setCoefficients( vector );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == STURM_TOK )
+ {
+ pNewPoly->setSturm( true );
+ nextToken( );
+ }
+
+ parseChildObjects( pNewPoly );
+ parseObjectModifiers( pNewPoly );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBicubicPatch( PMBicubicPatch* pNewPatch )
+{
+ PMVector vector;
+ bool stop = false;
+ int oldConsumed;
+ int type;
+ int steps;
+ double flatness;
+ int i;
+
+ if( !parseToken( BICUBIC_PATCH_TOK, "bicubic_patch" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ // parse patch items
+ do
+ {
+ switch( m_token )
+ {
+ case TYPE_TOK:
+ nextToken( );
+ if( parseInt( type ) )
+ {
+ if( ( type == 0 ) || ( type == 1 ) )
+ pNewPatch->setPatchType( type );
+ else
+ printError( i18n( "Patch type has to be 0 or 1" ) );
+ }
+ break;
+ case U_STEPS_TOK:
+ nextToken( );
+ if( parseInt( steps ) )
+ pNewPatch->setUSteps( steps );
+ break;
+ case V_STEPS_TOK:
+ nextToken( );
+ if( parseInt( steps ) )
+ pNewPatch->setVSteps( steps );
+ break;
+ case FLATNESS_TOK:
+ nextToken( );
+ if( parseFloat( flatness ) )
+ pNewPatch->setFlatness( flatness );
+ break;
+ case UV_VECTORS_TOK:
+ pNewPatch->enableUV( true );
+ nextToken( );
+ for ( i = 0; i < 4; ++i )
+ {
+ if( parseVector( vector ) )
+ pNewPatch->setUVVector( i, vector );
+ else
+ return false;
+ }
+ break;
+ case ',':
+ nextToken( );
+ stop = true;
+ break;
+ default:
+ stop = true;
+ break;
+ }
+ }
+ while( !stop );
+
+ // parse control points
+ stop = false;
+ for( i = 0; ( i < 16 ) && !stop; i++ )
+ {
+ if( parseVector( vector ) )
+ {
+ pNewPatch->setControlPoint( i, vector );
+ if( i < 15 )
+ if( !parseToken( ',' ) )
+ stop = true;
+ }
+ else
+ stop = true;
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewPatch );
+ parseObjectModifiers( pNewPatch );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseDisc( PMDisc* pNewDisc )
+{
+ double d;
+ PMVector vector;
+ int oldConsumed;
+
+ if( !parseToken( DISC_TOK, "disc" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ pNewDisc->setCenter( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseVector( vector ) )
+ return false;
+ pNewDisc->setNormal( vector );
+
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( d ) )
+ return false;
+ pNewDisc->setRadius( d );
+
+ if( m_token == ',' )
+ {
+ nextToken( );
+ if( !parseFloat( d ) )
+ return false;
+ pNewDisc->setHoleRadius( d );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewDisc );
+ parseObjectModifiers( pNewDisc );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseTriangle( PMTriangle* pNewTriangle )
+{
+ PMVector vector;
+ int oldConsumed;
+ int i;
+
+ if( m_token == SMOOTH_TRIANGLE_TOK )
+ pNewTriangle->setSmoothTriangle( true );
+ else if( m_token == TRIANGLE_TOK )
+ pNewTriangle->setSmoothTriangle( false );
+ else
+ {
+ printExpected( "triangle", m_pScanner->sValue( ) );
+ return false;
+ }
+ nextToken( );
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ for( i = 0; i < 3; i++ )
+ {
+ if( i != 0 )
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ pNewTriangle->setPoint( i, vector );
+
+ if( pNewTriangle->isSmoothTriangle( ) )
+ {
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ pNewTriangle->setNormal( i, vector );
+ }
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewTriangle );
+ parseObjectModifiers( pNewTriangle );
+ if( m_token == UV_VECTORS_TOK )
+ {
+ nextToken( );
+ pNewTriangle->enableUV( true );
+ for ( i = 0; i < 3; ++i )
+ {
+ if( parseVector( vector ) )
+ pNewTriangle->setUVVector( i, vector );
+ else
+ return false;
+ }
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseLathe( PMLathe* pNewLathe )
+{
+ PMVector vector;
+ int oldConsumed;
+ int i;
+ bool stop = false;
+
+ if( !parseToken( LATHE_TOK, "lathe" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ int minp = 2;
+ while( !stop )
+ {
+ switch( m_token )
+ {
+ case LINEAR_SPLINE_TOK:
+ pNewLathe->setSplineType( PMLathe::LinearSpline );
+ nextToken( );
+ minp = 2;
+ break;
+ case QUADRATIC_SPLINE_TOK:
+ pNewLathe->setSplineType( PMLathe::QuadraticSpline );
+ nextToken( );
+ minp = 3;
+ break;
+ case CUBIC_SPLINE_TOK:
+ pNewLathe->setSplineType( PMLathe::CubicSpline );
+ nextToken( );
+ minp = 4;
+ break;
+ case BEZIER_SPLINE_TOK:
+ pNewLathe->setSplineType( PMLathe::BezierSpline );
+ nextToken( );
+ minp = 4;
+ break;
+ default:
+ stop = true;
+ break;
+ }
+ }
+
+ int nump;
+ if( !parseInt( nump ) )
+ return false;
+
+ QValueList<PMVector> points;
+ for( i = 0; i < nump; i++ )
+ {
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ vector.resize( 2 );
+ points.append( vector );
+ }
+
+ if( nump < minp )
+ printError( i18n( "At least %1 points are needed for that spline type" )
+ .arg( minp ) );
+ else if( ( pNewLathe->splineType( ) == PMLathe::BezierSpline ) &&
+ ( ( nump % 4 ) != 0 ) )
+ printError( i18n( "Bezier splines need 4 points for each segment" ) );
+ else
+ pNewLathe->setPoints( points );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == STURM_TOK )
+ {
+ pNewLathe->setSturm( true );
+ nextToken( );
+ }
+
+ parseChildObjects( pNewLathe );
+ parseObjectModifiers( pNewLathe );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePrism( PMPrism* pNewPrism )
+{
+ PMVector vector;
+ double height;
+ int oldConsumed;
+ int i;
+ bool stop = false;
+
+ if( !parseToken( PRISM_TOK, "prism" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ int minp = 3;
+ while( !stop )
+ {
+ switch( m_token )
+ {
+ case LINEAR_SPLINE_TOK:
+ pNewPrism->setSplineType( PMPrism::LinearSpline );
+ nextToken( );
+ minp = 3;
+ break;
+ case QUADRATIC_SPLINE_TOK:
+ pNewPrism->setSplineType( PMPrism::QuadraticSpline );
+ nextToken( );
+ minp = 4;
+ break;
+ case CUBIC_SPLINE_TOK:
+ pNewPrism->setSplineType( PMPrism::CubicSpline );
+ nextToken( );
+ minp = 5;
+ break;
+ case BEZIER_SPLINE_TOK:
+ pNewPrism->setSplineType( PMPrism::BezierSpline );
+ nextToken( );
+ minp = 4;
+ break;
+ case LINEAR_SWEEP_TOK:
+ pNewPrism->setSweepType( PMPrism::LinearSweep );
+ nextToken( );
+ break;
+ case CONIC_SWEEP_TOK:
+ pNewPrism->setSweepType( PMPrism::ConicSweep );
+ nextToken( );
+ break;
+ default:
+ stop = true;
+ break;
+ }
+ }
+
+ if( !parseFloat( height ) )
+ return false;
+ pNewPrism->setHeight1( height );
+ parseToken( ',' );
+ if( !parseFloat( height ) )
+ return false;
+ pNewPrism->setHeight2( height );
+ parseToken( ',' );
+
+ int nump;
+ if( !parseInt( nump ) )
+ return false;
+
+ QValueList<PMVector> allPoints;
+ for( i = 0; i < nump; i++ )
+ {
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ vector.resize( 2 );
+ allPoints.append( vector );
+ }
+
+ QValueList< QValueList<PMVector> > points;
+ QValueList<PMVector> subPoints;
+ QValueList<PMVector>::Iterator it = allPoints.begin( );
+ int pnr = 0, pmod4;
+ PMVector ref( 2 ), ref2( 2 );
+ bool error = false;
+ bool last = false;
+
+ switch( pNewPrism->splineType( ) )
+ {
+ case PMPrism::LinearSpline:
+ for( ; ( it != allPoints.end( ) ) && !error; ++it, pnr++ )
+ {
+ if( pnr == 0 )
+ {
+ ref = *it;
+ subPoints.append( *it );
+ }
+ else
+ {
+ if( ref.approxEqual( *it ) )
+ {
+ if( pnr < 3 )
+ {
+ printError( i18n( "Linear splines need at least 4 points." ) );
+ error = true;
+ }
+ else
+ {
+ points.append( subPoints );
+ subPoints.clear( );
+ pnr = -1;
+ }
+ }
+ else
+ subPoints.append( *it );
+ }
+ }
+ if( ( pnr != 0 ) && ( !error ) )
+ {
+ printWarning( i18n( "Linear spline not closed" ) );
+ if( pnr < 3 )
+ {
+ printError( i18n( "Linear splines need at least 4 points." ) );
+ error = true;
+ }
+ else
+ {
+ points.append( subPoints );
+ subPoints.clear( );
+ }
+ }
+ break;
+ case PMPrism::QuadraticSpline:
+ for( ; ( it != allPoints.end( ) ) && !error; ++it, pnr++ )
+ {
+ if( pnr == 0 )
+ subPoints.append( *it );
+ else if( pnr == 1 )
+ {
+ ref = *it;
+ subPoints.append( *it );
+ }
+ else
+ {
+ if( ref.approxEqual( *it ) )
+ {
+ if( pnr < 4 )
+ {
+ printError( i18n( "Quadratic splines need at least 5 points." ) );
+ error = true;
+ }
+ else
+ {
+ points.append( subPoints );
+ subPoints.clear( );
+ pnr = -1;
+ }
+ }
+ else
+ subPoints.append( *it );
+ }
+ }
+ if( ( pnr != 0 ) && ( !error ) )
+ {
+ printError( i18n( "Quadratic spline not closed" ) );
+ error = true;
+ }
+ break;
+ case PMPrism::CubicSpline:
+ for( ; ( it != allPoints.end( ) ) && !error; ++it, pnr++ )
+ {
+ if( pnr == 0 )
+ subPoints.append( *it );
+ else if( pnr == 1 )
+ {
+ ref = *it;
+ subPoints.append( *it );
+ }
+ else if( last )
+ {
+ if( pnr < 5 )
+ {
+ printError( i18n( "Cubic splines need at least 6 points." ) );
+ error = true;
+ }
+ else
+ {
+ subPoints.append( *it );
+ points.append( subPoints );
+ subPoints.clear( );
+ pnr = -1;
+ last = false;
+ }
+ }
+ else
+ {
+ if( ref.approxEqual( *it ) )
+ last = true;
+ else
+ subPoints.append( *it );
+ }
+ }
+ if( ( pnr != 0 ) && ( !error ) )
+ {
+ printError( i18n( "Cubic spline not closed" ) );
+ error = true;
+ }
+ break;
+ case PMPrism::BezierSpline:
+ for( ; ( it != allPoints.end( ) ) && !error; ++it, pnr++ )
+ {
+ pmod4 = pnr % 4;
+
+ if( pnr == 0 )
+ {
+ ref = *it;
+ subPoints.append( *it );
+ }
+ else if( pmod4 == 0 )
+ {
+ if( !ref2.approxEqual( *it ) )
+ {
+ printError( i18n( "Bezier spline not closed" ) );
+ error = true;
+ }
+ }
+ else if( pmod4 == 3 )
+ {
+ if( ref.approxEqual( *it ) )
+ {
+ points.append( subPoints );
+ subPoints.clear( );
+ pnr = -1;
+ }
+ else
+ {
+ subPoints.append( *it );
+ ref2 = *it;
+ }
+ }
+ else
+ subPoints.append( *it );
+ }
+ if( ( pnr != 0 ) && ( !error ) )
+ {
+ printError( i18n( "Bezier spline not closed" ) );
+ error = true;
+ }
+ break;
+ }
+
+ if( !error )
+ pNewPrism->setPoints( points );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case STURM_TOK:
+ pNewPrism->setSturm( true );
+ nextToken( );
+ break;
+ case OPEN_TOK:
+ pNewPrism->setOpen( true );
+ nextToken( );
+ break;
+ default:
+ break;
+ }
+
+ parseChildObjects( pNewPrism );
+ parseObjectModifiers( pNewPrism );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSor( PMSurfaceOfRevolution* pNewSor )
+{
+ PMVector vector;
+ int oldConsumed;
+ int i;
+
+ if( !parseToken( SOR_TOK, "sor" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ int nump;
+ if( !parseInt( nump ) )
+ return false;
+
+ QValueList<PMVector> points;
+ for( i = 0; i < nump; i++ )
+ {
+ parseToken( ',' );
+ if( !parseVector( vector ) )
+ return false;
+ vector.resize( 2 );
+ points.append( vector );
+ }
+
+ if( nump < 4 )
+ printError( i18n( "At least 4 points are needed for the surface of revolution" ) );
+ else
+ {
+ QValueList<PMVector>::Iterator it1 = points.begin( );
+ QValueList<PMVector>::Iterator it2 = it1; ++it2;
+ QValueList<PMVector>::Iterator it3 = it2; ++it3;
+ int pnr = 0;
+
+ for( ; it3 != points.end( ); ++it1, ++it2, ++it3, pnr++ )
+ {
+ if( ( pnr == 0 ) || ( pnr == ( nump - 3 ) ) )
+ {
+ if( approxZero( ( *it1 )[1] - ( *it3 )[1], c_sorTolerance ) )
+ {
+ printError( i18n( "The v coordinate of point %1 and %2 must be different; fixed" )
+ .arg( pnr + 1 ).arg( pnr + 3 ) );
+ if( pnr == 0 )
+ ( *it1 )[1] = ( *it3 )[1] - c_sorTolerance;
+ else
+ ( *it3 )[1] = ( *it1 )[1] + c_sorTolerance;
+ }
+ }
+
+ if( pnr != 0 )
+ {
+ if( ( ( *it2 )[1] - ( *it1 )[1] ) < c_sorTolerance )
+ {
+ printError( i18n( "The v coordinates must be strictly increasing; fixed" ) );
+ ( *it2 )[1] = ( *it1 )[1] + c_sorTolerance;
+ }
+ }
+ }
+ pNewSor->setPoints( points );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case STURM_TOK:
+ pNewSor->setSturm( true );
+ nextToken( );
+ break;
+ case OPEN_TOK:
+ pNewSor->setOpen( true );
+ nextToken( );
+ break;
+ default:
+ break;
+ }
+
+ parseChildObjects( pNewSor );
+ parseObjectModifiers( pNewSor );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSqe( PMSuperquadricEllipsoid* pNewSqe )
+{
+ PMVector vector;
+ int oldConsumed;
+
+ if( !parseToken( SUPERELLIPSOID_TOK ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( !parseVector( vector ) )
+ return false;
+ vector.resize( 2 );
+
+ if( vector[0] < 0.001 )
+ {
+ printError( i18n( "The east-west exponent must be greater than 0.001" ) );
+ vector[0] = 0.001;
+ }
+ if( vector[1] < 0.001 )
+ {
+ printError( i18n( "The north-south exponent must be greater than 0.001" ) );
+ vector[1] = 0.001;
+ }
+
+ pNewSqe->setEastWestExponent( vector[0] );
+ pNewSqe->setNorthSouthExponent( vector[1] );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pNewSqe );
+ parseObjectModifiers( pNewSqe );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseRotate( PMRotate* rotate )
+{
+ PMVector v;
+
+ if( !parseToken( ROTATE_TOK, "rotate" ) )
+ return false;
+ if( !parseVector( v ) )
+ return false;
+
+ rotate->setRotation( v );
+ return true;
+}
+
+bool PMPovrayParser::parseScale( PMScale* scale )
+{
+ PMVector v;
+
+ if( !parseToken( SCALE_TOK, "scale" ) )
+ return false;
+ if( !parseVector( v ) )
+ return false;
+
+ scale->setScale( v );
+ return true;
+}
+
+bool PMPovrayParser::parseTranslate( PMTranslate* translate )
+{
+ PMVector v;
+
+ if( !parseToken( TRANSLATE_TOK, "translate" ) )
+ return false;
+ if( !parseVector( v ) )
+ return false;
+
+ translate->setTranslation( v );
+ return true;
+}
+
+bool PMPovrayParser::parseMatrix( PMPovrayMatrix* matrix )
+{
+ PMVector v;
+
+ if( !parseToken( MATRIX_TOK ), "matrix" )
+ return false;
+ if( !parseVectorLiteral( v ) )
+ return false;
+
+ if( v.size( ) != 12 )
+ {
+ printError( i18n( "Wrong number of matrix values." ) );
+ v.resize( 12 );
+ }
+ matrix->setValues( v );
+ return true;
+}
+
+bool PMPovrayParser::parseBoundedBy( PMBoundedBy* bound )
+{
+ int oldConsumed;
+
+ if( !parseToken( BOUNDED_BY_TOK, "bounded_by" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == CLIPPED_BY_TOK )
+ nextToken( );
+
+ parseChildObjects( bound );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseClippedBy( PMClippedBy* clipped )
+{
+ int oldConsumed;
+
+ if( !parseToken( CLIPPED_BY_TOK, "clipped_by" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == BOUNDED_BY_TOK )
+ nextToken( );
+
+ parseChildObjects( clipped );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseCamera( PMCamera* camera )
+{
+ PMVector v;
+ double d;
+ int i;
+
+ int oldConsumed;
+
+ if( !parseToken( CAMERA_TOK, "camera" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ switch( m_token )
+ {
+ case PERSPECTIVE_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Perspective );
+ break;
+ case ORTHOGRAPHIC_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Orthographic );
+ break;
+ case FISHEYE_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::FishEye );
+ break;
+ case ULTRA_WIDE_ANGLE_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::UltraWideAngle );
+ break;
+ case OMNIMAX_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Omnimax );
+ break;
+ case PANORAMIC_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Panoramic );
+ break;
+ case CYLINDER_TOK:
+ nextToken( );
+ camera->setCameraType( PMCamera::Cylinder );
+ if( parseInt( i ) )
+ camera->setCylinderType( i );
+ break;
+ case LOCATION_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setLocation( v );
+ break;
+ case SKY_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setSky( v );
+ break;
+ case UP_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setUp( v );
+ break;
+ case RIGHT_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setRight( v );
+ break;
+ case DIRECTION_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setDirection( v );
+ break;
+ case LOOK_AT_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setLookAt( v );
+ break;
+ case ANGLE_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ {
+ camera->enableAngle( true );
+ camera->setAngle( d );
+ }
+ break;
+ case BLUR_SAMPLES_TOK:
+ nextToken( );
+ camera->enableFocalBlur( true );
+ if( parseInt( i ) )
+ camera->setBlurSamples( i );
+ break;
+ case APERTURE_TOK:
+ nextToken( );
+ camera->enableFocalBlur( true );
+ if( parseFloat( d ) )
+ camera->setAperture( d );
+ break;
+ case FOCAL_POINT_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ camera->setFocalPoint( v );
+ break;
+ case CONFIDENCE_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ camera->setConfidence( d );
+ break;
+ case VARIANCE_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ camera->setVariance( d );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+ parseChildObjects( camera );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseLight( PMLight* light )
+{
+ PMVector v;
+ PMColor c;
+ double d;
+ int i;
+
+ int oldConsumed;
+
+ if( !parseToken( LIGHT_SOURCE_TOK, "light_source" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+ if( !parseVector( v ) )
+ return false;
+ light->setLocation( v );
+ if( m_token == ',' )
+ nextToken( );
+ if( !parseColor( c ) )
+ return false;
+ light->setColor( c );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( light );
+
+ switch( m_token )
+ {
+ case SPOTLIGHT_TOK:
+ nextToken( );
+ light->setLightType( PMLight::SpotLight );
+ break;
+ case CYLINDER_TOK:
+ nextToken( );
+ light->setLightType( PMLight::CylinderLight );
+ break;
+ case SHADOWLESS_TOK:
+ nextToken( );
+ light->setLightType( PMLight::ShadowlessLight );
+ break;
+ case RADIUS_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ light->setRadius( d );
+ break;
+ case FALLOFF_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ light->setFalloff( d );
+ break;
+ case TIGHTNESS_TOK:
+ nextToken( );
+ if( parseFloat( d ) )
+ light->setTightness( d );
+ break;
+ case POINT_AT_TOK:
+ nextToken( );
+ if( parseVector( v ) )
+ light->setPointAt( v );
+ break;
+ case PARALLEL_TOK:
+ nextToken( );
+ light->setParallel( parseBool( ) );
+ break;
+ case AREA_LIGHT_TOK:
+ nextToken( );
+ light->setAreaLight( true );
+ if( parseVector( v ) )
+ light->setAxis1( v );
+ parseToken( ',' );
+ if( parseVector( v ) )
+ light->setAxis2( v );
+ parseToken( ',' );
+ if( parseInt( i ) )
+ light->setSize1( i );
+ parseToken( ',' );
+ if( parseInt( i ) )
+ light->setSize2( i );
+ break;
+ case AREA_CIRCULAR_TOK:
+ nextToken( );
+ light->setAreaType( PMLight::Circular );
+ break;
+ case ADAPTIVE_TOK:
+ nextToken( );
+ if( parseInt( i ) )
+ light->setAdaptive( i );
+ break;
+ case ORIENT_TOK:
+ nextToken( );
+ light->setOrient( parseBool( ) );
+ break;
+ case JITTER_TOK:
+ nextToken( );
+ light->setJitter( parseBool( ) );
+ break;
+ case FADE_POWER_TOK:
+ nextToken( );
+ light->setFading( true );
+ if( parseInt( i ) )
+ light->setFadePower( i );
+ break;
+ case FADE_DISTANCE_TOK:
+ nextToken( );
+ light->setFading( true );
+ if( parseFloat( d ) )
+ light->setFadeDistance( d );
+ break;
+ case MEDIA_INTERACTION_TOK:
+ nextToken( );
+ light->setMediaInteraction( parseBool( ) );
+ break;
+ case MEDIA_ATTENUATION_TOK:
+ nextToken( );
+ light->setMediaAttenuation( parseBool( ) );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseLooksLike( PMLooksLike* ll )
+{
+ if( !parseToken( LOOKS_LIKE_TOK, "looks_like" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ parseChildObjects( ll );
+
+ if( !parseToken( '}' ) )
+ return false;
+ return true;
+}
+
+bool PMPovrayParser::parseProjectedThrough( PMProjectedThrough* ll )
+{
+ if( !parseToken( PROJECTED_THROUGH_TOK, "projected_through" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ parseChildObjects( ll );
+
+ if( !parseToken( '}' ) )
+ return false;
+ return true;
+}
+
+bool PMPovrayParser::parseTexture( PMTexture* texture, bool parseOuter )
+{
+ int oldConsumed;
+
+ if( parseOuter )
+ {
+ if( !parseToken( TEXTURE_TOK, "texture" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+ }
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !texture->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( texture );
+ if( m_token == UV_MAPPING_TOK )
+ {
+ nextToken();
+ texture->setUVMapping( parseBool( ) );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( parseOuter )
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePattern( PMPattern* pattern, bool normal )
+{
+ PMVector vector;
+ double f_number;
+ int i_number;
+ int oldConsumed;
+ bool type;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ type = false;
+
+ switch( m_token )
+ {
+ case AGATE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternAgate );
+ type = true;
+ break;
+ case AGATE_TURB_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setAgateTurbulence( f_number );
+ break;
+ case AVERAGE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternAverage );
+ type = true;
+ break;
+ case BOXED_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternBoxed );
+ type = true;
+ break;
+ case BOZO_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternBozo );
+ type = true;
+ break;
+ case BUMPS_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternBumps );
+ type = true;
+ break;
+ case CELLS_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternCells );
+ type = true;
+ break;
+ case CRACKLE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternCrackle );
+ type = true;
+ break;
+ case CYLINDRICAL_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternCylindrical );
+ type = true;
+ break;
+ case DENTS_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternDents );
+ type = true;
+ break;
+ case DENSITY_FILE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternDensity );
+ type = true;
+ if( !parseToken( DF3_TOK, "df3" ) )
+ return false;
+ if( m_token != STRING_TOK )
+ {
+ printError( i18n( "Expecting a file name." ) );
+ return false;
+ }
+ else
+ {
+ pattern->setDensityFile( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+ if( parseToken( INTERPOLATE_TOK, "interpolate" ) )
+ {
+ if( !parseInt( i_number ) )
+ return false;
+ else
+ pattern->setDensityInterpolate( i_number );
+ }
+ break;
+ case GRADIENT_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternGradient );
+ type = true;
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setGradient( vector );
+ break;
+ case GRANITE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternGranite );
+ type = true;
+ break;
+ case JULIA_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternJulia );
+ type = true;
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setJuliaComplex( vector );
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setMaxIterations( i_number );
+ break;
+ case LEOPARD_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternLeopard );
+ type = true;
+ break;
+ case MANDEL_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternMandel );
+ type = true;
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setMaxIterations( i_number );
+ break;
+ case MARBLE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternMarble );
+ type = true;
+ break;
+ case ONION_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternOnion );
+ type = true;
+ break;
+ case PLANAR_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternPlanar );
+ type = true;
+ break;
+ case QUILTED_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternQuilted );
+ type = true;
+ break;
+ case CONTROL0_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setQuiltControl0( f_number );
+ break;
+ case CONTROL1_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setQuiltControl1( f_number );
+ break;
+ case RADIAL_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternRadial );
+ type = true;
+ break;
+ case RIPPLES_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternRipples );
+ type = true;
+ break;
+ case SLOPE_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternSlope );
+ type = true;
+ if( !parseToken( '{' ) )
+ return false;
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setSlopeDirection( vector );
+ if ( parseToken( ',' ) )
+ {
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setSlopeLoSlope( f_number );
+ if ( parseToken( ',' ) )
+ {
+ if ( !parseFloat( f_number ) )
+ return false;
+ pattern->setSlopeHiSlope( f_number );
+ }
+ }
+ if( m_token == ALTITUDE_TOK )
+ {
+ pattern->setSlopeAltFlag( true );
+ nextToken( );
+ if ( !parseVector( vector ) )
+ return false;
+ pattern->setSlopeAltitude( vector );
+ if( parseToken( ',' ) )
+ {
+ if ( !parseFloat( f_number ) )
+ return false;
+ pattern->setSlopeLoAlt( f_number );
+ if ( parseToken( ',' ) )
+ {
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setSlopeHiAlt( f_number );
+ }
+ }
+ }
+ if( !parseToken( '}' ) )
+ return false;
+ break;
+ case SPHERICAL_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternSpherical );
+ type = true;
+ break;
+ case SPIRAL1_TOK:
+ case SPIRAL2_TOK:
+ if( m_token == SPIRAL1_TOK )
+ pattern->setPatternType( PMPattern::PatternSpiral1 );
+ else
+ pattern->setPatternType( PMPattern::PatternSpiral2 );
+ type = true;
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setSpiralNumberArms( i_number );
+ break;
+ case SPOTTED_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternSpotted );
+ type = true;
+ break;
+ case WAVES_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternWaves );
+ type = true;
+ break;
+ case WOOD_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternWood );
+ type = true;
+ break;
+ case WRINKLES_TOK:
+ nextToken( );
+ pattern->setPatternType( PMPattern::PatternWrinkles );
+ type = true;
+ break;
+
+ //crackle parameters
+ case FORM_TOK:
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setCrackleForm( vector );
+ break;
+ case METRIC_TOK:
+ nextToken( );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setCrackleMetric( i_number );
+ break;
+ case OFFSET_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setCrackleOffset( f_number );
+ break;
+ case SOLID_TOK:
+ nextToken( );
+ pattern->setCrackleSolid( true );
+ break;
+
+ //fractal parameters
+ case MAGNET_TOK:
+ nextToken( );
+ pattern->setFractalMagnet( true );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setFractalMagnetType( i_number );
+ break;
+ case EXPONENT_TOK:
+ nextToken( );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setFractalExponent( i_number );
+ break;
+ case EXTERIOR_TOK:
+ nextToken( );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setFractalExtType( i_number );
+ if ( !parseFloat( f_number ) )
+ return false;
+ pattern->setFractalExtFactor( f_number );
+ break;
+ case INTERIOR_TOK:
+ nextToken( );
+ if ( !parseInt( i_number ) )
+ return false;
+ pattern->setFractalIntType( i_number );
+ if ( !parseFloat( f_number ) )
+ return false;
+ pattern->setFractalIntFactor( f_number );
+ break;
+
+ //turbulence
+ case TURBULENCE_TOK:
+ nextToken( );
+ pattern->enableTurbulence( true );
+ if( !parseVector( vector ) )
+ return false;
+ pattern->setValueVector( vector );
+ break;
+ case OCTAVES_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setOctaves( i_number );
+ break;
+ case OMEGA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setOmega( f_number );
+ break;
+ case LAMBDA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ pattern->setLambda( f_number );
+ break;
+
+ case NOISE_GENERATOR_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ pattern->setNoiseGenerator( ( PMPattern::PMNoiseType ) ( i_number ) );
+ break;
+ default:
+ break;
+ }
+
+ if( type && normal )
+ {
+ // try to parse the normal pattern depth
+ double depth;
+ if( parseFloat( depth, true ) )
+ pattern->setDepth( depth );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ return true;
+}
+
+bool PMPovrayParser::parseBlendMapModifiers( PMBlendMapModifiers* blend )
+{
+ int oldConsumed;
+ double f_number;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case FREQUENCY_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ blend->enableFrequency( true );
+ blend->setFrequency( f_number );
+ break;
+ case PHASE_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ blend->enablePhase( true );
+ blend->setPhase( f_number );
+ break;
+ case RAMP_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::RampWave );
+ break;
+ case TRIANGLE_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::TriangleWave );
+ break;
+ case SINE_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::SineWave );
+ break;
+ case SCALLOP_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::ScallopWave );
+ break;
+ case CUBIC_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::CubicWave );
+ break;
+ case POLY_WAVE_TOK:
+ nextToken( );
+ blend->enableWaveForm( true );
+ blend->setWaveFormType( PMBlendMapModifiers::PolyWave );
+ if( parseFloat( f_number, true ) )
+ blend->setWaveFormExponent( f_number );
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ return true;
+}
+
+bool PMPovrayParser::parseWarp( PMWarp* warp )
+{
+ int oldConsumed;
+ PMVector vector;
+ double f_number;
+ int i_number;
+ bool parsedFirst;
+ bool mapping;
+
+ if( !parseToken( WARP_TOK, "warp" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ mapping = false;
+ parsedFirst = false;
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if( !parsedFirst &&
+ ( m_token != REPEAT_TOK ||
+ m_token != BLACK_HOLE_TOK ||
+ m_token != TURBULENCE_TOK ||
+ m_token != CYLINDRICAL_TOK ||
+ m_token != SPHERICAL_TOK ||
+ m_token != TOROIDAL_TOK ||
+ m_token != PLANAR_TOK ) )
+ {
+ printError( i18n( "Expecting a warp type" ) );
+ return false;
+ }
+ switch( m_token )
+ {
+ case REPEAT_TOK:
+ nextToken( );
+ if( !parsedFirst )
+ {
+ warp->setWarpType( PMWarp::Repeat );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setDirection( vector );
+ parsedFirst = true;
+ }
+ else
+ {
+ if( !parseVector( vector ) )
+ return false;
+ warp->setRepeat( vector );
+ }
+ break;
+ case OFFSET_TOK:
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setOffset( vector );
+ break;
+ case FLIP_TOK:
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setFlip( vector );
+ break;
+ case BLACK_HOLE_TOK:
+ nextToken( );
+ warp->setWarpType( PMWarp::BlackHole );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setLocation( vector );
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setRadius( f_number );
+ parsedFirst = true;
+ break;
+ case STRENGTH_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setStrength( f_number );
+ break;
+ case FALLOFF_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setFalloff( f_number );
+ break;
+ case INVERSE_TOK:
+ nextToken( );
+ warp->setInverse( true );
+ break;
+ case TURBULENCE_TOK:
+ if( !parsedFirst )
+ {
+ nextToken( );
+ warp->setWarpType( PMWarp::Turbulence );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setValueVector( vector );
+ parsedFirst = true;
+ }
+ else
+ {
+ if( !parseVector( vector ) )
+ return false;
+ warp->setTurbulence( vector );
+ }
+ break;
+ case OCTAVES_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ warp->setOctaves( i_number );
+ break;
+ case OMEGA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setOmega( f_number );
+ break;
+ case LAMBDA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setLambda( f_number );
+ break;
+ case CYLINDRICAL_TOK:
+ warp->setWarpType( PMWarp::Cylindrical );
+ mapping = true;
+ break;
+ case SPHERICAL_TOK:
+ warp->setWarpType( PMWarp::Spherical );
+ mapping = true;
+ break;
+ case TOROIDAL_TOK:
+ warp->setWarpType( PMWarp::Toroidal );
+ mapping = true;
+ break;
+ case PLANAR_TOK:
+ nextToken( );
+ warp->setWarpType( PMWarp::Planar );
+ if( parseVector( vector ) )
+ {
+ warp->setOrientation( vector );
+ if( parseToken( ',' ) )
+ {
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setDistExp( f_number );
+ }
+ }
+ parsedFirst = true;
+ break;
+ case DIST_EXP_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setDistExp( f_number );
+ break;
+ case MAJOR_RADIUS_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ warp->setMajorRadius( f_number );
+ break;
+ default:
+ break;
+ }
+
+ if( mapping)
+ {
+ nextToken( );
+ if( !parseVector( vector ) )
+ return false;
+ warp->setOrientation( vector );
+ parsedFirst = true;
+ mapping = false;
+ }
+
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePigment( PMPigment* pigment, bool parseOuter )
+{
+ PMColor c;
+ PMSolidColor* sc;
+ int oldConsumed;
+
+ if( parseOuter )
+ {
+ if( !parseToken( PIGMENT_TOK, "pigment" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+ }
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMSymbol* s = getSymbol( id );
+ bool skipID = false;
+
+ if( s )
+ if( s->type( ) == PMSymbol::Value )
+ skipID = true;
+
+ if( !skipID )
+ {
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !pigment->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( pigment );
+
+ switch( m_token )
+ {
+ case '<':
+ case COLOR_TOK:
+ case COLOUR_TOK:
+ case RGB_TOK:
+ case RGBT_TOK:
+ case RGBF_TOK:
+ case RGBFT_TOK:
+ case RED_TOK:
+ case GREEN_TOK:
+ case BLUE_TOK:
+ case TRANSMIT_TOK:
+ case FILTER_TOK:
+ case ID_TOK:
+ if( parseColor( c ) )
+ {
+ sc = new PMSolidColor( m_pPart );
+ sc->setColor( c );
+ if( !insertChild( sc, pigment ) )
+ {
+ delete sc;
+ sc = 0;
+ }
+ }
+ break;
+ case UV_MAPPING_TOK:
+ nextToken();
+ pigment->setUVMapping( parseBool( ) );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( parseOuter )
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseNormal( PMNormal* normal )
+{
+ double f_number;
+ int oldConsumed;
+
+ if( !parseToken( NORMAL_TOK, "normal" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !normal->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( normal );
+ switch( m_token )
+ {
+ case BUMP_SIZE_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ normal->enableBumpSize( true );
+ normal->setBumpSize( f_number );
+ break;
+ case ACCURACY_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ normal->setAccuracy( f_number );
+ break;
+ case UV_MAPPING_TOK:
+ nextToken( );
+ normal->setUVMapping( parseBool( ) );
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseTextureMap( PMTextureMap* textureMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMTexture* texture;
+ QValueList<double> mapValues;
+
+ if( !parseToken( TEXTURE_MAP_TOK, "texture_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !textureMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == '[' )
+ {
+ nextToken( );
+
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ texture = new PMTexture( m_pPart );
+
+ parseTexture( texture, false );
+
+ if( !insertChild( texture, textureMap ) )
+ delete texture;
+
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ textureMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePigmentMap( PMPigmentMap* pigmentMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMPigment* pigment;
+ QValueList<double> mapValues;
+
+ if( !parseToken( PIGMENT_MAP_TOK, "pigment_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !pigmentMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == '[' )
+ {
+ nextToken( );
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ pigment = new PMPigment( m_pPart );
+
+ parsePigment( pigment, false );
+ if( !insertChild( pigment, pigmentMap ) )
+ delete pigment;
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ pigmentMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseNormalMap( PMNormalMap* normalMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMNormal* normal;
+ QValueList<double> mapValues;
+
+ if( !parseToken( NORMAL_MAP_TOK, "normal_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !normalMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ // If we find '}' no need to search for an entry
+ if( m_token != '}' && parseToken( '[' ) )
+ {
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ normal = new PMNormal( m_pPart );
+ if( !parseNormal( normal ) )
+ {
+ delete normal;
+ return false;
+ }
+ if( !insertChild( normal, normalMap ) )
+ delete normal;
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ normalMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseBumpMap( PMBumpMap* bumpMap )
+{
+ int oldConsumed;
+ int i_number;
+ double f_number;
+
+ if( !parseToken( BUMP_MAP_TOK, "bump_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse the bitmap type
+ if( m_token != STRING_TOK )
+ {
+ switch( m_token )
+ {
+ case GIF_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapGif );
+ nextToken( );
+ break;
+ case TGA_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapTga );
+ nextToken( );
+ break;
+ case IFF_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapIff );
+ nextToken( );
+ break;
+ case PPM_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapPpm );
+ nextToken( );
+ break;
+ case PGM_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapPgm );
+ nextToken( );
+ break;
+ case PNG_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapPng );
+ nextToken( );
+ break;
+ case SYS_TOK:
+ bumpMap->setBitmapType( PMBumpMap::BitmapSys );
+ nextToken( );
+ break;
+ default:
+ printError( i18n( "Unknown bitmap type" ) );
+ return false;
+ }
+ }
+
+ // Parse the bitmap file name
+ if( m_token != STRING_TOK )
+ {
+ printError( i18n( "Expecting a file name." ) );
+ return false;
+ }
+ else
+ {
+ bumpMap->setBitmapFileName( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case ONCE_TOK:
+ nextToken( );
+ bumpMap->enableOnce( true );
+ break;
+ case MAP_TYPE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 0:
+ bumpMap->setMapType( PMBumpMap::MapPlanar );
+ break;
+ case 1:
+ bumpMap->setMapType( PMBumpMap::MapSpherical );
+ break;
+ case 2:
+ bumpMap->setMapType( PMBumpMap::MapCylindrical );
+ break;
+ case 5:
+ bumpMap->setMapType( PMBumpMap::MapToroidal );
+ break;
+ }
+ break;
+ case INTERPOLATE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 2:
+ bumpMap->setInterpolateType( PMBumpMap::InterpolateBilinear );
+ break;
+ case 4:
+ bumpMap->setInterpolateType( PMBumpMap::InterpolateNormalized );
+ break;
+ }
+ break;
+ case USE_INDEX_TOK:
+ nextToken( );
+ bumpMap->enableUseIndex( true );
+ break;
+ case BUMP_SIZE_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ bumpMap->setBumpSize( f_number );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseMaterialMap( PMMaterialMap* materialMap )
+{
+ int oldConsumed;
+ int i_number;
+
+ if( !parseToken( MATERIAL_MAP_TOK, "material_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse the bitmap type
+ if( m_token != STRING_TOK )
+ {
+ switch( m_token )
+ {
+ case GIF_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapGif );
+ nextToken( );
+ break;
+ case TGA_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapTga );
+ nextToken( );
+ break;
+ case IFF_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapIff );
+ nextToken( );
+ break;
+ case PPM_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapPpm );
+ nextToken( );
+ break;
+ case PGM_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapPgm );
+ nextToken( );
+ break;
+ case PNG_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapPng );
+ nextToken( );
+ break;
+ case SYS_TOK:
+ materialMap->setBitmapType( PMMaterialMap::BitmapSys );
+ nextToken( );
+ break;
+ default:
+ printError( i18n( "Unknown bitmap type" ) );
+ return false;
+ }
+ }
+
+ // Parse the bitmap file name
+ if( m_token != STRING_TOK )
+ {
+ printError( i18n( "Expecting a file name." ) );
+ return false;
+ }
+ else
+ {
+ materialMap->setBitmapFileName( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( materialMap );
+ switch( m_token )
+ {
+ case ONCE_TOK:
+ nextToken( );
+ materialMap->enableOnce( true );
+ break;
+ case MAP_TYPE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 0:
+ materialMap->setMapType( PMMaterialMap::MapPlanar );
+ break;
+ case 1:
+ materialMap->setMapType( PMMaterialMap::MapSpherical );
+ break;
+ case 2:
+ materialMap->setMapType( PMMaterialMap::MapCylindrical );
+ break;
+ case 5:
+ materialMap->setMapType( PMMaterialMap::MapToroidal );
+ break;
+ }
+ break;
+ case INTERPOLATE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 2:
+ materialMap->setInterpolateType( PMMaterialMap::InterpolateBilinear );
+ break;
+ case 4:
+ materialMap->setInterpolateType( PMMaterialMap::InterpolateNormalized );
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSlopeMap( PMSlopeMap* slopeMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMSlope* slope;
+ QValueList<double> mapValues;
+
+ if( !parseToken( SLOPE_MAP_TOK, "slope_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !slopeMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ // If we find '}' no need to search for an entry
+ if( m_token != '}' && parseToken( '[' ) )
+ {
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ slope = new PMSlope( m_pPart );
+ if( !parseSlope( slope ) )
+ {
+ delete slope;
+ return false;
+ }
+ if( !insertChild( slope, slopeMap ) )
+ delete slope;
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ slopeMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseDensityMap( PMDensityMap* densityMap )
+{
+ int oldConsumed;
+ double f_number1;
+ PMDensity* density;
+ QValueList<double> mapValues;
+
+ if( !parseToken( DENSITY_MAP_TOK, "density_map" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !densityMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ // If we find '}' no need to search for an entry
+ if( m_token != '}' && parseToken( '[' ) )
+ {
+ if( !parseFloat( f_number1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ density = new PMDensity( m_pPart );
+ if( !parseDensity( density ) )
+ {
+ delete density;
+ return false;
+ }
+ if( !insertChild( density, densityMap ) )
+ delete density;
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ densityMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseImageMap( PMImageMap* imageMap )
+{
+ int oldConsumed;
+ int i_number;
+ double f_number;
+ PMPaletteValue newPaletteValue;
+ QValueList<PMPaletteValue> l_valuesFilter;
+ QValueList<PMPaletteValue> l_valuesTransmit;
+
+ if( !parseToken( IMAGE_MAP_TOK, "image_map" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse the bitmap type
+ if( m_token != STRING_TOK )
+ {
+ switch( m_token )
+ {
+ case GIF_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapGif );
+ nextToken( );
+ break;
+ case TGA_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapTga );
+ nextToken( );
+ break;
+ case IFF_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapIff );
+ nextToken( );
+ break;
+ case PPM_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapPpm );
+ nextToken( );
+ break;
+ case PGM_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapPgm );
+ nextToken( );
+ break;
+ case PNG_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapPng );
+ nextToken( );
+ break;
+ case SYS_TOK:
+ imageMap->setBitmapType( PMImageMap::BitmapSys );
+ nextToken( );
+ break;
+ default:
+ printError( i18n( "Unknown bitmap type" ) );
+ return false;
+ }
+ }
+
+ // Parse the bitmap file name
+ if( m_token != STRING_TOK )
+ {
+ printError( i18n( "Expecting a file name." ) );
+ return false;
+ }
+ else
+ {
+ imageMap->setBitmapFileName( m_pScanner->sValue( ) );
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case TRANSMIT_TOK:
+ nextToken( );
+ if( m_token == ALL_TOK )
+ {
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ imageMap->enableTransmitAll( true );
+ imageMap->setTransmitAll( f_number );
+ }
+ else
+ {
+ if( !parseInt( i_number ) )
+ return false;
+ parseToken( ',' );
+ if( !parseFloat( f_number ) )
+ return false;
+ newPaletteValue.setIndex( i_number );
+ newPaletteValue.setValue( f_number );
+ l_valuesTransmit.append( newPaletteValue );
+ }
+ break;
+ case FILTER_TOK:
+ nextToken( );
+ if( m_token == ALL_TOK )
+ {
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ imageMap->enableFilterAll( true );
+ imageMap->setFilterAll( f_number );
+ }
+ else
+ {
+ if( !parseInt( i_number ) )
+ return false;
+ parseToken( ',' );
+ if( !parseFloat( f_number ) )
+ return false;
+ newPaletteValue.setIndex( i_number );
+ newPaletteValue.setValue( f_number );
+ l_valuesFilter.append( newPaletteValue );
+ }
+ break;
+ case ONCE_TOK:
+ nextToken( );
+ imageMap->enableOnce( true );
+ break;
+ case MAP_TYPE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 0:
+ imageMap->setMapType( PMImageMap::MapPlanar );
+ break;
+ case 1:
+ imageMap->setMapType( PMImageMap::MapSpherical );
+ break;
+ case 2:
+ imageMap->setMapType( PMImageMap::MapCylindrical );
+ break;
+ case 5:
+ imageMap->setMapType( PMImageMap::MapToroidal );
+ break;
+ }
+ break;
+ case INTERPOLATE_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ switch( i_number )
+ {
+ case 2:
+ imageMap->setInterpolateType( PMImageMap::InterpolateBilinear );
+ break;
+ case 4:
+ imageMap->setInterpolateType( PMImageMap::InterpolateNormalized );
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+ imageMap->setFilters( l_valuesFilter );
+ imageMap->setTransmits( l_valuesTransmit );
+
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePigmentList( PMPigmentList* pigmentList, int expectedItems )
+{
+ int oldConsumed;
+ PMPigment* pigment;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ pigment = new PMPigment( m_pPart );
+ if( !parsePigment( pigment ) )
+ {
+ delete pigment;
+ return false;
+ }
+ if( !insertChild( pigment, pigmentList ) )
+ delete pigment;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseColorList( PMColorList* colorList, int expectedItems )
+{
+ int oldConsumed;
+ PMColor color;
+ PMSolidColor* sc;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if( !parseColor( color ) )
+ {
+ return false;
+ }
+ sc = new PMSolidColor( m_pPart );
+ sc->setColor( color );
+ if( !insertChild( sc, colorList ) )
+ delete sc;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseNormalList( PMNormalList* normalList, int expectedItems )
+{
+ int oldConsumed;
+ PMNormal* normal;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ normal = new PMNormal( m_pPart );
+ if( !parseNormal( normal ) )
+ {
+ delete normal;
+ return false;
+ }
+ if( !insertChild( normal, normalList ) )
+ delete normal;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseTextureList( PMTextureList* textureList, int expectedItems )
+{
+ int oldConsumed;
+ PMTexture* texture;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ texture = new PMTexture( m_pPart );
+ if( !parseTexture( texture ) )
+ {
+ delete texture;
+ return false;
+ }
+ if( !insertChild( texture, textureList ) )
+ delete texture;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseDensityList( PMDensityList* densityList, int expectedItems )
+{
+ int oldConsumed;
+ PMDensity* density;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ density = new PMDensity( m_pPart );
+ if( !parseDensity( density ) )
+ {
+ delete density;
+ return false;
+ }
+ if( !insertChild( density, densityList ) )
+ delete density;
+
+ // In the last entry don't expect a comma
+ if( expectedItems-- )
+ if( m_token == ',' )
+ nextToken( );
+ }
+ while( oldConsumed != m_consumedTokens && expectedItems );
+
+ return true;
+}
+
+bool PMPovrayParser::parseColorMap( PMColorMap* colorMap )
+{
+ int oldConsumed;
+ double f_number1, f_number2;
+ PMColor color1, color2;
+ PMSolidColor* solidColor;
+ PMSolidColor* lastColor = 0;
+ QValueList<double> mapValues;
+ bool newEntry;
+ bool twoColors;
+
+ if( m_token != COLOR_MAP_TOK && m_token != COLOUR_MAP_TOK )
+ return false;
+ nextToken( );
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !colorMap->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+
+ if( m_token == '[' )
+ {
+ nextToken( );
+ if( !parseFloat( f_number1 ) )
+ return false;
+
+ twoColors = false;
+ if( m_token == ',' )
+ {
+ twoColors = true;
+ nextToken( );
+ }
+ else if( ( m_token == INTEGER_TOK ) || ( m_token == FLOAT_TOK ) )
+ twoColors = true;
+
+ if( twoColors )
+ {
+ // Two colors in the same entry
+
+ if( parseFloat( f_number2 ) )
+ {
+ if( !parseColor( color1 ) )
+ return false;
+ if( !parseColor( color2 ) )
+ return false;
+ // If the first value doesn't pick up from the previous,
+ // or the color is different...
+ newEntry = true;
+ if( lastColor && !mapValues.isEmpty( ) )
+ if( ( mapValues.last( ) == f_number1 ) &&
+ ( lastColor->color( ) == color1 ) )
+ newEntry = false;
+
+ if( newEntry )
+ {
+ // ... add the two colors in two different entries ...
+ mapValues.append( f_number1 );
+ solidColor = new PMSolidColor( m_pPart );
+ solidColor->setColor( color1 );
+ if( !insertChild( solidColor, colorMap ) )
+ delete solidColor;
+ else
+ lastColor = solidColor;
+
+ mapValues.append( f_number2 );
+ solidColor = new PMSolidColor( m_pPart );
+ solidColor->setColor( color2 );
+ if( !insertChild( solidColor, colorMap ) )
+ delete solidColor;
+ else
+ lastColor = solidColor;
+ }
+ else
+ {
+ // ... else just add the last value and color
+ mapValues.append( f_number2 );
+ solidColor = new PMSolidColor( m_pPart );
+ solidColor->setColor( color2 );
+ if( !insertChild( solidColor, colorMap ) )
+ delete solidColor;
+ else
+ lastColor = solidColor;
+ }
+ }
+ }
+ else
+ {
+ // Only one color in the entry
+ if( !parseColor( color1 ) )
+ return false;
+ mapValues.append( f_number1 );
+ solidColor = new PMSolidColor( m_pPart );
+ solidColor->setColor( color1 );
+ if( !insertChild( solidColor, colorMap ) )
+ delete solidColor;
+ else
+ lastColor = solidColor;
+ }
+ if( !parseToken( ']' ) )
+ return false;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ colorMap->setMapValues( mapValues );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSkySphere( PMSkySphere* sky )
+{
+ int oldConsumed;
+
+ if( !parseToken( SKY_SPHERE_TOK, "sky_sphere" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !sky->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( sky );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseRainbow( PMRainbow* rainbow )
+{
+ PMVector vector;
+ double f_number;
+ int oldConsumed;
+
+ if( !parseToken( RAINBOW_TOK, "rainbow" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !rainbow->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( rainbow );
+ switch( m_token )
+ {
+ case DIRECTION_TOK:
+ nextToken( );
+ if( parseVector( vector ) )
+ {
+ rainbow->enableDirection( true );
+ rainbow->setDirection( vector );
+ }
+ break;
+ case ANGLE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableAngle( true );
+ rainbow->setAngle( f_number );
+ }
+ break;
+ case WIDTH_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableWidth( true );
+ rainbow->setWidth( f_number );
+ }
+ break;
+ case DISTANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableDistance( true );
+ rainbow->setDistance( f_number );
+ }
+ break;
+ case JITTER_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableJitter( true );
+ rainbow->setJitter( f_number );
+ }
+ break;
+ case UP_TOK:
+ nextToken( );
+ if( parseVector( vector ) )
+ {
+ rainbow->enableUp( true );
+ rainbow->setUp( vector );
+ }
+ break;
+ case ARC_ANGLE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableArcAngle( true );
+ rainbow->setArcAngle( f_number );
+ }
+ break;
+ case FALLOFF_ANGLE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ rainbow->enableFalloffAngle( true );
+ rainbow->setFalloffAngle( f_number );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseFog( PMFog* fog )
+{
+ PMColor color;
+ PMVector vector;
+ double f_number;
+ int i_number;
+ int fog_type;
+ int oldConsumed;
+
+ if( !parseToken( FOG_TOK, "fog" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !fog->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ fog_type = 1;
+ if( parseToken( FOG_TYPE_TOK, "fog_type" ) )
+ {
+ if( !parseInt( i_number ) )
+ return false;
+ fog_type = i_number;
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case DISTANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ fog->setDistance( f_number );
+ break;
+ case '<':
+ case COLOR_TOK:
+ case COLOUR_TOK:
+ case RGB_TOK:
+ case RGBT_TOK:
+ case RGBF_TOK:
+ case RGBFT_TOK:
+ case RED_TOK:
+ case GREEN_TOK:
+ case BLUE_TOK:
+ case TRANSMIT_TOK:
+ case FILTER_TOK:
+ case ID_TOK:
+ if( parseColor( color ) )
+ fog->setColor( color );
+ break;
+ case TURBULENCE_TOK:
+ nextToken( );
+ fog->enableTurbulence( true );
+ if( !parseVector( vector ) )
+ return false;
+ fog->setValueVector( vector );
+ break;
+ case OCTAVES_TOK:
+ nextToken( );
+ if( !parseInt( i_number ) )
+ return false;
+ fog->setOctaves( i_number );
+ break;
+ case OMEGA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ fog->setOmega( f_number );
+ break;
+ case LAMBDA_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ fog->setLambda( f_number );
+ break;
+ case TURB_DEPTH_TOK:
+ nextToken( );
+ if( !parseFloat( f_number ) )
+ return false;
+ fog->setDepth( f_number );
+ break;
+ case FOG_OFFSET_TOK:
+ nextToken( );
+ fog_type = 2;
+ if( parseFloat( f_number ) )
+ fog->setFogOffset( f_number );
+ break;
+ case FOG_ALT_TOK:
+ nextToken( );
+ fog_type = 2;
+ if( parseFloat( f_number ) )
+ fog->setFogAlt( f_number );
+ break;
+ case UP_TOK:
+ nextToken( );
+ fog_type = 2;
+ if( !parseVector( vector ) )
+ return false;
+ fog->setUp( vector );
+ break;
+ default:
+ break;
+ }
+ // Only parseChildObjects() if the token is not turbulence, because this
+ // function parses that token.
+ if( m_token != TURBULENCE_TOK )
+ parseChildObjects( fog );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ fog->setFogType( fog_type );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseMedia( PMMedia* media )
+{
+ PMColor color;
+ double f_number;
+ int i_number;
+ int oldConsumed, oldConsumed1;
+
+ if( !parseToken( MEDIA_TOK, "media" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !media->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( media );
+ switch( m_token )
+ {
+ case METHOD_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ media->setMethod( i_number );
+ break;
+ case INTERVALS_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ media->setIntervals( i_number );
+ break;
+ case SAMPLES_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ media->setSamplesMin( i_number );
+ parseToken( ',' );
+ if( parseInt( i_number ) )
+ media->setSamplesMax( i_number );
+ break;
+ case CONFIDENCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setConfidence( f_number );
+ break;
+ case VARIANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setVariance( f_number );
+ break;
+ case RATIO_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setRatio( f_number );
+ break;
+ case AA_LEVEL_TOK:
+ nextToken( );
+ if ( parseInt( i_number ) )
+ media->setAALevel( i_number );
+ break;
+ case AA_THRESHOLD_TOK:
+ nextToken( );
+ if ( parseFloat( f_number ) )
+ media->setAAThreshold( f_number );
+ break;
+ case ABSORPTION_TOK:
+ nextToken( );
+ if( parseColor( color ) )
+ {
+ media->enableAbsorption( true );
+ media->setAbsorption( color );
+ }
+ break;
+ case EMISSION_TOK:
+ nextToken( );
+ media->enableEmission( true );
+ if( parseColor( color ) )
+ media->setEmission( color );
+ break;
+ case SCATTERING_TOK:
+ nextToken( );
+ parseToken( '{' );
+ media->enableScattering( true );
+ if( parseInt( i_number ) )
+ media->setScatteringType( i_number );
+ parseToken( ',' );
+ if( parseColor( color ) )
+ media->setScatteringColor( color );
+ do
+ {
+ oldConsumed1 = m_consumedTokens;
+ switch( m_token )
+ {
+ case ECCENTRICITY_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setScatteringEccentricity( f_number );
+ break;
+ case EXTINCTION_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ media->setScatteringExtinction( f_number );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed1 != m_consumedTokens );
+ parseToken( '}' );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseDensity( PMDensity* density )
+{
+ int oldConsumed;
+
+ if( !parseToken( DENSITY_TOK, "density" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !density->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( density );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseInterior( PMInterior* interior )
+{
+ double f_number;
+ int i_number;
+ int oldConsumed;
+
+ if( !parseToken( INTERIOR_TOK, "interior" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !interior->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( interior );
+ switch( m_token )
+ {
+ case IOR_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ interior->enableIor( true );
+ interior->setIor( f_number );
+ }
+ break;
+ case CAUSTICS_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ interior->enableCaustics( true );
+ interior->setCaustics( f_number );
+ }
+ break;
+ case DISPERSION_TOK:
+ nextToken( );
+ if ( parseFloat( f_number ) )
+ {
+ interior->enableDispersion( true );
+ interior->setDispersion( f_number );
+ }
+ break;
+ case DISPERSION_SAMPLES_TOK:
+ nextToken( );
+ if ( parseInt( i_number ) )
+ {
+ interior->enableDispSamples( true );
+ interior->setDispSamples( i_number );
+ }
+ break;
+ case FADE_DISTANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ interior->enableFadeDistance( true );
+ interior->setFadeDistance( f_number );
+ }
+ break;
+ case FADE_POWER_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ interior->enableFadePower( true );
+ interior->setFadePower( f_number );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseMaterial( PMMaterial* material )
+{
+ int oldConsumed;
+
+ if( !parseToken( MATERIAL_TOK, "material" ) )
+ return false;
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !material->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( material );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSlope( PMSlope* slope )
+{
+ double f_number;
+
+ if( !parseToken( '<' ) )
+ return false;
+ if( !parseFloat( f_number ) )
+ return false;
+ slope->setHeight( f_number );
+ if( !parseToken( ',' ) )
+ return false;
+ if( !parseFloat( f_number ) )
+ return false;
+ slope->setSlope( f_number );
+ if( !parseToken( '>' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseGlobalSettings( PMGlobalSettings* globalsettings )
+{
+ PMColor color;
+ double f_number;
+ int i_number;
+ int oldConsumed;
+
+ // Initial global settings tokens
+ if( !parseToken( GLOBAL_SETTINGS_TOK, "global_settings" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse global settings tokens
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( globalsettings );
+
+ switch( m_token )
+ {
+ case ADC_BAILOUT_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ globalsettings->setAdcBailout( f_number );
+ break;
+ case AMBIENT_LIGHT_TOK:
+ nextToken( );
+ if( parseColor( color ) )
+ globalsettings->setAmbientLight( color );
+ break;
+ case ASSUMED_GAMMA_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ globalsettings->setAssumedGamma( f_number );
+ break;
+ case HF_GRAY_16_TOK:
+ nextToken( );
+ switch( m_token )
+ {
+ case ON_TOK:
+ globalsettings->setHfGray16( true );
+ nextToken( );
+ break;
+ case OFF_TOK:
+ globalsettings->setHfGray16( false );
+ nextToken( );
+ break;
+ default:
+ break;
+ }
+ break;
+ case IRID_WAVELENGTH_TOK:
+ nextToken( );
+ if( parseColor( color ) )
+ globalsettings->setIridWaveLength( color );
+ break;
+ case MAX_INTERSECTIONS_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ globalsettings->setMaxIntersections( i_number );
+ break;
+ case MAX_TRACE_LEVEL_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ globalsettings->setMaxTraceLevel( i_number );
+ break;
+ case NUMBER_OF_WAVES_TOK:
+ nextToken( );
+ if( parseInt( i_number ) )
+ globalsettings->setNumberWaves( i_number );
+ break;
+ case NOISE_GENERATOR_TOK:
+ nextToken( );
+ if ( parseInt( i_number ) )
+ globalsettings->setNoiseGenerator(
+ ( PMGlobalSettings::PMNoiseType ) ( i_number - 1 ) );
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseFinish( PMFinish* finish )
+{
+ PMColor color;
+ double f_number;
+ int oldConsumed, oldConsumed1;
+
+ // Initial finish tokens "finish {"
+ if( !parseToken( FINISH_TOK, "finish" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ // Parse a possible declare link identifier
+ if( m_token == ID_TOK )
+ {
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !finish->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+ }
+
+ // Parse finish tokens
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case AMBIENT_TOK:
+ nextToken( );
+ finish->enableAmbient( true );
+ if( parseColor( color ) )
+ finish->setAmbientColor( color );
+ break;
+ case DIFFUSE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableDiffuse( true );
+ finish->setDiffuse( f_number );
+ }
+ break;
+ case BRILLIANCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableBrilliance( true );
+ finish->setBrilliance( f_number );
+ }
+ break;
+ case PHONG_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enablePhong( true );
+ finish->setPhong( f_number );
+ }
+ break;
+ case PHONG_SIZE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enablePhongSize( true );
+ finish->setPhongSize( f_number );
+ }
+ break;
+ case METALLIC_TOK:
+ nextToken( );
+ finish->enableMetallic( true );
+ finish->setMetallic( 1.0 );
+ if( parseFloat( f_number, true ) )
+ finish->setMetallic( f_number );
+ break;
+ case SPECULAR_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableSpecular( true );
+ finish->setSpecular( f_number );
+ }
+ break;
+ case ROUGHNESS_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableRoughness( true );
+ finish->setRoughness( f_number );
+ }
+ break;
+ case CRAND_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableCrand( true );
+ finish->setCrand( f_number );
+ }
+ break;
+ case CONSERVE_ENERGY_TOK:
+ nextToken( );
+ finish->setConserveEnergy( parseBool( ) );
+ break;
+ case REFLECTION_TOK:
+ nextToken( );
+ finish->enableReflection( true );
+ if( !parseToken( '{' ) )
+ {
+ printError( i18n( "Using Old Reflection Syntax" ) );
+ if( parseColor( color ) )
+ finish->setReflectionColor( color );
+ }
+ else if( parseColor( color ) )
+ {
+ if( parseToken( ',' ) )
+ {
+ finish->enableReflectionMin( true );
+ finish->setReflectionMinColor( color );
+ if( parseColor( color ) )
+ finish->setReflectionColor( color );
+ else
+ return false;
+ }
+ else
+ finish->setReflectionColor( color );
+
+ do
+ {
+ oldConsumed1 = m_consumedTokens;
+ switch( m_token )
+ {
+ case FRESNEL_TOK:
+ nextToken( );
+ finish->setReflectionFresnel( parseBool( ) );
+ break;
+ case FALLOFF_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableRefFalloff( true );
+ finish->setReflectionFalloff( f_number );
+ }
+ break;
+ case EXPONENT_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ {
+ finish->enableRefExponent( true );
+ finish->setReflectionExponent( f_number );
+ }
+ break;
+ case METALLIC_TOK:
+ nextToken( );
+ if ( parseFloat( f_number ) )
+ {
+ finish->enableRefMetallic( true );
+ finish->setReflectionMetallic( f_number );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed1 != m_consumedTokens );
+ parseToken( '}' );
+ }
+ else
+ return false;
+ break;
+ case REFLECTION_EXPONENT_TOK:
+ nextToken( );
+ if ( parseFloat( f_number ) )
+ {
+ finish->enableRefExponent( true );
+ finish->setReflectionExponent( f_number );
+ }
+ break;
+ case IRID_TOK:
+ nextToken( );
+ parseToken( '{' );
+ finish->setIrid( true );
+ if( parseFloat( f_number ) )
+ finish->setIridAmount( f_number );
+ do
+ {
+ oldConsumed1 = m_consumedTokens;
+ switch( m_token )
+ {
+ case THICKNESS_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ finish->setIridThickness( f_number );
+ break;
+ case TURBULENCE_TOK:
+ nextToken( );
+ if( parseFloat( f_number ) )
+ finish->setIridTurbulence( f_number );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed1 != m_consumedTokens );
+ parseToken( '}' );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseDeclare( PMDeclare* decl )
+{
+ PMObject* child = 0;
+ PMTexture* texture = 0;
+ bool error = false;
+
+ switch( m_token )
+ {
+ case OBJECT_TOK:
+ error = !parseObject( decl );
+ break;
+ // finite solid
+ case BLOB_TOK:
+ child = new PMBlob( m_pPart );
+ error = !parseBlob( ( PMBlob* ) child );
+ break;
+ case BOX_TOK:
+ child = new PMBox( m_pPart );
+ error = !parseBox( ( PMBox* ) child );
+ break;
+ case CONE_TOK:
+ child = new PMCone( m_pPart );
+ error = !parseCone( ( PMCone* ) child );
+ break;
+ case CYLINDER_TOK:
+ child = new PMCylinder( m_pPart );
+ error = !parseCylinder( ( PMCylinder* ) child );
+ break;
+ case HEIGHT_FIELD_TOK:
+ child = new PMHeightField( m_pPart );
+ error = !parseHeightField( ( PMHeightField* ) child );
+ break;
+ case JULIA_FRACTAL_TOK:
+ child = new PMJuliaFractal( m_pPart );
+ error = !parseJuliaFractal( ( PMJuliaFractal* ) child );
+ break;
+ case LATHE_TOK:
+ child = new PMLathe( m_pPart );
+ error = !parseLathe( ( PMLathe* ) child );
+ break;
+ case PRISM_TOK:
+ child = new PMPrism( m_pPart );
+ error = !parsePrism( ( PMPrism* ) child );
+ break;
+ case SPHERE_TOK:
+ child = new PMSphere( m_pPart );
+ error = !parseSphere( ( PMSphere* ) child );
+ break;
+ case SUPERELLIPSOID_TOK:
+ child = new PMSuperquadricEllipsoid( m_pPart );
+ error = !parseSqe( ( PMSuperquadricEllipsoid* ) child );
+ break;
+ case SOR_TOK:
+ child = new PMSurfaceOfRevolution( m_pPart );
+ error = !parseSor( ( PMSurfaceOfRevolution* ) child );
+ break;
+ case TEXT_TOK:
+ child = new PMText( m_pPart );
+ error = !parseText( ( PMText* ) child );
+ break;
+ case TORUS_TOK:
+ child = new PMTorus( m_pPart );
+ error = !parseTorus( ( PMTorus* ) child );
+ break;
+ // finite patch
+ case BICUBIC_PATCH_TOK:
+ child = new PMBicubicPatch( m_pPart );
+ error = !parseBicubicPatch( ( PMBicubicPatch* ) child );
+ break;
+ case DISC_TOK:
+ child = new PMDisc( m_pPart );
+ error = !parseDisc( ( PMDisc* ) child );
+ break;
+ case TRIANGLE_TOK:
+ case SMOOTH_TRIANGLE_TOK:
+ child = new PMTriangle( m_pPart );
+ error = !parseTriangle( ( PMTriangle* ) child );
+ break;
+ // infinite solid
+ case PLANE_TOK:
+ child = new PMPlane( m_pPart );
+ error = !parsePlane( ( PMPlane* ) child );
+ break;
+ case QUADRIC_TOK:
+ case CUBIC_TOK:
+ case QUARTIC_TOK:
+ case POLY_TOK:
+ child = new PMPolynom( m_pPart );
+ error = !parsePolynom( ( PMPolynom* ) child );
+ break;
+ // csg
+ case UNION_TOK:
+ case DIFFERENCE_TOK:
+ case INTERSECTION_TOK:
+ case MERGE_TOK:
+ child = new PMCSG( m_pPart );
+ error = !parseCSG( ( PMCSG* ) child );
+ break;
+ // textures
+ case TEXTURE_TOK:
+ while( m_token == TEXTURE_TOK )
+ {
+ texture = new PMTexture( m_pPart );
+ if( !parseTexture( texture ) )
+ error = true;
+ if( !insertChild( texture, decl ) )
+ {
+ delete texture;
+ texture = 0;
+ }
+ }
+ break;
+ case PIGMENT_TOK:
+ child = new PMPigment( m_pPart );
+ error = !parsePigment( ( PMPigment* ) child );
+ break;
+ case NORMAL_TOK:
+ child = new PMNormal( m_pPart );
+ error = !parseNormal( ( PMNormal* ) child );
+ break;
+ case FINISH_TOK:
+ child = new PMFinish( m_pPart );
+ error = !parseFinish( ( PMFinish* ) child );
+ break;
+ case TEXTURE_MAP_TOK:
+ child = new PMTextureMap( m_pPart );
+ error = !parseTextureMap( ( PMTextureMap* ) child );
+ break;
+ case PIGMENT_MAP_TOK:
+ child = new PMPigmentMap( m_pPart );
+ error = !parsePigmentMap( ( PMPigmentMap* ) child );
+ break;
+ case COLOR_MAP_TOK:
+ case COLOUR_MAP_TOK:
+ child = new PMColorMap( m_pPart );
+ error = !parseColorMap( ( PMColorMap* ) child );
+ break;
+ case NORMAL_MAP_TOK:
+ child = new PMNormalMap( m_pPart );
+ error = !parseNormalMap( ( PMNormalMap* ) child );
+ break;
+ case SLOPE_MAP_TOK:
+ child = new PMSlopeMap( m_pPart );
+ error = !parseSlopeMap( ( PMSlopeMap* ) child );
+ break;
+ case DENSITY_MAP_TOK:
+ child = new PMDensityMap( m_pPart );
+ error = !parseDensityMap( ( PMDensityMap* ) child );
+ break;
+ case INTERIOR_TOK:
+ child = new PMInterior( m_pPart );
+ error = !parseInterior( ( PMInterior* ) child );
+ break;
+ case MEDIA_TOK:
+ child = new PMMedia( m_pPart );
+ error = !parseMedia( ( PMMedia* ) child );
+ break;
+ case DENSITY_TOK:
+ child = new PMDensity( m_pPart );
+ error = !parseDensity( ( PMDensity* ) child );
+ break;
+ case MATERIAL_TOK:
+ child = new PMMaterial( m_pPart );
+ error = !parseMaterial( ( PMMaterial* ) child );
+ break;
+ case SKY_SPHERE_TOK:
+ child = new PMSkySphere( m_pPart );
+ error = !parseSkySphere( ( PMSkySphere* ) child );
+ break;
+ case RAINBOW_TOK:
+ child = new PMRainbow( m_pPart );
+ error = !parseRainbow( ( PMRainbow* ) child );
+ break;
+ case FOG_TOK:
+ child = new PMFog( m_pPart );
+ error = !parseFog( ( PMFog* ) child );
+ break;
+ // misc
+ case LIGHT_SOURCE_TOK:
+ child = new PMLight( m_pPart );
+ error = !parseLight( ( PMLight* ) child );
+ break;
+ case ISOSURFACE_TOK:
+ child = new PMIsoSurface( m_pPart );
+ error = !parseIsoSurface( ( PMIsoSurface* ) child );
+ break;
+ case PHOTONS_TOK:
+ child = new PMPhotons( m_pPart );
+ error = !parsePhotons( ( PMPhotons* ) child );
+ break;
+ case LIGHT_GROUP_TOK:
+ child = new PMLightGroup( m_pPart );
+ error = !parseLightGroup( ( PMLightGroup* ) child );
+ break;
+ case INTERIOR_TEXTURE_TOK:
+ child = new PMInteriorTexture( m_pPart );
+ error = !parseInteriorTexture( ( PMInteriorTexture* ) child );
+ break;
+ case SPHERE_SWEEP_TOK:
+ child = new PMSphereSweep( m_pPart );
+ error = !parseSphereSweep( ( PMSphereSweep* ) child );
+ break;
+ case MESH_TOK:
+ child = new PMMesh( m_pPart );
+ error = !parseMesh( ( PMMesh* ) child );
+ break;
+ }
+
+ if( child )
+ {
+ if( !insertChild( child, decl ) )
+ {
+ delete child;
+ child = 0;
+ }
+ }
+ return !error;
+}
+
+bool PMPovrayParser::parseObject( PMCompositeObject* parent )
+{
+ PMObject* child;
+ bool error = false;
+ if( !parseToken( OBJECT_TOK, "object" ) )
+ return false;
+
+ if( parseToken( '{' ) )
+ {
+ switch( m_token )
+ {
+ case ID_TOK:
+ child = new PMObjectLink( m_pPart );
+ error = !parseObjectLink( ( PMObjectLink* ) child );
+ if( !insertChild( child, parent ) )
+ delete child;
+ break;
+ default:
+ {
+ PMObject* lastChild = 0;
+ if( parent )
+ lastChild = parent->lastChild( );
+ else
+ lastChild = m_pResultList->last( );
+
+ error = !parseChildObjects( parent, 1 );
+ if( !error )
+ {
+ PMObject* newLast = 0;
+ if( parent )
+ newLast = parent->lastChild( );
+ else
+ newLast = m_pResultList->last( );
+
+ if( newLast && ( newLast != lastChild ) &&
+ newLast->isA( "CompositeObject" ) )
+ {
+ // one child was parsed
+ // append all following objects
+ error = !parseChildObjects( ( PMCompositeObject* ) newLast );
+ }
+ else
+ {
+ printError( i18n( "One graphical object expected" ) );
+ error = true;
+ }
+ }
+ break;
+ }
+ }
+ if( !parseToken( '}' ))
+ error = true;
+ }
+ else
+ error = true;
+ return !error;
+}
+
+bool PMPovrayParser::parseObjectLink( PMObjectLink* link )
+{
+ int oldConsumed;
+
+ if( m_token != ID_TOK )
+ {
+ printExpected( "identifier", m_pScanner->sValue( ) );
+ return false;
+ }
+
+ QString id( m_pScanner->sValue( ) );
+ PMDeclare* decl = checkLink( id );
+ if( decl )
+ {
+ if( !link->setLinkedObject( decl ) )
+ printError( i18n( "Wrong declare type" ) );
+ }
+ nextToken( );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( link );
+ parseObjectModifiers( link );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ return true;
+}
+
+bool PMPovrayParser::parseIsoSurface( PMIsoSurface* iso )
+{
+ PMVector vector;
+ double f;
+ int i;
+ int oldConsumed;
+
+ if( !parseToken( ISOSURFACE_TOK, "isosurface" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( iso );
+ parseObjectModifiers( iso );
+
+ switch( m_token )
+ {
+ case FUNCTION_TOK:
+ nextToken( );
+ if( m_token != '{' )
+ {
+ printExpected( '{', m_pScanner->sValue( ) );
+ return false;
+ }
+
+ m_pScanner->scanFunction( );
+ nextToken( );
+ if( m_token != FUNCTION_TOK )
+ return false;
+ iso->setFunction( QString( m_pScanner->sValue( ) ).simplifyWhiteSpace( ) );
+
+ nextToken( );
+ parseToken( '}' );
+
+ break;
+ case CONTAINED_BY_TOK:
+ nextToken( );
+
+ if( !parseToken( '{' ) )
+ return false;
+
+ if( m_token == BOX_TOK )
+ {
+ iso->setContainedBy( PMIsoSurface::Box );
+ nextToken( );
+ parseToken( '{' );
+ if( parseVector( vector ) )
+ iso->setCorner1( vector );
+ parseToken( ',' );
+ if( parseVector( vector ) )
+ iso->setCorner2( vector );
+ if( !parseToken( '}' ) )
+ return false;
+ }
+ else if( m_token == SPHERE_TOK )
+ {
+ iso->setContainedBy( PMIsoSurface::Sphere );
+ nextToken( );
+ parseToken( '{' );
+ if( parseVector( vector ) )
+ iso->setCenter( vector );
+ parseToken( ',' );
+ if( parseFloat( f ) )
+ iso->setRadius( f );
+ if( !parseToken( '}' ) )
+ return false;
+ }
+ else
+ {
+ printUnexpected( m_pScanner->sValue( ) );
+ return false;
+ }
+
+ if( !parseToken( '}' ) )
+ return false;
+ break;
+ case THRESHOLD_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ iso->setThreshold( f );
+ break;
+ case ACCURACY_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ iso->setAccuracy( f );
+ break;
+ case MAX_GRADIENT_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ iso->setMaxGradient( f );
+ break;
+ case EVALUATE_TOK:
+ nextToken( );
+ iso->setEvaluate( true );
+ if( parseFloat( f ) )
+ {
+ iso->setEvaluateValue( 0, f );
+ if( parseToken( ',' ) && parseFloat( f ) )
+ {
+ iso->setEvaluateValue( 1, f );
+ if( parseToken( ',' ) && parseFloat( f ) )
+ iso->setEvaluateValue( 2, f );
+ }
+ }
+ break;
+ case OPEN_TOK:
+ nextToken( );
+ iso->setOpen( true );
+ break;
+ case MAX_TRACE_TOK:
+ nextToken( );
+ if( parseInt( i ) )
+ iso->setMaxTrace( i );
+ break;
+ case ALL_INTERSECTIONS_TOK:
+ nextToken( );
+ iso->setAllIntersections( true );
+ break;
+ default:
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseRadiosity( PMRadiosity* rad )
+{
+ double f;
+ int i;
+ int oldConsumed;
+
+
+ if( !parseToken( RADIOSITY_TOK, "radiosity" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case ADC_BAILOUT_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setAdcBailout( f );
+ break;
+ case ALWAYS_SAMPLE_TOK:
+ nextToken( );
+ rad->setAlwaysSample( parseBool( ) );
+ break;
+ case BRIGHTNESS_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setBrightness( f );
+ break;
+ case COUNT_TOK:
+ nextToken( );
+ if( parseInt( i ) )
+ rad->setCount( i );
+ break;
+ case ERROR_BOUND_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setErrorBound( f );
+ break;
+ case GRAY_THRESHOLD_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setGrayThreshold( f );
+ break;
+ case LOW_ERROR_FACTOR_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setLowErrorFactor( f );
+ break;
+ case MAX_SAMPLE_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ rad->setMaxSample( f );
+ break;
+ case MEDIA_TOK:
+ nextToken( );
+ rad->setMedia( parseBool( ) );
+ break;
+ case MINIMUM_REUSE_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setMinimumReuse( f );
+ break;
+ case NEAREST_COUNT_TOK:
+ nextToken( );
+ if( parseInt( i ) )
+ rad->setNearestCount( i );
+ break;
+ case NORMAL_TOK:
+ nextToken( );
+ rad->setNormal( parseBool( ) );
+ break;
+ case PRETRACE_START_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setPretraceStart( f );
+ break;
+ case PRETRACE_END_TOK:
+ nextToken( );
+ if( parseFloat( f ) )
+ rad->setPretraceEnd( f );
+ break;
+ case RECURSION_LIMIT_TOK:
+ nextToken( );
+ if( parseInt( i) )
+ rad->setRecursionLimit( i );
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseGlobalPhotons( PMGlobalPhotons* gp )
+{
+ double f;
+ int i;
+ int oldConsumed;
+
+
+ if( !parseToken( PHOTONS_TOK, "photons" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case SPACING_TOK:
+ gp->setNumberType( PMGlobalPhotons::Spacing );
+ nextToken( );
+ if ( parseFloat( f ) )
+ gp->setSpacing( f );
+ break;
+ case COUNT_TOK:
+ gp->setNumberType( PMGlobalPhotons::Count );
+ nextToken( );
+ if ( parseInt( i ) )
+ gp->setCount( i );
+ break;
+ case GATHER_TOK:
+ nextToken( );
+ if ( parseInt( i ) )
+ {
+ gp->setGatherMin( i );
+ if ( parseToken( ',' ) && parseInt( i ) )
+ gp->setGatherMax( i );
+ }
+ break;
+ case MEDIA_TOK:
+ nextToken( );
+ if ( parseInt( i ) )
+ {
+ gp->setMediaMaxSteps( i );
+ if ( parseToken( ',' ) && parseFloat( f ) )
+ gp->setMediaFactor( f );
+ }
+ case JITTER_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ gp->setJitter( f );
+ break;
+ case MAX_TRACE_LEVEL_TOK:
+ nextToken( );
+ gp->setMaxTraceLevelGlobal( false );
+ if ( parseInt( i ) )
+ gp->setMaxTraceLevel( i );
+ break;
+ case ADC_BAILOUT_TOK:
+ nextToken( );
+ gp->setAdcBailoutGlobal( false );
+ if ( parseFloat( f ) )
+ gp->setAdcBailout( f );
+ break;
+ case AUTOSTOP_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ gp->setAutostop( f );
+ break;
+ case EXPAND_THRESHOLDS_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ {
+ gp->setExpandIncrease( f );
+ if ( parseToken( ',' ) && parseInt( i ) )
+ gp->setExpandMin( i );
+ }
+ break;
+ case RADIUS_TOK:
+ nextToken( );
+ if ( parseFloat( f ) )
+ {
+ gp->setRadiusGather( f );
+ if ( parseToken( ',' ) && parseFloat( f ) )
+ {
+ gp->setRadiusGatherMulti( f );
+ if ( parseToken( ',' ) && parseFloat( f ) )
+ {
+ gp->setRadiusMedia( f );
+ if ( parseToken( ',' ) && parseFloat( f ) )
+ gp->setRadiusMediaMulti( f );
+ }
+ }
+ }
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parsePhotons( PMPhotons* p )
+{
+ double f;
+ int oldConsumed;
+
+ if( !parseToken( PHOTONS_TOK, "photons" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ p->setTarget( false );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ switch( m_token )
+ {
+ case TARGET_TOK:
+ nextToken( );
+ p->setTarget( true );
+ if ( parseFloat( f ) )
+ p->setSpacingMulti( f );
+ break;
+ case REFRACTION_TOK:
+ nextToken( );
+ p->setRefraction( parseBool( ) );
+ break;
+ case REFLECTION_TOK:
+ nextToken( );
+ p->setReflection( parseBool( ) );
+ break;
+ case COLLECT_TOK:
+ nextToken( );
+ p->setCollect( parseBool( ) );
+ break;
+ case PASS_THROUGH_TOK:
+ nextToken( );
+ p->setPassThrough( parseBool( ) );
+ break;
+ case AREA_LIGHT_TOK:
+ nextToken( );
+ p->setAreaLight( parseBool( ) );
+ break;
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseLightGroup( PMLightGroup* lg )
+{
+ int oldConsumed;
+
+ if ( !parseToken( LIGHT_GROUP_TOK, "light_group" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if ( m_token == GLOBAL_LIGHTS_TOK )
+ {
+ nextToken( );
+ lg->setGlobalLights( parseBool( ) );
+ }
+ else
+ {
+ parseChildObjects( lg );
+ parseObjectModifiers( lg );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseInteriorTexture( PMInteriorTexture* it )
+{
+ int oldConsumed;
+
+ if( !parseToken( INTERIOR_TEXTURE_TOK, "interior_texture" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ parseChildObjects( it );
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseSphereSweep( PMSphereSweep* ss )
+{
+ int oldConsumed, numspheres;
+ QValueList<PMVector> points;
+ QValueList<double> radii;
+ PMVector point;
+ double f;
+
+ if( !parseToken( SPHERE_SWEEP_TOK, "sphere_sweep" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ nextToken( );
+ switch ( m_token )
+ {
+ case LINEAR_SPLINE_TOK:
+ ss->setSplineType( PMSphereSweep::LinearSpline );
+ break;
+ case B_SPLINE_TOK:
+ ss->setSplineType( PMSphereSweep::BSpline );
+ break;
+ case CUBIC_SPLINE_TOK:
+ ss->setSplineType( PMSphereSweep::CubicSpline );
+ break;
+ default:
+ return false;
+ }
+
+ if ( !parseInt( numspheres ) )
+ return false;
+
+ for ( int i = 0; i < numspheres; ++i )
+ {
+ if ( !parseVector( point ) )
+ return false;
+ points.append( point );
+ if ( !parseToken( ',' ) )
+ return false;
+ if ( !parseFloat( f ) )
+ return false;
+ radii.append( f );
+ }
+
+ ss->setPoints( points );
+ ss->setRadii( radii );
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if ( m_token == TOLERANCE_TOK )
+ {
+ nextToken( );
+ if ( !parseFloat( f ) )
+ return false;
+ ss->setTolerance( f );
+ }
+ else
+ {
+ parseObjectModifiers( ss );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
+
+bool PMPovrayParser::parseMesh( PMMesh* m )
+{
+ int oldConsumed;
+ PMVector vector;
+
+ if( !parseToken( MESH_TOK, "mesh" ) )
+ return false;
+ if( !parseToken( '{' ) )
+ return false;
+
+ do
+ {
+ oldConsumed = m_consumedTokens;
+ if ( m_token == HIERARCHY_TOK )
+ {
+ nextToken( );
+ m->setHierarchy( parseBool( ) );
+ }
+ else if ( m_token == INSIDE_VECTOR_TOK )
+ {
+ nextToken( );
+ if ( !parseVector( vector ) )
+ return false;
+ m->enableInsideVector( true );
+ m->setInsideVector( vector );
+ }
+ else
+ {
+ parseChildObjects( m );
+ parseObjectModifiers( m );
+ }
+ }
+ while( oldConsumed != m_consumedTokens );
+
+ if( !parseToken( '}' ) )
+ return false;
+
+ return true;
+}
diff --git a/kpovmodeler/pmpovrayparser.h b/kpovmodeler/pmpovrayparser.h
new file mode 100644
index 00000000..b41beaf9
--- /dev/null
+++ b/kpovmodeler/pmpovrayparser.h
@@ -0,0 +1,534 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPOVRAYPARSER_H
+#define PMPOVRAYPARSER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmparser.h"
+#include "pmcomment.h"
+#include "pmvector.h"
+
+class PMCompositeObject;
+class PMGraphicalObject;
+class PMBox;
+class PMSphere;
+class PMCylinder;
+class PMCone;
+class PMTorus;
+class PMPlane;
+class PMPolynom;
+class PMDisc;
+class PMBlob;
+class PMBlobCylinder;
+class PMBlobSphere;
+class PMBicubicPatch;
+class PMTriangle;
+class PMCSG;
+class PMHeightField;
+class PMText;
+class PMJuliaFractal;
+class PMLathe;
+class PMPrism;
+class PMSurfaceOfRevolution;
+class PMSuperquadricEllipsoid;
+class PMScale;
+class PMRotate;
+class PMTranslate;
+class PMBoundedBy;
+class PMClippedBy;
+class PMPovrayMatrix;
+class PMCamera;
+class PMLight;
+class PMLooksLike;
+class PMProjectedThrough;
+class PMColor;
+class PMTexture;
+class PMPattern;
+class PMBlendMapModifiers;
+class PMWarp;
+class PMPigment;
+class PMNormal;
+class PMTextureMap;
+class PMPigmentMap;
+class PMColorMap;
+class PMNormalMap;
+class PMBumpMap;
+class PMMaterialMap;
+class PMSlopeMap;
+class PMDensityMap;
+class PMListPattern;
+class PMTextureList;
+class PMPigmentList;
+class PMColorList;
+class PMNormalList;
+class PMDensityList;
+class PMImageMap;
+class PMSlope;
+class PMFinish;
+class PMInterior;
+class PMMedia;
+class PMDensity;
+class PMMaterial;
+class PMSkySphere;
+class PMRainbow;
+class PMFog;
+class PMDeclare;
+class PMObjectLink;
+class PMGlobalSettings;
+
+class PMIsoSurface;
+class PMRadiosity;
+class PMGlobalPhotons;
+class PMPhotons;
+class PMLightGroup;
+class PMInteriorTexture;
+class PMSphereSweep;
+class PMMesh;
+
+/**
+ * Parser that parses povray code.
+ *
+ * All parse functions return false or 0 if an error occurred and the parse
+ * function couldn't recover.
+ */
+class PMPovrayParser : public PMParser
+{
+public:
+ /**
+ * Parser that parses the device
+ */
+ PMPovrayParser( PMPart* part, QIODevice* device );
+ /**
+ * Parser that parses the byte array
+ */
+ PMPovrayParser( PMPart* part, const QByteArray& array );
+ /**
+ * Deletes the parser
+ */
+ virtual ~PMPovrayParser( );
+
+protected:
+ /**
+ * Top level parse function
+ */
+ virtual void topParse( );
+
+private:
+ /**
+ * Initializes the parser
+ */
+ void init( );
+
+ /**
+ * Sets m_token to the next token
+ */
+ void nextToken( );
+
+ /**
+ * Returns true if the current token is ON_TOK, TRUE_TOK or YES_TOK
+ */
+ bool isTrue( ) const;
+ /**
+ * Returns true if the current token is OFF_TOK, FALSE_TOK or NO_TOK
+ */
+ bool isFalse( ) const;
+ /**
+ * Returns true if the next token is no bool value or one of the
+ * ON, TRUE or YES tokens
+ */
+ bool parseBool( );
+
+
+ /**
+ * Looks for child objects, parses them and appends them to the parent
+ * object. If parent is 0, all objects are appended to the result list.
+ *
+ * If max is > 0, then the maximum number of parsed objects is max.
+ *
+ * Returns true if there where no objects or parsing was successful.
+ */
+ bool parseChildObjects( PMCompositeObject* parent, int max = -1 );
+
+
+ /**
+ * Parses the token t.
+ *
+ * If the next token is not t, it appends an error to the messages
+ * and returns false.
+ *
+ * If t is not a single character token, set tokenName to the token
+ * name (like "box", "sphere" ...)
+ */
+ bool parseToken( int t, const QString& tokenName = QString::null );
+
+ /**
+ * Parses an item of a vector, float or color expression
+ */
+ bool parseNumericItem( PMValue& v, bool checkForBool = false );
+ /**
+ * Parse function for a vector literal <x, y, z, ...>
+ */
+ bool parseVectorLiteral( PMVector& v );
+ /**
+ * Parses a vector, float or color expression
+ */
+ bool parseNumericExpression( PMValue& v, bool checkForBool = false );
+
+ /**
+ * parses a vector and float expression and returns a vector
+ * of size s
+ */
+ bool parseVector( PMVector& v, unsigned int s=3 );
+ /**
+ * parses a vector and float expression and returns the
+ * float value or the first coordinate of the vector
+ */
+ bool parseFloat( double& d, bool suppressError = false );
+ /**
+ * parses a float or int value and rounds if necessary
+ */
+ bool parseInt( int& d );
+ /**
+ * parses a color expression
+ */
+ bool parseColor( PMColor& c );
+
+ /**
+ * Parse function for object modifiers
+ */
+ bool parseObjectModifiers( PMGraphicalObject* obj );
+
+ /**
+ * Parse function for cvs objects
+ */
+ bool parseCSG( PMCSG* csg );
+
+ /**
+ * Parse function for box objects
+ */
+ bool parseBox( PMBox* box );
+ /**
+ * Parse function for box objects
+ */
+ bool parseSphere( PMSphere* sphere );
+ /**
+ * Parse function for cylinder objects
+ */
+ bool parseCylinder( PMCylinder* pNewCyl );
+ /**
+ * Parse function for cone objects
+ */
+ bool parseCone( PMCone* pNewCone );
+ /**
+ * Parse function for torus objects
+ */
+ bool parseTorus( PMTorus* pNewTorus );
+
+ /**
+ * Parse function for blob objects
+ */
+ bool parseBlob( PMBlob* pNewBlob );
+ /**
+ * Parse function for blob sphere components
+ */
+ bool parseBlobSphere( PMBlobSphere* pNewBlobSphere );
+ /**
+ * Parse function for blob cylinder components
+ */
+ bool parseBlobCylinder( PMBlobCylinder* pNewBlobCylinder );
+ /**
+ * Parse function for old blob components
+ */
+ bool parseBlobComponent( PMBlobSphere* pNewBlobSphere );
+
+ /**
+ * Parse function for height fields
+ */
+ bool parseHeightField( PMHeightField* pNewHeightField );
+ /**
+ * Parse function for text objects
+ */
+ bool parseText( PMText* pNewText );
+ /**
+ * Parse function for julia fractals
+ */
+ bool parseJuliaFractal( PMJuliaFractal* pNewFractal );
+
+ /**
+ * Parse function for plane objects
+ */
+ bool parsePlane( PMPlane* pNewPlane );
+ /**
+ * Parse function for quadric, cubic, quartic and poly
+ */
+ bool parsePolynom( PMPolynom* pNewPoly );
+ /**
+ * Parse function for bicubic patch objects
+ */
+ bool parseBicubicPatch( PMBicubicPatch* pNewPatch );
+ /**
+ * Parse function for disks
+ */
+ bool parseDisc( PMDisc* pNewDisc );
+ /**
+ * Parse function for triangles
+ */
+ bool parseTriangle( PMTriangle* pNewTriangle );
+
+ /**
+ * Parse function for lathes
+ */
+ bool parseLathe( PMLathe* pNewLathe );
+ /**
+ * Parse function for prisms
+ */
+ bool parsePrism( PMPrism* pNewPrism );
+ /**
+ * Parse function for surface of revolutions
+ */
+ bool parseSor( PMSurfaceOfRevolution* pNewSor );
+ /**
+ * Parse function for superquadric ellipsoid
+ */
+ bool parseSqe( PMSuperquadricEllipsoid* pNewSqe );
+
+ /**
+ * Parse function for scale commands
+ */
+ bool parseScale( PMScale* scale );
+ /**
+ * Parse function for rotate commands
+ */
+ bool parseRotate( PMRotate* rotate );
+ /**
+ * Parse function for translate commands
+ */
+ bool parseTranslate( PMTranslate* translate );
+ /**
+ * Parse function for matrix commands
+ */
+ bool parseMatrix( PMPovrayMatrix* matrix );
+
+ /**
+ * Parse function for bounded_by statements
+ */
+ bool parseBoundedBy( PMBoundedBy* bound );
+ /**
+ * Parse function for clipped_by statements
+ */
+ bool parseClippedBy( PMClippedBy* clipped );
+
+ /**
+ * Parse function for camera objects
+ */
+ bool parseCamera( PMCamera* camera );
+
+ /**
+ * Parse function for light objects
+ */
+ bool parseLight( PMLight* light );
+ /**
+ * Parse function for looks_like statement
+ */
+ bool parseLooksLike( PMLooksLike* ll );
+ /**
+ * Parse function for projected_through statement
+ */
+ bool parseProjectedThrough( PMProjectedThrough* ll );
+
+ /**
+ * Parse function for texture objects. If parseOuter is false, the parser
+ * won't search for the texture{} wrapper. This is useful inside a texture
+ * map.
+ */
+ bool parseTexture( PMTexture* pigment, bool parseOuter = true );
+ /**
+ * Parse function for pattern objects
+ */
+ bool parsePattern( PMPattern* pattern, bool normal = false );
+ /**
+ * Parse function for blend map modifier objects
+ */
+ bool parseBlendMapModifiers( PMBlendMapModifiers* blend );
+ /**
+ * Parse function for warp objects
+ */
+ bool parseWarp( PMWarp* pattern );
+ /**
+ * Parse function for pigment objects
+ */
+ bool parsePigment( PMPigment* pigment, bool parseOuter = true );
+ /**
+ * Parse function for normal objects
+ */
+ bool parseNormal( PMNormal* normal );
+ /**
+ * Parse function for texture map objects
+ */
+ bool parseTextureMap( PMTextureMap* textureMap );
+ /**
+ * Parse function for pigment map objects
+ */
+ bool parsePigmentMap( PMPigmentMap* pigmentMap );
+ /**
+ * Parse function for color map objects
+ */
+ bool parseColorMap( PMColorMap* colorMap );
+ /**
+ * Parse function for normal map objects
+ */
+ bool parseNormalMap( PMNormalMap* normalMap );
+ /**
+ * Parse function for bump map objects
+ */
+ bool parseBumpMap( PMBumpMap* bumpMap );
+ /**
+ * Parse function for material map objects
+ */
+ bool parseMaterialMap( PMMaterialMap* materialMap );
+ /**
+ * Parse function for slope map objects
+ */
+ bool parseSlopeMap( PMSlopeMap* slopeMap );
+ /**
+ * Parse function for density map objects
+ */
+ bool parseDensityMap( PMDensityMap* densityMap );
+ /**
+ * Parse function for image map objects
+ */
+ bool parseImageMap( PMImageMap* imageMap );
+ /**
+ * Parse function for slope objects
+ */
+ bool parseSlope( PMSlope* slope );
+ /**
+ * Parse function for texture list objects
+ */
+ bool parseTextureList( PMTextureList* textureList, int expectedItems );
+ /**
+ * Parse function for pigment list objects
+ */
+ bool parsePigmentList( PMPigmentList* pigmentList, int expectedItems );
+ /**
+ * Parse function for color list objects
+ */
+ bool parseColorList( PMColorList* colorList, int expectedItems );
+ /**
+ * Parse function for normal list objects
+ */
+ bool parseNormalList( PMNormalList* normalList, int expectedItems );
+ /**
+ * Parse function for density list objects
+ */
+ bool parseDensityList( PMDensityList* densityList, int expectedItems );
+ /**
+ * Parse function for finish objects
+ */
+ bool parseFinish( PMFinish* finish );
+ /**
+ * Parse function for interior objects
+ */
+ bool parseInterior( PMInterior* interior );
+ /**
+ * Parse function for media objects
+ */
+ bool parseMedia( PMMedia* media );
+ /**
+ * Parse function for density objects
+ */
+ bool parseDensity( PMDensity* density );
+ /**
+ * Parse function for material objects
+ */
+ bool parseMaterial( PMMaterial* material );
+
+ /**
+ * Parse function for sky sphere objects
+ */
+ bool parseSkySphere( PMSkySphere* sky );
+ /**
+ * Parse function for rainbow objects
+ */
+ bool parseRainbow( PMRainbow* rainbow );
+ /**
+ * Parse function for fog objects
+ */
+ bool parseFog( PMFog* fog );
+
+ /**
+ * Parse function for global settings
+ */
+ bool parseGlobalSettings( PMGlobalSettings* decl );
+ /**
+ * Parse function for declares
+ */
+ bool parseDeclare( PMDeclare* decl );
+ /**
+ * Parse function for object links
+ */
+ bool parseObjectLink( PMObjectLink* link );
+ /**
+ * Parse function for object keywords
+ */
+ bool parseObject( PMCompositeObject* parent );
+
+ // POV-Ray 3.5 objects
+ bool parseIsoSurface( PMIsoSurface* iso );
+ bool parseRadiosity( PMRadiosity* rad );
+ bool parseGlobalPhotons( PMGlobalPhotons* gp );
+ bool parsePhotons( PMPhotons* p );
+ bool parseLightGroup( PMLightGroup* lg );
+ bool parseInteriorTexture( PMInteriorTexture* it );
+ bool parseSphereSweep( PMSphereSweep * ss );
+ bool parseMesh( PMMesh* m );
+
+ /**
+ * The used scanner
+ */
+ PMScanner* m_pScanner;
+ /**
+ * The last scanned token
+ */
+ int m_token;
+
+ /**
+ * Number of consumed tokens.
+ */
+ int m_consumedTokens;
+
+ /**
+ * All comments are skipped during parsing and stored here
+ */
+ QPtrList<PMComment> m_skippedComments;
+ /**
+ * The last skipped comment text with special kpovmodeler tags*/
+ QString m_lastPMComment;
+ /**
+ * true if m_lastPMComment is empty
+ */
+ bool m_bLastPMCommentEmpty;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmpovrayrenderwidget.cpp b/kpovmodeler/pmpovrayrenderwidget.cpp
new file mode 100644
index 00000000..3cd44f20
--- /dev/null
+++ b/kpovmodeler/pmpovrayrenderwidget.cpp
@@ -0,0 +1,437 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovrayrenderwidget.h"
+#include "pmdefaults.h"
+#include "pmdebug.h"
+#include "pmdragwidget.h"
+
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kurl.h>
+#include <ktempfile.h>
+#include <qcolor.h>
+#include <qpainter.h>
+#include <qtextstream.h>
+#include <qdragobject.h>
+
+#ifdef KDE_NO_COMPAT
+#undef KDE_NO_COMPAT
+#endif
+
+#include <kapplication.h>
+
+QString PMPovrayRenderWidget::s_povrayCommand = c_defaultPovrayCommand;
+QStringList PMPovrayRenderWidget::s_libraryPaths;
+
+PMPovrayRenderWidget::PMPovrayRenderWidget( QWidget* parent, const char* name )
+ : PMDragWidget( parent, name )
+{
+ m_pProcess = 0;
+ m_bSuspended = false;
+ m_rcvHeader = false;
+ m_skipBytes = 0;
+ m_bPixmapUpToDate = false;
+ m_pTempFile = 0;
+
+ setBackgroundColor( QColor( 0, 0, 0 ) );
+}
+
+PMPovrayRenderWidget::~PMPovrayRenderWidget( )
+{
+ cleanup( );
+}
+
+bool PMPovrayRenderWidget::render( const QByteArray& scene,
+ const PMRenderMode& m,
+ const KURL& documentURL )
+{
+ cleanup( );
+
+ m_povrayOutput = "";
+ m_renderMode = m;
+
+ if( !scene.data( ) )
+ {
+ KMessageBox::sorry( this, i18n( "Can't render an empty scene.\n" ) );
+ return false;
+ }
+
+ // output to tmp file
+ m_pTempFile = new KTempFile( QString::null, ".pov" );
+ QDataStream* dstr = m_pTempFile->dataStream( );
+
+ if( ( m_pTempFile->status( ) != 0 ) || !dstr )
+ {
+ KMessageBox::sorry( this, i18n( "Couldn't write the scene to a temp file.\n" ) );
+ return false;
+ }
+
+ dstr->writeRawBytes( scene.data( ), scene.size( ) );
+ m_pTempFile->close( );
+
+ m_pProcess = new KProcess( );
+ connect( m_pProcess, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ SLOT( slotPovrayImage( KProcess*, char*, int ) ) );
+ connect( m_pProcess, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ SLOT( slotPovrayMessage( KProcess*, char*, int ) ) );
+ connect( m_pProcess, SIGNAL( processExited( KProcess* ) ),
+ SLOT( slotRenderingFinished( KProcess* ) ) );
+
+ *m_pProcess << s_povrayCommand;
+
+ QStringList::ConstIterator it;
+ QStringList args = m_renderMode.commandLineSwitches( );
+ for( it = args.begin( ); it != args.end( ); ++it )
+ *m_pProcess << *it;
+
+ for( it = s_libraryPaths.begin( ); it != s_libraryPaths.end( ); ++it )
+ {
+ QString path = *it;
+ if( path != QString( "/" ) )
+ if( path.right( 1 ) == QString( "/" ) )
+ path.truncate( path.length( ) - 1 );
+ *m_pProcess << ( QString( "+L" ) + path );
+ }
+ *m_pProcess << QString( "+I" ) + m_pTempFile->name( ) << "+O-" << "+FT"
+ << "+K0.0" << "+KFI1" << "+KFF1" << "+KI0.0" << "+KF0.0"
+ << "+SF1" << "+EF1" << "-KC" << "-D";
+
+#if ( ( KDE_VERSION_MAJOR == 2 ) && ( KDE_VERSION_MINOR >= 9 ) ) || ( KDE_VERSION_MAJOR == 3 )
+ if( !documentURL.isEmpty( ) && documentURL.isLocalFile( ) )
+ m_pProcess->setWorkingDirectory( documentURL.directory( ) );
+#endif
+
+ m_rcvHeader = true;
+ m_rcvHeaderBytes = 0;
+ m_rcvPixels = 0;
+ m_progress = 0;
+ m_numRestBytes = 0;
+ m_line = 0;
+ m_column = 0;
+ m_skipBytes = 0;
+
+ int width = m_renderMode.width( );
+ int height = m_renderMode.height( );
+
+ m_image.create( width, height, 32 );
+ m_image.setAlphaBuffer( m_renderMode.alpha( ) );
+ m_image.fill( qRgb( 0, 0, 0 ) );
+ m_bPixmapUpToDate = false;
+ repaint( );
+
+ if( !m_pProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ) )
+ {
+ KMessageBox::error( this, i18n( "Couldn't call povray.\n"
+ "Please check your installation "
+ "or set another povray command." ) );
+ delete m_pProcess;
+ m_pProcess = 0;
+ return false;
+ }
+
+ m_bSuspended = false;
+ return true;
+}
+
+void PMPovrayRenderWidget::killRendering( )
+{
+ if( m_pProcess )
+ {
+ if( m_bSuspended )
+ m_pProcess->kill( SIGCONT );
+ m_bSuspended = false;
+ m_pProcess->kill( );
+ }
+}
+
+void PMPovrayRenderWidget::suspendRendering( )
+{
+ if( m_pProcess )
+ {
+ m_bSuspended = true;
+ m_pProcess->kill( SIGSTOP );
+ }
+}
+
+void PMPovrayRenderWidget::resumeRendering( )
+{
+ if( m_pProcess )
+ {
+ m_pProcess->kill( SIGCONT );
+ m_bSuspended = false;
+ }
+}
+
+void PMPovrayRenderWidget::slotPovrayMessage( KProcess*,
+ char* buffer, int buflen )
+{
+ QString str;
+ str.setLatin1( buffer, buflen );
+ m_povrayOutput += str;
+ emit povrayMessage( str );
+}
+
+void PMPovrayRenderWidget::slotPovrayImage( KProcess*, char* buffer, int buflen )
+{
+ int index = 0;
+ int i;
+ int oldLine = m_line;
+
+ if( m_rcvHeader )
+ {
+ // receive targa header
+ while( ( m_rcvHeaderBytes < 18 ) && ( index < buflen ) )
+ {
+ m_header[m_rcvHeaderBytes] = ( unsigned char ) buffer[index];
+ m_rcvHeaderBytes++;
+ index++;
+ }
+
+ if( m_rcvHeaderBytes == 18 )
+ {
+ // complete targa header received
+ m_rcvHeader = false;
+ m_skipBytes = m_header[0]; // id length
+ m_bytespp = m_header[16] / 8;
+ }
+ }
+
+ if( m_skipBytes > 0 )
+ {
+ int skip = buflen - index;
+ if( skip > m_skipBytes )
+ skip = m_skipBytes;
+ m_skipBytes -= skip;
+ index += skip;
+ }
+
+ if( ( m_numRestBytes > 0 ) && ( index < buflen ) )
+ {
+ while( ( m_numRestBytes < m_bytespp ) && ( index < buflen ) )
+ {
+ m_restBytes[m_numRestBytes] = ( unsigned char ) buffer[index];
+ index++;
+ m_numRestBytes++;
+ }
+ if( m_numRestBytes == m_bytespp )
+ {
+ m_numRestBytes = 0;
+
+ if( m_bytespp == 4 )
+ setPixel( m_column, m_line,
+ qRgba( m_restBytes[2], m_restBytes[1],
+ m_restBytes[0], m_restBytes[3] ) );
+ else
+ setPixel( m_column, m_line,
+ qRgb( m_restBytes[2], m_restBytes[1], m_restBytes[0] ) );
+
+ m_column++;
+ m_rcvPixels++;
+ if( m_column == m_renderMode.width( ) )
+ {
+ m_column = 0;
+ m_line++;
+ }
+ }
+ }
+
+ if( index < buflen )
+ {
+ int num = ( buflen - index ) / m_bytespp;
+ for( i = 0; i < num; i++ )
+ {
+ if( m_bytespp == 4 )
+ setPixel( m_column, m_line,
+ qRgba( buffer[index+2], buffer[index+1],
+ buffer[index], buffer[index+3] ) );
+ else
+ setPixel( m_column, m_line,
+ qRgb( buffer[index+2], buffer[index+1],
+ buffer[index] ) );
+ index += m_bytespp;
+
+ m_column++;
+ m_rcvPixels++;
+ if( m_column == m_renderMode.width( ) )
+ {
+ m_column = 0;
+ m_line++;
+ }
+ }
+ }
+
+ if( index < buflen )
+ {
+ m_numRestBytes = buflen - index;
+ for( i = 0; i < m_numRestBytes; i++ )
+ {
+ m_restBytes[i] = buffer[index];
+ index++;
+ }
+ }
+
+ if( m_line != oldLine )
+ {
+ QPainter paint( this );
+ int offset = 0;
+ if( m_renderMode.subSection( ) )
+ {
+ double sr = m_renderMode.startRow( );
+ if( sr < 1 )
+ offset = ( int ) ( m_renderMode.height( ) * sr + 0.5 );
+ else
+ offset += ( int ) sr;
+ }
+ paint.drawImage( 0, offset + oldLine,
+ m_image.copy( 0, offset + oldLine, m_image.width( ), offset + m_line - oldLine ) );
+
+ emit lineFinished( m_line - 1 );
+ }
+
+ int oldProgress = m_progress;
+ int numPixels = 0;
+ if( m_renderMode.subSection( ) )
+ {
+ int sr = 0;
+ if( m_renderMode.startRow( ) < 1 )
+ sr = ( int ) ( m_renderMode.height( ) * m_renderMode.startRow( ) + 0.5 );
+ else
+ sr = ( int ) m_renderMode.startRow( );
+ int er = 0;
+ if( m_renderMode.endRow( ) < 1 )
+ er = ( int ) ( m_renderMode.height( ) * m_renderMode.endRow( ) + 0.5 );
+ else
+ er = ( int ) m_renderMode.endRow( );
+
+ numPixels = m_renderMode.width( ) * ( er - sr );
+ }
+ else
+ numPixels = m_renderMode.width( ) * m_renderMode.height( );
+
+ m_progress = m_rcvPixels * 100 / numPixels;
+
+ if( m_progress != oldProgress )
+ emit progress( m_progress );
+ m_bPixmapUpToDate = false;
+}
+
+void PMPovrayRenderWidget::setPixel( int x, int y, uint c )
+{
+ if( m_renderMode.subSection( ) )
+ {
+ double sr = m_renderMode.startRow( );
+ if( sr < 1 )
+ y += ( int ) ( m_renderMode.height( ) * sr + 0.5 );
+ else
+ y += ( int ) sr;
+ }
+
+ if( x >= 0 && x < m_image.width( ) &&
+ y >= 0 && y < m_image.height( ) )
+ m_image.setPixel( x, y, c );
+}
+
+/**
+void PMPovrayRenderWidget::slotWroteStdin( KProcess* )
+{
+ if( m_pProcess )
+ m_pProcess->closeStdin( );
+ m_data.resize( 0 );
+}
+*/
+
+void PMPovrayRenderWidget::slotRenderingFinished( KProcess* )
+{
+ if( m_pProcess->normalExit( ) )
+ emit( finished( m_pProcess->exitStatus( ) ) );
+ else
+ emit( finished( -1000 ) );
+
+ cleanup( );
+}
+
+void PMPovrayRenderWidget::paintEvent( QPaintEvent* ev )
+{
+ if( !m_bPixmapUpToDate )
+ {
+ if( !m_image.isNull( ) )
+ m_pixmap.convertFromImage( m_image );
+ m_bPixmapUpToDate = true;
+ }
+ bitBlt( this, ev->rect( ).left( ), ev->rect( ).top( ),
+ &m_pixmap, ev->rect( ).left( ), ev->rect( ).top( ),
+ ev->rect( ).width( ), ev->rect( ).height( ), CopyROP );
+}
+
+void PMPovrayRenderWidget::cleanup( )
+{
+ if( m_pProcess )
+ delete m_pProcess;
+ m_pProcess = 0;
+ if( m_pTempFile )
+ {
+ m_pTempFile->unlink( );
+ delete m_pTempFile;
+ }
+ m_pTempFile = 0;
+}
+
+QSize PMPovrayRenderWidget::sizeHint( ) const
+{
+ QSize s;
+ if( m_image.isNull( ) )
+ s = QSize( 200, 200 );
+ else
+ s = m_image.size( );
+
+ return s.expandedTo( minimumSize( ) );
+}
+
+void PMPovrayRenderWidget::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Povray" );
+#if ( ( KDE_VERSION_MAJOR == 3 ) && ( KDE_VERSION_MINOR <= 1 ) )
+ cfg->writeEntry( "PovrayCommand", s_povrayCommand );
+ cfg->writeEntry( "LibraryPaths", s_libraryPaths );
+#else
+ cfg->writePathEntry( "PovrayCommand", s_povrayCommand );
+ cfg->writePathEntry( "LibraryPaths", s_libraryPaths );
+#endif
+}
+
+void PMPovrayRenderWidget::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Povray" );
+#if ( ( KDE_VERSION_MAJOR == 3 ) && ( KDE_VERSION_MINOR <= 1 ) )
+ s_povrayCommand = cfg->readEntry( "PovrayCommand", s_povrayCommand );
+ s_libraryPaths = cfg->readListEntry( "LibraryPaths" );
+#else
+ s_povrayCommand = cfg->readPathEntry( "PovrayCommand", s_povrayCommand );
+ s_libraryPaths = cfg->readPathListEntry( "LibraryPaths" );
+#endif
+}
+
+void PMPovrayRenderWidget::startDrag( )
+{
+ QImageDrag* d = new QImageDrag( m_image, this );
+ d->dragCopy( );
+}
+
+#include "pmpovrayrenderwidget.moc"
diff --git a/kpovmodeler/pmpovrayrenderwidget.h b/kpovmodeler/pmpovrayrenderwidget.h
new file mode 100644
index 00000000..23e30721
--- /dev/null
+++ b/kpovmodeler/pmpovrayrenderwidget.h
@@ -0,0 +1,177 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAYRENDERWIDGET_H
+#define PMPOVRAYRENDERWIDGET_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qcstring.h>
+#include <qimage.h>
+#include <qbuffer.h>
+#include <qstringlist.h>
+
+#include "pmrendermode.h"
+#include "pmdragwidget.h"
+
+class KProcess;
+class KConfig;
+class KURL;
+class KTempFile;
+
+/**
+ * Widget that calls povray to render a scene and
+ * displays the output.
+ */
+class PMPovrayRenderWidget : public PMDragWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Standard constructor
+ */
+ PMPovrayRenderWidget( QWidget* parent = 0, const char* name = 0 );
+ /**
+ * destructor
+ */
+ virtual ~PMPovrayRenderWidget( );
+
+ /**
+ * Starts rendering for the povray code in the byte array with
+ * render mode m.
+ * @see PMRenderMode
+ */
+ bool render( const QByteArray& scene, const PMRenderMode& m,
+ const KURL& documentURL );
+
+ /**
+ * Returns the povray text output
+ */
+ QString povrayOutput( ) const { return m_povrayOutput; }
+ /**
+ * Returns the rendered image
+ */
+ QImage image( ) const { return m_image; }
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+
+ /**
+ * Returns the povray command
+ */
+ static QString povrayCommand( ) { return s_povrayCommand; }
+ /**
+ * Sets the povray command
+ */
+ static void setPovrayCommand( const QString& c ) { s_povrayCommand = c; }
+ /**
+ * Returns the library paths
+ */
+ static QStringList povrayLibraryPaths( ) { return s_libraryPaths; }
+ /**
+ * Sets the library paths
+ */
+ static void setPovrayLibraryPaths( const QStringList& slist )
+ { s_libraryPaths = slist; }
+ virtual QSize sizeHint( ) const;
+
+ virtual void startDrag( );
+signals:
+ /**
+ * Emitted when rendering has finished
+ */
+ void finished( int exitStatus );
+ /**
+ * Provides progress information
+ */
+ void progress( int percent );
+ /**
+ * Provides progress imformation
+ */
+ void lineFinished( int line );
+ /**
+ * The povray output text
+ */
+ void povrayMessage( const QString& msg );
+
+public slots:
+ /**
+ * Kills rendering
+ */
+ void killRendering( );
+ /**
+ * Suspends rendering
+ */
+ void suspendRendering( );
+ /**
+ * Resumes rendering
+ */
+ void resumeRendering( );
+
+protected slots:
+ /**
+ * Receive povray messages
+ */
+ void slotPovrayMessage( KProcess* proc, char* buffer, int buflen );
+ /**
+ * Receive rendered image
+ */
+ void slotPovrayImage( KProcess* proc, char* buffer, int buflen );
+ /**
+ * Called when output has been written to the povray process
+ */
+ //void slotWroteStdin( KProcess* proc );
+ /**
+ * Called when the process has finished
+ */
+ void slotRenderingFinished( KProcess* proc );
+
+protected:
+ virtual void paintEvent( QPaintEvent* );
+
+private:
+ void setPixel( int x, int y, uint c );
+ void cleanup( );
+
+ KProcess* m_pProcess;
+ bool m_bSuspended;
+ PMRenderMode m_renderMode;
+ QImage m_image;
+ bool m_rcvHeader;
+ unsigned char m_header[18];
+ int m_rcvHeaderBytes;
+ int m_skipBytes;
+ int m_bytespp;
+ int m_rcvPixels;
+ int m_progress;
+ unsigned char m_restBytes[4];
+ int m_numRestBytes;
+ int m_line;
+ int m_column;
+ QPixmap m_pixmap;
+ bool m_bPixmapUpToDate;
+ QString m_povrayOutput;
+ KTempFile* m_pTempFile;
+
+ static QString s_povrayCommand;
+ static QStringList s_libraryPaths;
+};
+
+#endif
diff --git a/kpovmodeler/pmpovraysettings.cpp b/kpovmodeler/pmpovraysettings.cpp
new file mode 100644
index 00000000..0b2824ae
--- /dev/null
+++ b/kpovmodeler/pmpovraysettings.cpp
@@ -0,0 +1,308 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovraysettings.h"
+
+#include "pmdocumentationmap.h"
+#include "pmpovrayrenderwidget.h"
+#include "pmdefaults.h"
+#include "pmresourcelocator.h"
+#include "pmtext.h"
+
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qlistbox.h>
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+
+PMPovraySettings::PMPovraySettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ m_selectionIndex = 0;
+
+ QHBoxLayout* hlayout;
+ QVBoxLayout* vlayout;
+ QVBoxLayout* gvl;
+ QGroupBox* gb;
+
+ vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+
+ gb = new QGroupBox( i18n( "Povray Command" ), this );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+ hlayout = new QHBoxLayout( gvl );
+ hlayout->addWidget( new QLabel( i18n( "Command:" ), gb ) );
+ m_pPovrayCommand = new QLineEdit( gb );
+ hlayout->addWidget( m_pPovrayCommand );
+ m_pBrowsePovrayCommand = new QPushButton( gb );
+ m_pBrowsePovrayCommand->setPixmap( SmallIcon( "fileopen" ) );
+ connect( m_pBrowsePovrayCommand, SIGNAL( clicked( ) ),
+ SLOT( slotBrowsePovrayCommand( ) ) );
+ hlayout->addWidget( m_pBrowsePovrayCommand );
+ vlayout->addWidget( gb );
+
+ gb = new QGroupBox( i18n( "Povray User Documentation" ), this );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+ hlayout = new QHBoxLayout( gvl );
+ hlayout->addWidget( new QLabel( i18n( "Path:" ), gb ) );
+ m_pDocumentationPath = new QLineEdit( gb );
+ hlayout->addWidget( m_pDocumentationPath );
+ m_pBrowseDocumentationPath = new QPushButton( gb );
+ m_pBrowseDocumentationPath->setPixmap( SmallIcon( "fileopen" ) );
+ connect( m_pBrowseDocumentationPath, SIGNAL( clicked( ) ),
+ SLOT( slotBrowsePovrayDocumentation( ) ) );
+ hlayout->addWidget( m_pBrowseDocumentationPath );
+ vlayout->addWidget( gb );
+ hlayout = new QHBoxLayout( gvl );
+ hlayout->addWidget( new QLabel( i18n( "Version:" ), gb ) );
+ m_pDocumentationVersion = new QComboBox( false, gb );
+ QValueList<QString> versions = PMDocumentationMap::theMap( )->availableVersions( );
+ QValueListIterator<QString> it;
+ for( it = versions.begin( ); it != versions.end( ); ++it )
+ m_pDocumentationVersion->insertItem( *it );
+ hlayout->addWidget( m_pDocumentationVersion );
+ hlayout->addStretch( );
+
+ gb = new QGroupBox( i18n( "Library Paths" ), this );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+ hlayout = new QHBoxLayout( gvl );
+ m_pLibraryPaths = new QListBox( gb );
+ connect( m_pLibraryPaths, SIGNAL( highlighted( int ) ),
+ SLOT( slotPathSelected( int ) ) );
+ hlayout->addWidget( m_pLibraryPaths );
+
+ QVBoxLayout* bl = new QVBoxLayout( hlayout );
+ m_pAddLibraryPath = new QPushButton( i18n( "Add..." ), gb );
+ connect( m_pAddLibraryPath, SIGNAL( clicked( ) ), SLOT( slotAddPath( ) ) );
+ bl->addWidget( m_pAddLibraryPath );
+ m_pRemoveLibraryPath = new QPushButton( i18n( "Remove" ), gb );
+ connect( m_pRemoveLibraryPath, SIGNAL( clicked( ) ),
+ SLOT( slotRemovePath( ) ) );
+ bl->addWidget( m_pRemoveLibraryPath );
+ m_pChangeLibraryPath = new QPushButton( i18n( "Edit..." ), gb );
+ connect( m_pChangeLibraryPath, SIGNAL( clicked( ) ),
+ SLOT( slotEditPath( ) ) );
+ bl->addWidget( m_pChangeLibraryPath );
+ m_pLibraryPathUp = new QPushButton( i18n( "Up" ), gb );
+ connect( m_pLibraryPathUp, SIGNAL( clicked( ) ), SLOT( slotPathUp( ) ) );
+ bl->addWidget( m_pLibraryPathUp );
+ m_pLibraryPathDown = new QPushButton( i18n( "Down" ), gb );
+ connect( m_pLibraryPathDown, SIGNAL( clicked( ) ),
+ SLOT( slotPathDown( ) ) );
+ bl->addWidget( m_pLibraryPathDown );
+ bl->addStretch( 1 );
+ vlayout->addWidget( gb );
+
+ vlayout->addStretch( 1 );
+}
+
+void PMPovraySettings::displaySettings( )
+{
+ m_pPovrayCommand->setText( PMPovrayRenderWidget::povrayCommand( ) );
+ m_pDocumentationPath->setText( PMDocumentationMap::theMap( )->povrayDocumentationPath( ) );
+ int c = m_pDocumentationVersion->count( );
+ QString s = PMDocumentationMap::theMap( )->documentationVersion( );
+ int i;
+ for( i = 0; i < c; i++ )
+ if( m_pDocumentationVersion->text( i ) == s )
+ m_pDocumentationVersion->setCurrentItem( i );
+
+ bool sb = m_pLibraryPaths->signalsBlocked( );
+ m_pLibraryPaths->blockSignals( true );
+ m_pLibraryPaths->clear( );
+ QStringList plist = PMPovrayRenderWidget::povrayLibraryPaths( );
+ QStringList::ConstIterator it = plist.begin( );
+ m_selectionIndex = -1;
+ for( ; it != plist.end( ); ++it )
+ {
+ m_pLibraryPaths->insertItem( *it );
+ m_selectionIndex++;
+ }
+
+ m_pRemoveLibraryPath->setEnabled( false );
+ m_pChangeLibraryPath->setEnabled( false );
+ m_pLibraryPathUp->setEnabled( false );
+ m_pLibraryPathDown->setEnabled( false );
+ m_pLibraryPaths->blockSignals( sb );
+}
+
+void PMPovraySettings::displayDefaults( )
+{
+ m_pPovrayCommand->setText( c_defaultPovrayCommand );
+ m_pDocumentationVersion->setCurrentItem( 0 );
+ m_pDocumentationPath->setText( QString::null );
+ m_pLibraryPaths->clear();
+
+}
+
+bool PMPovraySettings::validateData( )
+{
+ return true;
+}
+
+void PMPovraySettings::applySettings( )
+{
+ PMPovrayRenderWidget::setPovrayCommand( m_pPovrayCommand->text( ) );
+ PMDocumentationMap::theMap( )->setPovrayDocumentationPath(
+ m_pDocumentationPath->text( ) );
+ PMDocumentationMap::theMap( )->setDocumentationVersion(
+ m_pDocumentationVersion->currentText( ) );
+ QStringList plist;
+ int num = ( signed ) m_pLibraryPaths->count( );
+ int i;
+ for( i = 0; i < num; i++ )
+ plist.append( m_pLibraryPaths->text( i ) );
+
+ if( PMPovrayRenderWidget::povrayLibraryPaths( ) != plist )
+ {
+ PMPovrayRenderWidget::setPovrayLibraryPaths( plist );
+ PMResourceLocator::clearCache( );
+ PMText::povrayLibraryPathsChanged( );
+ emit repaintViews( );
+ }
+}
+
+void PMPovraySettings::slotAddPath( )
+{
+ if( m_pLibraryPaths->count( ) >= 20 )
+ KMessageBox::error( this, i18n( "Povray only supports up to 20 library paths." ) );
+ else
+ {
+ QString path = KFileDialog::getExistingDirectory( QString::null, this );
+ if( !path.isEmpty( ) )
+ {
+#if ( QT_VERSION >= 300 )
+ QListBoxItem* item = m_pLibraryPaths->findItem( path, ExactMatch );
+#else
+ QListBoxItem* item = 0;
+#endif
+ if( !item )
+ {
+ m_pLibraryPaths->insertItem( path, m_selectionIndex + 1 );
+ m_pLibraryPaths->setCurrentItem( m_selectionIndex + 1 );
+ }
+ else
+ KMessageBox::error( this, i18n( "The list of library paths already contains this path." ) );
+ }
+ }
+}
+
+void PMPovraySettings::slotRemovePath( )
+{
+ m_pLibraryPaths->removeItem( m_selectionIndex );
+ if( ( unsigned ) m_selectionIndex >= m_pLibraryPaths->count( ) )
+ m_selectionIndex--;
+ m_pLibraryPaths->setCurrentItem( m_selectionIndex );
+}
+
+void PMPovraySettings::slotPathUp( )
+{
+ QListBoxItem* lbi = m_pLibraryPaths->item( m_selectionIndex );
+ if( lbi )
+ {
+ QString text = lbi->text( );
+ m_pLibraryPaths->removeItem( m_selectionIndex );
+ if( m_selectionIndex > 0 )
+ m_selectionIndex--;
+ m_pLibraryPaths->insertItem( text, m_selectionIndex );
+ m_pLibraryPaths->setCurrentItem( m_selectionIndex );
+ }
+}
+
+void PMPovraySettings::slotPathDown( )
+{
+ QListBoxItem* lbi = m_pLibraryPaths->item( m_selectionIndex );
+ if( lbi )
+ {
+ QString text = lbi->text( );
+ m_pLibraryPaths->removeItem( m_selectionIndex );
+ if( ( unsigned ) m_selectionIndex < m_pLibraryPaths->count( ) )
+ m_selectionIndex++;
+ m_pLibraryPaths->insertItem( text, m_selectionIndex );
+ m_pLibraryPaths->setCurrentItem( m_selectionIndex );
+ }
+}
+
+void PMPovraySettings::slotEditPath( )
+{
+ QListBoxItem* lbi = m_pLibraryPaths->item( m_selectionIndex );
+ if( lbi )
+ {
+ QString text = lbi->text( );
+ QString path = KFileDialog::getExistingDirectory( text, this );
+ if( !path.isEmpty( ) )
+ {
+#if ( QT_VERSION >= 300 )
+ QListBoxItem* item = m_pLibraryPaths->findItem( path, ExactMatch );
+#else
+ QListBoxItem* item = 0;
+#endif
+ if( !item )
+ m_pLibraryPaths->changeItem( path, m_selectionIndex );
+ else if( item != lbi )
+ KMessageBox::error( this, i18n( "The list of library paths already contains this path." ) );
+ }
+ }
+}
+
+void PMPovraySettings::slotPathSelected( int index )
+{
+ m_selectionIndex = index;
+ QListBoxItem* lbi = m_pLibraryPaths->item( m_selectionIndex );
+ if( lbi )
+ {
+ m_pRemoveLibraryPath->setEnabled( true );
+ m_pChangeLibraryPath->setEnabled( true );
+ m_pLibraryPathUp->setEnabled( index > 0 );
+ m_pLibraryPathDown->setEnabled( index < ( ( signed ) m_pLibraryPaths->count( ) - 1 ) );
+ }
+ else
+ {
+ m_pRemoveLibraryPath->setEnabled( false );
+ m_pChangeLibraryPath->setEnabled( false );
+ m_pLibraryPathUp->setEnabled( false );
+ m_pLibraryPathDown->setEnabled( false );
+ }
+}
+
+void PMPovraySettings::slotBrowsePovrayCommand( )
+{
+ QString str = KFileDialog::getOpenFileName( QString::null, QString::null );
+
+ if( !str.isEmpty() )
+ {
+ m_pPovrayCommand->setText( str );
+ }
+}
+
+void PMPovraySettings::slotBrowsePovrayDocumentation( )
+{
+ QString str = KFileDialog::getExistingDirectory( );
+
+ if( !str.isEmpty( ) )
+ m_pDocumentationPath->setText( str );
+}
+
+#include "pmpovraysettings.moc"
diff --git a/kpovmodeler/pmpovraysettings.h b/kpovmodeler/pmpovraysettings.h
new file mode 100644
index 00000000..cbe07827
--- /dev/null
+++ b/kpovmodeler/pmpovraysettings.h
@@ -0,0 +1,98 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAYSETTINGS_H
+#define PMPOVRAYSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+
+class QLineEdit;
+class QPushButton;
+class QComboBox;
+class QListBox;
+
+/**
+ * Povray configuration dialog page
+ */
+class PMPovraySettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMPovraySettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual void displayDefaults( );
+
+protected slots:
+ void slotAddPath( );
+ /**
+ * Called when the remove button is clicked
+ */
+ void slotRemovePath( );
+ /**
+ * Called when the up button is clicked
+ */
+ void slotPathUp( );
+ /**
+ * Called when the down button is clicked
+ */
+ void slotPathDown( );
+ /**
+ * Called when the edit button is clicked
+ */
+ void slotEditPath( );
+ /**
+ * Called when a path is selected in the list view
+ */
+ void slotPathSelected( int index );
+ /**
+ * Called when the browse button for the povray command is clicked
+ */
+ void slotBrowsePovrayCommand( );
+ /**
+ * Called when the browse button for the povray documentation is clicked
+ */
+ void slotBrowsePovrayDocumentation( );
+
+private:
+ QLineEdit* m_pPovrayCommand;
+ QPushButton* m_pBrowsePovrayCommand;
+ QLineEdit* m_pDocumentationPath;
+ QPushButton* m_pBrowseDocumentationPath;
+ QComboBox* m_pDocumentationVersion;
+ QListBox* m_pLibraryPaths;
+ QPushButton* m_pAddLibraryPath;
+ QPushButton* m_pRemoveLibraryPath;
+ QPushButton* m_pChangeLibraryPath;
+ QPushButton* m_pLibraryPathUp;
+ QPushButton* m_pLibraryPathDown;
+ int m_selectionIndex;
+};
+
+#endif
diff --git a/kpovmodeler/pmpovraywidget.cpp b/kpovmodeler/pmpovraywidget.cpp
new file mode 100644
index 00000000..d50edc7e
--- /dev/null
+++ b/kpovmodeler/pmpovraywidget.cpp
@@ -0,0 +1,411 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpovraywidget.h"
+#include "pmpovrayrenderwidget.h"
+#include "pmpovrayoutputwidget.h"
+#include "pmshell.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kimageio.h>
+#include <kfiledialog.h>
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+#include <kglobalsettings.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+#include <qlayout.h>
+#include <qprogressbar.h>
+#include <qlabel.h>
+#include <qscrollview.h>
+#include <qtimer.h>
+#include <qapplication.h>
+
+const int timerIntervall = 1000;
+bool PMPovrayWidget::s_imageFormatsRegistered = false;
+
+PMPovrayWidget::PMPovrayWidget( QWidget* parent, const char* name )
+ : KDialog( parent, name )
+{
+ QVBoxLayout* topLayout = new QVBoxLayout( this, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ topLayout->addStretch( );
+
+ QHBoxLayout* renderLayout = new QHBoxLayout( );
+ topLayout->addLayout( renderLayout, 2 );
+ m_pScrollView = new QScrollView( this );
+ m_pScrollView->setBackgroundMode( PaletteBase );
+ renderLayout->addWidget( m_pScrollView, 2 );
+ m_pRenderWidget = new PMPovrayRenderWidget( m_pScrollView->viewport( ) );
+ m_pRenderWidget->setFixedSize( 200, 200 );
+ m_pScrollView->addChild( m_pRenderWidget );
+ topLayout->addStretch( );
+
+ QHBoxLayout* progressLayout = new QHBoxLayout( topLayout );
+ m_pProgressBar = new QProgressBar( this );
+ m_pProgressBar->hide( );
+ progressLayout->addWidget( m_pProgressBar, 1 );
+ m_pProgressLabel = new QLabel( this );
+ progressLayout->addWidget( m_pProgressLabel, 2 );
+
+ QHBoxLayout* buttonLayout = new QHBoxLayout( topLayout );
+ m_pStopButton = new QPushButton( i18n( "Stop" ), this );
+ m_pStopButton->setEnabled( false );
+ buttonLayout->addWidget( m_pStopButton );
+ m_pSuspendButton = new QPushButton( i18n( "Suspend" ), this );
+ m_pSuspendButton->setEnabled( false );
+ buttonLayout->addWidget( m_pSuspendButton );
+ m_pResumeButton = new QPushButton( i18n( "Resume" ), this );
+ m_pResumeButton->setEnabled( false );
+ buttonLayout->addWidget( m_pResumeButton );
+ buttonLayout->addStretch( 1 );
+ m_pPovrayOutputButton = new QPushButton( i18n( "Povray Output" ), this );
+ buttonLayout->addWidget( m_pPovrayOutputButton );
+
+ buttonLayout = new QHBoxLayout( topLayout );
+ m_pSaveButton = new KPushButton( KStdGuiItem::saveAs(), this );
+ m_pSaveButton->setEnabled( false );
+ buttonLayout->addWidget( m_pSaveButton );
+ buttonLayout->addStretch( 1 );
+ QPushButton* closeButton = new KPushButton( KStdGuiItem::close(), this );
+ buttonLayout->addWidget( closeButton );
+
+ connect( m_pRenderWidget, SIGNAL( finished( int ) ),
+ SLOT( slotRenderingFinished( int ) ) );
+ connect( m_pRenderWidget, SIGNAL( progress( int ) ),
+ SLOT( slotProgress( int ) ) );
+ connect( m_pRenderWidget, SIGNAL( lineFinished( int ) ),
+ SLOT( slotLineFinished( int ) ) );
+
+ connect( m_pStopButton, SIGNAL( clicked( ) ), SLOT( slotStop( ) ) );
+ connect( m_pSuspendButton, SIGNAL( clicked( ) ), SLOT( slotSuspend( ) ) );
+ connect( m_pResumeButton, SIGNAL( clicked( ) ), SLOT( slotResume( ) ) );
+ connect( m_pSaveButton, SIGNAL( clicked( ) ), SLOT( slotSave( ) ) );
+ connect( closeButton, SIGNAL( clicked( ) ), SLOT( slotClose( ) ) );
+ connect( m_pPovrayOutputButton, SIGNAL( clicked( ) ),
+ SLOT( slotPovrayOutput( ) ) );
+
+ m_bRunning = false;
+ m_pProgressTimer = new QTimer( this );
+ connect( m_pProgressTimer, SIGNAL( timeout( ) ),
+ SLOT( slotUpdateSpeed( ) ) );
+
+ setCaption( i18n( "Render Window" ) );
+
+ m_height = m_width = 0;
+ m_stopped = false;
+
+ m_pPovrayOutputWidget = new PMPovrayOutputWidget( );
+ connect( m_pRenderWidget, SIGNAL( povrayMessage( const QString& ) ),
+ m_pPovrayOutputWidget, SLOT( slotText( const QString& ) ) );
+}
+
+PMPovrayWidget::~PMPovrayWidget( )
+{
+ delete m_pPovrayOutputWidget;
+}
+
+bool PMPovrayWidget::render( const QByteArray& scene, const PMRenderMode& m,
+ const KURL& documentURL )
+{
+ bool updateSize = ( m_height != m.height( ) ) || ( m_width != m.width( ) );
+ m_height = m.height( );
+ m_width = m.width( );
+ m_bRunning = false;
+ m_pPovrayOutputWidget->slotClear( );
+ m_stopped = false;
+
+ m_pRenderWidget->setFixedSize( m_width, m_height );
+ QSize maxSize( m_width + m_pScrollView->frameWidth( ) * 2,
+ m_height + m_pScrollView->frameWidth( ) * 2 );
+ m_pScrollView->setMaximumSize( maxSize );
+
+ if( updateSize )
+ {
+ int w, h;
+
+ w = maxSize.width( ) + KDialog::spacingHint( ) * 2;
+ h = maxSize.height( ) + m_pSaveButton->sizeHint( ).height( ) * 2
+ + KDialog::spacingHint( ) * 6;
+ if( m_pProgressLabel->sizeHint( ).height( )
+ > m_pProgressBar->sizeHint( ).height( ) )
+ h += m_pProgressLabel->sizeHint( ).height( );
+ else
+ h += m_pProgressBar->sizeHint( ).height( );
+
+ w += 16;
+ h += 16;
+
+#if ( ( KDE_VERSION_MAJOR == 3 ) && ( KDE_VERSION_MINOR <= 1 ) )
+ QWidget* dw = QApplication::desktop( );
+ if( w > dw->width( ) )
+ w = dw->width( );
+ if( h > dw->height( ) )
+ h = dw->height( );
+#else
+ QRect dw = KGlobalSettings::desktopGeometry(this);
+ if( w > dw.width() )
+ w = dw.width();
+ if( h > dw.height() )
+ h = dw.height();
+#endif
+ resize( w, h );
+ }
+
+ if( m_pRenderWidget->render( scene, m, documentURL ) )
+ {
+ m_bRunning = true;
+ m_pProgressBar->setProgress( 0 );
+ m_pProgressBar->show( );
+ m_pProgressLabel->setText( i18n( "running" ) );
+ m_pStopButton->setEnabled( true );
+ m_pSuspendButton->setEnabled( true );
+ m_pResumeButton->setEnabled( false );
+ m_pSaveButton->setEnabled( false );
+
+ m_lastSpeedTime = QTime( );
+ m_pProgressTimer->start( timerIntervall, true );
+ m_speedInfo = false;
+ m_speed = 0;
+ m_line = 0;
+ m_immediateUpdate = false;
+ showSpeed( 0 );
+ }
+
+ return m_bRunning;
+}
+
+void PMPovrayWidget::slotStop( )
+{
+ m_stopped = true;
+ m_pRenderWidget->killRendering( );
+ m_pSaveButton->setEnabled( true );
+}
+
+void PMPovrayWidget::slotSuspend( )
+{
+ m_pRenderWidget->suspendRendering( );
+ m_pSuspendButton->setEnabled( false );
+ m_pResumeButton->setEnabled( true );
+ m_pSaveButton->setEnabled( true );
+
+ m_pProgressTimer->stop( );
+ m_lastSpeedTime = QTime( );
+ m_speedInfo = false;
+ m_immediateUpdate = false;
+ m_pProgressLabel->setText( i18n( "suspended" ) );
+}
+
+void PMPovrayWidget::slotResume( )
+{
+ m_pRenderWidget->resumeRendering( );
+ m_pSuspendButton->setEnabled( true );
+ m_pResumeButton->setEnabled( false );
+ m_pSaveButton->setEnabled( false );
+
+ m_pProgressTimer->start( timerIntervall, true );
+ showSpeed( m_speed );
+}
+
+void PMPovrayWidget::slotClose( )
+{
+ hide( );
+}
+
+void PMPovrayWidget::slotSave( )
+{
+ KTempFile* tempFile = 0;
+ QFile* file = 0;
+ bool ok = true;
+
+ if( !s_imageFormatsRegistered )
+ {
+ KImageIO::registerFormats( );
+ s_imageFormatsRegistered = true;
+ }
+
+ KURL url = KFileDialog::getSaveURL( QString::null, KImageIO::pattern( KImageIO::Writing ) );
+ if( url.isEmpty( ) )
+ return;
+ if( !PMShell::overwriteURL( url ) )
+ return;
+
+ if( !url.isValid( ) )
+ {
+ KMessageBox::error( this, i18n( "Malformed URL" ) );
+ return;
+ }
+
+ QString format = KImageIO::type( url.fileName( ) );
+ if( format.isEmpty( ) )
+ {
+ KMessageBox::error( this, i18n( "Unknown image format.\n"
+ "Please enter a valid suffix." ) );
+ return;
+ }
+
+ if( !KImageIO::canWrite( format ) )
+ {
+ KMessageBox::error( this, i18n( "Format is not supported for writing." ) );
+ return;
+ }
+
+ if( url.isLocalFile( ) )
+ {
+ // Local file
+ file = new QFile( url.path( ) );
+ if( !file->open( IO_WriteOnly ) )
+ ok = false;
+ }
+ else
+ {
+ // Remote file
+ // provide a temp file
+ tempFile = new KTempFile( );
+ if( tempFile->status( ) != 0 )
+ ok = false;
+ else
+ file = tempFile->file( );
+ }
+
+ if( ok )
+ {
+ QImageIO iio( file, format.latin1( ) );
+ iio.setImage( m_pRenderWidget->image( ) );
+ ok = iio.write( );
+
+ if( ok )
+ {
+ if( tempFile )
+ {
+ tempFile->close( );
+ ok = KIO::NetAccess::upload( tempFile->name( ), url );
+ tempFile->unlink( );
+ file = 0;
+ }
+ else
+ file->close( );
+ }
+ else
+ KMessageBox::error( this, i18n( "Couldn't correctly write the image.\n"
+ "Wrong image format?" ) );
+ }
+ else
+ KMessageBox::error( this, i18n( "Couldn't write the image.\n"
+ "Permission denied." ) );
+
+
+ delete file;
+ delete tempFile;
+}
+
+void PMPovrayWidget::slotPovrayOutput( )
+{
+ m_pPovrayOutputWidget->show( );
+}
+
+void PMPovrayWidget::slotRenderingFinished( int returnStatus )
+{
+ kdDebug( PMArea ) << "Povray exited with status " << returnStatus << endl;
+ m_bRunning = false;
+ if( returnStatus == 0 )
+ m_pSaveButton->setEnabled( true );
+ m_pStopButton->setEnabled( false );
+ m_pSuspendButton->setEnabled( false );
+ m_pResumeButton->setEnabled( false );
+ m_pProgressLabel->setText( i18n( "finished" ) );
+ m_pProgressTimer->stop( );
+
+ if( ( returnStatus != 0 ) && !m_stopped )
+ {
+ KMessageBox::error( this, i18n( "Povray exited abnormally.\n"
+ "See the povray output for details." )
+ .arg( returnStatus ) );
+ }
+ else if( m_pRenderWidget->povrayOutput( ).contains( "ERROR" ) )
+ {
+ KMessageBox::error( this, i18n( "There were errors while rendering.\n"
+ "See the povray output for details." ) );
+ }
+}
+
+void PMPovrayWidget::slotProgress( int i )
+{
+ m_pProgressBar->setProgress( i );
+}
+
+void PMPovrayWidget::slotLineFinished( int line )
+{
+ m_speedInfo = true;
+ QTime ct = QTime::currentTime( );
+
+ if( !m_lastSpeedTime.isNull( ) )
+ {
+ int msecs = m_lastSpeedTime.msecsTo( ct );
+ if( msecs < 1 )
+ msecs = 1;
+
+ double g = 1.0 / ( ( double ) msecs / 500.0 + 1.0 );
+ m_speed = g * m_speed +
+ 1000 * ( 1.0 - g ) * m_width * ( line - m_line ) / msecs;
+ }
+
+ if( m_immediateUpdate )
+ {
+ m_immediateUpdate = false;
+ showSpeed( m_speed );
+ m_pProgressTimer->start( timerIntervall, true );
+ m_speedInfo = false;
+ }
+
+ m_lastSpeedTime = ct;
+ m_line = line;
+}
+
+void PMPovrayWidget::slotUpdateSpeed( )
+{
+ if( m_speedInfo )
+ {
+ showSpeed( m_speed );
+ m_pProgressTimer->start( timerIntervall, true );
+ m_speedInfo = false;
+ }
+ else
+ m_immediateUpdate = true;
+}
+
+void PMPovrayWidget::showSpeed( double pps )
+{
+ QString num;
+ if( pps >= 1000000 )
+ {
+ num.setNum( pps / 100000, 'g', 3 );
+ num += 'M';
+ }
+ else if( pps >= 1000 )
+ {
+ num.setNum( pps / 1000, 'g', 3 );
+ num += 'K';
+ }
+ else
+ num.setNum( pps, 'g', 3 );
+
+ m_pProgressLabel->setText( i18n( "running, %1 pixels/second" ).arg( num ) );
+}
+
+#include "pmpovraywidget.moc"
diff --git a/kpovmodeler/pmpovraywidget.h b/kpovmodeler/pmpovraywidget.h
new file mode 100644
index 00000000..26d5bb1e
--- /dev/null
+++ b/kpovmodeler/pmpovraywidget.h
@@ -0,0 +1,103 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPOVRAYWIDGET_H
+#define PMPOVRAYWIDGET_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialog.h>
+#include <qcstring.h>
+#include <qdatetime.h>
+
+class PMPovrayRenderWidget;
+class PMPovrayOutputWidget;
+class PMRenderMode;
+
+class QProgressBar;
+class QPushButton;
+class QLabel;
+class QScrollView;
+class KURL;
+
+/**
+ * Widget with toolbar, statusbar and a @ref PMPovrayRenderWidget
+ */
+class PMPovrayWidget : public KDialog
+{
+ Q_OBJECT
+public:
+ /**
+ * Standard constructor
+ */
+ PMPovrayWidget( QWidget* parent = 0, const char* name = 0 );
+ /**
+ * Destructor
+ */
+ virtual ~PMPovrayWidget( );
+
+ /**
+ * Starts rendering for the povray code in the byte array with
+ * render mode m.
+ * @see PMRenderMode
+ */
+ bool render( const QByteArray& scene, const PMRenderMode& m,
+ const KURL& documentURL );
+
+public slots:
+ void slotStop( );
+ void slotSuspend( );
+ void slotResume( );
+ void slotClose( );
+ void slotSave( );
+ void slotPovrayOutput( );
+
+protected slots:
+ void slotRenderingFinished( int returnStatus );
+ void slotProgress( int i );
+ void slotLineFinished( int line );
+ void slotUpdateSpeed( );
+
+protected:
+ void showSpeed( double pps );
+
+private:
+ PMPovrayRenderWidget* m_pRenderWidget;
+ PMPovrayOutputWidget* m_pPovrayOutputWidget;
+ QPushButton* m_pStopButton;
+ QPushButton* m_pSuspendButton;
+ QPushButton* m_pResumeButton;
+ QPushButton* m_pSaveButton;
+ QPushButton* m_pPovrayOutputButton;
+ QProgressBar* m_pProgressBar;
+ QLabel* m_pProgressLabel;
+ QScrollView* m_pScrollView;
+ int m_height, m_width;
+ bool m_bRunning;
+ QTime m_lastSpeedTime;
+ QTimer* m_pProgressTimer;
+ bool m_speedInfo;
+ bool m_immediateUpdate;
+ float m_speed;
+ int m_line;
+ bool m_stopped;
+ static bool s_imageFormatsRegistered;
+};
+
+#endif
diff --git a/kpovmodeler/pmpreviewsettings.cpp b/kpovmodeler/pmpreviewsettings.cpp
new file mode 100644
index 00000000..1254431e
--- /dev/null
+++ b/kpovmodeler/pmpreviewsettings.cpp
@@ -0,0 +1,207 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmpreviewsettings.h"
+
+#include "pmlineedits.h"
+#include "pmdialogeditbase.h"
+#include "pmdefaults.h"
+
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <kcolorbutton.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+PMPreviewSettings::PMPreviewSettings( QWidget* parent, const char* name )
+ : PMSettingsDialogPage( parent, name )
+{
+ QHBoxLayout* hlayout;
+ QVBoxLayout* vlayout;
+ QVBoxLayout* gvl;
+ QGridLayout* grid;
+ QGroupBox* gb;
+
+ vlayout = new QVBoxLayout( this, 0, KDialog::spacingHint( ) );
+
+ hlayout = new QHBoxLayout( vlayout );
+ grid = new QGridLayout( hlayout, 2, 2 );
+ grid->addWidget( new QLabel( i18n( "Size:" ), this ), 0, 0 );
+ m_pPreviewSize = new PMIntEdit( this );
+ m_pPreviewSize->setValidation( true, 10, true, 400 );
+ grid->addWidget( m_pPreviewSize, 0, 1 );
+
+ grid->addWidget( new QLabel( i18n( "Gamma:" ), this ), 1, 0 );
+ m_pPreviewGamma = new PMFloatEdit( this );
+ grid->addWidget( m_pPreviewGamma, 1, 1 );
+ hlayout->addStretch( 1 );
+
+ gb = new QGroupBox( i18n( "Rendered Objects" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+ m_pPreviewSphere = new QCheckBox( i18n( "Sphere" ), gb );
+ gvl->addWidget( m_pPreviewSphere );
+ m_pPreviewCylinder = new QCheckBox( i18n( "Cylinder" ), gb );
+ gvl->addWidget( m_pPreviewCylinder );
+ m_pPreviewBox = new QCheckBox( i18n( "Box" ), gb );
+ gvl->addWidget( m_pPreviewBox );
+
+ gb = new QGroupBox( i18n( "Wall" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+ m_pPreviewWall = new QCheckBox( i18n( "Enable wall" ), gb );
+ gvl->addWidget( m_pPreviewWall );
+ hlayout = new QHBoxLayout( gvl );
+ hlayout->addWidget( new QLabel( i18n( "Color 1:" ), gb ) );
+ m_pWallColor1 = new KColorButton( gb );
+ hlayout->addWidget( m_pWallColor1 );
+ hlayout->addWidget( new QLabel( i18n( "Color 2:" ), gb ) );
+ m_pWallColor2 = new KColorButton( gb );
+ hlayout->addWidget( m_pWallColor2 );
+ hlayout->addStretch( 1 );
+
+ gb = new QGroupBox( i18n( "Floor" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+ m_pPreviewFloor = new QCheckBox( i18n( "Enable floor" ), gb );
+ gvl->addWidget( m_pPreviewFloor );
+ hlayout = new QHBoxLayout( gvl );
+ hlayout->addWidget( new QLabel( i18n( "Color 1:" ), gb ) );
+ m_pFloorColor1 = new KColorButton( gb );
+ hlayout->addWidget( m_pFloorColor1 );
+ hlayout->addWidget( new QLabel( i18n( "Color 2:" ), gb ) );
+ m_pFloorColor2 = new KColorButton( gb );
+ hlayout->addWidget( m_pFloorColor2 );
+ hlayout->addStretch( 1 );
+
+ gb = new QGroupBox( i18n( "Antialiasing" ), this );
+ vlayout->addWidget( gb );
+ gvl = new QVBoxLayout( gb, KDialog::marginHint( ), KDialog::spacingHint( ) );
+ gvl->addSpacing( 10 );
+ m_pPreviewAA = new QCheckBox( i18n( "Enable antialiasing" ), gb );
+ gvl->addWidget( m_pPreviewAA );
+ hlayout = new QHBoxLayout( gvl );
+ hlayout->addWidget( new QLabel( i18n( "Depth:" ), gb ) );
+ m_pPreviewAALevel = new PMIntEdit( gb );
+ m_pPreviewAALevel->setValidation( true, 1, true, 9 );
+ hlayout->addWidget( m_pPreviewAALevel );
+ hlayout->addWidget( new QLabel( i18n( "Threshold:" ), gb ) );
+ m_pPreviewAAThreshold = new PMFloatEdit( gb );
+ hlayout->addWidget( m_pPreviewAAThreshold );
+ hlayout->addStretch( 1 );
+
+ vlayout->addStretch( 1 );
+}
+
+void PMPreviewSettings::displaySettings( )
+{
+ m_pPreviewSize->setValue( PMDialogEditBase::previewSize( ) );
+ m_pPreviewGamma->setValue( PMDialogEditBase::previewGamma( ) );
+ m_pPreviewSphere->setChecked( PMDialogEditBase::previewShowSphere( ) );
+ m_pPreviewCylinder->setChecked( PMDialogEditBase::previewShowCylinder( ) );
+ m_pPreviewBox->setChecked( PMDialogEditBase::previewShowBox( ) );
+ m_pPreviewAA->setChecked( PMDialogEditBase::isPreviewAAEnabled( ) );
+ m_pPreviewAALevel->setValue( PMDialogEditBase::previewAADepth( ) );
+ m_pPreviewAAThreshold->setValue( PMDialogEditBase::previewAAThreshold( ) );
+ m_pPreviewWall->setChecked( PMDialogEditBase::previewShowWall( ) );
+ m_pPreviewFloor->setChecked( PMDialogEditBase::previewShowFloor( ) );
+ m_pFloorColor1->setColor( PMDialogEditBase::previewFloorColor1( ) );
+ m_pFloorColor2->setColor( PMDialogEditBase::previewFloorColor2( ) );
+ m_pWallColor1->setColor( PMDialogEditBase::previewWallColor1( ) );
+ m_pWallColor2->setColor( PMDialogEditBase::previewWallColor2( ) );
+}
+
+void PMPreviewSettings::displayDefaults( )
+{
+ m_pPreviewSize->setValue( c_defaultTPSize );
+ m_pPreviewGamma->setValue( c_defaultTPGamma );
+ m_pPreviewSphere->setChecked( c_defaultTPShowSphere );
+ m_pPreviewCylinder->setChecked( c_defaultTPShowCylinder );
+ m_pPreviewBox->setChecked( c_defaultTPShowBox );
+ m_pPreviewAA->setChecked( c_defaultTPAA );
+ m_pPreviewAALevel->setValue( c_defaultTPAADepth );
+ m_pPreviewAAThreshold->setValue( c_defaultTPAAThreshold );
+ m_pPreviewWall->setChecked( c_defaultTPShowWall );
+ m_pPreviewFloor->setChecked( c_defaultTPShowFloor );
+ m_pFloorColor1->setColor( c_defaultTPFloorColor1 );
+ m_pFloorColor2->setColor( c_defaultTPFloorColor2 );
+ m_pWallColor1->setColor( c_defaultTPWallColor1 );
+ m_pWallColor2->setColor( c_defaultTPWallColor2 );
+}
+
+bool PMPreviewSettings::validateData( )
+{
+ if( !m_pPreviewSize->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pPreviewSize->setFocus( );
+ return false;
+ }
+ if( !m_pPreviewGamma->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pPreviewGamma->setFocus( );
+ return false;
+ }
+ if( !m_pPreviewAALevel->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pPreviewAALevel->setFocus( );
+ return false;
+ }
+ if( !m_pPreviewAAThreshold->isDataValid( ) )
+ {
+ emit showMe( );
+ m_pPreviewAAThreshold->setFocus( );
+ return false;
+ }
+ if( !( m_pPreviewSphere->isChecked( ) || m_pPreviewCylinder->isChecked( )
+ || m_pPreviewBox->isChecked( ) ) )
+ {
+ emit showMe( );
+ KMessageBox::error( this, i18n( "At least one object has to be selected." ),
+ i18n( "Error" ) );
+
+ return false;
+ }
+ return true;
+}
+
+void PMPreviewSettings::applySettings( )
+{
+ PMDialogEditBase::setPreviewSize( m_pPreviewSize->value( ) );
+ PMDialogEditBase::setPreviewGamma( m_pPreviewGamma->value( ) );
+ PMDialogEditBase::previewShowSphere( m_pPreviewSphere->isChecked( ) );
+ PMDialogEditBase::previewShowCylinder( m_pPreviewCylinder->isChecked( ) );
+ PMDialogEditBase::previewShowBox( m_pPreviewBox->isChecked( ) );
+ PMDialogEditBase::setPreviewAAEnabled( m_pPreviewAA->isChecked( ) );
+ PMDialogEditBase::setPreviewAADepth( m_pPreviewAALevel->value( ) );
+ PMDialogEditBase::setPreviewAAThreshold( m_pPreviewAAThreshold->value( ) );
+ PMDialogEditBase::previewShowFloor( m_pPreviewFloor->isChecked( ) );
+ PMDialogEditBase::previewShowWall( m_pPreviewWall->isChecked( ) );
+ PMDialogEditBase::setPreviewWallColor1( m_pWallColor1->color( ) );
+ PMDialogEditBase::setPreviewWallColor2( m_pWallColor2->color( ) );
+ PMDialogEditBase::setPreviewFloorColor1( m_pFloorColor1->color( ) );
+ PMDialogEditBase::setPreviewFloorColor2( m_pFloorColor2->color( ) );
+}
+
+#include "pmpreviewsettings.moc"
diff --git a/kpovmodeler/pmpreviewsettings.h b/kpovmodeler/pmpreviewsettings.h
new file mode 100644
index 00000000..a0983002
--- /dev/null
+++ b/kpovmodeler/pmpreviewsettings.h
@@ -0,0 +1,69 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMPREVIEWSETTINGS_H
+#define PMPREVIEWSETTINGS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsettingsdialog.h"
+
+class PMIntEdit;
+class PMFloatEdit;
+class QCheckBox;
+class KColorButton;
+
+/**
+ * Texture preview configuration dialog page
+ */
+class PMPreviewSettings : public PMSettingsDialogPage
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMPreviewSettings( QWidget* parent, const char* name = 0 );
+ /** */
+ virtual void displaySettings( );
+ /** */
+ virtual bool validateData( );
+ /** */
+ virtual void applySettings( );
+ /** */
+ virtual void displayDefaults( );
+
+private:
+ PMIntEdit* m_pPreviewSize;
+ QCheckBox* m_pPreviewSphere;
+ QCheckBox* m_pPreviewCylinder;
+ QCheckBox* m_pPreviewBox;
+ QCheckBox* m_pPreviewAA;
+ PMIntEdit* m_pPreviewAALevel;
+ PMFloatEdit* m_pPreviewAAThreshold;
+ QCheckBox* m_pPreviewWall;
+ QCheckBox* m_pPreviewFloor;
+ KColorButton* m_pFloorColor1;
+ KColorButton* m_pFloorColor2;
+ KColorButton* m_pWallColor1;
+ KColorButton* m_pWallColor2;
+ PMFloatEdit* m_pPreviewGamma;
+};
+
+#endif
diff --git a/kpovmodeler/pmprism.cpp b/kpovmodeler/pmprism.cpp
new file mode 100644
index 00000000..26fa9035
--- /dev/null
+++ b/kpovmodeler/pmprism.cpp
@@ -0,0 +1,1187 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmprism.h"
+
+#include "pmxmlhelper.h"
+#include "pmprismedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm2dcontrolpoint.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmprismmemento.h"
+#include "pmsplinesegment.h"
+#include "pmdefaults.h"
+#include "pmenumproperty.h"
+#include "pmobjectaction.h"
+
+#include <klocale.h>
+
+const int defaultNumberOfPoints = 6;
+const PMVector defaultPoint[defaultNumberOfPoints] =
+{
+ PMVector( 0.5, 1.0 ),
+ PMVector( 1.0, 0.0 ),
+ PMVector( 0.5, -1.0 ),
+ PMVector( -0.5, -1.0 ),
+ PMVector( -1.0, 0.0 ),
+ PMVector( -0.5, 1.0 ),
+};
+
+const bool defaultSturm = false;
+const bool defaultOpen = false;
+const PMPrism::SplineType defaultSplineType = PMPrism::LinearSpline;
+const PMPrism::SweepType defaultSweepType = PMPrism::LinearSweep;
+const double defaultHeight1 = 0.0;
+const double defaultHeight2 = 1.0;
+
+int PMPrism::s_sSteps = c_defaultPrismSSteps;
+int PMPrism::s_parameterKey = 0;
+PMMetaObject* PMPrism::s_pMetaObject = 0;
+PMObject* createNewPrism( PMPart* part )
+{
+ return new PMPrism( part );
+}
+
+PMDefinePropertyClass( PMPrism, PMPrismProperty );
+PMDefineEnumPropertyClass( PMPrism, PMPrism::SplineType, PMSplineTypeProperty );
+PMDefineEnumPropertyClass( PMPrism, PMPrism::SweepType, PMSweepTypeProperty );
+
+class PMPointProperty : public PMPropertyBase
+{
+public:
+ PMPointProperty( )
+ : PMPropertyBase( "splinePoints", PMVariant::Vector )
+ {
+ m_index[0] = 0;
+ m_index[1] = 0;
+ }
+ virtual int dimensions( ) const { return 2; }
+ virtual void setIndex( int dimension, int index )
+ {
+ if( dimension == 0 || dimension == 1 )
+ m_index[dimension] = index;
+ }
+ virtual int size( PMObject* object, int dimension ) const
+ {
+ PMPrism* prism = ( PMPrism* ) object;
+ QValueList< QValueList<PMVector> > points = prism->points( );
+ if( dimension == 0 )
+ return points.size( );
+ else
+ {
+ QValueList< QValueList<PMVector> >::ConstIterator it
+ = points.at( m_index[0] );
+ if( it != points.end( ) )
+ return ( *it ).size( );
+ }
+ return 0;
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& var )
+ {
+ PMPrism* p = ( PMPrism* ) obj;
+ QValueList< QValueList<PMVector> > list = p->points( );
+ QValueList< QValueList<PMVector> >::Iterator sit = list.begin( );
+ int i;
+ PMVector v = var.vectorData( );
+ v.resize( 2 );
+
+ for( i = 0; i < m_index[0] && sit != list.end( ); ++i )
+ ++sit;
+ // expand the list if necessary
+ for( ; i < m_index[0]; ++i )
+ list.insert( sit, QValueList< PMVector >( ) );
+ if( sit == list.end( ) )
+ sit = list.insert( sit, QValueList< PMVector >( ) );
+
+ QValueList<PMVector>::Iterator it = ( *sit ).begin( );
+
+ for( i = 0; i < m_index[1] && it != ( *sit ).end( ); ++i )
+ ++it;
+ // expand the list if necessary
+ for( ; i < m_index[1]; ++i )
+ ( *sit ).insert( it, v );
+ if( it == ( *sit ).end( ) )
+ it = ( *sit ).insert( it, v );
+ else
+ *it = v;
+
+ p->setPoints( list );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ PMPrism* p = ( PMPrism* ) obj;
+ QValueList< QValueList<PMVector> > list = p->points( );
+ QValueList< QValueList<PMVector> >::ConstIterator sit = list.at( m_index[0] );
+ if( sit == list.end( ) )
+ {
+ kdError( PMArea ) << "Range error in PMPrism::PointProperty::get" << endl;
+ return PMVariant( );
+ }
+
+ QValueList<PMVector>::ConstIterator it = ( *sit ).at( m_index[1] );
+
+ if( it == ( *sit ).end( ) )
+ {
+ kdError( PMArea ) << "Range error in PMPrism::PointProperty::get" << endl;
+ return PMVariant( );
+ }
+
+ return PMVariant( *it );
+ }
+
+private:
+ int m_index[2];
+};
+
+PMPrism::PMPrism( PMPart* part )
+ : Base( part )
+{
+ int i;
+ QValueList<PMVector> p;
+
+ for( i = 0; i < defaultNumberOfPoints; ++i )
+ p.append( defaultPoint[i] );
+ m_points.append( p );
+ m_splineType = defaultSplineType;
+ m_sweepType = defaultSweepType;
+ m_sturm = defaultSturm;
+ m_open = defaultOpen;
+ m_height1 = defaultHeight1;
+ m_height2 = defaultHeight2;
+}
+
+PMPrism::PMPrism( const PMPrism& p )
+ : Base( p )
+{
+ m_splineType = p.m_splineType;
+ m_sweepType = p.m_sweepType;
+ m_points = p.m_points;
+ m_height1 = p.m_height1;
+ m_height2 = p.m_height2;
+ m_open = p.m_open;
+ m_sturm = p.m_sturm;
+}
+
+PMPrism::~PMPrism( )
+{
+}
+
+QString PMPrism::description( ) const
+{
+ return i18n( "prism" );
+}
+
+void PMPrism::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ QDomElement data = doc.createElement( "extra_data" );
+ QDomElement p, p2;
+
+ e.setAttribute( "spline_type", m_splineType );
+ e.setAttribute( "sweep_type", m_sweepType );
+ e.setAttribute( "sturm", m_sturm );
+ e.setAttribute( "open", m_open );
+ e.setAttribute( "height1", m_height1 );
+ e.setAttribute( "height2", m_height2 );
+
+ QValueList< QValueList<PMVector> >::ConstIterator it;
+ QValueList<PMVector>::ConstIterator it2;
+ for( it = m_points.begin( ); it != m_points.end( ); ++it )
+ {
+ p = doc.createElement( "sub_prism" );
+ for( it2 = ( *it ).begin( ); it2 != ( *it ).end( ); ++it2 )
+ {
+ p2 = doc.createElement( "point" );
+ p2.setAttribute( "vector", ( *it2 ).serializeXML( ) );
+ p.appendChild( p2 );
+ }
+ data.appendChild( p );
+ }
+
+ e.appendChild( data );
+ Base::serialize( e, doc );
+}
+
+void PMPrism::readAttributes( const PMXMLHelper& h )
+{
+ m_splineType = ( SplineType ) h.intAttribute( "spline_type", defaultSplineType );
+ m_sweepType = ( SweepType ) h.intAttribute( "sweep_type", defaultSweepType );
+ m_open = h.boolAttribute( "open", defaultOpen );
+ m_sturm = h.boolAttribute( "sturm", defaultSturm );
+ m_height1 = h.doubleAttribute( "height1", defaultHeight1 );
+ m_height2 = h.doubleAttribute( "height2", defaultHeight2 );
+
+ m_points.clear( );
+ QValueList<PMVector> list;
+ PMVector v( 2 );
+
+ QDomElement e = h.extraData( );
+ if( !e.isNull( ) )
+ {
+ QDomNode sp = e.firstChild( );
+ while( !sp.isNull( ) )
+ {
+ if( sp.isElement( ) )
+ {
+ QDomElement spe = sp.toElement( );
+ if( spe.tagName( ) == "sub_prism" )
+ {
+ list.clear( );
+ QDomNode c = spe.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ if( ce.tagName( ) == "point" )
+ {
+ QString str = ce.attribute( "vector" );
+ if( !str.isNull( ) )
+ {
+ v.loadXML( str );
+ list.append( v );
+ }
+ }
+ }
+ c = c.nextSibling( );
+ }
+ m_points.append( list );
+ }
+ }
+ sp = sp.nextSibling( );
+ }
+ }
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMPrism::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Prism", Base::metaObject( ),
+ createNewPrism );
+ s_pMetaObject->addProperty(
+ new PMPrismProperty( "sturm", &PMPrism::setSturm, &PMPrism::sturm ) );
+ s_pMetaObject->addProperty(
+ new PMPrismProperty( "open", &PMPrism::setOpen, &PMPrism::open ) );
+ s_pMetaObject->addProperty(
+ new PMPrismProperty( "height1", &PMPrism::setHeight1, &PMPrism::height1 ) );
+ s_pMetaObject->addProperty(
+ new PMPrismProperty( "height2", &PMPrism::setHeight2, &PMPrism::height2 ) );
+
+ PMSplineTypeProperty* p = new PMSplineTypeProperty(
+ "splineType", &PMPrism::setSplineType, &PMPrism::splineType );
+ p->addEnumValue( "LinearSpline", LinearSpline );
+ p->addEnumValue( "QuadraticSpline", QuadraticSpline );
+ p->addEnumValue( "CubicSpline", CubicSpline );
+ p->addEnumValue( "BezierSpline", BezierSpline );
+ s_pMetaObject->addProperty( p );
+
+ PMSweepTypeProperty* sp = new PMSweepTypeProperty(
+ "sweepType", &PMPrism::setSweepType, &PMPrism::sweepType );
+ sp->addEnumValue( "LinearSweep", LinearSweep );
+ sp->addEnumValue( "ConicSweep", ConicSweep );
+ s_pMetaObject->addProperty( sp );
+
+ s_pMetaObject->addProperty( new PMPointProperty( ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMPrism::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMPrism::setSplineType( PMPrism::SplineType t )
+{
+ if( m_splineType != t )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSplineTypeID, ( int ) m_splineType );
+ setViewStructureChanged( );
+ m_splineType = t;
+ }
+}
+
+void PMPrism::setSweepType( PMPrism::SweepType t )
+{
+ if( m_sweepType != t )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSweepTypeID, ( int ) m_sweepType );
+ setViewStructureChanged( );
+ m_sweepType = t;
+ }
+}
+
+void PMPrism::setSturm( bool s )
+{
+ if( m_sturm != s )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSturmID, m_sturm );
+ m_sturm = s;
+ }
+}
+
+void PMPrism::setOpen( bool o )
+{
+ if( m_open != o )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOpenID, m_open );
+ m_open = o;
+ }
+}
+
+void PMPrism::setHeight1( double h )
+{
+ if( m_height1 != h )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHeight1ID, m_height1 );
+ m_height1 = h;
+ setViewStructureChanged( );
+ }
+}
+
+void PMPrism::setHeight2( double h )
+{
+ if( m_height2 != h )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHeight2ID, m_height2 );
+ m_height2 = h;
+ setViewStructureChanged( );
+ }
+}
+
+void PMPrism::setPoints( const QValueList< QValueList<PMVector> >& points )
+{
+ if( m_points != points )
+ {
+ if( m_pMemento )
+ ( ( PMPrismMemento* ) m_pMemento )->setPrismPoints( m_points );
+
+ setViewStructureChanged( );
+ m_points = points;
+ }
+}
+
+PMDialogEditBase* PMPrism::editWidget( QWidget* parent ) const
+{
+ return new PMPrismEdit( parent );
+}
+
+void PMPrism::createMemento( )
+{
+ if( m_pMemento )
+ delete m_pMemento;
+ m_pMemento = new PMPrismMemento( this );
+}
+
+void PMPrism::restoreMemento( PMMemento* s )
+{
+ PMPrismMemento* m = ( PMPrismMemento* ) s;
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMSplineTypeID:
+ setSplineType( ( SplineType ) data->intData( ) );
+ break;
+ case PMSweepTypeID:
+ setSweepType( ( SweepType ) data->intData( ) );
+ break;
+ case PMOpenID:
+ setOpen( data->boolData( ) );
+ break;
+ case PMSturmID:
+ setSturm( data->boolData( ) );
+ break;
+ case PMHeight1ID:
+ setHeight1( data->doubleData( ) );
+ break;
+ case PMHeight2ID:
+ setHeight2( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMPrism::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ if( m->prismPointsSaved( ) )
+ setPoints( m->prismPoints( ) );
+
+ Base::restoreMemento( s );
+}
+
+
+void PMPrism::createViewStructure( )
+{
+ if( s_sSteps == 0 )
+ s_sSteps = c_defaultPrismSSteps;
+
+ int sSteps = (int)( ( (float)s_sSteps / 2 ) * ( displayDetail( ) + 1 ) );
+
+ // calculate number of points and lines of the view structure
+ QValueList< QValueList<PMVector> >::ConstIterator spit = m_points.begin( );
+ int np = 0;
+ for( ; spit != m_points.end( ); ++spit )
+ {
+ int snp = ( *spit ).count( );
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ break;
+ case QuadraticSpline:
+ snp -= 1;
+ break;
+ case CubicSpline:
+ snp -= 2;
+ break;
+ case BezierSpline:
+ snp /= 3;
+ break;
+ }
+ np += snp;
+ }
+
+ int nl = 0;
+ nl = np * sSteps * 3;
+ np *= sSteps * 2;
+
+ if( m_pViewStructure )
+ {
+ if( m_pViewStructure->points( ).size( ) != ( unsigned ) np )
+ m_pViewStructure->points( ).resize( np );
+ if( m_pViewStructure->lines( ).size( ) != ( unsigned ) nl )
+ m_pViewStructure->lines( ).resize( nl );
+ }
+ else
+ m_pViewStructure = new PMViewStructure( np, nl );
+
+ PMLineArray& lines = m_pViewStructure->lines( );
+ PMPointArray& points = m_pViewStructure->points( );
+ int lb = 0;
+ int pb = 0;
+
+ for( spit = m_points.begin( ); spit != m_points.end( ); ++spit )
+ {
+ QValueList<PMSplineSegment> segments;
+ QValueList<PMVector> fullPoints = expandedPoints( *spit );
+
+ int ns = fullPoints.count( );
+ int i, j;
+
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ ns -= 1;
+ break;
+ case QuadraticSpline:
+ ns -= 2;
+ break;
+ case CubicSpline:
+ ns -= 3;
+ break;
+ case BezierSpline:
+ ns = ns / 4;
+ break;
+ }
+ QValueList<PMVector>::Iterator it1, it2, it3, it4;
+
+ // create the spline segments
+ it1 = fullPoints.begin( );
+ it2 = it1; ++it2;
+ it3 = it2; ++it3;
+ it4 = it3; ++it4;
+ PMSplineSegment s;
+
+ for( i = 0; i < ns; ++i )
+ {
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ s.calculateLinear( *it1, *it2 );
+ ++it1;
+ ++it2;
+ break;
+ case QuadraticSpline:
+ s.calculateQuadratic( *it1, *it2, *it3 );
+ ++it1;
+ ++it2;
+ ++it3;
+ break;
+ case CubicSpline:
+ s.calculateCubic( *it1, *it2, *it3, *it4 );
+ ++it1;
+ ++it2;
+ ++it3;
+ ++it4;
+ break;
+ case BezierSpline:
+ s.calculateBezier( *it1, *it2, *it3, *it4 );
+ for( j = 0; j < 4; ++j )
+ {
+ ++it1;
+ ++it2;
+ ++it3;
+ ++it4;
+ }
+ break;
+ }
+ segments.append( s );
+ }
+
+ // create the line array
+ int vp = ns * sSteps;
+ for( i = 0; i < vp - 1; ++i )
+ lines[lb+i] = PMLine( pb + i, pb + i + 1 );
+ lines[lb+vp-1] = PMLine( pb, pb + vp - 1 );
+ lb += vp;
+ for( i = 0; i < vp - 1; ++i )
+ lines[lb+i] = PMLine( pb + vp + i, pb + vp + i + 1 );
+ lines[lb+vp-1] = PMLine( pb + vp, pb + vp + vp - 1 );
+ lb += vp;
+ for( i = 0; i < vp; ++i )
+ lines[lb+i] = PMLine( pb + i, pb + vp + i );
+ lb += vp;
+
+ // calculate the points
+ PMVector point2( 2 ), point3;
+ QValueList<PMSplineSegment>::Iterator sit = segments.begin( );
+ int pi = 0;
+ double poffset = 1.0 / sSteps;
+
+ for( i = 0; i < ns; ++i, ++sit )
+ {
+ for( j = 0; j < sSteps; ++j )
+ {
+ point2 = ( *sit ).point( poffset * j );
+ if( m_sweepType == LinearSweep )
+ {
+ point3[0] = point2[0];
+ point3[1] = m_height1;
+ point3[2] = point2[1];
+ points[pb+pi] = PMPoint( point3 );
+ point3[1] = m_height2;
+ points[pb+pi+vp] = PMPoint( point3 );
+ }
+ else
+ {
+ point3[0] = point2[0];
+ point3[1] = 1.0;
+ point3[2] = point2[1];
+ points[pb+pi] = PMPoint( point3 * m_height1 );
+ points[pb+pi+vp] = PMPoint( point3 * m_height2 );
+ }
+ ++pi;
+ }
+ }
+ pb += vp * 2;
+ }
+}
+
+void PMPrism::controlPoints( PMControlPointList& list )
+{
+ QValueList< QValueList<PMVector> >::Iterator it1;
+ QValueList<PMVector>::Iterator it2;
+ int i1, i2;
+
+ list.append( new PMDistanceControlPoint( PMVector( 0.0, 0.0, 0.0 ),
+ PMVector( 0.0, 1.0, 0.0 ),
+ m_height1, PMHeight1ID,
+ i18n( "Height 1" ) ) );
+ list.append( new PMDistanceControlPoint( PMVector( 0.0, 0.0, 0.0 ),
+ PMVector( 0.0, 1.0, 0.0 ),
+ m_height2, PMHeight2ID,
+ i18n( "Height 2" ) ) );
+
+ PM2DControlPoint* cp;
+
+ for( it1 = m_points.begin( ), i1 = 0; it1 != m_points.end( ); ++it1, ++i1 )
+ {
+ if( m_splineType != BezierSpline )
+ {
+ int refb = ( *it1 ).count( ) - 1;
+ if( m_splineType == CubicSpline )
+ --refb;
+ it2 = ( *it1 ).begin( );
+ PM2DControlPoint* firstPoint = 0;
+ PM2DControlPoint* secondPoint = 0;
+
+ for( i2 = 0; it2 != ( *it1 ).end( ); ++it2, ++i2 )
+ {
+ cp = new PM2DControlPoint( *it2, PM2DControlPoint::PM2DXZ, i2,
+ i18n( "Point %1.%2" ).arg( i1 + 1 ).arg( i2 + 1 ) );
+ if( i2 == 0 )
+ firstPoint = cp;
+ else if( i2 == 1 )
+ secondPoint = cp;
+
+ cp->setThirdCoordinate( m_height2 );
+ if( m_sweepType == ConicSweep )
+ cp->setScale( m_height2 );
+ if( ( ( m_splineType == QuadraticSpline )
+ || ( m_splineType == CubicSpline ) )
+ && ( i2 == 1 ) )
+ firstPoint->setBasePoint( cp );
+ if( ( m_splineType == CubicSpline ) && ( i2 == ( refb + 2 ) ) )
+ cp->setBasePoint( secondPoint );
+
+ list.append( cp );
+
+ if( ( m_splineType != BezierSpline ) && ( i2 == refb ) )
+ ++i2;
+ }
+ }
+ else
+ {
+ it2 = ( *it1 ).begin( );
+ PM2DControlPoint* firstPoint = 0;
+ PM2DControlPoint* lastPoint = 0;
+ PM2DControlPoint* startPoint = 0;
+
+ for( i2 = 0; it2 != ( *it1 ).end( ); ++it2, ++i2 )
+ {
+ int i2mod4 = i2 % 4;
+ cp = new PM2DControlPoint( *it2, PM2DControlPoint::PM2DXZ, i2,
+ i18n( "Point %1.%2" ).arg( i1 + 1 ).arg( i2 + 1 ) );
+ if( i2mod4 == 0 )
+ firstPoint = cp;
+ if( i2mod4 == 2 )
+ lastPoint = cp;
+ if( !startPoint )
+ startPoint = cp;
+
+ cp->setThirdCoordinate( m_height2 );
+ if( m_sweepType == ConicSweep )
+ cp->setScale( m_height2 );
+ if( i2mod4 == 1 )
+ cp->setBasePoint( firstPoint );
+ if( ( i2mod4 == 0 ) && lastPoint )
+ lastPoint->setBasePoint( cp );
+
+ list.append( cp );
+
+ if( i2mod4 == 2 )
+ ++i2;
+ }
+ if( lastPoint )
+ lastPoint->setBasePoint( startPoint );
+ }
+ }
+}
+
+void PMPrism::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPointListIterator it( list );
+ QValueList< QValueList<PMVector> >::Iterator spit = m_points.begin( );
+ QValueList<PMVector>::Iterator pit = ( *spit ).begin( );
+ PM2DControlPoint* p1;
+ PMDistanceControlPoint* dcp;
+ bool firstChange = true;
+ bool h2changed = false;
+
+ // IDs are ignored, quick hack, but should work
+ if( it.current( )->changed( ) )
+ {
+ dcp = ( PMDistanceControlPoint* ) it.current( );
+ setHeight1( dcp->distance( ) );
+ }
+ ++it;
+ if( it.current( )->changed( ) )
+ {
+ dcp = ( PMDistanceControlPoint* ) it.current( );
+ setHeight2( dcp->distance( ) );
+ h2changed = true;
+ }
+ ++it;
+
+ for( ; it.current( ); ++it )
+ {
+ p1 = ( PM2DControlPoint* ) it.current( );
+ if( p1->changed( ) )
+ {
+ if( firstChange )
+ {
+ if( m_pMemento )
+ {
+ PMPrismMemento* m = ( PMPrismMemento* ) m_pMemento;
+ if( !m->prismPointsSaved( ) )
+ m->setPrismPoints( m_points );
+ }
+ firstChange = false;
+ setViewStructureChanged( );
+ }
+ ( *pit ) = p1->point( );
+ }
+ if( h2changed )
+ {
+ p1->setThirdCoordinate( m_height2 );
+ if( m_sweepType == ConicSweep )
+ p1->setScale( m_height2 );
+ }
+
+ ++pit;
+ if( pit == ( *spit ).end( ) )
+ {
+ ++spit;
+ pit = ( *spit ).begin( );
+ }
+ }
+}
+
+void PMPrism::addObjectActions( const PMControlPointList& /*cp*/,
+ QPtrList<PMObjectAction>& actions )
+{
+ PMObjectAction* a;
+
+ a = new PMObjectAction( s_pMetaObject, PMSplitSegmentID,
+ i18n( "Add Point" ) );
+ actions.append( a );
+
+ a = new PMObjectAction( s_pMetaObject, PMJoinSegmentsID,
+ i18n( "Remove Point" ) );
+
+ bool enableJoin = false;
+ QValueList< QValueList<PMVector> >::ConstIterator spit = m_points.begin( );
+
+ int minp = 4;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ minp = 4;
+ break;
+ case QuadraticSpline:
+ minp = 5;
+ break;
+ case CubicSpline:
+ minp = 6;
+ break;
+ case BezierSpline:
+ minp = 6;
+ break;
+ }
+
+ for( ; ( spit != m_points.end( ) ) && !enableJoin; ++spit )
+ if( ( *spit ).count( ) >= ( unsigned ) minp )
+ enableJoin = true;
+
+ a->setEnabled( enableJoin );
+ actions.append( a );
+}
+
+void PMPrism::objectActionCalled( const PMObjectAction* action,
+ const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ if( action->objectType( ) == s_pMetaObject )
+ {
+ switch( action->actionID( ) )
+ {
+ case PMSplitSegmentID:
+ splitSegment( cp, cpViewPosition, clickPosition );
+ break;
+ case PMJoinSegmentsID:
+ joinSegments( cp, cpViewPosition, clickPosition );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMPrism::objectActionCalled\n";
+ break;
+ }
+ }
+ else
+ Base::objectActionCalled( action, cp, cpViewPosition, clickPosition );
+}
+
+void PMPrism::splitSegment( const PMControlPointList& /*cp*/,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ // find nearest segment
+ double abs = 0.0, minabs = 1e10;
+ int ns = -1;
+ int nsp = 0;
+ int spnr = 0, pnr = 0;
+ int i;
+ PMVector mid( 3 ), dist( 2 );
+ PMVector firstPoint( 3 );
+
+ QPtrListIterator<PMVector> it1( cpViewPosition );
+ QPtrListIterator<PMVector> it2( cpViewPosition );
+ for( i = 0; i < 2; ++i ) ++it1;
+ for( i = 0; i < 3; ++i ) ++it2;
+
+ QValueList< QValueList<PMVector> >::Iterator spit = m_points.begin( );
+ for( spnr = 0; spit != m_points.end( ); ++spit, ++spnr )
+ {
+ int nump = ( *spit ).count( );
+ bool first = true;
+ for( pnr = 0; pnr < nump; ++pnr )
+ {
+ bool skip = false;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ case BezierSpline:
+ break;
+ case QuadraticSpline:
+ if( pnr == 0 )
+ skip = true;
+ break;
+ case CubicSpline:
+ if( ( pnr == 0 ) || ( pnr == ( nump - 1 ) ) )
+ skip = true;
+ break;
+ }
+
+ if( !skip )
+ {
+ if( first )
+ {
+ firstPoint = **it1;
+ first = false;
+ }
+
+ if( ( ( m_splineType == CubicSpline ) && ( pnr == ( nump - 2 ) ) )
+ || ( ( m_splineType != CubicSpline ) && ( pnr == ( nump - 1 ) ) ) )
+ mid = ( **it1 + firstPoint ) / 2.0;
+ else
+ mid = ( **it1 + **it2 ) / 2.0;
+
+ dist[0] = mid[0];
+ dist[1] = mid[1];
+ dist -= clickPosition;
+ abs = dist.abs( );
+
+ if( ( minabs > abs ) || ( ns < 0 ) )
+ {
+ minabs = abs;
+ ns = pnr;
+ nsp = spnr;
+ }
+ }
+ ++it1;
+ ++it2;
+ }
+ }
+
+ // add a new segment
+ QValueList< QValueList<PMVector> > newPoints = m_points;
+ spit = newPoints.at( nsp );
+ QValueList<PMVector> newSubPoints = *spit;
+
+ if( m_splineType == BezierSpline )
+ {
+ ns /= 3;
+ ns *= 3;
+ }
+ QValueList<PMVector>::Iterator it = newSubPoints.at( ( unsigned ) ns );
+ PMVector p[4];
+ QValueList<PMVector>::Iterator hit = it, eit = newSubPoints.end( );
+ --eit;
+
+ // calculate the spline segment
+ PMSplineSegment segment;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ for( i = 0; i < 2; ++i )
+ {
+ p[i] = *hit;
+ ++hit;
+ if( hit == newSubPoints.end( ) )
+ hit = newSubPoints.begin( );
+ }
+ segment.calculateLinear( p[0], p[1] );
+ break;
+ case QuadraticSpline:
+ --hit;
+ for( i = 0; i < 3; ++i )
+ {
+ p[i] = *hit;
+ ++hit;
+ if( hit == newSubPoints.end( ) )
+ {
+ hit = newSubPoints.begin( );
+ ++hit;
+ }
+ }
+ segment.calculateQuadratic( p[0], p[1], p[2] );
+ break;
+ case CubicSpline:
+ --hit;
+ for( i = 0; i < 4; ++i )
+ {
+ if( hit == eit )
+ {
+ hit = newSubPoints.begin( );
+ ++hit;
+ p[i] = *hit;
+ hit = eit;
+ ++i;
+ if( i < 4 )
+ p[i] = *hit;
+ }
+ else
+ p[i] = *hit;
+ ++hit;
+ }
+ segment.calculateCubic( p[0], p[1], p[2], p[3] );
+ break;
+ case BezierSpline:
+ for( i = 0; i < 4; ++i )
+ {
+ p[i] = *hit;
+ ++hit;
+ if( hit == newSubPoints.end( ) )
+ hit = newSubPoints.begin( );
+ }
+ segment.calculateBezier( p[0], p[1], p[2], p[3] );
+ break;
+ }
+
+ mid = segment.point( 0.5 );
+ if( m_splineType != BezierSpline )
+ {
+ ++it;
+ newSubPoints.insert( it, mid );
+ }
+ else
+ {
+ PMVector end = *it;
+ ++it;
+ *it = end + ( *it - end ) / 2.0;
+ ++it;
+
+ PMVector grad = segment.gradient( 0.5 ) / 4.0;
+
+ newSubPoints.insert( it, mid - grad );
+ newSubPoints.insert( it, mid );
+ newSubPoints.insert( it, mid + grad );
+
+ ++it;
+ if( it == newSubPoints.end( ) )
+ end = *newSubPoints.begin( );
+ else
+ end = *it;
+ --it;
+ *it = end + ( *it - end ) / 2.0;
+ }
+ ( *spit ) = newSubPoints;
+ setPoints( newPoints );
+}
+
+void PMPrism::joinSegments( const PMControlPointList& /*cp*/,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ // find nearest point
+ double abs = 0.0, minabs = 1e10;
+ int ns = -1;
+ int nsp = 0;
+ int spnr = 0, pnr = 0;
+ int i;
+ PMVector dist( 2 );
+
+ QPtrListIterator<PMVector> it1( cpViewPosition );
+ for( i = 0; i < 2; ++i ) ++it1;
+
+ int minp = 0;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ minp = 4;
+ break;
+ case QuadraticSpline:
+ minp = 5;
+ break;
+ case CubicSpline:
+ minp = 6;
+ break;
+ case BezierSpline:
+ minp = 6;
+ break;
+ }
+
+ QValueList< QValueList<PMVector> >::Iterator spit = m_points.begin( );
+ for( spnr = 0; spit != m_points.end( ); ++spit, ++spnr )
+ {
+ int nump = ( *spit ).count( );
+
+ for( pnr = 0; pnr < nump; ++pnr )
+ {
+ bool skip = false;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ case BezierSpline:
+ break;
+ case QuadraticSpline:
+ if( pnr == 0 )
+ skip = true;
+ break;
+ case CubicSpline:
+ if( ( pnr == 0 ) || ( pnr == ( nump - 1 ) ) )
+ skip = true;
+ break;
+ }
+ if( nump < minp )
+ skip = true;
+
+ if( !skip )
+ {
+ dist[0] = (**it1)[0];
+ dist[1] = (**it1)[1];
+ dist -= clickPosition;
+ abs = dist.abs( );
+
+ if( ( minabs > abs ) || ( ns < 0 ) )
+ {
+ minabs = abs;
+ ns = pnr;
+ nsp = spnr;
+ }
+ }
+ ++it1;
+ }
+ }
+
+ if( ns < 0 )
+ {
+ kdError( PMArea ) << "Not enough points in PMPrism::joinSegments\n";
+ return;
+ }
+
+ // remove the segment
+ QValueList< QValueList<PMVector> > newPoints = m_points;
+ spit = newPoints.at( nsp );
+ QValueList<PMVector> newSubPoints = *spit;
+ QValueList<PMVector>::Iterator it;
+
+ if( m_splineType != BezierSpline )
+ {
+ it = newSubPoints.at( ( unsigned ) ns );
+ newSubPoints.remove( it );
+ }
+ else
+ {
+ int last = ( newSubPoints.count( ) - 3 ) / 3;
+ ns -= 2;
+ if( ns < 0 )
+ ns = last;
+ else
+ ns /= 3;
+
+ it = newSubPoints.at( ns * 3 + 2 );
+ if( ns != last )
+ {
+ it = newSubPoints.remove( it );
+ it = newSubPoints.remove( it );
+ it = newSubPoints.remove( it );
+ }
+ else
+ {
+ newSubPoints.remove( it );
+ it = newSubPoints.begin( );
+ it = newSubPoints.remove( it );
+ it = newSubPoints.remove( it );
+ PMVector h = *it;
+ it = newSubPoints.remove( it );
+ newSubPoints.insert( newSubPoints.end( ), h );
+ }
+ }
+ ( *spit ) = newSubPoints;
+ setPoints( newPoints );
+}
+
+void PMPrism::setSSteps( int s )
+{
+ if( s >= 1 )
+ s_sSteps = s;
+ else
+ kdDebug( PMArea ) << "PMPrism::setSSteps: S must be greater than 0\n";
+ ++s_parameterKey;
+}
+
+QValueList<PMVector> PMPrism::expandedPoints( const QValueList<PMVector>& p ) const
+{
+ // add the missing points
+ int refa = 0, refb = p.count( );
+ QValueList<PMVector> result = p;
+
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ break;
+ case QuadraticSpline:
+ ++refa;
+ break;
+ case CubicSpline:
+ ++refa;
+ --refb;
+ break;
+ case BezierSpline:
+ refb = refb / 3 * 4;
+ break;
+ }
+ QValueList<PMVector>::Iterator it1, it2, it3;
+ if( m_splineType != BezierSpline )
+ {
+ it1 = result.at( refa );
+ it2 = result.at( refb );
+ result.insert( it2, *it1 );
+ }
+ else
+ {
+ int i;
+ it1 = result.begin( );
+ for( i = 1; it1 != result.end( ); ++it1, ++i )
+ {
+ if( ( i % 3 ) == 0 )
+ {
+ it2 = it1;
+ ++it2;
+ it3 = it2;
+ if( it3 == result.end( ) )
+ it3 = result.begin( );
+ it1 = result.insert( it2, *it3 );
+ }
+ }
+ }
+ return result;
+}
diff --git a/kpovmodeler/pmprism.h b/kpovmodeler/pmprism.h
new file mode 100644
index 00000000..64511ee5
--- /dev/null
+++ b/kpovmodeler/pmprism.h
@@ -0,0 +1,224 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPRISM_H
+#define PMPRISM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <math.h>
+
+class PMViewStructure;
+
+/**
+ * Class for povray prism objects.
+ */
+
+class PMPrism : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * The spline type
+ */
+ enum SplineType { LinearSpline, QuadraticSpline, CubicSpline, BezierSpline };
+ /**
+ * The sweep type
+ */
+ enum SweepType { LinearSweep, ConicSweep };
+ /**
+ * Creates an empty PMPrism
+ */
+ PMPrism( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPrism( const PMPrism& p );
+ /**
+ * deletes the PMPrism
+ */
+ virtual ~PMPrism( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPrism( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMPrismEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmprism" ); }
+
+ /** */
+ virtual void createMemento( );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool multipleSelectControlPoints( ) const { return true; }
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual void addObjectActions( const PMControlPointList&,
+ QPtrList<PMObjectAction>& );
+ /** */
+ virtual void objectActionCalled( const PMObjectAction*,
+ const PMControlPointList&,
+ const QPtrList<PMVector>&,
+ const PMVector& );
+
+ /**
+ * Returns the spline points
+ */
+ QValueList< QValueList<PMVector> > points( ) const { return m_points; }
+ /**
+ * Sets the spline points
+ */
+ void setPoints( const QValueList< QValueList<PMVector> >& points );
+ /**
+ * Returns the spline type
+ */
+ SplineType splineType( ) const { return m_splineType; }
+ /**
+ * Sets the spline type
+ */
+ void setSplineType( SplineType t );
+ /**
+ * Returns the sweep type
+ */
+ SweepType sweepType( ) const { return m_sweepType; }
+ /**
+ * Sets the sweep type
+ */
+ void setSweepType( SweepType t );
+ /**
+ * Returns the sturm flag
+ */
+ bool sturm( ) const { return m_sturm; }
+ /**
+ * Sets the sturm flag
+ */
+ void setSturm( bool s );
+ /**
+ * Returns the open flag
+ */
+ bool open( ) const { return m_open; }
+ /**
+ * Sets the open flag
+ */
+ void setOpen( bool o );
+ /**
+ * Returns the height 1
+ */
+ double height1( ) const { return m_height1; }
+ /**
+ * Returns the height 2
+ */
+ double height2( ) const { return m_height2; }
+ /**
+ * Sets the height 1
+ */
+ void setHeight1( double h );
+ /**
+ * Sets the height 2
+ */
+ void setHeight2( double h );
+
+ /**
+ * Sets the number of steps around the y axis
+ */
+ static void setSSteps( int s );
+ /**
+ * Returns the number of steps around the y axis
+ */
+ static int sSteps( ) { return s_sSteps; }
+ /**
+ * Returns the points for POV-Ray serialization (contains additional points)
+ */
+ QValueList<PMVector> expandedPoints( const QValueList<PMVector>& p ) const;
+
+protected:
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey( ); }
+
+private:
+ /**
+ * Object action. Adds a spline point
+ */
+ void splitSegment( const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition );
+ /**
+ * Object action. Removes a spline point
+ */
+ void joinSegments( const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition );
+
+ void stringToValues( const QString& str );
+ QString valuesToString( ) const;
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMPrismMementoID { PMSplineTypeID, PMSweepTypeID, PMSturmID, PMOpenID,
+ PMHeight1ID, PMHeight2ID };
+ /**
+ * IDs for the object actions
+ */
+ enum PMPrismActionID { PMSplitSegmentID, PMJoinSegmentsID };
+ SplineType m_splineType;
+ SweepType m_sweepType;
+ QValueList< QValueList<PMVector> > m_points;
+ double m_height1, m_height2;
+ bool m_sturm;
+ bool m_open;
+
+ static int s_sSteps;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmprismedit.cpp b/kpovmodeler/pmprismedit.cpp
new file mode 100644
index 00000000..13ac49b5
--- /dev/null
+++ b/kpovmodeler/pmprismedit.cpp
@@ -0,0 +1,696 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmprismedit.h"
+#include "pmprism.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmvectorlistedit.h"
+#include "pmpart.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+PMPrismEdit::PMPrismEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+ m_lastSplineType = 0;
+}
+
+PMPrismEdit::~PMPrismEdit( )
+{
+}
+
+void PMPrismEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Spline type:" ), this ) );
+ m_pSplineType = new QComboBox( false, this );
+ m_pSplineType->insertItem( i18n( "Linear Spline" ) );
+ m_pSplineType->insertItem( i18n( "Quadratic Spline" ) );
+ m_pSplineType->insertItem( i18n( "Cubic Spline" ) );
+ m_pSplineType->insertItem( i18n( "Bezier Spline" ) );
+ hl->addWidget( m_pSplineType );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Sweep type:" ), this ) );
+ m_pSweepType = new QComboBox( false, this );
+ m_pSweepType->insertItem( i18n( "Linear Sweep" ) );
+ m_pSweepType->insertItem( i18n( "Conic Sweep" ) );
+ hl->addWidget( m_pSweepType );
+
+ connect( m_pSplineType, SIGNAL( activated( int ) ),
+ SLOT( slotTypeChanged( int ) ) );
+ connect( m_pSweepType, SIGNAL( activated( int ) ),
+ SLOT( slotSweepChanged( int ) ) );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ QGridLayout* gl = new QGridLayout( hl, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Height 1:" ), this ), 0, 0 );
+ m_pHeight1 = new PMFloatEdit( this );
+ gl->addWidget( m_pHeight1, 0, 1 );
+ connect( m_pHeight1, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ gl->addWidget( new QLabel( i18n( "Height 2:" ), this ), 1, 0 );
+ m_pHeight2 = new PMFloatEdit( this );
+ gl->addWidget( m_pHeight2, 1, 1 );
+ connect( m_pHeight2, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ hl->addStretch( 1 );
+}
+
+void PMPrismEdit::createBottomWidgets( )
+{
+ m_pEditWidget = new QWidget( this );
+ topLayout( )->addWidget( m_pEditWidget );
+ m_pOpen = new QCheckBox( i18n( "type of the object", "Open" ), this );
+ topLayout( )->addWidget( m_pOpen );
+ m_pSturm = new QCheckBox( i18n( "Sturm" ), this );
+ topLayout( )->addWidget( m_pSturm );
+ connect( m_pSturm, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOpen, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+
+ Base::createBottomWidgets( );
+}
+
+void PMPrismEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Prism" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMPrism* ) o;
+
+ switch( m_pDisplayedObject->splineType( ) )
+ {
+ case PMPrism::LinearSpline:
+ m_pSplineType->setCurrentItem( 0 );
+ break;
+ case PMPrism::QuadraticSpline:
+ m_pSplineType->setCurrentItem( 1 );
+ break;
+ case PMPrism::CubicSpline:
+ m_pSplineType->setCurrentItem( 2 );
+ break;
+ case PMPrism::BezierSpline:
+ m_pSplineType->setCurrentItem( 3 );
+ break;
+ }
+ m_pSplineType->setEnabled( !readOnly );
+ switch( m_pDisplayedObject->sweepType( ) )
+ {
+ case PMPrism::LinearSweep:
+ m_pSweepType->setCurrentItem( 0 );
+ break;
+ case PMPrism::ConicSweep:
+ m_pSweepType->setCurrentItem( 1 );
+ break;
+ }
+ m_pHeight1->setValue( m_pDisplayedObject->height1( ) );
+ m_pHeight1->setReadOnly( readOnly );
+ m_pHeight2->setValue( m_pDisplayedObject->height2( ) );
+ m_pHeight2->setReadOnly( readOnly );
+ m_pSweepType->setEnabled( !readOnly );
+ m_pSturm->setChecked( m_pDisplayedObject->sturm( ) );
+ m_pSturm->setEnabled( !readOnly );
+ m_pOpen->setChecked( m_pDisplayedObject->open( ) );
+ m_pOpen->setEnabled( !readOnly );
+ displayPoints( m_pDisplayedObject->points( ) );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMPrismEdit: Can't display object\n";
+}
+
+void PMPrismEdit::displayPoints( const QValueList< QValueList<PMVector> >& sp )
+{
+ bool readOnly = m_pDisplayedObject->isReadOnly( );
+
+ // (re)create the edit widget if necessary
+ createEdits( sp );
+
+ QValueList< QValueList<PMVector> >::ConstIterator spit = sp.begin( );
+ QPtrListIterator< PMVectorListEdit > seit( m_points );
+ QPtrListIterator< QPushButton > sbit1( m_removeButtons );
+
+ // display the points
+ for( ; ( spit != sp.end( ) ) && *seit; ++spit, ++seit, ++sbit1 )
+ {
+ ( *seit )->setVectors( *spit );
+ ( *seit )->setReadOnly( readOnly );
+ ( *sbit1 )->setEnabled( !readOnly && ( *spit ).size( ) > 3 );
+ }
+
+ QPtrListIterator< QPushButton > sbit2( m_addAboveButtons );
+ QPtrListIterator< QPushButton > sbit3( m_addBelowButtons );
+ for( ; *sbit2; ++sbit2 )
+ ( *sbit2 )->setEnabled( !readOnly );
+ for( ; *sbit3; ++sbit3 )
+ ( *sbit3 )->setEnabled( !readOnly );
+
+ QPtrListIterator<QPushButton> bit1( m_subPrismAddButtons );
+ for( ; *bit1; ++bit1 )
+ ( *bit1 )->setEnabled( !readOnly );
+ QPtrListIterator<QPushButton> bit2( m_subPrismRemoveButtons );
+ for( ; *bit2; ++bit2 )
+ ( *bit2 )->setEnabled( !readOnly && sp.size( ) > 1 );
+ updateControlPointSelection( );
+}
+
+void PMPrismEdit::createEdits( const QValueList< QValueList<PMVector> >& sp )
+{
+ int st = m_pSplineType->currentItem( );
+
+ if( sp.size( ) != m_points.count( ) )
+ {
+ deleteEdits( );
+
+ QPixmap addPixmap = SmallIcon( "pmaddpoint" );
+ QPixmap removePixmap = SmallIcon( "pmremovepoint" );
+ QPixmap addPrismPixmap = SmallIcon( "pmaddsubprism" );
+ QVBoxLayout* tvl = new QVBoxLayout( m_pEditWidget,
+ 0, KDialog::spacingHint( ) );
+ QHBoxLayout* hl = 0;
+ QVBoxLayout* vl;
+ QLabel* label = 0;
+ QPushButton* button = 0;
+ PMVectorListEdit* vle;
+ int spnr = 0;
+
+ for( spnr = 0; spnr < ( signed ) sp.size( ); spnr++ )
+ {
+ // create all edits for one sub prism
+ hl = new QHBoxLayout( tvl );
+ label = new QLabel( i18n( "Sub prism %1:" ).arg( spnr + 1 ),
+ m_pEditWidget );
+ hl->addWidget( label );
+ hl->addStretch( 1 );
+ m_labels.append( label );
+ label->show( );
+
+ button = new QPushButton( m_pEditWidget );
+ button->setPixmap( addPrismPixmap );
+ m_subPrismAddButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotAddSubPrism( ) ) );
+ hl->addWidget( button );
+ button->show( );
+ QToolTip::add( button, i18n( "Add sub prism" ) );
+
+ button = new QPushButton( m_pEditWidget );
+ button->setPixmap( removePixmap );
+ m_subPrismRemoveButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotRemoveSubPrism( ) ) );
+ hl->addWidget( button );
+ button->show( );
+ if( sp.size( ) < 2 )
+ button->setEnabled( false );
+ QToolTip::add( button, i18n( "Remove sub prism" ) );
+
+ hl = new QHBoxLayout( tvl );
+
+ vle = new PMVectorListEdit( "x", "z", m_pEditWidget );
+ m_points.append( vle );
+ connect( vle, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( vle, SIGNAL( selectionChanged( ) ),
+ SLOT( slotSelectionChanged( ) ) );
+ hl->addWidget( vle, 2 );
+ vle->show( );
+
+ vl = new QVBoxLayout( hl );
+
+ button = new QPushButton( m_pEditWidget );
+ button->setPixmap( SmallIcon( "pmaddpointabove" ) );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotAddPointAbove( ) ) );
+ m_addAboveButtons.append( button );
+ button->show( );
+ vl->addWidget( button );
+ button = new QPushButton( m_pEditWidget );
+ button->setPixmap( SmallIcon( "pmaddpoint" ) );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotAddPointBelow( ) ) );
+ m_addBelowButtons.append( button );
+ button->show( );
+ vl->addWidget( button );
+ button = new QPushButton( m_pEditWidget );
+ button->setPixmap( SmallIcon( "pmremovepoint" ) );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotRemovePoint( ) ) );
+ m_removeButtons.append( button );
+ button->show( );
+ vl->addWidget( button );
+
+ vl->addStretch( 1 );
+
+ tvl->addSpacing( KDialog::spacingHint( ) );
+ }
+
+ hl = new QHBoxLayout( tvl );
+ label = new QLabel( i18n( "New sub prism" ), m_pEditWidget );
+ hl->addWidget( label );
+ hl->addStretch( 1 );
+ m_labels.append( label );
+ label->show( );
+
+ button = new QPushButton( m_pEditWidget );
+ button->setPixmap( addPrismPixmap );
+ m_subPrismAddButtons.append( button );
+ connect( button, SIGNAL( clicked( ) ), SLOT( slotAddSubPrism( ) ) );
+ hl->addWidget( button );
+ button->show( );
+ QToolTip::add( button, i18n( "Append sub prism" ) );
+ }
+
+ QPtrListIterator< PMVectorListEdit > vlit( m_points );
+ QValueList< QValueList< PMVector > >::ConstIterator spit;
+ PMVectorListEdit* vle = 0;
+ bool newSize = false;
+
+ for( spit = sp.begin( ); spit != sp.end( ); ++spit, ++vlit )
+ {
+ int lines = ( *spit ).count( );
+
+ vle = *vlit;
+ if( ( vle->size( ) != lines ) /*|| ( st != m_lastSplineType )*/ )
+ {
+ newSize = true;
+ vle->setSize( lines );
+ }
+ }
+ if( newSize )
+ {
+ m_pEditWidget->updateGeometry( );
+ emit sizeChanged( );
+ }
+
+ m_lastSplineType = st;
+}
+
+void PMPrismEdit::deleteEdits( )
+{
+ m_labels.setAutoDelete( true );
+ m_labels.clear( );
+ m_labels.setAutoDelete( false );
+ m_subPrismAddButtons.setAutoDelete( true );
+ m_subPrismAddButtons.clear( );
+ m_subPrismAddButtons.setAutoDelete( false );
+ m_subPrismRemoveButtons.setAutoDelete( true );
+ m_subPrismRemoveButtons.clear( );
+ m_subPrismRemoveButtons.setAutoDelete( false );
+ m_addAboveButtons.setAutoDelete( true );
+ m_addAboveButtons.clear( );
+ m_addAboveButtons.setAutoDelete( false );
+ m_addBelowButtons.setAutoDelete( true );
+ m_addBelowButtons.clear( );
+ m_addBelowButtons.setAutoDelete( false );
+ m_removeButtons.setAutoDelete( true );
+ m_removeButtons.clear( );
+ m_removeButtons.setAutoDelete( false );
+ m_points.setAutoDelete( true );
+ m_points.clear( );
+ m_points.setAutoDelete( false );
+
+ if( m_pEditWidget->layout( ) )
+ delete m_pEditWidget->layout( );
+}
+
+QValueList< QValueList<PMVector> > PMPrismEdit::splinePoints( )
+{
+ QPtrListIterator< PMVectorListEdit > it( m_points );
+ QValueList< QValueList<PMVector> > values;
+
+ for( ; it.current( ); ++it )
+ values.append( ( *it )->vectors( ) );
+
+ return values;
+}
+
+void PMPrismEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ m_pDisplayedObject->setPoints( splinePoints( ) );
+
+ switch( m_pSplineType->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setSplineType( PMPrism::LinearSpline );
+ break;
+ case 1:
+ m_pDisplayedObject->setSplineType( PMPrism::QuadraticSpline );
+ break;
+ case 2:
+ m_pDisplayedObject->setSplineType( PMPrism::CubicSpline );
+ break;
+ case 3:
+ m_pDisplayedObject->setSplineType( PMPrism::BezierSpline );
+ break;
+ }
+ switch( m_pSweepType->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setSweepType( PMPrism::LinearSweep );
+ break;
+ case 1:
+ m_pDisplayedObject->setSweepType( PMPrism::ConicSweep );
+ break;
+ }
+ m_pDisplayedObject->setSturm( m_pSturm->isChecked( ) );
+ m_pDisplayedObject->setOpen( m_pOpen->isChecked( ) );
+ m_pDisplayedObject->setHeight1( m_pHeight1->value( ) );
+ m_pDisplayedObject->setHeight2( m_pHeight2->value( ) );
+ Base::saveContents( );
+ }
+}
+
+bool PMPrismEdit::isDataValid( )
+{
+ QPtrListIterator< PMVectorListEdit > it( m_points );
+ for( ; it.current( ); ++it )
+ if( !it.current( )->isDataValid( ) )
+ return false;
+
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ int np = it.current( )->size( );
+ switch( m_pSplineType->currentItem( ) )
+ {
+ case 0:
+ if( np < 3 )
+ {
+ KMessageBox::error( this, i18n( "Linear splines need at least 3 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 1:
+ if( np < 4 )
+ {
+ KMessageBox::error( this, i18n( "Quadratic splines need at least 4 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 2:
+ if( np < 5 )
+ {
+ KMessageBox::error( this, i18n( "Cubic splines need at least 5 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 3:
+ if( ( np < 3 ) || ( ( np % 3 ) != 0 ) )
+ {
+ KMessageBox::error( this, i18n( "Bezier splines need 3 points for each segment." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ }
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMPrismEdit::slotTypeChanged( int )
+{
+ displayPoints( splinePoints( ) );
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+void PMPrismEdit::slotSweepChanged( int )
+{
+ emit dataChanged( );
+}
+
+void PMPrismEdit::slotAddPointAbove( )
+{
+ QPushButton* bt = ( QPushButton* ) sender( );
+ if( bt )
+ {
+ int subIndex = m_addAboveButtons.findRef( bt );
+ if( subIndex >= 0 )
+ {
+ PMVectorListEdit* ed = m_points.at( subIndex );
+ int index = ed->currentRow( );
+ if( index >= 0 && index < ed->size( ) )
+ {
+ QValueList<PMVector> points = ed->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ PMVector newPoint = *it;
+ if( index != 0 )
+ {
+ --it;
+ newPoint = ( newPoint + *it ) / 2;
+ ++it;
+ }
+ points.insert( it, newPoint );
+
+ ed->setSize( points.size( ) );
+ ed->setVectors( points );
+ if( points.size( ) > 3 )
+ m_removeButtons.at( subIndex )->setEnabled( true );
+
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+ }
+}
+
+void PMPrismEdit::slotAddPointBelow( )
+{
+ QPushButton* bt = ( QPushButton* ) sender( );
+ if( bt )
+ {
+ int subIndex = m_addBelowButtons.findRef( bt );
+ if( subIndex >= 0 )
+ {
+ PMVectorListEdit* ed = m_points.at( subIndex );
+ int index = ed->currentRow( );
+ if( index >= 0 && index < ed->size( ) )
+ {
+ QValueList<PMVector> points = ed->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ PMVector newPoint = *it;
+ ++it;
+
+ if( it != points.end( ) )
+ newPoint = ( newPoint + *it ) / 2;
+
+ points.insert( it, newPoint );
+
+ ed->setSize( points.size( ) );
+ ed->setVectors( points );
+ ed->setCurrentCell( index + 1, ed->currentColumn( ) );
+ if( points.size( ) > 3 )
+ m_removeButtons.at( subIndex )->setEnabled( true );
+
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+ }
+}
+
+void PMPrismEdit::slotRemovePoint( )
+{
+ QPushButton* bt = ( QPushButton* ) sender( );
+ if( bt )
+ {
+ int subIndex = m_removeButtons.findRef( bt );
+ if( subIndex >= 0 )
+ {
+ PMVectorListEdit* ed = m_points.at( subIndex );
+ int index = ed->currentRow( );
+ if( index >= 0 && index < ed->size( ) )
+ {
+ QValueList<PMVector> points = ed->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ points.remove( it );
+
+ ed->setSize( points.size( ) );
+ ed->setVectors( points );
+ if( points.size( ) <= 3 )
+ m_removeButtons.at( subIndex )->setEnabled( false );
+
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+ }
+}
+
+void PMPrismEdit::slotAddSubPrism( )
+{
+ if( m_pSplineType->currentItem( ) == 3 )
+ {
+ KMessageBox::information( this, i18n( "Sub prisms do not work with "
+ "bezier splines in POV-Ray 3.1." ),
+ i18n( "Warning" ), "subPrismWithBezierSplines" );
+ }
+
+ QPushButton* button = ( QPushButton* ) sender( );
+ if( button )
+ {
+ int index = m_subPrismAddButtons.findRef( button );
+ if( index >= 0 )
+ {
+ QValueList< QValueList<PMVector> > points = splinePoints( );
+ QValueList< QValueList<PMVector> >::Iterator it = points.at( index );
+ QValueList<PMVector> newSubPrism;
+
+ if( it != points.begin( ) )
+ {
+ --it;
+ newSubPrism = *it;
+ ++it;
+
+ // find middle point
+ PMVector mid( 2 );
+ int num = 0;
+ QValueList<PMVector>::Iterator pit = newSubPrism.begin( );
+ for( ; pit != newSubPrism.end( ); ++pit, ++num )
+ mid += *pit;
+ if( num > 0 )
+ mid /= num;
+ for( pit = newSubPrism.begin( ); pit != newSubPrism.end( ); ++pit )
+ *pit = ( *pit - mid ) * 0.8 + mid;
+ }
+ else
+ newSubPrism = *it;
+
+ points.insert( it, newSubPrism );
+ displayPoints( points );
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+}
+
+void PMPrismEdit::slotRemoveSubPrism( )
+{
+ QPushButton* button = ( QPushButton* ) sender( );
+ if( button )
+ {
+ int index = m_subPrismRemoveButtons.findRef( button );
+ if( index >= 0 )
+ {
+ QValueList< QValueList<PMVector> > points = splinePoints( );
+ QValueList< QValueList<PMVector> >::Iterator it = points.at( index );
+
+ if( points.count( ) > 1 )
+ {
+ points.remove( it );
+ displayPoints( points );
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+ }
+}
+
+void PMPrismEdit::slotSelectionChanged( )
+{
+ PMVectorListEdit* edit = ( PMVectorListEdit* ) sender( );
+ if( edit )
+ {
+ QValueList< QValueList< PMVector > > points = m_pDisplayedObject->points( );
+
+ if( m_points.count( ) == points.size( ) )
+ {
+ int i;
+ bool changed = false;
+ QValueList< QValueList< PMVector > >::Iterator spit;
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp ); ++it; ++it;
+ QPtrListIterator<PMVectorListEdit> edit( m_points );
+
+ for( spit = points.begin( ); spit != points.end( ) && it.current( );
+ ++spit, ++edit )
+ {
+ int np = ( *spit ).size( );
+
+ if( ( *edit )->size( ) == np )
+ {
+ for( i = 0; i < np && it.current( ); i++, ++it )
+ ( *it )->setSelected( ( *edit )->isSelected( i ) );
+ changed = true;
+ }
+ else
+ for( i = 0; i < np; i++ )
+ ++it;
+ }
+ if( changed )
+ emit controlPointSelectionChanged( );
+ }
+ }
+}
+
+void PMPrismEdit::updateControlPointSelection( )
+{
+ QValueList< QValueList< PMVector > > points = m_pDisplayedObject->points( );
+
+ if( m_points.count( ) == points.size( ) )
+ {
+ QValueList< QValueList< PMVector > >::Iterator spit;
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp ); ++it; ++it;
+ QPtrListIterator<PMVectorListEdit> edit( m_points );
+
+ for( spit = points.begin( ); spit != points.end( ) && it.current( );
+ ++spit, ++edit )
+ {
+ PMVectorListEdit* vl = *edit;
+ int np = ( *spit ).size( );
+ int i;
+
+ if( vl->size( ) == np )
+ {
+ vl->blockSelectionUpdates( true );
+ bool sb = vl->signalsBlocked( );
+ vl->blockSignals( true );
+
+ vl->clearSelection( );
+ for( i = 0; i < np && it.current( ); i++, ++it )
+ if( ( *it )->selected( ) )
+ vl->select( i );
+
+ vl->blockSignals( sb );
+ vl->blockSelectionUpdates( false );
+ }
+ else
+ for( i = 0; i < np; i++ )
+ ++it;
+ }
+ }
+}
+
+#include "pmprismedit.moc"
diff --git a/kpovmodeler/pmprismedit.h b/kpovmodeler/pmprismedit.h
new file mode 100644
index 00000000..75a65dbd
--- /dev/null
+++ b/kpovmodeler/pmprismedit.h
@@ -0,0 +1,122 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPRISMEDIT_H
+#define PMPRISMEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+#include "pmvectoredit.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+
+
+class PMPrism;
+class PMFloatEdit;
+class PMVectorListEdit;
+class QVBoxLayout;
+class QComboBox;
+class QCheckBox;
+class QPushButton;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMPrism
+ */
+class PMPrismEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMPrismEdit with parent and name
+ */
+ PMPrismEdit( QWidget* parent, const char* name = 0 );
+ /**
+ * Destructor
+ */
+ virtual ~PMPrismEdit( );
+ /** */
+ virtual void displayObject( PMObject* o );
+ /** */
+ void updateControlPointSelection( );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void createBottomWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ /**
+ * Displays the spline points
+ */
+ void displayPoints( const QValueList< QValueList<PMVector> >& list );
+ /**
+ * Returns the spline points from the vector edits
+ */
+ QValueList< QValueList<PMVector> > splinePoints( );
+ /**
+ * Deletes the spline point edits
+ */
+ void deleteEdits( );
+ /**
+ * Creates the edits for the points
+ */
+ void createEdits( const QValueList< QValueList<PMVector> >& points );
+
+protected slots:
+ void slotTypeChanged( int );
+ void slotSweepChanged( int );
+ void slotAddSubPrism( );
+ void slotRemoveSubPrism( );
+ void slotAddPointAbove( );
+ void slotAddPointBelow( );
+ void slotRemovePoint( );
+ void slotSelectionChanged( );
+
+private:
+ PMPrism* m_pDisplayedObject;
+ QPtrList< QLabel > m_labels;
+ QPtrList< QPushButton > m_subPrismAddButtons;
+ QPtrList< QPushButton > m_subPrismRemoveButtons;
+ QPtrList< QPushButton > m_addAboveButtons;
+ QPtrList< QPushButton > m_addBelowButtons;
+ QPtrList< QPushButton > m_removeButtons;
+ QPtrList< PMVectorListEdit> m_points;
+ QWidget* m_pEditWidget;
+ QComboBox* m_pSplineType;
+ QComboBox* m_pSweepType;
+ QCheckBox* m_pSturm;
+ QCheckBox* m_pOpen;
+ PMFloatEdit* m_pHeight1;
+ PMFloatEdit* m_pHeight2;
+ int m_lastSplineType;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmprismmemento.cpp b/kpovmodeler/pmprismmemento.cpp
new file mode 100644
index 00000000..0f50449d
--- /dev/null
+++ b/kpovmodeler/pmprismmemento.cpp
@@ -0,0 +1,55 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmprismmemento.h"
+
+PMPrismMemento::PMPrismMemento( PMObject* originator )
+ : PMMemento( originator )
+{
+ m_bPrismPointsSaved = false;
+}
+
+PMPrismMemento::~PMPrismMemento( )
+{
+}
+
+void PMPrismMemento::setPrismPoints( const QValueList< QValueList<PMVector> >& v )
+{
+ if( !m_bPrismPointsSaved )
+ {
+ // Direct assignment does not work with Qt 2.3.x
+ // The list will be changed later in a graphical
+ // change because QValueList::detach( ) is called
+ // too late!
+ // Copy the list by hand.
+
+ QValueList< QValueList< PMVector > >::ConstIterator sit = v.begin( );
+ for( ; sit != v.end( ); ++sit )
+ {
+ QValueList<PMVector> list;
+ QValueList<PMVector>::ConstIterator it = ( *sit ).begin( );
+ for( ; it != ( *sit ).end( ); ++it )
+ list.append( *it );
+ m_prismPoints.append( list );
+ }
+
+ m_bPrismPointsSaved = true;
+ addChange( PMCData );
+ }
+}
+
+
diff --git a/kpovmodeler/pmprismmemento.h b/kpovmodeler/pmprismmemento.h
new file mode 100644
index 00000000..a45f7fef
--- /dev/null
+++ b/kpovmodeler/pmprismmemento.h
@@ -0,0 +1,71 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPRISMMEMENTO_H
+#define PMPRISMMEMENTO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmmemento.h"
+#include "pmvector.h"
+#include <qvaluelist.h>
+
+
+/**
+ * Memento for @ref PMPrism
+ */
+class PMPrismMemento : public PMMemento
+{
+public:
+ /**
+ * Creates a memento for the object originator
+ */
+ PMPrismMemento( PMObject* originator );
+ /**
+ * Deletes the memento
+ */
+ virtual ~PMPrismMemento( );
+
+ /**
+ * Saves the prism points
+ */
+ void setPrismPoints( const QValueList< QValueList<PMVector> >& v );
+ /**
+ * Returns the prism points
+ */
+ QValueList< QValueList<PMVector> > prismPoints( ) const
+ {
+ return m_prismPoints;
+ }
+ /**
+ * Returns true if the prism points were saved
+ */
+ bool prismPointsSaved( ) const { return m_bPrismPointsSaved; }
+
+private:
+ /**
+ * The stored points
+ */
+ QValueList< QValueList<PMVector> > m_prismPoints;
+ bool m_bPrismPointsSaved;
+};
+
+#endif
diff --git a/kpovmodeler/pmprojectedthrough.cpp b/kpovmodeler/pmprojectedthrough.cpp
new file mode 100644
index 00000000..46ecc51c
--- /dev/null
+++ b/kpovmodeler/pmprojectedthrough.cpp
@@ -0,0 +1,92 @@
+/*
+**************************************************************************
+ description
+ -------------------
+ and : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmprojectedthrough.h"
+
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmnamedobjectedit.h"
+
+#include <klocale.h>
+
+PMMetaObject* PMProjectedThrough::s_pMetaObject = 0;
+PMObject* createNewProjectedThrough( PMPart* part )
+{
+ return new PMProjectedThrough( part );
+}
+
+PMProjectedThrough::PMProjectedThrough( PMPart* part )
+ : Base( part )
+{
+}
+
+PMProjectedThrough::PMProjectedThrough( const PMProjectedThrough& l )
+ : Base( l )
+{
+}
+
+PMProjectedThrough::~PMProjectedThrough( )
+{
+}
+
+
+QString PMProjectedThrough::description( ) const
+{
+ return i18n( "projected through" );
+}
+
+PMMetaObject* PMProjectedThrough::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "ProjectedThrough", Base::metaObject( ),
+ createNewProjectedThrough );
+ // no properties
+ }
+ return s_pMetaObject;
+}
+
+void PMProjectedThrough::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMProjectedThrough::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ Base::serialize( e, doc );
+}
+
+void PMProjectedThrough::readAttributes( const PMXMLHelper& h )
+{
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMProjectedThrough::editWidget( QWidget* parent ) const
+{
+ return new PMNamedObjectEdit( parent );
+}
+
+void PMProjectedThrough::restoreMemento( PMMemento* s )
+{
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmprojectedthrough.h b/kpovmodeler/pmprojectedthrough.h
new file mode 100644
index 00000000..66b2a7bd
--- /dev/null
+++ b/kpovmodeler/pmprojectedthrough.h
@@ -0,0 +1,82 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ -------------------
+ and : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPROJECTEDTHROUGH_H
+#define PMPROJECTEDTHROUGH_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobject.h"
+
+/**
+ * Class for povray projected_through statements.
+ */
+class PMProjectedThrough : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+
+public:
+ /**
+ * Constructor
+ */
+ PMProjectedThrough( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMProjectedThrough( const PMProjectedThrough& l );
+ /**
+ * Deletes the PMProjectedThrough
+ */
+ virtual ~PMProjectedThrough( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMProjectedThrough( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMProjectedThroughEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmprojectedthrough" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmprototypemanager.cpp b/kpovmodeler/pmprototypemanager.cpp
new file mode 100644
index 00000000..f458e248
--- /dev/null
+++ b/kpovmodeler/pmprototypemanager.cpp
@@ -0,0 +1,243 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmprototypemanager.h"
+#include "pmallobjects.h"
+#include <klocale.h>
+
+PMPrototypeManager::PMPrototypeManager( PMPart* part )
+ : m_metaDict( 43 )
+{
+ m_pPart = part;
+ addPrototype( new PMScene( part ) );
+ addPrototype( new PMGlobalSettings( part ) );
+ addPrototype( new PMBox( part ) );
+ addPrototype( new PMSphere( part ) );
+ addPrototype( new PMCylinder( part ) );
+ addPrototype( new PMCone( part ) );
+ addPrototype( new PMTorus( part ) );
+ addPrototype( new PMLathe( part ) );
+ addPrototype( new PMPrism( part ) );
+
+ addPrototype( new PMSurfaceOfRevolution( part ) );
+ addPrototype( new PMSuperquadricEllipsoid( part ) );
+ addPrototype( new PMHeightField( part ) );
+ addPrototype( new PMText( part ) );
+ addPrototype( new PMJuliaFractal( part ) );
+
+ addPrototype( new PMBlob( part ) );
+ addPrototype( new PMBlobSphere( part ) );
+ addPrototype( new PMBlobCylinder( part ) );
+
+ addPrototype( new PMPlane( part ) );
+ addPrototype( new PMPolynom( part ) );
+
+ addPrototype( new PMCSG( part ) );
+ addPrototype( new PMDeclare( part ) );
+ addPrototype( new PMObjectLink( part ) );
+
+ addPrototype( new PMDisc( part ) );
+ addPrototype( new PMBicubicPatch( part ) );
+ addPrototype( new PMTriangle( part ) );
+
+ addPrototype( new PMBoundedBy( part ) );
+ addPrototype( new PMClippedBy( part ) );
+
+ addPrototype( new PMTranslate( part ) );
+ addPrototype( new PMScale( part ) );
+ addPrototype( new PMRotate( part ) );
+ addPrototype( new PMPovrayMatrix( part ) );
+ addPrototype( new PMComment( part ) );
+ addPrototype( new PMRaw( part ) );
+ addPrototype( new PMCamera( part ) );
+ addPrototype( new PMLight( part ) );
+ addPrototype( new PMLooksLike( part ) );
+ addPrototype( new PMProjectedThrough( part ) );
+
+ addPrototype( new PMTexture( part ) );
+ addPrototype( new PMPigment( part ) );
+ addPrototype( new PMSolidColor( part ) );
+ addPrototype( new PMNormal( part ) );
+ addPrototype( new PMFinish( part ) );
+ addPrototype( new PMPattern( part ) );
+ addPrototype( new PMBlendMapModifiers( part ) );
+ addPrototype( new PMImageMap( part ) );
+ addPrototype( new PMTextureMap( part ) );
+ addPrototype( new PMColorMap( part ) );
+ addPrototype( new PMPigmentMap( part ) );
+ addPrototype( new PMNormalMap( part ) );
+ addPrototype( new PMSlopeMap( part ) );
+ addPrototype( new PMDensityMap( part ) );
+ addPrototype( new PMMaterialMap( part ) );
+ addPrototype( new PMBumpMap( part ) );
+ addPrototype( new PMTextureList( part ) );
+ addPrototype( new PMColorList( part ) );
+ addPrototype( new PMPigmentList( part ) );
+ addPrototype( new PMNormalList( part ) );
+ addPrototype( new PMDensityList( part ) );
+ addPrototype( new PMWarp( part ) );
+ addPrototype( new PMQuickColor( part ) );
+ addPrototype( new PMSlope( part ) );
+ addPrototype( new PMSkySphere( part ) );
+ addPrototype( new PMRainbow( part ) );
+ addPrototype( new PMFog( part ) );
+ addPrototype( new PMInterior( part ) );
+ addPrototype( new PMMedia( part ) );
+ addPrototype( new PMMaterial( part ) );
+ addPrototype( new PMDensity( part ) );
+
+ // POV-Ray 3.5 objects
+ addPrototype( new PMIsoSurface( part ) );
+ addPrototype( new PMRadiosity( part ) );
+ addPrototype( new PMGlobalPhotons( part ) );
+ addPrototype( new PMPhotons( part ) );
+ addPrototype( new PMLightGroup( part ) );
+ addPrototype( new PMInteriorTexture( part ) );
+ addPrototype( new PMSphereSweep( part ) );
+ addPrototype( new PMMesh( part ) );
+
+ addDeclarationType( "GraphicalObject", i18n( "object declaration" ), "pmobjectdeclare" );
+ addDeclarationType( "Light", i18n( "object declaration" ), "pmobjectdeclare" );
+ addDeclarationType( "Texture", i18n( "texture declaration" ), "pmtexturedeclare" );
+ addDeclarationType( "Pigment", i18n( "pigment declaration" ), "pmpigmentdeclare" );
+ addDeclarationType( "Normal", i18n( "normal declaration" ), "pmnormaldeclare" );
+ addDeclarationType( "Finish", i18n( "finish declaration" ), "pmfinishdeclare" );
+ addDeclarationType( "TextureMap", i18n( "texture map declaration" ), "pmtexturemapdeclare" );
+ addDeclarationType( "PigmentMap", i18n( "pigment map declaration" ), "pmpigmentmapdeclare" );
+ addDeclarationType( "ColorMap", i18n( "color map declaration" ), "pmcolormapdeclare" );
+ addDeclarationType( "NormalMap", i18n( "normal map declaration" ), "pmnormaldeclare" );
+ addDeclarationType( "SlopeMap", i18n( "slope map declaration" ), "pmslopemapdeclare" );
+ addDeclarationType( "DensityMap", i18n( "density map declaration" ), "pmdensitydeclare" );
+ addDeclarationType( "Interior", i18n( "interior declaration" ), "pminteriordeclare" );
+ addDeclarationType( "Media", i18n( "media declaration" ), "pmmediadeclare" );
+ addDeclarationType( "SkySphere", i18n( "sky sphere declaration" ), "pmskyspheredeclare" );
+ addDeclarationType( "Rainbow", i18n( "rainbow declaration" ), "pmrainbowdeclare" );
+ addDeclarationType( "Fog", i18n( "fog declaration" ), "pmfogdeclare" );
+ addDeclarationType( "Material", i18n( "material declaration" ), "pmmaterialdeclare" );
+ addDeclarationType( "Density", i18n( "density declaration" ), "pmdensitydeclare" );
+ addDeclarationType( "InteriorTexture", i18n( "texture declaration" ), "pminteriortexturedeclare" );
+}
+
+PMPrototypeManager::~PMPrototypeManager( )
+{
+ /*
+ PMObjectListIterator it( m_prototypes );
+ for( ; it.current( ); ++it )
+ it.current( )->cleanUp( );
+ */
+}
+
+void PMPrototypeManager::addPrototype( PMObject* obj )
+{
+ if( !obj )
+ return;
+
+ PMMetaObject* metaObject = obj->metaObject( );
+ PMMetaObject* m2 = m_metaDict.find( metaObject->className( ) );
+ if( m2 )
+ {
+ kdError( PMArea ) << "PMPrototypeManager: Class '"
+ << metaObject->className( )
+ << "' already registered." << endl;
+ }
+ else
+ {
+ if( metaObject->isAbstract( ) )
+ kdError( PMArea ) << "PMPrototypeManager: The meta object for the prototype "
+ << metaObject->className( )
+ << " doesn't have a factory method" << endl;
+
+ m_prototypes.append( metaObject );
+ m_lowerCaseDict[metaObject->className( ).lower( )] = metaObject->className( );
+
+ // insert the meta object and all super classes into the hash table
+ while( metaObject )
+ {
+ if( m_metaDict.find( metaObject->className( ) ) )
+ metaObject = 0;
+ else
+ {
+ m_metaDict.insert( metaObject->className( ), metaObject );
+ metaObject = metaObject->superClass( );
+ }
+ }
+ }
+ delete obj;
+}
+
+void PMPrototypeManager::addDeclarationType( const QString& className,
+ const QString& description,
+ const QString& pixmap )
+{
+ PMMetaObject* m = metaObject( className );
+ if( !m )
+ kdError( PMArea ) << "PMPrototypeManager::addDeclarationType: Unknown class " << className << endl;
+ else
+ m_declareDescriptions.push_back( PMDeclareDescription( m, description, pixmap ) );
+}
+
+QPtrListIterator<PMMetaObject> PMPrototypeManager::prototypeIterator( ) const
+{
+ return QPtrListIterator<PMMetaObject>( m_prototypes );
+}
+
+const QValueList<PMDeclareDescription>& PMPrototypeManager::declarationTypes( ) const
+{
+ return m_declareDescriptions;
+}
+
+PMObject* PMPrototypeManager::newObject( const QString& name ) const
+{
+ if( name.isEmpty( ) )
+ return 0;
+
+ PMMetaObject* meta = m_metaDict.find( name );
+ if( !meta )
+ return 0;
+ return meta->newObject( m_pPart );
+}
+
+PMMetaObject* PMPrototypeManager::metaObject( const QString& name ) const
+{
+ if( name.isNull( ) )
+ return 0;
+ return m_metaDict.find( name );
+}
+
+bool PMPrototypeManager::isA( const QString& className,
+ const QString& baseClass ) const
+{
+ return isA( metaObject( className ), baseClass );
+}
+
+bool PMPrototypeManager::isA( PMMetaObject* c,
+ const QString& baseClass ) const
+{
+ PMMetaObject* bc = metaObject( baseClass );
+ while( c && c != bc )
+ c = c->superClass( );
+ return( c && ( c == bc ) );
+}
+
+QString PMPrototypeManager::className( const QString& lowercase ) const
+{
+ QMap<QString, QString>::const_iterator it = m_lowerCaseDict.find( lowercase );
+ if( it != m_lowerCaseDict.end( ) )
+ return *it;
+ return QString::null;
+}
diff --git a/kpovmodeler/pmprototypemanager.h b/kpovmodeler/pmprototypemanager.h
new file mode 100644
index 00000000..025b8213
--- /dev/null
+++ b/kpovmodeler/pmprototypemanager.h
@@ -0,0 +1,149 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMPTMANAGER_H
+#define PMPTMANAGER_H
+
+#include "pmobject.h"
+#include <qdict.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+
+class PMPart;
+
+/**
+ * Description class for declarations types, used by @ref PMPrototypeManager
+ * and @ref PMDeclare
+ */
+class PMDeclareDescription
+{
+public:
+ PMDeclareDescription( ) { }
+ PMDeclareDescription( const PMDeclareDescription& d )
+ {
+ type = d.type;
+ description = d.description;
+ pixmap = d.pixmap;
+ }
+ PMDeclareDescription( PMMetaObject* t, const QString& d, const QString& p )
+ {
+ type = t;
+ description = d;
+ pixmap = p;
+ }
+ PMDeclareDescription& operator=( const PMDeclareDescription& d )
+ {
+ type = d.type;
+ description = d.description;
+ pixmap = d.pixmap;
+ return *this;
+ }
+ PMMetaObject* type;
+ QString description;
+ QString pixmap;
+};
+
+/**
+ * Prototype manager for @ref PMObject.
+ *
+ * This class stores class and inheritance information for each
+ * available object type.
+ *
+ * Each @ref PMPart class holds one instance of this class. The
+ * available objects depend on the loaded plugins.
+ *
+ * Patterns: Prototype
+ */
+class PMPrototypeManager
+{
+public:
+ /**
+ * Creates a prototype manager for the part.
+ */
+ PMPrototypeManager( PMPart* part );
+ /**
+ * Deletes the prototype manager
+ */
+ ~PMPrototypeManager( );
+ /**
+ * Adds the object to the list of prototypes. The prototype becomes
+ * the owner of the object and will be delete immediately by the
+ * prototype manager.
+ */
+ void addPrototype( PMObject* obj );
+ /**
+ * Adds a declaration type. Needed information is the class type,
+ * the @ref description( ) and the @ref pixmap( )
+ */
+ void addDeclarationType( const QString& className,
+ const QString& description,
+ const QString& pixmap );
+ /**
+ * Returns an iterator to the list of available objects
+ */
+ QPtrListIterator<PMMetaObject> prototypeIterator( ) const;
+ /**
+ * Returns an iterator to the list of available declaration types
+ */
+ const QValueList<PMDeclareDescription>& declarationTypes( ) const;
+ /**
+ * Returns a new PMObject by class name
+ */
+ PMObject* newObject( const QString& name ) const;
+ /**
+ * Returns the meta object by class name or 0 if this class does
+ * not exist.
+ * @see PMMetaObject
+ */
+ PMMetaObject* metaObject( const QString& name ) const;
+ /**
+ * Returns true if the class exists
+ */
+ bool existsClass( const QString& name ) const
+ {
+ return metaObject( name );
+ }
+ /**
+ * Returns true if the second class is a base class for
+ * the first class
+ */
+ bool isA( const QString& className, const QString& baseClassName ) const;
+ /**
+ * Returns true if the second class is a base class for
+ * the first class
+ */
+ bool isA( PMMetaObject* c, const QString& baseClassName ) const;
+ /**
+ * Returns the real class if only the lower case version is know.
+ * Used by the xml parser
+ */
+ QString className( const QString& lowercase ) const;
+ /**
+ * Returns a pointer to the part
+ */
+ PMPart* part( ) const { return m_pPart; }
+
+private:
+ QPtrList<PMMetaObject> m_prototypes;
+ QDict<PMMetaObject> m_metaDict;
+ QMap<QString, QString> m_lowerCaseDict;
+ QValueList<PMDeclareDescription> m_declareDescriptions;
+ PMPart* m_pPart;
+};
+#endif
diff --git a/kpovmodeler/pmquickcolor.cpp b/kpovmodeler/pmquickcolor.cpp
new file mode 100644
index 00000000..fcf34e85
--- /dev/null
+++ b/kpovmodeler/pmquickcolor.cpp
@@ -0,0 +1,132 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmquickcolor.h"
+
+#include "pmxmlhelper.h"
+#include "pmquickcoloredit.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+const PMColor colorDefault = PMColor( 1.0, 1.0, 1.0, 0.0, 0.0 );
+
+PMDefinePropertyClass( PMQuickColor, PMQuickColorProperty );
+
+PMMetaObject* PMQuickColor::s_pMetaObject = 0;
+PMObject* createNewQuickColor( PMPart* part )
+{
+ return new PMQuickColor( part );
+}
+
+PMQuickColor::PMQuickColor( PMPart* part )
+ : Base( part )
+{
+ m_color = colorDefault;
+}
+
+PMQuickColor::PMQuickColor( const PMQuickColor& c )
+ : Base( c )
+{
+ m_color = c.m_color;
+}
+
+PMQuickColor::~PMQuickColor( )
+{
+}
+
+QString PMQuickColor::description( ) const
+{
+ return i18n( "quick color" );
+}
+
+void PMQuickColor::serialize( QDomElement& e, QDomDocument& /*doc*/ ) const
+{
+ e.setAttribute( "quickcolor", m_color.serializeXML( ) );
+}
+
+void PMQuickColor::readAttributes( const PMXMLHelper& h )
+{
+ m_color = h.colorAttribute( "quickcolor", colorDefault );
+}
+
+PMMetaObject* PMQuickColor::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "QuickColor", Base::metaObject( ),
+ createNewQuickColor );
+ s_pMetaObject->addProperty(
+ new PMQuickColorProperty( "color", &PMQuickColor::setColor, &PMQuickColor::color ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMQuickColor::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMQuickColor::setColor( const PMColor& c )
+{
+ if( c != m_color )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMColorID, m_color );
+ m_pMemento->setViewStructureChanged( );
+ }
+ m_color = c;
+ }
+}
+
+PMDialogEditBase* PMQuickColor::editWidget( QWidget* parent ) const
+{
+ return new PMQuickColorEdit( parent );
+}
+
+void PMQuickColor::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMColorID:
+ setColor( data->colorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMQuickColor::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmquickcolor.h b/kpovmodeler/pmquickcolor.h
new file mode 100644
index 00000000..a1dce42d
--- /dev/null
+++ b/kpovmodeler/pmquickcolor.h
@@ -0,0 +1,100 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk2if.ufrj.br
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMQUICKCOLOR_H
+#define PMQUICKCOLOR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+#include "pmcolor.h"
+
+/**
+ * Class for quick colors.
+ * Tell POV-Ray what solid color to use for quick renders instead of a paterned pigment.
+ */
+
+class PMQuickColor : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates a PMQuickColor
+ */
+ PMQuickColor( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMQuickColor( const PMQuickColor& c );
+ /**
+ * deletes the PMQuickColor
+ */
+ virtual ~PMQuickColor( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMQuickColor( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMQuickColorEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmquickcolor" ); }
+
+ /**
+ * Returns the color
+ */
+ PMColor color( ) const { return m_color; }
+ /**
+ * Sets the color
+ */
+ void setColor( const PMColor& c );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMQuickColorMementoID { PMColorID };
+ PMColor m_color;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmquickcoloredit.cpp b/kpovmodeler/pmquickcoloredit.cpp
new file mode 100644
index 00000000..35c21234
--- /dev/null
+++ b/kpovmodeler/pmquickcoloredit.cpp
@@ -0,0 +1,77 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmquickcoloredit.h"
+#include "pmquickcolor.h"
+#include "pmcoloredit.h"
+#include "pmdebug.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMQuickColorEdit::PMQuickColorEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMQuickColorEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout = new QHBoxLayout( topLayout( ) );
+ m_pColorEdit = new PMColorEdit( false, this );
+ layout->addWidget( new QLabel( i18n( "Color:" ), this ), 0, AlignTop );
+ layout->addWidget( m_pColorEdit );
+
+ connect( m_pColorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMQuickColorEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "QuickColor" ) )
+ {
+ m_pDisplayedObject = ( PMQuickColor* ) o;
+ m_pColorEdit->setColor( m_pDisplayedObject->color( ) );
+ m_pColorEdit->setReadOnly( m_pDisplayedObject->isReadOnly( ) );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMQuickColorEdit: Can't display object\n";
+}
+
+void PMQuickColorEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setColor( m_pColorEdit->color( ) );
+ }
+}
+
+bool PMQuickColorEdit::isDataValid( )
+{
+ if( !m_pColorEdit->isDataValid( ) )
+ return false;
+ return Base::isDataValid( );
+}
+
+#include "pmquickcoloredit.moc"
diff --git a/kpovmodeler/pmquickcoloredit.h b/kpovmodeler/pmquickcoloredit.h
new file mode 100644
index 00000000..78759a88
--- /dev/null
+++ b/kpovmodeler/pmquickcoloredit.h
@@ -0,0 +1,65 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Leonardo Skorianez
+ email : lsk@if.ufrj.br
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMQUICKCOLOREDIT_H
+#define PMQUICKCOLOREDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kcolordialog.h>
+
+#include "pmdialogeditbase.h"
+
+class PMQuickColor;
+class PMColorEdit;
+
+/**
+ * Dialog edit class for @ref PMQuickColor.
+ */
+class PMQuickColorEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMQuickColorEdit with parent and name
+ */
+ PMQuickColorEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMQuickColor* m_pDisplayedObject;
+ PMColorEdit* m_pColorEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmradiosity.cpp b/kpovmodeler/pmradiosity.cpp
new file mode 100644
index 00000000..d5446b25
--- /dev/null
+++ b/kpovmodeler/pmradiosity.cpp
@@ -0,0 +1,428 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmradiosity.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmradiosityedit.h"
+
+#include <klocale.h>
+
+const double adcBailoutDefault = 0.01;
+const double brightnessDefault = 1.0;
+const int countDefault = 35;
+const double errorBoundDefault = 1.8;
+const double grayThresholdDefault = 0.0;
+const double lowErrorFactorDefault = 0.5;
+const double maxSampleDefault = -1.0;
+const double minimumReuseDefault = 0.015;
+const int nearestCountDefault = 5;
+const double pretraceStartDefault = 0.08;
+const double pretraceEndDefault = 0.04;
+const int recursionLimitDefault = 2;
+
+PMDefinePropertyClass( PMRadiosity, PMRadiosityProperty );
+PMMetaObject* PMRadiosity::s_pMetaObject = 0;
+PMObject* createNewRadiosity( PMPart* part )
+{
+ return new PMRadiosity( part );
+}
+
+PMRadiosity::PMRadiosity( PMPart* part ) : Base( part )
+{
+ m_adcBailout = adcBailoutDefault;
+ m_alwaysSample = true;
+ m_brightness = brightnessDefault;
+ m_count = countDefault;
+ m_errorBound = errorBoundDefault;
+ m_grayThreshold = grayThresholdDefault;
+ m_lowErrorFactor = lowErrorFactorDefault;
+ m_maxSample = maxSampleDefault;
+ m_media = false;
+ m_minimumReuse = minimumReuseDefault;
+ m_nearestCount = nearestCountDefault;
+ m_normal = false;
+ m_pretraceStart = pretraceStartDefault;
+ m_pretraceEnd = pretraceEndDefault;
+ m_recursionLimit = recursionLimitDefault;
+}
+
+PMRadiosity::PMRadiosity( const PMRadiosity& r )
+ : Base( r )
+{
+ m_adcBailout = r.m_adcBailout;
+ m_alwaysSample = r.m_alwaysSample;
+ m_brightness = r.m_brightness;
+ m_count = r.m_count;
+ m_errorBound = r.m_errorBound;
+ m_grayThreshold = r.m_grayThreshold;
+ m_lowErrorFactor = r.m_lowErrorFactor;
+ m_maxSample = r.m_maxSample;
+ m_media = r.m_media;
+ m_minimumReuse = r.m_minimumReuse;
+ m_nearestCount = r.m_nearestCount;
+ m_normal = r.m_normal;
+ m_pretraceStart = r.m_pretraceStart;
+ m_pretraceEnd = r.m_pretraceEnd;
+ m_recursionLimit = r.m_recursionLimit;
+}
+
+PMRadiosity::~PMRadiosity( )
+{
+}
+
+PMMetaObject* PMRadiosity::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Radiosity", Base::metaObject( ),
+ createNewRadiosity );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "adcBailout", &PMRadiosity::setAdcBailout, &PMRadiosity::adcBailout ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "alwaysSample", &PMRadiosity::setAlwaysSample, &PMRadiosity::alwaysSample ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "brightness", &PMRadiosity::setBrightness, &PMRadiosity::brightness ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "count", &PMRadiosity::setCount, &PMRadiosity::count ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "errorBound", &PMRadiosity::setErrorBound, &PMRadiosity::errorBound ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "grayThreshold", &PMRadiosity::setGrayThreshold, &PMRadiosity::grayThreshold ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "lowErrorFactor", &PMRadiosity::setLowErrorFactor, &PMRadiosity::lowErrorFactor ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "maxSample", &PMRadiosity::setMaxSample, &PMRadiosity::maxSample ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "media", &PMRadiosity::setMedia, &PMRadiosity::media ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "minimumReuse", &PMRadiosity::setMinimumReuse, &PMRadiosity::minimumReuse ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "nearestCount", &PMRadiosity::setNearestCount, &PMRadiosity::nearestCount ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "normal", &PMRadiosity::setNormal, &PMRadiosity::normal ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "pretraceStart", &PMRadiosity::setPretraceStart, &PMRadiosity::pretraceStart ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "pretraceEnd", &PMRadiosity::setPretraceEnd, &PMRadiosity::pretraceEnd ) );
+ s_pMetaObject->addProperty(
+ new PMRadiosityProperty( "recursionLimit", &PMRadiosity::setRecursionLimit, &PMRadiosity::recursionLimit ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMRadiosity::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMRadiosity::description( ) const
+{
+ return i18n( "radiosity" );
+}
+
+void PMRadiosity::serialize( QDomElement& e, QDomDocument& ) const
+{
+ e.setAttribute( "adc_bailout", m_adcBailout );
+
+ if ( m_alwaysSample )
+ e.setAttribute( "always_sample", "1" );
+ else
+ e.setAttribute( "always_sample", "0" );
+
+ e.setAttribute( "brightness", m_brightness );
+ e.setAttribute( "count", m_count );
+ e.setAttribute( "error_bound", m_errorBound );
+ e.setAttribute( "gray_threshold", m_grayThreshold );
+ e.setAttribute( "low_error_factor", m_lowErrorFactor );
+ e.setAttribute( "max_sample", m_maxSample );
+
+ if ( m_media )
+ e.setAttribute( "media", "1" );
+ else
+ e.setAttribute( "media", "0" );
+
+ e.setAttribute( "minimum_reuse", m_minimumReuse );
+ e.setAttribute( "nearest_count", m_nearestCount );
+
+ if ( m_normal )
+ e.setAttribute( "normal", "1" );
+ else
+ e.setAttribute( "normal", "0" );
+
+ e.setAttribute( "pretrace_start", m_pretraceStart );
+ e.setAttribute( "pretrace_end", m_pretraceEnd );
+ e.setAttribute( "recursion_limit", m_recursionLimit );
+}
+
+void PMRadiosity::readAttributes( const PMXMLHelper& h )
+{
+ m_adcBailout = h.doubleAttribute( "adc_bailout", adcBailoutDefault );
+ m_alwaysSample = h.boolAttribute( "always_sample", true );
+ m_brightness = h.doubleAttribute( "brightness", brightnessDefault );
+ m_count = h.intAttribute( "count", countDefault );
+ m_errorBound = h.doubleAttribute( "error_bound", errorBoundDefault );
+ m_grayThreshold = h.doubleAttribute( "gray_threshold", grayThresholdDefault );
+ m_lowErrorFactor = h.doubleAttribute( "low_error_factor", lowErrorFactorDefault );
+ m_maxSample = h.doubleAttribute( "max_sample", maxSampleDefault );
+ m_media = h.boolAttribute( "media", false );
+ m_minimumReuse = h.doubleAttribute( "minimum_reuse", minimumReuseDefault );
+ m_nearestCount = h.intAttribute( "nearest_count", nearestCountDefault );
+ m_normal = h.boolAttribute( "normal", false );
+ m_pretraceStart = h.doubleAttribute( "pretrace_start", pretraceStartDefault );
+ m_pretraceEnd = h.doubleAttribute( "pretrace_end", pretraceEndDefault );
+ m_recursionLimit = h.intAttribute( "recursion_limit", recursionLimitDefault );
+}
+
+void PMRadiosity::setAdcBailout( double ab )
+{
+ if( ab != m_adcBailout )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAdcBailoutID, m_adcBailout );
+ m_adcBailout = ab;
+ }
+}
+
+void PMRadiosity::setAlwaysSample( bool as )
+{
+ if( as != m_alwaysSample )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAlwaysSampleID, m_alwaysSample );
+ m_alwaysSample = as;
+ }
+}
+
+void PMRadiosity::setBrightness( double b )
+{
+ if( b != m_brightness )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMBrightnessID, m_brightness );
+ m_brightness = b;
+ }
+}
+
+void PMRadiosity::setCount( int c )
+{
+ if( c != m_count )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCountID, m_count );
+ m_count = c;
+ }
+}
+
+void PMRadiosity::setErrorBound( double eb )
+{
+ if( eb != m_errorBound )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMErrorBoundID, m_errorBound );
+ m_errorBound = eb;
+ }
+}
+
+void PMRadiosity::setGrayThreshold( double gt )
+{
+ if( gt != m_grayThreshold )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMGrayThresholdID, m_grayThreshold );
+ m_grayThreshold = gt;
+ }
+}
+
+void PMRadiosity::setLowErrorFactor( double lew )
+{
+ if( lew != m_lowErrorFactor )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLowErrorFactorID, m_lowErrorFactor );
+ m_lowErrorFactor = lew;
+ }
+}
+
+void PMRadiosity::setMaxSample( double ms )
+{
+ if( ms != m_maxSample )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMaxSampleID, m_maxSample );
+ m_maxSample = ms;
+ }
+}
+
+void PMRadiosity::setMedia( bool m )
+{
+ if( m != m_media )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMediaID, m_media );
+ m_media = m;
+ }
+}
+
+void PMRadiosity::setMinimumReuse( double c )
+{
+ if( c != m_minimumReuse )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMinimumReuseID, m_minimumReuse );
+ m_minimumReuse = c;
+ }
+}
+
+void PMRadiosity::setNearestCount( int c )
+{
+ if( c != m_nearestCount )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNearestCountID, m_nearestCount );
+ m_nearestCount = c;
+ }
+}
+
+void PMRadiosity::setNormal( bool n )
+{
+ if( n != m_normal )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNormalID, m_normal );
+ m_normal = n;
+ }
+}
+
+void PMRadiosity::setPretraceStart( double ps )
+{
+ if ( ps < m_pretraceEnd )
+ {
+ kdError( PMArea ) << "Pretrace Start < Pretrace End in PMRadiosity::setPretraceStart\n";
+ ps = m_pretraceEnd;
+ }
+
+ if( ps != m_pretraceStart )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPretraceStartID, m_pretraceStart );
+ m_pretraceStart = ps;
+ }
+}
+
+void PMRadiosity::setPretraceEnd( double pe )
+{
+ if ( pe > m_pretraceStart )
+ {
+ kdError( PMArea ) << "Pretrace End > Pretrace Start in PMRadiosity::setPretraceEnd\n";
+ pe = m_pretraceStart;
+ }
+
+ if( pe != m_pretraceEnd )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPretraceEndID, m_pretraceEnd );
+ m_pretraceEnd = pe;
+ }
+}
+
+void PMRadiosity::setRecursionLimit( int c )
+{
+ if( c != m_recursionLimit )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRecursionLimitID, m_recursionLimit );
+ m_recursionLimit = c;
+ }
+}
+
+PMDialogEditBase* PMRadiosity::editWidget( QWidget* parent ) const
+{
+ return new PMRadiosityEdit( parent );
+}
+
+void PMRadiosity::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMAdcBailoutID:
+ setAdcBailout( data->doubleData( ) );
+ break;
+ case PMAlwaysSampleID:
+ setAlwaysSample( data->boolData( ) );
+ break;
+ case PMBrightnessID:
+ setBrightness( data->doubleData( ) );
+ break;
+ case PMCountID:
+ setCount( data->intData( ) );
+ break;
+ case PMErrorBoundID:
+ setErrorBound( data->doubleData( ) );
+ break;
+ case PMGrayThresholdID:
+ setGrayThreshold( data->doubleData( ) );
+ break;
+ case PMLowErrorFactorID:
+ setLowErrorFactor( data->doubleData( ) );
+ break;
+ case PMMaxSampleID:
+ setMaxSample( data->doubleData( ) );
+ break;
+ case PMMediaID:
+ setMedia( data->boolData( ) );
+ break;
+ case PMMinimumReuseID:
+ setMinimumReuse( data->doubleData( ) );
+ break;
+ case PMNearestCountID:
+ setNearestCount( data->intData( ) );
+ break;
+ case PMNormalID:
+ setNormal( data->boolData( ) );
+ break;
+ case PMPretraceStartID:
+ setPretraceStart( data->doubleData( ) );
+ break;
+ case PMPretraceEndID:
+ setPretraceEnd( data->doubleData( ) );
+ break;
+ case PMRecursionLimitID:
+ setRecursionLimit( data->intData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMRadiosity::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmradiosity.h b/kpovmodeler/pmradiosity.h
new file mode 100644
index 00000000..56a1cbd4
--- /dev/null
+++ b/kpovmodeler/pmradiosity.h
@@ -0,0 +1,241 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMRADIOSITY_H
+#define PMRADIOSITY_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+/**
+ * Class for radiosity settings.
+ */
+
+class PMRadiosity : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates a PMRadiosity
+ */
+ PMRadiosity( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMRadiosity( const PMRadiosity& r );
+ /**
+ * deletes the PMRadiosity
+ */
+ virtual ~PMRadiosity( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMRadiosity( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMRadiosityEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmradiosity" ); }
+
+ /**
+ * Returns the adc bailout
+ */
+ double adcBailout( ) const { return m_adcBailout; }
+ /**
+ * Sets the adc bailout
+ */
+ void setAdcBailout( double ab );
+
+ /**
+ * Returns the always sample flag
+ */
+ bool alwaysSample( ) const { return m_alwaysSample; }
+ /**
+ * Sets the always sample flag
+ */
+ void setAlwaysSample( bool as );
+
+ /**
+ * Returns brightness
+ */
+ double brightness( ) const { return m_brightness; }
+ /**
+ * Sets the brightness
+ */
+ void setBrightness( double b );
+
+ /**
+ * Returns count
+ */
+ int count( ) const { return m_count; }
+ /**
+ * Sets the count
+ */
+ void setCount( int c );
+
+ /**
+ * Returns error boundary
+ */
+ double errorBound( ) const { return m_errorBound; }
+ /**
+ * Sets the error boundary
+ */
+ void setErrorBound( double eb );
+
+ /**
+ * Returns gray threshold
+ */
+ double grayThreshold( ) const { return m_grayThreshold; }
+ /**
+ * Sets the gray threshold
+ */
+ void setGrayThreshold( double gt );
+
+ /**
+ * Returns low error factor
+ */
+ double lowErrorFactor( ) const { return m_lowErrorFactor; }
+ /**
+ * Sets the low error factor
+ */
+ void setLowErrorFactor( double lew );
+
+ /**
+ * Returns the maximum sample
+ */
+ double maxSample( ) const { return m_maxSample; }
+ /**
+ * Sets the maximum sample
+ */
+ void setMaxSample( double ms );
+
+ /**
+ * Returns the media flag
+ */
+ bool media( ) const { return m_media; }
+ /**
+ * Sets the media flag
+ */
+ void setMedia( bool m );
+
+ /**
+ * Returns minimum reuse
+ */
+ double minimumReuse( ) const { return m_minimumReuse; }
+ /**
+ * Sets the minimum reuse
+ */
+ void setMinimumReuse( double mr );
+
+ /**
+ * Returns nearest count
+ */
+ int nearestCount( ) const { return m_nearestCount; }
+ /**
+ * Sets the nearest count
+ */
+ void setNearestCount( int nc );
+
+ /**
+ * Returns the normal flag
+ */
+ bool normal( ) const { return m_normal; }
+ /**
+ * Sets the normal flag
+ */
+ void setNormal( bool n );
+
+ /**
+ * Returns the pretrace start
+ */
+ double pretraceStart( ) const { return m_pretraceStart; }
+ /**
+ * Sets the pretrace start
+ */
+ void setPretraceStart( double ps );
+
+ /**
+ * Returns the pretrace end
+ */
+ double pretraceEnd( ) const { return m_pretraceEnd; }
+ /**
+ * Sets the pretrace end
+ */
+ void setPretraceEnd( double pe );
+
+ /**
+ * Returns recursion limit
+ */
+ int recursionLimit( ) const { return m_recursionLimit; }
+ /**
+ * Sets the recursion limit
+ */
+ void setRecursionLimit( int rl );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMRadiosityMementoID { PMAdcBailoutID, PMAlwaysSampleID, PMBrightnessID,
+ PMCountID, PMErrorBoundID, PMGrayThresholdID,
+ PMLowErrorFactorID, PMMaxSampleID, PMMediaID,
+ PMMinimumReuseID, PMNearestCountID, PMNormalID,
+ PMPretraceStartID, PMPretraceEndID, PMRecursionLimitID };
+
+ double m_adcBailout;
+ bool m_alwaysSample;
+ double m_brightness;
+ int m_count;
+ double m_errorBound;
+ double m_grayThreshold;
+ double m_lowErrorFactor;
+ double m_maxSample;
+ bool m_media;
+ double m_minimumReuse;
+ int m_nearestCount;
+ bool m_normal;
+ double m_pretraceStart;
+ double m_pretraceEnd;
+ int m_recursionLimit;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmradiosityedit.cpp b/kpovmodeler/pmradiosityedit.cpp
new file mode 100644
index 00000000..1154214d
--- /dev/null
+++ b/kpovmodeler/pmradiosityedit.cpp
@@ -0,0 +1,233 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmradiosityedit.h"
+#include "pmradiosity.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+
+
+PMRadiosityEdit::PMRadiosityEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMRadiosityEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+ QGridLayout *gl;
+ QLabel* lbl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 15, 2 );
+
+ lbl = new QLabel( i18n( "Adc bailout:" ), this );
+ m_pAdcBailout = new PMFloatEdit( this );
+ m_pAdcBailout->setValidation( true, 0, true, 1 );
+ gl->addWidget( lbl, 0, 0 );
+ gl->addWidget( m_pAdcBailout, 0, 1 );
+
+ m_pAlwaysSample = new QCheckBox( i18n( "Always sample" ), this );
+ gl->addMultiCellWidget( m_pAlwaysSample, 1, 1, 0, 1 );
+
+ lbl = new QLabel( i18n( "Brightness:" ), this );
+ m_pBrightness = new PMFloatEdit( this );
+ m_pBrightness->setValidation( true, 0, false, 0 );
+ gl->addWidget( lbl, 2, 0 );
+ gl->addWidget( m_pBrightness, 2, 1 );
+
+ lbl = new QLabel( i18n( "Count:" ), this );
+ m_pCount = new PMIntEdit( this );
+ m_pCount->setValidation( true, 0, true, 1600 );
+ gl->addWidget( lbl, 3, 0 );
+ gl->addWidget( m_pCount, 3, 1 );
+
+ lbl = new QLabel( i18n( "Error boundary:" ), this );
+ m_pErrorBound = new PMFloatEdit( this );
+ m_pErrorBound->setValidation( true, 0, false, 0 );
+ gl->addWidget( lbl, 4, 0 );
+ gl->addWidget( m_pErrorBound, 4, 1 );
+
+ lbl = new QLabel( i18n( "Gray threshold:" ), this );
+ m_pGrayThreshold = new PMFloatEdit( this );
+ m_pGrayThreshold->setValidation( true, 0, true, 1 );
+ gl->addWidget( lbl, 5, 0 );
+ gl->addWidget( m_pGrayThreshold, 5, 1 );
+
+ lbl = new QLabel( i18n( "Low error factor:" ), this );
+ m_pLowErrorFactor = new PMFloatEdit( this );
+ m_pLowErrorFactor->setValidation( true, 0, true, 1 );
+ gl->addWidget( lbl, 6, 0 );
+ gl->addWidget( m_pLowErrorFactor, 6, 1 );
+
+ lbl = new QLabel( i18n( "Maximum sample:" ), this );
+ m_pMaxSample = new PMFloatEdit( this );
+ m_pMaxSample->setValidation( true, -1, false, 0 );
+ gl->addWidget( lbl, 7, 0 );
+ gl->addWidget( m_pMaxSample, 7, 1 );
+
+ m_pMedia = new QCheckBox( i18n( "Media" ), this );
+ gl->addMultiCellWidget( m_pMedia, 8, 8, 0, 1 );
+
+ lbl = new QLabel( i18n( "Minimum reuse:" ), this );
+ m_pMinimumReuse = new PMFloatEdit( this );
+ m_pMinimumReuse->setValidation( true, 0, true, 1 );
+ gl->addWidget( lbl, 9, 0 );
+ gl->addWidget( m_pMinimumReuse, 9, 1 );
+
+ lbl = new QLabel( i18n( "Nearest count:" ), this );
+ m_pNearestCount = new PMIntEdit( this );
+ m_pNearestCount->setValidation( true, 0, true, 20 );
+ gl->addWidget( lbl, 10, 0 );
+ gl->addWidget( m_pNearestCount, 10, 1 );
+
+ m_pNormal = new QCheckBox( i18n( "Normal" ), this );
+ gl->addMultiCellWidget( m_pNormal, 11, 11, 0, 1 );
+
+ lbl = new QLabel( i18n( "Pretrace start:" ), this );
+ m_pPretraceStart = new PMFloatEdit( this );
+ m_pPretraceStart->setValidation( true, 0, true, 1 );
+ gl->addWidget( lbl, 12, 0 );
+ gl->addWidget( m_pPretraceStart, 12, 1 );
+
+ lbl = new QLabel( i18n( "Pretrace end:" ), this );
+ m_pPretraceEnd = new PMFloatEdit( this );
+ m_pPretraceEnd->setValidation( true, 0, true, 1 );
+ gl->addWidget( lbl, 13, 0 );
+ gl->addWidget( m_pPretraceEnd, 13, 1 );
+
+ lbl = new QLabel( i18n( "Recursion limit:" ), this );
+ m_pRecursionLimit = new PMIntEdit( this );
+ m_pRecursionLimit->setValidation( true, 1, true, 20 );
+ gl->addWidget( lbl, 14, 0 );
+ gl->addWidget( m_pRecursionLimit, 14, 1 );
+
+ hl->addStretch( 1 );
+
+ connect( m_pAdcBailout, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAlwaysSample, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pBrightness, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pCount, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pErrorBound, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pGrayThreshold, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pLowErrorFactor, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMaxSample, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMedia, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMinimumReuse, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pNearestCount, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pNormal, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPretraceStart, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPretraceEnd, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRecursionLimit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMRadiosityEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Radiosity" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMRadiosity* ) o;
+
+ m_pAdcBailout->setValue( m_pDisplayedObject->adcBailout( ) );
+ m_pAdcBailout->setReadOnly( readOnly );
+ m_pAlwaysSample->setChecked( m_pDisplayedObject->alwaysSample( ) );
+ m_pAlwaysSample->setEnabled( !readOnly );
+ m_pBrightness->setValue( m_pDisplayedObject->brightness( ) );
+ m_pBrightness->setReadOnly( readOnly );
+ m_pCount->setValue( m_pDisplayedObject->count( ) );
+ m_pCount->setReadOnly( readOnly );
+ m_pErrorBound->setValue( m_pDisplayedObject->errorBound( ) );
+ m_pErrorBound->setReadOnly( readOnly );
+ m_pGrayThreshold->setValue( m_pDisplayedObject->grayThreshold( ) );
+ m_pGrayThreshold->setReadOnly( readOnly );
+ m_pLowErrorFactor->setValue( m_pDisplayedObject->lowErrorFactor( ) );
+ m_pLowErrorFactor->setReadOnly( readOnly );
+ m_pMaxSample->setValue( m_pDisplayedObject->maxSample( ) );
+ m_pMaxSample->setReadOnly( readOnly );
+ m_pMedia->setChecked( m_pDisplayedObject->media( ) );
+ m_pMedia->setEnabled( !readOnly );
+ m_pMinimumReuse->setValue( m_pDisplayedObject->minimumReuse( ) );
+ m_pMinimumReuse->setReadOnly( readOnly );
+ m_pNearestCount->setValue( m_pDisplayedObject->nearestCount( ) );
+ m_pNearestCount->setReadOnly( readOnly );
+ m_pNormal->setChecked( m_pDisplayedObject->normal( ) );
+ m_pNormal->setEnabled( !readOnly );
+ m_pPretraceStart->setValue( m_pDisplayedObject->pretraceStart( ) );
+ m_pPretraceStart->setReadOnly( readOnly );
+ m_pPretraceEnd->setValue( m_pDisplayedObject->pretraceEnd( ) );
+ m_pPretraceEnd->setReadOnly( readOnly );
+ m_pRecursionLimit->setValue( m_pDisplayedObject->recursionLimit( ) );
+ m_pRecursionLimit->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMRadiosityEdit: Can't display object\n";
+}
+
+void PMRadiosityEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setAdcBailout( m_pAdcBailout->value( ) );
+ m_pDisplayedObject->setAlwaysSample( m_pAlwaysSample->isChecked( ) );
+ m_pDisplayedObject->setBrightness( m_pBrightness->value( ) );
+ m_pDisplayedObject->setCount( m_pCount->value( ) );
+ m_pDisplayedObject->setErrorBound( m_pErrorBound->value( ) );
+ m_pDisplayedObject->setGrayThreshold( m_pGrayThreshold->value( ) );
+ m_pDisplayedObject->setLowErrorFactor( m_pLowErrorFactor->value( ) );
+ m_pDisplayedObject->setMaxSample( m_pMaxSample->value( ) );
+ m_pDisplayedObject->setMedia( m_pMedia->isChecked( ) );
+ m_pDisplayedObject->setMinimumReuse( m_pMinimumReuse->value( ) );
+ m_pDisplayedObject->setNearestCount( m_pNearestCount->value( ) );
+ m_pDisplayedObject->setNormal( m_pNormal->isChecked( ) );
+ m_pDisplayedObject->setPretraceStart( m_pPretraceStart->value( ) );
+ m_pDisplayedObject->setPretraceEnd( m_pPretraceEnd->value( ) );
+ m_pDisplayedObject->setRecursionLimit( m_pRecursionLimit->value( ) );
+ }
+}
+
+bool PMRadiosityEdit::isDataValid( )
+{
+ if( !m_pAdcBailout->isDataValid( ) ) return false;
+ if( !m_pBrightness->isDataValid( ) ) return false;
+ if( !m_pCount->isDataValid( ) ) return false;
+ if( !m_pErrorBound->isDataValid( ) ) return false;
+ if( !m_pGrayThreshold->isDataValid( ) ) return false;
+ if( !m_pLowErrorFactor->isDataValid( ) ) return false;
+ if( !m_pMaxSample->isDataValid( ) ) return false;
+ if( !m_pMinimumReuse->isDataValid( ) ) return false;
+ if( !m_pNearestCount->isDataValid( ) ) return false;
+ if( !m_pPretraceStart->isDataValid( ) ) return false;
+ if( !m_pPretraceEnd->isDataValid( ) ) return false;
+ if( !m_pRecursionLimit->isDataValid( ) ) return false;
+
+ return Base::isDataValid( );
+}
+
+#include "pmradiosityedit.moc"
diff --git a/kpovmodeler/pmradiosityedit.h b/kpovmodeler/pmradiosityedit.h
new file mode 100644
index 00000000..37ee18c7
--- /dev/null
+++ b/kpovmodeler/pmradiosityedit.h
@@ -0,0 +1,81 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Leon Pennington
+ email : leon@leonscape.co.uk
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMRADIOSITYEDIT_H
+#define PMRADIOSITYEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMRadiosity;
+class PMFloatEdit;
+class PMIntEdit;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMRadiosity.
+ */
+class PMRadiosityEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMRadiosityEdit with parent and name
+ */
+ PMRadiosityEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+
+private:
+ PMRadiosity* m_pDisplayedObject;
+
+ PMFloatEdit* m_pAdcBailout;
+ QCheckBox* m_pAlwaysSample;
+ PMFloatEdit* m_pBrightness;
+ PMIntEdit* m_pCount;
+ PMFloatEdit* m_pErrorBound;
+ PMFloatEdit* m_pGrayThreshold;
+ PMFloatEdit* m_pLowErrorFactor;
+ PMFloatEdit* m_pMaxSample;
+ QCheckBox* m_pMedia;
+ PMFloatEdit* m_pMinimumReuse;
+ PMIntEdit* m_pNearestCount;
+ QCheckBox* m_pNormal;
+ PMFloatEdit* m_pPretraceStart;
+ PMFloatEdit* m_pPretraceEnd;
+ PMIntEdit* m_pRecursionLimit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmrainbow.cpp b/kpovmodeler/pmrainbow.cpp
new file mode 100644
index 00000000..5a80e013
--- /dev/null
+++ b/kpovmodeler/pmrainbow.cpp
@@ -0,0 +1,422 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmrainbow.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmrainbowedit.h"
+#include "pmvector.h"
+
+#include <klocale.h>
+
+PMMetaObject* PMRainbow::s_pMetaObject = 0;
+PMObject* createNewRainbow( PMPart* part )
+{
+ return new PMRainbow( part );
+}
+
+const PMVector directionDefault = PMVector( 0.0, 0.0, 0.0 );
+const double angleDefault = 0.0;
+const double widthDefault = 0.0;
+const double distanceDefault = 0.0;
+const double jitterDefault = 0.0;
+const PMVector upDefault = PMVector( 0.0, 0.0, 0.0 );
+const double arcAngleDefault = 0.0;
+const double falloffAngleDefault = 0.0;
+
+PMDefinePropertyClass( PMRainbow, PMRainbowProperty );
+
+PMRainbow::PMRainbow( PMPart* part )
+ : Base( part )
+{
+ m_direction = directionDefault;
+ m_angle = angleDefault;
+ m_width = widthDefault;
+ m_distance = distanceDefault;
+ m_jitter = jitterDefault;
+ m_up = upDefault;
+ m_arcAngle = arcAngleDefault;
+ m_falloffAngle = falloffAngleDefault;
+ m_enableDirection = false;
+ m_enableAngle = false;
+ m_enableWidth = false;
+ m_enableDistance = false;
+ m_enableJitter = false;
+ m_enableUp = false;
+ m_enableArcAngle = false;
+ m_enableFalloffAngle = false;
+}
+
+PMRainbow::PMRainbow( const PMRainbow& r )
+ : Base( r )
+{
+ m_direction = r.m_direction;
+ m_angle = r.m_angle;
+ m_width = r.m_width;
+ m_distance = r.m_distance;
+ m_jitter = r.m_jitter;
+ m_up = r.m_up;
+ m_arcAngle = r.m_arcAngle;
+ m_falloffAngle = r.m_falloffAngle;
+ m_enableDirection = r.m_enableDirection;
+ m_enableAngle = r.m_enableAngle;
+ m_enableWidth = r.m_enableWidth;
+ m_enableDistance = r.m_enableDistance;
+ m_enableJitter = r.m_enableJitter;
+ m_enableUp = r.m_enableUp;
+ m_enableArcAngle = r.m_enableArcAngle;
+ m_enableFalloffAngle = r.m_enableFalloffAngle;
+}
+
+PMRainbow::~PMRainbow( )
+{
+}
+
+PMMetaObject* PMRainbow::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Rainbow", Base::metaObject( ),
+ createNewRainbow );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "direction", &PMRainbow::setDirection, &PMRainbow::direction ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "angle", &PMRainbow::setAngle, &PMRainbow::angle ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "width", &PMRainbow::setWidth, &PMRainbow::width ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "distance", &PMRainbow::setDistance, &PMRainbow::distance ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "jitter", &PMRainbow::setJitter, &PMRainbow::jitter ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "up", &PMRainbow::setUp, &PMRainbow::up ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "arcAngle", &PMRainbow::setArcAngle, &PMRainbow::arcAngle ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "falloffAngle", &PMRainbow::setFalloffAngle, &PMRainbow::falloffAngle ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "directionEnabled", &PMRainbow::enableDirection, &PMRainbow::isDirectionEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "angleEnabled", &PMRainbow::enableAngle, &PMRainbow::isAngleEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "widthEnabled", &PMRainbow::enableWidth, &PMRainbow::isWidthEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "distanceEnabled", &PMRainbow::enableDistance, &PMRainbow::isDistanceEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "jitterEnabled", &PMRainbow::enableJitter, &PMRainbow::isJitterEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "upEnabled", &PMRainbow::enableUp, &PMRainbow::isUpEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "arcAngleEnabled", &PMRainbow::enableArcAngle, &PMRainbow::isArcAngleEnabled ) );
+ s_pMetaObject->addProperty(
+ new PMRainbowProperty( "falloffAngleEnabled", &PMRainbow::enableFalloffAngle, &PMRainbow::isFalloffAngleEnabled ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMRainbow::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMRainbow::description( ) const
+{
+ return i18n( "rainbow" );
+}
+
+void PMRainbow::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ Base::serialize( e, doc );
+ e.setAttribute( "enable_direction", m_enableDirection );
+ e.setAttribute( "enable_angle", m_enableAngle );
+ e.setAttribute( "enable_width", m_enableWidth );
+ e.setAttribute( "enable_distance", m_enableDistance );
+ e.setAttribute( "enable_jitter", m_enableJitter );
+ e.setAttribute( "enable_up", m_enableUp );
+ e.setAttribute( "enable_arc_angle", m_enableArcAngle );
+ e.setAttribute( "enable_falloff_angle", m_enableFalloffAngle );
+ e.setAttribute( "direction", m_direction.serializeXML( ) );
+ e.setAttribute( "angle", m_angle );
+ e.setAttribute( "width", m_width );
+ e.setAttribute( "distance", m_distance );
+ e.setAttribute( "jitter", m_jitter );
+ e.setAttribute( "up", m_up.serializeXML( ) );
+ e.setAttribute( "arc_angle", m_arcAngle );
+ e.setAttribute( "falloff_angle", m_falloffAngle );
+}
+
+void PMRainbow::readAttributes( const PMXMLHelper& h )
+{
+ Base::readAttributes( h );
+ m_enableDirection = h.boolAttribute( "enable_direction", false );
+ m_enableAngle = h.boolAttribute( "enable_angle", false );
+ m_enableWidth = h.boolAttribute( "enable_width", false );
+ m_enableDistance = h.boolAttribute( "enable_distance", false );
+ m_enableJitter = h.boolAttribute( "enable_jitter", false );
+ m_enableUp = h.boolAttribute( "enable_up", false );
+ m_enableArcAngle = h.boolAttribute( "enable_arc_angle", false );
+ m_enableFalloffAngle = h.boolAttribute( "enable_falloff_angle", false );
+ m_direction = h.vectorAttribute( "direction", directionDefault );
+ m_angle = h.doubleAttribute( "angle", angleDefault );
+ m_width = h.doubleAttribute( "width", widthDefault );
+ m_distance = h.doubleAttribute( "distance", distanceDefault );
+ m_jitter = h.doubleAttribute( "jitter", jitterDefault );
+ m_up = h.vectorAttribute( "up", upDefault );
+ m_arcAngle = h.doubleAttribute( "arc_angle", arcAngleDefault );
+ m_falloffAngle = h.doubleAttribute( "falloff_angle", falloffAngleDefault );
+}
+
+void PMRainbow::setDirection( const PMVector& c )
+{
+ if( c != m_direction )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDirectionID, m_direction );
+ m_direction = c;
+ }
+}
+
+void PMRainbow::setAngle( double c )
+{
+ if( c != m_angle )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMAngleID, m_angle );
+ m_angle = c;
+ }
+}
+
+void PMRainbow::setWidth( double c )
+{
+ if( c != m_width )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMWidthID, m_width );
+ m_width = c;
+ }
+}
+
+void PMRainbow::setDistance( double c )
+{
+ if( c != m_distance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDistanceID, m_distance );
+ m_distance = c;
+ }
+}
+
+void PMRainbow::setJitter( double c )
+{
+ if( c != m_jitter )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMJitterID, m_jitter );
+ m_jitter = c;
+ }
+}
+
+void PMRainbow::setUp( const PMVector& c )
+{
+ if( c != m_up )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUpID, m_up );
+ m_up = c;
+ }
+}
+
+void PMRainbow::setArcAngle( double c )
+{
+ if( c != m_arcAngle )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMArcAngleID, m_arcAngle );
+ m_arcAngle = c;
+ }
+}
+
+void PMRainbow::setFalloffAngle( double c )
+{
+ if( c != m_falloffAngle )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFalloffAngleID, m_falloffAngle );
+ m_falloffAngle = c;
+ }
+}
+
+void PMRainbow::enableDirection( bool c )
+{
+ if( c != m_enableDirection )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableDirectionID, m_enableDirection );
+ m_enableDirection = c;
+ }
+}
+
+void PMRainbow::enableAngle( bool c )
+{
+ if( c != m_enableAngle )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableAngleID, m_enableAngle );
+ m_enableAngle = c;
+ }
+}
+
+void PMRainbow::enableWidth( bool c )
+{
+ if( c != m_enableWidth )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableWidthID, m_enableWidth );
+ m_enableWidth = c;
+ }
+}
+
+void PMRainbow::enableDistance( bool c )
+{
+ if( c != m_enableDistance )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableDistanceID, m_enableDistance );
+ m_enableDistance = c;
+ }
+}
+
+void PMRainbow::enableJitter( bool c )
+{
+ if( c != m_enableJitter )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableJitterID, m_enableJitter );
+ m_enableJitter = c;
+ }
+}
+
+void PMRainbow::enableUp( bool c )
+{
+ if( c != m_enableUp )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableUpID, m_enableUp );
+ m_enableUp = c;
+ }
+}
+
+void PMRainbow::enableArcAngle( bool c )
+{
+ if( c != m_enableArcAngle )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableArcAngleID, m_enableArcAngle );
+ m_enableArcAngle = c;
+ }
+}
+
+void PMRainbow::enableFalloffAngle( bool c )
+{
+ if( c != m_enableFalloffAngle )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEnableFalloffAngleID,
+ m_enableFalloffAngle );
+ m_enableFalloffAngle = c;
+ }
+}
+
+PMDialogEditBase* PMRainbow::editWidget( QWidget* parent ) const
+{
+ return new PMRainbowEdit( parent );
+}
+
+void PMRainbow::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMDirectionID:
+ setDirection( data->vectorData( ) );
+ break;
+ case PMAngleID:
+ setAngle( data->doubleData( ) );
+ break;
+ case PMWidthID:
+ setWidth( data->doubleData( ) );
+ break;
+ case PMDistanceID:
+ setDistance( data->doubleData( ) );
+ break;
+ case PMJitterID:
+ setJitter( data->doubleData( ) );
+ break;
+ case PMUpID:
+ setUp( data->vectorData( ) );
+ break;
+ case PMArcAngleID:
+ setArcAngle( data->doubleData( ) );
+ break;
+ case PMFalloffAngleID:
+ setFalloffAngle( data->doubleData( ) );
+ break;
+ case PMEnableDirectionID:
+ enableDirection( data->boolData( ) );
+ break;
+ case PMEnableAngleID:
+ enableAngle( data->boolData( ) );
+ break;
+ case PMEnableWidthID:
+ enableWidth( data->boolData( ) );
+ break;
+ case PMEnableDistanceID:
+ enableDistance( data->boolData( ) );
+ break;
+ case PMEnableJitterID:
+ enableJitter( data->boolData( ) );
+ break;
+ case PMEnableUpID:
+ enableUp( data->boolData( ) );
+ break;
+ case PMEnableArcAngleID:
+ enableArcAngle( data->boolData( ) );
+ break;
+ case PMEnableFalloffAngleID:
+ enableFalloffAngle( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMRainbow::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmrainbow.h b/kpovmodeler/pmrainbow.h
new file mode 100644
index 00000000..0c95c459
--- /dev/null
+++ b/kpovmodeler/pmrainbow.h
@@ -0,0 +1,139 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMRAINBOW_H
+#define PMRAINBOW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+
+/**
+ * Class for povray rainbows
+ */
+class PMRainbow : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMRainbow
+ */
+ PMRainbow( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMRainbow( const PMRainbow& r );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMRainbow( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMRainbow( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMRainbowEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmrainbow" ); }
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ PMVector direction( ) const { return m_direction; }
+ double angle( ) const { return m_angle; }
+ double width( ) const { return m_width; }
+ double distance( ) const { return m_distance; }
+ double jitter( ) const { return m_jitter; }
+ PMVector up( ) const { return m_up; }
+ double arcAngle( ) const { return m_arcAngle; }
+ double falloffAngle( ) const { return m_falloffAngle; }
+ bool isDirectionEnabled( ) const { return m_enableDirection; }
+ bool isAngleEnabled( ) const { return m_enableAngle; }
+ bool isWidthEnabled( ) const { return m_enableWidth; }
+ bool isDistanceEnabled( ) const { return m_enableDistance; }
+ bool isJitterEnabled( ) const { return m_enableJitter; }
+ bool isUpEnabled( ) const { return m_enableUp; }
+ bool isArcAngleEnabled( ) const { return m_enableArcAngle; }
+ bool isFalloffAngleEnabled( ) const { return m_enableFalloffAngle; }
+
+ void setDirection( const PMVector& c );
+ void setAngle( double c );
+ void setWidth( double c );
+ void setDistance( double c );
+ void setJitter( double c );
+ void setUp( const PMVector& c );
+ void setArcAngle( double c );
+ void setFalloffAngle( double c );
+ void enableDirection( bool c );
+ void enableAngle( bool c );
+ void enableWidth( bool c );
+ void enableDistance( bool c );
+ void enableJitter( bool c );
+ void enableUp( bool c );
+ void enableArcAngle( bool c );
+ void enableFalloffAngle( bool c );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMRainbowMementoID { PMDirectionID, PMAngleID, PMWidthID,
+ PMDistanceID, PMJitterID, PMUpID, PMArcAngleID,
+ PMFalloffAngleID, PMEnableDirectionID,
+ PMEnableAngleID, PMEnableWidthID,
+ PMEnableDistanceID, PMEnableJitterID, PMEnableUpID,
+ PMEnableArcAngleID, PMEnableFalloffAngleID };
+ PMVector m_direction;
+ double m_angle;
+ double m_width;
+ double m_distance;
+ double m_jitter;
+ PMVector m_up;
+ double m_arcAngle;
+ double m_falloffAngle;
+
+ bool m_enableDirection;
+ bool m_enableAngle;
+ bool m_enableWidth;
+ bool m_enableDistance;
+ bool m_enableJitter;
+ bool m_enableUp;
+ bool m_enableArcAngle;
+ bool m_enableFalloffAngle;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmrainbowedit.cpp b/kpovmodeler/pmrainbowedit.cpp
new file mode 100644
index 00000000..ff359a7e
--- /dev/null
+++ b/kpovmodeler/pmrainbowedit.cpp
@@ -0,0 +1,278 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmrainbowedit.h"
+#include "pmrainbow.h"
+#include "pmlineedits.h"
+#include "pmvectoredit.h"
+#include "pmvector.h"
+#include "pmmath.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+
+PMRainbowEdit::PMRainbowEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMRainbowEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+ QGridLayout* gl;
+
+ Base::createTopWidgets( );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pEnableDirectionEdit = new QCheckBox( i18n( "Direction:" ), this );
+ m_pDirectionEdit = new PMVectorEdit( "x", "y", "z", this );
+ hl->addWidget( m_pEnableDirectionEdit );
+ hl->addWidget( m_pDirectionEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 4, 2 );
+ m_pEnableAngleEdit = new QCheckBox( i18n( "Angle:" ), this );
+ m_pAngleEdit = new PMFloatEdit( this );
+ gl->addWidget( m_pEnableAngleEdit, 0, 0 );
+ gl->addWidget( m_pAngleEdit, 0, 1 );
+
+ m_pEnableWidthEdit = new QCheckBox( i18n( "Width:" ), this );
+ m_pWidthEdit = new PMFloatEdit( this );
+ gl->addWidget( m_pEnableWidthEdit, 1, 0 );
+ gl->addWidget( m_pWidthEdit, 1, 1 );
+
+ m_pEnableDistanceEdit = new QCheckBox( i18n( "Distance:" ), this );
+ m_pDistanceEdit = new PMFloatEdit( this );
+ gl->addWidget( m_pEnableDistanceEdit, 2, 0 );
+ gl->addWidget( m_pDistanceEdit, 2, 1 );
+
+ m_pEnableJitterEdit = new QCheckBox( i18n( "Jitter:" ), this );
+ m_pJitterEdit = new PMFloatEdit( this );
+ gl->addWidget( m_pEnableJitterEdit, 3, 0 );
+ gl->addWidget( m_pJitterEdit, 3, 1 );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pEnableUpEdit = new QCheckBox( i18n( "Up:" ), this );
+ m_pUpEdit = new PMVectorEdit( "x", "y", "z", this );
+ hl->addWidget( m_pEnableUpEdit );
+ hl->addWidget( m_pUpEdit );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 2, 2 );
+ m_pEnableArcAngleEdit = new QCheckBox( i18n( "Arc angle:" ), this );
+ m_pArcAngleEdit = new PMFloatEdit( this );
+ m_pArcAngleEdit->setValidation( true, 0, true, 360 );
+ gl->addWidget( m_pEnableArcAngleEdit, 0, 0 );
+ gl->addWidget( m_pArcAngleEdit, 0, 1 );
+ m_pEnableFalloffAngleEdit = new QCheckBox( i18n( "Falloff angle:" ), this );
+ m_pFalloffAngleEdit = new PMFloatEdit( this );
+ m_pFalloffAngleEdit->setValidation( true, 0, true, 360 );
+ gl->addWidget( m_pEnableFalloffAngleEdit, 1, 0 );
+ gl->addWidget( m_pFalloffAngleEdit, 1, 1 );
+ hl->addStretch( 1 );
+
+ connect( m_pDirectionEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pAngleEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pWidthEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDistanceEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pJitterEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pUpEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pArcAngleEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFalloffAngleEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pEnableDirectionEdit, SIGNAL( clicked( ) ), SLOT( slotDirectionClicked( ) ) );
+ connect( m_pEnableAngleEdit, SIGNAL( clicked( ) ), SLOT( slotAngleClicked( ) ) );
+ connect( m_pEnableWidthEdit, SIGNAL( clicked( ) ), SLOT( slotWidthClicked( ) ) );
+ connect( m_pEnableDistanceEdit, SIGNAL( clicked( ) ), SLOT( slotDistanceClicked( ) ) );
+ connect( m_pEnableJitterEdit, SIGNAL( clicked( ) ), SLOT( slotJitterClicked( ) ) );
+ connect( m_pEnableUpEdit, SIGNAL( clicked( ) ), SLOT( slotUpClicked( ) ) );
+ connect( m_pEnableArcAngleEdit, SIGNAL( clicked( ) ), SLOT( slotArcAngleClicked( ) ) );
+ connect( m_pEnableFalloffAngleEdit, SIGNAL( clicked( ) ), SLOT( slotFalloffAngleClicked( ) ) );
+}
+
+void PMRainbowEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Rainbow" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMRainbow* ) o;
+
+ m_pDirectionEdit->setVector( m_pDisplayedObject->direction( ) );
+ m_pDirectionEdit->setReadOnly( readOnly );
+ m_pAngleEdit->setValue( m_pDisplayedObject->angle( ) );
+ m_pAngleEdit->setReadOnly( readOnly );
+ m_pWidthEdit->setValue( m_pDisplayedObject->width( ) );
+ m_pWidthEdit->setReadOnly( readOnly );
+ m_pDistanceEdit->setValue( m_pDisplayedObject->distance( ) );
+ m_pDistanceEdit->setReadOnly( readOnly );
+ m_pJitterEdit->setValue( m_pDisplayedObject->jitter( ) );
+ m_pJitterEdit->setReadOnly( readOnly );
+ m_pUpEdit->setVector( m_pDisplayedObject->up( ) );
+ m_pUpEdit->setReadOnly( readOnly );
+ m_pArcAngleEdit->setValue( m_pDisplayedObject->arcAngle( ) );
+ m_pArcAngleEdit->setReadOnly( readOnly );
+ m_pFalloffAngleEdit->setValue( m_pDisplayedObject->falloffAngle( ) );
+ m_pFalloffAngleEdit->setReadOnly( readOnly );
+ m_pEnableDirectionEdit->setChecked( m_pDisplayedObject->isDirectionEnabled( ) );
+ m_pEnableDirectionEdit->setEnabled( !readOnly );
+ m_pEnableAngleEdit->setChecked( m_pDisplayedObject->isAngleEnabled( ) );
+ m_pEnableAngleEdit->setEnabled( !readOnly );
+ m_pEnableWidthEdit->setChecked( m_pDisplayedObject->isWidthEnabled( ) );
+ m_pEnableWidthEdit->setEnabled( !readOnly );
+ m_pEnableDistanceEdit->setChecked( m_pDisplayedObject->isDistanceEnabled( ) );
+ m_pEnableDistanceEdit->setEnabled( !readOnly );
+ m_pEnableJitterEdit->setChecked( m_pDisplayedObject->isJitterEnabled( ) );
+ m_pEnableJitterEdit->setEnabled( !readOnly );
+ m_pEnableUpEdit->setChecked( m_pDisplayedObject->isUpEnabled( ) );
+ m_pEnableUpEdit->setEnabled( !readOnly );
+ m_pEnableArcAngleEdit->setChecked( m_pDisplayedObject->isArcAngleEnabled( ) );
+ m_pEnableArcAngleEdit->setEnabled( !readOnly );
+ m_pEnableFalloffAngleEdit->setChecked( m_pDisplayedObject->isFalloffAngleEnabled( ) );
+ m_pEnableFalloffAngleEdit->setEnabled( !readOnly );
+ slotDirectionClicked( );
+ slotAngleClicked( );
+ slotWidthClicked( );
+ slotDistanceClicked( );
+ slotJitterClicked( );
+ slotUpClicked( );
+ slotArcAngleClicked( );
+ slotFalloffAngleClicked( );
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMRainbowEdit: Can't display object\n";
+}
+
+void PMRainbowEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setDirection( m_pDirectionEdit->vector( ) );
+ m_pDisplayedObject->setAngle( m_pAngleEdit->value( ) );
+ m_pDisplayedObject->setWidth( m_pWidthEdit->value( ) );
+ m_pDisplayedObject->setDistance( m_pDistanceEdit->value( ) );
+ m_pDisplayedObject->setJitter( m_pJitterEdit->value( ) );
+ m_pDisplayedObject->setUp( m_pUpEdit->vector( ) );
+ m_pDisplayedObject->setArcAngle( m_pArcAngleEdit->value( ) );
+ m_pDisplayedObject->setFalloffAngle( m_pFalloffAngleEdit->value( ) );
+ m_pDisplayedObject->enableDirection( m_pEnableDirectionEdit->isChecked( ) );
+ m_pDisplayedObject->enableAngle( m_pEnableAngleEdit->isChecked( ) );
+ m_pDisplayedObject->enableWidth( m_pEnableWidthEdit->isChecked( ) );
+ m_pDisplayedObject->enableDistance( m_pEnableDistanceEdit->isChecked( ) );
+ m_pDisplayedObject->enableJitter( m_pEnableJitterEdit->isChecked( ) );
+ m_pDisplayedObject->enableUp( m_pEnableUpEdit->isChecked( ) );
+ m_pDisplayedObject->enableArcAngle( m_pEnableArcAngleEdit->isChecked( ) );
+ m_pDisplayedObject->enableFalloffAngle( m_pEnableFalloffAngleEdit->isChecked( ) );
+ }
+}
+
+bool PMRainbowEdit::isDataValid( )
+{
+ double f_angle;
+
+ if( !m_pDirectionEdit->isDataValid( ) ) return false;
+ if( !m_pAngleEdit->isDataValid( ) ) return false;
+ if( !m_pWidthEdit->isDataValid( ) ) return false;
+ if( !m_pDistanceEdit->isDataValid( ) ) return false;
+ if( !m_pJitterEdit->isDataValid( ) ) return false;
+ if( !m_pUpEdit->isDataValid( ) ) return false;
+ if( !m_pArcAngleEdit->isDataValid( ) ) return false;
+ if( !m_pFalloffAngleEdit->isDataValid( ) ) return false;
+ if( m_pFalloffAngleEdit->value( ) > m_pArcAngleEdit->value( ) )
+ {
+ KMessageBox::error( this, i18n( "Arc angle is smaller than falloff angle in rainbow." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ if( approxZero( fabs( PMVector::dot( m_pDirectionEdit->vector( ), m_pDirectionEdit->vector( ) ) ) ) )
+ {
+ KMessageBox::error( this, i18n( "Direction vector is zero." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ if( approxZero( fabs( PMVector::dot( m_pUpEdit->vector( ), m_pUpEdit->vector( ) ) ) ) )
+ {
+ KMessageBox::error( this, i18n( "Up vector is zero." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ f_angle = fabs( rad2Deg( PMVector::angle( m_pDirectionEdit->vector( ), m_pUpEdit->vector( ) ) ) );
+ if( f_angle == 0.0 || f_angle == 180.0 )
+ {
+ KMessageBox::error( this, i18n( "Direction and up vectors are co-linear." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ return Base::isDataValid( );
+}
+
+void PMRainbowEdit::slotDirectionClicked( )
+{
+ m_pDirectionEdit->setEnabled( m_pEnableDirectionEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMRainbowEdit::slotAngleClicked( )
+{
+ m_pAngleEdit->setEnabled( m_pEnableAngleEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMRainbowEdit::slotWidthClicked( )
+{
+ m_pWidthEdit->setEnabled( m_pEnableWidthEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMRainbowEdit::slotDistanceClicked( )
+{
+ m_pDistanceEdit->setEnabled( m_pEnableDistanceEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMRainbowEdit::slotJitterClicked( )
+{
+ m_pJitterEdit->setEnabled( m_pEnableJitterEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMRainbowEdit::slotUpClicked( )
+{
+ m_pUpEdit->setEnabled( m_pEnableUpEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMRainbowEdit::slotArcAngleClicked( )
+{
+ m_pArcAngleEdit->setEnabled( m_pEnableArcAngleEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+void PMRainbowEdit::slotFalloffAngleClicked( )
+{
+ m_pFalloffAngleEdit->setEnabled( m_pEnableFalloffAngleEdit->isChecked( ) );
+ emit dataChanged( );
+}
+
+#include "pmrainbowedit.moc"
diff --git a/kpovmodeler/pmrainbowedit.h b/kpovmodeler/pmrainbowedit.h
new file mode 100644
index 00000000..c5d4b714
--- /dev/null
+++ b/kpovmodeler/pmrainbowedit.h
@@ -0,0 +1,90 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMRAINBOWEDIT_H
+#define PMRAINBOWEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMRainbow;
+class PMFloatEdit;
+class PMVectorEdit;
+class QCheckBox;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMRainbow
+ */
+class PMRainbowEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMRainbowEdit with parent and name
+ */
+ PMRainbowEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotDirectionClicked( );
+ void slotAngleClicked( );
+ void slotWidthClicked( );
+ void slotDistanceClicked( );
+ void slotJitterClicked( );
+ void slotUpClicked( );
+ void slotArcAngleClicked( );
+ void slotFalloffAngleClicked( );
+
+private:
+ PMRainbow* m_pDisplayedObject;
+ PMVectorEdit* m_pDirectionEdit;
+ PMFloatEdit* m_pAngleEdit;
+ PMFloatEdit* m_pWidthEdit;
+ PMFloatEdit* m_pDistanceEdit;
+ PMFloatEdit* m_pJitterEdit;
+ PMVectorEdit* m_pUpEdit;
+ PMFloatEdit* m_pArcAngleEdit;
+ PMFloatEdit* m_pFalloffAngleEdit;
+ QCheckBox* m_pEnableDirectionEdit;
+ QCheckBox* m_pEnableAngleEdit;
+ QCheckBox* m_pEnableWidthEdit;
+ QCheckBox* m_pEnableDistanceEdit;
+ QCheckBox* m_pEnableJitterEdit;
+ QCheckBox* m_pEnableUpEdit;
+ QCheckBox* m_pEnableArcAngleEdit;
+ QCheckBox* m_pEnableFalloffAngleEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmraw.cpp b/kpovmodeler/pmraw.cpp
new file mode 100644
index 00000000..a2d44784
--- /dev/null
+++ b/kpovmodeler/pmraw.cpp
@@ -0,0 +1,135 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmraw.h"
+#include "pmxmlhelper.h"
+
+#include "pmrawedit.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+#include <qtextstream.h>
+
+PMDefinePropertyClass( PMRaw, PMRawProperty );
+
+PMMetaObject* PMRaw::s_pMetaObject = 0;
+PMObject* createNewRaw( PMPart* part )
+{
+ return new PMRaw( part );
+}
+
+PMRaw::PMRaw( PMPart* part )
+ : Base( part )
+{
+}
+
+PMRaw::PMRaw( const PMRaw& r )
+ : Base( r )
+{
+ m_code = r.m_code;
+}
+
+PMRaw::PMRaw( PMPart* part, const QString& t )
+ : Base( part )
+{
+ m_code = t;
+}
+
+PMRaw::~PMRaw( )
+{
+}
+
+QString PMRaw::description( ) const
+{
+ return i18n( "raw povray" );
+}
+
+void PMRaw::setCode( const QString& code )
+{
+ if( code != m_code )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCodeID, m_code );
+ m_code = code;
+ }
+}
+
+PMMetaObject* PMRaw::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Raw", Base::metaObject( ),
+ createNewRaw );
+ s_pMetaObject->addProperty(
+ new PMRawProperty( "code", &PMRaw::setCode, &PMRaw::code ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMRaw::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMRaw::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ QDomText t = doc.createTextNode( m_code );
+ e.appendChild( t );
+}
+
+void PMRaw::readAttributes( const PMXMLHelper& h )
+{
+ QDomNode e = h.element( ).firstChild( );
+ if( e.isText( ) )
+ m_code = e.toText( ).data( );
+}
+
+PMDialogEditBase* PMRaw::editWidget( QWidget* parent ) const
+{
+ return new PMRawEdit( parent );
+}
+
+void PMRaw::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMCodeID:
+ setCode( data->stringData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMRaw::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
diff --git a/kpovmodeler/pmraw.h b/kpovmodeler/pmraw.h
new file mode 100644
index 00000000..2ba888bc
--- /dev/null
+++ b/kpovmodeler/pmraw.h
@@ -0,0 +1,90 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMRAW_H
+#define PMRAW_H
+
+#include "pmnamedobject.h"
+#include <qstring.h>
+
+
+/**
+ * Class for raw povray code
+ */
+class PMRaw : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+public:
+ /**
+ * Creates an empty raw povray object
+ */
+ PMRaw( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMRaw( const PMRaw& r );
+ /**
+ * Creates a raw povray object with text t
+ */
+ PMRaw( PMPart* part, const QString& t );
+ /**
+ * Deletes the raw povray object
+ */
+ ~PMRaw( );
+
+ /**
+ * Sets the povray code
+ */
+ void setCode( const QString& text );
+ /**
+ * Returns the raw povray code
+ */
+ QString code( ) const { return m_code; }
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMRaw( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmraw" ); }
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMRawMementoID { PMCodeID };
+ QString m_code;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmrawedit.cpp b/kpovmodeler/pmrawedit.cpp
new file mode 100644
index 00000000..81d752d2
--- /dev/null
+++ b/kpovmodeler/pmrawedit.cpp
@@ -0,0 +1,79 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmrawedit.h"
+#include "pmraw.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qmultilineedit.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+
+PMRawEdit::PMRawEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMRawEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ topLayout( )->addWidget( new QLabel( i18n( "Povray code:" ), this ) );
+ m_pEdit = new QMultiLineEdit( this );
+#if ( QT_VERSION >= 300 )
+ m_pEdit->setTextFormat( Qt::PlainText );
+ m_pEdit->setWordWrap( QTextEdit::NoWrap );
+#endif
+ m_pEdit->setFont( KGlobalSettings::fixedFont( ) );
+ topLayout( )->addWidget( m_pEdit, 2 );
+
+ connect( m_pEdit, SIGNAL( textChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMRawEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Raw" ) )
+ {
+ m_pDisplayedObject = ( PMRaw* ) o;
+ m_pEdit->setText( m_pDisplayedObject->code( ) );
+
+ m_pEdit->setReadOnly( o->isReadOnly( ) );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMRawEdit: Can't display object\n";
+}
+
+void PMRawEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setCode( m_pEdit->text( ) );
+ }
+}
+
+bool PMRawEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+#include "pmrawedit.moc"
diff --git a/kpovmodeler/pmrawedit.h b/kpovmodeler/pmrawedit.h
new file mode 100644
index 00000000..911ceb4e
--- /dev/null
+++ b/kpovmodeler/pmrawedit.h
@@ -0,0 +1,62 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMRAWEDIT_H
+#define PMRAWEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobjectedit.h"
+
+class PMRaw;
+class QMultiLineEdit;
+
+/**
+ * Dialog edit class for @ref PMRaw.
+ */
+class PMRawEdit : public PMNamedObjectEdit
+{
+ Q_OBJECT
+ typedef PMNamedObjectEdit Base;
+public:
+ /**
+ * Creates a PMRawEdit with parent and name
+ */
+ PMRawEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMRaw* m_pDisplayedObject;
+ QMultiLineEdit* m_pEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmrecursiveobjectiterator.cpp b/kpovmodeler/pmrecursiveobjectiterator.cpp
new file mode 100644
index 00000000..eeacfaa6
--- /dev/null
+++ b/kpovmodeler/pmrecursiveobjectiterator.cpp
@@ -0,0 +1,62 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmobject.h"
+#include "pmrecursiveobjectiterator.h"
+
+PMRecursiveObjectIterator::PMRecursiveObjectIterator( PMObject* obj )
+{
+ m_pObject = obj;
+ m_pCurrent = obj;
+}
+
+PMObject* PMRecursiveObjectIterator::operator++( )
+{
+ if( m_pCurrent )
+ {
+ if( m_pCurrent->firstChild( ) )
+ m_pCurrent = m_pCurrent->firstChild( );
+ else if( m_pCurrent == m_pObject )
+ m_pCurrent = 0;
+ else if( m_pCurrent->nextSibling( ) )
+ m_pCurrent = m_pCurrent->nextSibling( );
+ else
+ {
+ bool stop = false;
+ do
+ {
+ m_pCurrent = m_pCurrent->parent( );
+ if( !m_pCurrent )
+ stop = true;
+ else if( m_pCurrent == m_pObject )
+ {
+ // finished
+ stop = true;
+ m_pCurrent = 0;
+ }
+ else if( m_pCurrent->nextSibling( ) )
+ {
+ m_pCurrent = m_pCurrent->nextSibling( );
+ stop = true;
+ }
+ }
+ while( !stop );
+ }
+ }
+
+ return m_pCurrent;
+}
diff --git a/kpovmodeler/pmrecursiveobjectiterator.h b/kpovmodeler/pmrecursiveobjectiterator.h
new file mode 100644
index 00000000..aafeaad3
--- /dev/null
+++ b/kpovmodeler/pmrecursiveobjectiterator.h
@@ -0,0 +1,49 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMRECURSIVEOBJECTITERATOR_H
+#define PMRECURSIVEOBJECTITERATOR_H
+
+class PMObject;
+
+/**
+ * Iterator that
+ */
+class PMRecursiveObjectIterator
+{
+public:
+ /**
+ * Creates an iterator that iterates recursively over the childs
+ * of obj.
+ */
+ PMRecursiveObjectIterator( PMObject* obj );
+ /**
+ * Makes the next object the current one and returns it.
+ */
+ PMObject* operator++( );
+ /**
+ * Returns the current object.
+ */
+ PMObject* current( ) const { return m_pCurrent; }
+
+private:
+ PMObject* m_pObject;
+ PMObject* m_pCurrent;
+};
+
+#endif
diff --git a/kpovmodeler/pmrendermanager.cpp b/kpovmodeler/pmrendermanager.cpp
new file mode 100644
index 00000000..664f0fd9
--- /dev/null
+++ b/kpovmodeler/pmrendermanager.cpp
@@ -0,0 +1,1647 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+// conflicting types for INT32 in qt and glx
+#ifndef QT_CLEAN_NAMESPACE
+#define QT_CLEAN_NAMESPACE
+#endif
+
+#include "pmrendermanager.h"
+#include "pmviewstructure.h"
+#include "pmobject.h"
+#include "pmdeclare.h"
+#include "pmcamera.h"
+#include "pmquickcolor.h"
+#include "pmdefaults.h"
+#include "pmgraphicalobject.h"
+#include "pmmath.h"
+
+#include <qptrstack.h>
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <kconfig.h>
+#include <klocale.h>
+
+#include <time.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <GL/glu.h> // Only needed for gluPerspective
+
+#include "pmglview.h"
+
+const GLdouble dA = 0.75;
+const GLdouble dB = 0.15;
+
+const GLdouble viewVolumeZ = 1e5;
+
+// Size has to be controlPointSize (see pmglview.h)
+const GLubyte PointBitmap[7] = { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE };
+const GLubyte CrossBitmap[7] = { 0x10, 0x10, 0x10, 0xFE, 0x10, 0x10, 0x10 };
+
+
+const int activeTimeAfterRendering = 2;
+const int maxEventTime = 0;
+const int maxSubdivisions = 32;
+const double subdivisionDistance = 0.05;
+
+
+PMRenderManager* PMRenderManager::s_pManager = 0;
+KStaticDeleter<PMRenderManager> PMRenderManager::s_staticDeleter;
+
+bool PMRenderManager::s_hasOpenGL = true;
+bool PMRenderManager::s_hasOpenGLChecked = false;
+
+PMRenderManager* PMRenderManager::theManager( )
+{
+ if( !s_pManager )
+ s_staticDeleter.setObject( s_pManager, new PMRenderManager( ) );
+ return s_pManager;
+}
+
+PMRenderManager::PMRenderManager( )
+ : QObject( qApp )
+{
+ int i;
+
+ m_bStartTask = false;
+ m_bStopTask = false;
+ m_bTaskIsRunning = false;
+
+ m_graphicalObjectColor[0] = c_defaultGraphicalObjectColor0;
+ m_graphicalObjectColor[1] = c_defaultGraphicalObjectColor1;
+ m_textureColor[0] = c_defaultTextureColor0;
+ m_textureColor[1] = c_defaultTextureColor1;
+ m_axesColor[0] = c_defaultAxesColorX;
+ m_axesColor[1] = c_defaultAxesColorY;
+ m_axesColor[2] = c_defaultAxesColorZ;
+ m_controlPointColor[0] = c_defaultControlPointColor0;
+ m_controlPointColor[1] = c_defaultControlPointColor1;
+ m_backgroundColor = c_defaultBackgroundColor;
+ m_fieldOfViewColor = c_defaultFieldOfViewColor;
+ m_highDetailCameraView = c_defaultHighDetailCameraView;
+ m_nMaxRenderedLines = 1000;
+ m_gridDistance = c_defaultGridDistance;
+ m_gridColor = c_defaultGridColor;
+ m_axesViewStructureCreated = false;
+ m_currentVisibility = 0;
+
+ m_renderTasks.setAutoDelete( true );
+ m_matrixStack.setAutoDelete( true );
+ m_quickColors.setAutoDelete( true );
+
+ m_nViews = 0;
+
+ m_subdivisionViewStructure = PMViewStructure( maxSubdivisions + 1,
+ maxSubdivisions );
+ PMLineArray& lines = m_subdivisionViewStructure.lines( );
+ for( i = 0; i < maxSubdivisions; i++ )
+ lines[i] = PMLine( i, i+1 );
+}
+
+PMRenderManager::~PMRenderManager( )
+{
+ s_pManager = 0;
+}
+
+void PMRenderManager::addView( PMGLView* view, PMObject* active, PMObject* top,
+ PMControlPointList* controlPoints,
+ double aspectRatio, int visibilityLevel,
+ bool graphicalChange )
+{
+ PMRenderTaskListIterator it( m_renderTasks );
+ PMRenderTask* task = 0;
+ bool restart = false;
+ bool first = true;
+
+ for( ; it.current( ) && !task; ++it )
+ {
+ if( it.current( )->view( ) == view )
+ task = it.current( );
+ else
+ first = false;
+ }
+
+ if( task )
+ {
+ if( first )
+ restart = true;
+ else if( graphicalChange )
+ {
+ m_renderTasks.findRef( task );
+ m_renderTasks.take( );
+ m_renderTasks.prepend( task );
+ restart = true;
+ }
+ task->setActiveObject( active );
+ task->setTopLevelObject( top );
+ task->setControlPoints( controlPoints );
+ task->setAspectRatio( aspectRatio );
+ task->setVisibilityLevel( visibilityLevel );
+ }
+ else
+ {
+ task = new PMRenderTask( view, active, top, controlPoints, aspectRatio,
+ visibilityLevel );
+ if( graphicalChange )
+ {
+ m_renderTasks.prepend( task );
+ restart = true;
+ }
+ else
+ {
+ m_renderTasks.append( task );
+ if( m_renderTasks.count( ) == 1 )
+ restart = true;
+ }
+ }
+ if( restart )
+ restartRendering( );
+}
+
+void PMRenderManager::removeView( PMGLView* view )
+{
+ PMRenderTaskListIterator it( m_renderTasks );
+ PMRenderTask* task = 0;
+ bool restart = false;
+
+ for( ; it.current( ) && !task; ++it )
+ if( it.current( )->view( ) == view )
+ task = it.current( );
+
+ if( task )
+ {
+ if( task == m_renderTasks.first( ) )
+ {
+ restart = true;
+ if( m_bTaskIsRunning )
+ emit renderingFinished( task->view( ) );
+ }
+ m_renderTasks.removeRef( task );
+ }
+
+ if( restart )
+ restartRendering( );
+}
+
+bool PMRenderManager::containsTask( PMGLView* view ) const
+{
+ PMRenderTaskListIterator it( m_renderTasks );
+ bool contains = false;
+
+ for( ; it.current( ) && !contains; ++it )
+ if( it.current( )->view( ) == view )
+ contains = true;
+ return contains;
+}
+
+QColor PMRenderManager::controlPointColor( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 1 ) )
+ return m_controlPointColor[i];
+ return QColor( 0, 0, 0 );
+}
+
+void PMRenderManager::setControlPointColor( int i, const QColor& c )
+{
+ if( ( i >= 0 ) && ( i <= 1 ) )
+ m_controlPointColor[i] = c;
+}
+
+QColor PMRenderManager::graphicalObjectColor( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 1 ) )
+ return m_graphicalObjectColor[i];
+ return QColor( 0, 0, 0 );
+}
+
+void PMRenderManager::setGraphicalObjectColor( int i, const QColor& c )
+{
+ if( ( i >= 0 ) && ( i <= 1 ) )
+ m_graphicalObjectColor[i] = c;
+}
+
+QColor PMRenderManager::axesColor( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 2 ) )
+ return m_axesColor[i];
+ return QColor( 0, 0, 0 );
+}
+
+void PMRenderManager::setAxesColor( int i, const QColor& c )
+{
+ if( ( i >= 0 ) && ( i <= 2 ) )
+ m_axesColor[i] = c;
+}
+
+void PMRenderManager::setGridDistance( int d )
+{
+ if( d >= 20 )
+ m_gridDistance = d;
+}
+
+void PMRenderManager::restartRendering( )
+{
+ if( !m_bTaskIsRunning && !m_bStartTask )
+ startTimer( 0 );
+
+ m_bStartTask = true;
+ m_bStopTask = false;
+}
+
+void PMRenderManager::slotStopRendering( )
+{
+ m_bStopTask = true;
+ m_bStartTask = false;
+
+ if( m_bTaskIsRunning )
+ if( m_pCurrentTask )
+ emit renderingFinished( m_pCurrentTask->view( ) );
+ m_renderTasks.clear( );
+}
+
+void PMRenderManager::timerEvent( QTimerEvent* )
+{
+ killTimers( );
+ renderTask( );
+}
+
+void PMRenderManager::renderTask( )
+{
+ m_bTaskIsRunning = true;
+ emit renderingStarted( );
+
+ int r, g, b;
+ bool disableView = false;
+
+ while( m_bStartTask && !m_bStopTask )
+ {
+ m_bStartTask = false;
+
+ // render the views sequential
+ while( m_renderTasks.first( ) && !m_bStopTask && !m_bStartTask )
+ {
+ // reset the member variables for rendering
+ m_pCurrentTask = m_renderTasks.first( );
+ m_pCurrentGlView = m_pCurrentTask->view( );
+ emit renderingStarted( m_pCurrentGlView );
+
+ m_renderedLines = 0;
+ m_selected = false;
+ m_pDeselectObject = 0;
+ m_matrixStack.clear( );
+ m_quickColorObjects.clear( );
+ m_quickColors.clear( );
+ m_currentColor = m_graphicalObjectColor[0];
+ m_specialCameraMode = false;
+ m_currentVisibility = 0;
+ m_visibilityStack.clear( );
+
+ if( m_bStopTask || m_bStartTask )
+ break;
+ m_pCurrentGlView->makeCurrent( );
+
+ m_backgroundColor.rgb( &r, &g, &b );
+ glClearColor( r/255.0, g/255.0, b/255.0, 1.0 );
+ glPointSize( controlPointSize );
+ glEnable( GL_DEPTH_TEST );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ glViewport( 0, 0, ( GLint ) m_pCurrentGlView->width( ),
+ ( GLint ) m_pCurrentGlView->height( ) );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ disableView = false;
+ if( m_pCurrentGlView->type( ) == PMGLView::PMViewCamera )
+ {
+ if( m_pCurrentGlView->camera( ) )
+ {
+ if( m_pCurrentGlView->camera( )->cameraType( )
+ == PMCamera::Omnimax )
+ disableView = true;
+ }
+ else
+ disableView = true;
+ }
+
+ if( !disableView )
+ setProjection( );
+
+ glLoadIdentity( );
+
+ glDisable( GL_DEPTH_TEST );
+ if( m_pCurrentGlView->type( ) == PMGLView::PMViewCamera )
+ renderFieldOfView( );
+ else
+ renderGrid( );
+ renderDescription( );
+ glEnable( GL_DEPTH_TEST );
+
+ if( !disableView )
+ {
+ renderAxes( );
+
+ renderObject( m_pCurrentTask->topLevelObject( ) );
+ if( !m_bStopTask && ! m_bStartTask )
+ renderControlPoints( );
+ }
+
+ if( !m_bStopTask && ! m_bStartTask )
+ {
+ glXWaitX( );
+ emit aboutToUpdate( m_pCurrentGlView );
+ if( m_bStopTask || m_bStartTask )
+ break;
+ glXWaitX( );
+ m_pCurrentGlView->swapBuffers( );
+ glFinish( );
+ glXWaitGL( );
+ emit renderingFinished( m_pCurrentGlView );
+ if( m_bStopTask || m_bStartTask )
+ break;
+ qApp->processEvents( maxEventTime );
+ if( m_bStopTask || m_bStartTask )
+ break;
+ m_renderTasks.removeFirst( );
+ }
+ }
+ }
+
+ emit renderingFinished( );
+
+ m_bStopTask = false;
+ m_bStartTask = false;
+ m_bTaskIsRunning = false;
+}
+
+void PMRenderManager::renderObject( PMObject* objectToRender )
+{
+ bool children = false;
+ PMGraphicalObject* go = 0;
+
+ m_objectToRenderStack.append( objectToRender );
+
+ if( objectToRender->isA( "GraphicalObject" ) )
+ {
+ go = ( PMGraphicalObject* ) objectToRender;
+ m_visibilityStack.push( m_currentVisibility );
+ if( go->isVisibilityLevelRelative( ) )
+ m_currentVisibility += go->visibilityLevel( );
+ else
+ m_currentVisibility = go->visibilityLevel( );
+ }
+
+ if( !m_selected )
+ {
+ if( objectToRender->isSelected( ) )
+ {
+ m_selected = true;
+ m_pDeselectObject = objectToRender;
+ if( objectToRender->hasTransformationMatrix( ) )
+ if( objectToRender->parent( ) )
+ m_pDeselectObject = objectToRender->parent( );
+ }
+ }
+
+ if( ( m_pCurrentGlView->type( ) != PMGLView::PMViewCamera )
+ || ( objectToRender != ( PMObject* ) ( m_pCurrentGlView->camera( ) ) ) )
+ {
+ PMObject* obj = 0;
+
+ children = objectToRender->lastChild( ) || objectToRender->linkedObject( );
+ if( children )
+ {
+ bool stop;
+
+ PMMatrix* matrix;
+ if( m_specialCameraMode )
+ matrix = new PMMatrix( m_viewTransformation );
+ else
+ matrix = new PMMatrix( PMMatrix::modelviewMatrix( ) );
+ m_matrixStack.push( matrix );
+
+ // render the children and the linked object
+ obj = objectToRender->lastChild( );
+ while( obj && !m_bStopTask && !m_bStartTask )
+ {
+ if( !obj->isA( "Declare" ) )
+ renderObject( obj );
+ if( !m_bStopTask && !m_bStartTask )
+ {
+ do
+ {
+ // Do not render declares
+ obj = obj->prevSibling( );
+ if( !obj )
+ stop = true;
+ else
+ stop = !obj->isA( "Declare" );
+ }
+ while( !stop );
+ }
+ }
+ if( !m_bStopTask && !m_bStartTask )
+ {
+ obj = objectToRender->linkedObject( );
+ if( obj )
+ renderObject( obj );
+ }
+ }
+
+
+ if( !m_bStopTask && !m_bStartTask )
+ {
+ // children of the object are rendered
+ // render the object
+
+ if( objectToRender == m_pCurrentTask->activeObject( ) )
+ {
+ if( m_specialCameraMode )
+ m_controlPointTransformation = m_viewTransformation;
+ else
+ m_controlPointTransformation = PMMatrix::modelviewMatrix( );
+ }
+
+ if( objectToRender->type( ) == "QuickColor" )
+ {
+ PMQuickColor* qc = ( PMQuickColor* ) objectToRender;
+ PMObjectListIterator it( m_objectToRenderStack );
+ bool pofound = false;
+ it.toLast( );
+
+ while( it.current( ) && !pofound )
+ {
+ if( it.current( )->isA( "GraphicalObject" ) )
+ pofound = true;
+ else
+ --it;
+ }
+ if( pofound )
+ {
+ if( m_quickColorObjects.top( ) != it.current( ) )
+ {
+ m_quickColorObjects.push( it.current( ) );
+ m_quickColors.push( new QColor( m_currentColor ) );
+ m_currentColor = qc->color( ).toQColor( );
+ }
+ }
+ }
+
+ PMViewStructure* vs = objectToRender->viewStructure( );
+ if( objectToRender->hasTransformationMatrix( ) || vs )
+ {
+ // object has transformation or view structure
+ if( vs )
+ {
+ if( ( m_currentVisibility <= m_pCurrentTask->visibilityLevel( ) )
+ || ( objectToRender == m_pCurrentTask->activeObject( ) ) )
+ {
+ // render the view structure.
+ // call qApp->processEvents( ) each m_nMaxRenderedLines rendered
+ // lines
+ if( m_selected )
+ setGLColor( m_graphicalObjectColor[ 1 ] );
+ else
+ setGLColor( m_currentColor );
+
+ renderViewStructure( *vs );
+ }
+ }
+ else if( objectToRender->hasTransformationMatrix( ) )
+ {
+ if( m_specialCameraMode )
+ m_viewTransformation = m_viewTransformation * objectToRender->transformationMatrix( );
+ else
+ glMultMatrixd( objectToRender->transformationMatrix( ).data( ) );
+ }
+ }
+ // end rendering
+ }
+ }
+ if( !m_bStopTask && !m_bStartTask )
+ {
+ if( children )
+ {
+ PMMatrix* matrix = m_matrixStack.pop( );
+
+ if( matrix )
+ {
+ if( m_specialCameraMode )
+ m_viewTransformation = (*matrix);
+ else
+ glLoadMatrixd( matrix->data( ) );
+ delete matrix;
+ matrix = 0;
+ }
+ }
+ if( m_selected )
+ {
+ if( m_pDeselectObject == objectToRender )
+ {
+ m_selected = false;
+ m_pDeselectObject = 0;
+ }
+ }
+ if( m_quickColorObjects.top( ) == objectToRender )
+ {
+ m_quickColorObjects.pop( );
+ QColor* col = m_quickColors.pop( );
+ if( col )
+ {
+ m_currentColor = *col;
+ delete col;
+ col = 0;
+ }
+ }
+ }
+
+ if( go )
+ m_currentVisibility = m_visibilityStack.pop( );
+
+ m_objectToRenderStack.removeLast( );
+}
+
+void PMRenderManager::renderViewStructure( PMViewStructure& vs )
+{
+ if( m_specialCameraMode )
+ {
+ PMPointArray points = vs.points( );
+ points.detach( );
+ transformProjection( points.data( ), points.size( ),
+ m_pCurrentGlView->camera( ) );
+
+ if( m_highDetailCameraView )
+ {
+ // subdivide line
+ PMLineArray& lines = vs.lines( );
+ PMPointArray& utPoints = vs.points( );
+ int numLines = lines.size( );
+ PMPointArray& sdPoints = m_subdivisionViewStructure.points( );
+ PMLineArray& sdLines = m_subdivisionViewStructure.lines( );
+ int i, li, sd;
+ double distance;
+ PMPoint start, end, dir;
+
+ for( i = 0; ( i < numLines ) && !m_bStopTask && !m_bStartTask; i++ )
+ {
+ // calculate screen distance
+ start = points[lines[i].startPoint( )];
+ end = points[lines[i].endPoint( )];
+ dir[0] = ( end[0] - start[0] ) / m_anglex;
+ dir[1] = ( end[1] - start[1] ) / m_angley;
+ distance = sqrt( dir[0] * dir[0] + dir[1] * dir[1] );
+
+ // calculate number of subdivisions
+ sd = ( int ) ( distance / subdivisionDistance );
+ if( sd > 1 )
+ {
+ // calculate subdivision
+ if( sd > maxSubdivisions )
+ sd = maxSubdivisions;
+
+ sdPoints[0] = start;
+ sdPoints[sd] = end;
+
+ start = utPoints[lines[i].startPoint( )];
+ end = utPoints[lines[i].endPoint( )];
+ dir[0] = ( end[0] - start[0] ) / sd;
+ dir[1] = ( end[1] - start[1] ) / sd;
+ dir[2] = ( end[2] - start[2] ) / sd;
+
+ for( li = 1; li < sd; li++ )
+ {
+ sdPoints[li][0] = start[0] + li * dir[0];
+ sdPoints[li][1] = start[1] + li * dir[1];
+ sdPoints[li][2] = start[2] + li * dir[2];
+ }
+ // transform points (first and last are already transformed)
+ transformProjection( sdPoints.data( ) + 1, sd - 1,
+ m_pCurrentGlView->camera( ) );
+ renderViewStructureSimple( sdPoints, sdLines, sd );
+ }
+ else
+ {
+ sdPoints[0] = start;
+ sdPoints[1] = end;
+ renderViewStructureSimple( sdPoints, sdLines, 1 );
+ }
+ }
+ }
+ else
+ renderViewStructureSimple( points, vs.lines( ) );
+ }
+ else
+ renderViewStructureSimple( vs.points( ), vs.lines( ) );
+}
+
+void PMRenderManager::renderViewStructureSimple( PMPointArray& points,
+ PMLineArray& lines,
+ int numberOfLines )
+{
+ GLuint* linesData = ( GLuint* ) ( lines.data( ) );
+ unsigned int vsLines = 0;
+ unsigned int rl;
+
+ if( numberOfLines < 0 )
+ vsLines = lines.size( );
+ else
+ vsLines = ( unsigned ) numberOfLines;
+
+ glEnableClientState( GL_VERTEX_ARRAY );
+ glVertexPointer( 3, GL_DOUBLE, 0, points.data( ) );
+
+ while( ( vsLines > 0 ) && !m_bStopTask && !m_bStartTask )
+ {
+ rl = m_nMaxRenderedLines - m_renderedLines;
+ if( rl > vsLines )
+ rl = vsLines;
+
+ glDrawElements( GL_LINES, rl * 2,
+ GL_UNSIGNED_INT, linesData );
+
+ m_renderedLines += rl;
+ if( m_renderedLines >= m_nMaxRenderedLines )
+ {
+ m_renderedLines = 0;
+ qApp->processEvents( maxEventTime );
+ if( !m_bStopTask && !m_bStartTask )
+ m_pCurrentGlView->makeCurrent( );
+ }
+
+ vsLines -= rl;
+ linesData = linesData + ( rl * 2 );
+ }
+
+ glDisableClientState( GL_VERTEX_ARRAY );
+}
+
+void PMRenderManager::transformProjection( PMPoint* points, int size,
+ PMCamera* camera )
+{
+ int i;
+ PMPoint* data = points;
+ PMPoint p;
+ double cameraAngle = camera->angle( ) * M_PI / 180.0;
+ double rad, phi, h;
+
+ if( approxZero( cameraAngle ) )
+ cameraAngle = M_PI;
+
+ switch( camera->cameraType( ) )
+ {
+ case PMCamera::Perspective:
+ case PMCamera::Orthographic:
+ break;
+
+ case PMCamera::UltraWideAngle:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+ h = sqrt( p[0] * p[0] + p[1] * p[1] + p[2] * p[2] );
+ if( !approxZero( h ) )
+ {
+ p[0] /= h;
+ p[1] /= h;
+ }
+
+ (*data)[0] = asin( p[0] );
+ (*data)[1] = asin( p[1] );
+ if( p[2] > 0 )
+ {
+ (*data)[0] = M_PI - (*data)[0];
+ (*data)[1] = M_PI - (*data)[1];
+ }
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+
+ case PMCamera::FishEye:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ phi = atan2( p[1], p[0] );
+ rad = atan2( sqrt( p[0] * p[0] + p[1] * p[1] ), -p[2] );
+
+ (*data)[0] = rad * cos( phi );
+ (*data)[1] = rad * sin( phi );
+ (*data)[2] = -sqrt( p[0] * p[0] + p[1] * p[1] + p[2] * p[2] );
+
+ data++;
+ }
+ break;
+
+ case PMCamera::Panoramic:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ (*data)[0] = atan2( p[0], -p[2] );
+ (*data)[1] = atan2( p[1], sqrt( p[0] * p[0] + p[2] * p[2] ) );
+ (*data)[2] = -sqrt( p[0] * p[0] + p[1] * p[1] + p[2] * p[2] );
+
+ data++;
+ }
+ break;
+
+ case PMCamera::Cylinder:
+ switch( camera->cylinderType( ) )
+ {
+ case 1:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ h = sqrt( p[0] * p[0] + p[2] * p[2] );
+ if( approxZero( h ) )
+ h = 1e-5;
+
+ (*data)[0] = atan2( p[0], -p[2] ) / cameraAngle;
+ (*data)[1] = p[1] / h;
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+
+ case 2:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ h = sqrt( p[1] * p[1] + p[2] * p[2] );
+ if( approxZero( h ) )
+ h = 1e-5;
+
+ (*data)[0] = p[0] / h;
+ (*data)[1] = atan2( p[1], -p[2] ) / cameraAngle;
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+
+ case 3:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ h = sqrt( p[0] * p[0] + p[2] * p[2] );
+ if( approxZero( h ) )
+ h = 1e-5;
+
+ (*data)[0] = atan2( p[0], -p[2] ) / cameraAngle;
+ (*data)[1] = p[1];
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+
+ case 4:
+ for( i = 0; i < size; i++ )
+ {
+ p = m_viewTransformation * (*data);
+
+ // reverse povray's calculations
+ p[0] /= m_rightLength;
+ p[1] /= m_upLength;
+ p[2] /= m_directionLength;
+
+ h = sqrt( p[1] * p[1] + p[2] * p[2] );
+ if( approxZero( h ) )
+ h = 1e-5;
+
+ (*data)[0] = p[0];
+ (*data)[1] = atan2( p[1], -p[2] ) / cameraAngle;
+ (*data)[2] = -h;
+
+ data++;
+ }
+ break;
+ }
+ break;
+
+ case PMCamera::Omnimax:
+ break;
+
+ }
+}
+
+void PMRenderManager::renderControlPoints( )
+{
+ if( ( m_pCurrentGlView->type( ) == PMGLView::PMViewCamera )
+ && ( m_pCurrentGlView->camera( ) == m_pCurrentTask->activeObject( ) ) )
+ return;
+
+ if( m_specialCameraMode )
+ m_viewTransformation = m_controlPointTransformation;
+ else
+ glLoadMatrixd( m_controlPointTransformation.data( ) );
+
+ PMControlPointList* cplist = m_pCurrentTask->controlPoints( );
+ if( cplist->count( ) > 0 )
+ {
+ PMControlPointListIterator it( *cplist );
+ PMControlPoint* cp;
+ PMPoint v;
+ const GLubyte* bitmap = 0;
+
+ // draw extra control point lines
+ setGLColor( m_graphicalObjectColor[1] );
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ cp = it.current( );
+ if( cp->hasExtraLine( ) )
+ {
+ PMPoint s = PMPoint( cp->extraLineStart( ) );
+ PMPoint e = PMPoint( cp->extraLineEnd( ) );
+
+ if( m_specialCameraMode )
+ {
+ transformProjection( &s, 1, m_pCurrentGlView->camera( ) );
+ transformProjection( &e, 1, m_pCurrentGlView->camera( ) );
+ }
+
+ glBegin( GL_LINES );
+ glVertex3d( s[0], s[1], s[2] );
+ glVertex3d( e[0], e[1], e[2] );
+ glEnd( );
+ }
+ }
+
+ glDisable( GL_DEPTH_TEST );
+ // draw not selected control points
+ setGLColor( m_controlPointColor[0] );
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ cp = it.current( );
+
+ if( cp->display( ) )
+ {
+ v = PMPoint( cp->position( ) );
+ if( m_specialCameraMode )
+ transformProjection( &v, 1, m_pCurrentGlView->camera( ) );
+ switch( cp->displayType( ) )
+ {
+ case PMControlPoint::CPPoint:
+ if( !cp->selected( ) )
+ bitmap = PointBitmap;
+ break;
+ case PMControlPoint::CPCross:
+ bitmap = CrossBitmap;
+ break;
+ }
+
+ glRasterPos3d( v[0], v[1], v[2] );
+ if( bitmap )
+ glBitmap( controlPointSize, controlPointSize,
+ controlPointSize/2, controlPointSize/2,
+ 0, 0, bitmap );
+ }
+ }
+ // draw selected control points
+ setGLColor( m_controlPointColor[1] );
+ for( it.toFirst( ); it.current( ); ++it )
+ {
+ cp = it.current( );
+
+ if( cp->selected( ) && cp->display( ) )
+ {
+ v = PMPoint( cp->position( ) );
+ if( m_specialCameraMode )
+ transformProjection( &v, 1, m_pCurrentGlView->camera( ) );
+ if( cp->displayType( ) == PMControlPoint::CPPoint )
+ bitmap = PointBitmap;
+
+ glRasterPos3d( v[0], v[1], v[2] );
+ if( bitmap )
+ glBitmap( controlPointSize, controlPointSize,
+ controlPointSize/2, controlPointSize/2,
+ 0, 0, bitmap );
+ }
+ }
+ }
+}
+
+void PMRenderManager::renderAxes( )
+{
+ int i;
+
+ if( !m_axesViewStructureCreated )
+ {
+ m_axesViewStructure[0] = PMViewStructure( 6, 9 );
+ PMPointArray& points = m_axesViewStructure[0].points( );
+ PMLineArray& lines = m_axesViewStructure[0].lines( );
+
+ lines[0] = PMLine( 0, 1 );
+ lines[1] = PMLine( 1, 2 );
+ lines[2] = PMLine( 1, 3 );
+ lines[3] = PMLine( 1, 4 );
+ lines[4] = PMLine( 1, 5 );
+ lines[5] = PMLine( 2, 3 );
+ lines[6] = PMLine( 3, 4 );
+ lines[7] = PMLine( 4, 5 );
+ lines[8] = PMLine( 5, 2 );
+
+ points[0] = PMPoint( 0.0, 0.0, 0.0 );
+ points[1] = PMPoint( 1.0, 0.0, 0.0 );
+ points[2] = PMPoint( dA, dB, dB );
+ points[3] = PMPoint( dA, -dB, dB );
+ points[4] = PMPoint( dA, -dB, -dB );
+ points[5] = PMPoint( dA, dB, -dB );
+
+ m_axesViewStructure[1] = m_axesViewStructure[0];
+ PMPointArray& points1 = m_axesViewStructure[1].points( );
+ points1.detach( );
+
+ points1[0] = PMPoint( 0.0, 0.0, 0.0 );
+ points1[1] = PMPoint( 0.0, 1.0, 0.0 );
+ points1[2] = PMPoint( dB, dA, dB );
+ points1[3] = PMPoint( -dB, dA, dB );
+ points1[4] = PMPoint( -dB, dA, -dB );
+ points1[5] = PMPoint( dB, dA, -dB );
+
+ m_axesViewStructure[2] = m_axesViewStructure[0];
+ PMPointArray& points2 = m_axesViewStructure[2].points( );
+ points2.detach( );
+
+ points2[0] = PMPoint( 0.0, 0.0, 0.0 );
+ points2[1] = PMPoint( 0.0, 0.0, 1.0 );
+ points2[2] = PMPoint( dB, dB, dA );
+ points2[3] = PMPoint( -dB, dB, dA );
+ points2[4] = PMPoint( -dB, -dB, dA );
+ points2[5] = PMPoint( dB, -dB, dA );
+
+ m_axesViewStructureCreated = true;
+ }
+
+ glEnable( GL_DEPTH_TEST );
+ for( i = 0; i < 3; i++ )
+ {
+ setGLColor( m_axesColor[i] );
+ renderViewStructure( m_axesViewStructure[i] );
+ }
+}
+
+PMMatrix PMRenderManager::viewTransformation( PMCamera* c ) const
+{
+ PMVector location, lookAt, sky;
+ PMMatrix m;
+
+ sky = c->sky( );
+ location = c->location( );
+ lookAt = c->lookAt( );
+
+ if( approxZero( sky.abs( ) ) )
+ sky = PMVector( 0.0, 1.0, 0.0 );
+ if( approxZero( ( location - lookAt ).abs( ) ) )
+ lookAt = location + PMVector( 0.0, 0.0, 1.0 );
+
+ m = c->transformedWith( );
+ if( m.canBuildInverse( ) )
+ return PMMatrix::viewTransformation( location, lookAt, sky ) * m.inverse( );
+ return PMMatrix::viewTransformation( location, lookAt, sky );
+}
+
+void PMRenderManager::setProjection( )
+{
+ PMGLView::PMViewType type = m_pCurrentGlView->type( );
+ PMCamera* camera = m_pCurrentGlView->camera( );
+ int width = m_pCurrentGlView->width( );
+ int height = m_pCurrentGlView->height( );
+
+ if( type == PMGLView::PMViewCamera )
+ {
+ if( camera )
+ setCameraProjection( );
+ }
+ else
+ {
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity( );
+
+ double d = m_pCurrentGlView->scale( );
+
+ // TODO calculating the z clipping plane
+ glOrtho( -width/2, width/2, -height/2, height/2,
+ -viewVolumeZ, viewVolumeZ );
+ glScaled( d, d, d );
+ glTranslated( m_pCurrentGlView->translationX( ),
+ m_pCurrentGlView->translationY( ), 0 );
+
+ switch( type )
+ {
+ case PMGLView::PMViewPosZ:
+ break;
+ case PMGLView::PMViewNegZ:
+ glRotated( 180.0, 0.0, 1.0, 0.0 );
+ break;
+ case PMGLView::PMViewNegY:
+ glRotated( 90.0, 1.0, 0.0, 0.0 );
+ break;
+ case PMGLView::PMViewPosY:
+ glRotated( -90.0, 1.0, 0.0, 0.0 );
+ break;
+ case PMGLView::PMViewPosX:
+ glRotated( 90.0, 0.0, 1.0, 0.0 );
+ break;
+ case PMGLView::PMViewNegX:
+ glRotated( -90.0, 0.0, 1.0, 0.0 );
+ break;
+ default:
+ break;
+ }
+
+ glScaled( 1.0, 1.0, -1.0 );
+
+ glMatrixMode( GL_MODELVIEW );
+ m_pCurrentGlView->setProjectionUpToDate( true );
+ }
+}
+
+void PMRenderManager::setCameraProjection( )
+{
+ PMCamera* camera = m_pCurrentGlView->camera( );
+ int width = m_pCurrentGlView->width( );
+ int height = m_pCurrentGlView->height( );
+ double angle = M_PI / 2.0;
+ double modeAspect, viewAspect, cameraAspect;
+
+ m_viewTransformation = viewTransformation( camera );
+ m_upLength = camera->up( ).abs( );
+ if( approxZero( m_upLength ) )
+ m_upLength = 1.0;
+ m_rightLength = camera->right( ).abs( );
+ if( approxZero( m_rightLength ) )
+ m_rightLength = 1.0;
+ m_directionLength = camera->direction( ).abs( );
+ if( approxZero( m_directionLength ) )
+ m_directionLength = 1.0;
+
+ if( camera->isAngleEnabled( ) )
+ angle = camera->angle( ) * M_PI / 180.0;
+
+ m_anglex = 0.5;
+ m_angley = 0.5;
+ if( ( angle <= 0.0 ) || ( angle > 2 * M_PI ) )
+ angle = M_PI;
+
+ switch( camera->cameraType( ) )
+ {
+ case PMCamera::Perspective:
+ // If angle wasn't specified determine one from right and direction
+ if( !camera->isAngleEnabled( ) )
+ angle = 2 * atan2( 0.5 * m_rightLength, m_directionLength );
+ break;
+ case PMCamera::UltraWideAngle:
+ m_anglex = angle / ( 2.0 * M_PI );
+ m_angley = angle / ( 2.0 * M_PI );
+ m_specialCameraMode = true;
+ break;
+ case PMCamera::FishEye:
+ m_anglex = angle / 2.0;
+ m_angley = angle / 2.0;
+ m_specialCameraMode = true;
+ break;
+ case PMCamera::Panoramic:
+ m_anglex = M_PI / 2.0;
+ m_angley = M_PI / 2.0;
+ m_specialCameraMode = true;
+ break;
+ case PMCamera::Cylinder:
+ m_anglex = 0.5;
+ m_angley = 0.5;
+ m_specialCameraMode = true;
+ break;
+ case PMCamera::Omnimax:
+ m_specialCameraMode = true;
+ break;
+ default:
+ break;
+ }
+
+ modeAspect = m_pCurrentTask->aspectRatio( );
+ if( approxZero( modeAspect ) )
+ modeAspect = 1.0;
+ cameraAspect = camera->aspect( );
+ if( approxZero( cameraAspect ) )
+ cameraAspect = 1.0;
+ viewAspect = ( double ) width / ( double ) height;
+ if( approxZero( viewAspect ) )
+ viewAspect = 1.0;
+
+ if( viewAspect > modeAspect )
+ m_anglex *= viewAspect / modeAspect;
+ else
+ m_angley *= modeAspect / viewAspect;
+
+
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity( );
+
+
+ PMVector up, right, direction;
+ double handedness;
+ PMMatrix m;
+
+ up = camera->up( );
+ right = camera->right( );
+ direction = camera->direction( );
+
+ if( approxZero( m_upLength ) )
+ up = PMVector( 0.0, 1.0, 0.0 );
+ if( approxZero( m_rightLength ) )
+ right = PMVector( 1.0, 0.0, 0.0 );
+ if( approxZero( m_directionLength ) )
+ direction = PMVector( 0.0, 0.0, 1.0 );
+
+ handedness = PMVector::dot( PMVector::cross( up, direction ), right );
+
+ switch( camera->cameraType( ) )
+ {
+ case PMCamera::Perspective:
+ if( ( angle <= 0.0 ) || ( angle >= M_PI ) )
+ angle = M_PI / 2.0;
+
+ // opengl needs the vertical angle
+ if( viewAspect < modeAspect )
+ angle = atan( tan( angle / 2.0 ) / cameraAspect * modeAspect
+ / viewAspect ) * 360.0 / M_PI;
+ else
+ angle = atan( tan( angle / 2.0 ) / cameraAspect )
+ * 360.0 / M_PI;
+
+ gluPerspective( angle, cameraAspect * viewAspect / modeAspect,
+ 0.001, viewVolumeZ );
+
+ if( handedness > 0 )
+ glScaled( -1.0, 1.0, 1.0 );
+
+ glMultMatrixd( m_viewTransformation.data( ) );
+ break;
+
+ case PMCamera::Orthographic:
+ m_anglex = m_rightLength / 2.0;
+ m_angley = m_upLength / 2.0;
+
+ if( viewAspect > modeAspect )
+ m_anglex *= viewAspect / modeAspect;
+ else
+ m_angley *= modeAspect / viewAspect;
+
+ glOrtho( -m_anglex, m_anglex, -m_angley, m_angley,
+ 0, viewVolumeZ );
+
+ if( handedness > 0 )
+ glScaled( -1.0, 1.0, 1.0 );
+
+ glMultMatrixd( m_viewTransformation.data( ) );
+ break;
+
+ case PMCamera::UltraWideAngle:
+ case PMCamera::FishEye:
+ case PMCamera::Panoramic:
+ case PMCamera::Cylinder:
+ case PMCamera::Omnimax:
+ glOrtho( -m_anglex, m_anglex, -m_angley, m_angley,
+ -viewVolumeZ, viewVolumeZ );
+
+ if( handedness > 0 )
+ glScaled( -1.0, 1.0, 1.0 );
+ break;
+ }
+
+ glMatrixMode( GL_MODELVIEW );
+ m_pCurrentGlView->setProjectionUpToDate( true );
+}
+
+void PMRenderManager::renderFieldOfView( )
+{
+ if( m_pCurrentGlView->type( ) == PMGLView::PMViewCamera )
+ {
+ PMCamera* camera = m_pCurrentGlView->camera( );
+
+ if( camera )
+ {
+ int width = m_pCurrentGlView->width( );
+ int height = m_pCurrentGlView->height( );
+ double modeAspect, viewAspect;
+ int d, vx1, vx2, vy1, vy2;
+
+ modeAspect = m_pCurrentTask->aspectRatio( ); //camera->aspect( );
+ if( approxZero( modeAspect ) )
+ modeAspect = 1.0;
+ viewAspect = ( double ) width / ( double ) height;
+
+ if( viewAspect < modeAspect )
+ {
+ vx1 = 0;
+ vx2 = width - 1;
+
+ d = ( int ) ( height - width / modeAspect + 0.5 ) / 2;
+
+ vy1 = d;
+ vy2 = height - d - 1;
+ }
+ else
+ {
+ vy1 = 0;
+ vy2 = height - 1;
+
+ d = ( int ) ( height * modeAspect );
+
+ d = ( width - d ) / 2;
+ vx1 = d;
+ vx2 = width - d - 1;
+ }
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glOrtho( 0, width, 0, height, -2, 2 );
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix( );
+ glLoadIdentity( );
+
+ setGLColor( m_fieldOfViewColor );
+ glDisable( GL_DEPTH_TEST );
+
+ if( camera->cameraType( ) == PMCamera::Omnimax )
+ renderString( i18n( "not supported" ), 5.0,
+ height - qApp->fontMetrics( ).height( ) * 2 - 2 );
+ else if( m_specialCameraMode && !m_highDetailCameraView )
+ renderString( i18n( "approximated" ), 5.0,
+ height - qApp->fontMetrics( ).height( ) * 2 - 2 );
+
+ glBegin( GL_LINE_LOOP );
+
+ glVertex2d( vx1, vy1 );
+ glVertex2d( vx2, vy1 );
+ glVertex2d( vx2, vy2 );
+ glVertex2d( vx1, vy2 );
+
+ glEnd( );
+ glEnable( GL_DEPTH_TEST );
+
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix( );
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix( );
+ }
+ }
+}
+
+void PMRenderManager::renderGrid( )
+{
+ double scale = m_pCurrentGlView->scale( );
+
+ if( scale >= 0 )
+ {
+ // calculate the views grid distance
+ double viewGridDistance = pow( 10.0, ceil( log10( ( double ) m_gridDistance / scale ) ) );
+ int sd = ( int ) ( viewGridDistance * scale + 0.5 );
+ if( ( sd * 0.2 ) > m_gridDistance )
+ viewGridDistance *= 0.2;
+ else if( ( sd * 0.5 ) > m_gridDistance )
+ viewGridDistance *= 0.5;
+
+ // draw the grid
+ double x1, x2, y1, y2, sx, sy;
+ double x, y;
+ int gi;
+ double screenx, screeny;
+ double signx = 1.0, signy = 1.0;
+
+ int height = m_pCurrentGlView->height( );
+ int width = m_pCurrentGlView->width( );
+ double transX = m_pCurrentGlView->translationX( );
+ double transY = m_pCurrentGlView->translationY( );
+ int fontHeight = qApp->fontMetrics( ).height( );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glOrtho( -width/2, width/2, -height/2, height/2, -2, 2 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix( );
+ glLoadIdentity( );
+
+ setGLColor( m_gridColor );
+ glDisable( GL_DEPTH_TEST );
+
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosX:
+ signx = -1.0;
+ break;
+ case PMGLView::PMViewPosY:
+ signy = -1.0;
+ break;
+ case PMGLView::PMViewNegZ:
+ signx = -1.0;
+ break;
+ default:
+ break;
+ }
+
+ sx = width / scale;
+ sy = height / scale;
+ x1 = -transX - sx / 2;
+ x2 = -transX + sx / 2;
+ y1 = -transY - sy / 2;
+ y2 = -transY + sy / 2;
+
+ sx = ceil( x1 / viewGridDistance ) * viewGridDistance;
+ gi = 0;
+ x = sx;
+ while( x < x2 )
+ {
+ screenx = ( x + transX ) * scale;
+ glBegin( GL_LINES );
+ glVertex2d( screenx, -height/2 );
+ glVertex2d( screenx, height/2 );
+ glEnd( );
+
+ QString label = QString( "%1" ).arg( x * signx, 0, 'g', 4 );
+ if( approxZero( x ) && label.find( "e-" ) )
+ label = "0";
+
+ renderString( label, screenx + 3, height / 2 - fontHeight - 2 );
+
+ gi++;
+ x = sx + viewGridDistance * gi;
+ }
+
+ sy = ceil( y1 / viewGridDistance ) * viewGridDistance;
+ gi = 0;
+ y = sy;
+ while( y < y2 )
+ {
+ screeny = ( y + transY ) * scale;
+ glBegin( GL_LINES );
+ glVertex2d( -width/2, screeny );
+ glVertex2d( width/2, screeny );
+ glEnd( );
+
+ QString label = QString( "%1" ).arg( y * signy, 0, 'g', 4 );
+ if( approxZero( y ) && label.find( "e-" ) )
+ label = "0";
+
+ renderString( label, -width / 2 + 3, screeny + 2 );
+
+ gi++;
+ y = sy + viewGridDistance * gi;
+ }
+
+
+ setGLColor( axesColor( 0 ) );
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosY:
+ case PMGLView::PMViewPosZ:
+ case PMGLView::PMViewNegY:
+ renderString( "x", width / 2 - qApp->fontMetrics( ).boundingRect( "x" ).width( ) - 4, -3 );
+ break;
+ case PMGLView::PMViewNegZ:
+ renderString( "x", -width / 2 + 3, -3 );
+ break;
+ default:
+ break;
+ }
+ setGLColor( axesColor( 1 ) );
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosX:
+ case PMGLView::PMViewNegX:
+ case PMGLView::PMViewPosZ:
+ case PMGLView::PMViewNegZ:
+ renderString( "y", -3, height / 2 - fontHeight );
+ break;
+ default:
+ break;
+ }
+ setGLColor( axesColor( 2 ) );
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosX:
+ renderString( "z", -width / 2 + 3, -3 );
+ break;
+ case PMGLView::PMViewNegX:
+ renderString( "z", width / 2 - qApp->fontMetrics( ).boundingRect( "z" ).width( ) - 4, -3 );
+ break;
+ case PMGLView::PMViewNegY:
+ renderString( "z", -3, height / 2 - fontHeight );
+ break;
+ case PMGLView::PMViewPosY:
+ renderString( "z", -3, -height / 2 );
+ break;
+ default:
+ break;
+ }
+
+ glEnable( GL_DEPTH_TEST );
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix( );
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix( );
+ }
+}
+
+void PMRenderManager::renderDescription( )
+{
+ int height = m_pCurrentGlView->height( );
+ int width = m_pCurrentGlView->width( );
+ int fontHeight = qApp->fontMetrics( ).height( );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix( );
+ glLoadIdentity( );
+ glOrtho( 0, width, 0, height, -2, 2 );
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix( );
+ glLoadIdentity( );
+
+ setGLColor( m_fieldOfViewColor );
+
+ switch( m_pCurrentGlView->type( ) )
+ {
+ case PMGLView::PMViewPosX:
+ renderString( i18n( "left" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewNegX:
+ renderString( i18n( "right" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewPosY:
+ renderString( i18n( "bottom" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewNegY:
+ renderString( i18n( "top" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewPosZ:
+ renderString( i18n( "front" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewNegZ:
+ renderString( i18n( "back" ), 5.0, height - fontHeight - 2 );
+ break;
+ case PMGLView::PMViewCamera:
+ {
+ PMCamera* c = m_pCurrentGlView->camera( );
+ if( c )
+ {
+ QString name( "-" );
+ if( !c->name( ).isEmpty( ) )
+ name = c->name( );
+ else
+ name = i18n( "(unnamed)" );
+
+ renderString( i18n( "camera" ) + ": " + name,
+ 5.0, height - fontHeight - 2 );
+ }
+ else
+ renderString( i18n( "camera" ), 5.0, height - fontHeight - 2 );
+ break;
+ }
+ }
+
+ glEnable( GL_DEPTH_TEST );
+
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix( );
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix( );
+}
+
+void PMRenderManager::renderString( const QString& str, double x, double y )
+{
+ int width = qApp->fontMetrics( ).boundingRect( str ).width( );
+ int height = qApp->fontMetrics( ).height( );
+
+ // GL wants word aligned bitmap
+ QBitmap bm( ( ( width + 32 ) % 32 ) * 32, height, true );
+
+ QPainter p( &bm );
+ p.setFont( qApp->font( ) );
+ p.drawText( bm.rect( ), Qt::AlignLeft | Qt::AlignBottom, str );
+ p.end();
+
+ // Transform to GL bitmap
+ QImage img = bm.convertToImage( ).mirror( ).convertBitOrder( QImage::BigEndian );
+
+ glRasterPos2d( x, y );
+ glBitmap( img.width( ), img.height( ), 0, 0, 0, 0, img.bits( ) );
+}
+
+void PMRenderManager::setGLColor( const QColor& c )
+{
+ int r, g, b;
+
+ c.rgb( &r, &g, &b );
+ glColor3ub( ( GLubyte ) r, ( GLubyte ) g, ( GLubyte ) b );
+}
+
+void PMRenderManager::slotRenderingSettingsChanged( )
+{
+ emit renderingSettingsChanged( );
+}
+
+void PMRenderManager::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Rendering" );
+ cfg->writeEntry( "BackgroundColor", m_backgroundColor );
+ cfg->writeEntry( "GraphicalObjectColor0", m_graphicalObjectColor[0] );
+ cfg->writeEntry( "GraphicalObjectColor1", m_graphicalObjectColor[1] );
+ cfg->writeEntry( "ControlPointColor0", m_controlPointColor[0] );
+ cfg->writeEntry( "ControlPointColor1", m_controlPointColor[1] );
+ cfg->writeEntry( "AxesColorX", m_axesColor[0] );
+ cfg->writeEntry( "AxesColorY", m_axesColor[1] );
+ cfg->writeEntry( "AxesColorZ", m_axesColor[2] );
+ cfg->writeEntry( "GridColor", m_gridColor );
+ cfg->writeEntry( "GridDistance", m_gridDistance );
+ cfg->writeEntry( "FieldOfViewColor", m_fieldOfViewColor );
+ cfg->writeEntry( "HighDetailCameraViews", m_highDetailCameraView );
+}
+
+void PMRenderManager::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Rendering" );
+
+ m_backgroundColor = cfg->readColorEntry( "BackgroundColor", &m_backgroundColor );
+ m_graphicalObjectColor[0] = cfg->readColorEntry( "GraphicalObjectColor0", &( m_graphicalObjectColor[0] ) );
+ m_graphicalObjectColor[1] = cfg->readColorEntry( "GraphicalObjectColor1", &( m_graphicalObjectColor[1] ) );
+ m_controlPointColor[0] = cfg->readColorEntry( "ControlPointColor0", &( m_controlPointColor[0] ) );
+ m_controlPointColor[1] = cfg->readColorEntry( "ControlPointColor1", &( m_controlPointColor[1] ) );
+ m_axesColor[0] = cfg->readColorEntry( "AxesColorX", &( m_axesColor[0] ) );
+ m_axesColor[1] = cfg->readColorEntry( "AxesColorY", &( m_axesColor[1] ) );
+ m_axesColor[2] = cfg->readColorEntry( "AxesColorZ", &( m_axesColor[2] ) );
+ m_gridColor = cfg->readColorEntry( "GridColor", &m_gridColor );
+ m_gridDistance = cfg->readNumEntry( "GridDistance", m_gridDistance );
+ m_fieldOfViewColor = cfg->readColorEntry( "FieldOfViewColor", &m_fieldOfViewColor );
+ m_highDetailCameraView = cfg->readBoolEntry( "HighDetailCameraViews", m_highDetailCameraView );
+}
+
+bool PMRenderManager::hasOpenGL( )
+{
+ if( !s_hasOpenGLChecked )
+ {
+ s_hasOpenGL = ( glXQueryExtension( qt_xdisplay( ), 0, 0 ) != 0 );
+ s_hasOpenGLChecked = true;
+ }
+
+ return s_hasOpenGL;
+}
+
+void PMRenderManager::disableOpenGL( )
+{
+ s_hasOpenGLChecked = true;
+ s_hasOpenGL = false;
+}
+
+#include "pmrendermanager.moc"
diff --git a/kpovmodeler/pmrendermanager.h b/kpovmodeler/pmrendermanager.h
new file mode 100644
index 00000000..a29a6589
--- /dev/null
+++ b/kpovmodeler/pmrendermanager.h
@@ -0,0 +1,435 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMRENDERMANAGER_H
+#define PMRENDERMANAGER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcontrolpoint.h"
+#include "pmmatrix.h"
+#include "pmobject.h"
+#include "pmviewstructure.h"
+
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qcolor.h>
+#include <qptrstack.h>
+#include <qvaluestack.h>
+#include <kstaticdeleter.h>
+#include <GL/gl.h>
+
+class PMGLView;
+class PMCamera;
+class PMPoint;
+class KConfig;
+class QString;
+
+/**
+ * Used internally by PMRenderManager.
+ *
+ * This class stores informations for one render task.
+ */
+class PMRenderTask
+{
+public:
+ PMRenderTask( PMGLView* view, PMObject* active, PMObject* top,
+ PMControlPointList* controlPoints, double aspectRatio,
+ int visibilityLevel )
+ {
+ m_pView = view;
+ m_pActiveObject = active;
+ m_pTopLevelObject = top;
+ m_pControlPoints = controlPoints;
+ m_aspectRatio = aspectRatio;
+ m_visibilityLevel = visibilityLevel;
+ }
+
+ ~PMRenderTask( ) { };
+
+ PMGLView* view( ) const { return m_pView; }
+ PMObject* activeObject( ) const { return m_pActiveObject; }
+ PMObject* topLevelObject( ) const { return m_pTopLevelObject; }
+ PMControlPointList* controlPoints( ) const { return m_pControlPoints; }
+ double aspectRatio( ) const { return m_aspectRatio; }
+ int visibilityLevel( ) const { return m_visibilityLevel; }
+
+ void setView( PMGLView* view ) { m_pView = view; }
+ void setActiveObject( PMObject* obj ) { m_pActiveObject = obj; }
+ void setTopLevelObject( PMObject* obj ) { m_pTopLevelObject = obj; }
+ void setControlPoints( PMControlPointList* list ) { m_pControlPoints = list; }
+ void setAspectRatio( double ar ) { m_aspectRatio = ar; }
+ void setVisibilityLevel( int l ) { m_visibilityLevel = l; }
+
+private:
+ PMGLView* m_pView;
+ PMObject* m_pActiveObject;
+ PMObject* m_pTopLevelObject;
+ PMControlPointList* m_pControlPoints;
+ double m_aspectRatio;
+ int m_visibilityLevel;
+};
+
+typedef QPtrList<PMRenderTask> PMRenderTaskList;
+typedef QPtrListIterator<PMRenderTask> PMRenderTaskListIterator;
+
+/**
+ * Class that controls the background rendering
+ */
+class PMRenderManager : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Returns a pointer to the render manager
+ */
+ static PMRenderManager* theManager( );
+ /**
+ * destructor
+ */
+ ~PMRenderManager( );
+ /**
+ * Adds the @ref PMGLView to the list of views that have to be rendered.
+ *
+ * @param view The view
+ * @param active The active object
+ * @param top The top level object (normally the scene)
+ * @param controlPoints A pointer to the list of control points for the
+ * active object
+ * @param graphicalChange If true the view will be rendered with higher
+ * priority
+ */
+ void addView( PMGLView* view, PMObject* active, PMObject* top,
+ PMControlPointList* controlPoints, double aspectRatio,
+ int visibilityLevel, bool graphicalChange );
+ /**
+ * Removes the view from the list of views that have to be rendered
+ */
+ void removeView( PMGLView* view );
+
+ /**
+ * Call this method if a PMGLView was created
+ */
+ void viewCreated( ) { m_nViews++; }
+ /**
+ * Call this method if a PMGLView was deleted
+ */
+ void viewDeleted( ) { m_nViews--; }
+
+ /**
+ * Returns true if the render manager holds a task for the view
+ */
+ bool containsTask( PMGLView* view ) const;
+
+ /**
+ * Returns the color for the control points
+ */
+ QColor controlPointColor( int i ) const;
+ /**
+ * Sets the control point color
+ */
+ void setControlPointColor( int i, const QColor& c );
+ /**
+ * Returns the color for graphical objects
+ */
+ QColor graphicalObjectColor( int i ) const;
+ /**
+ * Sets the graphical object color
+ */
+ void setGraphicalObjectColor( int i, const QColor& c );
+ /**
+ * Returns the color for the coordinate axes
+ */
+ QColor axesColor( int i ) const;
+ /**
+ * Sets the axes color
+ */
+ void setAxesColor( int i, const QColor& c );
+ /**
+ * Returns the background color
+ */
+ QColor backgroundColor( ) const { return m_backgroundColor; }
+ /**
+ * Sets the background color
+ */
+ void setBackgroundColor( const QColor& c ) { m_backgroundColor = c; }
+ /**
+ * Returns the field of view color.
+ */
+ QColor fieldOfViewColor( ) const { return m_fieldOfViewColor; }
+ /**
+ * Sets the field of view color
+ */
+ void setFieldOfViewColor( const QColor& c ) { m_fieldOfViewColor = c; }
+
+ /**
+ * Sets the grid color
+ */
+ void setGridColor( const QColor& c ) { m_gridColor = c; }
+ /**
+ * Returns the grid color
+ */
+ QColor gridColor( ) { return m_gridColor; }
+ /**
+ * Sets the grid distance
+ */
+ void setGridDistance( int d );
+ /**
+ * Returns the grid distance
+ */
+ int gridDistance( ) { return m_gridDistance; }
+
+ /**
+ * Returns true if the camera views with complex projections
+ * are rendered with high detail
+ */
+ bool highDetailCameraViews( ) const { return m_highDetailCameraView; }
+ /**
+ * Sets the highDetailCameraView flag
+ */
+ void setHighDetailCameraViews( bool yes ) { m_highDetailCameraView = yes; }
+
+ /**
+ * Sets the gl drawing color
+ */
+ static void setGLColor( const QColor& c );
+
+ /**
+ * Saves the configuration
+ */
+ void saveConfig( KConfig* cfg );
+ /**
+ * Restores the configuration
+ */
+ void restoreConfig( KConfig* cfg );
+
+ /**
+ * Returns true if the glx extension is available
+ */
+ static bool hasOpenGL( );
+ /**
+ * Disables OpenGL rendering
+ */
+ static void disableOpenGL( );
+
+public slots:
+ /**
+ * Stops rendering
+ */
+ void slotStopRendering( );
+ /**
+ * Call this when rendering settings have been changed
+ */
+ void slotRenderingSettingsChanged( );
+
+signals:
+ /**
+ * Emitted when rendering starts for the view v
+ */
+ void renderingStarted( PMGLView* v );
+ /**
+ * Emitted just before the view is updated
+ */
+ void aboutToUpdate( PMGLView* v );
+ /**
+ * Emitted when rendering has been finished for the view v
+ */
+ void renderingFinished( PMGLView* v );
+ /**
+ * Emitted when rendering settings (colors ...) have been changed
+ */
+ void renderingSettingsChanged( );
+ /**
+ * Emitted when rendering has started
+ */
+ void renderingStarted( );
+ /**
+ * Emitted when rendering has finished
+ */
+ void renderingFinished( );
+
+protected:
+ virtual void timerEvent( QTimerEvent* );
+
+private:
+ /**
+ * constructor
+ */
+ PMRenderManager( );
+
+ /**
+ * Restarts rendering
+ */
+ void restartRendering( );
+
+ /**
+ * The background task for rendering
+ */
+ void renderTask( );
+ /**
+ * Renders one object
+ */
+ void renderObject( PMObject* obj );
+ /**
+ * Renders the view structure, subdivides the lines in high
+ detail camera views */
+ void renderViewStructure( PMViewStructure& vs );
+ /**
+ * Renders the view structure without subdivisions
+ */
+ void renderViewStructureSimple( PMPointArray& points, PMLineArray& lines,
+ int numberOfLines = -1 );
+ /**
+ * Renders the control points
+ */
+ void renderControlPoints( );
+ /**
+ * Draws the grid
+ */
+ void renderGrid( );
+ /**
+ * Draws the coordinate axis
+ */
+ void renderAxes( );
+ /**
+ * Draws the field of view for camera views
+ */
+ void renderFieldOfView( );
+ /**
+ * Draws the view descriptions
+ */
+ void renderDescription( );
+ /**
+ * Renders the string
+ */
+ void renderString( const QString& str, double x, double y );
+
+ /**
+ * Transforms and renders the view structure for special
+ * camera projection types.
+ */
+ void transformProjection( PMPoint* points, int size, PMCamera* camera );
+ /**
+ * Sets the projection for the current view
+ */
+ void setProjection( );
+ /**
+ * Sets the projection for a camera view
+ */
+ void setCameraProjection( );
+
+ /**
+ * Calculates the view transformation for the camera c
+ */
+ PMMatrix viewTransformation( PMCamera* c ) const;
+
+ /**
+ * List of render tasks. The first has the highest priority
+ */
+ QPtrList<PMRenderTask> m_renderTasks;
+ /**
+ * Flag for background rendering
+ */
+ bool m_bStopTask, m_bStartTask, m_bTaskIsRunning;
+ /**
+ * The color for view structures of graphical objects.
+ *
+ * index 0: normal color, 1: selected
+ */
+ QColor m_graphicalObjectColor[2];
+ /**
+ * The color for view structures of textures
+ */
+ QColor m_textureColor[2];
+ /**
+ * The color for the coordinate axes
+ */
+ QColor m_axesColor[3];
+ /**
+ * The background color
+ */
+ QColor m_backgroundColor;
+ /**
+ * color for control points
+ *
+ * index 0: normal color, 1: selected
+ */
+ QColor m_controlPointColor[2];
+ /**
+ * Color for the field of view box
+ */
+ QColor m_fieldOfViewColor;
+
+ /**
+ * Grid distance and color
+ */
+ int m_gridDistance;
+ QColor m_gridColor;
+ /**
+ * If true, lines are subdivided in camera views with complex
+ * projections
+ */
+ bool m_highDetailCameraView;
+
+ /**
+ * Number of rendered lines between calls of processEvents( )
+ */
+ unsigned int m_nMaxRenderedLines;
+
+ /**
+ * Number of gl views
+ */
+ unsigned int m_nViews;
+ /**
+ * The render manager (singleton pattern)
+ */
+ static PMRenderManager* s_pManager;
+ static KStaticDeleter<PMRenderManager> s_staticDeleter;
+
+ // Member variables to save stack space during rendering
+ PMRenderTask* m_pCurrentTask;
+ PMGLView* m_pCurrentGlView;
+ QPtrStack<PMMatrix> m_matrixStack; // I don't know if the build in gl matrix stack is deep enough
+ bool m_selected;
+ PMObject* m_pDeselectObject;
+ PMObjectList m_objectToRenderStack;
+ QPtrStack<PMObject> m_quickColorObjects;
+ QPtrStack<QColor> m_quickColors;
+ QColor m_currentColor;
+ QValueStack<int> m_visibilityStack;
+ int m_currentVisibility;
+ unsigned int m_renderedLines;
+ PMMatrix m_controlPointTransformation;
+
+ // for transformProjection
+ bool m_specialCameraMode;
+ PMMatrix m_viewTransformation;
+ double m_upLength, m_rightLength, m_directionLength;
+ double m_anglex, m_angley;
+ PMViewStructure m_subdivisionViewStructure;
+
+ PMViewStructure m_axesViewStructure[3];
+ bool m_axesViewStructureCreated;
+
+ static bool s_hasOpenGL;
+ static bool s_hasOpenGLChecked;
+};
+
+#endif
diff --git a/kpovmodeler/pmrendermode.cpp b/kpovmodeler/pmrendermode.cpp
new file mode 100644
index 00000000..1dc32290
--- /dev/null
+++ b/kpovmodeler/pmrendermode.cpp
@@ -0,0 +1,220 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmrendermode.h"
+#include <klocale.h>
+
+#include "pmxmlhelper.h"
+
+
+PMRenderMode::PMRenderMode( )
+{
+ init( );
+}
+
+void PMRenderMode::init( )
+{
+ m_width = 640;
+ m_height = 480;
+
+ m_subSection = false;
+ m_startRow = 1;
+ m_endRow = m_height;
+ m_startColumn = 1;
+ m_endColumn = m_width;
+
+ m_quality = 9;
+
+ m_radiosity = false;
+
+ m_antialiasing = false;
+ m_samplingMethod = AntialiasingNonRecursive;
+ m_antialiasThreshold = 0.3;
+ m_antialiasJitter = false;
+ m_antialiasJitterAmount = 1.0;
+ m_antialiasDepth = 2;
+
+ m_description = i18n( "New mode" );
+
+ m_alpha = false;
+}
+
+PMRenderMode::PMRenderMode( const QDomElement& e )
+{
+ init( );
+
+ PMXMLHelper hlp( e, 0, 0, 0, 0 );
+ m_description = hlp.stringAttribute( "description", m_description );
+ m_height = hlp.intAttribute( "height", m_height );
+ m_width = hlp.intAttribute( "width", m_width );
+ m_subSection = hlp.boolAttribute( "subsection", m_subSection );
+ m_startColumn = hlp.doubleAttribute( "start_column", m_startColumn );
+ m_endColumn = hlp.doubleAttribute( "end_column", m_endColumn );
+ m_startRow = hlp.doubleAttribute( "start_row", m_startRow );
+ m_endRow = hlp.doubleAttribute( "end_row", m_endRow );
+ m_quality = hlp.intAttribute( "quality", m_quality );
+ m_radiosity = hlp.boolAttribute( "radiosity", m_radiosity );
+ m_antialiasing = hlp.boolAttribute( "antialiasing", m_antialiasing );
+ m_samplingMethod = hlp.intAttribute( "sampling_method", m_samplingMethod );
+ m_antialiasThreshold = hlp.doubleAttribute( "aa_threshold", m_antialiasThreshold );
+ m_antialiasJitter = hlp.boolAttribute( "aa_jitter", m_antialiasJitter );
+ m_antialiasJitterAmount = hlp.doubleAttribute( "aa_jitter_amount", m_antialiasJitterAmount );
+ m_antialiasDepth = hlp.intAttribute( "aa_depth", m_antialiasDepth );
+ m_alpha = hlp.boolAttribute( "alpha", m_alpha );
+}
+
+void PMRenderMode::serialize( QDomElement& e ) const
+{
+ e.setAttribute( "description", m_description );
+ e.setAttribute( "height", m_height );
+ e.setAttribute( "width", m_width );
+ e.setAttribute( "subsection", m_subSection );
+ e.setAttribute( "start_row", m_startRow );
+ e.setAttribute( "end_row", m_endRow );
+ e.setAttribute( "start_column", m_startColumn );
+ e.setAttribute( "end_column", m_endColumn );
+ e.setAttribute( "quality", m_quality );
+ e.setAttribute( "radiosity", m_radiosity );
+ e.setAttribute( "antialiasing", m_antialiasing );
+ e.setAttribute( "sampling_method", m_samplingMethod );
+ e.setAttribute( "aa_threshold", m_antialiasThreshold );
+ e.setAttribute( "aa_jitter", m_antialiasJitter );
+ e.setAttribute( "aa_jitter_amount", m_antialiasJitterAmount );
+ e.setAttribute( "aa_depth", m_antialiasDepth );
+ e.setAttribute( "alpha", m_alpha );
+}
+
+void PMRenderMode::setHeight( int height )
+{
+ if( height >= 1 )
+ m_height = height;
+}
+
+void PMRenderMode::setWidth( int width )
+{
+ if( width >= 1 )
+ m_width = width;
+}
+
+void PMRenderMode::setStartRow( double startRow )
+{
+ if( startRow >= 0 )
+ m_startRow = startRow;
+}
+
+void PMRenderMode::setEndRow( double endRow )
+{
+ if( endRow >= 0 )
+ m_endRow = endRow;
+}
+
+void PMRenderMode::setStartColumn( double startColumn )
+{
+ if( startColumn >= 0 )
+ m_startColumn = startColumn;
+}
+
+void PMRenderMode::setEndColumn( double endColumn )
+{
+ if( endColumn >= 0 )
+ m_endColumn = endColumn;
+}
+
+void PMRenderMode::setQuality( int quality )
+{
+ if( ( quality >= 0 ) && ( quality <= 11 ) )
+ m_quality = quality;
+}
+
+void PMRenderMode::setAntialiasingDepth( int depth )
+{
+ if( ( depth >= 1 ) && ( depth <= 9 ) )
+ m_antialiasDepth = depth;
+}
+
+void PMRenderMode::setSamplingMethod( int method )
+{
+ if( ( method == AntialiasingNonRecursive )
+ || ( method == AntialiasingRecursive ) )
+ m_samplingMethod = method;
+ else
+ m_samplingMethod = AntialiasingNonRecursive;
+}
+
+QStringList PMRenderMode::commandLineSwitches( ) const
+{
+ QStringList cl;
+ QString tmp;
+
+ cl.append( QString( "+W%1" ).arg( m_width ) );
+ cl.append( QString( "+H%1" ).arg( m_height ) );
+ if( m_subSection )
+ {
+ if( m_startRow < 1.0 )
+ tmp.sprintf( "+SR%4.2f", m_startRow );
+ else
+ tmp = QString( "+SR%1" ).arg( ( int ) ( m_startRow + 0.5 ) );
+ cl.append( tmp );
+ if( m_endRow < 1.0 )
+ tmp.sprintf( "+ER%4.2f", m_endRow );
+ else
+ tmp = QString( "+ER%1" ).arg( ( int ) ( m_endRow + 0.5 ) );
+ cl.append( tmp );
+
+ if( m_startColumn < 1.0 )
+ tmp.sprintf( "+SC%4.2f", m_startColumn );
+ else
+ tmp = QString( "+SC%1" ).arg( ( int ) ( m_startColumn + 0.5 ) );
+ cl.append( tmp );
+ if( m_endColumn < 1.0 )
+ tmp.sprintf( "+EC%4.2f", m_endColumn );
+ else
+ tmp = QString( "+EC%1" ).arg( ( int ) ( m_endColumn + 0.5 ) );
+ cl.append( tmp );
+ }
+ cl.append( QString( "+Q%1" ).arg( m_quality ) );
+ if( m_radiosity )
+ cl.append( QString( "+QR" ) );
+ else
+ cl.append( QString( "-QR" ) );
+
+ if( m_antialiasing )
+ {
+ cl.append( QString( "+A" ) );
+ cl.append( QString( "+AM%1" ).arg( m_samplingMethod ) );
+ tmp.sprintf( "+A%5.3f", m_antialiasThreshold );
+ cl.append( tmp );
+ if( m_antialiasJitter )
+ {
+ tmp.sprintf( "+J%5.3f", m_antialiasJitterAmount );
+ cl.append( tmp );
+ }
+ else
+ cl.append( QString( "-J" ) );
+ cl.append( QString( "+R%1" ).arg( m_antialiasDepth ) );
+ }
+ else
+ cl.append( QString( "-A" ) );
+
+ if( m_alpha )
+ cl.append( QString( "+UA" ) );
+ else
+ cl.append( QString( "-UA" ) );
+
+ return cl;
+}
+
diff --git a/kpovmodeler/pmrendermode.h b/kpovmodeler/pmrendermode.h
new file mode 100644
index 00000000..a8c891ce
--- /dev/null
+++ b/kpovmodeler/pmrendermode.h
@@ -0,0 +1,128 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMRENDERMODE_H
+#define PMRENDERMODE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qdom.h>
+
+/**
+ * Class that represents the render options for povray
+ *
+ * See povray documentation, output options.
+ */
+class PMRenderMode
+{
+public:
+ /**
+ * Sampling method for antialiasing. See povray documentation.
+ */
+ enum AASamplingMethod { AntialiasingNonRecursive = 0, AntialiasingRecursive = 1 };
+
+ /**
+ * Default constructor
+ */
+ PMRenderMode( );
+ /**
+ * Reads the attributes from the QDomElement
+ */
+ PMRenderMode( const QDomElement& e );
+
+ void setDescription( const QString& descr ) { m_description = descr; }
+ QString description( ) const { return m_description; }
+
+ void setHeight( int height );
+ int height( ) const { return m_height; }
+ void setWidth( int width );
+ int width( ) const { return m_width; }
+
+ void setSubSection( bool on ) { m_subSection = on; }
+ bool subSection( ) const { return m_subSection; }
+ void setStartRow( double startRow );
+ double startRow( ) const { return m_startRow; }
+ void setEndRow( double endRow );
+ double endRow( ) const { return m_endRow; }
+ void setStartColumn( double startColumn );
+ double startColumn( ) const { return m_startColumn; }
+ void setEndColumn( double endColumn );
+ double endColumn( ) const { return m_endColumn; }
+
+ void setQuality( int quality );
+ int quality( ) const { return m_quality; }
+
+ void setRadiosity( bool on ) { m_radiosity = on; }
+ bool radiosity( ) const { return m_radiosity; }
+
+ void setAntialiasing( bool on ) { m_antialiasing = on; }
+ bool antialiasing( ) const { return m_antialiasing; }
+ void setSamplingMethod( int method );
+ int samplingMethod( ) const { return m_samplingMethod; }
+ void setAntialiasingThreshold( double t ) { m_antialiasThreshold = t; }
+ double antialiasingThreshold( ) const { return m_antialiasThreshold; }
+ void setAntialiasingJitter( bool on ) { m_antialiasJitter = on; }
+ bool antialiasingJitter( ) const { return m_antialiasJitter; }
+ void setAntialiasingJitterAmount( double amount ) { m_antialiasJitterAmount = amount; }
+ double antialiasingJitterAmount( ) const { return m_antialiasJitterAmount; }
+ void setAntialiasingDepth( int depth );
+ int antialiasingDepth( ) const { return m_antialiasDepth; }
+
+ void setAlpha( bool on ) { m_alpha = on; }
+ bool alpha( ) const { return m_alpha; }
+
+
+ /**
+ * Returns the settings as povray command line switches
+ */
+ QStringList commandLineSwitches( ) const;
+ /**
+ * Saves the data
+ */
+ void serialize( QDomElement& e ) const;
+
+private:
+ void init( );
+
+ QString m_description;
+ int m_height, m_width;
+ bool m_subSection;
+ double m_startRow, m_endRow, m_startColumn, m_endColumn;
+
+ int m_quality;
+ bool m_radiosity;
+ bool m_antialiasing;
+ int m_samplingMethod;
+ double m_antialiasThreshold;
+ bool m_antialiasJitter;
+ double m_antialiasJitterAmount;
+ int m_antialiasDepth;
+
+ bool m_alpha;
+};
+
+typedef QPtrList<PMRenderMode> PMRenderModeList;
+typedef QPtrListIterator<PMRenderMode> PMRenderModeListIterator;
+
+#endif
diff --git a/kpovmodeler/pmrendermodesdialog.cpp b/kpovmodeler/pmrendermodesdialog.cpp
new file mode 100644
index 00000000..5c4b4b7b
--- /dev/null
+++ b/kpovmodeler/pmrendermodesdialog.cpp
@@ -0,0 +1,611 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmrendermodesdialog.h"
+
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlineedit.h>
+#include <qtabwidget.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+
+#include "pmlineedits.h"
+
+QSize PMRenderModesDialog::s_size = QSize( 300, 200 );
+
+PMRenderModesDialog::PMRenderModesDialog( PMRenderModeList* modes, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Render Modes" ),
+ Ok | Cancel, Ok )
+{
+ m_selectionIndex = modes->at( );
+ m_pOriginalModes = modes;
+ PMRenderModeListIterator it( *modes );
+ for( ; it.current( ); ++it )
+ m_workingModes.append( new PMRenderMode( *( it.current( ) ) ) );
+ m_workingModes.setAutoDelete( true );
+
+ QVBox* mainPage = makeVBoxMainWidget( );
+ m_pListBox = new QListBox( mainPage );
+ connect( m_pListBox, SIGNAL( highlighted( int ) ), SLOT( slotModeSelected( int ) ) );
+
+ QHBox* buttons = new QHBox( mainPage );
+ buttons->setSpacing( KDialog::spacingHint( ) );
+ m_pAddButton = new QPushButton( i18n( "Add" ), buttons );
+ connect( m_pAddButton, SIGNAL( clicked( ) ), SLOT( slotAdd( ) ) );
+ m_pRemoveButton = new QPushButton( i18n( "Remove" ), buttons );
+ connect( m_pRemoveButton, SIGNAL( clicked( ) ), SLOT( slotRemove( ) ) );
+ m_pEditButton = new QPushButton( i18n( "Edit..." ), buttons );
+ connect( m_pEditButton, SIGNAL( clicked( ) ), SLOT( slotEdit( ) ) );
+ m_pUpButton = new QPushButton( i18n( "Up" ), buttons );
+ connect( m_pUpButton, SIGNAL( clicked( ) ), SLOT( slotUp( ) ) );
+ m_pDownButton = new QPushButton( i18n( "Down" ), buttons );
+ connect( m_pDownButton, SIGNAL( clicked( ) ), SLOT( slotDown( ) ) );
+
+ m_pRemoveButton->setEnabled( false );
+ m_pUpButton->setEnabled( false );
+ m_pDownButton->setEnabled( false );
+
+ enableButtonOK( false );
+
+ resize( s_size );
+ displayList( );
+ connect( m_pListBox, SIGNAL( doubleClicked ( QListBoxItem *) ), this, SLOT(slotEdit( ) ) );
+}
+
+void PMRenderModesDialog::slotChanged( )
+{
+ enableButtonOK( true );
+}
+
+void PMRenderModesDialog::slotModeSelected( int index )
+{
+ m_selectionIndex = index;
+ checkButtons( );
+ slotChanged( );
+}
+
+void PMRenderModesDialog::displayList( )
+{
+ PMRenderModeListIterator it( m_workingModes );
+ bool b = m_pListBox->signalsBlocked( );
+ m_pListBox->blockSignals( true );
+
+ m_pListBox->clear( );
+ for( ; it.current( ); ++it )
+ m_pListBox->insertItem( it.current( )->description( ) );
+ m_pListBox->setSelected( m_selectionIndex, true );
+
+ m_pListBox->blockSignals( b );
+
+ checkButtons( );
+}
+
+void PMRenderModesDialog::checkButtons( )
+{
+ if( m_selectionIndex < 0 )
+ {
+ m_pRemoveButton->setEnabled( false );
+ m_pEditButton->setEnabled( false );
+ m_pUpButton->setEnabled( false );
+ m_pDownButton->setEnabled( false );
+ }
+ else
+ {
+ int num = m_workingModes.count( );
+
+ m_pRemoveButton->setEnabled( true );
+ m_pEditButton->setEnabled( true );
+ m_pUpButton->setEnabled( m_selectionIndex != 0 );
+ m_pDownButton->setEnabled( m_selectionIndex != ( num - 1 ) );
+ }
+}
+
+void PMRenderModesDialog::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+ cfg->writeEntry( "RenderModesDialogSize", s_size );
+}
+
+void PMRenderModesDialog::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+
+ QSize defaultSize( 300, 200 );
+ s_size = cfg->readSizeEntry( "RenderModesDialogSize", &defaultSize );
+}
+
+void PMRenderModesDialog::resizeEvent( QResizeEvent* ev )
+{
+ s_size = ev->size( );
+}
+
+void PMRenderModesDialog::slotAdd( )
+{
+ m_selectionIndex++;
+ if( m_selectionIndex < 0 )
+ m_selectionIndex = 0;
+ m_workingModes.insert( ( uint ) m_selectionIndex, new PMRenderMode( ) );
+
+ displayList( );
+ slotChanged( );
+}
+
+void PMRenderModesDialog::slotRemove( )
+{
+ m_workingModes.remove( ( uint ) m_selectionIndex );
+
+ int num = m_workingModes.count( );
+ if( m_selectionIndex >= num )
+ m_selectionIndex = num - 1;
+
+ displayList( );
+ slotChanged( );
+}
+
+void PMRenderModesDialog::slotUp( )
+{
+ PMRenderMode* mode = m_workingModes.take( ( uint ) m_selectionIndex );
+ m_selectionIndex--;
+ if( m_selectionIndex < 0 )
+ m_selectionIndex = 0;
+ m_workingModes.insert( m_selectionIndex, mode );
+
+ displayList( );
+ slotChanged( );
+}
+
+void PMRenderModesDialog::slotDown( )
+{
+ PMRenderMode* mode = m_workingModes.take( ( uint ) m_selectionIndex );
+ m_selectionIndex++;
+
+ int num = m_workingModes.count( );
+ if( m_selectionIndex > num )
+ m_selectionIndex = num;
+ m_workingModes.insert( m_selectionIndex, mode );
+
+ displayList( );
+ slotChanged( );
+}
+
+void PMRenderModesDialog::slotEdit( )
+{
+ if ( m_selectionIndex==-1 )
+ return;
+ PMRenderModeDialog dlg( m_workingModes.at( m_selectionIndex ) );
+ bool changed = ( dlg.exec( ) == QDialog::Accepted );
+ if( changed )
+ {
+ slotChanged( );
+ displayList( );
+ }
+}
+
+void PMRenderModesDialog::slotOk( )
+{
+ m_pOriginalModes->setAutoDelete( true );
+ m_pOriginalModes->clear( );
+ m_pOriginalModes->setAutoDelete( false );
+ *m_pOriginalModes = m_workingModes;
+ m_pOriginalModes->at( m_selectionIndex );
+
+ m_workingModes.setAutoDelete( false );
+ m_workingModes.clear( );
+
+ accept( );
+}
+
+
+QSize PMRenderModeDialog::s_size = QSize( 300, 200 );
+
+const int numQuality = 9;
+const char* qualityString[numQuality] =
+{
+ I18N_NOOP( "0, 1: Quick colors, full ambient lighting only" ),
+ I18N_NOOP( "2, 3: Show specified diffuse and ambient light" ),
+ I18N_NOOP( "4: Render shadows, but no extended lights" ),
+ I18N_NOOP( "5: Render shadows, including extended lights" ),
+ I18N_NOOP( "6, 7: Compute texture patterns" ),
+ I18N_NOOP( "8: Compute reflected, refracted, and transmitted rays" ),
+ I18N_NOOP( "9: Compute media" ),
+ I18N_NOOP( "10: Compute radiosity but no media" ),
+ I18N_NOOP( "11: Compute radiosity and media" )
+};
+
+const int c_qualityToIndex[12] = { 0, 0, 1, 1, 2, 3, 4, 4, 5, 6, 7, 8 };
+const int c_indexToQuality[numQuality] = { 0, 2, 4, 5, 6, 8, 9, 10, 11 };
+
+PMRenderModeDialog::PMRenderModeDialog( PMRenderMode* mode, QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "Render Modes" ),
+ Ok | Cancel, Ok )
+{
+ m_pMode = mode;
+ int i;
+
+ // main page
+ QWidget* page = new QWidget( this );
+ setMainWidget( page );
+ QVBoxLayout* topLayout = new QVBoxLayout( page, 0, spacingHint( ) );
+
+ QHBoxLayout* descrLayout = new QHBoxLayout( topLayout );
+ QLabel* descrLabel = new QLabel( i18n( "Description:" ), page );
+ descrLayout->addWidget( descrLabel );
+
+ m_pDescriptionEdit = new QLineEdit( page );
+ descrLayout->addWidget( m_pDescriptionEdit );
+
+ m_pTabWidget = new QTabWidget( page );
+ topLayout->addWidget( m_pTabWidget );
+
+ QWidget* tab;
+ QVBoxLayout* tabLayout;
+
+ // size tab
+ tab = new QWidget( );
+ m_pTabWidget->addTab( tab, i18n( "Size" ) );
+ tabLayout = new QVBoxLayout( tab, marginHint( ), spacingHint( ) );
+
+ QHBoxLayout* sizeHelpLayout = new QHBoxLayout( tabLayout );
+ QGridLayout* sizeLayout = new QGridLayout( sizeHelpLayout, 2, 2 );
+ sizeLayout->addWidget( new QLabel( i18n( "Width:" ), tab ), 0, 0 );
+ m_pWidthEdit = new PMIntEdit( tab );
+ m_pWidthEdit->setValidation( true, 1, false, 0 );
+ sizeLayout->addWidget( m_pWidthEdit, 0, 1 );
+ sizeLayout->addWidget( new QLabel( i18n( "Height:" ), tab ), 1, 0 );
+ m_pHeightEdit = new PMIntEdit( tab );
+ m_pHeightEdit->setValidation( true, 1, false, 0 );
+ sizeLayout->addWidget( m_pHeightEdit, 1, 1 );
+ sizeHelpLayout->addStretch( 1 );
+
+ m_pSubsectionBox = new QCheckBox( i18n( "Subsection" ), tab );
+ tabLayout->addWidget( m_pSubsectionBox );
+
+ QHBoxLayout* ssHelpLayout = new QHBoxLayout( tabLayout );
+ QGridLayout* ssLayout = new QGridLayout( ssHelpLayout, 4, 2 );
+ ssLayout->addWidget( new QLabel( i18n( "Start column:" ), tab ), 0, 0 );
+ m_pStartColumnEdit = new PMFloatEdit( tab );
+ m_pStartColumnEdit->setValidation( true, 0.0, false, 0.0 );
+ ssLayout->addWidget( m_pStartColumnEdit, 0, 1 );
+ ssLayout->addWidget( new QLabel( i18n( "End column:" ), tab ), 1, 0 );
+ m_pEndColumnEdit = new PMFloatEdit( tab );
+ m_pEndColumnEdit->setValidation( true, 0.0, false, 0.0 );
+ ssLayout->addWidget( m_pEndColumnEdit, 1, 1 );
+ ssLayout->addWidget( new QLabel( i18n( "Start row:" ), tab ), 2, 0 );
+ m_pStartRowEdit = new PMFloatEdit( tab );
+ m_pStartRowEdit->setValidation( true, 0.0, false, 0.0 );
+ ssLayout->addWidget( m_pStartRowEdit, 2, 1 );
+ ssLayout->addWidget( new QLabel( i18n( "End row:" ), tab ), 3, 0 );
+ m_pEndRowEdit = new PMFloatEdit( tab );
+ m_pEndRowEdit->setValidation( true, 0.0, false, 0.0 );
+ ssLayout->addWidget( m_pEndRowEdit, 3, 1 );
+ ssHelpLayout->addStretch( 1 );
+
+ tabLayout->addStretch( 1 );
+
+ // quality tab
+ tab = new QWidget( );
+ m_pTabWidget->addTab( tab, i18n( "Quality" ) );
+ tabLayout = new QVBoxLayout( tab, marginHint( ), spacingHint( ) );
+
+ QHBoxLayout* quHelpLayout = new QHBoxLayout( tabLayout );
+ quHelpLayout->addWidget( new QLabel( i18n( "Quality:" ), tab ) );
+ m_pQualityCombo = new QComboBox( tab );
+ quHelpLayout->addWidget( m_pQualityCombo );
+ for( i = 0; i < numQuality; i++ )
+ m_pQualityCombo->insertItem( i18n( qualityString[i] ) );
+
+ m_pAntialiasingBox = new QCheckBox( i18n( "Antialiasing" ), tab );
+ tabLayout->addWidget( m_pAntialiasingBox );
+
+ QHBoxLayout* aaHelpLayout = new QHBoxLayout( tabLayout );
+ QGridLayout* aaGridLayout = new QGridLayout( aaHelpLayout, 5, 2 );
+ aaGridLayout->addWidget( new QLabel( i18n( "Method:" ), tab ), 0, 0 );
+ m_pSamplingCombo = new QComboBox( tab );
+ aaGridLayout->addWidget( m_pSamplingCombo, 0, 1 );
+ m_pSamplingCombo->insertItem( i18n( "Non Recursive" ) );
+ m_pSamplingCombo->insertItem( i18n( "Recursive" ) );
+
+ aaGridLayout->addWidget( new QLabel( i18n( "Threshold:" ), tab ), 1, 0 );
+ m_pThresholdEdit = new PMFloatEdit( tab );
+ aaGridLayout->addWidget( m_pThresholdEdit, 1, 1 );
+
+ aaGridLayout->addWidget( new QLabel( i18n( "Depth:" ), tab ), 2, 0 );
+ m_pAntialiasDepthEdit = new PMIntEdit( tab );
+ m_pAntialiasDepthEdit->setValidation( true, 1, true, 9 );
+ aaGridLayout->addWidget( m_pAntialiasDepthEdit, 2, 1 );
+
+ m_pJitterBox = new QCheckBox( i18n( "Jitter" ), tab );
+ aaGridLayout->addMultiCellWidget( m_pJitterBox, 3, 3, 0, 1 );
+
+ aaGridLayout->addWidget( new QLabel( i18n( "Amount:" ), tab ), 4, 0 );
+ m_pJitterAmountEdit = new PMFloatEdit( tab );
+ aaGridLayout->addWidget( m_pJitterAmountEdit, 4, 1 );
+
+ aaHelpLayout->addStretch( 1 );
+
+ m_pRadiosityBox = new QCheckBox( i18n( "Radiosity" ), tab );
+ tabLayout->addWidget( m_pRadiosityBox );
+
+ tabLayout->addStretch( 1 );
+
+ // output options tab
+ tab = new QWidget( );
+ m_pTabWidget->addTab( tab, i18n( "Output" ) );
+ tabLayout = new QVBoxLayout( tab, marginHint( ), spacingHint( ) );
+
+ m_pAlphaBox = new QCheckBox( i18n( "Alpha" ), tab );
+ tabLayout->addWidget( m_pAlphaBox );
+
+ tabLayout->addStretch( 1 );
+
+
+ resize( s_size );
+
+ // display the mode BEFORE the signals are connected!!!
+ displayMode( );
+
+ enableButtonOK( false );
+
+ // connect signals
+ connect( m_pDescriptionEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotTextChanged( const QString& ) ) );
+ connect( m_pHeightEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pWidthEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pSubsectionBox, SIGNAL( toggled( bool ) ), SLOT( slotSubsectionToggled( bool ) ) );
+ connect( m_pStartRowEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pEndRowEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pStartColumnEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pEndColumnEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pQualityCombo, SIGNAL( activated( int ) ), SLOT( slotActivated( int ) ) );
+ connect( m_pRadiosityBox, SIGNAL( clicked( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pAntialiasingBox, SIGNAL( toggled( bool ) ), SLOT( slotAntialiasingToggled( bool ) ) );
+ connect( m_pSamplingCombo, SIGNAL( activated( int ) ), SLOT( slotActivated( int ) ) );
+ connect( m_pThresholdEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pJitterBox, SIGNAL( toggled( bool ) ), SLOT( slotJitterToggled( bool ) ) );
+ connect( m_pJitterAmountEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pAntialiasDepthEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+ connect( m_pAlphaBox, SIGNAL( toggled( bool ) ), SLOT( slotToggled( bool ) ) );
+}
+
+void PMRenderModeDialog::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+ cfg->writeEntry( "RenderModeDialogSize", s_size );
+}
+
+void PMRenderModeDialog::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+
+ QSize defaultSize( 400, 400 );
+ s_size = cfg->readSizeEntry( "RenderModeDialogSize", &defaultSize );
+}
+
+void PMRenderModeDialog::resizeEvent( QResizeEvent* ev )
+{
+ s_size = ev->size( );
+}
+
+bool PMRenderModeDialog::saveChanges( )
+{
+ if( validate( ) )
+ {
+ m_pMode->setDescription( m_pDescriptionEdit->text( ) );
+ m_pMode->setWidth( m_pWidthEdit->value( ) );
+ m_pMode->setHeight( m_pHeightEdit->value( ) );
+ m_pMode->setSubSection( m_pSubsectionBox->isChecked( ) );
+ if( m_pSubsectionBox->isChecked( ) )
+ {
+ m_pMode->setStartRow( m_pStartRowEdit->value( ) );
+ m_pMode->setEndRow( m_pEndRowEdit->value( ) );
+ m_pMode->setStartColumn( m_pStartColumnEdit->value( ) );
+ m_pMode->setEndColumn( m_pEndColumnEdit->value( ) );
+ }
+ m_pMode->setQuality( indexToQuality( m_pQualityCombo->currentItem( ) ) );
+ m_pMode->setRadiosity( m_pRadiosityBox->isChecked( ) );
+ m_pMode->setAntialiasing( m_pAntialiasingBox->isChecked( ) );
+ if( m_pAntialiasingBox->isChecked( ) )
+ {
+ m_pMode->setSamplingMethod( m_pSamplingCombo->currentItem( ) );
+ m_pMode->setAntialiasingThreshold( m_pThresholdEdit->value( ) );
+ m_pMode->setAntialiasingJitter( m_pJitterBox->isChecked( ) );
+ if( m_pJitterBox->isChecked( ) )
+ m_pMode->setAntialiasingJitterAmount( m_pJitterAmountEdit->value( ) );
+ m_pMode->setAntialiasingDepth( m_pAntialiasDepthEdit->value( ) );
+ }
+ m_pMode->setAlpha( m_pAlphaBox->isChecked( ) );
+ return true;
+ }
+ return false;
+}
+
+bool PMRenderModeDialog::validate( )
+{
+ if( m_pDescriptionEdit->text( ).isEmpty( ) )
+ {
+ KMessageBox::error( this, i18n( "Please enter a description for the "
+ "render mode." ), i18n( "Error" ) );
+ m_pDescriptionEdit->selectAll( );
+ return false;
+ }
+
+ // tab 0
+ bool error = true;
+
+ if( m_pHeightEdit->isDataValid( ) )
+ if( m_pWidthEdit->isDataValid( ) )
+ error = false;
+ if( !error && m_pSubsectionBox->isChecked( ) )
+ {
+ error = true;
+ if( m_pStartColumnEdit->isDataValid( ) )
+ if( m_pEndColumnEdit->isDataValid( ) )
+ if( m_pStartRowEdit->isDataValid( ) )
+ if( m_pEndRowEdit->isDataValid( ) )
+ error = false;
+ }
+
+ if( error )
+ {
+ m_pTabWidget->setCurrentPage( 0 );
+ return false;
+ }
+
+ // tab 1
+ if( m_pAntialiasingBox->isChecked( ) )
+ {
+ error = false;
+ if( m_pThresholdEdit->isDataValid( ) )
+ if( m_pAntialiasDepthEdit->isDataValid( ) )
+ error = false;
+
+ if( m_pJitterBox->isChecked( ) && !error )
+ error = !m_pJitterAmountEdit->isDataValid( );
+
+ if( error )
+ {
+ m_pTabWidget->setCurrentPage( 1 );
+ return false;
+ }
+ }
+
+ // tab 2
+
+ return true;
+}
+
+void PMRenderModeDialog::displayMode( )
+{
+ m_pDescriptionEdit->setText( m_pMode->description( ) );
+ m_pHeightEdit->setValue( m_pMode->height( ) );
+ m_pWidthEdit->setValue( m_pMode->width( ) );
+ m_pSubsectionBox->setChecked( m_pMode->subSection( ) );
+ enableSubsection( m_pMode->subSection( ) );
+ m_pStartRowEdit->setValue( m_pMode->startRow( ) );
+ m_pEndRowEdit->setValue( m_pMode->endRow( ) );
+ m_pStartColumnEdit->setValue( m_pMode->startColumn( ) );
+ m_pEndColumnEdit->setValue( m_pMode->endColumn( ) );
+ m_pQualityCombo->setCurrentItem( qualityToIndex( m_pMode->quality( ) ) );
+ m_pRadiosityBox->setChecked( m_pMode->radiosity( ) );
+ m_pAntialiasingBox->setChecked( m_pMode->antialiasing( ) );
+ enableAntialiasing( m_pMode->antialiasing( ) );
+ m_pSamplingCombo->setCurrentItem( m_pMode->samplingMethod( ) );
+ m_pThresholdEdit->setValue( m_pMode->antialiasingThreshold( ) );
+ m_pJitterBox->setChecked( m_pMode->antialiasingJitter( ) );
+ enableJitter( m_pMode->antialiasingJitter( ) && m_pMode->antialiasing( ) );
+ m_pJitterAmountEdit->setValue( m_pMode->antialiasingJitterAmount( ) );
+ m_pAntialiasDepthEdit->setValue( m_pMode->antialiasingDepth( ) );
+ m_pAlphaBox->setChecked( m_pMode->alpha( ) );
+}
+
+void PMRenderModeDialog::enableSubsection( bool yes )
+{
+ m_pStartRowEdit->setEnabled( yes );
+ m_pEndRowEdit->setEnabled( yes );
+ m_pStartColumnEdit->setEnabled( yes );
+ m_pEndColumnEdit->setEnabled( yes );
+}
+
+void PMRenderModeDialog::enableAntialiasing( bool yes )
+{
+ m_pSamplingCombo->setEnabled( yes );
+ m_pThresholdEdit->setEnabled( yes );
+ m_pAntialiasDepthEdit->setEnabled( yes );
+ m_pJitterBox->setEnabled( yes );
+ enableJitter( m_pJitterBox->isChecked( ) );
+}
+
+void PMRenderModeDialog::enableJitter( bool yes )
+{
+ m_pJitterAmountEdit->setEnabled( yes );
+}
+
+int PMRenderModeDialog::qualityToIndex( int quality )
+{
+ if( quality < 0 )
+ quality = 0;
+ if( quality > 11 )
+ quality = 11;
+
+ return c_qualityToIndex[quality];
+}
+
+int PMRenderModeDialog::indexToQuality( int index )
+{
+ if( index < 0 )
+ index = 0;
+ if( index >= numQuality )
+ index = numQuality - 1;
+
+ return c_indexToQuality[index];
+}
+
+void PMRenderModeDialog::slotOk( )
+{
+ if( saveChanges( ) )
+ accept( );
+}
+
+void PMRenderModeDialog::slotChanged( )
+{
+ enableButtonOK( true );
+}
+
+void PMRenderModeDialog::slotTextChanged( const QString& )
+{
+ slotChanged( );
+}
+
+void PMRenderModeDialog::slotActivated( int )
+{
+ slotChanged( );
+}
+
+void PMRenderModeDialog::slotSubsectionToggled( bool on )
+{
+ slotChanged( );
+ enableSubsection( on );
+}
+
+void PMRenderModeDialog::slotAntialiasingToggled( bool on )
+{
+ slotChanged( );
+ enableAntialiasing( on );
+}
+
+void PMRenderModeDialog::slotJitterToggled( bool on )
+{
+ slotChanged( );
+ enableJitter( on );
+}
+
+void PMRenderModeDialog::slotToggled( bool )
+{
+ slotChanged( );
+}
+
+#include "pmrendermodesdialog.moc"
+
diff --git a/kpovmodeler/pmrendermodesdialog.h b/kpovmodeler/pmrendermodesdialog.h
new file mode 100644
index 00000000..a6b6482f
--- /dev/null
+++ b/kpovmodeler/pmrendermodesdialog.h
@@ -0,0 +1,179 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMRENDERMODESDIALOG_H
+#define PMRENDERMODESDIALOG_H
+
+#include "pmrendermode.h"
+#include <kdialogbase.h>
+
+class QCheckBox;
+class QComboBox;
+class QLineEdit;
+class QListBox;
+class QPushButton;
+class QTabWidget;
+class KConfig;
+class PMIntEdit;
+class PMFloatEdit;
+
+/**
+ * Dialog for editing a list of render modes.
+ * @see PMRenderMode
+ */
+class PMRenderModesDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a dialog for the modes list
+ */
+ PMRenderModesDialog( PMRenderModeList* modes, QWidget* parent = 0, const char* name = 0 );
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+
+protected slots:
+ /**
+ * Called when a mode is selected in the list view
+ */
+ void slotModeSelected( int index );
+
+ /**
+ * Called when the add button is klicked
+ */
+ void slotAdd( );
+ /**
+ * Called when the remove button is klicked
+ */
+ void slotRemove( );
+ /**
+ * Called when the up button is klicked
+ */
+ void slotUp( );
+ /**
+ * Called when the down button is klicked
+ */
+ void slotDown( );
+ /**
+ * Called when the edit button is klicked
+ */
+ void slotEdit( );
+ /**
+ * Called when the modes are changed
+ */
+ void slotChanged( );
+ virtual void slotOk( );
+
+protected:
+ virtual void resizeEvent( QResizeEvent* ev );
+
+private:
+ void displayList( );
+ void checkButtons( );
+
+ PMRenderModeList* m_pOriginalModes;
+ PMRenderModeList m_workingModes;
+ int m_selectionIndex;
+
+ QListBox* m_pListBox;
+ QPushButton* m_pAddButton;
+ QPushButton* m_pRemoveButton;
+ QPushButton* m_pUpButton;
+ QPushButton* m_pDownButton;
+ QPushButton* m_pEditButton;
+ static QSize s_size;
+};
+
+/**
+ * Dialog for editing one render mode
+ * @see PMRenderMode
+ */
+class PMRenderModeDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a dialog for the mode
+ */
+ PMRenderModeDialog( PMRenderMode* mode, QWidget* parent = 0, const char* name = 0 );
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+
+protected:
+ virtual void resizeEvent( QResizeEvent* ev );
+
+
+protected slots:
+ virtual void slotOk( );
+ void slotChanged( );
+ void slotTextChanged( const QString& );
+ void slotActivated( int );
+ void slotSubsectionToggled( bool );
+ void slotAntialiasingToggled( bool );
+ void slotJitterToggled( bool );
+ void slotToggled( bool );
+
+private:
+ /**
+ * Saves the current changes. Returns true if successful.
+ */
+ bool saveChanges( );
+ /**
+ * Returns true if the data is valid
+ */
+ bool validate( );
+ /**
+ * Displays the selected mode
+ */
+ void displayMode( );
+
+ void enableSubsection( bool yes );
+ void enableAntialiasing( bool yes );
+ void enableJitter( bool yes );
+ int qualityToIndex( int quality );
+ int indexToQuality( int index );
+
+ PMRenderMode* m_pMode;
+
+ QTabWidget* m_pTabWidget;
+ QLineEdit* m_pDescriptionEdit;
+ PMIntEdit* m_pHeightEdit;
+ PMIntEdit* m_pWidthEdit;
+ QCheckBox* m_pSubsectionBox;
+ PMFloatEdit* m_pStartRowEdit;
+ PMFloatEdit* m_pEndRowEdit;
+ PMFloatEdit* m_pStartColumnEdit;
+ PMFloatEdit* m_pEndColumnEdit;
+ // quality
+ QComboBox* m_pQualityCombo;
+ QCheckBox* m_pRadiosityBox;
+ QCheckBox* m_pAntialiasingBox;
+ QComboBox* m_pSamplingCombo;
+ PMFloatEdit* m_pThresholdEdit;
+ QCheckBox* m_pJitterBox;
+ PMFloatEdit* m_pJitterAmountEdit;
+ PMIntEdit* m_pAntialiasDepthEdit;
+ // output
+ QCheckBox* m_pAlphaBox;
+
+ static QSize s_size;
+};
+
+#endif
diff --git a/kpovmodeler/pmresourcelocator.cpp b/kpovmodeler/pmresourcelocator.cpp
new file mode 100644
index 00000000..7c778b31
--- /dev/null
+++ b/kpovmodeler/pmresourcelocator.cpp
@@ -0,0 +1,103 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmresourcelocator.h"
+#include "pmpovrayrenderwidget.h"
+#include "pmdebug.h"
+
+#include <qfileinfo.h>
+#include <qdir.h>
+
+PMResourceLocator* PMResourceLocator::s_pInstance = 0;
+KStaticDeleter<PMResourceLocator> PMResourceLocator::s_staticDeleter;
+
+PMResourceLocator::PMResourceLocator( )
+ : m_cache( 100, 109, true )
+{
+ m_cache.setAutoDelete( true );
+}
+
+PMResourceLocator::~PMResourceLocator( )
+{
+ m_cache.clear( );
+}
+
+QString PMResourceLocator::findFile( const QString& file )
+{
+ if( !s_pInstance )
+ s_staticDeleter.setObject( s_pInstance, new PMResourceLocator( ) );
+ return s_pInstance->lookUp( file );
+}
+
+void PMResourceLocator::clearCache( )
+{
+ if( s_pInstance )
+ s_pInstance->m_cache.clear( );
+}
+
+QString PMResourceLocator::lookUp( const QString& file )
+{
+ if( file.isEmpty( ) )
+ return QString::null;
+
+ kdDebug( PMArea ) << "LookUp: " << file << endl;
+
+ QString* ps = m_cache.find( file );
+ if( ps )
+ return *ps;
+
+ bool found = false;
+ QString fullPath = QString::null;
+
+ if( file[0] == '/' )
+ {
+ // absolute path, library paths are not used
+ QFileInfo info( file );
+ if( info.exists( ) && info.isReadable( ) && info.isFile( ) )
+ {
+ found = true;
+ fullPath = file;
+ }
+ }
+ else
+ {
+ QStringList plist = PMPovrayRenderWidget::povrayLibraryPaths( );
+ QStringList::ConstIterator it = plist.begin( );
+ for( ; ( it != plist.end( ) ) && !found; ++it )
+ {
+ QDir dir( *it );
+ QFileInfo info( dir, file );
+ if( info.exists( ) && info.isReadable( ) && info.isFile( ) )
+ {
+ found = true;
+ fullPath = info.absFilePath( );
+ }
+ }
+ }
+
+ if( found )
+ {
+ QString* ni = new QString( fullPath );
+ if( !m_cache.insert( file, ni ) )
+ delete ni;
+ kdDebug( PMArea ) << "File \"" << file << "\" found in "
+ << fullPath << endl;
+ }
+
+ return fullPath;
+}
+
diff --git a/kpovmodeler/pmresourcelocator.h b/kpovmodeler/pmresourcelocator.h
new file mode 100644
index 00000000..02e725cb
--- /dev/null
+++ b/kpovmodeler/pmresourcelocator.h
@@ -0,0 +1,65 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMRESOURCELOCATOR_H
+#define PMRESOURCELOCATOR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qcache.h>
+#include <kstaticdeleter.h>
+
+/**
+ * Class to find files in the povray library paths
+ */
+class PMResourceLocator
+{
+public:
+ /**
+ * Destructor
+ */
+ ~PMResourceLocator( );
+ /**
+ * Returns the full path for the file or a null string if the file
+ * was not found. The file can be a relative or absolute path.
+ */
+ static QString findFile( const QString& file );
+ /**
+ * Clears the resource cache. Call this if the library paths are changed
+ */
+ static void clearCache( );
+
+private:
+ /**
+ * Constructor
+ */
+ PMResourceLocator( );
+ /**
+ * File lookup function
+ */
+ QString lookUp( const QString& file );
+ static PMResourceLocator* s_pInstance;
+ static KStaticDeleter<PMResourceLocator> s_staticDeleter;
+
+ QCache<QString> m_cache;
+};
+
+#endif
diff --git a/kpovmodeler/pmrotate.cpp b/kpovmodeler/pmrotate.cpp
new file mode 100644
index 00000000..f3e34040
--- /dev/null
+++ b/kpovmodeler/pmrotate.cpp
@@ -0,0 +1,164 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmrotate.h"
+#include "pmrotateedit.h"
+
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmrotatecontrolpoint.h"
+
+#include <klocale.h>
+#include <qdom.h>
+
+const PMVector rotateDefault = PMVector( 0, 0, 0 );
+
+PMDefinePropertyClass( PMRotate, PMRotateProperty );
+
+PMMetaObject* PMRotate::s_pMetaObject = 0;
+PMObject* createNewRotate( PMPart* part )
+{
+ return new PMRotate( part );
+}
+
+PMRotate::PMRotate( PMPart* part )
+ : Base( part )
+{
+}
+
+PMRotate::PMRotate( const PMRotate& r )
+ : Base( r )
+{
+ m_rotate = r.m_rotate;
+}
+
+PMRotate::~PMRotate( )
+{
+}
+
+QString PMRotate::description( ) const
+{
+ return i18n( "rotate" );
+}
+
+void PMRotate::serialize( QDomElement& e, QDomDocument& /*doc*/ ) const
+{
+ e.setAttribute( "value", m_rotate.serializeXML( ) );
+}
+
+void PMRotate::readAttributes( const PMXMLHelper& h )
+{
+ m_rotate = h.vectorAttribute( "value", rotateDefault );
+}
+
+PMMetaObject* PMRotate::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Rotate", Base::metaObject( ),
+ createNewRotate );
+ s_pMetaObject->addProperty(
+ new PMRotateProperty( "rotation", &PMRotate::setRotation, &PMRotate::rotation ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMRotate::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMRotate::setRotation( const PMVector& p )
+{
+ if( p != m_rotate )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMRotationID, m_rotate );
+ m_pMemento->setViewStructureChanged( );
+ }
+ m_rotate = p;
+ m_rotate.resize( 3 );
+ }
+}
+
+PMDialogEditBase* PMRotate::editWidget( QWidget* parent ) const
+{
+ return new PMRotateEdit( parent );
+}
+
+void PMRotate::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMRotationID:
+ setRotation( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMRotate::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+PMMatrix PMRotate::transformationMatrix( ) const
+{
+ return PMMatrix::rotation( deg2Rad( m_rotate[0] ), deg2Rad( m_rotate[1] ),
+ deg2Rad( m_rotate[2] ) );
+}
+
+void PMRotate::controlPoints( PMControlPointList& list )
+{
+ list.append( new PMRotateControlPoint( m_rotate, PMRotationID ) );
+}
+
+void PMRotate::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMRotationID:
+ setRotation( ( ( PMRotateControlPoint* ) p )->rotation( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMRotate::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+}
diff --git a/kpovmodeler/pmrotate.h b/kpovmodeler/pmrotate.h
new file mode 100644
index 00000000..0a8a1dbb
--- /dev/null
+++ b/kpovmodeler/pmrotate.h
@@ -0,0 +1,102 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMROTATE_H
+#define PMROTATE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+#include "pmvector.h"
+
+/**
+ * Class for povray rotate commands.
+ */
+
+class PMRotate : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates a rotate < 0, 0, 0 >
+ */
+ PMRotate( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMRotate( const PMRotate& r );
+ /**
+ * deletes the object
+ */
+ virtual ~PMRotate( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMRotate( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMRotateEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmrotate" ); }
+
+ /**
+ * Returns the rotation
+ */
+ PMVector rotation( ) const { return m_rotate; }
+ /**
+ * Sets the rotation
+ */
+ void setRotation( const PMVector& p );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual bool hasTransformationMatrix( ) const { return true; }
+ /** */
+ virtual PMMatrix transformationMatrix( ) const;
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMRotateMementoID { PMRotationID };
+ PMVector m_rotate;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmrotatecontrolpoint.cpp b/kpovmodeler/pmrotatecontrolpoint.cpp
new file mode 100644
index 00000000..b612b4c9
--- /dev/null
+++ b/kpovmodeler/pmrotatecontrolpoint.cpp
@@ -0,0 +1,78 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmrotatecontrolpoint.h"
+#include "pmmath.h"
+#include "pmdebug.h"
+
+#include <klocale.h>
+#include <math.h>
+
+const double precision = 0.1;
+
+PMRotateControlPoint::PMRotateControlPoint( const PMVector& rot, int id )
+ : PMControlPoint( id, i18n( "Rotation" ) )
+{
+ m_rotation = rot;
+}
+
+void PMRotateControlPoint::graphicalChangeStarted( )
+{
+ m_originalRotation = m_rotation;
+ m_originalTransformation =
+ PMMatrix::rotation( deg2Rad( m_rotation.x( ) ),
+ deg2Rad( m_rotation.y( ) ),
+ deg2Rad( m_rotation.z( ) ) );
+}
+
+void PMRotateControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint )
+{
+ double a, x, y, z;
+
+ a = PMVector::angle( startPoint, endPoint );
+ if( !approxZero( a ) )
+ {
+ PMMatrix m;
+
+ if( !approx( a, M_PI ) )
+ {
+ PMVector n = PMVector::cross( startPoint, endPoint );
+ m = PMMatrix::rotation( n, a )
+ * m_originalTransformation;
+ }
+ else
+ m = PMMatrix::rotation( viewNormal, M_PI )
+ * m_originalTransformation;
+
+ m.toRotation( &x, &y, &z );
+ m_rotation[0] = rint( rad2Deg( x ) / precision ) * precision;
+ m_rotation[1] = rint( rad2Deg( y ) / precision ) * precision;
+ m_rotation[2] = rint( rad2Deg( z ) / precision ) * precision;
+ }
+}
+
+void PMRotateControlPoint::snapToGrid( )
+{
+ int i;
+ double d = rotateGrid( );
+ if( !approxZero( d ) )
+ for( i = 0; i < 3; i++ )
+ m_rotation[i] = rint( m_rotation[i] / d ) * d;
+ setChanged( );
+}
diff --git a/kpovmodeler/pmrotatecontrolpoint.h b/kpovmodeler/pmrotatecontrolpoint.h
new file mode 100644
index 00000000..1918eec4
--- /dev/null
+++ b/kpovmodeler/pmrotatecontrolpoint.h
@@ -0,0 +1,73 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMROTATECONTROLPOINT_H
+#define PMROTATECONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "pmcontrolpoint.h"
+#include "pmmatrix.h"
+
+/**
+ * Control points for rotation
+ */
+class PMRotateControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Creates a PMRotateControlPoint with id.
+ */
+ PMRotateControlPoint( const PMVector& rotation, int id );
+ /**
+ * Deletes the PMRotateControlPoint
+ */
+ virtual ~PMRotateControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const { return PMVector( 0.0, 0.0, 0.0 ); }
+
+ /**
+ * Sets the rotation
+ */
+ void setRotation( const PMVector& rot ) { m_rotation = rot; }
+ /**
+ * Returns the rotation
+ */
+ PMVector rotation( ) const { return m_rotation; }
+
+ /** */
+ virtual PMCPDisplayType displayType( ) const { return CPCross; };
+ /** */
+ virtual void snapToGrid( );
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ PMVector m_rotation, m_originalRotation;
+ PMMatrix m_originalTransformation;
+};
+
+#endif
diff --git a/kpovmodeler/pmrotateedit.cpp b/kpovmodeler/pmrotateedit.cpp
new file mode 100644
index 00000000..df2c2340
--- /dev/null
+++ b/kpovmodeler/pmrotateedit.cpp
@@ -0,0 +1,74 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmrotateedit.h"
+#include "pmrotate.h"
+#include "pmvectoredit.h"
+
+#include <qlayout.h>
+#include <klocale.h>
+
+
+PMRotateEdit::PMRotateEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMRotateEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pVector = new PMVectorEdit( "x", "y", "z", this );
+ topLayout( )->addWidget( m_pVector );
+
+ connect( m_pVector, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMRotateEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Rotate" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMRotate* ) o;
+
+ m_pVector->setVector( m_pDisplayedObject->rotation( ) );
+ m_pVector->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMRotateEdit: Can't display object\n";
+}
+
+void PMRotateEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setRotation( m_pVector->vector( ) );
+ }
+}
+
+bool PMRotateEdit::isDataValid( )
+{
+ if( m_pVector->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+#include "pmrotateedit.moc"
diff --git a/kpovmodeler/pmrotateedit.h b/kpovmodeler/pmrotateedit.h
new file mode 100644
index 00000000..89ca56fd
--- /dev/null
+++ b/kpovmodeler/pmrotateedit.h
@@ -0,0 +1,62 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMROTATEEDIT_H
+#define PMROTATEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMRotate;
+class PMVectorEdit;
+
+/**
+ * Dialog edit class for @ref PMRotate
+ */
+class PMRotateEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMRotateEdit with parent and name
+ */
+ PMRotateEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMRotate* m_pDisplayedObject;
+ PMVectorEdit* m_pVector;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmscale.cpp b/kpovmodeler/pmscale.cpp
new file mode 100644
index 00000000..2be064c2
--- /dev/null
+++ b/kpovmodeler/pmscale.cpp
@@ -0,0 +1,163 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmscale.h"
+#include "pmscaleedit.h"
+#include "pmscalecontrolpoint.h"
+
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+const PMVector scaleDefault = PMVector( 0, 0, 0 );
+
+PMDefinePropertyClass( PMScale, PMScaleProperty );
+
+PMMetaObject* PMScale::s_pMetaObject = 0;
+PMObject* createNewScale( PMPart* part )
+{
+ return new PMScale( part );
+}
+
+PMScale::PMScale( PMPart* part )
+ : Base( part )
+{
+ m_scale = PMVector( 1.0, 1.0, 1.0 );
+}
+
+PMScale::PMScale( const PMScale& s )
+ : Base( s )
+{
+ m_scale = s.m_scale;
+}
+
+PMScale::~PMScale( )
+{
+}
+
+QString PMScale::description( ) const
+{
+ return i18n( "scale" );
+}
+
+void PMScale::serialize( QDomElement& e, QDomDocument& /*d*/ ) const
+{
+ e.setAttribute( "value", m_scale.serializeXML( ) );
+}
+
+void PMScale::readAttributes( const PMXMLHelper& h )
+{
+ m_scale = h.vectorAttribute( "value", scaleDefault );
+}
+
+PMMetaObject* PMScale::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Scale", Base::metaObject( ),
+ createNewScale );
+ s_pMetaObject->addProperty(
+ new PMScaleProperty( "scale", &PMScale::setScale, &PMScale::scale ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMScale::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMScale::setScale( const PMVector& p )
+{
+ if( p != m_scale )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMScaleID, m_scale );
+ m_pMemento->setViewStructureChanged( );
+ }
+ m_scale = p;
+ m_scale.resize( 3 );
+ }
+}
+
+PMDialogEditBase* PMScale::editWidget( QWidget* parent ) const
+{
+ return new PMScaleEdit( parent );
+}
+
+void PMScale::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMScaleID:
+ setScale( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMScale::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+PMMatrix PMScale::transformationMatrix( ) const
+{
+ return PMMatrix::scale( m_scale[0], m_scale[1], m_scale[2] );
+}
+
+void PMScale::controlPoints( PMControlPointList& list )
+{
+ list.append( new PMScaleControlPoint( m_scale, PMScaleID ) );
+}
+
+void PMScale::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMScaleID:
+ setScale( ( ( PMScaleControlPoint* ) p )->scale( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMScale::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+}
diff --git a/kpovmodeler/pmscale.h b/kpovmodeler/pmscale.h
new file mode 100644
index 00000000..bc1a391d
--- /dev/null
+++ b/kpovmodeler/pmscale.h
@@ -0,0 +1,103 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSCALE_H
+#define PMSCALE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+#include "pmvector.h"
+
+
+/**
+ * Class for povray scale commands.
+ */
+
+class PMScale : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates a scale < 0, 0, 0 >
+ */
+ PMScale( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMScale( const PMScale& s );
+ /**
+ * deletes the object
+ */
+ virtual ~PMScale( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMScale( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMScaleEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmscale" ); }
+
+ /**
+ * Returns the scale
+ */
+ PMVector scale( ) const { return m_scale; }
+ /**
+ * Sets the scale
+ */
+ void setScale( const PMVector& p );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual bool hasTransformationMatrix( ) const { return true; }
+ /** */
+ virtual PMMatrix transformationMatrix( ) const;
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMScaleMementoID { PMScaleID };
+ PMVector m_scale;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmscalecontrolpoint.cpp b/kpovmodeler/pmscalecontrolpoint.cpp
new file mode 100644
index 00000000..c6def808
--- /dev/null
+++ b/kpovmodeler/pmscalecontrolpoint.cpp
@@ -0,0 +1,58 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmscalecontrolpoint.h"
+#include "pmmath.h"
+#include "pmdebug.h"
+
+#include <klocale.h>
+#include <math.h>
+
+const double precision = 0.001;
+
+PMScaleControlPoint::PMScaleControlPoint( const PMVector& scale, int id )
+ : PMControlPoint( id, i18n( "Scale" ) )
+{
+ m_scale = scale;
+}
+
+void PMScaleControlPoint::graphicalChangeStarted( )
+{
+ m_originalScale = m_scale;
+}
+
+void PMScaleControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& /*viewNormal*/,
+ const PMVector& endPoint )
+{
+ int i;
+
+ for( i = 0; i < 3; i++ )
+ if( !approxZero( startPoint[i] ) )
+ m_scale[i] = rint( m_originalScale[i] * endPoint[i] / startPoint[i]
+ / precision ) * precision;
+}
+
+void PMScaleControlPoint::snapToGrid( )
+{
+ int i;
+ double d = scaleGrid( );
+ if( !approxZero( d ) )
+ for( i = 0; i < 3; i++ )
+ m_scale[i] = rint( m_scale[i] / d ) * d;
+ setChanged( );
+}
diff --git a/kpovmodeler/pmscalecontrolpoint.h b/kpovmodeler/pmscalecontrolpoint.h
new file mode 100644
index 00000000..5cb4a091
--- /dev/null
+++ b/kpovmodeler/pmscalecontrolpoint.h
@@ -0,0 +1,71 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMSCALECONTROLPOINT_H
+#define PMSCALECONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "pmcontrolpoint.h"
+
+/**
+ * Control points for scale
+ */
+class PMScaleControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Creates a PMScaleControlPoint with id.
+ */
+ PMScaleControlPoint( const PMVector& scale, int id );
+ /**
+ * Deletes the PMScaleControlPoint
+ */
+ virtual ~PMScaleControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const { return PMVector( 0.0, 0.0, 0.0 ); }
+
+ /**
+ * Sets the scale
+ */
+ void setScale( const PMVector& sc ) { m_scale = sc; }
+ /**
+ * Returns the scale
+ */
+ PMVector scale( ) const { return m_scale; }
+
+ /** */
+ virtual PMCPDisplayType displayType( ) const { return CPCross; };
+ /** */
+ virtual void snapToGrid( );
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ PMVector m_scale, m_originalScale;
+};
+
+#endif
diff --git a/kpovmodeler/pmscaleedit.cpp b/kpovmodeler/pmscaleedit.cpp
new file mode 100644
index 00000000..1df7b40f
--- /dev/null
+++ b/kpovmodeler/pmscaleedit.cpp
@@ -0,0 +1,74 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmscaleedit.h"
+#include "pmscale.h"
+#include "pmvectoredit.h"
+
+#include <qlayout.h>
+#include <klocale.h>
+
+
+PMScaleEdit::PMScaleEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMScaleEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pVector = new PMVectorEdit( "x", "y", "z", this );
+ topLayout( )->addWidget( m_pVector );
+
+ connect( m_pVector, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMScaleEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Scale" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMScale* ) o;
+
+ m_pVector->setVector( m_pDisplayedObject->scale( ) );
+ m_pVector->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMScaleEdit: Can't display object\n";
+}
+
+void PMScaleEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setScale( m_pVector->vector( ) );
+ }
+}
+
+bool PMScaleEdit::isDataValid( )
+{
+ if( m_pVector->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+#include "pmscaleedit.moc"
diff --git a/kpovmodeler/pmscaleedit.h b/kpovmodeler/pmscaleedit.h
new file mode 100644
index 00000000..f18989f5
--- /dev/null
+++ b/kpovmodeler/pmscaleedit.h
@@ -0,0 +1,62 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSCALEEDIT_H
+#define PMSCALEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMScale;
+class PMVectorEdit;
+
+/**
+ * Dialog edit class for @ref PMScale
+ */
+class PMScaleEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMScaleEdit with parent and name
+ */
+ PMScaleEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMScale* m_pDisplayedObject;
+ PMVectorEdit* m_pVector;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmscanner.cpp b/kpovmodeler/pmscanner.cpp
new file mode 100644
index 00000000..f67b7035
--- /dev/null
+++ b/kpovmodeler/pmscanner.cpp
@@ -0,0 +1,1353 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <klocale.h>
+
+#include "pmdebug.h"
+#include "pmscanner.h"
+#include "pmtokens.h"
+
+
+//#define PMSCAN_DEBUG
+
+PMReservedWordDict::PMReservedWordDict( PMDictMode mode )
+ : QAsciiDict<int>( 353 )
+{
+ switch( mode )
+ {
+ case PMDReservedWords:
+ insert( "aa_level", new int( AA_LEVEL_TOK ) );
+ insert( "aa_threshold", new int( AA_THRESHOLD_TOK ) );
+ insert( "abs", new int( ABS_TOK ) );
+ insert( "absorption", new int( ABSORPTION_TOK ) );
+ insert( "accuracy", new int( ACCURACY_TOK ) );
+ insert( "acos", new int( ACOS_TOK ) );
+ insert( "acosh", new int( ACOSH_TOK ) );
+ insert( "adaptive", new int( ADAPTIVE_TOK ) );
+ insert( "adc_bailout", new int( ADC_BAILOUT_TOK ) );
+ insert( "agate", new int( AGATE_TOK ) );
+ insert( "agate_turb", new int( AGATE_TURB_TOK ) );
+ insert( "all", new int( ALL_TOK ) );
+ insert( "all_intersections", new int( ALL_INTERSECTIONS_TOK ) );
+ insert( "alpha", new int( ALPHA_TOK ) );
+ insert( "altitude", new int( ALTITUDE_TOK ) );
+ insert( "always_sample", new int ( ALWAYS_SAMPLE_TOK ) );
+ insert( "ambient", new int( AMBIENT_TOK ) );
+ insert( "ambient_light", new int( AMBIENT_LIGHT_TOK ) );
+ insert( "angle", new int( ANGLE_TOK ) );
+ insert( "aperture", new int( APERTURE_TOK ) );
+ insert( "arc_angle", new int( ARC_ANGLE_TOK ) );
+ insert( "area_light", new int( AREA_LIGHT_TOK ) );
+ insert( "autostop", new int ( AUTOSTOP_TOK ) );
+ insert( "circular", new int( AREA_CIRCULAR_TOK ) );
+ insert( "asc", new int( ASC_TOK ) );
+ insert( "asin", new int( ASIN_TOK ) );
+ insert( "asinh", new int( ASINH_TOK ) );
+ insert( "assumed_gamma", new int( ASSUMED_GAMMA_TOK ) );
+ insert( "atan", new int( ATAN_TOK ) );
+ insert( "atan2", new int( ATAN2_TOK ) );
+ insert( "atanh", new int( ATANH_TOK ) );
+ insert( "atmosphere", new int( ATMOSPHERE_TOK ) );
+ insert( "atmospheric_attenuation", new int( ATMOSPHERIC_ATTENUATION_TOK ) );
+ insert( "attenuating", new int( ATTENUATING_TOK ) );
+ insert( "average", new int( AVERAGE_TOK ) );
+ insert( "b_spline", new int( B_SPLINE_TOK ) );
+ insert( "background", new int( BACKGROUND_TOK ) );
+ insert( "bezier_spline", new int( BEZIER_SPLINE_TOK ) );
+ insert( "bicubic_patch", new int( BICUBIC_PATCH_TOK ) );
+ insert( "black_hole", new int( BLACK_HOLE_TOK ) );
+ insert( "blob", new int( BLOB_TOK ) );
+ insert( "blue", new int( BLUE_TOK ) );
+ insert( "blur_samples", new int( BLUR_SAMPLES_TOK ) );
+ insert( "bounded_by", new int( BOUNDED_BY_TOK ) );
+ insert( "box", new int( BOX_TOK ) );
+ insert( "boxed", new int( BOXED_TOK ) );
+ insert( "bozo", new int( BOZO_TOK ) );
+ insert( "brick", new int( BRICK_TOK ) );
+ insert( "brick_size", new int( BRICK_SIZE_TOK ) );
+ insert( "brightness", new int( BRIGHTNESS_TOK ) );
+ insert( "brilliance", new int( BRILLIANCE_TOK ) );
+ insert( "bumps", new int( BUMPS_TOK ) );
+ insert( "bumpy1", new int( BUMPY1_TOK ) );
+ insert( "bumpy2", new int( BUMPY2_TOK ) );
+ insert( "bumpy3", new int( BUMPY3_TOK ) );
+ insert( "bump_map", new int( BUMP_MAP_TOK ) );
+ insert( "bump_size", new int( BUMP_SIZE_TOK ) );
+ insert( "camera", new int( CAMERA_TOK ) );
+ insert( "caustics", new int( CAUSTICS_TOK ) );
+ insert( "ceil", new int( CEIL_TOK ) );
+ insert( "checker", new int( CHECKER_TOK ) );
+ insert( "chr", new int( CHR_TOK ) );
+ insert( "cells", new int( CELLS_TOK ) );
+ insert( "clipped_by", new int( CLIPPED_BY_TOK ) );
+ insert( "clock", new int( CLOCK_TOK ) );
+ insert( "clock_delta", new int( CLOCK_DELTA_TOK ) );
+ insert( "collect", new int( COLLECT_TOK ) );
+ insert( "color", new int( COLOR_TOK ) );
+ insert( "color_map", new int( COLOR_MAP_TOK ) );
+ insert( "colour", new int( COLOUR_TOK ) );
+ insert( "colour_map", new int( COLOUR_MAP_TOK ) );
+ insert( "component", new int( COMPONENT_TOK ) );
+ insert( "composite", new int( COMPOSITE_TOK ) );
+ insert( "concat", new int( CONCAT_TOK ) );
+ insert( "cone", new int( CONE_TOK ) );
+ insert( "confidence", new int( CONFIDENCE_TOK ) );
+ insert( "conic_sweep", new int( CONIC_SWEEP_TOK ) );
+ insert( "conserve_energy", new int( CONSERVE_ENERGY_TOK ) );
+ insert( "constant", new int( CONSTANT_TOK ) );
+ insert( "contained_by", new int( CONTAINED_BY_TOK ) );
+ insert( "control0", new int( CONTROL0_TOK ) );
+ insert( "control1", new int( CONTROL1_TOK ) );
+ insert( "cos", new int( COS_TOK ) );
+ insert( "cosh", new int( COSH_TOK ) );
+ insert( "count", new int( COUNT_TOK ) );
+ insert( "crackle", new int( CRACKLE_TOK ) );
+ insert( "crand", new int( CRAND_TOK ) );
+ insert( "cube", new int( CUBE_TOK ) );
+ insert( "cubic", new int( CUBIC_TOK ) );
+ insert( "cubic_spline", new int( CUBIC_SPLINE_TOK ) );
+ insert( "cubic_wave", new int( CUBIC_WAVE_TOK ) );
+ insert( "cylinder", new int( CYLINDER_TOK ) );
+ insert( "cylindrical", new int( CYLINDRICAL_TOK ) );
+ insert( "degrees", new int( DEGREES_TOK ) );
+ insert( "dents", new int( DENTS_TOK ) );
+ insert( "density", new int( DENSITY_TOK ) );
+ insert( "density_file", new int( DENSITY_FILE_TOK ) );
+ insert( "density_map", new int( DENSITY_MAP_TOK ) );
+ insert( "df3", new int( DF3_TOK ) );
+ insert( "difference", new int( DIFFERENCE_TOK ) );
+ insert( "diffuse", new int( DIFFUSE_TOK ) );
+ insert( "direction", new int( DIRECTION_TOK ) );
+ insert( "disc", new int( DISC_TOK ) );
+ insert( "dispersion", new int ( DISPERSION_TOK ) );
+ insert( "dispersion_samples", new int ( DISPERSION_SAMPLES_TOK ) );
+ insert( "dist_exp", new int ( DIST_EXP_TOK ) );
+ insert( "distance", new int( DISTANCE_TOK ) );
+ insert( "distance_maximum", new int( DISTANCE_MAXIMUM_TOK ) );
+ insert( "div", new int( DIV_TOK ) );
+ insert( "double_illuminate", new int( DOUBLE_ILLUMINATE_TOK ) );
+ insert( "dust", new int( DUST_TOK ) );
+ insert( "dust_type", new int( DUST_TYPE_TOK ) );
+ insert( "eccentricity", new int( ECCENTRICITY_TOK ) );
+ insert( "emission", new int( EMISSION_TOK ) );
+ insert( "emitting", new int( EMITTING_TOK ) );
+ insert( "error", new int( ERROR_TOK ) );
+ insert( "error_bound", new int( ERROR_BOUND_TOK ) );
+ insert( "evaluate", new int( EVALUATE_TOK ) );
+ insert( "exp", new int( EXP_TOK ) );
+ insert( "expand_thresholds", new int (EXPAND_THRESHOLDS_TOK) );
+ insert( "exponent", new int( EXPONENT_TOK ) );
+ insert( "exterior", new int( EXTERIOR_TOK ) );
+ insert( "extinction", new int( EXTINCTION_TOK ) );
+ insert( "fade_distance", new int( FADE_DISTANCE_TOK ) );
+ insert( "fade_power", new int( FADE_POWER_TOK ) );
+ insert( "falloff", new int( FALLOFF_TOK ) );
+ insert( "falloff_angle", new int( FALLOFF_ANGLE_TOK ) );
+ insert( "false", new int( FALSE_TOK ) );
+ insert( "file_exists", new int( FILE_EXISTS_TOK ) );
+ insert( "filter", new int( FILTER_TOK ) );
+ insert( "finish", new int( FINISH_TOK ) );
+ insert( "fisheye", new int( FISHEYE_TOK ) );
+ insert( "flatness", new int( FLATNESS_TOK ) );
+ insert( "flip", new int( FLIP_TOK ) );
+ insert( "floor", new int( FLOOR_TOK ) );
+ insert( "focal_point", new int( FOCAL_POINT_TOK ) );
+ insert( "fog", new int( FOG_TOK ) );
+ insert( "fog_alt", new int( FOG_ALT_TOK ) );
+ insert( "fog_offset", new int( FOG_OFFSET_TOK ) );
+ insert( "fog_type", new int( FOG_TYPE_TOK ) );
+ insert( "form", new int( FORM_TOK ) );
+ insert( "fresnel", new int( FRESNEL_TOK ) );
+ insert( "frequency", new int( FREQUENCY_TOK ) );
+ insert( "function", new int( FUNCTION_TOK ) );
+ insert( "gather", new int( GATHER_TOK ) );
+ insert( "gif", new int( GIF_TOK ) );
+ insert( "global_lights", new int ( GLOBAL_LIGHTS_TOK ) );
+ insert( "global_settings", new int( GLOBAL_SETTINGS_TOK ) );
+ insert( "glowing", new int( GLOWING_TOK ) );
+ insert( "gradient", new int( GRADIENT_TOK ) );
+ insert( "granite", new int( GRANITE_TOK ) );
+ insert( "gray_threshold", new int( GRAY_THRESHOLD_TOK ) );
+ insert( "green", new int( GREEN_TOK ) );
+ insert( "halo", new int( HALO_TOK ) );
+ insert( "height_field", new int( HEIGHT_FIELD_TOK ) );
+ insert( "hexagon", new int( HEXAGON_TOK ) );
+ insert( "hf_gray_16", new int( HF_GRAY_16_TOK ) );
+ insert( "hierarchy", new int( HIERARCHY_TOK ) );
+ insert( "hollow", new int( HOLLOW_TOK ) );
+ insert( "hypercomplex", new int( HYPERCOMPLEX_TOK ) );
+ insert( "iff", new int( IFF_TOK ) );
+ insert( "image_map", new int( IMAGE_MAP_TOK ) );
+ insert( "incidence", new int( INCIDENCE_TOK ) );
+ insert( "inside_vector", new int( INSIDE_VECTOR_TOK ) );
+ insert( "int", new int( INT_TOK ) );
+ insert( "interior", new int( INTERIOR_TOK ) );
+ insert( "interior_texture", new int( INTERIOR_TEXTURE_TOK ) );
+ insert( "interpolate", new int( INTERPOLATE_TOK ) );
+ insert( "intersection", new int( INTERSECTION_TOK ) );
+ insert( "intervals", new int( INTERVALS_TOK ) );
+ insert( "inverse", new int( INVERSE_TOK ) );
+ insert( "ior", new int( IOR_TOK ) );
+ insert( "irid", new int( IRID_TOK ) );
+ insert( "irid_wavelength", new int( IRID_WAVELENGTH_TOK ) );
+ insert( "isosurface", new int( ISOSURFACE_TOK ) );
+ insert( "jitter", new int( JITTER_TOK ) );
+ insert( "julia", new int( JULIA_TOK ) );
+ insert( "julia_fractal", new int( JULIA_FRACTAL_TOK ) );
+ insert( "lambda", new int( LAMBDA_TOK ) );
+ insert( "lathe", new int( LATHE_TOK ) );
+ insert( "leopard", new int( LEOPARD_TOK ) );
+ insert( "light_group", new int ( LIGHT_GROUP_TOK ) );
+ insert( "light_source", new int( LIGHT_SOURCE_TOK ) );
+ insert( "linear", new int( LINEAR_TOK ) );
+ insert( "linear_spline", new int( LINEAR_SPLINE_TOK ) );
+ insert( "linear_sweep", new int( LINEAR_SWEEP_TOK ) );
+ insert( "location", new int( LOCATION_TOK ) );
+ insert( "log", new int( LOG_TOK ) );
+ insert( "looks_like", new int( LOOKS_LIKE_TOK ) );
+ insert( "look_at", new int( LOOK_AT_TOK ) );
+ insert( "low_error_factor", new int( LOW_ERROR_FACTOR_TOK ) );
+ insert( "magnet", new int ( MAGNET_TOK ) );
+ insert( "major_radius", new int( MAJOR_RADIUS_TOK ) );
+ insert( "mandel", new int( MANDEL_TOK ) );
+ insert( "map_type", new int( MAP_TYPE_TOK ) );
+ insert( "marble", new int( MARBLE_TOK ) );
+ insert( "material", new int( MATERIAL_TOK ) );
+ insert( "material_map", new int( MATERIAL_MAP_TOK ) );
+ insert( "matrix", new int( MATRIX_TOK ) );
+ insert( "max", new int( MAX_TOK ) );
+ insert( "max_gradient", new int( MAX_GRADIENT_TOK ) );
+ insert( "max_intersections", new int( MAX_INTERSECTIONS_TOK ) );
+ insert( "max_iteration", new int( MAX_ITERATION_TOK ) );
+ insert( "max_sample", new int( MAX_SAMPLE_TOK ) );
+ insert( "max_trace", new int( MAX_TRACE_TOK ) );
+ insert( "max_trace_level", new int( MAX_TRACE_LEVEL_TOK ) );
+ insert( "max_value", new int( MAX_VALUE_TOK ) );
+ insert( "media", new int( MEDIA_TOK ) );
+ insert( "media_attenuation", new int( MEDIA_ATTENUATION_TOK ) );
+ insert( "media_interaction", new int( MEDIA_INTERACTION_TOK ) );
+ insert( "merge", new int( MERGE_TOK ) );
+ insert( "mesh", new int( MESH_TOK ) );
+ insert( "metallic", new int( METALLIC_TOK ) );
+ insert( "method", new int( METHOD_TOK ) );
+ insert( "metric", new int( METRIC_TOK ) );
+ insert( "min", new int( MIN_TOK ) );
+ insert( "minimum_reuse", new int( MINIMUM_REUSE_TOK ) );
+ insert( "mod", new int( MOD_TOK ) );
+ insert( "mortar", new int( MORTAR_TOK ) );
+ insert( "nearest_count", new int( NEAREST_COUNT_TOK ) );
+ insert( "no", new int( NO_TOK ) );
+ insert( "noise_generator", new int( NOISE_GENERATOR_TOK ) );
+ insert( "normal", new int( NORMAL_TOK ) );
+ insert( "normal_map", new int( NORMAL_MAP_TOK ) );
+ insert( "no_image", new int( NO_IMAGE_TOK ) );
+ insert( "no_reflection", new int( NO_REFLECTION_TOK ) );
+ insert( "no_shadow", new int( NO_SHADOW_TOK ) );
+ insert( "number_of_waves", new int( NUMBER_OF_WAVES_TOK ) );
+ insert( "object", new int( OBJECT_TOK ) );
+ insert( "octaves", new int( OCTAVES_TOK ) );
+ insert( "off", new int( OFF_TOK ) );
+ insert( "offset", new int( OFFSET_TOK ) );
+ insert( "omega", new int( OMEGA_TOK ) );
+ insert( "omnimax", new int( OMNIMAX_TOK ) );
+ insert( "on", new int( ON_TOK ) );
+ insert( "once", new int( ONCE_TOK ) );
+ insert( "onion", new int( ONION_TOK ) );
+ insert( "open", new int( OPEN_TOK ) );
+ insert( "orient", new int( ORIENT_TOK ) );
+ insert( "orthographic", new int( ORTHOGRAPHIC_TOK ) );
+ insert( "panoramic", new int( PANORAMIC_TOK ) );
+ insert( "parallel", new int( PARALLEL_TOK ) );
+ insert( "pass_through", new int ( PASS_THROUGH_TOK ) );
+ insert( "pattern1", new int( PATTERN1_TOK ) );
+ insert( "pattern2", new int( PATTERN2_TOK ) );
+ insert( "pattern3", new int( PATTERN3_TOK ) );
+ insert( "perspective", new int( PERSPECTIVE_TOK ) );
+ insert( "pgm", new int( PGM_TOK ) );
+ insert( "phase", new int( PHASE_TOK ) );
+ insert( "phong", new int( PHONG_TOK ) );
+ insert( "phong_size", new int( PHONG_SIZE_TOK ) );
+ insert( "photons", new int ( PHOTONS_TOK ) );
+ insert( "pi", new int( PI_TOK ) );
+ insert( "pigment", new int( PIGMENT_TOK ) );
+ insert( "pigment_map", new int( PIGMENT_MAP_TOK ) );
+ insert( "planar", new int( PLANAR_TOK ) );
+ insert( "plane", new int( PLANE_TOK ) );
+ insert( "png", new int( PNG_TOK ) );
+ insert( "point_at", new int( POINT_AT_TOK ) );
+ insert( "poly", new int( POLY_TOK ) );
+ insert( "poly_wave", new int( POLY_WAVE_TOK ) );
+ insert( "polygon", new int( POLYGON_TOK ) );
+ insert( "pot", new int( POT_TOK ) );
+ insert( "pow", new int( POW_TOK ) );
+ insert( "ppm", new int( PPM_TOK ) );
+ insert( "precision", new int( PRECISION_TOK ) );
+ insert( "pretrace_end", new int( PRETRACE_END_TOK ) );
+ insert( "pretrace_start", new int( PRETRACE_START_TOK ) );
+ insert( "prism", new int( PRISM_TOK ) );
+ insert( "projected_through", new int( PROJECTED_THROUGH_TOK ) );
+ insert( "pwr", new int( PWR_TOK ) );
+ insert( "quadratic_spline", new int( QUADRATIC_SPLINE_TOK ) );
+ insert( "quadric", new int( QUADRIC_TOK ) );
+ insert( "quartic", new int( QUARTIC_TOK ) );
+ insert( "quaternion", new int( QUATERNION_TOK ) );
+ insert( "quick_color", new int( QUICK_COLOR_TOK ) );
+ insert( "quick_colour", new int( QUICK_COLOUR_TOK ) );
+ insert( "quilted", new int( QUILTED_TOK ) );
+ insert( "radial", new int( RADIAL_TOK ) );
+ insert( "radians", new int( RADIANS_TOK ) );
+ insert( "radiosity", new int( RADIOSITY_TOK ) );
+ insert( "radius", new int( RADIUS_TOK ) );
+ insert( "rainbow", new int( RAINBOW_TOK ) );
+ insert( "ramp_wave", new int( RAMP_WAVE_TOK ) );
+ insert( "rand", new int( RAND_TOK ) );
+ insert( "ratio", new int( RATIO_TOK ) );
+ insert( "reciprocal", new int( RECIPROCAL_TOK ) );
+ insert( "recursion_limit", new int( RECURSION_LIMIT_TOK ) );
+ insert( "red", new int( RED_TOK ) );
+ insert( "reflection", new int( REFLECTION_TOK ) );
+ insert( "reflection_exponent", new int( REFLECTION_EXPONENT_TOK ) );
+ insert( "refraction", new int( REFRACTION_TOK ) );
+ insert( "repeat", new int( REPEAT_TOK ) );
+ insert( "rgb", new int( RGB_TOK ) );
+ insert( "rgbf", new int( RGBF_TOK ) );
+ insert( "rgbft", new int( RGBFT_TOK ) );
+ insert( "rgbt", new int( RGBT_TOK ) );
+ insert( "right", new int( RIGHT_TOK ) );
+ insert( "ripples", new int( RIPPLES_TOK ) );
+ insert( "rotate", new int( ROTATE_TOK ) );
+ insert( "roughness", new int( ROUGHNESS_TOK ) );
+ insert( "samples", new int( SAMPLES_TOK ) );
+ insert( "scale", new int( SCALE_TOK ) );
+ insert( "scallop_wave", new int( SCALLOP_WAVE_TOK ) );
+ insert( "scattering", new int( SCATTERING_TOK ) );
+ insert( "seed", new int( SEED_TOK ) );
+ insert( "shadowless", new int( SHADOWLESS_TOK ) );
+ insert( "sin", new int( SIN_TOK ) );
+ insert( "sine_wave", new int( SINE_WAVE_TOK ) );
+ insert( "sinh", new int( SINH_TOK ) );
+ insert( "sky", new int( SKY_TOK ) );
+ insert( "sky_sphere", new int( SKY_SPHERE_TOK ) );
+ insert( "slice", new int( SLICE_TOK ) );
+ insert( "slope", new int( SLOPE_TOK ) );
+ insert( "slope_map", new int( SLOPE_MAP_TOK ) );
+ insert( "smooth", new int( SMOOTH_TOK ) );
+ insert( "smooth_triangle", new int( SMOOTH_TRIANGLE_TOK ) );
+ insert( "solid", new int( SOLID_TOK ) );
+ insert( "sor", new int( SOR_TOK ) );
+ insert( "spacing", new int ( SPACING_TOK ) );
+ insert( "specular", new int( SPECULAR_TOK ) );
+ insert( "sphere", new int( SPHERE_TOK ) );
+ insert( "sphere_sweep", new int ( SPHERE_SWEEP_TOK ) );
+ insert( "spherical", new int( SPHERICAL_TOK ) );
+ insert( "spiral", new int( SPIRAL_TOK ) );
+ insert( "spiral1", new int( SPIRAL1_TOK ) );
+ insert( "spiral2", new int( SPIRAL2_TOK ) );
+ insert( "spotlight", new int( SPOTLIGHT_TOK ) );
+ insert( "spotted", new int( SPOTTED_TOK ) );
+ insert( "sqr", new int( SQR_TOK ) );
+ insert( "sqrt", new int( SQRT_TOK ) );
+ insert( "str", new int( STR_TOK ) );
+ insert( "strcmp", new int( STRCMP_TOK ) );
+ insert( "strength", new int( STRENGTH_TOK ) );
+ insert( "strlen", new int( STRLEN_TOK ) );
+ insert( "strlwr", new int( STRLWR_TOK ) );
+ insert( "strupr", new int( STRUPR_TOK ) );
+ insert( "sturm", new int( STURM_TOK ) );
+ insert( "substr", new int( SUBSTR_TOK ) );
+ insert( "superellipsoid", new int( SUPERELLIPSOID_TOK ) );
+ insert( "sys", new int( SYS_TOK ) );
+ insert( "t", new int( T_TOK ) );
+ insert( "tan", new int( TAN_TOK ) );
+ insert( "tanh", new int( TANH_TOK ) );
+ insert( "target", new int( TARGET_TOK ) );
+ insert( "test_camera_1", new int( TEST_CAMERA_1_TOK ) );
+ insert( "test_camera_2", new int( TEST_CAMERA_2_TOK ) );
+ insert( "test_camera_3", new int( TEST_CAMERA_3_TOK ) );
+ insert( "test_camera_4", new int( TEST_CAMERA_4_TOK ) );
+ insert( "text", new int( TEXT_TOK ) );
+ insert( "texture", new int( TEXTURE_TOK ) );
+ insert( "texture_map", new int( TEXTURE_MAP_TOK ) );
+ insert( "tga", new int( TGA_TOK ) );
+ insert( "thickness", new int( THICKNESS_TOK ) );
+ insert( "threshold", new int( THRESHOLD_TOK ) );
+ insert( "tightness", new int( TIGHTNESS_TOK ) );
+ insert( "tile2", new int( TILE2_TOK ) );
+ insert( "tiles", new int( TILES_TOK ) );
+ insert( "tolerance", new int( TOLERANCE_TOK ) );
+ insert( "toroidal", new int( TOROIDAL_TOK ) );
+ insert( "torus", new int( TORUS_TOK ) );
+ insert( "track", new int( TRACK_TOK ) );
+ insert( "transform", new int( TRANSFORM_TOK ) );
+ insert( "translate", new int( TRANSLATE_TOK ) );
+ insert( "transmit", new int( TRANSMIT_TOK ) );
+ insert( "triangle", new int( TRIANGLE_TOK ) );
+ insert( "triangle_wave", new int( TRIANGLE_WAVE_TOK ) );
+ insert( "true", new int( TRUE_TOK ) );
+ insert( "ttf", new int( TTF_TOK ) );
+ insert( "turbulence", new int( TURBULENCE_TOK ) );
+ insert( "turb_depth", new int( TURB_DEPTH_TOK ) );
+ insert( "type", new int( TYPE_TOK ) );
+ insert( "u", new int( U_TOK ) );
+ insert( "ultra_wide_angle", new int( ULTRA_WIDE_ANGLE_TOK ) );
+ insert( "union", new int( UNION_TOK ) );
+ insert( "up", new int( UP_TOK ) );
+ insert( "use_color", new int( USE_COLOR_TOK ) );
+ insert( "use_colour", new int( USE_COLOUR_TOK ) );
+ insert( "use_index", new int( USE_INDEX_TOK ) );
+ insert( "u_steps", new int( U_STEPS_TOK ) );
+ insert( "uv_mapping", new int( UV_MAPPING_TOK ) );
+ insert( "uv_vectors", new int( UV_VECTORS_TOK ) );
+ insert( "v", new int( V_TOK ) );
+ insert( "val", new int( VAL_TOK ) );
+ insert( "variance", new int( VARIANCE_TOK ) );
+ insert( "vaxis_rotate", new int( VAXIS_ROTATE_TOK ) );
+ insert( "vcross", new int( VCROSS_TOK ) );
+ insert( "vdot", new int( VDOT_TOK ) );
+ insert( "vlength", new int( VLENGTH_TOK ) );
+ insert( "vnormalize", new int( VNORMALIZE_TOK ) );
+ insert( "volume_object", new int( VOLUME_OBJECT_TOK ) );
+ insert( "volume_rendered", new int( VOLUME_RENDERED_TOK ) );
+ insert( "vol_with_light", new int( VOL_WITH_LIGHT_TOK ) );
+ insert( "vrotate", new int( VROTATE_TOK ) );
+ insert( "v_steps", new int( V_STEPS_TOK ) );
+ insert( "warp", new int( WARP_TOK ) );
+ insert( "water_level", new int( WATER_LEVEL_TOK ) );
+ insert( "waves", new int( WAVES_TOK ) );
+ insert( "width", new int( WIDTH_TOK ) );
+ insert( "wood", new int( WOOD_TOK ) );
+ insert( "wrinkles", new int( WRINKLES_TOK ) );
+ insert( "x", new int( X_TOK ) );
+ insert( "y", new int( Y_TOK ) );
+ insert( "yes", new int( YES_TOK ) );
+ insert( "z", new int( Z_TOK ) );
+ break;
+ case PMDDirectives:
+ insert( "break", new int( BREAK_TOK ) );
+ insert( "case", new int( CASE_TOK ) );
+ insert( "debug", new int( DEBUG_TOK ) );
+ insert( "declare", new int( DECLARE_TOK ) );
+ insert( "default", new int( DEFAULT_TOK ) );
+ insert( "else", new int( ELSE_TOK ) );
+ insert( "end", new int( END_TOK ) );
+ insert( "if", new int( IF_TOK ) );
+ insert( "ifdef", new int( IFDEF_TOK ) );
+ insert( "ifndef", new int( IFNDEF_TOK ) );
+ insert( "include", new int( INCLUDE_TOK ) );
+ insert( "range", new int( RANGE_TOK ) );
+ insert( "render", new int( RENDER_TOK ) );
+ insert( "statistics", new int( STATISTICS_TOK ) );
+ insert( "switch", new int( SWITCH_TOK ) );
+ insert( "version", new int( VERSION_TOK ) );
+ insert( "warning", new int( WARNING_TOK ) );
+ insert( "while", new int( WHILE_TOK ) );
+ break;
+ }
+}
+
+PMReservedWordDict::~PMReservedWordDict( )
+{
+}
+
+PMReservedWordDict PMScanner::m_reservedWords( PMReservedWordDict::PMDReservedWords );
+PMReservedWordDict PMScanner::m_directives( PMReservedWordDict::PMDDirectives );
+
+const char* c_commentName = "*PMName ";
+const int c_commentNameLength = 8;
+
+const char* c_commentRawBegin = "*PMRawBegin";
+const int c_commentRawBeginLength = 11;
+
+const char* c_commentRawEnd = "//*PMRawEnd";
+const int c_commentRawEndLength = 11;
+
+
+PMScanner::PMScanner( QIODevice* device )
+{
+ m_svalueAlloc = 256;
+ m_svalue = ( char* ) malloc( m_svalueAlloc );
+ m_svalue[0] = '\0';
+ m_lastAlloc = m_svalue + m_svalueAlloc;
+ m_lastChar = m_svalue;
+
+ m_ivalue = 0;
+ m_fvalue = 0;
+ m_pDevice = device;
+ m_line = 1;
+ m_char = 0;
+ m_indentation = 0;
+ m_rawIndentation = 0;
+ m_bFunctionMode = false;
+
+// m_lineData = "";
+// m_lineDataPos = 100;
+// m_lineDataLength = 0;
+ nextChar( );
+}
+
+PMScanner::~PMScanner( )
+{
+ if( m_svalue )
+ free( m_svalue );
+}
+
+void PMScanner::nextChar( )
+{
+ do
+ {
+ m_char = m_pDevice->getch( );
+ }
+ while( m_char == '\r' );
+}
+
+void PMScanner::clearSValue( )
+{
+ m_svalue[0] = '\0';
+ m_lastChar = m_svalue;
+}
+
+void PMScanner::addChar( char c )
+{
+ *m_lastChar = c;
+ m_lastChar++;
+
+ if( m_lastChar == m_lastAlloc )
+ {
+ m_svalueAlloc += 64;
+ m_svalue = ( char* ) realloc( m_svalue, m_svalueAlloc );
+ m_lastAlloc = m_svalue + m_svalueAlloc;
+ m_lastChar = m_lastAlloc - 64;
+ }
+
+ *m_lastChar = '\0';
+}
+
+bool PMScanner::isseparation( int c )
+{
+ if( c < 0 )
+ return true;
+ if( isspace( c ) )
+ return true;
+ switch( c )
+ {
+ case '{':
+ case '}':
+ case '<':
+ case '>':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case ',':
+ case ';':
+ case '=':
+ case '.':
+ return true;
+ break;
+ default:
+ return false;
+ }
+ return false;
+}
+
+
+void PMScanner::scanError( int c )
+{
+ m_token = SCANNER_ERROR_TOK;
+ if( isprint( c ) )
+ m_error = i18n( "Unexpected character '%1' after \"%2\"" )
+ .arg( ( char )c ).arg( m_svalue );
+ else
+ m_error = i18n( "Unexpected character %1 after \"%2\"" )
+ .arg( c, 4, 16 ).arg( m_svalue );
+
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+}
+
+
+int PMScanner::nextToken( )
+{
+ int status = START_ST;
+ int cdepth = 0;
+ bool consumed;
+ bool end = false;
+
+ clearSValue( );
+ m_ivalue = 0;
+ m_fvalue = 0;
+// m_error = "";
+
+ if( m_bFunctionMode )
+ {
+ m_bFunctionMode = false;
+ // FIXME: TODO brackets in comments will not be scanned correctly
+ int count = 1;
+
+ while( count > 0 )
+ {
+ if( m_char < 0 )
+ count = 0;
+ else if( m_char == '{' )
+ count++;
+ else if( m_char == '}' )
+ count--;
+ if( count > 0 )
+ {
+ addChar( m_char );
+ nextChar( );
+ }
+ }
+
+ if( m_char != '}' )
+ {
+ m_error = i18n( "Function statement not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ }
+ else
+ m_token = FUNCTION_TOK;
+ }
+ else while( status != TOKEN_END_ST )
+ {
+ consumed = true;
+ if( m_char < 0 )
+ end = true;
+ switch( status )
+ {
+ case START_ST: //begin
+ if( m_char < 0 )
+ {
+ m_token = EOF_TOK;
+ addChar( 'E' );
+ addChar( 'O' );
+ addChar( 'F' );
+ status = TOKEN_END_ST;
+ consumed = false;
+ break;
+ }
+ if( m_char == '\n' )
+ {
+ m_line ++;
+ m_indentation = 0;
+ break;
+ }
+ if( m_char == ' ' )
+ {
+ m_indentation++;
+ break;
+ }
+ if( m_char == '\t' )
+ {
+ m_indentation += 8 - m_indentation % 8;
+ break;
+ }
+ if( iscntrl( m_char ) )
+ break;
+ if( isspace( m_char ) )
+ break;
+ if( isalpha( m_char ) || ( m_char == '_' ) )
+ {
+ status = ID_ENDST;
+ addChar( m_char );
+ break;
+ }
+ if( isdigit( m_char ) )
+ {
+ status = INTEGER_ENDST;
+ addChar( m_char );
+ break;
+ }
+ switch( m_char )
+ {
+ case '.':
+ status = POINT_ST;
+ addChar( m_char );
+ break;
+ case '#':
+ status = DIRECTIVE1_ST;
+ break;
+ case '"':
+ status = STRING1_ST;
+ break;
+ case '/':
+ status = SLASH_ST;
+ break;
+ default:
+ addChar( m_char );
+ m_token = m_char;
+ status = TOKEN_END_ST;
+
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Single char '"
+ << QString( QChar( ( char ) m_char ) ) << "'\n";
+#endif
+ break;
+ }
+ break;
+ case ID_ENDST: // indentifier or reserved word
+ if( isalnum( m_char ) || ( m_char == '_' ) )
+ {
+ addChar( m_char );
+ break;
+ }
+ else if( isseparation( m_char ) )
+ {
+ consumed = false;
+ m_token = m_reservedWords[ m_svalue ];
+ if( m_token < 0 )
+ m_token = ID_TOK;
+
+#ifdef PMSCAN_DEBUG
+ if( m_token == ID_TOK )
+ kdDebug( PMArea ) << "Line " << m_line << ": Indentifier: \""
+ << m_svalue << "\"\n";
+ else
+ kdDebug( PMArea ) << "Line " << m_line << ": Reserved word: \""
+ << m_svalue << "\"\n";
+#endif
+
+
+ status = TOKEN_END_ST;
+ }
+ else
+ {
+ status = TOKEN_END_ST;
+ scanError( m_char );
+ consumed = false;
+ }
+ break;
+ case INTEGER_ENDST:
+ if( isdigit ( m_char ) )
+ {
+ addChar( m_char );
+ break;
+ }
+ else if( m_char == '.' )
+ {
+ status = FLOAT1_ST;
+ addChar( m_char );
+ break;
+ }
+ else if( ( m_char == 'e' ) || ( m_char == 'E' ) )
+ {
+ status = FLOAT_EXP1_ST;
+ addChar( m_char );
+ break;
+ }
+ else if( isseparation( m_char ) )
+ {
+ consumed = false;
+ m_ivalue = atoi( m_svalue );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Integer: "
+ << m_ivalue << "\n";
+#endif
+ m_token = INTEGER_TOK;
+ status = TOKEN_END_ST;
+ }
+ else
+ {
+ status = TOKEN_END_ST;
+ scanError( m_char );
+ consumed = false;
+ }
+ break;
+ case POINT_ST:
+ if( isdigit( m_char ) )
+ {
+ status = FLOAT_ENDST;
+ addChar( m_char );
+ }
+ else
+ {
+ status = TOKEN_END_ST;
+ consumed = false;
+ m_token = '.';
+ }
+ break;
+ case FLOAT1_ST:
+ if( isdigit( m_char ) )
+ {
+ status = FLOAT_ENDST;
+ addChar( m_char );
+ break;
+ }
+ else
+ {
+ scanError( m_char );
+ status = TOKEN_END_ST;
+ consumed = false;
+ }
+ break;
+ case FLOAT_ENDST:
+ if( isdigit ( m_char ) )
+ {
+ addChar( m_char );
+ break;
+ }
+ if( ( m_char == 'e' ) || ( m_char == 'E' ) )
+ {
+ status = FLOAT_EXP1_ST;
+ addChar( m_char );
+ break;
+ }
+ else if( isseparation( m_char ) )
+ {
+ consumed = false;
+ m_fvalue = atof( m_svalue );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Float: "
+ << m_fvalue << "\n";
+#endif
+ m_token = FLOAT_TOK;
+ status = TOKEN_END_ST;
+ }
+ else
+ {
+ scanError( m_char );
+ status = TOKEN_END_ST;
+ consumed = false;
+ }
+ break;
+ case FLOAT_EXP1_ST:
+ if( ( m_char == '-' ) || ( m_char == '+' ) )
+ {
+ status = FLOAT_EXP2_ST;
+ addChar( m_char );
+ break;
+ }
+ if( isdigit( m_char ) )
+ {
+ status = FLOAT_EXP_ENDST;
+ addChar( m_char );
+ break;
+ }
+ else
+ {
+ scanError( m_char );
+ consumed = false;
+ status = TOKEN_END_ST;
+ }
+ break;
+ case FLOAT_EXP2_ST:
+ if( isdigit( m_char ) )
+ {
+ status = FLOAT_EXP_ENDST;
+ addChar( m_char );
+ break;
+ }
+ else
+ {
+ scanError( m_char );
+ consumed = false;
+ status = TOKEN_END_ST;
+ }
+ break;
+ case FLOAT_EXP_ENDST:
+ if( isdigit ( m_char ) )
+ {
+ addChar( m_char );
+ break;
+ }
+ else if( isseparation( m_char ) )
+ {
+ consumed = false;
+ m_fvalue = atof( m_svalue );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Float: "
+ << m_fvalue << "\n";
+#endif
+ m_token = FLOAT_TOK;
+ status = TOKEN_END_ST;
+ }
+ else
+ {
+ scanError( m_char );
+ consumed = false;
+ status = TOKEN_END_ST;
+ }
+ break;
+ case DIRECTIVE1_ST:
+ if( m_char == ' ' )
+ {
+ // special treatment for povray inc files
+ // "# debug" directives
+ break;
+ }
+ else if( isalpha ( m_char ) )
+ {
+ status = DIRECTIVE_ENDST;
+ addChar( m_char );
+ break;
+ }
+ else
+ {
+ scanError( m_char );
+ consumed = false;
+ status = TOKEN_END_ST;
+ }
+ break;
+ case DIRECTIVE_ENDST:
+ if( isalpha( m_char ) )
+ {
+ addChar( m_char );
+ break;
+ }
+ else if( isseparation( m_char ) )
+ {
+ consumed = false;
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Directive: \""
+ << m_svalue << "\"\n";
+#endif
+ m_token = m_directives[ m_svalue ];
+ if( m_token < 0 )
+ {
+ m_error = i18n( "Unknown directive" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+
+ m_token = SCANNER_ERROR_TOK;
+ }
+ status = TOKEN_END_ST;
+ }
+ else
+ {
+ scanError( m_char );
+ consumed = false;
+ status = TOKEN_END_ST;
+ }
+ break;
+ case STRING1_ST:
+ switch( m_char )
+ {
+ case '\n':
+ case '\r':
+ consumed = false;
+ m_error = i18n( "String not terminated" );
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ break;
+ case '"':
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": String: \""
+ << m_svalue << "\"\n";
+#endif
+
+ m_token = STRING_TOK;
+ status = TOKEN_END_ST;
+ break;
+ case '\\':
+ status = STRINGBS_ST;
+ addChar( m_char );
+ break;
+ default:
+ addChar( m_char );
+ break;
+ }
+ break;
+ case STRINGBS_ST:
+ if( ( m_char == '\n' ) || ( m_char == '\r' ) || ( m_char < 0 ) )
+ {
+ consumed = false;
+ m_error = i18n( "String not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+ break;
+ }
+ else
+ {
+ status = STRING1_ST;
+ addChar( m_char );
+ break;
+ }
+ break;
+ case SLASH_ST:
+ switch( m_char )
+ {
+ case '/':
+ status = LINE_COMMENT_FIRST_ST;
+ break;
+ case '*':
+ status = COMMENT_NEW_LINE_ST;
+ cdepth ++;
+ break;
+ default:
+ consumed = false;
+ m_token = '/';
+ status = TOKEN_END_ST;
+ }
+ break;
+ case LINE_COMMENT_FIRST_ST:
+ // skip the first space char
+ if( ( m_char == '\n' ) || ( m_char == '\r' ) || ( m_char < 0 ) )
+ {
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Empty line comment\n";
+#endif
+ consumed = false;
+ m_token = LINE_COMMENT_TOK;
+ status = TOKEN_END_ST;
+ break;
+ }
+ else if( !isspace( m_char ) )
+ addChar( m_char );
+ status = LINE_COMMENT_ST;
+ break;
+ case LINE_COMMENT_ST:
+ if( ( m_char == '\n' ) || ( m_char == '\r' ) || ( m_char < 0 ) )
+ {
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Line comment: \""
+ << m_svalue << "\"\n";
+#endif
+ consumed = false;
+ m_token = LINE_COMMENT_TOK;
+ status = TOKEN_END_ST;
+ break;
+ }
+ else
+ {
+ addChar( m_char );
+ int l = m_lastChar - m_svalue;
+ if( l == c_commentNameLength )
+ {
+ if( strcmp( m_svalue, c_commentName ) == 0 )
+ {
+ status = PMNAME_ST;
+ clearSValue( );
+ }
+ }
+ if( l == c_commentRawBeginLength )
+ {
+ if( strcmp( m_svalue, c_commentRawBegin ) == 0 )
+ {
+ status = RAW_POVRAY_FIRST_ST;
+ clearSValue( );
+ }
+ }
+ break;
+ }
+ break;
+ case COMMENT_NEW_LINE_ST:
+ // skip any white spaces at begin of line.
+ if( m_char < 0 )
+ {
+ consumed = false;
+ m_error = i18n( "Comment not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+ }
+ else if( m_char == '\n' )
+ {
+ addChar( '\n' );
+ m_line ++;
+ }
+ else if( !isspace( m_char ) )
+ {
+ consumed = false;
+ status = C_COMMENT_ST;
+ }
+ break;
+ case C_COMMENT_ST:
+ if( m_char < 0 )
+ {
+ consumed = false;
+ m_error = i18n( "Comment not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+ }
+ else
+ {
+ switch( m_char )
+ {
+ case '*':
+ status = COMMENT_ST_ST;
+ break;
+ case '/':
+ status = COMMENT_SL_ST;
+ addChar( m_char );
+ break;
+ case '\n':
+ addChar( m_char );
+ m_line ++;
+ status = COMMENT_NEW_LINE_ST;
+ break;
+ default:
+ addChar( m_char );
+ }
+ }
+ break;
+ case COMMENT_ST_ST:
+ if( m_char < 0 )
+ {
+ consumed = false;
+ m_error = i18n( "Comment not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+ }
+ else
+ {
+ switch( m_char )
+ {
+ case '/':
+ cdepth --;
+ if( cdepth == 0 )
+ {
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Comment: \""
+ << m_svalue << "\"\n";
+#endif
+ m_token = COMMENT_TOK;
+ status = TOKEN_END_ST;
+ break;
+ }
+ else
+ {
+ status = C_COMMENT_ST;
+ addChar( '*' );
+ addChar( '/' );
+ break;
+ }
+ case '*':
+ addChar( m_char );
+ break;
+ case '\n':
+ status = C_COMMENT_ST;
+ addChar( '*' );
+ addChar( m_char );
+ m_line ++;
+ break;
+ default:
+ status = C_COMMENT_ST;
+ addChar( '*' );
+ addChar( m_char );
+ break;
+ }
+ }
+ break;
+ case COMMENT_SL_ST:
+ if( m_char < 0 )
+ {
+ consumed = false;
+ m_error = i18n( "Comment not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+ }
+ else
+ {
+ switch( m_char )
+ {
+ case '/':
+ addChar( m_char );
+ break;
+ case '*':
+ status = C_COMMENT_ST;
+ addChar( m_char );
+ cdepth ++;
+ break;
+ case '\n':
+ status = C_COMMENT_ST;
+ addChar( m_char );
+ m_line ++;
+ break;
+ default:
+ status = C_COMMENT_ST;
+ addChar( m_char );
+ }
+ }
+ break;
+ case PMNAME_ST:
+ if( ( m_char == '\n' ) || ( m_char == '\r' ) || ( m_char < 0 ) )
+ {
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": PMName: \""
+ << m_svalue << "\"\n";
+#endif
+ consumed = false;
+ m_token = PMNAME_TOK;
+ status = TOKEN_END_ST;
+ break;
+ }
+ else
+ {
+ addChar( m_char );
+ break;
+ }
+ break;
+ case RAW_POVRAY_FIRST_ST: // skip the first line
+ if( m_char < 0 )
+ {
+ consumed = false;
+ m_error = i18n( "Raw povray not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+ }
+ if( m_char == '\n' )
+ {
+ m_line++;
+ m_rawIndentation = 0;
+ status = RAW_POVRAY_LB_ST;
+ }
+ break;
+ case RAW_POVRAY_LB_ST:
+ switch( m_char )
+ {
+ case '\n':
+ addChar( m_char );
+ m_line++;
+ m_rawIndentation = 0;
+ // status = RAW_POVRAY_LB_ST;
+ break;
+ case ' ':
+ m_rawIndentation++;
+ if( m_rawIndentation >= m_indentation )
+ status = RAW_POVRAY_ST;
+ break;
+ case '\t':
+ m_rawIndentation += 8 - m_rawIndentation % 8;
+ if( m_rawIndentation >= m_indentation )
+ status = RAW_POVRAY_ST;
+ break;
+ default:
+ consumed = false;
+ status = RAW_POVRAY_ST;
+ break;
+ }
+ break;
+ case RAW_POVRAY_ST:
+ if( m_char < 0 )
+ {
+ consumed = false;
+ m_error = i18n( "Raw povray not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+ }
+ else if( m_char == '\n' )
+ {
+ addChar( m_char );
+ m_line++;
+ m_rawIndentation = 0;
+ status = RAW_POVRAY_LB_ST;
+ }
+ else if( m_char == '/' )
+ {
+ m_rawPovrayEnd = 1;
+ status = RAW_POVRAY_END_ST;
+ }
+ else
+ addChar( m_char );
+ break;
+ case RAW_POVRAY_END_ST:
+ if( m_char < 0 )
+ {
+ consumed = false;
+ m_error = i18n( "Raw povray not terminated" );
+#ifdef PMSCAN_DEBUG
+ kdDebug( PMArea ) << "Line " << m_line << ": Error " << m_error << "\n";
+#endif
+ m_token = SCANNER_ERROR_TOK;
+ status = TOKEN_END_ST;
+ }
+ else if( m_char != c_commentRawEnd[m_rawPovrayEnd] )
+ {
+ status = RAW_POVRAY_ST;
+ int i;
+ for( i = 0; i < m_rawPovrayEnd; i++ )
+ addChar( c_commentRawEnd[i] );
+ consumed = false;
+ }
+ else
+ {
+ m_rawPovrayEnd++;
+ if( m_rawPovrayEnd >= c_commentRawEndLength )
+ {
+ status = RAW_POVRAY_END_END_ST;
+ if( m_lastChar > m_svalue )
+ {
+ if( *( m_lastChar - 1 ) == '\n' )
+ {
+ m_lastChar--;
+ *m_lastChar = 0;
+ }
+ }
+ }
+ }
+ break;
+ case RAW_POVRAY_END_END_ST:
+ if( ( m_char < 0 ) || ( m_char == '\n' ) )
+ {
+ consumed = false;
+ status = TOKEN_END_ST;
+ m_token = RAW_POVRAY_TOK;
+ }
+ break;
+ case TOKEN_END_ST:
+ break;
+ }
+ if( consumed )
+ nextChar( );
+ if( end && ( status != TOKEN_END_ST ) )
+ {
+ status = TOKEN_END_ST;
+ kdError( PMArea ) << "Error in scanner: No TOKEN_END_ST after EOF\n";
+ }
+ }
+
+ return m_token;
+}
+
+void PMScanner::scanFunction( )
+{
+ m_bFunctionMode = true;
+}
diff --git a/kpovmodeler/pmscanner.h b/kpovmodeler/pmscanner.h
new file mode 100644
index 00000000..6a3e8529
--- /dev/null
+++ b/kpovmodeler/pmscanner.h
@@ -0,0 +1,191 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSCANNER_H
+#define PMSCANNER_H
+
+#include <qiodevice.h>
+#include <qstring.h>
+#include <qasciidict.h>
+
+/**
+ * Dictionary of reserved words for fast lookup
+ *
+ * The class @ref PMScanner has two static dictionaries: one for reserved
+ * words and one for directives. The constructor will insert the items.
+ */
+class PMReservedWordDict : protected QAsciiDict<int>
+{
+public:
+ /**
+ * Mode for constructor.
+ */
+ enum PMDictMode { PMDReservedWords, PMDDirectives };
+ /**
+ * Creates a dictionary for povray reserved words or directives.
+ */
+ PMReservedWordDict( PMDictMode mode );
+ /**
+ * Deletes the dictionary
+ */
+ ~PMReservedWordDict( );
+
+ /**
+ * Returns the token constant for the key if found, otherwise -1
+ */
+ int operator[] ( const char* key ) const { return find( key ); }
+ /**
+ * Returns the token constant for the key if found, otherwise -1
+ */
+ int find( const char* key ) const
+ {
+ int* result = QAsciiDict<int>::find( key );
+ if( result )
+ return *result;
+ return -1;
+ }
+};
+
+
+/**
+ * Scanner that scans povray tokens out of a QIODevice
+ */
+class PMScanner
+{
+public:
+ /**
+ * Creates a scanner that scans the QIODevice device
+ */
+ PMScanner( QIODevice* device );
+ /**
+ * Deletes the scanner
+ */
+ ~PMScanner( );
+
+ /**
+ * Scans the device for the next token. Returns a value of @ref PMToken
+ * ( > 0xFF ) or a single character
+ */
+ int nextToken( );
+ /**
+ * Returns the current token
+ */
+ int currentToken( ) const { return m_token; }
+
+ /**
+ * Returns the integer value of the current token if currentToken
+ * is INTEGER_TOK
+ */
+ int iValue( ) const { return m_ivalue; }
+ /**
+ * Returns the double value of the current token if currentToken
+ * is FLOAT_TOK
+ */
+ double fValue( ) const { return m_fvalue; }
+ /**
+ * Returns the string value of the current token if currentToken
+ * is ID_TOK, COMMENT_TOK, STRING_TOK
+ */
+ const char* sValue( ) const { return m_svalue; }
+ /**
+ * Returns the current line number
+ */
+ int currentLine( ) const { return m_line; }
+ /**
+ * Returns the error string if current token is SCANNER_ERROR_TOK
+ */
+ QString error( ) const { return m_error; }
+ /**
+ * Special parse method for a function statement
+ */
+ void scanFunction( );
+ /**
+ * Returns a pointer to a dictionary with reserved words
+ */
+ static PMReservedWordDict* reservedWords( ) { return &m_reservedWords; }
+ /**
+ * Returns a pointer to a dictionary with directives
+ */
+ static PMReservedWordDict* directives( ) { return &m_directives; }
+private:
+ /**
+ * returns true if c is one of the following characters:
+ * space, tab, newline, '{', '}', '<', '>', '+', '-', '*', '/', ',',
+ * '(', ')', '=', '[', ']', ';'
+ */
+ inline bool isseparation( int c );
+ /**
+ * Called on unexpected character
+ */
+ void scanError( int c );
+ /**
+ * Reads the next character out of the device
+ */
+ inline void nextChar( );
+ /**
+ * Adds the char to m_svalue
+ */
+ inline void addChar( char c );
+ /**
+ * Clears m_svalue
+ */
+ inline void clearSValue( );
+
+ static PMReservedWordDict m_reservedWords;
+ static PMReservedWordDict m_directives;
+
+ /**
+ * States for the state machine of the scanner
+ */
+ enum PMScanStates
+ {
+ START_ST = 0, ID_ENDST, INTEGER_ENDST,
+ FLOAT1_ST, FLOAT_ENDST, FLOAT_EXP1_ST, FLOAT_EXP2_ST, FLOAT_EXP_ENDST,
+ POINT_ST,
+ DIRECTIVE1_ST, DIRECTIVE_ENDST,
+ STRING1_ST, STRINGBS_ST,
+ SLASH_ST, LINE_COMMENT_FIRST_ST, LINE_COMMENT_ST,
+ C_COMMENT_ST, COMMENT_ST_ST, COMMENT_SL_ST, COMMENT_NEW_LINE_ST,
+ PMNAME_ST,
+ RAW_POVRAY_FIRST_ST, RAW_POVRAY_LB_ST, RAW_POVRAY_ST, RAW_POVRAY_END_ST,
+ RAW_POVRAY_END_END_ST,
+ TOKEN_END_ST
+ };
+
+ QIODevice* m_pDevice;
+
+ int m_char;
+ int m_token;
+ int m_ivalue;
+ double m_fvalue;
+ char* m_svalue;
+ char* m_lastChar;
+ char* m_lastAlloc;
+ unsigned int m_svalueAlloc;
+ int m_indentation;
+ int m_rawIndentation;
+ int m_rawPovrayEnd;
+ bool m_bFunctionMode;
+
+ int m_line;
+ QString m_error;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmscene.cpp b/kpovmodeler/pmscene.cpp
new file mode 100644
index 00000000..b8de8eef
--- /dev/null
+++ b/kpovmodeler/pmscene.cpp
@@ -0,0 +1,119 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmscene.h"
+#include <klocale.h>
+#include <qdom.h>
+#include "pmxmlhelper.h"
+#include "pmdocumentformat.h"
+
+const int c_defaultVisibilityLevel = 10;
+PMMetaObject* PMScene::s_pMetaObject = 0;
+PMObject* createNewScene( PMPart* part )
+{
+ return new PMScene( part );
+}
+
+PMScene::PMScene( PMPart* part )
+ : Base( part )
+{
+ m_visibilityLevel = c_defaultVisibilityLevel;
+}
+
+PMScene::PMScene( const PMScene& s )
+ : Base( s )
+{
+ m_visibilityLevel = s.m_visibilityLevel;
+}
+
+PMScene::~PMScene( )
+{
+ m_renderModes.setAutoDelete( true );
+ m_renderModes.clear( );
+}
+
+QString PMScene::description( ) const
+{
+ return i18n( "scene" );
+}
+
+PMMetaObject* PMScene::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Scene", Base::metaObject( ),
+ createNewScene );
+ }
+ return s_pMetaObject;
+}
+
+void PMScene::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMScene::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "majorFormat", c_majorDocumentFormat );
+ e.setAttribute( "minorFormat", c_minorDocumentFormat );
+ e.setAttribute( "visibility_level", m_visibilityLevel );
+ QDomElement data = doc.createElement( "extra_data" );
+ QDomElement rm;
+
+ PMRenderModeListIterator it( m_renderModes );
+ for( ; it.current( ); ++it )
+ {
+ rm = doc.createElement( "rendermode" );
+ it.current( )->serialize( rm );
+ data.appendChild( rm );
+ }
+
+ e.appendChild( data );
+ Base::serialize( e, doc );
+}
+
+void PMScene::readAttributes( const PMXMLHelper& h )
+{
+ m_visibilityLevel = h.intAttribute( "visibility_level", c_defaultVisibilityLevel );
+ QDomElement e = h.extraData( );
+ if( !e.isNull( ) )
+ {
+ QDomNode c = e.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ if( ce.tagName( ) == "rendermode" )
+ m_renderModes.append( new PMRenderMode( ce ) );
+ }
+ c = c.nextSibling( );
+ }
+ }
+
+ if( m_renderModes.count( ) > 0 )
+ m_renderModes.at( 0 );
+
+ Base::readAttributes( h );
+}
+
diff --git a/kpovmodeler/pmscene.h b/kpovmodeler/pmscene.h
new file mode 100644
index 00000000..2932c43c
--- /dev/null
+++ b/kpovmodeler/pmscene.h
@@ -0,0 +1,92 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSCENE_H
+#define PMSCENE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcompositeobject.h"
+#include "pmrendermode.h"
+
+/**
+ * Class for povray scenes.
+ *
+ * A document has a PMScene object as top level object. A PMScene can't have
+ * a parent
+ */
+class PMScene : public PMCompositeObject
+{
+ typedef PMCompositeObject Base;
+public:
+ /**
+ * Creates an empty PMScene
+ */
+ PMScene( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMScene( const PMScene& s );
+ /**
+ * deletes the scene and all objects
+ */
+ virtual ~PMScene( );
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMScene( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmscene" ); }
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a pointer to the list of render modes
+ * @see PMRenderMode
+ */
+ PMRenderModeList* renderModes( ) { return &m_renderModes; }
+ /**
+ * Returns the scenes visibility level
+ */
+ int visibilityLevel( ) const { return m_visibilityLevel; }
+ /**
+ * Sets the visibility level
+ */
+ void setVisibilityLevel( int l ) { m_visibilityLevel = l; }
+
+private:
+ PMRenderModeList m_renderModes;
+ int m_visibilityLevel;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmserializer.cpp b/kpovmodeler/pmserializer.cpp
new file mode 100644
index 00000000..087631cc
--- /dev/null
+++ b/kpovmodeler/pmserializer.cpp
@@ -0,0 +1,93 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmserializer.h"
+#include "pmerrorflags.h"
+#include "pmdebug.h"
+
+#include <klocale.h>
+
+unsigned int PMSerializer::s_maxErrors = 30;
+unsigned int PMSerializer::s_maxWarnings = 50;
+
+
+PMSerializer::PMSerializer( QIODevice* dev )
+{
+ m_pDev = dev;
+ m_errors = 0;
+ m_warnings = 0;
+ m_bFatalError = false;
+}
+
+PMSerializer::~PMSerializer( )
+{
+
+}
+
+void PMSerializer::serializeList( const PMObjectList& objects )
+{
+ PMObjectListIterator it( objects );
+ for( ; it.current( ); ++it )
+ serialize( it.current( ) );
+}
+
+int PMSerializer::errorFlags( ) const
+{
+ int result = 0;
+ if( errors( ) )
+ result |= PMEError;
+ if( warnings( ) )
+ result |= PMEWarning;
+ if( fatal( ) )
+ result |= PMEFatal;
+ return result;
+}
+
+void PMSerializer::printMessage( const QString& type, const QString& msg )
+{
+ m_messages += PMMessage( type + ": " + msg );
+}
+
+void PMSerializer::printError( const QString& msg )
+{
+ if( m_errors < s_maxErrors )
+ {
+ printMessage( i18n( "Error" ), msg );
+ m_errors++;
+ }
+ else if( m_errors == s_maxErrors )
+ {
+ m_messages += PMMessage( i18n( "Maximum of %1 errors reached." )
+ .arg( s_maxErrors ) );
+ m_errors++;
+ }
+}
+
+void PMSerializer::printWarning( const QString& msg )
+{
+ if( m_warnings < s_maxWarnings )
+ {
+ printMessage( i18n( "Warning" ), msg );
+ m_warnings++;
+ }
+ else if( m_warnings == s_maxWarnings )
+ {
+ m_messages += PMMessage( i18n( "Maximum of %1 warnings reached." )
+ .arg( s_maxWarnings ) );
+ m_warnings++;
+ }
+}
diff --git a/kpovmodeler/pmserializer.h b/kpovmodeler/pmserializer.h
new file mode 100644
index 00000000..73e509d8
--- /dev/null
+++ b/kpovmodeler/pmserializer.h
@@ -0,0 +1,179 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMSERIALIZER_H
+#define PMSERIALIZER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+class QIODevice;
+
+#include "pmobject.h"
+#include "pmerrordialog.h"
+
+#include <qdict.h>
+
+
+/**
+ * Class to serialize an object or a list of objects.
+ *
+ * Normally you don't have to create instances of this type or subclasses,
+ * the class @ref PMIOFormat has factory methods to create them.
+ *
+ * There is one sub class for each format.
+ *
+ * During serialization, errors can occur. These are returned
+ * by the method @ref errors.
+ */
+class PMSerializer
+{
+public:
+ /**
+ * Default constructor
+ *
+ * The serialized data will be written to the io device
+ */
+ PMSerializer( QIODevice* dev );
+ /**
+ * Destructor
+ */
+ virtual ~PMSerializer( );
+ /**
+ * Returns the translated description of the format. Should return
+ * the same string as description( ) of the corresponding
+ * IO format.
+ */
+ virtual QString description( ) const = 0;
+
+ /**
+ * Serializes one object to the device
+ */
+ virtual void serialize( PMObject* o ) = 0;
+ /**
+ * Serializes a list of objects. The default
+ * implementation will call serialize( PMObject* ) for each object.
+ */
+ virtual void serializeList( const PMObjectList& objects );
+ /**
+ * Closes the serializer
+ */
+ virtual void close( ) = 0;
+
+ /**
+ * Returns the messages of the serializer
+ */
+ PMMessageList messages( ) const { return m_messages; }
+ /**
+ * Returns true if there were errors during serializing
+ */
+ bool errors( ) const { return m_errors > 0; }
+ /**
+ * Returns true if there were warnings during serializing
+ */
+ bool warnings( ) const { return m_warnings > 0; }
+ /**
+ * Returns true, if a fatal error occurred
+ * and it doesn't make sense to continue
+ */
+ bool fatal( ) const { return m_bFatalError; }
+ /**
+ * Returns a bitwise combination of @ref PMErrorFlags constants
+ */
+ int errorFlags( ) const;
+
+ /**
+ * Adds an error to the message string
+ */
+ void printError( const QString& msg );
+ /**
+ * Adds a warning to the message string
+ */
+ void printWarning( const QString& msg );
+ /**
+ * Adds an info to the message string
+ */
+ void printInfo( const QString& msg );
+ /**
+ * Adds the message to the message string. Type is "error", "warning",
+ * "info"
+ */
+ void printMessage( const QString& type, const QString& msg );
+
+ /**
+ * Sets the fatal error flag
+ */
+ void setFatalError( ) { m_bFatalError = true; }
+
+ /**
+ * returns the maximum number of errors
+ */
+ static unsigned maxErrors( ) { return s_maxErrors; }
+ /**
+ * sets the maximum number of errors to m
+ */
+ static void setMaxErrors( unsigned m ) { s_maxErrors = m; }
+ /**
+ * returns the maximum number of warnings
+ */
+ static unsigned maxWarnings( ) { return s_maxWarnings; }
+ /**
+ * sets the maximum number of warnings to m
+ */
+ static void setMaxWarnings( unsigned m ) { s_maxWarnings = m; }
+
+protected:
+ /**
+ * The assigned IO device for serialization
+ */
+ QIODevice* m_pDev;
+
+private:
+ /**
+ * The serializer output (errors, warnings...)
+ */
+ PMMessageList m_messages;
+ /**
+ * A dictionary object -> message
+ */
+ QPtrDict< QPtrList<PMMessage> > m_messageDict;
+ /**
+ * Number of warnings during parsing
+ */
+ unsigned int m_warnings;
+ /**
+ * Number of errors during parsing
+ */
+ unsigned int m_errors;
+ /**
+ * Flag for fatal errors
+ */
+ bool m_bFatalError;
+
+ /**
+ * maximum number of errors
+ */
+ static unsigned int s_maxErrors;
+ /**
+ * maximum number of warnings
+ */
+ static unsigned int s_maxWarnings;
+};
+
+#endif
diff --git a/kpovmodeler/pmsettingsdialog.cpp b/kpovmodeler/pmsettingsdialog.cpp
new file mode 100644
index 00000000..898719bc
--- /dev/null
+++ b/kpovmodeler/pmsettingsdialog.cpp
@@ -0,0 +1,263 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmsettingsdialog.h"
+
+#include "pmpovraysettings.h"
+#include "pmcolorsettings.h"
+#include "pmgridsettings.h"
+#include "pmobjectsettings.h"
+#include "pmpreviewsettings.h"
+#include "pmlayoutsettings.h"
+#include "pmobjectlibrarysettings.h"
+#include "pmpluginsettings.h"
+#include "pmopenglsettings.h"
+
+#include "pmrendermanager.h"
+#include "pmdebug.h"
+
+#include <qvbox.h>
+#include <qlistview.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+
+//#define KPM_WITH_OBJECT_LIBRARY
+
+PMSettingsDialogPage::PMSettingsDialogPage( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+}
+
+QSize PMSettingsDialog::s_size = QSize( 640, 400 );
+
+PMSettingsDialog::PMSettingsDialog( PMPart* part, QWidget* parent, const char* name )
+ : KDialogBase( TreeList, i18n( "Configure" ), Ok | Apply | Cancel | Default, Ok,
+ parent, name )
+{
+ QStringList sl;
+ QWidget* w = 0;
+ PMSettingsDialogPage* p = 0;
+
+ m_pPart = part;
+
+ setShowIconsInTreeList( true );
+
+ sl.clear( );
+ sl.append( i18n( "Povray" ) );
+ w = addVBoxPage( sl, i18n( "Povray Options" ),
+ SmallIcon( "pmconfigurepovray", 22 ) );
+ p = new PMPovraySettings( w );
+ registerPage( w, p );
+
+ sl.clear( );
+ sl.append( i18n( "Graphical View" ) );
+ sl.append( i18n( "OpenGL" ) );
+ w = addVBoxPage( sl, i18n( "OpenGL Display Settings" ),
+ SmallIcon( "pmconfigureopengl", 22 ) );
+ p = new PMOpenGLSettings( w );
+ registerPage( w, p );
+
+ sl.clear( );
+ sl.append( i18n( "Graphical View" ) );
+ setFolderIcon( sl, SmallIcon( "pmconfiguregraphicalview", 22 ) );
+ sl.append( i18n( "Colors" ) );
+ w = addVBoxPage( sl, i18n( "Color Settings" ),
+ SmallIcon( "pmconfigurecolors", 22 ) );
+ p = new PMColorSettings( w );
+ registerPage( w, p );
+
+ sl.clear( );
+ sl.append( i18n( "Graphical View" ) );
+ sl.append( i18n( "Grid" ) );
+ w = addVBoxPage( sl, i18n( "Grid Settings" ),
+ SmallIcon( "pmconfiguregrid", 22 ) );
+ p = new PMGridSettings( w );
+ registerPage( w, p );
+
+ sl.clear( );
+ sl.append( i18n( "Graphical View" ) );
+ sl.append( i18n( "Objects" ) );
+ w = addVBoxPage( sl, i18n( "Display Settings for Objects" ),
+ SmallIcon( "pmconfigureobjects", 22 ) );
+ p = new PMObjectSettings( w );
+ registerPage( w, p );
+
+ sl.clear( );
+ sl.append( i18n( "Properties View" ) );
+ setFolderIcon( sl, SmallIcon( "pmconfiguredialogview", 22 ) );
+ sl.append( i18n( "Texture Preview" ) );
+ w = addVBoxPage( sl, i18n( "Display Settings for Texture Previews" ),
+ SmallIcon( "pmconfiguretexturepreview", 22 ) );
+ p = new PMPreviewSettings( w );
+ registerPage( w, p );
+
+ sl.clear( );
+ sl.append( i18n( "View Layout" ) );
+ w = addVBoxPage( sl, i18n( "Display Settings for View Layouts" ),
+ SmallIcon( "pmconfigureviewlayout", 22 ) );
+ p = new PMLayoutSettings( w );
+ registerPage( w, p );
+
+#ifdef KPM_WITH_OBJECT_LIBRARY
+ sl.clear( );
+ sl.append( i18n( "Object Libraries" ) );
+ w = addVBoxPage( sl, i18n( "Display Settings for Object Libraries" ),
+ SmallIcon( "pmconfigureobjectlibrary", 22 ) );
+ p = new PMObjectLibrarySettings( w );
+ registerPage( w, p );
+#endif
+
+#ifdef KPM_WITH_PLUGINS
+ sl.clear( );
+ sl.append( i18n( "Plugins" ) );
+ w = addVBoxPage( sl, i18n( "Plugin Settings" ) );
+ p = new PMPluginSettings( w );
+ registerPage( w, p );
+#endif
+
+ displaySettings( );
+
+ resize( s_size );
+}
+
+void PMSettingsDialog::displaySettings( )
+{
+ QValueList<PMRegisteredSettingsPage>::const_iterator it;
+ for( it = m_pages.begin( ); it != m_pages.end( ); ++it )
+ ( *it ).page->displaySettings( );
+}
+
+void PMSettingsDialog::slotCancel( )
+{
+ QDialog::reject( );
+}
+
+void PMSettingsDialog::slotApply( )
+{
+ if( validateData( ) )
+ saveSettings( );
+}
+
+void PMSettingsDialog::slotOk( )
+{
+ if( validateData( ) )
+ {
+ saveSettings( );
+ QDialog::accept( );
+ }
+}
+
+void PMSettingsDialog::slotDefault( )
+{
+ int currentPage = activePageIndex( );
+ PMSettingsDialogPage* page = 0;
+ QValueList<PMRegisteredSettingsPage>::const_iterator it;
+ for( it = m_pages.begin( ); it != m_pages.end( ) && !page; ++it )
+ if( ( *it ).index == currentPage )
+ page = ( *it ).page;
+ if( page )
+ page->displayDefaults( );
+}
+
+bool PMSettingsDialog::validateData( )
+{
+ bool valid = true;
+ QValueList<PMRegisteredSettingsPage>::const_iterator it;
+ for( it = m_pages.begin( ); it != m_pages.end( ) && valid; ++it )
+ valid = ( *it ).page->validateData( );
+ return valid;
+}
+
+void PMSettingsDialog::saveSettings( )
+{
+ m_repaint = false;
+
+ QValueList<PMRegisteredSettingsPage>::const_iterator it;
+ for( it = m_pages.begin( ); it != m_pages.end( ); ++it )
+ ( *it ).page->applySettings( );
+
+ if( m_repaint )
+ {
+ PMRenderManager* rm = PMRenderManager::theManager( );
+ rm->slotRenderingSettingsChanged( );
+ }
+}
+
+void PMSettingsDialog::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+ cfg->writeEntry( "SettingsDialogSize", s_size );
+}
+
+void PMSettingsDialog::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+
+ QSize defaultSize( 640, 400 );
+ s_size = cfg->readSizeEntry( "SettingsDialogSize", &defaultSize );
+}
+
+void PMSettingsDialog::resizeEvent( QResizeEvent* ev )
+{
+ s_size = ev->size( );
+}
+
+void PMSettingsDialog::registerPage( QWidget* topPage,
+ PMSettingsDialogPage* page )
+{
+ int i = pageIndex( topPage );
+ if( i < 0 )
+ kdError( PMArea ) << "PMSettingsDialog: Registered settings page"
+ << " not found" << endl;
+ else
+ {
+ m_pages.push_back( PMRegisteredSettingsPage( topPage, page, i ) );
+ connect( page, SIGNAL( repaintViews( ) ), SLOT( slotRepaint( ) ) );
+ connect( page, SIGNAL( showMe( ) ), SLOT( slotShowPage( ) ) );
+ }
+}
+
+void PMSettingsDialog::slotRepaint( )
+{
+ m_repaint = true;
+}
+
+void PMSettingsDialog::slotShowPage( )
+{
+ const QObject* w = sender( );
+ if( w )
+ {
+ int index = findPage( ( const PMSettingsDialogPage* ) w );
+ if( index >= 0 )
+ showPage( index );
+ }
+}
+
+int PMSettingsDialog::findPage( const PMSettingsDialogPage* p )
+{
+ int index = -1;
+ QValueList<PMRegisteredSettingsPage>::const_iterator it;
+ for( it = m_pages.begin( ); it != m_pages.end( ) && index < 0; ++it )
+ if( ( *it ).page == p )
+ index = ( *it ).index;
+ return index;
+}
+
+#include "pmsettingsdialog.moc"
diff --git a/kpovmodeler/pmsettingsdialog.h b/kpovmodeler/pmsettingsdialog.h
new file mode 100644
index 00000000..09f00973
--- /dev/null
+++ b/kpovmodeler/pmsettingsdialog.h
@@ -0,0 +1,187 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMSETTINGSDIALOG_H
+#define PMSETTINGSDIALOG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+#include <qvaluelist.h>
+#include <qvaluevector.h>
+
+class QFrame;
+class QCheckBox;
+class QLineEdit;
+class QListBox;
+class QListView;
+class QButtonGroup;
+class QComboBox;
+class KColorButton;
+class KConfig;
+class PMIntEdit;
+class PMFloatEdit;
+class PMPart;
+class PMViewLayout;
+class PMViewLayoutEntry;
+
+/**
+ * Base class for configuration dialog pages.
+ *
+ * All base classes have to implement the pure virtual
+ * methods @ref displaySettings, @ref displayDefaults, @ref validateData
+ * and @ref applySettings
+ */
+class PMSettingsDialogPage : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor
+ */
+ PMSettingsDialogPage( QWidget* parent, const char* name = 0 );
+ /**
+ * Display the settings here.
+ *
+ * Base classes have to implement this method.
+ */
+ virtual void displaySettings( ) = 0;
+ /**
+ * Validate the changed data here and return true
+ * if the data is valid. Display an error message
+ * and return false otherwise.
+ *
+ * Base classes have to implement this method.
+ */
+ virtual bool validateData( ) = 0;
+ /**
+ * Make the changes permanent here.
+ *
+ * Base classes have to implement this method.
+ */
+ virtual void applySettings( ) = 0;
+ /**
+ * Display the default values.
+ *
+ * Base classes have to implement this method.
+ */
+ virtual void displayDefaults( ) = 0;
+signals:
+ /**
+ * Emit this signal if a parameter was changed
+ * that influences the wire frame rendering.
+ */
+ void repaintViews( );
+ /**
+ * Tells the settings dialog to show this page.
+ */
+ void showMe( );
+};
+
+
+/**
+ * Helper class, used internally by @ref PMSettingsDialog
+ */
+class PMRegisteredSettingsPage
+{
+public:
+ PMRegisteredSettingsPage( )
+ {
+ topPage = 0;
+ page = 0;
+ index = 0;
+ }
+ PMRegisteredSettingsPage( QWidget* top, PMSettingsDialogPage* p,
+ int i )
+ {
+ topPage = top;
+ page = p;
+ index = i;
+ }
+ QWidget* topPage;
+ PMSettingsDialogPage* page;
+ int index;
+};
+
+/**
+ * Configuration dialog
+ */
+class PMSettingsDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Standard constructor
+ */
+ PMSettingsDialog( PMPart* part, QWidget* parent = 0, const char* name = 0 );
+ /**
+ * Registers a new settings page.
+ *
+ * @param topPage The page created with addVBoxPage
+ * @param page The internal settings page
+ */
+ void registerPage( QWidget* topPage, PMSettingsDialogPage* page );
+
+ static void saveConfig( KConfig* cfg );
+ static void restoreConfig( KConfig* cfg );
+
+protected:
+ virtual void resizeEvent( QResizeEvent* ev );
+
+protected slots:
+ /**
+ * Validates the data and makes the changes permanent.
+ */
+ virtual void slotApply( );
+ /**
+ * Validates the data, makes the changes permanent and closes the dialog.
+ */
+ virtual void slotOk( );
+ /**
+ * Displays the default values.
+ */
+ virtual void slotDefault( );
+ /**
+ * Closes the dialog without saving the data.
+ */
+ virtual void slotCancel( );
+
+ /**
+ * Repaints the opengl views
+ */
+ void slotRepaint( );
+ /**
+ * Shows the sender page
+ */
+ void slotShowPage( );
+
+private:
+ void displaySettings( );
+ bool validateData( );
+ void saveSettings( );
+ int findPage( const PMSettingsDialogPage* page );
+ bool m_repaint;
+ QValueList<PMRegisteredSettingsPage> m_pages;
+ PMPart* m_pPart;
+
+ static QSize s_size;
+};
+
+#endif
diff --git a/kpovmodeler/pmshell.cpp b/kpovmodeler/pmshell.cpp
new file mode 100644
index 00000000..52702492
--- /dev/null
+++ b/kpovmodeler/pmshell.cpp
@@ -0,0 +1,676 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include <klocale.h>
+#include <khelpmenu.h>
+#include <kstdaction.h>
+#include <kaction.h>
+#include <kstatusbar.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <kedittoolbar.h>
+#include <kkeydialog.h>
+#include <kaboutdialog.h>
+#include <kpopupmenu.h>
+#include <qtimer.h>
+
+#include "pmshell.h"
+#include "pmpart.h"
+#include "pmfactory.h"
+#include "pmsettingsdialog.h"
+#include "pmdefaults.h"
+#include "pmdockwidget.h"
+
+#include "pmviewfactory.h"
+#include "pmviewbase.h"
+#include "pmunknownview.h"
+#include "pmviewlayoutmanager.h"
+
+//#define KPM_WITH_OBJECT_LIBRARY
+
+const int c_statusBarInfo = 0;
+const int c_statusBarControlPoints = 1;
+
+PMShell::PMShell( const KURL& url )
+ : PMDockMainWindow( 0, "mainwindow" )
+{
+ setPluginLoadingMode( DoNotLoadPlugins );
+ setInstance( PMFactory::instance( ), false );
+
+ m_pPart = new PMPart( this, "part", this, "part", true, this );
+ m_pPart->setReadWrite( ); // read-write mode
+ m_viewNumber = 0;
+ m_objectsToDelete.setAutoDelete( true );
+
+ if (!initialGeometrySet())
+ resize(800,600);
+
+ setupActions( );
+
+ restoreOptions( );
+
+ setupView( );
+ setXMLFile( "kpovmodelershell.rc" );
+ createGUI( m_pPart );
+
+ //guiFactory( )->addClient( m_pPart );
+ m_pStatusBar = statusBar( );
+ m_pStatusBar->insertItem( " ", c_statusBarInfo, 1 );
+ m_pStatusBar->insertItem( "" , c_statusBarControlPoints );
+
+ KConfig* config = instance( )->config( );
+ config->setGroup( "Appearance" );
+ applyMainWindowSettings( config );
+
+ if( !url.isEmpty( ) )
+ openURL( url );
+
+ setCaption( url.prettyURL( ) );
+ connect( m_pPart, SIGNAL( modified( ) ), SLOT( slotModified( ) ) );
+ connect( m_pPart, SIGNAL( controlPointMessage( const QString& ) ),
+ SLOT( slotControlPointMsg( const QString& ) ) );
+}
+
+PMShell::~PMShell( )
+{
+}
+
+void PMShell::setupActions( )
+{
+// m_helpMenu = new KHelpMenu( this, PMFactory::aboutData( ), true,
+// actionCollection( ) );
+
+ KStdAction::openNew( this, SLOT( slotFileNew( ) ), actionCollection( ) );
+ KStdAction::open( this, SLOT( slotFileOpen( ) ), actionCollection( ) );
+ m_pRecent = KStdAction::openRecent( this, SLOT( slotOpenRecent( const KURL& ) ),
+ actionCollection( ) );
+ KStdAction::save( this, SLOT( slotFileSave( ) ), actionCollection( ) );
+ KStdAction::saveAs( this, SLOT( slotFileSaveAs( ) ), actionCollection( ) );
+
+ KStdAction::revert( this, SLOT( slotFileRevert( ) ), actionCollection( ) );
+ KStdAction::print( this, SLOT( slotFilePrint( ) ), actionCollection( ) );
+
+ KStdAction::close( this, SLOT( slotFileClose( ) ), actionCollection( ) );
+ KStdAction::quit( this, SLOT( close( ) ), actionCollection( ) );
+
+ m_pPathAction = new KToggleAction( i18n( "Show &Path" ), 0, this,
+ SLOT( slotShowPath( ) ), actionCollection( ),
+ "options_show_path" );
+ m_pPathAction->setCheckedState(i18n("Hide &Path"));
+
+ m_pStatusbarAction = KStdAction::showStatusbar( this, SLOT( slotShowStatusbar( ) ),
+ actionCollection( ) );
+
+ KStdAction::saveOptions( this, SLOT( saveOptions( ) ), actionCollection( ) );
+
+ KStdAction::keyBindings( this, SLOT( slotConfigureKeys( ) ),
+ actionCollection( ) );
+ KStdAction::configureToolbars( this, SLOT( slotConfigureToolbars( ) ),
+ actionCollection( ) );
+ KStdAction::preferences( this, SLOT( slotSettings( ) ), actionCollection( ) );
+
+ m_pNewTopViewAction = new KAction( i18n( "New Top View" ), 0, this,
+ SLOT( slotNewTopView( ) ),
+ actionCollection( ), "view_new_topview" );
+ m_pNewBottomViewAction = new KAction( i18n( "New Bottom View" ), 0, this,
+ SLOT( slotNewBottomView( ) ),
+ actionCollection( ), "view_new_bottomview" );
+ m_pNewLeftViewAction = new KAction( i18n( "New Left View" ), 0, this,
+ SLOT( slotNewLeftView( ) ),
+ actionCollection( ), "view_new_leftview" );
+ m_pNewRightViewAction = new KAction( i18n( "New Right View" ), 0, this,
+ SLOT( slotNewRightView( ) ),
+ actionCollection( ), "view_new_rightview" );
+ m_pNewFrontViewAction = new KAction( i18n( "New Front View" ), 0, this,
+ SLOT( slotNewFrontView( ) ),
+ actionCollection( ), "view_new_frontview" );
+ m_pNewBackViewAction = new KAction( i18n( "New Back View" ), 0, this,
+ SLOT( slotNewBackView( ) ),
+ actionCollection( ), "view_new_back_view" );
+ m_pNewCameraViewAction = new KAction( i18n( "New Camera View" ), 0, this,
+ SLOT( slotNewCameraView( ) ),
+ actionCollection( ), "view_new_cameraview" );
+
+ m_pNewTreeViewAction = new KAction( i18n( "New Object Tree" ), 0, this,
+ SLOT( slotNewTreeView( ) ), actionCollection( ),
+ "view_new_treeview" );
+ m_pNewDialogViewAction = new KAction( i18n( "New Properties View" ), 0, this,
+ SLOT( slotNewDialogView( ) ), actionCollection( ),
+ "view_new_dialogview" );
+
+#ifdef KPM_WITH_OBJECT_LIBRARY
+ m_pNewLibraryBrowserAction = new KAction( i18n( "New Library Browser" ), 0, this,
+ SLOT( slotNewLibraryBrowserView( ) ), actionCollection( ),
+ "view_new_librarybrowser" );
+#endif
+
+ // Creating the view layouts menu
+ m_pViewLayoutsAction = new KActionMenu( i18n( "View Layouts" ),
+ actionCollection( ), "view_layouts_menu" );
+ KPopupMenu* menu = m_pViewLayoutsAction->popupMenu( );
+ connect( menu, SIGNAL( aboutToShow( ) ), SLOT( slotViewsMenuAboutToShow( ) ) );
+ PMViewLayoutManager::theManager( )->fillPopupMenu( menu );
+ connect( menu, SIGNAL( activated( int ) ), SLOT( slotSelectedLayout( int ) ) );
+
+ m_pSaveViewLayoutAction = new KAction( i18n( "Save View Layout..." ), 0, this,
+ SLOT( slotSaveViewLayout( ) ),
+ actionCollection( ), "save_view_layout" );
+}
+
+void PMShell::setupView( )
+{
+ PMViewLayoutManager::theManager( )->displayDefaultLayout( this );
+}
+
+
+PMDockWidget* PMShell::createView( const QString& t, PMViewOptions* o,
+ bool initPosition )
+{
+ PMDockWidget* dock = 0;
+ PMViewBase* contents = 0;
+
+ PMViewTypeFactory* factory =
+ PMViewFactory::theFactory( )->viewFactory( t );
+
+ m_viewNumber++;
+ QString name = QString( "View (%1)" ).arg( m_viewNumber );
+
+ if( factory )
+ {
+ QString desc;
+ // Create the appropriate dock widget
+ if( o )
+ desc = factory->description( o );
+ else
+ desc = factory->description( );
+
+ dock = createDockWidget( name, SmallIcon( factory->iconName( ) ), 0L,
+ desc, desc );
+ contents = factory->newInstance( dock, m_pPart );
+ if( o )
+ contents->restoreViewConfig( o );
+ }
+ else
+ {
+ // unknown view type
+ dock = createDockWidget( name, SmallIcon( "unknown" ), 0L,
+ i18n( "Unknown" ), i18n( "Unknown" ) );
+ contents = new PMUnknownView( t, dock );
+ }
+
+ dock->setWidget( contents );
+ connect( dock, SIGNAL( headerCloseButtonClicked( ) ),
+ SLOT( slotDockWidgetClosed( ) ) );
+
+ if( initPosition )
+ {
+ dock->resize( 300, 400 );
+ dock->manualDock( 0, PMDockWidget::DockDesktop, 50,
+ mapToGlobal( QPoint( 50, 50 ) ) );
+ }
+ return dock;
+}
+
+/*
+PMDockWidget* PMShell::createTreeView( )
+{
+ PMDockWidget* dock = 0;
+ m_numTreeViews++;
+ QString name = QString( "Object Tree (%1)" ).arg( m_numTreeViews );
+ dock = createDockWidget( name, SmallIcon( "pmtreeview" ),
+ 0L, i18n( "Object Tree" ), i18n( "Object Tree" ) );
+ dock->setDockSite( PMDockWidget::DockFullSite );
+ PMTreeView* tv = new PMTreeView( m_pPart, dock );
+ dock->setWidget( tv );
+
+ connect( dock, SIGNAL( headerCloseButtonClicked( ) ),
+ SLOT( slotDockWidgetClosed( ) ) );
+
+ return dock;
+}
+
+PMDockWidget* PMShell::createDialogView( )
+{
+ PMDockWidget* dock = 0;
+ m_numDialogViews++;
+ QString name = QString( "Object Properties (%1)" ).arg( m_numDialogViews );
+ dock = createDockWidget( name, SmallIcon( "pmdialogview" ),
+ 0L, i18n( "Object Properties" ), i18n( "Object Properties" ) );
+ dock->setDockSite( PMDockWidget::DockFullSite );
+ PMDialogView* dv = new PMDialogView( m_pPart, dock );
+ dock->setWidget( dv );
+
+ connect( dock, SIGNAL( headerCloseButtonClicked( ) ),
+ SLOT( slotDockWidgetClosed( ) ) );
+
+ return dock;
+}
+
+PMDockWidget* PMShell::create3DView( PMGLView::PMViewType t )
+{
+ PMDockWidget* dock = 0;
+ m_numGLViews++;
+ QString name = QString( "3D View (%1)" ).arg( m_numGLViews );
+ dock = createDockWidget( name, SmallIcon( "pmglview" ),
+ 0L, i18n( "3D View" ), i18n( "3D View" ) );
+ dock->setDockSite( PMDockWidget::DockFullSite );
+ PMGLView* vgl = new PMGLView( m_pPart, t, dock );
+ dock->setWidget( vgl );
+ connect( vgl, SIGNAL( viewTypeChanged( const QString& ) ),
+ dock, SLOT( slotSetCaption( const QString& ) ) );
+ dock->slotSetCaption( PMGLView::viewTypeAsString( t ) );
+
+ connect( dock, SIGNAL( headerCloseButtonClicked( ) ),
+ SLOT( slotDockWidgetClosed( ) ) );
+
+ return dock;
+}
+*/
+
+void PMShell::slotNewGraphicalView( PMGLView::PMViewType t )
+{
+ PMGLViewOptions* o = new PMGLViewOptions( t );
+ createView( "glview", o );
+ delete o;
+}
+
+void PMShell::slotNewTopView( )
+{
+ slotNewGraphicalView( PMGLView::PMViewNegY );
+}
+
+void PMShell::slotNewBottomView( )
+{
+ slotNewGraphicalView( PMGLView::PMViewPosY );
+}
+
+void PMShell::slotNewLeftView( )
+{
+ slotNewGraphicalView( PMGLView::PMViewPosX );
+}
+
+void PMShell::slotNewRightView( )
+{
+ slotNewGraphicalView( PMGLView::PMViewNegX );
+}
+
+void PMShell::slotNewFrontView( )
+{
+ slotNewGraphicalView( PMGLView::PMViewPosZ );
+}
+
+void PMShell::slotNewBackView( )
+{
+ slotNewGraphicalView( PMGLView::PMViewNegZ );
+}
+
+void PMShell::slotNewCameraView( )
+{
+ slotNewGraphicalView( PMGLView::PMViewCamera );
+}
+
+void PMShell::slotNewDialogView( )
+{
+ createView( "dialogview" );
+}
+
+void PMShell::slotNewTreeView( )
+{
+ createView( "treeview" );
+}
+
+void PMShell::slotNewLibraryBrowserView( )
+{
+ createView( "librarybrowserview" );
+}
+
+void PMShell::slotDockWidgetClosed( )
+{
+ const QObject* o = sender( );
+ if( o && o->inherits( "PMDockWidget" ) )
+ {
+ if( m_objectsToDelete.containsRef( o ) == 0 )
+ {
+ m_objectsToDelete.append( o );
+ QTimer::singleShot( 0, this, SLOT( slotDeleteClosedObjects( ) ) );
+ }
+ }
+}
+
+void PMShell::slotDeleteClosedObjects( )
+{
+ m_objectsToDelete.clear( );
+}
+
+void PMShell::openURL( const KURL& url )
+{
+ m_pRecent->addURL( url );
+
+ if( !m_pPart->isModified( ) && m_pPart->url( ).isEmpty( ) )
+ {
+ m_pPart->openURL( url );
+ setCaption( m_pPart->url( ).prettyURL( ) );
+ }
+ else
+ {
+ PMShell *shell = new PMShell( );
+ shell->show( );
+ shell->openURL( url );
+ }
+}
+
+void PMShell::slotOpenRecent( const KURL& url )
+{
+ m_openRecentURL = url;
+ QTimer::singleShot( 0, this, SLOT( slotOpenRecentTimer( ) ) );
+}
+
+void PMShell::slotOpenRecentTimer( )
+{
+ openURL( m_openRecentURL );
+}
+
+void PMShell::slotFileNew( )
+{
+ if( !m_pPart->isModified( ) && m_pPart->url( ).isEmpty( ) )
+ {
+ m_pPart->newDocument( );
+ setCaption( );
+ }
+ else
+ {
+ PMShell *shell = new PMShell( );
+ shell->show( );
+ }
+}
+
+void PMShell::slotFileOpen( )
+{
+ KURL url = KFileDialog::getOpenURL(
+ QString::null, QString( "*.kpm|" ) + i18n( "Povray Modeler Files (*.kpm)" )
+ + "\n*|" + i18n( "All Files" ) );
+
+ if( !url.isEmpty( ) )
+ openURL( url );
+}
+
+void PMShell::slotFileSave( )
+{
+ m_pPart->slotAboutToSave( );
+
+ if( m_pPart->isModified( ) )
+ {
+ if( !m_pPart->url( ).isEmpty( ) &&
+ m_pPart->isReadWrite( ) )
+ m_pPart->saveAs( m_pPart->url( ) );
+ else
+ saveAs( );
+ setCaption( m_pPart->url( ).prettyURL( ) );
+ }
+ else
+ emit statusMsg( i18n( "No changes need to be saved" ) );
+}
+
+void PMShell::slotFileSaveAs( )
+{
+ m_pPart->slotAboutToSave( );
+ saveAs( );
+}
+
+void PMShell::saveAs( )
+{
+ KFileDialog dlg( QString::null,
+ QString( "*.kpm|" ) + i18n( "Povray Modeler Files (*.kpm)" ) +
+ QString( "\n*|" ) + i18n( "All Files" ),
+ 0, "filedialog", true );
+ dlg.setCaption( i18n( "Save As" ) );
+ dlg.setOperationMode( KFileDialog::Saving );
+ dlg.exec( );
+
+ KURL url = dlg.selectedURL( );
+
+ if( !url.isEmpty( ) )
+ {
+ if( dlg.currentFilter( ) == QString( "*.kpm" ) )
+ if( QFileInfo( url.path( ) ).extension( ).isEmpty( ) )
+ url.setPath( url.path( ) + ".kpm" );
+
+ if( overwriteURL( url ) )
+ {
+ m_pRecent->addURL( url );
+ if( m_pPart->saveAs( url ) )
+ setCaption( url.prettyURL( ) );
+ else
+ KMessageBox::sorry( this, i18n( "Couldn't save the file." ) );
+ }
+ }
+}
+
+void PMShell::slotFileRevert( )
+{
+ KURL url = m_pPart->url( );
+
+ if( !url.isEmpty( ) )
+ m_pPart->openURL( url );
+// else
+// slotFileNew( );
+}
+
+void PMShell::slotFilePrint( )
+{
+ //TODO
+ // m_pPart->slotPrint( );
+}
+
+void PMShell::slotFileNewWindow( )
+{
+ PMShell* shell = new PMShell;
+ shell->show( );
+}
+
+void PMShell::slotFileClose( )
+{
+ if( m_pPart->closeURL( ) )
+ {
+ m_pPart->closeDocument( );
+ m_pPart->newDocument( );
+ setCaption( );
+ }
+}
+
+void PMShell::slotShowToolbar( )
+{
+ if( toolBar( )->isVisible ( ) )
+ toolBar( )->hide( );
+ else
+ toolBar( )->show( );
+}
+
+void PMShell::slotShowStatusbar( )
+{
+ if( statusBar( )->isVisible ( ) )
+ statusBar( )->hide( );
+ else
+ statusBar( )->show( );
+}
+
+void PMShell::slotShowPath( )
+{
+ setCaption( m_pPart->url( ).prettyURL( ) );
+}
+
+void PMShell::slotConfigureKeys( )
+{
+ KKeyDialog kd;
+ kd.insert( m_pPart->actionCollection( ) );
+ kd.insert( actionCollection( ) );
+ kd.configure( true );
+ //KKeyDialog::configure( actionCollection( ) );
+}
+
+void PMShell::slotSettings( )
+{
+ PMSettingsDialog dlg( m_pPart );
+ dlg.exec( );
+}
+
+void PMShell::slotConfigureToolbars( )
+{
+ saveMainWindowSettings( KGlobal::config( ), "Appearance" );
+ KEditToolbar dlg( factory( ) );
+ connect( &dlg, SIGNAL( newToolbarConfig( ) ),
+ this, SLOT( slotNewToolbarConfig( ) ) );
+ dlg.exec( );
+}
+
+void PMShell::slotNewToolbarConfig( )
+{
+ createGUI( 0 );
+ createShellGUI( false );
+ createGUI( m_pPart );
+ applyMainWindowSettings( KGlobal::config( ), "Appearance" );
+}
+
+void PMShell::updateGUI( )
+{
+ saveMainWindowSettings( KGlobal::config( ), "Appearance" );
+ createGUI( 0 );
+ createShellGUI( false );
+ createGUI( m_pPart );
+ applyMainWindowSettings( KGlobal::config( ), "Appearance" );
+}
+
+void PMShell::saveOptions( )
+{
+ kdDebug( PMArea ) << "Saving configuration" << endl;
+ KConfig* config = KGlobal::config( );
+
+ // set group
+ config->setGroup( "Appearance" );
+ config->writeEntry( "ShowStatusbar", m_pStatusbarAction->isChecked( ) );
+ saveMainWindowSettings( config );
+ m_pRecent->saveEntries( config );
+
+ if( m_pPart )
+ m_pPart->saveConfig( config );
+
+ config->sync( );
+}
+
+void PMShell::restoreOptions( )
+{
+ KConfig* config = instance( )->config( );
+
+ // set group
+ config->setGroup( "Appearance" );
+
+ bool showStatusbar = config->readBoolEntry( "ShowStatusbar", true );
+
+ m_pStatusbarAction->blockSignals( true );
+ m_pStatusbarAction->setChecked( showStatusbar );
+ m_pStatusbarAction->blockSignals( false );
+
+ if( showStatusbar )
+ statusBar( )->show( );
+ else
+ statusBar( )->hide( );
+
+ m_pRecent->loadEntries( config );
+}
+
+void PMShell::setCaption( const QString& caption )
+{
+ QString tmp;
+
+ if( caption.isEmpty( ) )
+ tmp = i18n( "unknown" );
+ else
+ {
+ if( !m_pPathAction->isChecked( ) )
+ tmp = caption.right( caption.length( ) - caption.findRev( '/' ) - 1 );
+ else
+ tmp = caption;
+ }
+
+ KMainWindow::setCaption( tmp, m_pPart->isModified( ) );
+}
+
+void PMShell::statusMsg( const QString& text )
+{
+ m_pStatusBar->message( text, 5000 );
+}
+
+bool PMShell::queryClose( )
+{
+ saveOptions( );
+ return m_pPart->closeURL( );
+}
+
+void PMShell::showEvent( QShowEvent* ){
+ activateDock( );
+}
+
+void PMShell::slotModified( )
+{
+ setCaption( m_pPart->url( ).prettyURL( ) );
+}
+
+void PMShell::slotControlPointMsg( const QString& msg )
+{
+ if( msg.isEmpty( ) )
+ m_pStatusBar->changeItem( msg, c_statusBarControlPoints );
+ else
+ m_pStatusBar->changeItem( QString( " " ) + msg + QString( " " ),
+ c_statusBarControlPoints );
+}
+
+bool PMShell::overwriteURL( const KURL& u )
+{
+ int query = KMessageBox::Continue;
+
+ if( u.isLocalFile( ) )
+ {
+ QFileInfo info;
+ QString name( u.path( ) );
+ info.setFile( name );
+ if( info.exists( ) )
+ query = KMessageBox::warningContinueCancel( 0, i18n( "A file with this name already exists.\nDo you want to overwrite it?" ), QString::null, i18n("Overwrite") );
+ }
+ return ( query == KMessageBox::Continue );
+}
+
+void PMShell::slotSelectedLayout( int id )
+{
+ QMenuItem* menu = m_pViewLayoutsAction->popupMenu( )->findItem( id );
+ PMViewLayoutManager::theManager( )->displayLayout( menu->text( ), this );
+}
+
+void PMShell::slotSaveViewLayout( )
+{
+ PMSaveViewLayoutDialog dlg( this );
+ dlg.exec( );
+}
+
+void PMShell::slotViewsMenuAboutToShow( )
+{
+ KPopupMenu* menu = m_pViewLayoutsAction->popupMenu( );
+
+ PMViewLayoutManager::theManager( )->fillPopupMenu( menu );
+}
+
+#include "pmshell.moc"
diff --git a/kpovmodeler/pmshell.h b/kpovmodeler/pmshell.h
new file mode 100644
index 00000000..9a0dbb91
--- /dev/null
+++ b/kpovmodeler/pmshell.h
@@ -0,0 +1,172 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSHELL_H
+#define PMSHELL_H
+
+#include "pmdockwidget.h"
+
+#include "pmpart.h"
+#include "pmglview.h"
+#include "version.h"
+
+#include <qptrlist.h>
+
+//class KHelpMenu;
+class KStatusBar;
+class KListAction;
+class KToggleAction;
+class KSelectAction;
+class KRecentFilesAction;
+class KActionMenu;
+class PMViewOptions;
+
+/**
+ * Main view for KPovModeler
+ */
+class PMShell : public PMDockMainWindow
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Standard constructor
+ */
+ PMShell( const KURL& = KURL( ) );
+ /**
+ * Destructor
+ */
+ virtual ~PMShell( );
+
+ /**
+ * Creates the actions
+ */
+ void setupActions( );
+ /**
+ * Creates the docking views
+ */
+ void setupView( );
+ /**
+ * Updates the gui (menus and toolbars)
+ */
+ void updateGUI( );
+
+ /**
+ * Checks if a file with that name exists and asks if
+ * it should be overwritten.
+ *
+ * Returns true if the files is not a local file, the file does'n exist
+ * or the file should be overwritten.
+ */
+ static bool overwriteURL( const KURL& u );
+
+public slots:
+ void openURL( const KURL& );
+ void slotOpenRecent( const KURL& );
+ void slotOpenRecentTimer( );
+
+ void slotFileNew( );
+ void slotFileOpen( );
+ void slotFileSave( );
+ void slotFileSaveAs( );
+ void slotFileRevert( );
+ void slotFilePrint( );
+ void slotFileNewWindow( );
+ void slotFileClose( );
+
+ void slotShowToolbar( );
+ void slotShowStatusbar( );
+ void slotShowPath( );
+ void slotConfigureKeys( );
+ void slotConfigureToolbars( );
+ void slotSettings( );
+ void slotNewToolbarConfig( );
+
+ void slotNewGraphicalView( PMGLView::PMViewType );
+ void slotNewTopView( );
+ void slotNewBottomView( );
+ void slotNewLeftView( );
+ void slotNewRightView( );
+ void slotNewFrontView( );
+ void slotNewBackView( );
+ void slotNewCameraView( );
+ void slotNewTreeView( );
+ void slotNewDialogView( );
+ void slotNewLibraryBrowserView( );
+
+ void saveOptions( );
+ void restoreOptions( );
+
+ void setCaption( const QString& caption = QString::null );
+ void statusMsg( const QString& text = QString::null );
+ void slotControlPointMsg( const QString& msg = QString::null );
+
+ void slotModified( );
+ void slotDockWidgetClosed( );
+ void slotDeleteClosedObjects( );
+ void slotSelectedLayout( int id );
+ void slotSaveViewLayout( );
+ void slotViewsMenuAboutToShow( );
+
+protected:
+ virtual bool queryClose( );
+ virtual void showEvent( QShowEvent* );
+ void saveAs( );
+
+public:
+ /**
+ * Creates a dock widget of view type t with custom config c.
+ *
+ * If initPosition is true, the widget is docked to the desktop.
+ */
+ PMDockWidget* createView( const QString& t, PMViewOptions* c = 0,
+ bool initPosition = true );
+ //PMDockWidget* createTreeView( );
+ //PMDockWidget* createDialogView( );
+ //PMDockWidget* create3DView( PMGLView::PMViewType );
+
+private:
+ KRecentFilesAction* m_pRecent;
+ KToggleAction* m_pToolbarAction;
+ KToggleAction* m_pStatusbarAction;
+ KToggleAction* m_pPathAction;
+
+ KAction* m_pNewTreeViewAction;
+ KAction* m_pNewDialogViewAction;
+ KAction* m_pNewTopViewAction;
+ KAction* m_pNewBottomViewAction;
+ KAction* m_pNewLeftViewAction;
+ KAction* m_pNewRightViewAction;
+ KAction* m_pNewFrontViewAction;
+ KAction* m_pNewBackViewAction;
+ KAction* m_pNewCameraViewAction;
+ KAction* m_pNewLibraryBrowserAction;
+
+ KActionMenu* m_pViewLayoutsAction;
+ KAction* m_pSaveViewLayoutAction;
+
+ KStatusBar* m_pStatusBar;
+ PMPart* m_pPart;
+ KURL m_openRecentURL;
+
+ QPtrList<QObject> m_objectsToDelete;
+ int m_viewNumber;
+};
+
+#endif
diff --git a/kpovmodeler/pmskysphere.cpp b/kpovmodeler/pmskysphere.cpp
new file mode 100644
index 00000000..735c851b
--- /dev/null
+++ b/kpovmodeler/pmskysphere.cpp
@@ -0,0 +1,76 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmskysphere.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmskysphereedit.h"
+#include "pmdebug.h"
+
+#include <klocale.h>
+
+PMMetaObject* PMSkySphere::s_pMetaObject = 0;
+PMObject* createNewSkySphere( PMPart* part )
+{
+ return new PMSkySphere( part );
+}
+
+PMSkySphere::PMSkySphere( PMPart* part )
+ : Base( part )
+{
+}
+
+PMSkySphere::PMSkySphere( const PMSkySphere& s )
+ : Base( s )
+{
+}
+
+PMSkySphere::~PMSkySphere( )
+{
+}
+
+PMMetaObject* PMSkySphere::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "SkySphere", Base::metaObject( ),
+ createNewSkySphere );
+ }
+ return s_pMetaObject;
+}
+
+void PMSkySphere::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMSkySphere::description( ) const
+{
+ return i18n( "skysphere" );
+}
+
+PMDialogEditBase* PMSkySphere::editWidget( QWidget* parent ) const
+{
+ return new PMSkySphereEdit( parent );
+}
+
diff --git a/kpovmodeler/pmskysphere.h b/kpovmodeler/pmskysphere.h
new file mode 100644
index 00000000..f3799b75
--- /dev/null
+++ b/kpovmodeler/pmskysphere.h
@@ -0,0 +1,75 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSKYSPHERE_H
+#define PMSKYSPHERE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+
+/**
+ * Class for povray skyspheres
+ */
+class PMSkySphere : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMSkySphere
+ */
+ PMSkySphere( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSkySphere( const PMSkySphere& s );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMSkySphere( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMSkySphere( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /**
+ * Returns a new @ref PMSkySphereEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmskysphere" ); }
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+// enum PMSkySphereMementoID { };
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmskysphereedit.cpp b/kpovmodeler/pmskysphereedit.cpp
new file mode 100644
index 00000000..0dc05580
--- /dev/null
+++ b/kpovmodeler/pmskysphereedit.cpp
@@ -0,0 +1,44 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmskysphereedit.h"
+#include "pmskysphere.h"
+#include "pmlinkedit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMSkySphereEdit::PMSkySphereEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMSkySphereEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "SkySphere" ) )
+ {
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMSkySphereEdit: Can't display object\n";
+}
+
+#include "pmskysphereedit.moc"
diff --git a/kpovmodeler/pmskysphereedit.h b/kpovmodeler/pmskysphereedit.h
new file mode 100644
index 00000000..10ef2567
--- /dev/null
+++ b/kpovmodeler/pmskysphereedit.h
@@ -0,0 +1,58 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSKYSPHEREEDIT_H
+#define PMSKYSPHEREEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMSkySphere;
+
+/**
+ * Dialog edit class for @ref PMSkySphere
+ */
+class PMSkySphereEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMSkySphereEdit with parent and name
+ */
+ PMSkySphereEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+// virtual void createTopWidgets( );
+ /** */
+// virtual void saveContents( );
+
+private:
+ PMSkySphere* m_pDisplayedObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmslope.cpp b/kpovmodeler/pmslope.cpp
new file mode 100644
index 00000000..aa652be9
--- /dev/null
+++ b/kpovmodeler/pmslope.cpp
@@ -0,0 +1,146 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmxmlhelper.h"
+#include "pmvector.h"
+#include "pmslope.h"
+#include "pmslopeedit.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+const double heightDefault = 0;
+const double slopeDefault = 0;
+
+PMDefinePropertyClass( PMSlope, PMSlopeProperty );
+
+PMMetaObject* PMSlope::s_pMetaObject = 0;
+PMObject* createNewSlope( PMPart* part )
+{
+ return new PMSlope( part );
+}
+
+PMSlope::PMSlope( PMPart* part )
+ : Base( part )
+{
+ m_height = heightDefault;
+ m_slope = slopeDefault;
+}
+
+PMSlope::PMSlope( const PMSlope& s )
+ : Base( s )
+{
+ m_height = s.m_height;
+ m_slope = s.m_slope;
+}
+
+PMSlope::~PMSlope( )
+{
+}
+
+QString PMSlope::description( ) const
+{
+ return i18n( "slope" );
+}
+
+void PMSlope::serialize( QDomElement& e, QDomDocument& /*doc*/ ) const
+{
+ e.setAttribute( "height", m_height );
+ e.setAttribute( "slope", m_slope );
+}
+
+void PMSlope::readAttributes( const PMXMLHelper& h )
+{
+ m_height = h.doubleAttribute( "height", heightDefault );
+ m_slope = h.doubleAttribute( "slope", slopeDefault );
+}
+
+PMMetaObject* PMSlope::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Slope", Base::metaObject( ),
+ createNewSlope );
+ s_pMetaObject->addProperty(
+ new PMSlopeProperty( "height", &PMSlope::setHeight, &PMSlope::height ) );
+ s_pMetaObject->addProperty(
+ new PMSlopeProperty( "slope", &PMSlope::setSlope, &PMSlope::slope ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMSlope::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMSlope::setHeight( const double c )
+{
+ if( c != m_height )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHeightID, m_height );
+ m_height = c;
+ }
+}
+
+void PMSlope::setSlope( const double c )
+{
+ if( c != m_slope )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSlopeID, m_slope );
+ m_slope = c;
+ }
+}
+
+PMDialogEditBase* PMSlope::editWidget( QWidget* parent ) const
+{
+ return new PMSlopeEdit( parent );
+}
+
+void PMSlope::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMSlopeID:
+ setSlope( data->doubleData( ) );
+ break;
+ case PMHeightID:
+ setHeight( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSlope::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmslope.h b/kpovmodeler/pmslope.h
new file mode 100644
index 00000000..5f89b5b2
--- /dev/null
+++ b/kpovmodeler/pmslope.h
@@ -0,0 +1,94 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSLOPE_H
+#define PMSLOPE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+/**
+ * Class for Repeat Slopes
+ */
+
+class PMSlope : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates a PMSlope
+ */
+ PMSlope( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSlope( const PMSlope& s );
+ /**
+ * deletes the PMSlope
+ */
+ virtual ~PMSlope( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMSlope( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMSlopeEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmslope" ); }
+
+ double height( ) const { return m_height; }
+ void setHeight( double c );
+ double slope( ) const { return m_slope; }
+ void setSlope( double c );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMSlopeMementoID { PMHeightID, PMSlopeID };
+
+ double m_height;
+ double m_slope;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmslopeedit.cpp b/kpovmodeler/pmslopeedit.cpp
new file mode 100644
index 00000000..5bfcb88b
--- /dev/null
+++ b/kpovmodeler/pmslopeedit.cpp
@@ -0,0 +1,95 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmslopeedit.h"
+#include "pmslope.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+#include <kdialog.h>
+
+
+PMSlopeEdit::PMSlopeEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMSlopeEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+ QGridLayout* gl;
+
+ Base::createTopWidgets( );
+
+ QLabel* label = new QLabel( i18n( "Height:" ), this );
+ m_pHeightEdit = new PMFloatEdit( this );
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 2, 2 );
+ gl->addWidget( label, 0, 0 );
+ gl->addWidget( m_pHeightEdit, 0, 1 );
+ label = new QLabel( i18n( "Slope:" ), this );
+ m_pSlopeEdit = new PMFloatEdit( this );
+ gl->addWidget( label, 1, 0 );
+ gl->addWidget( m_pSlopeEdit, 1, 1 );
+ hl->addStretch( 1 );
+
+ connect( m_pHeightEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSlopeEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMSlopeEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Slope" ) )
+ {
+ m_pDisplayedObject = ( PMSlope* ) o;
+ m_pHeightEdit->setValue( m_pDisplayedObject->height( ) );
+ m_pHeightEdit->setReadOnly( m_pDisplayedObject->isReadOnly( ) );
+ m_pSlopeEdit->setValue( m_pDisplayedObject->slope( ) );
+ m_pSlopeEdit->setReadOnly( m_pDisplayedObject->isReadOnly( ) );
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMSlopeEdit: Can't display object\n";
+}
+
+void PMSlopeEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setHeight( m_pHeightEdit->value( ) );
+ m_pDisplayedObject->setSlope( m_pSlopeEdit->value( ) );
+ }
+}
+
+bool PMSlopeEdit::isDataValid( )
+{
+ if( !m_pHeightEdit->isDataValid( ) ||
+ !m_pSlopeEdit->isDataValid( ) )
+ return false;
+
+ return Base::isDataValid( );
+}
+
+#include "pmslopeedit.moc"
diff --git a/kpovmodeler/pmslopeedit.h b/kpovmodeler/pmslopeedit.h
new file mode 100644
index 00000000..2c4d2af4
--- /dev/null
+++ b/kpovmodeler/pmslopeedit.h
@@ -0,0 +1,68 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSLOPEEDIT_H
+#define PMSLOPEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMSlope;
+class PMVectorEdit;
+class PMIntEdit;
+class PMFloatEdit;
+class QComboBox;
+class QCheckBox;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMSlope.
+ */
+class PMSlopeEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMSlopeEdit with parent and name
+ */
+ PMSlopeEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMSlope* m_pDisplayedObject;
+ PMFloatEdit* m_pHeightEdit;
+ PMFloatEdit* m_pSlopeEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmsolidcolor.cpp b/kpovmodeler/pmsolidcolor.cpp
new file mode 100644
index 00000000..c067b12d
--- /dev/null
+++ b/kpovmodeler/pmsolidcolor.cpp
@@ -0,0 +1,127 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmsolidcolor.h"
+
+#include "pmxmlhelper.h"
+#include "pmsolidcoloredit.h"
+#include "pmmemento.h"
+
+#include <klocale.h>
+
+const PMColor colorDefault = PMColor( 0.0, 0.0, 0.0, 0.0, 0.0 );
+
+PMDefinePropertyClass( PMSolidColor, PMSolidColorProperty );
+
+PMMetaObject* PMSolidColor::s_pMetaObject = 0;
+PMObject* createNewSolidColor( PMPart* part )
+{
+ return new PMSolidColor( part );
+}
+
+PMSolidColor::PMSolidColor( PMPart* part )
+ : Base( part )
+{
+ m_color = colorDefault;
+}
+
+PMSolidColor::PMSolidColor( const PMSolidColor& c )
+ : Base( c )
+{
+ m_color = c.m_color;
+}
+
+PMSolidColor::~PMSolidColor( )
+{
+}
+
+QString PMSolidColor::description( ) const
+{
+ return i18n( "solid color" );
+}
+
+void PMSolidColor::serialize( QDomElement& e, QDomDocument& /*doc*/ ) const
+{
+ e.setAttribute( "color", m_color.serializeXML( ) );
+}
+
+void PMSolidColor::readAttributes( const PMXMLHelper& h )
+{
+ m_color = h.colorAttribute( "color", colorDefault );
+}
+
+PMMetaObject* PMSolidColor::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "SolidColor", Base::metaObject( ),
+ createNewSolidColor );
+ s_pMetaObject->addProperty(
+ new PMSolidColorProperty( "color", &PMSolidColor::setColor, &PMSolidColor::color ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMSolidColor::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMSolidColor::setColor( const PMColor& c )
+{
+ if( c != m_color )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMColorID, m_color );
+ m_color = c;
+ }
+}
+
+PMDialogEditBase* PMSolidColor::editWidget( QWidget* parent ) const
+{
+ return new PMSolidColorEdit( parent );
+}
+
+void PMSolidColor::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMColorID:
+ setColor( data->colorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSolidColor::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmsolidcolor.h b/kpovmodeler/pmsolidcolor.h
new file mode 100644
index 00000000..7a575758
--- /dev/null
+++ b/kpovmodeler/pmsolidcolor.h
@@ -0,0 +1,97 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSOLIDCOLOR_H
+#define PMSOLIDCOLOR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+#include "pmcolor.h"
+
+/**
+ * Class for solid colors.
+ */
+
+class PMSolidColor : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates a PMSolidColor
+ */
+ PMSolidColor( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSolidColor( const PMSolidColor& s );
+ /**
+ * deletes the PMSolidColor
+ */
+ virtual ~PMSolidColor( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMSolidColor( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMSolidColorEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmsolidcolor" ); }
+
+ /**
+ * Returns the color
+ */
+ PMColor color( ) const { return m_color; }
+ /**
+ * Sets the color
+ */
+ void setColor( const PMColor& c );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMSolidColorMementoID { PMColorID };
+ PMColor m_color;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmsolidcoloredit.cpp b/kpovmodeler/pmsolidcoloredit.cpp
new file mode 100644
index 00000000..49183582
--- /dev/null
+++ b/kpovmodeler/pmsolidcoloredit.cpp
@@ -0,0 +1,79 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmsolidcoloredit.h"
+#include "pmsolidcolor.h"
+#include "pmcoloredit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMSolidColorEdit::PMSolidColorEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMSolidColorEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout = new QHBoxLayout( topLayout( ) );
+ m_pColorEdit = new PMColorEdit( true, this );
+ QLabel* label = new QLabel( i18n( "Color:" ), this );
+
+ layout->addWidget( label, 0, AlignTop );
+ layout->addWidget( m_pColorEdit );
+
+ connect( m_pColorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMSolidColorEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "SolidColor" ) )
+ {
+ m_pDisplayedObject = ( PMSolidColor* ) o;
+ m_pColorEdit->setColor( m_pDisplayedObject->color( ) );
+
+ m_pColorEdit->setReadOnly( m_pDisplayedObject->isReadOnly( ) );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMSolidColorEdit: Can't display object\n";
+}
+
+void PMSolidColorEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setColor( m_pColorEdit->color( ) );
+ }
+}
+
+bool PMSolidColorEdit::isDataValid( )
+{
+ if( !m_pColorEdit->isDataValid( ) )
+ return false;
+ return Base::isDataValid( );
+}
+
+#include "pmsolidcoloredit.moc"
diff --git a/kpovmodeler/pmsolidcoloredit.h b/kpovmodeler/pmsolidcoloredit.h
new file mode 100644
index 00000000..57439f92
--- /dev/null
+++ b/kpovmodeler/pmsolidcoloredit.h
@@ -0,0 +1,62 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSOLIDCOLOREDIT_H
+#define PMSOLIDCOLOREDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMSolidColor;
+class PMColorEdit;
+
+/**
+ * Dialog edit class for @ref PMSolidColor.
+ */
+class PMSolidColorEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMSolidColorEdit with parent and name
+ */
+ PMSolidColorEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMSolidColor* m_pDisplayedObject;
+ PMColorEdit* m_pColorEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmsolidobject.cpp b/kpovmodeler/pmsolidobject.cpp
new file mode 100644
index 00000000..6907e731
--- /dev/null
+++ b/kpovmodeler/pmsolidobject.cpp
@@ -0,0 +1,140 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmsolidobject.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+
+
+PMDefinePropertyClass( PMSolidObject, PMSolidObjectProperty );
+
+PMMetaObject* PMSolidObject::s_pMetaObject = 0;
+
+PMSolidObject::PMSolidObject( PMPart* part )
+ : Base( part )
+{
+ m_inverse = false;
+ m_hollow = PMUnspecified;
+}
+
+PMSolidObject::PMSolidObject( const PMSolidObject& s )
+ : Base( s )
+{
+ m_inverse = s.m_inverse;
+ m_hollow = s.m_hollow;
+}
+
+PMSolidObject::~PMSolidObject( )
+{
+}
+
+PMMetaObject* PMSolidObject::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "SolidObject", Base::metaObject( ) );
+ s_pMetaObject->addProperty(
+ new PMSolidObjectProperty( "inverse", &PMSolidObject::setInverse, &PMSolidObject::inverse ) );
+ s_pMetaObject->addProperty(
+ new PMSolidObjectProperty( "hollow", &PMSolidObject::setHollow, &PMSolidObject::hollow ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMSolidObject::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMSolidObject::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ switch( m_hollow )
+ {
+ case PMTrue:
+ e.setAttribute( "hollow", "1" );
+ break;
+ case PMFalse:
+ e.setAttribute( "hollow", "0" );
+ break;
+ case PMUnspecified:
+ break;
+ }
+ e.setAttribute( "inverse", m_inverse );
+
+ Base::serialize( e, doc );
+}
+
+void PMSolidObject::readAttributes( const PMXMLHelper& h )
+{
+ m_hollow = h.threeStateAttribute( "hollow" );
+ m_inverse = h.boolAttribute( "inverse", false );
+
+ Base::readAttributes( h );
+}
+
+void PMSolidObject::setHollow( PMThreeState h )
+{
+ if( m_hollow != h )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMHollowID, m_hollow );
+ m_hollow = h;
+ }
+}
+
+void PMSolidObject::setInverse( bool yes )
+{
+ if( m_inverse != yes )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMInverseID, m_inverse );
+ m_inverse = yes;
+ }
+}
+
+void PMSolidObject::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMInverseID:
+ setInverse( data->boolData( ) );
+ break;
+ case PMHollowID:
+ setHollow( data->threeStateData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSolidObject::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmsolidobject.h b/kpovmodeler/pmsolidobject.h
new file mode 100644
index 00000000..e497c397
--- /dev/null
+++ b/kpovmodeler/pmsolidobject.h
@@ -0,0 +1,94 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSOLIDOBJECT_H
+#define PMSOLIDOBJECT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmgraphicalobject.h"
+
+
+/**
+ * Class for povray solid objects
+ */
+class PMSolidObject : public PMGraphicalObject
+{
+ typedef PMGraphicalObject Base;
+public:
+ /**
+ * Creates an empty PMSolidObject
+ */
+ PMSolidObject( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSolidObject( const PMSolidObject& s );
+
+ /**
+ * Deletes the object and all children
+ */
+ virtual ~PMSolidObject( );
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns the state of the hollow flag.
+ * Values can be PMTrue, PMFalse, PMUnspecified.
+ */
+ PMThreeState hollow( ) const { return m_hollow; }
+ /**
+ * Sets the hollow flag. Values can be PMTrue, PMFalse, PMUnspecified.
+ */
+ void setHollow( PMThreeState h );
+
+ /**
+ * Returns the state of the inverse flag.
+ */
+ bool inverse( ) const { return m_inverse; }
+ /**
+ * Sets the inverse flag
+ */
+ void setInverse( bool yes );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMSolidObjectMementoID { PMInverseID, PMHollowID };
+
+ bool m_inverse;
+ PMThreeState m_hollow;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmsolidobjectedit.cpp b/kpovmodeler/pmsolidobjectedit.cpp
new file mode 100644
index 00000000..e6aa3765
--- /dev/null
+++ b/kpovmodeler/pmsolidobjectedit.cpp
@@ -0,0 +1,82 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmsolidobjectedit.h"
+#include "pmsolidobject.h"
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <klocale.h>
+
+PMSolidObjectEdit::PMSolidObjectEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMSolidObjectEdit::createBottomWidgets( )
+{
+ m_pInverseButton = new QCheckBox( i18n( "Inverse" ), this );
+ m_pHollowButton = new QCheckBox( i18n( "Hollow" ), this );
+
+ m_pHollowButton->setTristate( true );
+
+ topLayout( )->addWidget( m_pInverseButton );
+ topLayout( )->addWidget( m_pHollowButton );
+
+ connect( m_pHollowButton, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pInverseButton, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+
+ Base::createBottomWidgets( );
+}
+
+void PMSolidObjectEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "SolidObject" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+
+ m_pDisplayedObject = ( PMSolidObject* ) o;
+ setCheckBox( m_pHollowButton, m_pDisplayedObject->hollow( ) );
+ m_pInverseButton->setChecked( m_pDisplayedObject->inverse( ) );
+
+ m_pHollowButton->setEnabled( !readOnly );
+ m_pInverseButton->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMSolidObjectEdit: Can't display object\n";
+}
+
+void PMSolidObjectEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ m_pDisplayedObject->setHollow( checkBoxState( m_pHollowButton ) );
+ m_pDisplayedObject->setInverse( m_pInverseButton->isChecked( ) );
+ Base::saveContents( );
+ }
+}
+
+bool PMSolidObjectEdit::isDataValid( )
+{
+ return Base::isDataValid( );
+}
+
+#include "pmsolidobjectedit.moc"
diff --git a/kpovmodeler/pmsolidobjectedit.h b/kpovmodeler/pmsolidobjectedit.h
new file mode 100644
index 00000000..3da2da6a
--- /dev/null
+++ b/kpovmodeler/pmsolidobjectedit.h
@@ -0,0 +1,63 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSOLIDOBJECTEDIT_H
+#define PMSOLIDOBJECTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmgraphicalobjectedit.h"
+
+class PMSolidObject;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMSolidObject.
+ */
+class PMSolidObjectEdit : public PMGraphicalObjectEdit
+{
+ Q_OBJECT
+ typedef PMGraphicalObjectEdit Base;
+public:
+ /**
+ * Creates a PMSolidObjectEdit with parent and name
+ */
+ PMSolidObjectEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createBottomWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMSolidObject* m_pDisplayedObject;
+ QCheckBox* m_pHollowButton;
+ QCheckBox* m_pInverseButton;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmsor.cpp b/kpovmodeler/pmsor.cpp
new file mode 100644
index 00000000..b7a9f0ef
--- /dev/null
+++ b/kpovmodeler/pmsor.cpp
@@ -0,0 +1,708 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmsor.h"
+
+#include "pmxmlhelper.h"
+#include "pmsoredit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pmsorcontrolpoint.h"
+#include "pmsplinememento.h"
+#include "pmsorsegment.h"
+#include "pmdefaults.h"
+#include "pmobjectaction.h"
+
+#include <klocale.h>
+
+const int defaultNumberOfPoints = 4;
+const PMVector defaultPoint[defaultNumberOfPoints] =
+{
+ PMVector( 0.0, 0.0 ),
+ PMVector( 0.5, 0.3 ),
+ PMVector( 0.5, 0.7 ),
+ PMVector( 0.0, 1.0 )
+};
+
+const bool defaultSturm = false;
+const bool defaultOpen = false;
+
+int PMSurfaceOfRevolution::s_rSteps = c_defaultSurfaceOfRevolutionRSteps;
+int PMSurfaceOfRevolution::s_sSteps = c_defaultSurfaceOfRevolutionSSteps;
+int PMSurfaceOfRevolution::s_parameterKey = 0;
+PMMetaObject* PMSurfaceOfRevolution::s_pMetaObject = 0;
+PMObject* createNewSurfaceOfRevolution( PMPart* part )
+{
+ return new PMSurfaceOfRevolution( part );
+}
+
+PMDefinePropertyClass( PMSurfaceOfRevolution, PMSurfaceOfRevolutionProperty );
+
+class PMPointProperty : public PMPropertyBase
+{
+public:
+ PMPointProperty( )
+ : PMPropertyBase( "controlPoints", PMVariant::Vector )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ m_index = index;
+ }
+ virtual int size( PMObject* object, int /*dimension*/ ) const
+ {
+ return ( ( PMSurfaceOfRevolution* ) object )->numberOfPoints( );
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& var )
+ {
+ PMSurfaceOfRevolution* p = ( PMSurfaceOfRevolution* ) obj;
+ QValueList<PMVector> list = p->points( );
+ QValueList<PMVector>::Iterator it = list.begin( );
+ int i;
+ PMVector v = var.vectorData( );
+ v.resize( 2 );
+
+ for( i = 0; i < m_index && it != list.end( ); ++i )
+ ++it;
+ // expand the list if necessary
+ for( ; i < m_index; ++i )
+ list.insert( it, v );
+ if( it == list.end( ) )
+ it = list.insert( it, v );
+ else
+ *it = v;
+
+ p->setPoints( list );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ PMSurfaceOfRevolution* p = ( PMSurfaceOfRevolution* ) obj;
+ QValueList<PMVector> list = p->points( );
+ QValueList<PMVector>::ConstIterator it = list.at( m_index );
+
+ if( it == list.end( ) )
+ {
+ kdError( PMArea ) << "Range error in PMSurfaceOfRevolution::PointProperty::get" << endl;
+ return PMVariant( );
+ }
+
+ return PMVariant( *it );
+ }
+
+private:
+ int m_index;
+};
+
+PMSurfaceOfRevolution::PMSurfaceOfRevolution( PMPart* part )
+ : Base( part )
+{
+ int i;
+
+ for( i = 0; i < defaultNumberOfPoints; ++i )
+ m_points.append( defaultPoint[i] );
+ m_sturm = defaultSturm;
+ m_open = defaultOpen;
+}
+
+PMSurfaceOfRevolution::PMSurfaceOfRevolution( const PMSurfaceOfRevolution& s )
+ : Base( s )
+{
+ m_points = s.m_points;
+ m_sturm = s.m_sturm;
+ m_open = s.m_open;
+}
+
+PMSurfaceOfRevolution::~PMSurfaceOfRevolution( )
+{
+}
+
+QString PMSurfaceOfRevolution::description( ) const
+{
+ return i18n( "surface of revolution" );
+}
+
+void PMSurfaceOfRevolution::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ QDomElement data = doc.createElement( "extra_data" );
+ QDomElement p;
+
+ e.setAttribute( "sturm", m_sturm );
+ e.setAttribute( "open", m_open );
+
+ QValueList<PMVector>::ConstIterator it;
+ for( it = m_points.begin( ); it != m_points.end( ); ++it )
+ {
+ p = doc.createElement( "point" );
+ p.setAttribute( "vector", ( *it ).serializeXML( ) );
+ data.appendChild( p );
+ }
+
+ e.appendChild( data );
+ Base::serialize( e, doc );
+}
+
+void PMSurfaceOfRevolution::readAttributes( const PMXMLHelper& h )
+{
+ m_sturm = h.boolAttribute( "sturm", defaultSturm );
+ m_open = h.boolAttribute( "open", defaultOpen );
+
+ m_points.clear( );
+ PMVector v( 2 );
+
+ QDomElement e = h.extraData( );
+ if( !e.isNull( ) )
+ {
+ QDomNode c = e.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ if( ce.tagName( ) == "point" )
+ {
+ QString str = ce.attribute( "vector" );
+ if( !str.isNull( ) )
+ {
+ v.loadXML( str );
+ m_points.append( v );
+ }
+ }
+ }
+ c = c.nextSibling( );
+ }
+ }
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMSurfaceOfRevolution::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "SurfaceOfRevolution", Base::metaObject( ),
+ createNewSurfaceOfRevolution );
+ s_pMetaObject->addProperty(
+ new PMSurfaceOfRevolutionProperty( "sturm", &PMSurfaceOfRevolution::setSturm,
+ &PMSurfaceOfRevolution::sturm ) );
+ s_pMetaObject->addProperty(
+ new PMSurfaceOfRevolutionProperty( "open", &PMSurfaceOfRevolution::setOpen,
+ &PMSurfaceOfRevolution::open ) );
+ s_pMetaObject->addProperty( new PMPointProperty( ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMSurfaceOfRevolution::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMSurfaceOfRevolution::setSturm( bool s )
+{
+ if( m_sturm != s )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSturmID, m_sturm );
+ m_sturm = s;
+ }
+}
+
+void PMSurfaceOfRevolution::setOpen( bool o )
+{
+ if( m_open != o )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOpenID, m_open );
+ m_open = o;
+ }
+}
+
+void PMSurfaceOfRevolution::setPoints( const QValueList<PMVector>& points )
+{
+ if( m_points != points )
+ {
+ if( m_pMemento )
+ ( ( PMSplineMemento* ) m_pMemento )->setSplinePoints( m_points );
+
+ setViewStructureChanged( );
+ m_points = points;
+ }
+}
+
+PMDialogEditBase* PMSurfaceOfRevolution::editWidget( QWidget* parent ) const
+{
+ return new PMSurfaceOfRevolutionEdit( parent );
+}
+
+void PMSurfaceOfRevolution::createMemento( )
+{
+ if( m_pMemento )
+ delete m_pMemento;
+ m_pMemento = new PMSplineMemento( this );
+}
+
+void PMSurfaceOfRevolution::restoreMemento( PMMemento* s )
+{
+ PMSplineMemento* m = ( PMSplineMemento* ) s;
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMSturmID:
+ setSturm( data->boolData( ) );
+ break;
+ case PMOpenID:
+ setOpen( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSurfaceOfRevolution::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ if( m->splinePointsSaved( ) )
+ setPoints( m->splinePoints( ) );
+
+ Base::restoreMemento( s );
+}
+
+
+void PMSurfaceOfRevolution::createViewStructure( )
+{
+ if( s_sSteps == 0 )
+ s_sSteps = c_defaultSurfaceOfRevolutionSSteps;
+ if( s_rSteps == 0 )
+ s_rSteps = c_defaultSurfaceOfRevolutionRSteps;
+
+ int rSteps = (int)( ( (float)s_rSteps / 2 ) * ( displayDetail( ) + 1 ) );
+ int sSteps = (int)( ( (float)s_sSteps / 2 ) * ( displayDetail( ) + 1 ) );
+
+ int np = m_points.count( );
+ int i, j, r;
+
+ // calculate number of segments
+ int ns = np - 3;
+
+ // calculate number of points and lines of the view structure
+ int vsp = ns * sSteps + 1;
+ int vsl = ( 2 * vsp - 1 ) * rSteps;
+ vsp *= rSteps;
+
+ if( m_pViewStructure )
+ {
+ if( m_pViewStructure->points( ).size( ) != ( unsigned ) vsp )
+ m_pViewStructure->points( ).resize( vsp );
+ if( m_pViewStructure->lines( ).size( ) != ( unsigned ) vsl )
+ m_pViewStructure->lines( ).resize( vsl );
+ }
+ else
+ m_pViewStructure = new PMViewStructure( vsp, vsl );
+
+
+ // calculate the spline segments
+ QValueList<PMSorSegment> segments;
+ QValueList<PMVector>::Iterator it1, it2, it3, it4;
+ it1 = m_points.begin( );
+ it2 = it1; ++it2;
+ it3 = it2; ++it3;
+ it4 = it3; ++it4;
+
+ for( i = 0; i < ns; ++i, ++it1, ++it2, ++it3, ++it4 )
+ segments.append( PMSorSegment( *it1, *it2, *it3, *it4 ) );
+
+ // create the line array
+ PMLineArray& lines = m_pViewStructure->lines( );
+ int vl = ns * sSteps;
+ int lb = 0;
+ for( i = 0; i < vl + 1; ++i )
+ {
+ for( j = 0; j < rSteps - 1; ++j )
+ lines[lb+j] = PMLine( lb + j, lb + j + 1 );
+ lines[lb+rSteps-1] = PMLine( lb, lb + rSteps - 1 );
+ lb += rSteps;
+ }
+ int pi = 0;
+ for( i = 0; i < vl; ++i )
+ {
+ for( j = 0; j < rSteps; ++j )
+ {
+ lines[lb] = PMLine( pi, pi + rSteps );
+ ++pi;
+ ++lb;
+ }
+ }
+
+ // calculate the points
+ PMVector point2, point3;
+ QValueList<PMSorSegment>::Iterator sit = segments.begin( );
+
+ double poffset = 1.0 / sSteps;
+ PMMatrix rot = PMMatrix::rotation( 0.0, M_PI * 2.0 / rSteps, 0.0 );
+ PMPointArray& points = m_pViewStructure->points( );
+ pi = 0;
+
+ for( i = 0; i < ns; ++i, ++sit )
+ {
+ for( j = 0; j < sSteps; ++j )
+ {
+ point2 = ( *sit ).point( poffset * j );
+ point3[0] = point2[0];
+ point3[1] = point2[1];
+ point3[2] = 0.0;
+
+ for( r = 0; r < rSteps; ++r )
+ {
+ points[pi] = PMPoint( point3 );
+ if( r != rSteps - 1 )
+ point3.transform( rot );
+ ++pi;
+ }
+ }
+ if( i == ns - 1 )
+ {
+ point2 = ( *sit ).point( 1.0 );
+ point3[0] = point2[0];
+ point3[1] = point2[1];
+ point3[2] = 0.0;
+
+ for( r = 0; r < rSteps; ++r )
+ {
+ points[pi] = PMPoint( point3 );
+ if( r != rSteps - 1 )
+ point3.transform( rot );
+ ++pi;
+ }
+ }
+ }
+}
+
+void PMSurfaceOfRevolution::controlPoints( PMControlPointList& list )
+{
+ QValueList<PMVector>::Iterator it;
+ QPtrList<PMSorControlPoint> tmp1, tmp2;
+ int i;
+
+ PMSorControlPoint* cp = 0;
+
+ PMSorControlPoint* lastPoint = 0;
+ cp = 0;
+
+ for( it = m_points.begin( ), i = 0; it != m_points.end( ); ++it, ++i )
+ {
+ lastPoint = cp;
+ cp = new PMSorControlPoint( lastPoint, *it, PMSorControlPoint::PM2DXY, i,
+ i18n( "Point %1 (xy)" ).arg( i + 1 ) );
+ tmp1.append( cp );
+ }
+
+ lastPoint = 0;
+ cp = 0;
+
+ for( it = m_points.begin( ), i = 0; it != m_points.end( ); ++it, ++i )
+ {
+ lastPoint = cp;
+ cp = new PMSorControlPoint( lastPoint, *it, PMSorControlPoint::PM2DZY, i,
+ i18n( "Point %1 (yz)" ).arg( i + 1 ) );
+ tmp2.append( cp );
+ }
+
+ QPtrListIterator<PMSorControlPoint> cit1( tmp1 ), cit2( tmp2 );
+
+ for( ; cit1.current( ) && cit2.current( ); ++cit1, ++cit2 )
+ {
+ ( *cit1 )->setSorLink( *cit2 );
+ ( *cit2 )->setSorLink( *cit1 );
+ }
+ for( cit1.toFirst( ); cit1.current( ); ++cit1 )
+ list.append( *cit1 );
+ for( cit2.toFirst( ); cit2.current( ); ++cit2 )
+ list.append( *cit2 );
+}
+
+void PMSurfaceOfRevolution::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPointListIterator it1( list ), it2( list );
+ QValueList<PMVector>::Iterator pit = m_points.begin( );
+ PMSorControlPoint* p1;
+ PMSorControlPoint* p2;
+ bool firstChange = true;
+ PMVector lastPoint( 2 );
+ int num = list.count( ) / 2;
+ int pnr = 0;
+
+ for( it2 += num; it2.current( ); ++it1, ++it2, ++pit, ++pnr )
+ {
+ p1 = ( PMSorControlPoint* ) it1.current( );
+ p2 = ( PMSorControlPoint* ) it2.current( );
+
+ if( p1->changed( ) )
+ {
+ if( firstChange )
+ {
+ if( m_pMemento )
+ {
+ PMSplineMemento* m = ( PMSplineMemento* ) m_pMemento;
+ if( !m->splinePointsSaved( ) )
+ m->setSplinePoints( m_points );
+ }
+ firstChange = false;
+ setViewStructureChanged( );
+ }
+ p2->setPoint( p1->point( ) );
+ ( *pit ) = p1->point( );
+ }
+ else if( p2->changed( ) )
+ {
+ if( firstChange )
+ {
+ if( m_pMemento )
+ {
+ PMSplineMemento* m = ( PMSplineMemento* ) m_pMemento;
+ if( !m->splinePointsSaved( ) )
+ m->setSplinePoints( m_points );
+ }
+ firstChange = false;
+ setViewStructureChanged( );
+ }
+ p1->setPoint( p2->point( ) );
+ ( *pit ) = p2->point( );
+ }
+
+ if( ( pnr > 1 ) && ( pnr < ( num - 1 ) ) )
+ {
+ if( ( ( *pit )[1] - lastPoint[1] ) < c_sorTolerance )
+ {
+ ( *pit )[1] = lastPoint[1] + c_sorTolerance;
+ p1->setPoint( *pit );
+ p2->setPoint( *pit );
+ }
+ }
+ if( ( pnr == ( num - 1 ) ) || ( pnr == 2 ) )
+ {
+ QValueList<PMVector>::Iterator hit = pit;
+ --hit; --hit;
+
+ if( approxZero( ( *hit )[1] - ( *pit )[1], c_sorTolerance ) )
+ {
+ ( *pit )[1] = ( *hit )[1] + c_sorTolerance;
+ p1->setPoint( *pit );
+ p2->setPoint( *pit );
+ }
+ }
+
+ lastPoint = *pit;
+ }
+}
+
+void PMSurfaceOfRevolution::addObjectActions( const PMControlPointList& /*cp*/,
+ QPtrList<PMObjectAction>& actions )
+{
+ PMObjectAction* a;
+
+ a = new PMObjectAction( s_pMetaObject, PMSplitSegmentID,
+ i18n( "Add Point" ) );
+ actions.append( a );
+
+ a = new PMObjectAction( s_pMetaObject, PMJoinSegmentsID,
+ i18n( "Remove Point" ) );
+ int np = m_points.count( );
+
+ if( np < 5 )
+ a->setEnabled( false );
+ actions.append( a );
+}
+
+void PMSurfaceOfRevolution::objectActionCalled( const PMObjectAction* action,
+ const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ if( action->objectType( ) == s_pMetaObject )
+ {
+ switch( action->actionID( ) )
+ {
+ case PMSplitSegmentID:
+ splitSegment( cp, cpViewPosition, clickPosition );
+ break;
+ case PMJoinSegmentsID:
+ joinSegments( cp, cpViewPosition, clickPosition );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSurfaceOfRevolution::objectActionCalled\n";
+ break;
+ }
+ }
+ else
+ Base::objectActionCalled( action, cp, cpViewPosition, clickPosition );
+}
+
+void PMSurfaceOfRevolution::splitSegment( const PMControlPointList& /*cp*/,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ // find nearest segment
+ int nump = cpViewPosition.count( ) / 2 - 1;
+ double abs = 0.0, minabs = 1e10;
+ int ns = -1;
+ int i, j;
+ PMVector mid( 3 ), dist( 2 );
+
+ QPtrListIterator<PMVector> it1( cpViewPosition );
+ QPtrListIterator<PMVector> it2( cpViewPosition );
+ ++it2;
+
+ for( j = 0; j < 2; ++j )
+ {
+ ++it1;
+ ++it2;
+ for( i = 1; i < ( nump - 1 ); ++i )
+ {
+ mid = ( **it1 + **it2 ) / 2.0;
+ dist[0] = mid[0];
+ dist[1] = mid[1];
+ dist -= clickPosition;
+ abs = dist.abs( );
+
+ if( ( minabs > abs ) || ( ns < 0 ) )
+ {
+ minabs = abs;
+ ns = i;
+ }
+ ++it1;
+ ++it2;
+ }
+ ++it1;
+ ++it2;
+ ++it1;
+ ++it2;
+ }
+
+ // add a new segment
+ QValueList<PMVector> newPoints = m_points;
+ QValueList<PMVector>::Iterator it = newPoints.at( ( unsigned ) ns );
+ PMVector p[4];
+ QValueList<PMVector>::Iterator hit = it;
+
+ // calculate the spline segment
+ --hit;
+ for( i = 0; i < 4; ++i, ++hit )
+ p[i] = *hit;
+ PMSorSegment segment( p[0], p[1], p[2], p[3] );
+
+ mid = segment.point( 0.5 );
+ if( mid[0] < 0 )
+ mid[0] = 0;
+ ++it;
+ it = newPoints.insert( it, mid );
+ hit = it;
+ --it;
+
+ for( ; hit != newPoints.end( ); ++it, ++hit )
+ if( ( ( *hit )[1] - ( *it )[1] ) < c_sorTolerance )
+ ( *hit )[1] = ( *it )[1] + c_sorTolerance;
+
+ setPoints( newPoints );
+}
+
+void PMSurfaceOfRevolution::joinSegments( const PMControlPointList& /*cp*/,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ // find nearest point
+ int nump = cpViewPosition.count( ) / 2;
+
+ if( nump < 5 )
+ {
+ kdError( PMArea ) << "Not enough points in PMSurfaceOfRevolution::joinSegments\n";
+ return;
+ }
+
+ double abs = 0.0, minabs = 1e10;
+ int ns = -1;
+ int i, j;
+ PMVector* p;
+ PMVector dist( 2 );
+
+ QPtrListIterator<PMVector> it1( cpViewPosition );
+
+ for( j = 0; j < 2; ++j )
+ {
+ for( i = 0; i < nump; ++i )
+ {
+ p = *it1;
+ dist[0] = (*p)[0];
+ dist[1] = (*p)[1];
+ dist -= clickPosition;
+ abs = dist.abs( );
+
+ if( ( minabs > abs ) || ( ns < 0 ) )
+ {
+ minabs = abs;
+ ns = i;
+ }
+ ++it1;
+ }
+ }
+
+ // join two segments
+ QValueList<PMVector> newPoints = m_points;
+ QValueList<PMVector>::Iterator it;
+
+ // never remove the first or last point
+ if( ns == 0 )
+ ++ns;
+ if( ns == ( nump - 1 ) )
+ --ns;
+ it = newPoints.at( ns );
+ newPoints.remove( it );
+
+ setPoints( newPoints );
+}
+
+void PMSurfaceOfRevolution::setRSteps( int r )
+{
+ if( r >= 4 )
+ s_rSteps = r;
+ else
+ kdDebug( PMArea ) << "PMSurfaceOfRevolution::setRSteps: R must be greater than 3\n";
+ ++s_parameterKey;
+}
+
+void PMSurfaceOfRevolution::setSSteps( int s )
+{
+ if( s >= 1 )
+ s_sSteps = s;
+ else
+ kdDebug( PMArea ) << "PMSurfaceOfRevolution::setSSteps: S must be greater than 0\n";
+ ++s_parameterKey;
+}
diff --git a/kpovmodeler/pmsor.h b/kpovmodeler/pmsor.h
new file mode 100644
index 00000000..c15b305d
--- /dev/null
+++ b/kpovmodeler/pmsor.h
@@ -0,0 +1,191 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSOR_H
+#define PMSOR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include "pmsorcontrolpoint.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <math.h>
+
+class PMViewStructure;
+
+/**
+ * Class for povray sor objects.
+ */
+
+class PMSurfaceOfRevolution : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMSurfaceOfRevolution
+ */
+ PMSurfaceOfRevolution( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSurfaceOfRevolution( const PMSurfaceOfRevolution& s );
+ /**
+ * deletes the PMSurfaceOfRevolution
+ */
+ virtual ~PMSurfaceOfRevolution( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMSurfaceOfRevolution( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMSurfaceOfRevolutionEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmsor" ); }
+
+ /** */
+ virtual void createMemento( );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool multipleSelectControlPoints( ) const { return true; }
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual void addObjectActions( const PMControlPointList&,
+ QPtrList<PMObjectAction>& );
+ /** */
+ virtual void objectActionCalled( const PMObjectAction*,
+ const PMControlPointList&,
+ const QPtrList<PMVector>&,
+ const PMVector& );
+
+ /**
+ * Returns the sor points
+ */
+ QValueList<PMVector> points( ) const { return m_points; }
+ /**
+ * Sets the spline points
+ */
+ void setPoints( const QValueList<PMVector>& points );
+ /**
+ * Returns the number of spline points
+ */
+ int numberOfPoints( ) const { return m_points.size( ); }
+ /**
+ * Returns the sturm flag
+ */
+ bool sturm( ) const { return m_sturm; }
+ /**
+ * Sets the sturm flag
+ */
+ void setSturm( bool s );
+ /**
+ * Returns the open flag
+ */
+ bool open( ) const { return m_open; }
+ /**
+ * Sets the open flag
+ */
+ void setOpen( bool o );
+
+ /**
+ * Sets the number of steps around the y axis
+ */
+ static void setRSteps( int r );
+ /**
+ * Sets the number of subdivisions of one spline segment
+ */
+ static void setSSteps( int v );
+ /**
+ * Returns the number of steps around the y axis
+ */
+ static int rSteps( ) { return s_rSteps; }
+ /**
+ * Returns the number of subdivisions of one spline segment
+ */
+ static int sSteps( ) { return s_sSteps; }
+
+protected:
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey( ); }
+
+private:
+ /**
+ * Object action. Adds a spline point
+ */
+ void splitSegment( const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition );
+ /**
+ * Object action. Removes a spline point
+ */
+ void joinSegments( const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition );
+
+ void stringToValues( const QString& str );
+ QString valuesToString( ) const;
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMSurfaceOfRevolutionMementoID { PMOpenID, PMSturmID };
+ /**
+ * IDs for the object actions
+ */
+ enum PMSurfaceOfRevolutionActionID { PMSplitSegmentID, PMJoinSegmentsID };
+
+ QValueList<PMVector> m_points;
+ bool m_sturm;
+ bool m_open;
+
+ static int s_rSteps;
+ static int s_sSteps;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmsorcontrolpoint.cpp b/kpovmodeler/pmsorcontrolpoint.cpp
new file mode 100644
index 00000000..88924d05
--- /dev/null
+++ b/kpovmodeler/pmsorcontrolpoint.cpp
@@ -0,0 +1,228 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmsorcontrolpoint.h"
+#include "pmmath.h"
+#include <math.h>
+
+PMSorControlPoint::PMSorControlPoint( PMSorControlPoint* prev,
+ const PMVector& point,
+ PMSorControlPoint::CPType type, int id,
+ const QString& description )
+ : PMControlPoint( id, description )
+{
+ m_point = point;
+ m_type = type;
+ m_pPrev = prev;
+ if( m_pPrev )
+ m_pPrev->m_pNext = this;
+ m_pNext = 0;
+ m_pSorLink = 0;
+}
+
+void PMSorControlPoint::graphicalChangeStarted( )
+{
+ if( m_pPrev && !m_pPrev->m_pPrev && !m_pPrev->selected( ) )
+ m_pPrev->graphicalChangeStarted( );
+ if( m_pNext && !m_pNext->m_pNext && !m_pNext->selected( ) )
+ m_pNext->graphicalChangeStarted( );
+
+ m_original2DPoint = m_point;
+ m_originalPoint = to3D( m_point );
+}
+
+void PMSorControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& /*viewNormal*/,
+ const PMVector& endPoint )
+{
+ if( !m_pPrev && m_pNext->selected( ) ||
+ !m_pNext && m_pPrev->selected( ) )
+ return;
+
+ m_point = to2D( m_originalPoint + endPoint - startPoint );
+
+ if( m_pSorLink && m_pSorLink->selected( ) )
+ {
+ PMSorControlPoint* ll = m_pSorLink;
+ PMVector op = ll->to2D( ll->m_originalPoint + endPoint - startPoint );
+
+ if( ( m_point - m_original2DPoint ).abs( ) <
+ ( op - ll->m_original2DPoint ).abs( ) )
+ m_point = op;
+ }
+
+ if( m_pPrev && m_pNext )
+ {
+ if( m_pPrev->m_pPrev )
+ if( ( m_point[1] - m_pPrev->m_point[1] ) < c_sorTolerance )
+ m_point[1] = m_pPrev->m_point[1] + c_sorTolerance;
+ if( m_pNext->m_pNext )
+ if( ( m_pNext->m_point[1] - m_point[1] ) < c_sorTolerance )
+ m_point[1] = m_pNext->m_point[1] - c_sorTolerance;
+ }
+ if( m_point[0] < 0.0 )
+ m_point[0] = 0.0;
+
+ if( m_pPrev && !m_pPrev->m_pPrev )
+ {
+ m_pPrev->m_point = m_point + m_pPrev->m_original2DPoint
+ - m_original2DPoint;
+ m_pPrev->setChanged( );
+ }
+ if( m_pNext && !m_pNext->m_pNext )
+ {
+ m_pNext->m_point = m_point + m_pNext->m_original2DPoint
+ - m_original2DPoint;
+ m_pNext->setChanged( );
+ }
+}
+
+void PMSorControlPoint::snapToGrid( )
+{
+ int i;
+ double d = moveGrid( );
+ bool diff = false;
+ PMVector change( 2 );
+ PMSorControlPoint* basePoint = 0;
+ PMSorControlPoint* linkedPoint = 0;
+ if( !m_pPrev )
+ basePoint = m_pNext;
+ if( !m_pNext )
+ basePoint = m_pPrev;
+ if( m_pPrev && !m_pPrev->m_pPrev )
+ linkedPoint = m_pPrev;
+ if( m_pNext && !m_pNext->m_pNext )
+ linkedPoint = m_pNext;
+
+ if( basePoint && basePoint->selected( ) )
+ {
+ m_point -= basePoint->m_point;
+ diff = true;
+ }
+
+ if( !approxZero( d ) )
+ {
+ for( i = 0; i < 2; i++ )
+ {
+ change[i] = -m_point[i];
+ m_point[i] = rint( m_point[i] / d ) * d;
+ change[i] += m_point[i];
+ }
+ }
+
+ if( diff )
+ m_point += basePoint->m_point;
+
+ if( linkedPoint )
+ {
+ linkedPoint->m_point += change;
+ linkedPoint->setChanged( );
+ }
+
+ setChanged( );
+}
+
+PMVector PMSorControlPoint::to2D( const PMVector& v ) const
+{
+ PMVector result( 2 );
+ switch( m_type )
+ {
+ case PM2DXY:
+ result[0] = v[0];
+ result[1] = v[1];
+ break;
+ case PM2DXZ:
+ result[0] = v[0];
+ result[1] = v[2];
+ break;
+ case PM2DYZ:
+ result[0] = v[1];
+ result[1] = v[2];
+ break;
+ case PM2DYX:
+ result[0] = v[1];
+ result[1] = v[0];
+ break;
+ case PM2DZX:
+ result[0] = v[2];
+ result[1] = v[0];
+ break;
+ case PM2DZY:
+ result[0] = v[2];
+ result[1] = v[1];
+ break;
+ }
+ return result;
+}
+
+PMVector PMSorControlPoint::to3D( const PMVector& vec ) const
+{
+ PMVector result( 3 );
+ switch( m_type )
+ {
+ case PM2DXY:
+ result[0] = vec[0];
+ result[1] = vec[1];
+ result[2] = 0.0;
+ break;
+ case PM2DXZ:
+ result[0] = vec[0];
+ result[1] = 0.0;
+ result[2] = vec[1];
+ break;
+ case PM2DYZ:
+ result[0] = 0.0;
+ result[1] = vec[0];
+ result[2] = vec[1];
+ break;
+ case PM2DYX:
+ result[1] = vec[0];
+ result[0] = vec[1];
+ result[2] = 0.0;
+ break;
+ case PM2DZX:
+ result[2] = vec[0];
+ result[0] = vec[1];
+ result[1] = 0.0;
+ break;
+ case PM2DZY:
+ result[2] = vec[0];
+ result[1] = vec[1];
+ result[0] = 0.0;
+ break;
+ }
+ return result;
+}
+
+bool PMSorControlPoint::hasExtraLine( ) const
+{
+ return( !m_pPrev || !m_pNext );
+}
+
+PMVector PMSorControlPoint::extraLineStart( ) const
+{
+ return position( );
+}
+
+PMVector PMSorControlPoint::extraLineEnd( ) const
+{
+ if( !m_pPrev && m_pNext )
+ return m_pNext->position( );
+ if( m_pPrev && !m_pNext )
+ return m_pPrev->position( );
+ return PMVector( 0, 0, 0 );
+}
diff --git a/kpovmodeler/pmsorcontrolpoint.h b/kpovmodeler/pmsorcontrolpoint.h
new file mode 100644
index 00000000..0d9ec283
--- /dev/null
+++ b/kpovmodeler/pmsorcontrolpoint.h
@@ -0,0 +1,99 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMSORCONTROLPOINT_H
+#define PMSORCONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmcontrolpoint.h"
+
+const double c_sorTolerance = 0.0001;
+
+/**
+ * Class for free moveable control points
+ */
+class PMSorControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Type enum
+ */
+ enum CPType { PM2DXY, PM2DYX, PM2DXZ, PM2DZX, PM2DYZ, PM2DZY };
+ /**
+ * Creates a PMSorControlPoint with id. Point has to be a 2D vector.
+ */
+ PMSorControlPoint( PMSorControlPoint* prev,
+ const PMVector& point, CPType type,
+ int id, const QString& description );
+ /**
+ * Deletes the PMSorControlPoint
+ */
+ virtual ~PMSorControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const { return to3D( m_point ); }
+ /**
+ * Sets the 2d coordinates of the control point
+ */
+ void setPoint( const PMVector& newPoint ) { m_point = newPoint; }
+ /**
+ * 2d coordinates of the control point
+ */
+ PMVector point( ) const { return m_point; }
+ /**
+ * This method is used by the sor object to link
+ * the control points in the xy and xz plane. These points are
+ * synchronized if both are selected.
+ */
+ void setSorLink( PMSorControlPoint* p ) { m_pSorLink = p; }
+ /**
+ * Returns the linked control point for lathe points
+ */
+ PMSorControlPoint* sorLink( ) const { return m_pSorLink; }
+ /** */
+ virtual void snapToGrid( );
+
+ /** */
+ virtual bool hasExtraLine( ) const;
+ /** */
+ virtual PMVector extraLineStart( ) const;
+ /** */
+ virtual PMVector extraLineEnd( ) const;
+
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ PMVector to2D( const PMVector& v ) const;
+ PMVector to3D( const PMVector& v ) const;
+
+ PMVector m_point, m_originalPoint, m_original2DPoint;
+ CPType m_type;
+ PMSorControlPoint* m_pPrev;
+ PMSorControlPoint* m_pNext;
+ PMSorControlPoint* m_pSorLink;
+};
+
+#endif
diff --git a/kpovmodeler/pmsoredit.cpp b/kpovmodeler/pmsoredit.cpp
new file mode 100644
index 00000000..b56949e6
--- /dev/null
+++ b/kpovmodeler/pmsoredit.cpp
@@ -0,0 +1,282 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmsoredit.h"
+#include "pmsor.h"
+#include "pmvectorlistedit.h"
+#include "pmpart.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+PMSurfaceOfRevolutionEdit::PMSurfaceOfRevolutionEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMSurfaceOfRevolutionEdit::createBottomWidgets( )
+{
+ topLayout( )->addWidget( new QLabel( i18n( "Spline points:" ), this ) );
+
+ m_pPoints = new PMVectorListEdit( "u", "v", this );
+ connect( m_pPoints, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPoints, SIGNAL( selectionChanged( ) ),
+ SLOT( slotSelectionChanged( ) ) );
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( m_pPoints, 2 );
+
+ m_pAddAbove = new QPushButton( this );
+ m_pAddAbove->setPixmap( SmallIcon( "pmaddpointabove" ) );
+ m_pAddBelow = new QPushButton( this );
+ m_pAddBelow->setPixmap( SmallIcon( "pmaddpoint" ) );
+ m_pRemove = new QPushButton( this );
+ m_pRemove->setPixmap( SmallIcon( "pmremovepoint" ) );
+ connect( m_pAddAbove, SIGNAL( clicked( ) ), SLOT( slotAddPointAbove( ) ) );
+ connect( m_pAddBelow, SIGNAL( clicked( ) ), SLOT( slotAddPointBelow( ) ) );
+ connect( m_pRemove, SIGNAL( clicked( ) ), SLOT( slotRemovePoint( ) ) );
+
+ QVBoxLayout* bl = new QVBoxLayout( hl );
+ bl->addWidget( m_pAddAbove );
+ bl->addWidget( m_pAddBelow );
+ bl->addWidget( m_pRemove );
+ bl->addStretch( 1 );
+
+ m_pOpen = new QCheckBox( i18n( "type of the object", "Open" ), this );
+ topLayout( )->addWidget( m_pOpen );
+ connect( m_pOpen, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ m_pSturm = new QCheckBox( i18n( "Sturm" ), this );
+ topLayout( )->addWidget( m_pSturm );
+ connect( m_pSturm, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+
+ Base::createBottomWidgets( );
+}
+
+void PMSurfaceOfRevolutionEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "SurfaceOfRevolution" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMSurfaceOfRevolution* ) o;
+
+ m_pOpen->setChecked( m_pDisplayedObject->open( ) );
+ m_pOpen->setEnabled( !readOnly );
+ m_pSturm->setChecked( m_pDisplayedObject->sturm( ) );
+ m_pSturm->setEnabled( !readOnly );
+ m_pPoints->setVectors( m_pDisplayedObject->points( ), true );
+ updateControlPointSelection( );
+ updatePointButtons( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMSurfaceOfRevolutionEdit: Can't display object\n";
+}
+
+void PMSurfaceOfRevolutionEdit::updateControlPointSelection( )
+{
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp );
+ int i;
+ int np = cp.count( ) / 2;
+
+ if( np == m_pPoints->size( ) )
+ {
+ m_pPoints->blockSelectionUpdates( true );
+ bool sb = m_pPoints->signalsBlocked( );
+ m_pPoints->blockSignals( true );
+
+ m_pPoints->clearSelection( );
+ for( i = 0; i < np; i++, ++it )
+ if( ( *it )->selected( ) )
+ m_pPoints->select( i );
+ for( i = 0; i < np; i++, ++it )
+ if( ( *it )->selected( ) )
+ m_pPoints->select( i );
+
+ m_pPoints->blockSignals( sb );
+ m_pPoints->blockSelectionUpdates( false );
+ }
+}
+
+void PMSurfaceOfRevolutionEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ m_pDisplayedObject->setPoints( m_pPoints->vectors( ) );
+ m_pDisplayedObject->setOpen( m_pOpen->isChecked( ) );
+ m_pDisplayedObject->setSturm( m_pSturm->isChecked( ) );
+ Base::saveContents( );
+ }
+}
+
+bool PMSurfaceOfRevolutionEdit::isDataValid( )
+{
+ if( !m_pPoints->isDataValid( ) )
+ return false;
+
+ int np = m_pPoints->size( );
+ if( np < 4 )
+ {
+ KMessageBox::error( this, i18n( "The surface of revolution object needs at least 4 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it1 = points.begin( );
+ QValueListIterator<PMVector> it2 = it1; ++it2;
+ QValueListIterator<PMVector> it3 = it2; ++it3;
+ int pnr;
+
+ for( pnr = 0; it3 != points.end( ); ++it1, ++it2, ++it3, pnr++ )
+ {
+ if( ( pnr == 0 ) || ( pnr == ( np - 3 ) ) )
+ {
+ if( approxZero( ( *it1 )[1] - ( *it3 )[1], c_sorTolerance ) )
+ {
+ m_pPoints->setCurrentCell( pnr, 1 );
+ KMessageBox::error( this, i18n( "The v coordinate of point %1 and %2 must be different." )
+ .arg( pnr + 1 ).arg( pnr + 3 ),
+ i18n( "Error" ) );
+ return false;
+ }
+ }
+
+ if( pnr != 0 )
+ {
+ if( ( ( *it2 )[1] - ( *it1 )[1] ) < c_sorTolerance )
+ {
+ m_pPoints->setCurrentCell( pnr + 1, 1 );
+ KMessageBox::error( this, i18n( "The v coordinates must be strictly increasing." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ }
+ }
+
+ return Base::isDataValid( );
+}
+
+void PMSurfaceOfRevolutionEdit::slotAddPointAbove( )
+{
+ int index = m_pPoints->currentRow( );
+ if( index >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ if( it != points.end( ) )
+ {
+ QValueListIterator<PMVector> it2 = it;
+ it2--;
+ PMVector v;
+ if( it2 == points.end( ) )
+ v = *it;
+ else
+ v = ( *it + *it2 ) / 2;
+
+ points.insert( it, v );
+ m_pPoints->setVectors( points, true );
+ updatePointButtons( );
+ emit dataChanged( );
+ }
+ }
+}
+
+void PMSurfaceOfRevolutionEdit::slotAddPointBelow( )
+{
+ int index = m_pPoints->currentRow( );
+ if( index >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ if( it != points.end( ) )
+ {
+ QValueListIterator<PMVector> it2 = it;
+ it2++;
+ PMVector v;
+ if( it2 == points.end( ) )
+ v = *it;
+ else
+ v = ( *it + *it2 ) / 2;
+
+ points.insert( it2, v );
+ m_pPoints->setVectors( points, true );
+ m_pPoints->setCurrentCell( index + 1, m_pPoints->currentColumn( ) );
+ updatePointButtons( );
+ emit dataChanged( );
+ }
+ }
+}
+
+void PMSurfaceOfRevolutionEdit::slotRemovePoint( )
+{
+ int row = m_pPoints->currentRow( );
+
+ if( row >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( row );
+
+ if( it != points.end( ) && points.size( ) > 1 )
+ {
+ points.remove( it );
+ m_pPoints->setVectors( points, true );
+ updatePointButtons( );
+ emit dataChanged( );
+ }
+ }
+}
+
+void PMSurfaceOfRevolutionEdit::slotSelectionChanged( )
+{
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp );
+ int np = cp.count( ) / 2;
+ int i;
+
+ if( np == m_pPoints->size( ) )
+ {
+ for( i = 0; i < np; i++, ++it )
+ ( *it )->setSelected( m_pPoints->isSelected( i ) );
+ for( i = 0; i < np; i++, ++it )
+ ( *it )->setSelected( m_pPoints->isSelected( i ) );
+ emit controlPointSelectionChanged( );
+ }
+ updatePointButtons( );
+}
+
+void PMSurfaceOfRevolutionEdit::updatePointButtons( )
+{
+ int row = m_pPoints->currentRow( );
+ m_pAddAbove->setEnabled( row >= 0 );
+ m_pAddBelow->setEnabled( row >= 0 );
+ m_pRemove->setEnabled( row >= 0 && m_pPoints->size( ) > 4 );
+}
+
+#include "pmsoredit.moc"
diff --git a/kpovmodeler/pmsoredit.h b/kpovmodeler/pmsoredit.h
new file mode 100644
index 00000000..eb64be67
--- /dev/null
+++ b/kpovmodeler/pmsoredit.h
@@ -0,0 +1,86 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSOREDIT_H
+#define PMSOREDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+#include "pmvectoredit.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+
+class PMSurfaceOfRevolution;
+class QVBoxLayout;
+class QComboBox;
+class QCheckBox;
+class QPushButton;
+class QLabel;
+class PMVectorListEdit;
+
+/**
+ * Dialog edit class for @ref PMSurfaceOfRevolution
+ */
+class PMSurfaceOfRevolutionEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMSurfaceOfRevolutionEdit with parent and name
+ */
+ PMSurfaceOfRevolutionEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+ /** */
+ virtual void updateControlPointSelection( );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createBottomWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotAddPointAbove( );
+ void slotAddPointBelow( );
+ void slotRemovePoint( );
+ void slotSelectionChanged( );
+
+private:
+ void updatePointButtons( );
+
+ PMSurfaceOfRevolution* m_pDisplayedObject;
+ PMVectorListEdit* m_pPoints;
+ QCheckBox* m_pOpen;
+ QCheckBox* m_pSturm;
+ QPushButton* m_pAddAbove;
+ QPushButton* m_pAddBelow;
+ QPushButton* m_pRemove;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmsorsegment.cpp b/kpovmodeler/pmsorsegment.cpp
new file mode 100644
index 00000000..966beb2b
--- /dev/null
+++ b/kpovmodeler/pmsorsegment.cpp
@@ -0,0 +1,97 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmsorsegment.h"
+#include "pmmath.h"
+#include "pmmatrix.h"
+#include "pmdebug.h"
+#include <math.h>
+
+PMVector PMSorSegment::point( double t ) const
+{
+ t = m_t + t * m_s;
+ double r2 = t * ( t * ( t * m_a + m_b ) + m_c ) + m_d;
+ if( r2 < 0.0 )
+ r2 = 0.0;
+
+ return PMVector( sqrt( r2 ), t );
+}
+
+void PMSorSegment::calculateSor( const PMVector& p0, const PMVector& p1,
+ const PMVector& p2, const PMVector& p3 )
+{
+ double b[4], h;
+ PMMatrix m;
+
+ m_t = p1[1];
+ m_s = p2[1] - p1[1];
+
+ if( approxZero( p2[1] - p0[1] ) || approxZero( p3[1] - p1[1] ) )
+ {
+ kdError( PMArea ) << "Incorrect points in PMSorSegment::calculateSor\n";
+ m_a = m_b = m_c = m_d = 0.0;
+ return;
+ }
+
+ // interpolate the points
+ // see povray documentation
+
+ b[0] = p1[0] * p1[0];
+ b[1] = p2[0] * p2[0];
+ b[2] = 2.0 * p1[0] * ( p2[0] - p0[0] ) / ( p2[1] - p0[1] );
+ b[3] = 2.0 * p2[0] * ( p3[0] - p1[0] ) / ( p3[1] - p1[1] );
+
+ h = p1[1];
+
+ m[0][0] = h * h * h;
+ m[0][1] = h * h;
+ m[0][2] = h;
+ m[0][3] = 1.0;
+
+ m[2][0] = 3.0 * h * h;
+ m[2][1] = 2.0 * h;
+ m[2][2] = 1.0;
+ m[2][3] = 0.0;
+
+ h = p2[1];
+
+ m[1][0] = h * h * h;
+ m[1][1] = h * h;
+ m[1][2] = h;
+ m[1][3] = 1.0;
+
+ m[3][0] = 3.0 * h * h;
+ m[3][1] = 2.0 * h;
+ m[3][2] = 1.0;
+ m[3][3] = 0.0;
+
+ // Calculate the coefficients
+ // x = M^-1 * b;
+
+ m = m.inverse( );
+
+ m_a = b[0] * m[0][0] + b[1] * m[0][1] + b[2] * m[0][2] + b[3] * m[0][3];
+ m_b = b[0] * m[1][0] + b[1] * m[1][1] + b[2] * m[1][2] + b[3] * m[1][3];
+ m_c = b[0] * m[2][0] + b[1] * m[2][1] + b[2] * m[2][2] + b[3] * m[2][3];
+ m_d = b[0] * m[3][0] + b[1] * m[3][1] + b[2] * m[3][2] + b[3] * m[3][3];
+
+ if( approxZero( m_a ) ) m_a = 0.0;
+ if( approxZero( m_b ) ) m_b = 0.0;
+ if( approxZero( m_c ) ) m_c = 0.0;
+ if( approxZero( m_d ) ) m_d = 0.0;
+}
diff --git a/kpovmodeler/pmsorsegment.h b/kpovmodeler/pmsorsegment.h
new file mode 100644
index 00000000..f0c5a2ea
--- /dev/null
+++ b/kpovmodeler/pmsorsegment.h
@@ -0,0 +1,77 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSORSEGMENT_H
+#define PMSORSEGMENT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmvector.h"
+
+/**
+ * Helper class for sors
+ *
+ * Each instance of this class represents one sor segment. A point
+ * on the segment is given by the equation
+ *
+ * fi(t) = A[i] * t^3 + B[i] * t^2 + C[i] * t + D[i]
+ *
+ * with t ranging from 0 to 1.
+ */
+class PMSorSegment
+{
+public:
+ /**
+ * Standard constructor
+ */
+ PMSorSegment( )
+ {
+ m_a = m_b = m_c = m_d = 0.0;
+ }
+ /**
+ * Constructor that calculates the segment
+ */
+ PMSorSegment( const PMVector& p0, const PMVector& p1,
+ const PMVector& p2, const PMVector& p3 )
+ {
+ calculateSor( p0, p1, p2, p3 );
+ }
+
+ /**
+ * Returns a 2D vector with the point on the sor segment
+ */
+ PMVector point( double t ) const;
+ /**
+ * Returns the gradient on the sor
+ */
+ //PMVector gradient( double t ) const;
+
+ /**
+ * Calculates the sor parameters
+ */
+ void calculateSor( const PMVector& p0, const PMVector& p1,
+ const PMVector& p2, const PMVector& p3 );
+private:
+ double m_a, m_b, m_c, m_d;
+ double m_t, m_s;
+};
+
+#endif
diff --git a/kpovmodeler/pmsphere.cpp b/kpovmodeler/pmsphere.cpp
new file mode 100644
index 00000000..698b5352
--- /dev/null
+++ b/kpovmodeler/pmsphere.cpp
@@ -0,0 +1,411 @@
+/*
+**************************************************************************
+ pmsphere.cpp - description
+ -------------------
+ copyright : (C) 2001 by Philippe Van Hecke
+ email : lephiloux@tiscalinet.be
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmsphere.h"
+
+#include "pmxmlhelper.h"
+#include "pmsphereedit.h"
+#include "pmmemento.h"
+#include "pm3dcontrolpoint.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmdefaults.h"
+
+#include <klocale.h>
+
+/** default param for the sphere */
+const double c_defaultRadius = 0.5;
+const PMVector c_defaultCentre = PMVector( 0, 0, 0 );
+
+/** default sphere structure */
+PMViewStructure* PMSphere::s_pDefaultViewStructure = 0;
+
+int PMSphere::s_vStep = c_defaultSphereVSteps;
+int PMSphere::s_uStep = c_defaultSphereUSteps;
+int PMSphere::s_parameterKey = 0;
+
+PMDefinePropertyClass( PMSphere, PMSphereProperty );
+
+PMMetaObject* PMSphere::s_pMetaObject = 0;
+PMObject* createNewSphere( PMPart* part )
+{
+ return new PMSphere( part );
+}
+
+PMSphere::PMSphere( PMPart* part )
+ : Base( part )
+{
+ m_radius = c_defaultRadius;
+ m_centre = c_defaultCentre;
+}
+
+PMSphere::PMSphere( const PMSphere& s )
+ : Base( s )
+{
+ m_radius = s.m_radius;
+ m_centre = s.m_centre;
+}
+
+PMSphere::~PMSphere( )
+{
+}
+
+
+QString PMSphere::description( ) const
+{
+ return i18n( "sphere" );
+}
+
+PMMetaObject* PMSphere::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Sphere", Base::metaObject( ),
+ createNewSphere );
+ s_pMetaObject->addProperty(
+ new PMSphereProperty( "radius", &PMSphere::setRadius, &PMSphere::radius ) );
+ s_pMetaObject->addProperty(
+ new PMSphereProperty( "center", &PMSphere::setCentre, &PMSphere::centre ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMSphere::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "centre", m_centre.serializeXML( ) );
+ e.setAttribute( "radius", m_radius );
+ Base::serialize( e, doc );
+}
+
+void PMSphere::readAttributes( const PMXMLHelper& h )
+{
+ m_centre = h.vectorAttribute( "centre", c_defaultCentre );
+ m_radius = h.doubleAttribute( "radius", c_defaultRadius );
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMSphere::editWidget( QWidget* parent ) const
+{
+
+ return new PMSphereEdit( parent );
+}
+
+void PMSphere::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMRadiusID:
+ setRadius( data->doubleData( ) );
+ break;
+ case PMCentreID:
+ setCentre( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PSphere::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+
+}
+
+void PMSphere::controlPoints( PMControlPointList& list )
+{
+ PM3DControlPoint* p = new PM3DControlPoint( m_centre, PMCentreID,
+ i18n( "Center" ) );
+ list.append( p );
+ list.append( new PMDistanceControlPoint( p, PMVector( 1.0, 0.0, 0.0 ),
+ m_radius, PMRadiusID,
+ i18n( "Radius (x)" ) ) );
+ list.append( new PMDistanceControlPoint( p, PMVector( 0.0, 1.0, 0.0 ),
+ m_radius, PMRadiusID,
+ i18n( "Radius (y)" ) ) );
+ list.append( new PMDistanceControlPoint( p, PMVector( 0.0, 0.0, 1.0 ),
+ m_radius, PMRadiusID,
+ i18n( "Radius (z)" ) ) );
+}
+
+void PMSphere::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+ bool radiusChanged = false;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMCentreID:
+ setCentre( ( ( PM3DControlPoint* ) p )->point( ) );
+ break;
+ case PMRadiusID:
+ setRadius( ( ( PMDistanceControlPoint* ) p )->distance( ) );
+ radiusChanged = true;
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSphere::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+
+ if( radiusChanged )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMRadiusID )
+ ( ( PMDistanceControlPoint* ) p )->setDistance( m_radius );
+}
+
+bool PMSphere::isDefault( )
+{
+ if( ( m_radius == c_defaultRadius ) && ( m_centre == c_defaultCentre ) && globalDetail( ) )
+ return true;
+ return false;
+}
+
+void PMSphere::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( displayDetail( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( displayDetail( ) + 1 ) );
+ unsigned ptsSize = vStep * ( uStep - 1 ) + 2;
+ unsigned lineSize = vStep * ( uStep - 1 ) * 2 + vStep;
+ unsigned faceSize = vStep * uStep;
+
+ if( ptsSize != m_pViewStructure->points( ).size( ) )
+ m_pViewStructure->points( ).resize( ptsSize );
+
+ createPoints( m_pViewStructure->points( ), m_centre, m_radius, uStep, vStep );
+
+ if( lineSize != m_pViewStructure->lines( ).size( ) )
+ {
+ m_pViewStructure->lines( ).detach( );
+ m_pViewStructure->lines( ).resize( lineSize );
+ createLines( m_pViewStructure->lines( ), uStep, vStep );
+ }
+
+ if( faceSize != m_pViewStructure->faces( ).size( ) )
+ {
+ m_pViewStructure->faces( ).resize( faceSize );
+ createFaces( m_pViewStructure->faces( ), uStep, vStep );
+ }
+}
+
+PMViewStructure* PMSphere::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
+
+ s_pDefaultViewStructure =
+ new PMViewStructure( vStep * ( uStep - 1 ) + 2,
+ vStep * ( uStep - 1 ) * 2 + vStep,
+ vStep * uStep );
+
+ // points
+ createPoints( s_pDefaultViewStructure->points( ), c_defaultCentre,
+ c_defaultRadius, uStep, vStep );
+ //lines
+ createLines( s_pDefaultViewStructure->lines( ), uStep, vStep );
+
+ //faces
+ createFaces( s_pDefaultViewStructure->faces( ), uStep, vStep );
+ }
+
+ return s_pDefaultViewStructure;
+}
+
+void PMSphere::createFaces( PMFaceArray& faces, int uStep, int vStep )
+{
+ int u, v, offsetPt1, offsetPt2, offsetFace;
+
+ offsetPt1 = vStep * ( uStep - 1 ) + 1;
+ offsetPt2 = vStep * ( uStep - 2 ) + 1;
+ offsetFace = vStep * ( uStep - 1 );
+ for( v = 0; v < vStep - 1; ++v )
+ {
+ faces[v] = PMFace( 0, v + 2, v + 1 );
+ faces[ offsetFace + v ] = PMFace( offsetPt1, v + offsetPt2, v + offsetPt2 + 1 );
+ }
+
+ faces[ vStep - 1 ] = PMFace( 0, 1, vStep );
+ faces[ offsetFace + vStep - 1 ] = PMFace( offsetPt1, vStep + offsetPt2 - 1, offsetPt2 );
+
+ offsetFace = vStep;
+ for( u = 0; u < ( uStep - 2 ); ++u )
+ {
+ offsetPt1 = ( u * vStep ) + 1;
+ offsetPt2 = ( ( u + 1 ) * vStep ) + 1;
+ for( v = 0; v < ( vStep - 1 ); ++v )
+ faces[ offsetFace + v ] = PMFace( v + offsetPt1, v + offsetPt1 + 1, v + offsetPt2 + 1, v + offsetPt2 );
+ faces[ offsetFace + vStep - 1 ] = PMFace( offsetPt1 + vStep - 1, offsetPt1, offsetPt2, offsetPt2 + vStep - 1 );
+ offsetFace += vStep;
+ }
+}
+
+void PMSphere::createLines( PMLineArray& lines, int uStep, int vStep )
+{
+ int u, v;
+ int offset = 0;
+
+ // horizontal lines
+ for( u = 0; u < ( uStep - 1 ); u++ )
+ {
+ for( v = 0; v < ( vStep - 1 ); v++ )
+ lines[offset + v] =
+ PMLine( u * vStep + v + 1, u * vStep + v + 2 );
+ lines[offset + vStep - 1] =
+ PMLine( u * vStep + 1, u * vStep + vStep );
+
+ offset += vStep;
+ }
+
+ // vertical lines
+ // lines at the "north pole"
+ for( v = 0; v < vStep; v++ )
+ lines[offset + v] = PMLine( 0, v + 1 );
+ offset += vStep;
+
+ for( v = 0; v < vStep; v++ )
+ {
+ for( u = 0; u < ( uStep - 2 ); u++ )
+ {
+ lines[offset + u] =
+ PMLine( u * vStep + v + 1, ( u + 1 ) * vStep + v + 1 );
+ }
+ offset += ( uStep - 2 );
+ }
+ // lines at the "south pole"
+ for( v = 0; v < vStep; v++ )
+ lines[offset + v] = PMLine( ( uStep - 2 ) * vStep + v + 1,
+ ( uStep - 1 ) * vStep + 1 );
+ // offset += s_vStep;
+}
+
+void PMSphere::createPoints( PMPointArray& points, const PMVector& centre, double radius,
+ int uStep, int vStep )
+{
+ double l_UradStep = M_PI / uStep;
+ double l_VradStep = ( 2.0 * M_PI ) / vStep;
+ double l_u = l_UradStep;
+ int u, v;
+
+ points[0] = PMPoint( centre + PMVector( 0, radius, 0 ) );
+ points[ vStep * ( uStep - 1 ) + 1] = PMPoint( centre - PMVector( 0, radius, 0 ) );
+
+ for( u = 0; u < ( uStep - 1 ); u++ )
+ {
+ double l_v = 0.0;
+ double l_rcosu = radius * sin( l_u );
+ double y = ( radius * cos( l_u ) ) + centre[1];
+ for( v = 0; v < vStep ; v++ )
+ {
+
+ double x = ( l_rcosu * cos( l_v ) ) + centre[0];
+ double z = ( l_rcosu * sin( l_v ) ) + centre[2];
+
+ points[u * vStep + v + 1] = PMPoint( x, y, z );
+ l_v = l_v + l_VradStep;
+ }
+ l_u = l_u + l_UradStep;
+ }
+}
+
+void PMSphere::setRadius( double radius )
+{
+ if( m_radius != radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusID, m_radius );
+ m_radius = radius;
+ setViewStructureChanged( );
+ }
+}
+
+void PMSphere::setCentre( const PMVector& centre )
+{
+ if( m_centre != centre )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMCentreID, m_centre );
+ m_centre = centre;
+ setViewStructureChanged( );
+ }
+}
+
+void PMSphere::setUSteps( int u )
+{
+ if( u >= 2 )
+ {
+ s_uStep = u;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMSPhere::setUSteps: U must be greater than 1\n";
+ s_parameterKey++;
+}
+
+void PMSphere::setVSteps( int v )
+{
+ if( v >= 4 )
+ {
+ s_vStep = v;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMSphere::setVSteps: V must be greater than 3\n";
+ s_parameterKey++;
+}
+
+void PMSphere::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmsphere.h b/kpovmodeler/pmsphere.h
new file mode 100644
index 00000000..876fd103
--- /dev/null
+++ b/kpovmodeler/pmsphere.h
@@ -0,0 +1,165 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ pmsphere.h - description
+ -------------------
+ copyright : (C) 2001 by Philippe Van Hecke
+ email : lephiloux@tiscalinet.be
+ and : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSPHERE_H
+#define PMSPHERE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include "pmviewstructure.h"
+
+/**
+ * Class for povray sphere.
+ */
+class PMSphere : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+
+public:
+ /**
+ * Create an empty Sphere
+ */
+ PMSphere( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSphere( const PMSphere& s );
+ /**
+ * Delete the PMSphere
+ */
+ virtual ~PMSphere( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMSphere( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMSphereEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmsphere" ); }
+
+ /**
+ * Returns the centre of the sphere
+ */
+ PMVector centre( ) const { return m_centre; }
+ /**
+ * Set the centre of the sphere
+ */
+ void setCentre( const PMVector& centre );
+ /**
+ * returns the radius of the sphere
+ */
+ double radius( ) const { return m_radius; }
+ /**
+ * Sets the radius of the sphere
+ */
+ void setRadius( double radius );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+
+ /**
+ * Sets the number of latitutes
+ */
+ static void setUSteps( int u );
+ /**
+ * Sets the number of longitudes
+ */
+ static void setVSteps( int v );
+ /**
+ * Returns the number or latitutes
+ */
+ static int uSteps( ) { return s_uStep; }
+ /**
+ * Returns the number or longitudes
+ */
+ static int vSteps( ) { return s_vStep; }
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey(); }
+
+private:
+ /**
+ * Creates the faces for the view structure
+ */
+ static void createFaces( PMFaceArray& faces, int uStep, int vStep );
+ /**
+ * Creates the lines for the view structure
+ */
+ static void createLines( PMLineArray& lines, int uStep, int vStep );
+ /**
+ * Creates the points for the view structure
+ */
+ static void createPoints( PMPointArray& points, const PMVector& centre,
+ double radius, int uStep, int vStep );
+
+ enum PMSphereMementoID { PMRadiusID, PMCentreID };
+ /**
+ * Radius of the sphere
+ */
+ double m_radius;
+ /**
+ * centre of the sphere
+ */
+ PMVector m_centre;
+
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_vStep;
+ static int s_uStep;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmsphereedit.cpp b/kpovmodeler/pmsphereedit.cpp
new file mode 100644
index 00000000..cb46d513
--- /dev/null
+++ b/kpovmodeler/pmsphereedit.cpp
@@ -0,0 +1,95 @@
+/*
+**************************************************************************
+
+ pmsphereedit.cpp - description
+ -------------------
+ begin : Wed Jun 6 2001
+ copyright : (C) 2001 by Philippe Van Hecke
+ email : lephiloux@tiscalinet.be
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmsphereedit.h"
+#include "pmsphere.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+PMSphereEdit::PMSphereEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMSphereEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* layout;
+
+ m_pCentre = new PMVectorEdit( "x", "y", "z", this );
+ m_pRadius = new PMFloatEdit( this );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Center:" ), this ) );
+ layout->addWidget( m_pCentre );
+
+ layout = new QHBoxLayout( topLayout( ) );
+ layout->addWidget( new QLabel( i18n( "Radius:" ), this ) );
+ layout->addWidget( m_pRadius );
+ layout->addStretch( 1 );
+
+ connect( m_pCentre, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMSphereEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Sphere" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMSphere* ) o;
+
+ m_pCentre->setVector( m_pDisplayedObject->centre( ) );
+ m_pRadius->setValue( m_pDisplayedObject->radius( ) );
+
+ m_pCentre->setReadOnly( readOnly );
+ m_pRadius->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMSphereEdit: Can't display object\n";
+}
+
+void PMSphereEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setCentre( m_pCentre->vector( ) );
+ m_pDisplayedObject->setRadius( m_pRadius->value( ) );
+ }
+}
+
+bool PMSphereEdit::isDataValid( )
+{
+ if( m_pCentre->isDataValid( ) )
+ if( m_pRadius->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+
+#include "pmsphereedit.moc"
diff --git a/kpovmodeler/pmsphereedit.h b/kpovmodeler/pmsphereedit.h
new file mode 100644
index 00000000..9cd64d86
--- /dev/null
+++ b/kpovmodeler/pmsphereedit.h
@@ -0,0 +1,64 @@
+/*
+**************************************************************************
+
+ pmsphereedit.h - description
+ -------------------
+ begin : Wed Jun 6 2001
+ copyright : (C) 2001 by Philippe Van Hecke
+ email : lephiloux@tiscalinet.be
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMSPHEREEDIT_H
+#define PMSPHEREEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMSphere;
+class PMVectorEdit;
+class PMFloatEdit ;
+
+/**
+ * Dialog edit class for @ref PMSphere
+ */
+class PMSphereEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMSphereEdit with parent and name
+ */
+ PMSphereEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMSphere* m_pDisplayedObject;
+ PMVectorEdit* m_pCentre;
+ PMFloatEdit* m_pRadius;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmspheresweep.cpp b/kpovmodeler/pmspheresweep.cpp
new file mode 100644
index 00000000..f65a029e
--- /dev/null
+++ b/kpovmodeler/pmspheresweep.cpp
@@ -0,0 +1,894 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmspheresweep.h"
+
+#include "pmxmlhelper.h"
+#include "pmspheresweepedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm3dcontrolpoint.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmsplinememento.h"
+#include "pmdefaults.h"
+#include "pmenumproperty.h"
+#include "pmobjectaction.h"
+#include "pmpoint.h"
+#include "pmmatrix.h"
+
+#include <klocale.h>
+
+const int defaultNumberOfPoints = 2;
+const PMVector defaultPoint[defaultNumberOfPoints] =
+{
+ PMVector( 0.0, 1.0, 0.0 ),
+ PMVector( 0.0, 0.0, 0.0 )
+};
+const double defaultRadii[defaultNumberOfPoints] =
+{
+ 0.3, 0.5
+};
+
+const double defaultTolerance = 1e-6;
+const PMSphereSweep::SplineType defaultSplineType = PMSphereSweep::LinearSpline;
+
+PMDefinePropertyClass( PMSphereSweep, PMSphereSweepProperty );
+PMDefineEnumPropertyClass( PMSphereSweep, PMSphereSweep::SplineType, PMSplineTypeProperty );
+
+PMMetaObject* PMSphereSweep::s_pMetaObject = 0;
+PMObject* createNewSphereSweep( PMPart* part )
+{
+ return new PMSphereSweep( part );
+}
+
+int PMSphereSweep::s_rSteps = c_defaultSphereSweepRSteps;
+int PMSphereSweep::s_sSteps = c_defaultSphereSweepSSteps;
+int PMSphereSweep::s_parameterKey = 0;
+
+
+/**
+ * Memento for @ref PMLathe
+ */
+class PMSphereSweepMemento : public PMSplineMemento
+{
+public:
+ /**
+ * Creates a memento for the object originator
+ */
+ PMSphereSweepMemento( PMObject* originator )
+ : PMSplineMemento( originator )
+ {
+ m_bRadiiSaved = false;
+ }
+ /**
+ * Deletes the memento
+ */
+ virtual ~PMSphereSweepMemento( ) { };
+
+ /**
+ * Saves the radii
+ */
+ void setRadii( const QValueList<double>& r )
+ {
+ if( !m_bRadiiSaved )
+ {
+ // Direct assignment does not work with Qt 2.3.x
+ // The list will be changed later in a graphical
+ // change because QValueList::detach( ) is called
+ // too late!
+ // Copy the list by hand.
+
+ QValueList<double>::ConstIterator it = r.begin( );
+ for( ; it != r.end( ); ++it )
+ m_radii.append( *it );
+
+ m_bRadiiSaved = true;
+ addChange( PMCData );
+ }
+ }
+ /**
+ * Returns the radii
+ */
+ QValueList<double> radii( ) const
+ {
+ if( !m_bRadiiSaved )
+ kdError( PMArea ) << "Radii points not saved in PMSphereSweepMemento::radii\n";
+ return m_radii;
+ }
+ /**
+ * Returns true if the spline points were saved
+ */
+ bool radiiSaved( ) const { return m_bRadiiSaved; }
+
+private:
+ /**
+ * The stored radii
+ */
+ QValueList<double> m_radii;
+ bool m_bRadiiSaved;
+};
+
+
+PMSphereSweep::PMSphereSweep( PMPart* part )
+ : Base( part )
+{
+ int i;
+
+ for( i = 0; i < defaultNumberOfPoints; i++ )
+ {
+ m_points.append( defaultPoint[i] );
+ m_radii.append( defaultRadii[i] );
+ }
+ m_splineType = defaultSplineType;
+ m_tolerance = defaultTolerance;
+}
+
+PMSphereSweep::PMSphereSweep( const PMSphereSweep& l )
+ : Base( l )
+{
+ m_points = l.m_points;
+ m_radii = l.m_radii;
+ m_splineType = l.m_splineType;
+ m_tolerance = l.m_tolerance;
+}
+
+PMSphereSweep::~PMSphereSweep( )
+{
+}
+
+QString PMSphereSweep::description( ) const
+{
+ return i18n( "sphere sweep" );
+}
+
+void PMSphereSweep::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ QDomElement data = doc.createElement( "extra_data" );
+ QDomElement p;
+
+ e.setAttribute( "spline_type", m_splineType );
+ e.setAttribute( "tolerance", m_tolerance );
+
+ QValueList<PMVector>::ConstIterator it;
+ QValueList<double>::ConstIterator it2;
+ for( it = m_points.begin( ), it2 = m_radii.begin( );
+ it != m_points.end( ) && it2 != m_radii.end( ); ++it, ++it2 )
+ {
+ p = doc.createElement( "point" );
+ p.setAttribute( "vector", ( *it ).serializeXML( ) );
+ p.setAttribute( "radius", *it2 );
+ data.appendChild( p );
+ }
+
+ e.appendChild( data );
+ Base::serialize( e, doc );
+}
+
+void PMSphereSweep::readAttributes( const PMXMLHelper& h )
+{
+ m_splineType = ( SplineType ) h.intAttribute( "spline_type", defaultSplineType );
+ m_tolerance = h.doubleAttribute( "tolerance", defaultTolerance );
+
+ m_points.clear( );
+ m_radii.clear( );
+ PMVector v( 3 );
+
+ QDomElement e = h.extraData( );
+ if( !e.isNull( ) )
+ {
+ QDomNode c = e.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ if( ce.tagName( ) == "point" )
+ {
+ QString str = ce.attribute( "vector" );
+ if( !str.isNull( ) )
+ {
+ v.loadXML( str );
+ m_points.append( v );
+ QString str = ce.attribute( "radius" );
+ m_radii.append( str.toDouble( ) );
+ }
+ }
+ }
+ c = c.nextSibling( );
+ }
+ }
+
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMSphereSweep::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "SphereSweep", Base::metaObject( ),
+ createNewSphereSweep );
+ s_pMetaObject->addProperty(
+ new PMSphereSweepProperty( "tolerance", &PMSphereSweep::setTolerance, &PMSphereSweep::tolerance ) );
+ PMSplineTypeProperty* p = new PMSplineTypeProperty(
+ "splineType", &PMSphereSweep::setSplineType, &PMSphereSweep::splineType );
+ p->addEnumValue( "LinearSpline", LinearSpline );
+ p->addEnumValue( "BSpline", BSpline );
+ p->addEnumValue( "CubicSpline", CubicSpline );
+ s_pMetaObject->addProperty( p );
+ //s_pMetaObject->addProperty( new PMPointProperty( ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMSphereSweep::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMSphereSweep::setSplineType( PMSphereSweep::SplineType t )
+{
+ if( m_splineType != t )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSplineTypeID, ( int ) m_splineType );
+ setViewStructureChanged( );
+ m_splineType = t;
+ }
+}
+
+void PMSphereSweep::setTolerance( double t )
+{
+ if( m_tolerance != t )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMToleranceID, m_tolerance );
+ m_tolerance = t;
+ }
+}
+
+void PMSphereSweep::setPoints( const QValueList<PMVector>& points )
+{
+ if( m_points != points )
+ {
+ if( m_pMemento )
+ ( ( PMSplineMemento* ) m_pMemento )->setSplinePoints( m_points );
+
+ setViewStructureChanged( );
+ m_points = points;
+ }
+}
+
+void PMSphereSweep::setRadii( const QValueList<double>& radii )
+{
+ if( m_radii != radii )
+ {
+ if( m_pMemento )
+ ( ( PMSphereSweepMemento* ) m_pMemento )->setRadii( m_radii );
+
+ setViewStructureChanged( );
+ m_radii = radii;
+ }
+}
+
+PMDialogEditBase* PMSphereSweep::editWidget( QWidget* parent ) const
+{
+ return new PMSphereSweepEdit( parent );
+}
+
+void PMSphereSweep::createMemento( )
+{
+ if( m_pMemento )
+ delete m_pMemento;
+ m_pMemento = new PMSphereSweepMemento( this );
+}
+
+void PMSphereSweep::restoreMemento( PMMemento* s )
+{
+ PMSphereSweepMemento* m = ( PMSphereSweepMemento* ) s;
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMSplineTypeID:
+ setSplineType( ( SplineType ) data->intData( ) );
+ break;
+ case PMToleranceID:
+ setTolerance( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSphereSweep::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ if( m->splinePointsSaved( ) )
+ setPoints( m->splinePoints( ) );
+ if( m->radiiSaved( ) )
+ setRadii( m->radii( ) );
+
+ Base::restoreMemento( s );
+}
+
+
+void PMSphereSweep::createViewStructure( )
+{
+ int numSegments = 0;
+ int numSpheres = m_points.size( );
+ m_segments.clear( );
+
+ int rSteps = (int)( ( (float)s_rSteps / 2 ) * ( displayDetail( ) + 1 ) );
+ int sSteps = (int)( ( (float)s_sSteps / 2 ) * ( displayDetail( ) + 1 ) );
+
+ switch ( m_splineType )
+ {
+ case LinearSpline:
+ numSegments = numSpheres - 1;
+ setLinear( sSteps );
+ break;
+ case BSpline:
+ numSegments = numSpheres - 3;
+ setCurved( false, sSteps );
+ break;
+ case CubicSpline:
+ numSegments = numSpheres - 3;
+ setCurved( true, sSteps );
+ break;
+ }
+
+ //Calculates sphere points
+ int numPoints = ( ( rSteps * ( rSteps - 2 ) ) + 2 ) *
+ ( numSegments + 1 );
+ //Calculates segments points
+ numPoints += ( rSteps * sSteps ) * numSegments;
+
+ //Calculates sphere lines
+ int numLines = ( rSteps * ( rSteps + rSteps - 3 ) ) *
+ ( numSegments + 1 );
+ //Calculates segments lines
+ numLines += ( ( sSteps * rSteps ) +
+ ( ( sSteps - 1 ) * rSteps ) ) * numSegments;
+
+ if ( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( numPoints, numLines );
+ }
+ else
+ {
+ m_pViewStructure->points( ).resize( numPoints );
+ m_pViewStructure->lines( ).resize( numLines );
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+ PMLineArray& lines = m_pViewStructure->lines( );
+ m_nextPoint = m_nextLine = 0;
+
+ PMVector v1, v2;
+ double rotval = M_PI / ( rSteps / 2 );
+
+ createSphere( m_segments[0].points[0], m_segments[0].radii[0], rSteps );
+ for ( int i = 0; i < numSegments; ++i )
+ {
+ for ( int j = 0; j < sSteps; ++ j )
+ {
+ v1 = m_segments[i].points[sSteps] - m_segments[i].points[0];
+ v1 = PMVector::cross( m_segments[i].direction[j], v1.orthogonal( ) );
+ v1 = ( v1 * ( 1 / v1.abs( ) ) ) * m_segments[i].radii[j];
+
+ for ( int k = 0; k < rSteps; ++k )
+ {
+ v2 = PMMatrix::rotation( m_segments[i].direction[j],
+ ( rotval * k ) ) * v1;
+ points[m_nextPoint++] = PMPoint( v2 + m_segments[i].points[j] );
+ if ( k < ( rSteps - 1 ) )
+ lines[m_nextLine++] = PMLine(
+ m_nextPoint - 1, m_nextPoint );
+ else
+ lines[m_nextLine++] = PMLine(
+ m_nextPoint - 1, m_nextPoint - rSteps );
+
+ if ( j < ( sSteps - 1 ) )
+ {
+ lines[m_nextLine++] = PMLine(
+ m_nextPoint - 1, m_nextPoint + ( rSteps - 1 ) );
+ }
+ }
+ }
+ createSphere( m_segments[i].points[sSteps - 1],
+ m_segments[i].radii[sSteps - 1], rSteps );
+ }
+}
+
+void PMSphereSweep::controlPoints( PMControlPointList& list )
+{
+ QValueList<PMVector>::Iterator it;
+ QValueList<double>::Iterator it2;
+ int i, nr;
+
+ for( it = m_points.begin( ), it2 = m_radii.begin( ), nr = 1, i = 0;
+ it != m_points.end( ) && it2 != m_radii.end( ); ++it, ++it2, ++nr )
+ {
+ PM3DControlPoint* p = new PM3DControlPoint( *it, i++,
+ i18n( "Center %1" ).arg( nr ) );
+ list.append( p );
+ list.append( new PMDistanceControlPoint( p, PMVector( 1.0, 0.0, 0.0 ),
+ *it2, i++,
+ i18n( "Radius %1 (x)" ).arg( nr ),
+ true ) );
+ list.append( new PMDistanceControlPoint( p, PMVector( 0.0, 1.0, 0.0 ),
+ *it2, i++,
+ i18n( "Radius %1 (y)" ).arg( nr ),
+ true ) );
+ list.append( new PMDistanceControlPoint( p, PMVector( 0.0, 0.0, 1.0 ),
+ *it2, i++,
+ i18n( "Radius %1 (z)" ).arg( nr ),
+ true ) );
+ }
+}
+
+void PMSphereSweep::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPointListIterator it1( list );
+ QValueList<PMVector>::Iterator pit = m_points.begin( );
+ QValueList<double>::Iterator rit = m_radii.begin( );
+ int i;
+ PM3DControlPoint* p;
+ PMDistanceControlPoint* r;
+ bool firstChange = true;
+
+ for( ; it1.current( ) && pit != m_points.end( ) && rit != m_radii.end( );
+ ++pit, ++rit )
+ {
+ p = ( PM3DControlPoint* ) it1.current( );
+ if( p->changed( ) )
+ {
+ if( firstChange )
+ {
+ firstChange = false;
+ setViewStructureChanged( );
+ }
+ if( m_pMemento )
+ {
+ PMSphereSweepMemento* m = ( PMSphereSweepMemento* ) m_pMemento;
+ if( !m->splinePointsSaved( ) )
+ m->setSplinePoints( m_points );
+ }
+ ( *pit ) = p->point( );
+ }
+ ++it1;
+
+ for( i = 0; i < 3 && it1.current( ); i++ )
+ {
+ r = ( PMDistanceControlPoint* ) it1.current( );
+ if( r->changed( ) )
+ {
+ if( firstChange )
+ {
+ firstChange = false;
+ setViewStructureChanged( );
+ }
+ if( m_pMemento )
+ {
+ PMSphereSweepMemento* m = ( PMSphereSweepMemento* ) m_pMemento;
+ if( !m->radiiSaved( ) )
+ m->setRadii( m_radii );
+ }
+ ( *rit ) = r->distance( );
+ }
+ ++it1;
+ }
+ }
+
+ for( it1.toFirst( ), rit = m_radii.begin( ); rit != m_radii.end( ); ++rit )
+ {
+ ++it1;
+ for( i = 0; i < 3; ++i, ++it1 )
+ ( ( PMDistanceControlPoint* ) *it1 )->setDistance( *rit );
+ }
+}
+
+void PMSphereSweep::addObjectActions( const PMControlPointList& /*cp*/,
+ QPtrList<PMObjectAction>& actions )
+{
+ PMObjectAction* a;
+
+ a = new PMObjectAction( s_pMetaObject, PMSplitSegmentID,
+ i18n( "Add Sphere" ) );
+ actions.append( a );
+
+ a = new PMObjectAction( s_pMetaObject, PMJoinSegmentsID,
+ i18n( "Remove Sphere" ) );
+ int np = m_points.count( );
+ int minp = 2;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ minp = 2;
+ break;
+ case BSpline:
+ minp = 4;
+ break;
+ case CubicSpline:
+ minp = 4;
+ break;
+ }
+
+ if( np < minp )
+ a->setEnabled( false );
+ actions.append( a );
+}
+
+void PMSphereSweep::objectActionCalled( const PMObjectAction* action,
+ const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ if( action->objectType( ) == s_pMetaObject )
+ {
+ switch( action->actionID( ) )
+ {
+ case PMSplitSegmentID:
+ splitSegment( cp, cpViewPosition, clickPosition );
+ break;
+ case PMJoinSegmentsID:
+ joinSegments( cp, cpViewPosition, clickPosition );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSphereSweep::objectActionCalled\n";
+ break;
+ }
+ }
+ else
+ Base::objectActionCalled( action, cp, cpViewPosition, clickPosition );
+}
+
+void PMSphereSweep::splitSegment( const PMControlPointList& /*cp*/,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ // find nearest segment
+ int nump = cpViewPosition.count( ) / 4 - 1;
+ double abs = 0.0, minabs = 1e10;
+ int ns = -1;
+ int i, j;
+ PMVector mid( 3 ), dist( 2 );
+
+ QPtrListIterator<PMVector> it1( cpViewPosition );
+ QPtrListIterator<PMVector> it2( cpViewPosition );
+ ++it2;
+
+ for( i = 0; i < nump; i++ )
+ {
+ bool skip = false;
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ break;
+ case BSpline:
+ case CubicSpline:
+ if( ( i == 0 ) || ( i == ( nump - 1 ) ) )
+ skip = true;
+ break;
+ }
+
+ if( !skip )
+ {
+ mid = ( **it1 + **it2 ) / 2.0;
+ dist[0] = mid[0];
+ dist[1] = mid[1];
+ dist -= clickPosition;
+ abs = dist.abs( );
+
+ if( ( minabs > abs ) || ( ns < 0 ) )
+ {
+ minabs = abs;
+ ns = i;
+ }
+ }
+ for( j = 0; j < 4; j++ )
+ {
+ ++it1;
+ ++it2;
+ }
+ }
+
+ // add a new segment
+ QValueList<PMVector> newPoints = m_points;
+ QValueList<double> newRadii = m_radii;
+
+ QValueList<PMVector>::Iterator it = newPoints.at( ( unsigned ) ns );
+ QValueList<PMVector>::Iterator hit = it;
+ ++it;
+ mid = ( *it + *hit ) / 2;
+ newPoints.insert( it, mid );
+
+ QValueList<double>::Iterator rit = newRadii.at( ( unsigned ) ns );
+ QValueList<double>::Iterator rhit = rit;
+ ++rit;
+ newRadii.insert( rit, ( *rit + *rhit ) / 2 );
+
+ setPoints( newPoints );
+ setRadii( newRadii );
+}
+
+void PMSphereSweep::joinSegments( const PMControlPointList& /*cp*/,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition )
+{
+ // find nearest point
+ int nump = cpViewPosition.count( ) / 4;
+ int minp = 0;
+
+ switch( m_splineType )
+ {
+ case LinearSpline:
+ minp = 3;
+ break;
+ case BSpline:
+ case CubicSpline:
+ minp = 5;
+ break;
+ }
+
+ if( nump < minp )
+ {
+ kdError( PMArea ) << "Not enough points in PMSphereSweep::joinSegments\n";
+ return;
+ }
+
+ double abs = 0.0, minabs = 1e10;
+ int ns = -1;
+ int i, j;
+ PMVector* p;
+ PMVector dist( 2 );
+
+ QPtrListIterator<PMVector> it1( cpViewPosition );
+
+ for( i = 0; i < nump; i++ )
+ {
+ p = *it1;
+ dist[0] = (*p)[0];
+ dist[1] = (*p)[1];
+ dist -= clickPosition;
+ abs = dist.abs( );
+
+ if( ( minabs > abs ) || ( ns < 0 ) )
+ {
+ minabs = abs;
+ ns = i;
+ }
+ for( j = 0; j < 4; j++ )
+ ++it1;
+ }
+
+ // join two segments
+ QValueList<PMVector> newPoints = m_points;
+ QValueList<PMVector>::Iterator it;
+ QValueList<double> newRadii = m_radii;
+ QValueList<double>::Iterator rit;
+
+ // never remove the first or last point
+ if( ns == 0 )
+ ns++;
+ if( ns == ( nump - 1 ) )
+ ns--;
+ it = newPoints.at( ns );
+ newPoints.remove( it );
+ rit = newRadii.at( ns );
+ newRadii.remove( rit );
+
+ setPoints( newPoints );
+ setRadii( newRadii );
+}
+
+void PMSphereSweep::setRSteps( int r )
+{
+ if( r >= 4 )
+ s_rSteps = r;
+ else
+ kdDebug( PMArea ) << "PMSphereSweep::setRSteps: R must be greater than 3\n";
+ s_parameterKey++;
+}
+
+void PMSphereSweep::setSSteps( int s )
+{
+ if( s >= 1 )
+ s_sSteps = s;
+ else
+ kdDebug( PMArea ) << "PMSphereSweep::setSSteps: S must be greater than 0\n";
+ s_parameterKey++;
+}
+
+void PMSphereSweep::setLinear( int sSteps )
+{
+ int numsegments = ( m_points.size( ) - 1 );
+
+ double raddif;
+ PMVector diff, angle;
+ Segment seg;
+
+ for ( int i = 0; i < numsegments; ++i )
+ {
+ seg.points.clear( );
+ seg.radii.clear( );
+ seg.direction.clear( );
+ diff = ( m_points[i + 1] - m_points[i] ) / ( sSteps - 1.0 );
+ raddif = ( m_radii[i + 1] - m_radii[i] ) / ( sSteps - 1.0 );
+ angle = diff * ( 1 / diff.abs( ) );
+
+ for ( int j = 0; j < sSteps; ++j )
+ {
+ seg.points.append( m_points[i] + ( diff * j ) );
+ seg.radii.append( m_radii[i] + ( raddif * j ) );
+ seg.direction.append( angle );
+ }
+ m_segments.append( seg );
+ }
+}
+
+void PMSphereSweep::setCurved( bool cubic, int sSteps )
+{
+ int numsegments = ( m_points.size( ) - 3 );
+ PMVector centres[4];
+ PMVector vtr;
+ double divs = 1.0 / ( sSteps - 1.0 );
+ double raddif;
+ Segment seg;
+
+ for ( int i = 0; i < numsegments; ++i )
+ {
+ seg.points.clear( );
+ seg.radii.clear( );
+ seg.direction.clear( );
+ raddif = ( m_radii[i + 2] - m_radii[i + 1] ) / ( sSteps - 1.0 );
+ for ( int j = 0; j < 4; ++j )
+ centres[j] = m_points[ i + j ];
+
+ for ( int j = 0; j < sSteps; ++j )
+ {
+ if ( cubic )
+ seg.points.append( catmullRom( centres, ( divs * j ) ) );
+ else
+ seg.points.append( bSpline( centres, ( divs * j ) ) );
+
+ seg.radii.append( m_radii[i + 1] + ( raddif * j ) );
+ }
+
+ seg.direction.append( seg.points[0] - seg.points[1] );
+ for ( int j = 1; j < ( sSteps - 1 ) ; ++ j )
+ {
+ vtr = seg.points[ j - 1 ] - seg.points[j];
+ vtr += seg.points[j] - seg.points[ j + 1 ];
+ seg.direction.append( vtr );
+ }
+ seg.direction.append( seg.points[ sSteps - 2 ] -
+ seg.points[ sSteps - 1 ] );
+
+ m_segments.append( seg );
+ }
+}
+
+PMVector PMSphereSweep::catmullRom( PMVector *v, double t )
+{
+ PMVector rst;
+ double t2 = t * t;
+ double t3 = t * t * t;
+
+ rst.setX( (
+ ( -t3 + 2 * t2 - t ) * v[0].x( ) +
+ ( 3 * t3 -5 * t2 + 2 ) * v[1].x( ) +
+ ( -3 * t3 + 4 * t2 + t ) * v[2].x( ) +
+ ( t3 - t2 ) * v[3].x( )
+ ) / 2
+ );
+ rst.setY( (
+ ( -t3 + 2 * t2 -t ) * v[0].y( ) +
+ ( 3 * t3 -5 * t2 + 2 ) * v[1].y( ) +
+ ( -3 * t3 + 4 * t2 + t ) * v[2].y( ) +
+ ( t3 - t2) * v[3].y( )
+ ) / 2
+ );
+ rst.setZ( (
+ ( -t3 + 2 * t2 - t ) * v[0].z( ) +
+ ( 3 * t3 -5 * t2 + 2 ) * v[1].z( ) +
+ ( -3 * t3 + 4 * t2 + t ) * v[2].z( ) +
+ ( t3 - t2 ) * v[3].z( )
+ ) / 2
+ );
+
+ return rst;
+}
+
+PMVector PMSphereSweep::bSpline( PMVector *v, double t )
+{
+ PMVector rst;
+ double t2 = t * t;
+ double t3 = t * t * t;
+
+ rst.setX( (
+ ( -t3 + 3 * t2 -3 * t + 1 ) * v[0].x( ) +
+ ( 3 * t3 -6 * t2 + 4 ) * v[1].x( ) +
+ ( -3 * t3 + 3 * t2 + 3 * t + 1 ) * v[2].x( ) +
+ ( t3 ) * v[3].x( )
+ ) / 6
+ );
+ rst.setY( (
+ ( -t3 + 3 * t2 -3 * t + 1 ) * v[0].y( ) +
+ ( 3 * t3 -6 * t2 + 4 ) * v[1].y( ) +
+ ( -3 * t3 + 3 * t2 + 3 * t + 1 ) * v[2].y( ) +
+ ( t3 ) * v[3].y( )
+ ) / 6
+ );
+ rst.setZ( (
+ ( -t3 + 3 * t2 -3 * t + 1 ) * v[0].z( ) +
+ ( 3 * t3 -6 * t2 + 4 ) * v[1].z( ) +
+ ( -3 * t3 + 3 * t2 + 3 * t + 1 ) * v[2].z( ) +
+ ( t3 ) * v[3].z( )
+ ) / 6
+ );
+
+ return rst;
+}
+
+void PMSphereSweep::createSphere( PMVector v, double r, int rSteps )
+{
+ PMPointArray& points = m_pViewStructure->points( );
+ PMLineArray& lines = m_pViewStructure->lines( );
+
+ PMVector point = PMVector( 0, 1, 0 ) * r;
+ int pointUp = m_nextPoint++;
+ int pointDown = m_nextPoint++;
+ double rotVal1 = M_PI / ( rSteps - 1 );
+ double rotVal2 = ( M_PI / rSteps ) * 2;
+
+ points[pointUp] = PMPoint ( point + v );
+ points[pointDown] = PMPoint ( ( PMMatrix::rotation( 0, 0, M_PI ) * point ) + v );
+
+
+ for ( int i = 0; i < rSteps; ++i )
+ {
+ lines[ m_nextLine++] = PMLine( pointUp, m_nextPoint );
+ for ( int j = 1; j < ( rSteps - 1 ); ++j )
+ {
+ points[m_nextPoint++] = PMPoint(
+ ( PMMatrix::rotation( ( rotVal1 * j ), ( rotVal2 * i ), 0 ) * point ) + v );
+
+ if ( i < ( rSteps - 1 ) )
+ lines[m_nextLine++] = PMLine( m_nextPoint - 1, m_nextPoint +
+ rSteps - 3 );
+ else
+ lines[m_nextLine++] = PMLine( m_nextPoint - 1, m_nextPoint -
+ ( ( rSteps - 1 ) * ( rSteps - 2 ) ) - 1 );
+
+ if ( j < ( rSteps - 2 ) )
+ lines[m_nextLine++] = PMLine( m_nextPoint - 1, m_nextPoint );
+ else
+ lines[m_nextLine++] = PMLine( m_nextPoint - 1, pointDown );
+ }
+ }
+}
diff --git a/kpovmodeler/pmspheresweep.h b/kpovmodeler/pmspheresweep.h
new file mode 100644
index 00000000..281db0c3
--- /dev/null
+++ b/kpovmodeler/pmspheresweep.h
@@ -0,0 +1,245 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSPHERESWEEP_H
+#define PMSPHERESWEEP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <math.h>
+
+class PMViewStructure;
+
+/**
+ * Class for povray sphere sweep objects.
+ */
+
+class PMSphereSweep : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * The spline type
+ */
+ enum SplineType { LinearSpline, BSpline, CubicSpline };
+ /**
+ * Creates an empty PMSphereSweep
+ */
+ PMSphereSweep( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSphereSweep( const PMSphereSweep& l );
+ /**
+ * deletes the PMSphereSweep
+ */
+ virtual ~PMSphereSweep( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMSphereSweep( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMSphereSweepEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmspheresweep" ); }
+
+ /** */
+ virtual void createMemento( );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual void addObjectActions( const PMControlPointList&,
+ QPtrList<PMObjectAction>& );
+ /** */
+ virtual void objectActionCalled( const PMObjectAction*,
+ const PMControlPointList&,
+ const QPtrList<PMVector>&,
+ const PMVector& );
+
+ /**
+ * Returns the spline points
+ */
+ QValueList<PMVector> points( ) const { return m_points; }
+ /**
+ * Sets the spline points
+ */
+ void setPoints( const QValueList<PMVector>& points );
+ /**
+ * Returns the radii
+ */
+ QValueList<double> radii( ) const { return m_radii; }
+ /**
+ * Sets the radii
+ */
+ void setRadii( const QValueList<double>& radii );
+ /**
+ * Returns the number of spline points
+ */
+ int numberOfPoints( ) const { return m_points.size( ); }
+ /**
+ * Returns the spline type
+ */
+ SplineType splineType( ) const { return m_splineType; }
+ /**
+ * Sets the spline type
+ */
+ void setSplineType( SplineType t );
+ /**
+ * Returns the depth tolerance
+ */
+ double tolerance( ) const { return m_tolerance; }
+ /**
+ * Sets the depth tolerance
+ */
+ void setTolerance( double t );
+
+ /**
+ * Sets the number of steps around the y axis
+ */
+ static void setRSteps( int r );
+ /**
+ * Sets the number of subdivisions of one spline segment
+ */
+ static void setSSteps( int v );
+ /**
+ * Returns the number of steps around the y axis
+ */
+ static int rSteps( ) { return s_rSteps; }
+ /**
+ * Returns the number of subdivisions of one spline segment
+ */
+ static int sSteps( ) { return s_sSteps; }
+
+protected:
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey( ); }
+
+private:
+ /**
+ * Object action. Adds a spline point
+ */
+ void splitSegment( const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition );
+ /**
+ * Object action. Removes a spline point
+ */
+ void joinSegments( const PMControlPointList& cp,
+ const QPtrList<PMVector>& cpViewPosition,
+ const PMVector& clickPosition );
+
+ void stringToValues( const QString& str );
+ QString valuesToString( ) const;
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMSphereSweepMementoID { PMSplineTypeID, PMToleranceID };
+ /**
+ * IDs for the object actions
+ */
+ enum PMSphereSweepActionID { PMSplitSegmentID, PMJoinSegmentsID };
+ SplineType m_splineType;
+ QValueList<PMVector> m_points;
+ QValueList<double> m_radii;
+ double m_tolerance;
+
+ static int s_rSteps;
+ static int s_sSteps;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+
+ /**
+ * Segment Structure for holding info for
+ * creating view structure
+ */
+ struct Segment{
+ QValueList<PMVector> points;
+ QValueList<double> radii;
+ QValueList<PMVector> direction;
+ };
+
+ QValueList<Segment> m_segments;
+ int m_nextPoint;
+ int m_nextLine;
+ /**
+ * Sets up the segments for linear spline
+ * @param sSteps the number of subdivisions per segment
+ */
+ void setLinear( int sSteps );
+ /**
+ * Sets up segments for curved splines
+ * @param cubic true for cubic_spline false for b_spline
+ * @param sSteps the number of subdivisions per segment
+ */
+ void setCurved( bool cubic, int sSteps );
+ /**
+ * Returns a point on a Catmull rom spline
+ * @param v Pointer to four control points
+ * @param t position along spline ( 0.0 - 1.0 )
+ */
+ PMVector catmullRom( PMVector *v, double t );
+ /**
+ * Returns a point on a cubic b spline
+ * @param v pointer to four control points
+ * @param t position along spline ( 0.0 - 1.0 )
+ */
+ PMVector bSpline( PMVector *v, double t );
+ /**
+ * Creates a sphere
+ * @param v poisition of sphere
+ * @param r radius of sphere
+ * @param rSteps the number of steps around the y axis
+ */
+ void createSphere( PMVector v, double r, int rSteps );
+
+};
+
+#endif
diff --git a/kpovmodeler/pmspheresweepedit.cpp b/kpovmodeler/pmspheresweepedit.cpp
new file mode 100644
index 00000000..582a0e80
--- /dev/null
+++ b/kpovmodeler/pmspheresweepedit.cpp
@@ -0,0 +1,354 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmspheresweepedit.h"
+#include "pmspheresweep.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+#include "pmvectorlistedit.h"
+#include "pmpart.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+
+PMSphereSweepEdit::PMSphereSweepEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMSphereSweepEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Spline type:" ), this ) );
+ m_pSplineType = new QComboBox( false, this );
+ m_pSplineType->insertItem( i18n( "Linear Spline" ) );
+ m_pSplineType->insertItem( i18n( "B-Spline" ) );
+ m_pSplineType->insertItem( i18n( "Cubic Spline" ) );
+ hl->addWidget( m_pSplineType );
+ hl->addStretch( 1 );
+
+ connect( m_pSplineType, SIGNAL( activated( int ) ),
+ SLOT( slotTypeChanged( int ) ) );
+}
+
+void PMSphereSweepEdit::createBottomWidgets( )
+{
+ topLayout( )->addWidget( new QLabel( i18n( "Spheres:" ), this ) );
+
+ m_pPoints = new PMVectorListEdit( "x", "y", "z", "r", this );
+ connect( m_pPoints, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pPoints, SIGNAL( selectionChanged( ) ),
+ SLOT( slotSelectionChanged( ) ) );
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( m_pPoints, 2 );
+
+ m_pAddAbove = new QPushButton( this );
+ m_pAddAbove->setPixmap( SmallIcon( "pmaddpointabove" ) );
+ m_pAddBelow = new QPushButton( this );
+ m_pAddBelow->setPixmap( SmallIcon( "pmaddpoint" ) );
+ m_pRemove = new QPushButton( this );
+ m_pRemove->setPixmap( SmallIcon( "pmremovepoint" ) );
+ connect( m_pAddAbove, SIGNAL( clicked( ) ), SLOT( slotAddPointAbove( ) ) );
+ connect( m_pAddBelow, SIGNAL( clicked( ) ), SLOT( slotAddPointBelow( ) ) );
+ connect( m_pRemove, SIGNAL( clicked( ) ), SLOT( slotRemovePoint( ) ) );
+
+ QVBoxLayout* bl = new QVBoxLayout( hl );
+ bl->addWidget( m_pAddAbove );
+ bl->addWidget( m_pAddBelow );
+ bl->addWidget( m_pRemove );
+ bl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Tolerance" ), this ) );
+ m_pTolerance = new PMFloatEdit( this );
+ m_pTolerance->setValidation( true, 0, false, 0 );
+ hl->addWidget( m_pTolerance );
+ connect( m_pTolerance, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+
+ Base::createBottomWidgets( );
+}
+
+void PMSphereSweepEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "SphereSweep" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMSphereSweep* ) o;
+
+ switch( m_pDisplayedObject->splineType( ) )
+ {
+ case PMSphereSweep::LinearSpline:
+ m_pSplineType->setCurrentItem( 0 );
+ break;
+ case PMSphereSweep::BSpline:
+ m_pSplineType->setCurrentItem( 1 );
+ break;
+ case PMSphereSweep::CubicSpline:
+ m_pSplineType->setCurrentItem( 2 );
+ break;
+ }
+ m_pSplineType->setEnabled( !readOnly );
+ m_pTolerance->setValue( m_pDisplayedObject->tolerance( ) );
+ m_pTolerance->setReadOnly( readOnly );
+ m_pPoints->setReadOnly( readOnly );
+
+ QValueList<PMVector> points = m_pDisplayedObject->points( );
+ QValueList<double> radii = m_pDisplayedObject->radii( );
+ QValueListIterator<PMVector> pit = points.begin( );
+ QValueListIterator<double> rit = radii.begin( );
+ for( ; pit != points.end( ) && rit != radii.end( ); ++pit, ++rit )
+ {
+ ( *pit ).resize( 4 );
+ ( *pit )[3] = *rit;
+ }
+
+ m_pPoints->setVectors( points, true );
+ updateControlPointSelection( );
+ updatePointButtons( );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMSphereSweepEdit: Can't display object\n";
+}
+
+void PMSphereSweepEdit::updateControlPointSelection( )
+{
+ /*
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp );
+ int i;
+ int np = cp.count( ) / 4;
+
+ if( np == m_pPoints->size( ) )
+ {
+ m_pPoints->blockSelectionUpdates( true );
+ bool sb = m_pPoints->signalsBlocked( );
+ m_pPoints->blockSignals( true );
+
+ m_pPoints->clearSelection( );
+ for( i = 0; i < np; i++, ++it )
+ if( ( *it )->selected( ) )
+ m_pPoints->select( i );
+ for( i = 0; i < np; i++, ++it )
+ if( ( *it )->selected( ) )
+ m_pPoints->select( i );
+
+ m_pPoints->blockSignals( sb );
+ m_pPoints->blockSelectionUpdates( false );
+ }
+ */
+}
+
+void PMSphereSweepEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueList<double> radii;
+ QValueListIterator<PMVector> pit = points.begin( );
+ for( ; pit != points.end( ); ++pit )
+ {
+ radii.append( ( *pit )[3] );
+ ( *pit ).resize( 3 );
+ }
+
+ m_pDisplayedObject->setPoints( points );
+ m_pDisplayedObject->setRadii( radii );
+
+ switch( m_pSplineType->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setSplineType( PMSphereSweep::LinearSpline );
+ break;
+ case 1:
+ m_pDisplayedObject->setSplineType( PMSphereSweep::BSpline );
+ break;
+ case 2:
+ m_pDisplayedObject->setSplineType( PMSphereSweep::CubicSpline );
+ break;
+ }
+ m_pDisplayedObject->setTolerance( m_pTolerance->value( ) );
+ Base::saveContents( );
+ }
+}
+
+bool PMSphereSweepEdit::isDataValid( )
+{
+ if( !m_pPoints->isDataValid( ) )
+ return false;
+
+ int np = m_pPoints->size( );
+ switch( m_pSplineType->currentItem( ) )
+ {
+ case 0:
+ if( np < 2 )
+ {
+ KMessageBox::error( this, i18n( "Linear splines need at least 2 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 1:
+ if( np < 4 )
+ {
+ KMessageBox::error( this, i18n( "B-splines need at least 4 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 2:
+ if( np < 4 )
+ {
+ KMessageBox::error( this, i18n( "Cubic splines need at least 4 points." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ case 3:
+ if( ( np < 4 ) || ( ( np % 4 ) != 0 ) )
+ {
+ KMessageBox::error( this, i18n( "Bezier splines need 4 points for each segment." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ break;
+ }
+ return Base::isDataValid( );
+}
+
+void PMSphereSweepEdit::slotTypeChanged( int )
+{
+ emit dataChanged( );
+}
+
+void PMSphereSweepEdit::slotAddPointAbove( )
+{
+ int index = m_pPoints->currentRow( );
+ if( index >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ if( it != points.end( ) )
+ {
+ QValueListIterator<PMVector> it2 = it;
+ it2--;
+ PMVector v;
+ if( it2 == points.end( ) )
+ v = *it;
+ else
+ v = ( *it + *it2 ) / 2;
+
+ points.insert( it, v );
+ m_pPoints->setVectors( points, true );
+ updatePointButtons( );
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+}
+
+void PMSphereSweepEdit::slotAddPointBelow( )
+{
+ int index = m_pPoints->currentRow( );
+ if( index >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( index );
+
+ if( it != points.end( ) )
+ {
+ QValueListIterator<PMVector> it2 = it;
+ it2++;
+ PMVector v;
+ if( it2 == points.end( ) )
+ v = *it;
+ else
+ v = ( *it + *it2 ) / 2;
+
+ points.insert( it2, v );
+ m_pPoints->setVectors( points, true );
+ m_pPoints->setCurrentCell( index + 1, m_pPoints->currentColumn( ) );
+ updatePointButtons( );
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+}
+
+void PMSphereSweepEdit::slotRemovePoint( )
+{
+ int row = m_pPoints->currentRow( );
+
+ if( row >= 0 )
+ {
+ QValueList<PMVector> points = m_pPoints->vectors( );
+ QValueListIterator<PMVector> it = points.at( row );
+
+ if( it != points.end( ) && points.size( ) > 1 )
+ {
+ points.remove( it );
+ m_pPoints->setVectors( points, true );
+ updatePointButtons( );
+ emit dataChanged( );
+ emit sizeChanged( );
+ }
+ }
+}
+
+void PMSphereSweepEdit::slotSelectionChanged( )
+{
+ /*
+ PMControlPointList cp = part( )->activeControlPoints( );
+ PMControlPointListIterator it( cp );
+ int np = cp.count( ) / 2;
+ int i;
+
+ if( np == m_pPoints->size( ) )
+ {
+ for( i = 0; i < np; i++, ++it )
+ ( *it )->setSelected( m_pPoints->isSelected( i ) );
+ for( i = 0; i < np; i++, ++it )
+ ( *it )->setSelected( m_pPoints->isSelected( i ) );
+ emit controlPointSelectionChanged( );
+ }
+ */
+ updatePointButtons( );
+}
+
+void PMSphereSweepEdit::updatePointButtons( )
+{
+ int row = m_pPoints->currentRow( );
+ m_pAddAbove->setEnabled( row >= 0 );
+ m_pAddBelow->setEnabled( row >= 0 );
+ m_pRemove->setEnabled( row >= 0 && m_pPoints->size( ) > 2 );
+}
+
+#include "pmspheresweepedit.moc"
diff --git a/kpovmodeler/pmspheresweepedit.h b/kpovmodeler/pmspheresweepedit.h
new file mode 100644
index 00000000..58f89372
--- /dev/null
+++ b/kpovmodeler/pmspheresweepedit.h
@@ -0,0 +1,90 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSPHERESWEEPEDIT_H
+#define PMSPHERESWEEPEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+#include "pmvectoredit.h"
+#include <qptrlist.h>
+#include <qvaluelist.h>
+
+class PMSphereSweep;
+class PMVectorListEdit;
+class PMFloatEdit;
+class QVBoxLayout;
+class QComboBox;
+class QCheckBox;
+class QPushButton;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMSphereSweep
+ */
+class PMSphereSweepEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMSphereSweepEdit with parent and name
+ */
+ PMSphereSweepEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+ /** */
+ virtual void updateControlPointSelection( );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void createBottomWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ void slotTypeChanged( int );
+ void slotAddPointAbove( );
+ void slotAddPointBelow( );
+ void slotRemovePoint( );
+ void slotSelectionChanged( );
+
+private:
+ void updatePointButtons( );
+
+ PMSphereSweep* m_pDisplayedObject;
+ QComboBox* m_pSplineType;
+ PMVectorListEdit* m_pPoints;
+ PMFloatEdit* m_pTolerance;
+ QPushButton* m_pAddAbove;
+ QPushButton* m_pAddBelow;
+ QPushButton* m_pRemove;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmsplinememento.cpp b/kpovmodeler/pmsplinememento.cpp
new file mode 100644
index 00000000..a197f8ea
--- /dev/null
+++ b/kpovmodeler/pmsplinememento.cpp
@@ -0,0 +1,58 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmsplinememento.h"
+#include "pmdebug.h"
+
+PMSplineMemento::PMSplineMemento( PMObject* originator )
+ : PMMemento( originator )
+{
+ m_bSplinePointsSaved = false;
+}
+
+PMSplineMemento::~PMSplineMemento( )
+{
+}
+
+void PMSplineMemento::setSplinePoints( const QValueList<PMVector>& v )
+{
+ if( !m_bSplinePointsSaved )
+ {
+ // Direct assignment does not work with Qt 2.3.x
+ // The list will be changed later in a graphical
+ // change because QValueList::detach( ) is called
+ // too late!
+ // Copy the list by hand.
+
+ QValueList<PMVector>::ConstIterator it = v.begin( );
+ for( ; it != v.end( ); ++it )
+ m_splinePoints.append( *it );
+
+ m_bSplinePointsSaved = true;
+ addChange( PMCData );
+ }
+}
+
+QValueList<PMVector> PMSplineMemento::splinePoints( ) const
+{
+ if( !m_bSplinePointsSaved )
+ kdError( PMArea ) << "Spline points not saved in PMSplineMemento::splinePoints\n";
+
+ return m_splinePoints;
+}
+
+
diff --git a/kpovmodeler/pmsplinememento.h b/kpovmodeler/pmsplinememento.h
new file mode 100644
index 00000000..daa4a70b
--- /dev/null
+++ b/kpovmodeler/pmsplinememento.h
@@ -0,0 +1,68 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSPLINEMEMENTO_H
+#define PMSPLINEMEMENTO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmmemento.h"
+#include "pmvector.h"
+#include <qvaluelist.h>
+
+
+/**
+ * Memento for @ref PMLathe
+ */
+class PMSplineMemento : public PMMemento
+{
+public:
+ /**
+ * Creates a memento for the object originator
+ */
+ PMSplineMemento( PMObject* originator );
+ /**
+ * Deletes the memento
+ */
+ virtual ~PMSplineMemento( );
+
+ /**
+ * Saves the spline points
+ */
+ void setSplinePoints( const QValueList<PMVector>& v );
+ /**
+ * Returns the spline points
+ */
+ QValueList<PMVector> splinePoints( ) const;
+ /**
+ * Returns true if the spline points were saved
+ */
+ bool splinePointsSaved( ) const { return m_bSplinePointsSaved; }
+
+private:
+ /**
+ * The stored points
+ */
+ QValueList<PMVector> m_splinePoints;
+ bool m_bSplinePointsSaved;
+};
+
+#endif
diff --git a/kpovmodeler/pmsplinesegment.cpp b/kpovmodeler/pmsplinesegment.cpp
new file mode 100644
index 00000000..dbbc6b18
--- /dev/null
+++ b/kpovmodeler/pmsplinesegment.cpp
@@ -0,0 +1,107 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmsplinesegment.h"
+
+PMVector PMSplineSegment::point( double t ) const
+{
+ double t2 = t * t;
+ double t3 = t2 * t;
+
+ return PMVector( m_a[0]*t3 + m_b[0]*t2 + m_c[0]*t + m_d[0],
+ m_a[1]*t3 + m_b[1]*t2 + m_c[1]*t + m_d[1] );
+}
+
+PMVector PMSplineSegment::gradient( double t ) const
+{
+ double t2 = t * t;
+
+ return PMVector( 3*m_a[0]*t2 + 2*m_b[0]*t + m_c[0],
+ 3*m_a[1]*t2 + 2*m_b[1]*t + m_c[1] );
+}
+
+void PMSplineSegment::calculateLinear( const PMVector& p1, const PMVector& p2 )
+{
+ m_a[0] = 0.0;
+ m_b[0] = 0.0;
+ m_c[0] = -1.0 * p1[0] + 1.0 * p2[0];
+ m_d[0] = 1.0 * p1[0];
+
+ m_a[1] = 0.0;
+ m_b[1] = 0.0;
+ m_c[1] = -1.0 * p1[1] + 1.0 * p2[1];
+ m_d[1] = 1.0 * p1[1];
+}
+
+void PMSplineSegment::calculateQuadratic( const PMVector& p1,
+ const PMVector& p2,
+ const PMVector& p3 )
+{
+ m_a[0] = 0.0;
+ m_b[0] = 0.5 * p1[0] - 1.0 * p2[0] + 0.5 * p3[0];
+ m_c[0] = -0.5 * p1[0] + 0.5 * p3[0];
+ m_d[0] = 1.0 * p2[0];
+
+ m_a[1] = 0.0;
+ m_b[1] = 0.5 * p1[1] - 1.0 * p2[1] + 0.5 * p3[1];
+ m_c[1] = -0.5 * p1[1] + 0.5 * p3[1];
+ m_d[1] = 1.0 * p2[1];
+}
+
+void PMSplineSegment::calculateCubic( const PMVector& p1, const PMVector& p2,
+ const PMVector& p3, const PMVector& p4 )
+{
+ m_a[0] = -0.5 * p1[0] + 1.5 * p2[0] - 1.5 * p3[0] + 0.5 * p4[0];
+ m_b[0] = p1[0] - 2.5 * p2[0] + 2.0 * p3[0] - 0.5 * p4[0];
+ m_c[0] = -0.5 * p1[0] + 0.5 * p3[0];
+ m_d[0] = p2[0];
+
+ m_a[1] = -0.5 * p1[1] + 1.5 * p2[1] - 1.5 * p3[1] + 0.5 * p4[1];
+ m_b[1] = p1[1] - 2.5 * p2[1] + 2.0 * p3[1] - 0.5 * p4[1];
+ m_c[1] = -0.5 * p1[1] + 0.5 * p3[1];
+ m_d[1] = p2[1];
+}
+
+void PMSplineSegment::calculateBezier( const PMVector& p1, const PMVector& p2,
+ const PMVector& p3, const PMVector& p4 )
+{
+ m_a[0] = - p1[0] + 3.0 * p2[0] - 3.0 * p3[0] + p4[0];
+ m_b[0] = 3.0 * p1[0] - 6.0 * p2[0] + 3.0 * p3[0];
+ m_c[0] = -3.0 * p1[0] + 3.0 * p2[0];
+ m_d[0] = p1[0];
+
+ m_a[1] = - p1[1] + 3.0 * p2[1] - 3.0 * p3[1] + p4[1];
+ m_b[1] = 3.0 * p1[1] - 6.0 * p2[1] + 3.0 * p3[1];
+ m_c[1] = -3.0 * p1[1] + 3.0 * p2[1];
+ m_d[1] = p1[1];
+}
+
+void PMSplineSegment::calculateQuadricBezier( const PMVector& p1,
+ const PMVector& p2,
+ const PMVector& p3 )
+{
+ m_a[0] = 0;
+ m_b[0] = p1[0] - 2.0 * p2[0] + p3[0];
+ m_c[0] = -2.0 * p1[0] + 2.0 * p2[0];
+ m_d[0] = p1[0];
+
+ m_a[1] = 0;
+ m_b[1] = p1[1] - 2.0 * p2[1] + p3[1];
+ m_c[1] = -2.0 * p1[1] + 2.0 * p2[1];
+ m_d[1] = p1[1];
+}
diff --git a/kpovmodeler/pmsplinesegment.h b/kpovmodeler/pmsplinesegment.h
new file mode 100644
index 00000000..5e97ff49
--- /dev/null
+++ b/kpovmodeler/pmsplinesegment.h
@@ -0,0 +1,122 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSPLINESEGMENT_H
+#define PMSPLINESEGMENT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmvector.h"
+#include <qvaluelist.h>
+
+/**
+ * Helper class for splines
+ *
+ * Each instance of this class represents one spline segment. A point
+ * on the segment is given by the equation
+ *
+ * fi(t) = A[i] * t^3 + B[i] * t^2 + C[i] * t + D[i]
+ *
+ * with t ranging from 0 to 1.
+ */
+class PMSplineSegment
+{
+public:
+ /**
+ * Standard constructor
+ */
+ PMSplineSegment( )
+ {
+ m_a[0] = m_b[0] = m_c[0] = m_d[0] = 0.0;
+ m_a[1] = m_b[1] = m_c[1] = m_d[1] = 0.0;
+ }
+ /**
+ * Copy constructor
+ */
+ PMSplineSegment( const PMSplineSegment& s )
+ {
+ int i;
+ for( i = 0; i < 2; i++ )
+ {
+ m_a[i] = s.m_a[i];
+ m_b[i] = s.m_b[i];
+ m_c[i] = s.m_c[i];
+ m_d[i] = s.m_d[i];
+ }
+ }
+ /**
+ * Assigns s to the segment
+ */
+ PMSplineSegment& operator= ( const PMSplineSegment& s )
+ {
+ int i;
+ for( i = 0; i < 2; i++ )
+ {
+ m_a[i] = s.m_a[i];
+ m_b[i] = s.m_b[i];
+ m_c[i] = s.m_c[i];
+ m_d[i] = s.m_d[i];
+ }
+ return *this;
+ }
+
+ /**
+ * Returns a 2D vector with the point on the spline segment
+ */
+ PMVector point( double t ) const;
+ /**
+ * Returns the gradient on the spline
+ */
+ PMVector gradient( double t ) const;
+
+ /**
+ * Calculates the spline parameters for the linear spline type
+ */
+ void calculateLinear( const PMVector& p1, const PMVector& p2 );
+ /**
+ * Calculates the spline parameters for the quadratic spline type
+ */
+ void calculateQuadratic( const PMVector& p1, const PMVector& p2,
+ const PMVector& p3 );
+ /**
+ * Calculates the spline parameters for the cubic spline type
+ */
+ void calculateCubic( const PMVector& p1, const PMVector& p2,
+ const PMVector& p3, const PMVector& p4 );
+ /**
+ * Calculates the spline parameters for the bezier spline type
+ */
+ void calculateBezier( const PMVector& p1, const PMVector& p2,
+ const PMVector& p3, const PMVector& p4 );
+ /**
+ * Calculates the spline parameters for the quadric bezier
+ */
+ void calculateQuadricBezier( const PMVector& p1, const PMVector& p2,
+ const PMVector& p3 );
+
+private:
+ double m_a[2], m_b[2], m_c[2], m_d[2];
+};
+
+typedef QValueList<PMSplineSegment> PMSegmentList;
+typedef QValueList<PMSegmentList> PMSegmentListList;
+
+#endif
diff --git a/kpovmodeler/pmsqe.cpp b/kpovmodeler/pmsqe.cpp
new file mode 100644
index 00000000..051aac72
--- /dev/null
+++ b/kpovmodeler/pmsqe.cpp
@@ -0,0 +1,413 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmsqe.h"
+
+#include "pmxmlhelper.h"
+#include "pmsqeedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pmdefaults.h"
+#include "pmmath.h"
+
+#include <klocale.h>
+
+const double c_defaultEastWestExponent = 1.0;
+const double c_defaultNorthSouthExponent = 1.0;
+
+PMViewStructure* PMSuperquadricEllipsoid::s_pDefaultViewStructure = 0;
+int PMSuperquadricEllipsoid::s_vStep = c_defaultSuperquadricEllipsoidVSteps;
+int PMSuperquadricEllipsoid::s_uStep = c_defaultSuperquadricEllipsoidUSteps;
+int PMSuperquadricEllipsoid::s_parameterKey = 0;
+
+PMDefinePropertyClass( PMSuperquadricEllipsoid, PMSuperquadricEllipsoidProperty );
+
+PMMetaObject* PMSuperquadricEllipsoid::s_pMetaObject = 0;
+PMObject* createNewSuperquadricEllipsoid( PMPart* part )
+{
+ return new PMSuperquadricEllipsoid( part );
+}
+
+PMSuperquadricEllipsoid::PMSuperquadricEllipsoid( PMPart* part )
+ : Base( part )
+{
+ m_eastWestExponent = c_defaultEastWestExponent;
+ m_northSouthExponent = c_defaultNorthSouthExponent;
+}
+
+PMSuperquadricEllipsoid::PMSuperquadricEllipsoid( const PMSuperquadricEllipsoid& s )
+ : Base( s )
+{
+ m_eastWestExponent = s.m_eastWestExponent;
+ m_northSouthExponent = s.m_northSouthExponent;
+}
+
+PMSuperquadricEllipsoid::~PMSuperquadricEllipsoid( )
+{
+}
+
+QString PMSuperquadricEllipsoid::description( ) const
+{
+ return i18n( "superquadric ellipsoid" );
+}
+
+void PMSuperquadricEllipsoid::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "value_e", m_eastWestExponent );
+ e.setAttribute( "value_n", m_northSouthExponent );
+ Base::serialize( e, doc );
+}
+
+void PMSuperquadricEllipsoid::readAttributes( const PMXMLHelper& h )
+{
+ m_eastWestExponent = h.doubleAttribute( "value_e", c_defaultEastWestExponent );
+ m_northSouthExponent = h.doubleAttribute( "value_n", c_defaultNorthSouthExponent );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMSuperquadricEllipsoid::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "SuperquadricEllipsoid", Base::metaObject( ),
+ createNewSuperquadricEllipsoid );
+ s_pMetaObject->addProperty(
+ new PMSuperquadricEllipsoidProperty( "eastWestExponent",
+ &PMSuperquadricEllipsoid::setEastWestExponent,
+ &PMSuperquadricEllipsoid::eastWestExponent ) );
+ s_pMetaObject->addProperty(
+ new PMSuperquadricEllipsoidProperty( "northSouthExponent",
+ &PMSuperquadricEllipsoid::setNorthSouthExponent,
+ &PMSuperquadricEllipsoid::northSouthExponent ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMSuperquadricEllipsoid::setEastWestExponent( double e )
+{
+ if( e != m_eastWestExponent )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMEastWestExponentID,
+ m_eastWestExponent );
+ if( e < 0.001 )
+ {
+ kdError( PMArea ) << "EastWestExponent < 0.001 in PMSuperquadricEllipsoid::setEastWestExponent\n";
+ e = 0.001;
+ }
+ m_eastWestExponent = e;
+ setViewStructureChanged( );
+ }
+}
+
+void PMSuperquadricEllipsoid::setNorthSouthExponent( double n )
+{
+ if( n != m_northSouthExponent )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNorthSouthExponentID,
+ m_northSouthExponent );
+ if( n < 0.001 )
+ {
+ kdError( PMArea ) << "NorthSouthExponent < 0.001 in PMSuperquadricEllipsoid::setNorthSouthExponent\n";
+ n = 0.001;
+ }
+
+ m_northSouthExponent = n;
+ setViewStructureChanged( );
+ }
+}
+
+PMDialogEditBase* PMSuperquadricEllipsoid::editWidget( QWidget* parent ) const
+{
+ return new PMSuperquadricEllipsoidEdit( parent );
+}
+
+void PMSuperquadricEllipsoid::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMEastWestExponentID:
+ setEastWestExponent( data->doubleData( ) );
+ break;
+ case PMNorthSouthExponentID:
+ setNorthSouthExponent( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMSuperquadricEllipsoid::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+
+bool PMSuperquadricEllipsoid::isDefault( )
+{
+ if( ( m_eastWestExponent == c_defaultEastWestExponent ) &&
+ ( m_northSouthExponent == c_defaultNorthSouthExponent )
+ && globalDetail( ) )
+ return true;
+ return false;
+}
+
+void PMSuperquadricEllipsoid::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( displayDetail( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( displayDetail( ) + 1 ) );
+ int uStep2 = uStep * 4;
+ int vStep2 = vStep * 8;
+ unsigned ptsSize = vStep2 * ( uStep2 - 1 ) + 2;
+ unsigned lineSize = vStep2 * ( uStep2 - 1 ) * 2 + vStep2;
+
+ if( ptsSize != m_pViewStructure->points( ).size( ) )
+ m_pViewStructure->points( ).resize( ptsSize );
+
+ createPoints( m_pViewStructure->points( ), m_eastWestExponent,
+ m_northSouthExponent, uStep, vStep );
+
+ if( lineSize != m_pViewStructure->lines( ).size( ) )
+ {
+ m_pViewStructure->lines( ).detach( );
+ m_pViewStructure->lines( ).resize( lineSize );
+ createLines( m_pViewStructure->lines( ), uStep2, vStep2 );
+ }
+}
+
+PMViewStructure* PMSuperquadricEllipsoid::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
+
+ // transform u and v steps to sphere u/v steps
+ int uStep2 = uStep * 4;
+ int vStep2 = vStep * 8;
+
+ s_pDefaultViewStructure =
+ new PMViewStructure( vStep2 * ( uStep2 - 1 ) + 2,
+ vStep2 * ( uStep2 - 1 ) * 2 + vStep2 );
+
+ // points
+ createPoints( s_pDefaultViewStructure->points( ),
+ c_defaultEastWestExponent, c_defaultNorthSouthExponent, uStep, vStep );
+
+ createLines( s_pDefaultViewStructure->lines( ), uStep2, vStep2 );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMSuperquadricEllipsoid::createLines( PMLineArray& lines, int uStep, int vStep )
+{
+ int u, v;
+ int offset = 0;
+
+ // horizontal lines
+ for( u = 0; u < ( uStep - 1 ); u++ )
+ {
+ for( v = 0; v < ( vStep - 1 ); v++ )
+ lines[offset + v] =
+ PMLine( u * vStep + v + 1, u * vStep + v + 2 );
+ lines[offset + vStep - 1] =
+ PMLine( u * vStep + 1, u * vStep + vStep );
+
+ offset += vStep;
+ }
+
+ // vertical lines
+ // lines at the "north pole"
+ for( v = 0; v < vStep; v++ )
+ lines[offset + v] = PMLine( 0, v + 1 );
+ offset += vStep;
+
+ for( v = 0; v < vStep; v++ )
+ {
+ for( u = 0; u < ( uStep - 2 ); u++ )
+ {
+ lines[offset + u] =
+ PMLine( u * vStep + v + 1, ( u + 1 ) * vStep + v + 1 );
+ }
+ offset += ( uStep - 2 );
+ }
+ // lines at the "south pole"
+ for( v = 0; v < vStep; v++ )
+ lines[offset + v] = PMLine( ( uStep - 2 ) * vStep + v + 1,
+ ( uStep - 1 ) * vStep + 1 );
+ // offset += vStep;
+}
+
+void PMSuperquadricEllipsoid::createPoints( PMPointArray& points,
+ double e, double n, int uStep, int vStep )
+{
+ int u, v;
+ int zi;
+ int pbase = 0, pref = 0;
+
+ if( e <= 0.001 )
+ e = 0.001;
+ if( n <= 0.001 )
+ n = 0.001;
+
+ double c2_e = 2.0 / e;
+ double c2_n = 2.0 / n;
+ double cn_2 = n / 2.0;
+ double ce_2 = e / 2.0;
+ double cn_e = n / e;
+// double ce_n = e / n;
+ double z = 0.0, c = 0.0, a = 0.0, a2 = 0.0, x = 0.0, y = 0.0;
+ double k = 0.0, k2 = 0.0, du = 0.0, dv = 0.0;
+ PMPoint p;
+
+ points[0] = PMPoint( 0, 0, 1 );
+ pbase++;
+
+ for( zi = 0; zi < 2; zi++ )
+ {
+ for( u = 0; u < uStep; u++ )
+ {
+ du = ( double ) ( u + 1 ) / ( double ) uStep;
+ if( zi == 1 )
+ du = 1.0 - du;
+ k = tan( M_PI / 4.0 * pow( du, n < 1.0 ? n : sqrt( n ) ) );
+ k2 = 1 / ( pow( k, c2_n ) + 1 );
+ z = pow( k2, cn_2 );
+ if( zi == 1 )
+ z *= k;
+ c = pow( 1 - pow( z, c2_n ), cn_e );
+
+ for( v = 0; v < ( vStep + 1 ); v++ )
+ {
+ dv = ( double ) v / ( double ) vStep;
+ a = tan( M_PI / 4.0 * pow( dv, e < 1.0 ? e : sqrt( e ) ) );
+ a2 = 1 + pow( a, c2_e );
+ x = pow( c / a2, ce_2 );
+ y = x * a;
+
+ points[pbase+v] = PMPoint( x, y, z );
+ }
+ // 1/8
+
+ pref = pbase + 2 * vStep;
+ for( v = 0; v < vStep; v++, pref-- )
+ {
+ p = points[pbase+v];
+ x = p[0];
+ p[0] = p[1];
+ p[1] = x;
+ points[pref] = p;
+ }
+ // 1/4
+
+ pref = pbase + 4 * vStep;
+ for( v = 0; v < ( 2 * vStep ); v++, pref-- )
+ {
+ p = points[pbase+v];
+ p[0] = -p[0];
+ points[pref] = p;
+ }
+ // 1/2
+
+ pref = pbase + 8 * vStep - 1;
+ for( v = 1; v < ( 4 * vStep ); v++, pref-- )
+ {
+ p = points[pbase+v];
+ p[1] = -p[1];
+ points[pref] = p;
+ }
+
+ pbase += 8 * vStep;
+ }
+ }
+
+ for( u = 0; u < ( uStep * 2 - 1 ); u++ )
+ {
+ pbase = 1 + u * vStep * 8;
+ pref = 1 + ( uStep * 4 - 2 - u ) * vStep * 8;
+
+ for( v = 0; v < ( vStep * 8 ); v++, pref++ )
+ {
+ p = points[pbase + v];
+ p[2] = -p[2];
+ points[pref] = p;
+ }
+ }
+ points[ vStep * 8 * ( uStep * 4 - 1 ) + 1 ] = PMPoint( 0, 0, -1 );
+}
+
+void PMSuperquadricEllipsoid::setUSteps( int u )
+{
+ if( u >= 2 )
+ {
+ s_uStep = u;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMSuperquadricEllipsoid::setUSteps: U must be greater than 1\n";
+ s_parameterKey++;
+}
+
+void PMSuperquadricEllipsoid::setVSteps( int v )
+{
+ if( v >= 2 )
+ {
+ s_vStep = v;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMSuperquadricEllipsoid::setVSteps: V must be greater than 1\n";
+ s_parameterKey++;
+}
+
+void PMSuperquadricEllipsoid::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmsqe.h b/kpovmodeler/pmsqe.h
new file mode 100644
index 00000000..e2d04c60
--- /dev/null
+++ b/kpovmodeler/pmsqe.h
@@ -0,0 +1,155 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSQE_H
+#define PMSQE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include "pmpoint.h"
+#include "pmline.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray superquadric ellipsoids.
+ */
+
+class PMSuperquadricEllipsoid : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMSuperquadricEllipsoid
+ */
+ PMSuperquadricEllipsoid( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSuperquadricEllipsoid( const PMSuperquadricEllipsoid& s );
+ /**
+ * deletes the PMSuperquadricEllipsoid
+ */
+ virtual ~PMSuperquadricEllipsoid( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMSuperquadricEllipsoid( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMSuperquadricEllipsoidEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmsqe" ); }
+
+ /**
+ * Returns the east west exponent
+ */
+ double eastWestExponent( ) const { return m_eastWestExponent; }
+ /**
+ * Sets the east west exponent
+ */
+ void setEastWestExponent( double e );
+ /**
+ * Returns the north south exponent
+ */
+ double northSouthExponent( ) const { return m_northSouthExponent; }
+ /**
+ * Sets the north south exponent
+ */
+ void setNorthSouthExponent( double n );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+
+ /**
+ * Sets the number of latitutes
+ */
+ static void setUSteps( int u );
+ /**
+ * Sets the number of longitudes
+ */
+ static void setVSteps( int v );
+ /**
+ * Returns the number or latitutes
+ */
+ static int uSteps( ) { return s_uStep; }
+ /**
+ * Returns the number or longitudes
+ */
+ static int vSteps( ) { return s_vStep; }
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey( ); }
+
+private:
+ /**
+ * Creates the lines for the view structure
+ */
+ static void createLines( PMLineArray& lines, int uStep, int vStep );
+ /**
+ * Creates the points for the view structure
+ */
+ static void createPoints( PMPointArray& points, double e, double n, int uStep, int vStep );
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMSQEMementoID { PMEastWestExponentID, PMNorthSouthExponentID };
+ double m_eastWestExponent, m_northSouthExponent;
+
+ /**
+ * The default view structure. It can be shared between sqe's
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_vStep;
+ static int s_uStep;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmsqeedit.cpp b/kpovmodeler/pmsqeedit.cpp
new file mode 100644
index 00000000..488ce2f2
--- /dev/null
+++ b/kpovmodeler/pmsqeedit.cpp
@@ -0,0 +1,93 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmsqeedit.h"
+#include "pmsqe.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+PMSuperquadricEllipsoidEdit::PMSuperquadricEllipsoidEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMSuperquadricEllipsoidEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pValueE = new PMFloatEdit( this );
+ m_pValueE->setValidation( true, 0.01, false, 1.0 );
+ m_pValueN = new PMFloatEdit( this );
+ m_pValueN->setValidation( true, 0.01, false, 1.0 );
+
+ topLayout( )->addWidget( new QLabel( i18n( "Exponents:" ), this ) );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ QGridLayout* gl = new QGridLayout( hl, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "East-west:" ), this ), 0, 0 );
+ gl->addWidget( m_pValueE, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "North-south:" ), this ), 1, 0 );
+ gl->addWidget( m_pValueN, 1, 1 );
+ hl->addStretch( 1 );
+
+ connect( m_pValueE, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pValueN, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMSuperquadricEllipsoidEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "SuperquadricEllipsoid" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMSuperquadricEllipsoid* ) o;
+
+ m_pValueE->setValue( m_pDisplayedObject->eastWestExponent( ) );
+ m_pValueN->setValue( m_pDisplayedObject->northSouthExponent( ) );
+
+ m_pValueE->setReadOnly( readOnly );
+ m_pValueN->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMSuperquadricEllipsoidEdit: Can't display object\n";
+}
+
+void PMSuperquadricEllipsoidEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setEastWestExponent( m_pValueE->value( ) );
+ m_pDisplayedObject->setNorthSouthExponent( m_pValueN->value( ) );
+ }
+}
+
+bool PMSuperquadricEllipsoidEdit::isDataValid( )
+{
+ if( m_pValueE->isDataValid( ) )
+ if( m_pValueN->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+#include "pmsqeedit.moc"
diff --git a/kpovmodeler/pmsqeedit.h b/kpovmodeler/pmsqeedit.h
new file mode 100644
index 00000000..45ae1a2f
--- /dev/null
+++ b/kpovmodeler/pmsqeedit.h
@@ -0,0 +1,63 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSQEEDIT_H
+#define PMSQEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMSuperquadricEllipsoid;
+class PMFloatEdit;
+
+/**
+ * Dialog edit class for @ref PMSuperquadricEllipsoid
+ */
+class PMSuperquadricEllipsoidEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMSuperquadricEllipsoidEdit with parent and name
+ */
+ PMSuperquadricEllipsoidEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMSuperquadricEllipsoid* m_pDisplayedObject;
+ PMFloatEdit* m_pValueE;
+ PMFloatEdit* m_pValueN;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmsymboltable.cpp b/kpovmodeler/pmsymboltable.cpp
new file mode 100644
index 00000000..bd1aab3b
--- /dev/null
+++ b/kpovmodeler/pmsymboltable.cpp
@@ -0,0 +1,121 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmsymboltable.h"
+#include "pmdeclare.h"
+#include "pmdebug.h"
+
+#include <string.h>
+
+PMSymbol::PMSymbol( const QString& id, PMDeclare* o )
+{
+ setId( id );
+ m_type = Object;
+ m_pObj = o;
+ m_pVal = 0;
+ m_pRenamedSymbol = 0;
+}
+
+PMSymbol::PMSymbol( const QString& id, const PMValue& v )
+{
+ setId( id );
+ m_type = Value;
+ m_pObj = 0;
+ m_pVal = new PMValue( v );
+ m_pRenamedSymbol = 0;
+}
+
+PMSymbol::~PMSymbol( )
+{
+ if( m_pVal )
+ delete m_pVal;
+}
+
+void PMSymbol::setId( const QString& id )
+{
+ m_id = id.left( MaxIDLength );
+}
+
+PMDeclare* PMSymbol::object( ) const
+{
+ if( m_type == Object )
+ return m_pObj;
+ kdError( PMArea ) << "Symbol is not an object\n";
+ return 0;
+}
+
+PMValue PMSymbol::value( ) const
+{
+ if( m_type == Value )
+ return *m_pVal;
+ kdError( PMArea ) << "Symbol is not a value\n";
+ return PMValue( );
+}
+
+
+PMSymbolTable::PMSymbolTable( )
+ : QDict<PMSymbol>( 1009 ), m_lastID( 47 )
+{
+ setAutoDelete( true );
+ m_lastID.setAutoDelete( true );
+}
+
+PMSymbolTable::~PMSymbolTable( )
+{
+ clear( );
+}
+
+QString PMSymbolTable::findNewID( const QString& prefix )
+{
+ PMSymbol* symbol;
+ QString testID;
+ unsigned int number;
+
+ int* lastNumber = m_lastID.find( prefix );
+ if( lastNumber )
+ number = *lastNumber + 1;
+ else
+ number = 0;
+
+ // find next free id
+ do
+ {
+ testID = prefix + QString( "%1" ).arg( number );
+ symbol = find( testID );
+ if( symbol )
+ number++;
+ }
+ while( symbol );
+
+ if( lastNumber )
+ *lastNumber = number;
+ else
+ m_lastID.insert( prefix, new int( number ) );
+
+ return testID;
+}
+
+PMSymbol* PMSymbolTable::findNewID( const QString& prefix, PMDeclare* obj )
+{
+ QString newID = findNewID( prefix );
+ obj->setID( newID );
+
+ PMSymbol* s = new PMSymbol( newID, obj );
+// insert( newID, s );
+
+ return s;
+}
diff --git a/kpovmodeler/pmsymboltable.h b/kpovmodeler/pmsymboltable.h
new file mode 100644
index 00000000..27e88785
--- /dev/null
+++ b/kpovmodeler/pmsymboltable.h
@@ -0,0 +1,128 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMSYMBOLTABLE_H
+#define PMSYMBOLTABLE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmvalue.h"
+class PMObject;
+class PMDeclare;
+
+#include <qdict.h>
+#include <qstring.h>
+
+/**
+ * Entry in a @ref PMSymbolTable. Can be a @ref PMValue or a @ref PMObject
+ */
+
+class PMSymbol
+{
+public:
+ enum PMSymbolType { Value, Object };
+ /**
+ * Creates a entry for an object
+ */
+ PMSymbol( const QString& id, PMDeclare* o );
+ /**
+ * Creates a entry for a value
+ */
+ PMSymbol( const QString& id, const PMValue& v );
+ /**
+ * Destructor
+ */
+ ~PMSymbol( );
+
+ /**
+ * Returns the type of the symbol
+ */
+ PMSymbolType type( ) const { return m_type; }
+ /**
+ * Returns the id of the symbol
+ */
+ QString id( ) const { return m_id; }
+ /**
+ * Sets the id
+ */
+ void setId( const QString& id );
+ /**
+ * Returns the stored object
+ */
+ PMDeclare* object( ) const;
+ /**
+ * Returns the stored value
+ */
+ PMValue value( ) const;
+ /**
+ * The maximum length for povray ids
+ */
+ static const unsigned int MaxIDLength = 40;
+ /**
+ * If the parser parses a declare object with this id, the
+ * new id is renamed. This function returns a pointer to the
+ * renamed symbol.
+ */
+ PMSymbol* renamedSymbol( ) const { return m_pRenamedSymbol; }
+ /**
+ * Sets the renamed declare object to symbol
+ */
+ void setRenamedSymbol( PMSymbol* symbol ) { m_pRenamedSymbol = symbol; }
+
+private:
+ PMSymbolType m_type;
+ PMDeclare* m_pObj;
+ PMSymbol* m_pRenamedSymbol;
+ PMValue* m_pVal;
+ QString m_id;
+};
+
+/**
+ * Symbol table for povray #declare statements
+ */
+class PMSymbolTable : public QDict<PMSymbol>
+{
+public:
+ /**
+ * Constructor
+ */
+ PMSymbolTable( );
+ /**
+ * Destructor
+ */
+ ~PMSymbolTable( );
+ /**
+ * Returns a free id with prefix prefix and a number as suffix
+ */
+ QString findNewID( const QString& prefix );
+ /**
+ * Returns a free id with prefix prefix and a number as suffix and assigns
+ * it to the object.
+ *
+ * Does NOT add the object to the symbol table.
+ *
+ * Returns the new symbol.*/
+ PMSymbol* findNewID( const QString& prefix, PMDeclare* obj );
+private:
+ QDict<int> m_lastID;
+};
+
+#endif
diff --git a/kpovmodeler/pmtext.cpp b/kpovmodeler/pmtext.cpp
new file mode 100644
index 00000000..21191cbc
--- /dev/null
+++ b/kpovmodeler/pmtext.cpp
@@ -0,0 +1,339 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtext.h"
+
+#include "pmxmlhelper.h"
+#include "pmtextedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pmresourcelocator.h"
+#include "pmtruetypecache.h"
+#include "pmdefaults.h"
+
+#include <klocale.h>
+
+const QString c_defaultFont = QString( "" );
+const QString c_defaultText = QString( "" );
+const double c_defaultThickness = 1.0;
+const PMVector c_defaultOffset = PMVector( 0.0, 0.0 );
+
+int PMText::s_parameterKey = 0;
+int PMText::s_steps = c_defaultTextSteps;
+
+PMDefinePropertyClass( PMText, PMTextProperty );
+
+PMMetaObject* PMText::s_pMetaObject = 0;
+PMObject* createNewText( PMPart* part )
+{
+ return new PMText( part );
+}
+
+PMText::PMText( PMPart* part )
+ : Base( part )
+{
+ m_text = c_defaultText;
+ m_font = c_defaultFont;
+ m_thickness = c_defaultThickness;
+ m_offset = c_defaultOffset;
+}
+
+PMText::PMText( const PMText& t )
+ : Base( t )
+{
+ m_text = t.m_text;
+ m_font = t.m_font;
+ m_thickness = t.m_thickness;
+ m_offset = t.m_offset;
+}
+
+PMText::~PMText( )
+{
+}
+
+QString PMText::description( ) const
+{
+ return i18n( "text" );
+}
+
+void PMText::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "font", m_font );
+ e.setAttribute( "text", m_text );
+ e.setAttribute( "thickness", m_thickness );
+ e.setAttribute( "offset", m_offset.serializeXML( ) );
+ Base::serialize( e, doc );
+}
+
+void PMText::readAttributes( const PMXMLHelper& h )
+{
+ m_font = h.stringAttribute( "font", c_defaultFont );
+ m_text = h.stringAttribute( "text", c_defaultText );
+ m_thickness = h.doubleAttribute( "thickness", c_defaultThickness );
+ m_offset = h.vectorAttribute( "offset", c_defaultOffset );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMText::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Text", Base::metaObject( ),
+ createNewText );
+ s_pMetaObject->addProperty(
+ new PMTextProperty( "font", &PMText::setFont, &PMText::font ) );
+ s_pMetaObject->addProperty(
+ new PMTextProperty( "text", &PMText::setText, &PMText::text ) );
+ s_pMetaObject->addProperty(
+ new PMTextProperty( "thickness", &PMText::setThickness, &PMText::thickness ) );
+ s_pMetaObject->addProperty(
+ new PMTextProperty( "offset", &PMText::setOffset, &PMText::offset ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMText::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMText::setFont( const QString& f )
+{
+ if( f != m_font )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFontID, m_font );
+ m_font = f;
+ setViewStructureChanged( );
+ }
+}
+
+void PMText::setText( const QString& t )
+{
+ if( t != m_text )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMTextID, m_text );
+ m_text = t;
+ setViewStructureChanged( );
+ }
+}
+
+void PMText::setThickness( double t )
+{
+ if( t != m_thickness )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMThicknessID, m_thickness );
+ m_thickness = t;
+ setViewStructureChanged( );
+ }
+}
+
+void PMText::setOffset( const PMVector& o )
+{
+ if( o != m_offset )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOffsetID, m_offset );
+ m_offset = o;
+ m_offset.resize( 2 );
+ setViewStructureChanged( );
+ }
+}
+
+PMDialogEditBase* PMText::editWidget( QWidget* parent ) const
+{
+ return new PMTextEdit( parent );
+}
+
+void PMText::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMFontID:
+ setFont( data->stringData( ) );
+ break;
+ case PMTextID:
+ setText( data->stringData( ) );
+ break;
+ case PMThicknessID:
+ setThickness( data->doubleData( ) );
+ break;
+ case PMOffsetID:
+ setOffset( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMText::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+void PMText::createViewStructure( )
+{
+ // calculate needed points and lines
+ int nlines = 0, npoints = 0;
+
+ QString file = PMResourceLocator::findFile( m_font );
+ PMTrueTypeFont* font = PMTrueTypeCache::font( file );
+
+ if( font && font->isValid( ) )
+ {
+ QTextStream str( &m_text, IO_ReadOnly );
+ QChar c;
+ PMTrueTypeOutline* ol;
+
+ while( !str.atEnd( ) )
+ {
+ str >> c;
+ ol = font->outline( c );
+ if( ol )
+ {
+ npoints += ol->segments( ) * 2 * s_steps;
+ nlines += ol->segments( ) * ( 2 * s_steps + 1 );
+ }
+ }
+ }
+
+ if( !m_pViewStructure )
+ m_pViewStructure = new PMViewStructure( npoints, nlines );
+ else
+ {
+ if( m_pViewStructure->points( ).size( ) != ( unsigned ) npoints )
+ m_pViewStructure->points( ).resize( npoints );
+ if( m_pViewStructure->lines( ).size( ) != ( unsigned ) nlines )
+ m_pViewStructure->lines( ).resize( nlines );
+ }
+
+ if( ( nlines > 0 ) && ( npoints > 0 ) && font )
+ {
+ // create the view structure
+ QTextStream str( &m_text, IO_ReadOnly );
+ QChar c, oldc;
+ PMTrueTypeOutline* ol;
+ double dp = 1.0 / s_steps;
+ int i;
+ int hnpoints = npoints / 2;
+ int pbase = 0;
+ int lbase = 0;
+ PMVector v2( 2 );
+ PMVector v3( 3 );
+ int firstPoint = 0;
+ PMVector coffset( 0.0, 0.0, 0.0 );
+ double kerning = 0;
+
+ PMPointArray& points = m_pViewStructure->points( );
+ PMLineArray& lines = m_pViewStructure->lines( );
+
+ while( !str.atEnd( ) )
+ {
+ // iterate over all characters with valid outline
+
+ str >> c;
+ ol = font->outline( c );
+ if( ol )
+ {
+ // kerning offset
+ kerning = font->kerning( oldc, c );
+ coffset[0] += kerning;
+
+ const PMSegmentListList& out = ol->outline( );
+ PMSegmentListList::ConstIterator oit;
+ for( oit = out.begin( ); oit != out.end( ); ++oit )
+ {
+ // iterate over all contours
+
+ PMSegmentList::ConstIterator sit;
+ PMSegmentList::ConstIterator eit = ( *oit ).end( );
+ eit--;
+
+ firstPoint = pbase;
+ for( sit = ( *oit ).begin( ); sit != ( *oit ).end( ); ++sit )
+ {
+ // iterate over all segments for the current contour
+
+ lines[lbase] = PMLine( pbase, pbase + hnpoints );
+ lbase++;
+
+ for( i = 0; i < s_steps; i++ )
+ {
+ v2 = ( *sit ).point( i * dp );
+ v3[0] = v2[0];
+ v3[1] = v2[1];
+ v3[2] = 0.0;
+ v3 += coffset;
+ points[pbase] = PMPoint( v3 );
+ v3[2] = m_thickness;
+ points[pbase + hnpoints] = PMPoint( v3 );
+
+ if( ( i != ( s_steps - 1 ) ) || ( sit != eit ) )
+ {
+ lines[lbase] = PMLine( pbase, pbase + 1 );
+ lbase++;
+ lines[lbase] = PMLine( pbase + hnpoints,
+ pbase + hnpoints + 1 );
+ lbase++;
+ }
+ else
+ {
+ lines[lbase] = PMLine( firstPoint, pbase );
+ lbase++;
+ lines[lbase] = PMLine( firstPoint + hnpoints,
+ pbase + hnpoints );
+ lbase++;
+ }
+
+ pbase++;
+ }
+ }
+ }
+ coffset[0] -= kerning;
+ coffset[0] += ol->advance( );
+ coffset += m_offset;
+ }
+ oldc = c;
+ }
+ if( ( lbase != nlines ) || ( pbase != hnpoints ) )
+ kdError( PMArea ) << "PMText::createViewStructure is buggy!\n";
+ }
+}
+
+void PMText::setSteps( int s )
+{
+ if( s >= 1 )
+ s_steps = s;
+ else
+ kdDebug( PMArea ) << "PMText::setSteps: S must be greater than 0\n";
+ s_parameterKey++;
+}
diff --git a/kpovmodeler/pmtext.h b/kpovmodeler/pmtext.h
new file mode 100644
index 00000000..3a7350bb
--- /dev/null
+++ b/kpovmodeler/pmtext.h
@@ -0,0 +1,147 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTEXT_H
+#define PMTEXT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray truetype texts.
+ */
+
+class PMText : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+public:
+ /**
+ * Creates an empty PMText
+ */
+ PMText( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMText( const PMText& t );
+ /**
+ * deletes the PMText
+ */
+ virtual ~PMText( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMText( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMTextEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmtext" ); }
+
+ /**
+ * Returns the font file
+ */
+ QString font( ) const { return m_font; }
+ /**
+ * Sets the font file
+ */
+ void setFont( const QString& f );
+ /**
+ * Returns the text
+ */
+ QString text( ) const { return m_text; }
+ /**
+ * Sets the text
+ */
+ void setText( const QString& t );
+ /**
+ * Returns the thickness
+ */
+ double thickness( ) const { return m_thickness; }
+ /**
+ * Sets the thickness
+ */
+ void setThickness( double t );
+ /**
+ * Returns the additional offset (2D vector)
+ */
+ PMVector offset( ) const { return m_offset; }
+ /**
+ * Sets the offset (2D vector)
+ */
+ void setOffset( const PMVector& o );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ /**
+ * Call this if the povray library paths have changed
+ */
+ static void povrayLibraryPathsChanged( ) { s_parameterKey++; }
+ /**
+ * Returns the number of lines for rendering
+ */
+ static int steps( ) { return s_steps; }
+ /**
+ * Sets the number of lines for rendering
+ */
+ static void setSteps( int s );
+
+protected:
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey; }
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMTextMementoID { PMFontID, PMTextID, PMThicknessID, PMOffsetID };
+ QString m_font, m_text;
+ double m_thickness;
+ PMVector m_offset;
+
+ static int s_steps;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmtextedit.cpp b/kpovmodeler/pmtextedit.cpp
new file mode 100644
index 00000000..16f8501d
--- /dev/null
+++ b/kpovmodeler/pmtextedit.cpp
@@ -0,0 +1,138 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtextedit.h"
+#include "pmtext.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+
+PMTextEdit::PMTextEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMTextEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Font:" ), this ) );
+ m_pFont = new QLineEdit( this );
+ hl->addWidget( m_pFont );
+ m_pChooseFont = new QPushButton( this );
+ m_pChooseFont->setPixmap( SmallIcon( "fileopen" ) );
+ hl->addWidget( m_pChooseFont );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Text:" ), this ) );
+ m_pText = new QLineEdit( this );
+ hl->addWidget( m_pText );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Thickness:" ), this ) );
+ m_pThickness = new PMFloatEdit( this );
+ hl->addWidget( m_pThickness );
+ hl->addStretch( 1 );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( new QLabel( i18n( "Offset:" ), this ) );
+ m_pOffset = new PMVectorEdit( "x", "y", this );
+ hl->addWidget( m_pOffset );
+
+ connect( m_pFont, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotTextChanged( const QString& ) ) );
+ connect( m_pChooseFont, SIGNAL( clicked( ) ),
+ SLOT( slotChooseFont( ) ) );
+ connect( m_pText, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotTextChanged( const QString& ) ) );
+ connect( m_pThickness, SIGNAL( dataChanged( ) ),
+ SIGNAL( dataChanged( ) ) );
+ connect( m_pOffset, SIGNAL( dataChanged( ) ),
+ SIGNAL( dataChanged( ) ) );
+}
+
+void PMTextEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Text" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMText* ) o;
+
+ m_pFont->setText( m_pDisplayedObject->font( ) );
+ m_pText->setText( m_pDisplayedObject->text( ) );
+ m_pThickness->setValue( m_pDisplayedObject->thickness( ) );
+ m_pOffset->setVector( m_pDisplayedObject->offset( ) );
+
+ m_pFont->setReadOnly( readOnly );
+ m_pChooseFont->setEnabled( !readOnly );
+ m_pText->setReadOnly( readOnly );
+ m_pThickness->setReadOnly( readOnly );
+ m_pOffset->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMTextEdit: Can't display object\n";
+}
+
+void PMTextEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setFont( m_pFont->text( ) );
+ m_pDisplayedObject->setText( m_pText->text( ) );
+ m_pDisplayedObject->setThickness( m_pThickness->value( ) );
+ m_pDisplayedObject->setOffset( m_pOffset->vector( ) );
+ }
+}
+
+bool PMTextEdit::isDataValid( )
+{
+ if( m_pThickness->isDataValid( ) )
+ if( m_pOffset->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+void PMTextEdit::slotTextChanged( const QString& )
+{
+ emit dataChanged( );
+}
+
+void PMTextEdit::slotChooseFont( )
+{
+ QString str = KFileDialog::getOpenFileName( QString::null, QString::null );
+
+ if( !str.isEmpty() )
+ {
+ m_pFont->setText( str );
+ emit dataChanged( );
+ }
+}
+
+#include "pmtextedit.moc"
diff --git a/kpovmodeler/pmtextedit.h b/kpovmodeler/pmtextedit.h
new file mode 100644
index 00000000..3dd11280
--- /dev/null
+++ b/kpovmodeler/pmtextedit.h
@@ -0,0 +1,74 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTEXTEDIT_H
+#define PMTEXTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMText;
+class PMVectorEdit;
+class PMFloatEdit;
+class QLineEdit;
+class QPushButton;
+
+/**
+ * Dialog edit class for @ref PMText
+ */
+class PMTextEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMTextEdit with parent and name
+ */
+ PMTextEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+
+protected slots:
+ void slotTextChanged( const QString& t );
+ void slotChooseFont( );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMText* m_pDisplayedObject;
+ QLineEdit* m_pFont;
+ QPushButton* m_pChooseFont;
+ QLineEdit* m_pText;
+ PMFloatEdit* m_pThickness;
+ PMVectorEdit* m_pOffset;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmtexture.cpp b/kpovmodeler/pmtexture.cpp
new file mode 100644
index 00000000..4b8a21ff
--- /dev/null
+++ b/kpovmodeler/pmtexture.cpp
@@ -0,0 +1,124 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtexture.h"
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmtextureedit.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMTexture, PMTextureProperty );
+
+PMMetaObject* PMTexture::s_pMetaObject = 0;
+PMObject* createNewTexture( PMPart* part )
+{
+ return new PMTexture( part );
+}
+
+PMTexture::PMTexture( PMPart* part ) : Base( part )
+{
+ m_uvMapping = false;
+}
+
+PMTexture::PMTexture( const PMTexture& t ) : Base( t )
+{
+ m_uvMapping = t.m_uvMapping;
+}
+
+PMTexture::~PMTexture( )
+{
+}
+
+PMMetaObject* PMTexture::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Texture", Base::metaObject( ),
+ createNewTexture );
+ s_pMetaObject->addProperty(
+ new PMTextureProperty( "uvMapping", &PMTexture::setUVMapping, &PMTexture::uvMapping ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMTexture::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMTexture::description( ) const
+{
+ return i18n( "texture" );
+}
+
+PMDialogEditBase* PMTexture::editWidget( QWidget* parent ) const
+{
+ return new PMTextureEdit( parent );
+}
+
+void PMTexture::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "uv_mapping", m_uvMapping );
+ Base::serialize( e, doc );
+}
+
+void PMTexture::readAttributes( const PMXMLHelper& h )
+{
+ m_uvMapping = h.boolAttribute( "uv_mapping", false );
+ Base::readAttributes( h );
+}
+
+void PMTexture::setUVMapping( bool m )
+{
+ if( m != m_uvMapping )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUVMappingID, m_uvMapping );
+ m_uvMapping = m;
+ }
+}
+
+void PMTexture::restoreMemento( PMMemento *s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMUVMappingID:
+ setUVMapping( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMTexture::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmtexture.h b/kpovmodeler/pmtexture.h
new file mode 100644
index 00000000..b8b176db
--- /dev/null
+++ b/kpovmodeler/pmtexture.h
@@ -0,0 +1,95 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTEXTURE_H
+#define PMTEXTURE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+
+/**
+ * Class for povray textures
+ */
+class PMTexture : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates an PMTexture
+ */
+ PMTexture( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMTexture( const PMTexture& t );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMTexture( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMTexture( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMTextureEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmtexture" ); }
+
+ /**
+ * Returns the uv mapping flag
+ */
+ bool uvMapping() const { return m_uvMapping; }
+ /**
+ * Sets the uv maaping flag
+ */
+ void setUVMapping( bool m );
+
+ /** */
+ virtual void restoreMemento( PMMemento *s );
+
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMPigmentMementoID { PMUVMappingID };
+
+ bool m_uvMapping;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmtexturebase.cpp b/kpovmodeler/pmtexturebase.cpp
new file mode 100644
index 00000000..82a92418
--- /dev/null
+++ b/kpovmodeler/pmtexturebase.cpp
@@ -0,0 +1,180 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtexturebase.h"
+#include "pmdeclare.h"
+#include "pmpart.h"
+#include "pmsymboltable.h"
+#include "pmtexturebaseedit.h"
+#include "pmparser.h"
+
+#include "pmmemento.h"
+#include "pmxmlhelper.h"
+
+#include <klocale.h>
+
+PMDefinePropertyClass( PMTextureBase, PMTextureBaseProperty );
+
+PMMetaObject* PMTextureBase::s_pMetaObject = 0;
+
+PMTextureBase::PMTextureBase( PMPart* part )
+ : Base( part )
+{
+ m_pLinkedObject = 0;
+}
+
+PMTextureBase::PMTextureBase( const PMTextureBase& b )
+ : Base( b )
+{
+ m_pLinkedObject = 0;
+ setLinkedObject( b.m_pLinkedObject );
+}
+
+PMTextureBase::~PMTextureBase( )
+{
+}
+
+PMMetaObject* PMTextureBase::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "TextureBase", Base::metaObject( ) );
+ s_pMetaObject->addProperty(
+ new PMTextureBaseProperty( "linkedObject", &PMTextureBase::setLinkedObjectProperty,
+ &PMTextureBase::linkedObjectProperty ) );
+ s_pMetaObject->addProperty(
+ new PMTextureBaseProperty( "hasLinkedObject", 0, &PMTextureBase::hasLinkedObject ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMTextureBase::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+bool PMTextureBase::setLinkedObject( PMDeclare* obj )
+{
+ if( obj )
+ {
+ if( obj->declareType( ) == type( ) )
+ {
+ if( m_pLinkedObject != obj )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMLinkedObjectID,
+ m_pLinkedObject );
+ m_pMemento->setViewStructureChanged( );
+ }
+
+ if( m_pLinkedObject )
+ {
+ m_pLinkedObject->removeLinkedObject( this );
+ if( m_pMemento )
+ m_pMemento->addChangedObject( m_pLinkedObject, PMCData );
+ }
+ m_pLinkedObject = obj;
+ m_pLinkedObject->addLinkedObject( this );
+ if( m_pMemento )
+ m_pMemento->addChangedObject( m_pLinkedObject, PMCData );
+ }
+ return true;
+ }
+ }
+ else
+ {
+ if( m_pLinkedObject != 0 )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMLinkedObjectID,
+ m_pLinkedObject );
+ m_pMemento->addChangedObject( m_pLinkedObject, PMCData );
+ }
+ m_pLinkedObject->removeLinkedObject( this );
+ m_pLinkedObject = 0;
+ }
+ return true;
+ }
+ return false;
+}
+
+void PMTextureBase::setLinkedObjectProperty( PMObject* o )
+{
+ if( o == 0 )
+ setLinkedObject( 0 );
+ else if( o->isA( "Declare" ) )
+ setLinkedObject( ( PMDeclare* ) o );
+}
+
+void PMTextureBase::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ if( m_pLinkedObject )
+ e.setAttribute( "prototype", m_pLinkedObject->id( ) );
+ Base::serialize( e, doc );
+}
+
+void PMTextureBase::readAttributes( const PMXMLHelper& h )
+{
+ QString id = h.stringAttribute( "prototype", "" );
+ if( !id.isEmpty( ) )
+ {
+ PMDeclare* link = h.parser( )->checkLink( id );
+ if( link )
+ {
+ if( link->declareType( ) == type( ) )
+ {
+ m_pLinkedObject = link;
+ m_pLinkedObject->addLinkedObject( this );
+ }
+ else
+ h.parser( )->printError( i18n( "Declare \"%1\" has wrong type." )
+ .arg( id ) );
+ }
+ }
+}
+
+void PMTextureBase::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMLinkedObjectID:
+ setLinkedObject( ( PMDeclare* ) data->objectData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMTextureBase::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmtexturebase.h b/kpovmodeler/pmtexturebase.h
new file mode 100644
index 00000000..2bd687f6
--- /dev/null
+++ b/kpovmodeler/pmtexturebase.h
@@ -0,0 +1,96 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTEXTUREBASE_H
+#define PMTEXTUREBASE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qvaluelist.h>
+
+#include "pmnamedobject.h"
+#include "pmdeclare.h"
+
+/**
+ * Base class for all textures that can link to declares
+ */
+class PMTextureBase : public PMNamedObject
+{
+ typedef PMNamedObject Base;
+public:
+ /**
+ * Creates an PMTextureBase
+ */
+ PMTextureBase( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMTextureBase( const PMTextureBase& b );
+ /**
+ * Deletes the object
+ */
+ virtual ~PMTextureBase( );
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ /** */
+ virtual PMDeclare* linkedObject( ) const { return m_pLinkedObject; }
+ /**
+ * Sets the linked object. Returns true if successful
+ */
+ bool setLinkedObject( PMDeclare* o );
+ /**
+ * Returns true if a linked object is set. Used by the
+ * insert possibilities framework.
+ */
+ bool hasLinkedObject( ) const { return m_pLinkedObject; }
+
+ /**
+ * Method used by the properties framework
+ */
+ PMObject* linkedObjectProperty( ) const { return m_pLinkedObject; }
+ /**
+ * Method used by the properties framework
+ */
+ void setLinkedObjectProperty( PMObject* o );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMTextureBaseMementoID { PMLinkedObjectID };
+ PMDeclare* m_pLinkedObject;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmtexturebaseedit.cpp b/kpovmodeler/pmtexturebaseedit.cpp
new file mode 100644
index 00000000..e9b91486
--- /dev/null
+++ b/kpovmodeler/pmtexturebaseedit.cpp
@@ -0,0 +1,72 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtexturebaseedit.h"
+#include "pmpigment.h"
+#include "pmlinkedit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+
+PMTextureBaseEdit::PMTextureBaseEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+
+void PMTextureBaseEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+ m_pLinkEdit = new PMLinkEdit( this );
+ topLayout( )->addWidget( m_pLinkEdit );
+ connect( m_pLinkEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+
+void PMTextureBaseEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "TextureBase" ) )
+ {
+ m_pDisplayedObject = ( PMTextureBase* ) o;
+ m_pLinkEdit->setReadOnly( o->isReadOnly( ) );
+ m_pLinkEdit->setDisplayedObject( o );
+ m_pLinkEdit->setLinkPossibility( m_pDisplayedObject->type( ) );
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMTextureBaseEdit: Can't display object\n";
+}
+
+void PMTextureBaseEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setLinkedObject( m_pLinkEdit->link( ) );
+ }
+}
+
+void PMTextureBaseEdit::enableLinkEdit( bool enable )
+{
+ m_pLinkEdit->setEnabled( enable );
+}
+
+#include "pmtexturebaseedit.moc"
diff --git a/kpovmodeler/pmtexturebaseedit.h b/kpovmodeler/pmtexturebaseedit.h
new file mode 100644
index 00000000..b8d67f56
--- /dev/null
+++ b/kpovmodeler/pmtexturebaseedit.h
@@ -0,0 +1,64 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTEXTUREBASEEDIT_H
+#define PMTEXTUREBASEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmnamedobjectedit.h"
+
+class PMTextureBase;
+class PMLinkEdit;
+
+/**
+ * Dialog edit class for @ref PMTextureBase
+ */
+class PMTextureBaseEdit : public PMNamedObjectEdit
+{
+ Q_OBJECT
+ typedef PMNamedObjectEdit Base;
+public:
+ /**
+ * Creates a PMTextureBaseEdit with parent and name
+ */
+ PMTextureBaseEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+ /**
+ * Enables/disables the link edit widget
+ */
+ void enableLinkEdit( bool enable );
+
+private:
+ PMTextureBase* m_pDisplayedObject;
+ PMLinkEdit* m_pLinkEdit;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmtextureedit.cpp b/kpovmodeler/pmtextureedit.cpp
new file mode 100644
index 00000000..8a3d4f9f
--- /dev/null
+++ b/kpovmodeler/pmtextureedit.cpp
@@ -0,0 +1,67 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtextureedit.h"
+#include "pmtexture.h"
+#include "pmlinkedit.h"
+
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+
+PMTextureEdit::PMTextureEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMTextureEdit::createTopWidgets()
+{
+ Base::createTopWidgets();
+ m_pUVMapping = new QCheckBox( i18n( "UV mapping" ), this );
+ topLayout( )->addWidget( m_pUVMapping );
+
+ connect( m_pUVMapping, SIGNAL( clicked() ), SIGNAL( dataChanged() ) );
+}
+
+void PMTextureEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Texture" ) )
+ {
+ m_pDisplayedObject = ( PMTexture* ) o;
+ bool readOnly = m_pDisplayedObject->isReadOnly( );
+ m_pUVMapping->setChecked( m_pDisplayedObject->uvMapping() );
+ m_pUVMapping->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMTextureEdit: Can't display object\n";
+}
+
+void PMTextureEdit::saveContents()
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents();
+ m_pDisplayedObject->setUVMapping( m_pUVMapping->isChecked() );
+ }
+}
+
+#include "pmtextureedit.moc"
diff --git a/kpovmodeler/pmtextureedit.h b/kpovmodeler/pmtextureedit.h
new file mode 100644
index 00000000..7b799a5e
--- /dev/null
+++ b/kpovmodeler/pmtextureedit.h
@@ -0,0 +1,60 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTEXTUREEDIT_H
+#define PMTEXTUREEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+
+class PMTexture;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMTexture
+ */
+class PMTextureEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMTextureEdit with parent and name
+ */
+ PMTextureEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMTexture* m_pDisplayedObject;
+ QCheckBox* m_pUVMapping;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmtexturemap.cpp b/kpovmodeler/pmtexturemap.cpp
new file mode 100644
index 00000000..fad93c61
--- /dev/null
+++ b/kpovmodeler/pmtexturemap.cpp
@@ -0,0 +1,601 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtexturemapedit.h"
+#include "pmtexturemap.h"
+
+#include "pmxmlhelper.h"
+#include "pmmapmemento.h"
+
+#include <qtextstream.h>
+#include <klocale.h>
+
+class PMValueProperty : public PMPropertyBase
+{
+public:
+ PMValueProperty( )
+ : PMPropertyBase( "mapValues", PMVariant::Double )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ m_index = index;
+ }
+ virtual int size( PMObject* object, int /*dimension*/ ) const
+ {
+ return ( ( PMTextureMapBase* ) object )->mapEntries( );
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& var )
+ {
+ PMTextureMapBase* m = ( PMTextureMapBase* ) obj;
+ QValueList<double> list = m->mapValues( );
+ QValueList<double>::Iterator it = list.at( m_index );
+
+ if( it == list.end( ) )
+ {
+ kdError( PMArea ) << "Range error in PMTextureMapBase::ValueProperty::set" << endl;
+ return false;
+ }
+
+ *it = var.doubleData( );
+
+ m->setMapValues( list );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ PMTextureMapBase* m = ( PMTextureMapBase* ) obj;
+ QValueList<double> list = m->mapValues( );
+ QValueList<double>::ConstIterator it = list.at( m_index );
+
+ if( it == list.end( ) )
+ {
+ kdError( PMArea ) << "Range error in PMTextureMapBase::ValueProperty::get" << endl;
+ return PMVariant( );
+ }
+
+ return PMVariant( *it );
+ }
+
+private:
+ int m_index;
+};
+
+
+PMMetaObject* PMTextureMapBase::s_pMetaObject = 0;
+
+PMTextureMapBase::PMTextureMapBase( PMPart* part )
+ : Base( part )
+{
+}
+
+PMTextureMapBase::PMTextureMapBase( const PMTextureMapBase& m )
+ : Base( m )
+{
+}
+
+PMTextureMapBase::~PMTextureMapBase( )
+{
+}
+
+void PMTextureMapBase::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "map_values", valuesToString( ) );
+ Base::serialize( e, doc );
+}
+
+void PMTextureMapBase::readAttributes( const PMXMLHelper& h )
+{
+ stringToValues( h.stringAttribute( "map_values", "" ) );
+ Base::readAttributes( h );
+}
+
+QString PMTextureMapBase::valuesToString( ) const
+{
+ QString str;
+ QValueList<double>::ConstIterator it;
+
+ it = m_mapValues.begin( );
+ if( it != m_mapValues.end( ) )
+ {
+ str.setNum( *it );
+ ++it;
+ for( ; it != m_mapValues.end( ); ++it )
+ str += QString( " %1" ).arg( *it );
+ }
+ return str;
+}
+
+void PMTextureMapBase::stringToValues( const QString& str )
+{
+ m_mapValues.clear( );
+ QString tstr = str;
+ QTextIStream s( &tstr );
+ double d;
+
+ while( !s.atEnd( ) )
+ {
+ s >> d;
+ m_mapValues.append( d );
+ }
+}
+
+PMMetaObject* PMTextureMapBase::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "TextureMapBase", Base::metaObject( ) );
+ s_pMetaObject->addProperty( new PMValueProperty( ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMTextureMapBase::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+PMDialogEditBase* PMTextureMapBase::editWidget( QWidget* parent ) const
+{
+ return new PMTextureMapEdit( parent );
+}
+
+void PMTextureMapBase::restoreMemento( PMMemento* s )
+{
+ PMMapMemento* m = ( PMMapMemento* ) s;
+ if( m->mapValuesSaved( ) )
+ {
+ if( m_pMemento )
+ ( ( PMMapMemento* ) m_pMemento )->setMapValues( m_mapValues );
+ m_mapValues = m->mapValues( );
+ }
+ if( m->removedValuesSaved( ) )
+ {
+ if( m_pMemento )
+ ( ( PMMapMemento* ) m_pMemento )->setRemovedValues( m_removedValues );
+ m_removedValues = m->removedValues( );
+ }
+
+ Base::restoreMemento( s );
+}
+
+void PMTextureMapBase::createMemento( )
+{
+ if( m_pMemento )
+ delete m_pMemento;
+ m_pMemento = new PMMapMemento( this );
+}
+
+QValueList<double>::Iterator PMTextureMapBase::valueForChild( PMObject* obj )
+{
+ PMObject* o = firstChild( );
+ QValueList<double>::Iterator it = m_mapValues.begin( );
+
+ while( o && ( o != obj ) )
+ {
+ if( o->type( ) == mapType( ) )
+ ++it;
+ o = o->nextSibling( );
+ }
+ return it;
+}
+
+double PMTextureMapBase::mapValue( const PMObject* obj ) const
+{
+ PMObject* o = firstChild( );
+ QValueList<double>::ConstIterator it = m_mapValues.begin( );
+
+ while( o && ( o != obj ) )
+ {
+ if( o->type( ) == mapType( ) )
+ ++it;
+ o = o->nextSibling( );
+ }
+ return *it;
+}
+
+void PMTextureMapBase::childAdded( PMObject* ao )
+{
+ if( ( unsigned ) countChildren( ) <= m_mapValues.count( ) )
+ return;
+
+ if( m_pMemento )
+ ( ( PMMapMemento* ) m_pMemento )->setMapValues( m_mapValues );
+ if( m_removedValues.isEmpty( ) )
+ {
+ QValueList<double>::Iterator it = valueForChild( ao );
+ if( it == m_mapValues.end( ) )
+ {
+ --it;
+ if( it == m_mapValues.end( ) )
+ m_mapValues.append( 0.0 );
+ else
+ {
+ double v = *it + 0.1;
+ if( v > 1.0 )
+ v = 1.0;
+ m_mapValues.append( v );
+ }
+ }
+ else if( it == m_mapValues.begin( ) )
+ m_mapValues.prepend( 0.0 );
+ else
+ {
+ double va = *it;
+ double vb = *( --it );
+ m_mapValues.insert( ++it, ( va + vb ) / 2.0 );
+ }
+ }
+ else
+ {
+ if( m_pMemento )
+ ( ( PMMapMemento* ) m_pMemento )->setRemovedValues( m_removedValues );
+
+ QValueList<double>::Iterator it = m_mapValues.begin( );
+ bool stop = false;
+ double v = m_removedValues.last( );
+ m_removedValues.remove( m_removedValues.fromLast( ) );
+
+ while( ( it != m_mapValues.end( ) ) && !stop )
+ {
+ if( ( *it ) > v )
+ stop = true;
+ else
+ ++it;
+ }
+ m_mapValues.insert( it, v );
+ }
+}
+
+bool PMTextureMapBase::takeChild( PMObject* o )
+{
+ if( m_pMemento )
+ {
+ ( ( PMMapMemento* ) m_pMemento )->setMapValues( m_mapValues );
+ ( ( PMMapMemento* ) m_pMemento )->setRemovedValues( m_removedValues );
+ }
+
+ QValueList<double>::Iterator it = valueForChild( o );
+ if( it != m_mapValues.end( ) )
+ {
+ m_removedValues.append( *it );
+ m_mapValues.remove( it );
+ }
+
+ return Base::takeChild( o );
+}
+
+void PMTextureMapBase::setMapValues( const QValueList<double>& v )
+{
+ if( m_pMemento )
+ {
+ ( ( PMMapMemento* ) m_pMemento )->setMapValues( m_mapValues );
+ ( ( PMMapMemento* ) m_pMemento )->setRemovedValues( m_removedValues );
+ }
+ m_removedValues.clear( );
+ m_mapValues = v;
+}
+
+PMObject* PMTextureMapBase::nextMapEntry( PMObject* o )
+{
+ bool stop = false;
+ PMObject* result = o;
+
+ do
+ {
+ if( result == 0 )
+ result = firstChild( );
+ else
+ result = result->nextSibling( );
+
+ if( !result )
+ stop = true;
+ else if( result->type( ) == mapType( ) )
+ stop = true;
+ }
+ while( !stop );
+
+ return result;
+}
+
+
+PMMetaObject* PMTextureMap::s_pMetaObject = 0;
+PMObject* createNewTextureMap( PMPart* part )
+{
+ return new PMTextureMap( part );
+}
+
+PMTextureMap::PMTextureMap( PMPart* part )
+ : Base( part )
+{
+}
+
+PMTextureMap::PMTextureMap( const PMTextureMap& m )
+ : Base( m )
+{
+}
+
+PMTextureMap::~PMTextureMap( )
+{
+}
+
+PMMetaObject* PMTextureMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "TextureMap", Base::metaObject( ),
+ createNewTextureMap );
+ }
+ return s_pMetaObject;
+}
+
+void PMTextureMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMTextureMap::description( ) const
+{
+ return i18n( "texture map" );
+}
+
+
+PMMetaObject* PMPigmentMap::s_pMetaObject = 0;
+PMObject* createNewPigmentMap( PMPart* part )
+{
+ return new PMPigmentMap( part );
+}
+
+PMPigmentMap::PMPigmentMap( PMPart* part )
+ : Base( part )
+{
+}
+
+PMPigmentMap::PMPigmentMap( const PMPigmentMap& m )
+ : Base( m )
+{
+}
+
+PMPigmentMap::~PMPigmentMap( )
+{
+}
+
+PMMetaObject* PMPigmentMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "PigmentMap", Base::metaObject( ),
+ createNewPigmentMap );
+ }
+ return s_pMetaObject;
+}
+
+void PMPigmentMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMPigmentMap::description( ) const
+{
+ return i18n( "pigment map" );
+}
+
+
+PMMetaObject* PMColorMap::s_pMetaObject = 0;
+PMObject* createNewColorMap( PMPart* part )
+{
+ return new PMColorMap( part );
+}
+
+PMColorMap::PMColorMap( PMPart* part )
+ : Base( part )
+{
+}
+
+PMColorMap::PMColorMap( const PMColorMap& m )
+ : Base( m )
+{
+}
+
+PMColorMap::~PMColorMap( )
+{
+}
+
+PMMetaObject* PMColorMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "ColorMap", Base::metaObject( ),
+ createNewColorMap );
+ }
+ return s_pMetaObject;
+}
+
+void PMColorMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMColorMap::description( ) const
+{
+ return i18n( "color map" );
+}
+
+
+PMMetaObject* PMNormalMap::s_pMetaObject = 0;
+PMObject* createNewNormalMap( PMPart* part )
+{
+ return new PMNormalMap( part );
+}
+
+PMNormalMap::PMNormalMap( PMPart* part )
+ : Base( part )
+{
+}
+
+PMNormalMap::PMNormalMap( const PMNormalMap& m )
+ : Base( m )
+{
+}
+
+PMNormalMap::~PMNormalMap( )
+{
+}
+
+PMMetaObject* PMNormalMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "NormalMap", Base::metaObject( ),
+ createNewNormalMap );
+ }
+ return s_pMetaObject;
+}
+
+void PMNormalMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMNormalMap::description( ) const
+{
+ return i18n( "normal map" );
+}
+
+
+PMMetaObject* PMSlopeMap::s_pMetaObject = 0;
+PMObject* createNewSlopeMap( PMPart* part )
+{
+ return new PMSlopeMap( part );
+}
+
+PMSlopeMap::PMSlopeMap( PMPart* part )
+ : Base( part )
+{
+}
+
+PMSlopeMap::PMSlopeMap( const PMSlopeMap& m )
+ : Base( m )
+{
+}
+
+PMSlopeMap::~PMSlopeMap( )
+{
+}
+
+PMMetaObject* PMSlopeMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "SlopeMap", Base::metaObject( ),
+ createNewSlopeMap );
+ }
+ return s_pMetaObject;
+}
+
+void PMSlopeMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMSlopeMap::description( ) const
+{
+ return i18n( "slope map" );
+}
+
+
+PMMetaObject* PMDensityMap::s_pMetaObject = 0;
+PMObject* createNewDensityMap( PMPart* part )
+{
+ return new PMDensityMap( part );
+}
+
+PMDensityMap::PMDensityMap( PMPart* part )
+ : Base( part )
+{
+}
+
+PMDensityMap::PMDensityMap( const PMDensityMap& m )
+ : Base( m )
+{
+}
+
+PMDensityMap::~PMDensityMap( )
+{
+}
+
+PMMetaObject* PMDensityMap::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "DensityMap", Base::metaObject( ),
+ createNewDensityMap );
+ }
+ return s_pMetaObject;
+}
+
+void PMDensityMap::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+QString PMDensityMap::description( ) const
+{
+ return i18n( "density map" );
+}
+
+
+
diff --git a/kpovmodeler/pmtexturemap.h b/kpovmodeler/pmtexturemap.h
new file mode 100644
index 00000000..227c7e1f
--- /dev/null
+++ b/kpovmodeler/pmtexturemap.h
@@ -0,0 +1,368 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTEXTUREMAP_H
+#define PMTEXTUREMAP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebase.h"
+#include "pmvector.h"
+
+#include <qvaluelist.h>
+
+/**
+ * Base class for color, pigment, texture and normal maps
+ */
+
+class PMTextureMapBase : public PMTextureBase
+{
+ typedef PMTextureBase Base;
+public:
+ /**
+ * Creates a PMTextureMapBase
+ */
+ PMTextureMapBase( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMTextureMapBase( const PMTextureMapBase& b );
+ /**
+ * deletes the PMTextureMapBase
+ */
+ virtual ~PMTextureMapBase( );
+
+ /** */
+ virtual bool dataChangeOnInsertRemove( ) const { return true; }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void childAdded( PMObject* o );
+ /** */
+ virtual bool takeChild( PMObject* o );
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns the map object type
+ */
+ virtual QString mapType( ) const = 0;
+
+ /**
+ * Returns a new @ref PMTextureMapEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+
+ /** */
+ virtual void createMemento( );
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+
+ /**
+ * Returns the map values
+ */
+ QValueList<double> mapValues( ) const { return m_mapValues; }
+ /**
+ * Sets the map values
+ */
+ void setMapValues( const QValueList<double>& v );
+ /**
+ * Returns the map value for the object o
+ */
+ double mapValue( const PMObject* o ) const;
+ /**
+ * Returns the number of map entries
+ */
+ int mapEntries( ) const { return m_mapValues.size( ); }
+
+private:
+ PMObject* nextMapEntry( PMObject* o );
+ void stringToValues( const QString& str );
+ QString valuesToString( ) const;
+ QValueList<double>::Iterator valueForChild( PMObject* o );
+
+ /**
+ * IDs for @ref PMMementoData
+ */
+ // enum PMTextureMapBaseMementoID { };
+
+ /**
+ * list of map values
+ */
+ QValueList<double> m_mapValues;
+ /**
+ * removed map values
+ */
+ QValueList<double> m_removedValues;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+/**
+ * Class for texture maps
+ */
+
+class PMTextureMap : public PMTextureMapBase
+{
+public:
+ typedef PMTextureMapBase Base;
+ /**
+ * Creates a texture map
+ */
+ PMTextureMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMTextureMap( const PMTextureMap& m );
+ /**
+ * Deletes the texture map
+ */
+ virtual ~PMTextureMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMTextureMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString mapType( ) const { return QString( "Texture" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmtexturemap" ); }
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for pigment maps
+ */
+
+class PMPigmentMap : public PMTextureMapBase
+{
+public:
+ typedef PMTextureMapBase Base;
+ /**
+ * Creates a pigment map
+ */
+ PMPigmentMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMPigmentMap( const PMPigmentMap& m );
+ /**
+ * Deletes the pigment map
+ */
+ virtual ~PMPigmentMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMPigmentMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString mapType( ) const { return QString( "Pigment" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmpigmentmap" ); }
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for color maps
+ */
+
+class PMColorMap : public PMTextureMapBase
+{
+public:
+ typedef PMTextureMapBase Base;
+ /**
+ * Creates a color map
+ */
+ PMColorMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMColorMap( const PMColorMap& m );
+ /**
+ * Deletes the color map
+ */
+ virtual ~PMColorMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMColorMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString mapType( ) const { return QString( "SolidColor" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmcolormap" ); }
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+
+/**
+ * Class for normal maps
+ */
+
+class PMNormalMap : public PMTextureMapBase
+{
+public:
+ typedef PMTextureMapBase Base;
+ /**
+ * Creates a normal map
+ */
+ PMNormalMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMNormalMap( const PMNormalMap& m );
+ /**
+ * Deletes the normal map
+ */
+ virtual ~PMNormalMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMNormalMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString mapType( ) const { return QString( "Normal" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmnormalmap" ); }
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for slope maps
+ */
+
+class PMSlopeMap : public PMTextureMapBase
+{
+public:
+ typedef PMTextureMapBase Base;
+ /**
+ * Creates a slope map
+ */
+ PMSlopeMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMSlopeMap( const PMSlopeMap& m );
+ /**
+ * Deletes the slope map
+ */
+ virtual ~PMSlopeMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMSlopeMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString mapType( ) const { return QString( "Slope" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmslopemap" ); }
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+/**
+ * Class for density maps
+ */
+
+class PMDensityMap : public PMTextureMapBase
+{
+public:
+ typedef PMTextureMapBase Base;
+ /**
+ * Creates a density map
+ */
+ PMDensityMap( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMDensityMap( const PMDensityMap& m );
+ /**
+ * Deletes the density map
+ */
+ virtual ~PMDensityMap( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMDensityMap( *this ); }
+ /** */
+ virtual QString description( ) const;
+ /** */
+ virtual QString mapType( ) const { return QString( "Density" ); }
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmdensitymap" ); }
+
+private:
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmtexturemapedit.cpp b/kpovmodeler/pmtexturemapedit.cpp
new file mode 100644
index 00000000..6faf4376
--- /dev/null
+++ b/kpovmodeler/pmtexturemapedit.cpp
@@ -0,0 +1,152 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtexturemapedit.h"
+#include "pmtexturemap.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+
+PMTextureMapEdit::PMTextureMapEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+ m_numValues = 0;
+}
+
+void PMTextureMapEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+ topLayout( )->addWidget( new QLabel( i18n( "Map values:" ), this ) );
+ m_pNoChildLabel = new QLabel( i18n( "(No Child Objects)" ), this );
+ m_pPureLinkLabel = new QLabel( i18n( "(Pure Link)" ), this );
+ topLayout( )->addWidget( m_pNoChildLabel );
+ topLayout( )->addWidget( m_pPureLinkLabel );
+ QHBoxLayout* hl = new QHBoxLayout( topLayout( ) );
+ m_pEditLayout = new QVBoxLayout( hl );
+ hl->addStretch( 1 );
+}
+
+void PMTextureMapEdit::displayObject( PMObject* o )
+{
+ QString str;
+
+ if( o->isA( "TextureMapBase" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMTextureMapBase* ) o;
+ QValueList<double> mv = m_pDisplayedObject->mapValues( );
+ QValueList<double>::Iterator vit = mv.begin( );
+ QPtrListIterator<PMFloatEdit> eit( m_edits );
+ PMFloatEdit* edit;
+
+ m_numValues = 0;
+
+ for( ; vit != mv.end( ); ++vit )
+ {
+ if( eit.current( ) )
+ {
+ eit.current( )->setValue( *vit );
+ eit.current( )->show( );
+ eit.current( )->setReadOnly( readOnly );
+ ++eit;
+ }
+ else
+ {
+ edit = new PMFloatEdit( this );
+ m_pEditLayout->addWidget( edit );
+ m_edits.append( edit );
+ edit->setValue( *vit );
+ edit->setValidation( true, 0.0, true, 1.0 );
+ edit->setReadOnly( readOnly );
+ connect( edit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ }
+ m_numValues++;
+ }
+ for( ; eit.current( ); ++eit )
+ eit.current( )->hide( );
+ if( m_numValues == 0 )
+ {
+ if( o->linkedObject( ) )
+ {
+ m_pPureLinkLabel->show( );
+ m_pNoChildLabel->hide( );
+ }
+ else
+ {
+ m_pPureLinkLabel->hide( );
+ m_pNoChildLabel->show( );
+ }
+ }
+ else
+ {
+ m_pNoChildLabel->hide( );
+ m_pPureLinkLabel->hide( );
+ }
+ }
+ else
+ kdError( PMArea ) << "PMTextureMapEdit: Can't display object\n";
+ Base::displayObject( o );
+ enableLinkEdit( m_numValues == 0 );
+}
+
+void PMTextureMapEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ if( m_numValues > 0 )
+ {
+ QPtrListIterator<PMFloatEdit> it( m_edits );
+ int i = 0;
+ QValueList<double> values;
+
+ for( ; ( i < m_numValues ) && it.current( ); ++i, ++it )
+ values.append( it.current( )->value( ) );
+ m_pDisplayedObject->setMapValues( values );
+ }
+ Base::saveContents( );
+ }
+}
+
+bool PMTextureMapEdit::isDataValid( )
+{
+ QPtrListIterator<PMFloatEdit> it( m_edits );
+ int i = 0;
+ double last = 0.0;
+
+ for( ; ( i < m_numValues ) && it.current( ); ++i, ++it )
+ {
+ if( !it.current( )->isDataValid( ) )
+ return false;
+ if( it.current( )->value( ) < last )
+ {
+ KMessageBox::error( this, i18n( "The map values have to be increasing." ),
+ i18n( "Error" ) );
+ it.current( )->setFocus( );
+ return false;
+ }
+ last = it.current( )->value( );
+ }
+ return Base::isDataValid( );
+}
+
+#include "pmtexturemapedit.moc"
diff --git a/kpovmodeler/pmtexturemapedit.h b/kpovmodeler/pmtexturemapedit.h
new file mode 100644
index 00000000..818d7435
--- /dev/null
+++ b/kpovmodeler/pmtexturemapedit.h
@@ -0,0 +1,70 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTEXTUREMAPEDIT_H
+#define PMTEXTUREMAPEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmtexturebaseedit.h"
+#include <qptrlist.h>
+
+class PMTextureMapBase;
+class PMFloatEdit;
+class QWidget;
+class QVBoxLayout;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMTextureMapBase.
+ */
+class PMTextureMapEdit : public PMTextureBaseEdit
+{
+ Q_OBJECT
+ typedef PMTextureBaseEdit Base;
+public:
+ /**
+ * Creates a PMTextureMapEdit with parent and name
+ */
+ PMTextureMapEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMTextureMapBase* m_pDisplayedObject;
+ QPtrList<PMFloatEdit> m_edits;
+ QVBoxLayout* m_pEditLayout;
+ QLabel* m_pNoChildLabel;
+ QLabel* m_pPureLinkLabel;
+ int m_numValues;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmthreestate.h b/kpovmodeler/pmthreestate.h
new file mode 100644
index 00000000..7dd04cf6
--- /dev/null
+++ b/kpovmodeler/pmthreestate.h
@@ -0,0 +1,26 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMTHREESTATE_H
+#define PMTHREESTATE_H
+
+/**
+ * Type for three state attributes: true, false, unspecified
+ */
+enum PMThreeState { PMTrue, PMFalse, PMUnspecified };
+
+#endif
diff --git a/kpovmodeler/pmtokens.h b/kpovmodeler/pmtokens.h
new file mode 100644
index 00000000..f1606e53
--- /dev/null
+++ b/kpovmodeler/pmtokens.h
@@ -0,0 +1,463 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTOKENS_H
+#define PMTOKENS_H
+
+
+enum PMToken {
+ SCANNER_ERROR_TOK=-2,
+ EOF_TOK=-1,
+ //single character tokens
+ //reserved words in povray
+ AA_LEVEL_TOK=0x100,
+ AA_THRESHOLD_TOK,
+ ABS_TOK,
+ ABSORPTION_TOK,
+ ACCURACY_TOK,
+ ACOS_TOK,
+ ACOSH_TOK,
+ ADAPTIVE_TOK,
+ ADC_BAILOUT_TOK,
+ AGATE_TOK,
+ AGATE_TURB_TOK,
+ ALL_TOK,
+ ALL_INTERSECTIONS_TOK,
+ ALPHA_TOK,
+ ALTITUDE_TOK,
+ ALWAYS_SAMPLE_TOK,
+ AMBIENT_TOK,
+ AMBIENT_LIGHT_TOK,
+ ANGLE_TOK,
+ APERTURE_TOK,
+ ARC_ANGLE_TOK,
+ AREA_LIGHT_TOK,
+ AREA_CIRCULAR_TOK,
+ ASC_TOK,
+ ASIN_TOK,
+ ASINH_TOK,
+ ASSUMED_GAMMA_TOK,
+ ATAN_TOK,
+ ATAN2_TOK,
+ ATANH_TOK,
+ ATMOSPHERE_TOK,
+ ATMOSPHERIC_ATTENUATION_TOK,
+ ATTENUATING_TOK,
+ AUTOSTOP_TOK,
+ AVERAGE_TOK,
+ B_SPLINE_TOK,
+ BACKGROUND_TOK,
+ BEZIER_SPLINE_TOK,
+ BICUBIC_PATCH_TOK,
+ BLACK_HOLE_TOK,
+ BLOB_TOK,
+ BLUE_TOK,
+ BLUR_SAMPLES_TOK,
+ BOUNDED_BY_TOK,
+ BOX_TOK,
+ BOXED_TOK,
+ BOZO_TOK,
+ BREAK_TOK,
+ BRICK_TOK,
+ BRICK_SIZE_TOK,
+ BRIGHTNESS_TOK,
+ BRILLIANCE_TOK,
+ BUMPS_TOK,
+ BUMPY1_TOK,
+ BUMPY2_TOK,
+ BUMPY3_TOK,
+ BUMP_MAP_TOK,
+ BUMP_SIZE_TOK,
+ CAMERA_TOK,
+ CASE_TOK,
+ CAUSTICS_TOK,
+ CEIL_TOK,
+ CELLS_TOK,
+ CHECKER_TOK,
+ CHR_TOK,
+ CLIPPED_BY_TOK,
+ CLOCK_TOK,
+ CLOCK_DELTA_TOK,
+ COLLECT_TOK,
+ COLOR_TOK,
+ COLOR_MAP_TOK,
+ COLOUR_TOK,
+ COLOUR_MAP_TOK,
+ COMPONENT_TOK,
+ COMPOSITE_TOK,
+ CONCAT_TOK,
+ CONE_TOK,
+ CONFIDENCE_TOK,
+ CONIC_SWEEP_TOK,
+ CONSERVE_ENERGY_TOK,
+ CONSTANT_TOK,
+ CONTAINED_BY_TOK,
+ CONTROL0_TOK,
+ CONTROL1_TOK,
+ COS_TOK,
+ COSH_TOK,
+ COUNT_TOK,
+ CRACKLE_TOK,
+ CRAND_TOK,
+ CUBE_TOK,
+ CUBIC_TOK,
+ CUBIC_SPLINE_TOK,
+ CUBIC_WAVE_TOK,
+ CYLINDER_TOK,
+ CYLINDRICAL_TOK,
+ DEBUG_TOK,
+ DECLARE_TOK,
+ DEFAULT_TOK,
+ DEGREES_TOK,
+ DENTS_TOK,
+ DENSITY_TOK,
+ DENSITY_FILE_TOK,
+ DENSITY_MAP_TOK,
+ DF3_TOK,
+ DIFFERENCE_TOK,
+ DIFFUSE_TOK,
+ DIRECTION_TOK,
+ DISC_TOK,
+ DISPERSION_TOK,
+ DISPERSION_SAMPLES_TOK,
+ DIST_EXP_TOK,
+ DISTANCE_TOK,
+ DISTANCE_MAXIMUM_TOK,
+ DIV_TOK,
+ DOUBLE_ILLUMINATE_TOK,
+ DUST_TOK,
+ DUST_TYPE_TOK,
+ ECCENTRICITY_TOK,
+ ELSE_TOK,
+ EMISSION_TOK,
+ EMITTING_TOK,
+ END_TOK,
+ ERROR_TOK,
+ ERROR_BOUND_TOK,
+ EVALUATE_TOK,
+ EXP_TOK,
+ EXPAND_THRESHOLDS_TOK,
+ EXPONENT_TOK,
+ EXTERIOR_TOK,
+ EXTINCTION_TOK,
+ FADE_DISTANCE_TOK,
+ FADE_POWER_TOK,
+ FALLOFF_TOK,
+ FALLOFF_ANGLE_TOK,
+ FALSE_TOK,
+ FILE_EXISTS_TOK,
+ FILTER_TOK,
+ FINISH_TOK,
+ FISHEYE_TOK,
+ FLATNESS_TOK,
+ FLIP_TOK,
+ FLOOR_TOK,
+ FOCAL_POINT_TOK,
+ FOG_TOK,
+ FOG_ALT_TOK,
+ FOG_OFFSET_TOK,
+ FOG_TYPE_TOK,
+ FORM_TOK,
+ FRESNEL_TOK,
+ FREQUENCY_TOK,
+ FUNCTION_TOK,
+ GATHER_TOK,
+ GIF_TOK,
+ GLOBAL_LIGHTS_TOK,
+ GLOBAL_SETTINGS_TOK,
+ GLOWING_TOK,
+ GRADIENT_TOK,
+ GRANITE_TOK,
+ GRAY_THRESHOLD_TOK,
+ GREEN_TOK,
+ HALO_TOK,
+ HEIGHT_FIELD_TOK,
+ HEXAGON_TOK,
+ HF_GRAY_16_TOK,
+ HIERARCHY_TOK,
+ HOLLOW_TOK,
+ HYPERCOMPLEX_TOK,
+ IF_TOK,
+ IFDEF_TOK,
+ IFF_TOK,
+ IFNDEF_TOK,
+ IMAGE_MAP_TOK,
+ INCIDENCE_TOK,
+ INCLUDE_TOK,
+ INSIDE_VECTOR_TOK,
+ INT_TOK,
+ INTERIOR_TOK,
+ INTERIOR_TEXTURE_TOK,
+ INTERPOLATE_TOK,
+ INTERSECTION_TOK,
+ INTERVALS_TOK,
+ INVERSE_TOK,
+ ISOSURFACE_TOK,
+ IOR_TOK,
+ IRID_TOK,
+ IRID_WAVELENGTH_TOK,
+ JITTER_TOK,
+ JULIA_TOK,
+ JULIA_FRACTAL_TOK,
+ LAMBDA_TOK,
+ LATHE_TOK,
+ LEOPARD_TOK,
+ LIGHT_GROUP_TOK,
+ LIGHT_SOURCE_TOK,
+ LINEAR_TOK,
+ LINEAR_SPLINE_TOK,
+ LINEAR_SWEEP_TOK,
+ LOCATION_TOK,
+ LOG_TOK,
+ LOOKS_LIKE_TOK,
+ LOOK_AT_TOK,
+ LOW_ERROR_FACTOR_TOK,
+ MAGNET_TOK,
+ MAJOR_RADIUS_TOK,
+ MANDEL_TOK,
+ MAP_TYPE_TOK,
+ MARBLE_TOK,
+ MATERIAL_TOK,
+ MATERIAL_MAP_TOK,
+ MATRIX_TOK,
+ MAX_TOK,
+ MAX_GRADIENT_TOK,
+ MAX_INTERSECTIONS_TOK,
+ MAX_ITERATION_TOK,
+ MAX_SAMPLE_TOK,
+ MAX_TRACE_TOK,
+ MAX_TRACE_LEVEL_TOK,
+ MAX_VALUE_TOK,
+ MEDIA_TOK,
+ MEDIA_ATTENUATION_TOK,
+ MEDIA_INTERACTION_TOK,
+ MERGE_TOK,
+ MESH_TOK,
+ METALLIC_TOK,
+ METHOD_TOK,
+ METRIC_TOK,
+ MIN_TOK,
+ MINIMUM_REUSE_TOK,
+ MOD_TOK,
+ MORTAR_TOK,
+ NEAREST_COUNT_TOK,
+ NO_TOK,
+ NOISE_GENERATOR_TOK,
+ NORMAL_TOK,
+ NORMAL_MAP_TOK,
+ NO_IMAGE_TOK,
+ NO_REFLECTION_TOK,
+ NO_SHADOW_TOK,
+ NUMBER_OF_WAVES_TOK,
+ OBJECT_TOK,
+ OCTAVES_TOK,
+ OFF_TOK,
+ OFFSET_TOK,
+ OMEGA_TOK,
+ OMNIMAX_TOK,
+ ON_TOK,
+ ONCE_TOK,
+ ONION_TOK,
+ OPEN_TOK,
+ ORIENT_TOK,
+ ORTHOGRAPHIC_TOK,
+ PANORAMIC_TOK,
+ PARALLEL_TOK,
+ PASS_THROUGH_TOK,
+ PATTERN1_TOK,
+ PATTERN2_TOK,
+ PATTERN3_TOK,
+ PERSPECTIVE_TOK,
+ PGM_TOK,
+ PHASE_TOK,
+ PHONG_TOK,
+ PHONG_SIZE_TOK,
+ PHOTONS_TOK,
+ PI_TOK,
+ PIGMENT_TOK,
+ PIGMENT_MAP_TOK,
+ PLANAR_TOK,
+ PLANE_TOK,
+ PNG_TOK,
+ POINT_AT_TOK,
+ POLY_TOK,
+ POLY_WAVE_TOK,
+ POLYGON_TOK,
+ POT_TOK,
+ POW_TOK,
+ PPM_TOK,
+ PRECISION_TOK,
+ PRETRACE_END_TOK,
+ PRETRACE_START_TOK,
+ PRISM_TOK,
+ PROJECTED_THROUGH_TOK,
+ PWR_TOK,
+ QUADRATIC_SPLINE_TOK,
+ QUADRIC_TOK,
+ QUARTIC_TOK,
+ QUATERNION_TOK,
+ QUICK_COLOR_TOK,
+ QUICK_COLOUR_TOK,
+ QUILTED_TOK,
+ RADIAL_TOK,
+ RADIANS_TOK,
+ RADIOSITY_TOK,
+ RADIUS_TOK,
+ RAINBOW_TOK,
+ RAMP_WAVE_TOK,
+ RAND_TOK,
+ RANGE_TOK,
+ RATIO_TOK,
+ RECIPROCAL_TOK,
+ RECURSION_LIMIT_TOK,
+ RED_TOK,
+ REFLECTION_TOK,
+ REFLECTION_EXPONENT_TOK,
+ REFRACTION_TOK,
+ RENDER_TOK,
+ REPEAT_TOK,
+ RGB_TOK,
+ RGBF_TOK,
+ RGBFT_TOK,
+ RGBT_TOK,
+ RIGHT_TOK,
+ RIPPLES_TOK,
+ ROTATE_TOK,
+ ROUGHNESS_TOK,
+ SAMPLES_TOK,
+ SCALE_TOK,
+ SCALLOP_WAVE_TOK,
+ SCATTERING_TOK,
+ SEED_TOK,
+ SHADOWLESS_TOK,
+ SIN_TOK,
+ SINE_WAVE_TOK,
+ SINH_TOK,
+ SKY_TOK,
+ SKY_SPHERE_TOK,
+ SLICE_TOK,
+ SLOPE_TOK,
+ SLOPE_MAP_TOK,
+ SMOOTH_TOK,
+ SMOOTH_TRIANGLE_TOK,
+ SOR_TOK,
+ SOLID_TOK,
+ SPACING_TOK,
+ SPECULAR_TOK,
+ SPHERE_TOK,
+ SPHERE_SWEEP_TOK,
+ SPHERICAL_TOK,
+ SPIRAL_TOK,
+ SPIRAL1_TOK,
+ SPIRAL2_TOK,
+ SPOTLIGHT_TOK,
+ SPOTTED_TOK,
+ SQR_TOK,
+ SQRT_TOK,
+ STATISTICS_TOK,
+ STR_TOK,
+ STRCMP_TOK,
+ STRENGTH_TOK,
+ STRLEN_TOK,
+ STRLWR_TOK,
+ STRUPR_TOK,
+ STURM_TOK,
+ SUBSTR_TOK,
+ SUPERELLIPSOID_TOK,
+ SWITCH_TOK,
+ SYS_TOK,
+ T_TOK,
+ TAN_TOK,
+ TANH_TOK,
+ TARGET_TOK,
+ TEST_CAMERA_1_TOK,
+ TEST_CAMERA_2_TOK,
+ TEST_CAMERA_3_TOK,
+ TEST_CAMERA_4_TOK,
+ TEXT_TOK,
+ TEXTURE_TOK,
+ TEXTURE_MAP_TOK,
+ TGA_TOK,
+ THICKNESS_TOK,
+ THRESHOLD_TOK,
+ TIGHTNESS_TOK,
+ TILE2_TOK,
+ TILES_TOK,
+ TOLERANCE_TOK,
+ TOROIDAL_TOK,
+ TORUS_TOK,
+ TRACK_TOK,
+ TRANSFORM_TOK,
+ TRANSLATE_TOK,
+ TRANSMIT_TOK,
+ TRIANGLE_TOK,
+ TRIANGLE_WAVE_TOK,
+ TRUE_TOK,
+ TTF_TOK,
+ TURBULENCE_TOK,
+ TURB_DEPTH_TOK,
+ TYPE_TOK,
+ U_TOK,
+ ULTRA_WIDE_ANGLE_TOK,
+ UNION_TOK,
+ UP_TOK,
+ USE_COLOR_TOK,
+ USE_COLOUR_TOK,
+ USE_INDEX_TOK,
+ U_STEPS_TOK,
+ UV_MAPPING_TOK,
+ UV_VECTORS_TOK,
+ V_TOK,
+ VAL_TOK,
+ VARIANCE_TOK,
+ VAXIS_ROTATE_TOK,
+ VCROSS_TOK,
+ VDOT_TOK,
+ VERSION_TOK,
+ VLENGTH_TOK,
+ VNORMALIZE_TOK,
+ VOLUME_OBJECT_TOK,
+ VOLUME_RENDERED_TOK,
+ VOL_WITH_LIGHT_TOK,
+ VROTATE_TOK,
+ V_STEPS_TOK,
+ WARNING_TOK,
+ WARP_TOK,
+ WATER_LEVEL_TOK,
+ WAVES_TOK,
+ WHILE_TOK,
+ WIDTH_TOK,
+ WOOD_TOK,
+ WRINKLES_TOK,
+ X_TOK,
+ Y_TOK,
+ YES_TOK,
+ Z_TOK,
+ // extra tokens
+ ID_TOK,
+ INTEGER_TOK,
+ FLOAT_TOK,
+ COMMENT_TOK,
+ LINE_COMMENT_TOK,
+ STRING_TOK,
+ PMNAME_TOK,
+ RAW_POVRAY_TOK
+};
+
+#endif
diff --git a/kpovmodeler/pmtorus.cpp b/kpovmodeler/pmtorus.cpp
new file mode 100644
index 00000000..c6f4238a
--- /dev/null
+++ b/kpovmodeler/pmtorus.cpp
@@ -0,0 +1,379 @@
+/***************************************************************************
+ pmtorus.cpp - description
+ -------------------
+ copyright : (C) 2001 Philippe Van Hecke
+ email : lephiloux@tiscalinet.be
+ copyright : (C) 2002 Andreas Zehender
+ email : zehender@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "pmtorus.h"
+
+#include "pmxmlhelper.h"
+#include "pmtorusedit.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm3dcontrolpoint.h"
+#include "pmdistancecontrolpoint.h"
+#include "pmdefaults.h"
+
+#include <klocale.h>
+
+/** default param for the Torus */
+const double c_defaultminorRadius = 0.25;
+const double c_defaultmajorRadius = 0.5;
+const bool c_defaultsturm = false;
+
+/** default Torus structure */
+PMViewStructure* PMTorus::s_pDefaultViewStructure = 0;
+
+int PMTorus::s_vStep = c_defaultTorusVSteps;
+int PMTorus::s_uStep = c_defaultTorusUSteps;
+int PMTorus::s_parameterKey = 0;
+
+PMDefinePropertyClass( PMTorus, PMTorusProperty );
+
+PMMetaObject* PMTorus::s_pMetaObject = 0;
+PMObject* createNewTorus( PMPart* part )
+{
+ return new PMTorus( part );
+}
+
+PMTorus::PMTorus( PMPart* part )
+ : Base( part )
+{
+ m_minorRadius = c_defaultminorRadius;
+ m_majorRadius = c_defaultmajorRadius;
+ m_sturm = c_defaultsturm ;
+}
+
+PMTorus::PMTorus( const PMTorus& t )
+ : Base( t )
+{
+ m_minorRadius = t.m_minorRadius;
+ m_majorRadius = t.m_majorRadius;
+ m_sturm = t.m_sturm;
+}
+
+PMTorus::~PMTorus( )
+{
+}
+
+
+QString PMTorus::description( ) const
+{
+ return i18n( "torus" );
+}
+
+PMMetaObject* PMTorus::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Torus", Base::metaObject( ),
+ createNewTorus );
+ s_pMetaObject->addProperty(
+ new PMTorusProperty( "minorRadius", &PMTorus::setMinorRadius,
+ &PMTorus::minorRadius ) );
+ s_pMetaObject->addProperty(
+ new PMTorusProperty( "majorRadius", &PMTorus::setMajorRadius,
+ &PMTorus::majorRadius ) );
+ s_pMetaObject->addProperty(
+ new PMTorusProperty( "sturm", &PMTorus::setSturm, &PMTorus::sturm ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMTorus::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "minor_radius", m_minorRadius );
+ e.setAttribute( "major_radius", m_majorRadius );
+ e.setAttribute( "sturm", m_sturm );
+
+ Base::serialize( e, doc );
+}
+
+void PMTorus::readAttributes( const PMXMLHelper& h )
+{
+ m_minorRadius = h.doubleAttribute( "minor_radius", c_defaultminorRadius );
+ m_majorRadius = h.doubleAttribute( "major_radius", c_defaultmajorRadius );
+ m_sturm = h.boolAttribute( "sturm", c_defaultsturm );
+
+ Base::readAttributes( h );
+}
+
+PMDialogEditBase* PMTorus::editWidget( QWidget* parent ) const
+{
+
+ return new PMTorusEdit( parent );
+}
+
+void PMTorus::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMMinorRadiusID:
+ setMinorRadius( data->doubleData( ) );
+ break;
+ case PMMajorRadiusID:
+ setMajorRadius( data->doubleData( ) );
+ break;
+ case PMSturmID:
+ setSturm( data->boolData( ) );
+ default:
+ kdError( PMArea ) << "Wrong ID in PMTorus::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+
+}
+
+void PMTorus::controlPoints( PMControlPointList& list )
+{
+ PMVector majorCenter( 0, 0, 0 );
+ /** control points of the major radius */
+ list.append( new PMDistanceControlPoint( majorCenter, PMVector( 1.0, 0.0, 0.0 ),
+ m_majorRadius, PMMajorRadiusID,
+ i18n( "Major radius (x)" ) ) );
+ PMDistanceControlPoint* rcp =
+ new PMDistanceControlPoint( majorCenter, PMVector( 0.0, 0.0, 1.0 ),
+ m_majorRadius, PMMajorRadiusID,
+ i18n( "Major radius (z)" ) );
+ list.append( rcp );
+
+ PMVector minorCenter( 0.0, 0.0, m_majorRadius );
+ list.append( new PMDistanceControlPoint( rcp, PMVector( 0.0, 1.0, 0.0 ),
+ m_minorRadius, PMMinorRadiusID,
+ i18n( "Minor radius (y)" ) ) );
+ list.append( new PMDistanceControlPoint( rcp, PMVector( 0.0, 0.0, 1.0 ),
+ m_minorRadius, PMMinorRadiusID,
+ i18n( "Minor radius (z)" ) ) );
+}
+
+void PMTorus::controlPointsChanged( PMControlPointList& list )
+{
+ bool majorChanged = false, minorChanged = false;
+ PMControlPoint* p;
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMMinorRadiusID:
+ setMinorRadius( ( ( PMDistanceControlPoint* ) p )->distance( ) );
+ ( ( PMDistanceControlPoint* ) p )->setDistance( m_minorRadius );
+ minorChanged = true;
+ break;
+ case PMMajorRadiusID:
+ setMajorRadius( ( ( PMDistanceControlPoint* ) p )->distance( ) );
+ ( ( PMDistanceControlPoint* ) p )->setDistance( m_majorRadius );
+ majorChanged = true;
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMTorus::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+
+ if( majorChanged )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMMajorRadiusID )
+ ( ( PMDistanceControlPoint* ) p )->setDistance( m_majorRadius );
+ if( minorChanged )
+ for( p = list.first( ); p; p = list.next( ) )
+ if( p->id( ) == PMMinorRadiusID )
+ ( ( PMDistanceControlPoint* ) p )->setDistance( m_minorRadius );
+}
+
+bool PMTorus::isDefault( )
+{
+ if( ( m_minorRadius == c_defaultminorRadius )
+ && ( m_majorRadius == c_defaultmajorRadius )
+ && globalDetail( ) )
+ return true;
+ return false;
+}
+
+void PMTorus::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( displayDetail( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( displayDetail( ) + 1 ) );
+ unsigned ptsSize = vStep * uStep;
+ unsigned lineSize = vStep * uStep * 2;
+
+ if( ptsSize != m_pViewStructure->points( ).size( ) )
+ m_pViewStructure->points( ).resize( ptsSize );
+
+ createPoints( m_pViewStructure->points( ), m_minorRadius, m_majorRadius, uStep, vStep );
+
+ if( lineSize != m_pViewStructure->lines( ).size( ) )
+ {
+ m_pViewStructure->lines( ).detach( );
+ m_pViewStructure->lines( ).resize( lineSize );
+ createLines( m_pViewStructure->lines( ), uStep, vStep );
+ }
+}
+
+PMViewStructure* PMTorus::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure || s_pDefaultViewStructure->parameterKey( ) != viewStructureParameterKey( ) )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ int uStep = (int)( ( (float)s_uStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
+ int vStep = (int)( ( (float)s_vStep / 2 ) * ( globalDetailLevel( ) + 1 ) );
+
+ s_pDefaultViewStructure =
+ new PMViewStructure( vStep * uStep ,
+ vStep * uStep * 2 );
+
+ createPoints( s_pDefaultViewStructure->points( ), c_defaultminorRadius,
+ c_defaultmajorRadius, uStep, vStep );
+
+ createLines( s_pDefaultViewStructure->lines( ), uStep, vStep );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMTorus::createLines( PMLineArray& lines, int uStep, int vStep )
+{
+ int u, v;
+ for( u = 0; u < uStep; ++u )
+ {
+ for( v = 0; v < vStep; ++v )
+ {
+ lines[ u * vStep + v ] = PMLine( u * vStep + v, u * vStep + ( (v+1) % vStep ) );
+ lines[ uStep * vStep + u * vStep + v ] = PMLine( u * vStep + v, ( (u+1) % uStep ) * vStep + v );
+ }
+ }
+}
+
+void PMTorus::createPoints( PMPointArray& points, double minor_radius,
+ double major_radius, int uStep, int vStep )
+{
+ double l_UradStep = ( 2.0 * M_PI ) / uStep;
+ double l_VradStep = ( 2.0 * M_PI ) / vStep;
+ double l_u = l_UradStep;
+ int u, v;
+
+ for( u = 0; u < uStep; ++u )
+ {
+ double l_v = 0.0;
+ double y = minor_radius * sin ( l_u );
+ double l_rcosu = major_radius + minor_radius * cos( l_u );
+
+ for( v = 0; v < vStep; ++v )
+ {
+ double x = l_rcosu * cos( l_v );
+ double z = l_rcosu * sin( l_v );
+ points[u * vStep + v ] = PMPoint( x, y, z );
+ l_v = l_v + l_VradStep;
+ }
+ l_u = l_u + l_UradStep;
+ }
+}
+
+void PMTorus::setMinorRadius( double minor_radius )
+{
+ if( m_minorRadius != minor_radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMinorRadiusID, m_minorRadius );
+ m_minorRadius = minor_radius;
+ setViewStructureChanged( );
+ }
+}
+
+void PMTorus::setMajorRadius( double major_radius )
+{
+ if( m_majorRadius != major_radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMajorRadiusID, m_majorRadius );
+ m_majorRadius = major_radius;
+ setViewStructureChanged( );
+ }
+}
+
+void PMTorus::setSturm( bool sturm )
+{
+ if( m_sturm != sturm )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMSturmID, m_sturm );
+ m_sturm = sturm;
+ setViewStructureChanged( );
+ }
+
+}
+
+void PMTorus::setUSteps( int u )
+{
+ if( u >= 2 )
+ {
+ s_uStep = u;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMTorus::setUSteps: U must be greater than 1\n";
+ s_parameterKey++;
+}
+
+void PMTorus::setVSteps( int v )
+{
+ if( v >= 4 )
+ {
+ s_vStep = v;
+ if( s_pDefaultViewStructure )
+ {
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ }
+ }
+ else
+ kdDebug( PMArea ) << "PMTorus::setVSteps: V must be greater than 3\n";
+ s_parameterKey++;
+}
+
+void PMTorus::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmtorus.h b/kpovmodeler/pmtorus.h
new file mode 100644
index 00000000..9f3f8225
--- /dev/null
+++ b/kpovmodeler/pmtorus.h
@@ -0,0 +1,172 @@
+/*
+ ***************************************************************************
+ pmtorus.h - description
+ -------------------
+ begin : Fri Jun 22 2001
+ copyright : (C) 2001 Philippe Van Hecke
+ email : lephiloux@tiscalinet.be
+ copyright : (C) 2002 Andreas Zehender
+ email : zehender@kde.org
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PMTORUS_H
+#define PMTORUS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobject.h"
+#include "pmvector.h"
+#include "pmviewstructure.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray torus.
+ */
+class PMTorus : public PMSolidObject
+{
+ typedef PMSolidObject Base;
+
+public:
+ /**
+ * Create an empty Sphere
+ */
+ PMTorus( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMTorus( const PMTorus& t );
+ /**
+ * Delete the PMTorus
+ */
+ virtual ~PMTorus( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMTorus( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMTrousEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmtorus" ); }
+ /**
+ * set minor radius see povray documentation about torus
+ */
+ void setMinorRadius( double minor_radius );
+ /**
+ * set major radius see povray documentation about torus
+ */
+ void setMajorRadius( double major_radius );
+ /**
+ * use sturm algorithme
+ */
+ void setSturm( bool sturm );
+ /**
+ * return minor radius see povray documentation about torus
+ */
+ double minorRadius( ) const { return m_minorRadius; }
+ /**
+ * return major radius see povray documentation about torus
+ */
+ double majorRadius( ) const { return m_majorRadius; }
+ /**
+ * return if we must use sturm algorithm for the torus
+ */
+ bool sturm( ) const { return m_sturm; }
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual bool hasDisplayDetail( ) const { return true; }
+ /** */
+ virtual void cleanUp( ) const;
+
+ /**
+ * Sets the number of circles
+ */
+ static void setUSteps( int u );
+ /**
+ * Sets the number of point for each circle
+ */
+ static void setVSteps( int v );
+ /**
+ * Returns the number circles
+ */
+ static int uSteps( ) { return s_uStep; }
+ /**
+ * Returns the number of point for each circle
+ */
+ static int vSteps( ) { return s_vStep; }
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+ /** */
+ virtual int viewStructureParameterKey( ) const { return s_parameterKey + globalDetailKey(); }
+
+private:
+ static void createLines( PMLineArray& lines, int uStep, int vStep );
+ static void createPoints( PMPointArray& points, double minor_radius,
+ double major_radius, int uStep, int vStep );
+ enum PMTorusMementoID { PMMinorRadiusID, PMMajorRadiusID, PMSturmID };
+ /**
+ * Minor radius
+ */
+ double m_minorRadius;
+ /**
+ * Major radius
+ */
+ double m_majorRadius;
+ /**
+ * use sturm algorithm
+ */
+ bool m_sturm;
+ /**
+ * default view structure
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+ static int s_vStep;
+ static int s_uStep;
+ static int s_parameterKey;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
+/*
+x = (major + minor cos(u)) cos(v)
+y = (major + minor cos(u)) sin(v)
+z = minor sin (u) */
+
+
diff --git a/kpovmodeler/pmtorusedit.cpp b/kpovmodeler/pmtorusedit.cpp
new file mode 100644
index 00000000..01784e1d
--- /dev/null
+++ b/kpovmodeler/pmtorusedit.cpp
@@ -0,0 +1,105 @@
+/***************************************************************************
+ pmtorusedit.cpp - description
+ -------------------
+ begin : Sun Jul 1 2001
+ copyright : (C) 2001 by Van Hecke Philippe
+ email : lephiloux@tiscalinet.be
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "pmtorusedit.h"
+#include "pmtorus.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <qcheckbox.h>
+
+
+PMTorusEdit::PMTorusEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMTorusEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ QGridLayout* gl;
+ QHBoxLayout* hl;
+
+ m_pMinorRadius = new PMFloatEdit( this );
+ m_pMajorRadius = new PMFloatEdit( this );
+ m_pSturm = new QCheckBox( i18n( "Sturm" ), this );
+
+ hl = new QHBoxLayout( topLayout( ) );
+ gl = new QGridLayout( hl, 2, 2 );
+ gl->addWidget( new QLabel( i18n( "Minor radius:" ), this ), 0, 0 );
+ gl->addWidget( m_pMinorRadius, 0, 1 );
+ gl->addWidget( new QLabel( i18n( "Major radius:" ), this ), 1, 0 );
+ gl->addWidget( m_pMajorRadius, 1, 1 );
+ hl->addStretch( 1 );
+
+ topLayout( )->addWidget( m_pSturm );
+
+
+ connect( m_pMinorRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMajorRadius, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pSturm, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMTorusEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Torus" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMTorus* ) o;
+
+ m_pMajorRadius->setValue( m_pDisplayedObject->majorRadius( ) );
+ m_pMinorRadius->setValue( m_pDisplayedObject->minorRadius( ) );
+ m_pSturm->setChecked( m_pDisplayedObject->sturm( ) );
+
+ m_pMajorRadius->setReadOnly( readOnly );
+ m_pMinorRadius->setReadOnly( readOnly );
+ m_pSturm->setEnabled( !readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMTorusEdit: Can't display object\n";
+}
+
+void PMTorusEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+
+ m_pDisplayedObject->setMajorRadius( m_pMajorRadius->value( ) );
+ m_pDisplayedObject->setMinorRadius( m_pMinorRadius->value( ) );
+ m_pDisplayedObject->setSturm( m_pSturm->isChecked( ) );
+ }
+}
+
+bool PMTorusEdit::isDataValid( )
+{
+ if( m_pMinorRadius->isDataValid( ) )
+ if( m_pMajorRadius->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+
+
+#include "pmtorusedit.moc"
+
diff --git a/kpovmodeler/pmtorusedit.h b/kpovmodeler/pmtorusedit.h
new file mode 100644
index 00000000..2aea334b
--- /dev/null
+++ b/kpovmodeler/pmtorusedit.h
@@ -0,0 +1,65 @@
+/*
+ **************************************************************************
+ pmtorusedit.h - description
+ -------------------
+ begin : Sat Jun 30 2001
+ copyright : (C) 2001 Philippe Van Hecke
+ email : lephiloux@tiscalinet.be
+ ***************************************************************************
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef PMTORUSEDIT_H
+#define PMTORUSEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsolidobjectedit.h"
+
+class PMTorus;
+class PMFloatEdit ;
+class QCheckBox;
+
+/**
+ * Dialog edit class for @ref PMTorus
+ */
+class PMTorusEdit : public PMSolidObjectEdit
+{
+ Q_OBJECT
+ typedef PMSolidObjectEdit Base;
+public:
+ /**
+ * Creates a PMSphereEdit with parent and name
+ */
+ PMTorusEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMTorus* m_pDisplayedObject;
+ PMFloatEdit* m_pMinorRadius;
+ PMFloatEdit* m_pMajorRadius;
+ QCheckBox * m_pSturm;
+
+};
+
+
+#endif
diff --git a/kpovmodeler/pmtranslate.cpp b/kpovmodeler/pmtranslate.cpp
new file mode 100644
index 00000000..0cfab44f
--- /dev/null
+++ b/kpovmodeler/pmtranslate.cpp
@@ -0,0 +1,162 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtranslate.h"
+#include "pmtranslateedit.h"
+
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmtranslatecontrolpoint.h"
+
+#include <klocale.h>
+
+const PMVector moveDefault = PMVector( 0.0, 0.0, 0.0 );
+
+PMDefinePropertyClass( PMTranslate, PMTranslateProperty );
+
+PMMetaObject* PMTranslate::s_pMetaObject = 0;
+PMObject* createNewTranslate( PMPart* part )
+{
+ return new PMTranslate( part );
+}
+
+PMTranslate::PMTranslate( PMPart* part )
+ : Base( part )
+{
+}
+
+PMTranslate::PMTranslate( const PMTranslate& t )
+ : Base( t )
+{
+ m_move = t.m_move;
+}
+
+PMTranslate::~PMTranslate( )
+{
+}
+
+QString PMTranslate::description( ) const
+{
+ return i18n( "translate" );
+}
+
+void PMTranslate::serialize( QDomElement& e, QDomDocument& /*doc*/ ) const
+{
+ e.setAttribute( "value", m_move.serializeXML( ) );
+}
+
+void PMTranslate::readAttributes( const PMXMLHelper& h )
+{
+ m_move = h.vectorAttribute( "value", moveDefault );
+}
+
+PMMetaObject* PMTranslate::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Translate", Base::metaObject( ),
+ createNewTranslate );
+ s_pMetaObject->addProperty(
+ new PMTranslateProperty( "translation", &PMTranslate::setTranslation, &PMTranslate::translation ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMTranslate::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMTranslate::setTranslation( const PMVector& p )
+{
+ if( p != m_move )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMTranslationID, m_move );
+ m_pMemento->setViewStructureChanged( );
+ }
+ m_move = p;
+ m_move.resize( 3 );
+ }
+}
+
+PMDialogEditBase* PMTranslate::editWidget( QWidget* parent ) const
+{
+ return new PMTranslateEdit( parent );
+}
+
+void PMTranslate::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMTranslationID:
+ setTranslation( data->vectorData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMTranslate::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+PMMatrix PMTranslate::transformationMatrix( ) const
+{
+ return PMMatrix::translation( m_move[0], m_move[1], m_move[2] );
+}
+
+void PMTranslate::controlPoints( PMControlPointList& list )
+{
+ list.append( new PMTranslateControlPoint( m_move, PMTranslationID ) );
+}
+
+void PMTranslate::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMTranslationID:
+ setTranslation( ( ( PMTranslateControlPoint* ) p )->translation( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMTranslate::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+}
diff --git a/kpovmodeler/pmtranslate.h b/kpovmodeler/pmtranslate.h
new file mode 100644
index 00000000..91f1c7c3
--- /dev/null
+++ b/kpovmodeler/pmtranslate.h
@@ -0,0 +1,102 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTRANSLATE_H
+#define PMTRANSLATE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+#include "pmvector.h"
+
+/**
+ * Class for povray move commands.
+ */
+
+class PMTranslate : public PMObject
+{
+ typedef PMObject Base;
+public:
+ /**
+ * Creates a move < 0, 0, 0 >
+ */
+ PMTranslate( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMTranslate( const PMTranslate& t );
+ /**
+ * deletes the object
+ */
+ virtual ~PMTranslate( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMTranslate( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMTranslateEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /** */
+ virtual QString pixmap( ) const { return QString( "pmtranslate" ); }
+
+ /**
+ * Returns the movement
+ */
+ PMVector translation( ) const { return m_move; }
+ /**
+ * Sets the movement
+ */
+ void setTranslation( const PMVector& p );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual bool hasTransformationMatrix( ) const { return true; }
+ /** */
+ virtual PMMatrix transformationMatrix( ) const;
+
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMTranslateMementoID { PMTranslationID };
+ PMVector m_move;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmtranslatecontrolpoint.cpp b/kpovmodeler/pmtranslatecontrolpoint.cpp
new file mode 100644
index 00000000..857e3af9
--- /dev/null
+++ b/kpovmodeler/pmtranslatecontrolpoint.cpp
@@ -0,0 +1,50 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmtranslatecontrolpoint.h"
+#include "pmmath.h"
+
+#include <klocale.h>
+#include <math.h>
+
+PMTranslateControlPoint::PMTranslateControlPoint( const PMVector& trans, int id )
+ : PMControlPoint( id, i18n( "Translation" ) )
+{
+ m_translation = trans;
+}
+
+void PMTranslateControlPoint::graphicalChangeStarted( )
+{
+ m_originalTranslation = m_translation;
+}
+
+void PMTranslateControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& /*viewNormal*/,
+ const PMVector& endPoint )
+{
+ m_translation = m_originalTranslation + endPoint - startPoint;
+}
+
+void PMTranslateControlPoint::snapToGrid( )
+{
+ int i;
+ double d = moveGrid( );
+ if( !approxZero( d ) )
+ for( i = 0; i < 3; i++ )
+ m_translation[i] = rint( m_translation[i] / d ) * d;
+ setChanged( );
+}
diff --git a/kpovmodeler/pmtranslatecontrolpoint.h b/kpovmodeler/pmtranslatecontrolpoint.h
new file mode 100644
index 00000000..292e8a67
--- /dev/null
+++ b/kpovmodeler/pmtranslatecontrolpoint.h
@@ -0,0 +1,71 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMTRANSLATECONTROLPOINT_H
+#define PMTRANSLATECONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "pmcontrolpoint.h"
+
+/**
+ * Control points for translation
+ */
+class PMTranslateControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Creates a PMTranslateControlPoint with id.
+ */
+ PMTranslateControlPoint( const PMVector& translation, int id );
+ /**
+ * Deletes the PMTranslateControlPoint
+ */
+ virtual ~PMTranslateControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const { return m_translation; }
+
+ /**
+ * Sets the translation
+ */
+ void setTranslation( PMVector trans ) { m_translation = trans; }
+ /**
+ * Returns the translation
+ */
+ PMVector translation( ) const { return m_translation; }
+
+ /** */
+ virtual PMCPDisplayType displayType( ) const { return CPCross; };
+ /** */
+ virtual void snapToGrid( );
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ PMVector m_translation, m_originalTranslation;
+};
+
+#endif
diff --git a/kpovmodeler/pmtranslateedit.cpp b/kpovmodeler/pmtranslateedit.cpp
new file mode 100644
index 00000000..d2690f51
--- /dev/null
+++ b/kpovmodeler/pmtranslateedit.cpp
@@ -0,0 +1,74 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtranslateedit.h"
+#include "pmtranslate.h"
+#include "pmvectoredit.h"
+
+#include <qlayout.h>
+#include <klocale.h>
+
+
+PMTranslateEdit::PMTranslateEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMTranslateEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ m_pVector = new PMVectorEdit( "x", "y", "z", this );
+ topLayout( )->addWidget( m_pVector );
+
+ connect( m_pVector, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMTranslateEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Translate" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMTranslate* ) o;
+
+ m_pVector->setVector( m_pDisplayedObject->translation( ) );
+ m_pVector->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMTranslateEdit: Can't display object\n";
+}
+
+void PMTranslateEdit::saveContents( )
+{
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ m_pDisplayedObject->setTranslation( m_pVector->vector( ) );
+ }
+}
+
+bool PMTranslateEdit::isDataValid( )
+{
+ if( m_pVector->isDataValid( ) )
+ return Base::isDataValid( );
+ return false;
+}
+#include "pmtranslateedit.moc"
diff --git a/kpovmodeler/pmtranslateedit.h b/kpovmodeler/pmtranslateedit.h
new file mode 100644
index 00000000..ce27b037
--- /dev/null
+++ b/kpovmodeler/pmtranslateedit.h
@@ -0,0 +1,62 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMMOVEEDIT_H
+#define PMMOVEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMTranslate;
+class PMVectorEdit;
+
+/**
+ * Dialog edit class for @ref PMTranslate
+ */
+class PMTranslateEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMTranslateEdit with parent and name
+ */
+ PMTranslateEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private:
+ PMTranslate* m_pDisplayedObject;
+ PMVectorEdit* m_pVector;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmtreeview.cpp b/kpovmodeler/pmtreeview.cpp
new file mode 100644
index 00000000..66ec18a0
--- /dev/null
+++ b/kpovmodeler/pmtreeview.cpp
@@ -0,0 +1,820 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include <stdlib.h>
+
+#include <qlistview.h>
+#include <qheader.h>
+#include <qlayout.h>
+#include <qpopupmenu.h>
+#include <qcursor.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <kxmlguifactory.h>
+
+#include "pmtreeview.h"
+#include "pmtreeviewitem.h"
+#include "pmcommand.h"
+#include "pmpart.h"
+#include "pmscene.h"
+#include "pmobjectdrag.h"
+
+
+PMTreeViewWidget::PMTreeViewWidget( PMPart* part, QWidget* parent /*= 0*/,
+ const char* name /*=0*/ )
+ : PMViewBase( parent, name )
+{
+ QHBoxLayout* hl = new QHBoxLayout( this );
+ PMTreeView* tv = new PMTreeView( part, this );
+ hl->addWidget( tv );
+}
+
+QString PMTreeViewWidget::description( ) const
+{
+ return i18n( "Object Tree" );
+}
+
+PMTreeView::PMTreeView( PMPart* part, QWidget* parent /*= 0*/,
+ const char* name /*= 0*/ )
+ : QListView( parent, name )
+{
+ addColumn( i18n( "Objects" ) );
+ header( )->hide( );
+ setRootIsDecorated( true );
+ setSorting( -1 );
+ setSelectionMode( Multi );
+ m_pPart = part;
+
+ m_itemSelected = false;
+ m_itemDeselected = false;
+ m_selectionCleared = false;
+ m_pLastSelected = 0;
+ m_event = false;
+ m_pressed = false;
+ m_pDragOverItem = 0;
+ m_acceptSelect = false;
+ m_pressedItem = 0;
+
+ viewport( )->setAcceptDrops( true );
+ viewport( )->setMouseTracking( true );
+ viewport( )->setFocusPolicy( QWidget::WheelFocus );
+ setFocusPolicy( QWidget::WheelFocus );
+ setAcceptDrops( true );
+
+ connect( part, SIGNAL( refresh( ) ), SLOT( slotRefresh( ) ) );
+ connect( part, SIGNAL( objectChanged( PMObject*, const int, QObject* ) ),
+ SLOT( slotObjectChanged( PMObject*, const int, QObject* ) ) );
+ connect( part, SIGNAL( clear( ) ), SLOT( slotClear( ) ) );
+ connect( this, SIGNAL( objectChanged( PMObject*, const int, QObject* ) ),
+ part, SLOT( slotObjectChanged( PMObject*, const int, QObject* ) ) );
+
+ slotRefresh( );
+}
+
+PMTreeView::~PMTreeView( )
+{
+ emit destroyed( this );
+}
+
+void PMTreeView::slotObjectChanged( PMObject* obj, const int mode,
+ QObject* sender )
+{
+ PMTreeViewItem* pTreeItem = 0;
+ bool as = m_acceptSelect;
+ m_acceptSelect = true;
+
+ if( sender != this )
+ {
+ if( ( mode & PMCAdd ) && !( mode & PMCInsertError ) )
+ {
+ // object was added
+ if( !obj->parent( ) )
+ {
+ // object has no parent, append it as top level item
+ pTreeItem = new PMTreeViewItem( obj, this );
+ }
+ else
+ {
+ // find the parent in the listview
+ QListViewItem* pParentTreeItem = findObject( obj->parent( ) );
+ if( pParentTreeItem )
+ {
+ PMObject* hObj = obj->prevSibling( );
+ QListViewItem* pSibling = 0;
+ bool found = false;
+
+ if( hObj )
+ {
+ // find the previous sibling
+ pSibling = pParentTreeItem->firstChild( );
+ while( pSibling && !found )
+ {
+ if( ( ( PMTreeViewItem* ) pSibling )->object( ) == hObj )
+ found = true;
+ else
+ pSibling = pSibling->nextSibling( );
+ }
+ }
+ if( found )
+ {
+ // object has sibling
+ pTreeItem = new PMTreeViewItem( obj, pParentTreeItem, pSibling );
+ }
+ else
+ {
+ // object has no sibling
+ pTreeItem = new PMTreeViewItem( obj, pParentTreeItem );
+ }
+ }
+ }
+
+ if( pTreeItem )
+ {
+ // add child items if necessary
+ if( obj->countChildren( ) > 0 )
+ addChildItems( pTreeItem );
+ }
+ }
+ if( mode & PMCDescription )
+ {
+ if( !pTreeItem )
+ pTreeItem = findObject( obj );
+
+ if( pTreeItem )
+ pTreeItem->setDescriptions( );
+ }
+ if( mode & PMCChildren )
+ {
+ if( !pTreeItem )
+ pTreeItem = findObject( obj );
+
+ if( pTreeItem )
+ {
+ // delete old items
+ while( pTreeItem->firstChild( ) )
+ delete pTreeItem->firstChild( );
+ // create new
+ addChildItems( pTreeItem );
+ pTreeItem->setOpen( true );
+ }
+ }
+ if( mode & PMCNewSelection )
+ {
+ clearSelection( );
+
+ if( !pTreeItem )
+ pTreeItem = findObject( obj );
+
+ if( pTreeItem )
+ {
+ PMTreeViewItem* p;
+ for( p = pTreeItem->parent( ); p; p = p->parent( ) )
+ p->setOpen( true );
+ pTreeItem->setSelected( true );
+ setCurrentItem( pTreeItem );
+ }
+ }
+ if( mode & PMCDeselected )
+ {
+ if( !pTreeItem )
+ pTreeItem = findObject( obj );
+ pTreeItem->setSelected( false );
+ }
+ if( mode & PMCSelected )
+ {
+ if( !pTreeItem )
+ pTreeItem = findObject( obj );
+ pTreeItem->setSelected( true );
+ }
+ if( mode & PMCRemove )
+ {
+ // object was removed, remove the listview item
+ if( !pTreeItem )
+ pTreeItem = findObject( obj );
+ delete( pTreeItem );
+ }
+ if( mode & PMCData )
+ {
+ // special case for texture maps
+ if( obj )
+ {
+ if( obj->isA( "TextureMapBase" ) )
+ {
+ if( !pTreeItem )
+ pTreeItem = findObject( obj );
+ if( pTreeItem )
+ {
+ PMTreeViewItem* it = ( PMTreeViewItem* ) pTreeItem->firstChild( );
+ for( ; it; it = ( PMTreeViewItem* ) it->nextSibling( ) )
+ it->setDescriptions( );
+ }
+ }
+ }
+ }
+ }
+ m_acceptSelect = as;
+}
+
+
+PMTreeViewItem* PMTreeView::findObject( const PMObject* obj )
+{
+ PMTreeViewItem* pTreeItem = 0;
+
+ if( !obj->parent( ) )
+ {
+ // top level object
+ pTreeItem = ( PMTreeViewItem* ) firstChild( );
+ for( ; pTreeItem; pTreeItem = ( PMTreeViewItem* ) pTreeItem->nextSibling( ) )
+ if( pTreeItem->object( ) == obj )
+ return pTreeItem;
+ }
+ else
+ {
+ pTreeItem = findObject( obj->parent( ) );
+ if( pTreeItem )
+ {
+ pTreeItem = ( PMTreeViewItem* ) pTreeItem->firstChild( );
+ for( ; pTreeItem; pTreeItem = ( PMTreeViewItem* ) pTreeItem->nextSibling( ) )
+ if( pTreeItem->object( ) == obj )
+ return pTreeItem;
+ }
+ }
+ return 0;
+}
+
+
+void PMTreeView::selectItem( QListViewItem* /*sitem*/ )
+{
+/* QListViewItem* pItem = 0;
+ bool emitSig;
+ emitSig = ( m_pSelectedObject != ( ( PMTreeViewItem* ) sitem )->object( ) );
+
+ m_pSelectedObject = ( ( PMTreeViewItem* ) sitem )->object( );
+
+ for( pItem = sitem->parent( ); pItem; pItem = pItem->parent( ) )
+ pItem->setOpen( true );
+ ensureItemVisible( sitem );
+ setCurrentItem( sitem );
+ setSelected( sitem, true );
+ if( emitSig )
+ emit objectSelected( m_pSelectedObject );
+*/
+}
+
+void PMTreeView::addChildItems( PMTreeViewItem* item )
+{
+ PMObject* obj = 0;
+ PMTreeViewItem* listItem = 0;
+
+ for( obj = item->object( )->firstChild( ); obj; obj = obj->nextSibling( ) )
+ {
+ // insert all child objects
+ if( listItem )
+ listItem = new PMTreeViewItem( obj, item, listItem );
+ else
+ // first child
+ listItem = new PMTreeViewItem( obj, item );
+ // recursive call, if child has children
+ if( obj->countChildren( ) > 0 )
+ addChildItems( listItem );
+ }
+}
+
+void PMTreeView::slotRefresh( )
+{
+ PMTreeViewItem* item;
+ slotClear( );
+ // insert the top level items
+ if( m_pPart->scene( ) )
+ {
+ item = new PMTreeViewItem( m_pPart->scene( ), this );
+ addChildItems( item );
+ item->setOpen( true );
+// item = new PMTreeViewItem( m_pPart->insertErrors( ), this );
+// addChildItems( item );
+// item->setOpen( true );
+ }
+}
+
+void PMTreeView::slotClear( )
+{
+ clear( );
+ m_pLastSelected = 0;
+ m_pDragOverItem = 0;
+ m_pressedItem = 0;
+}
+
+void PMTreeView::itemSelected( PMTreeViewItem* item, bool selected )
+{
+ repaintItem( item );
+
+ if( m_event )
+ {
+ m_pLastSelected = item;
+
+ if( selected )
+ m_itemSelected = true;
+ else
+ {
+ if( m_itemDeselected )
+ m_selectionCleared = true;
+ else
+ m_itemDeselected = true;
+ }
+ }
+}
+
+void PMTreeView::contentsMousePressEvent( QMouseEvent * e )
+{
+ m_itemSelected = false;
+ m_itemDeselected = false;
+ m_pLastSelected = 0;
+ m_selectionCleared = false;
+ m_selectOnReleaseEvent = false;
+ bool specialAction = false;
+
+ QListViewItem* oldCurrent = currentItem( );
+
+ m_event = true;
+ m_acceptSelect = true;
+ QListView::contentsMousePressEvent( e );
+ m_event = false;
+ m_acceptSelect = true;
+
+ if( m_selectionCleared )
+ {
+ emit objectChanged( 0, PMCNewSelection, this );
+ specialAction = true;
+ }
+ else if( m_itemSelected || m_itemDeselected )
+ {
+ if( !( e->state( ) & ( ShiftButton | ControlButton ) ) )
+ {
+ specialAction = true;
+ // simple click, deselect all selected item
+ // m_pLastSelected is the new selection
+
+ if( m_itemSelected )
+ {
+ clearSelection( );
+ m_pLastSelected->setSelected( true );
+
+ emit objectChanged( m_pLastSelected->object( ), PMCNewSelection,
+ this );
+ }
+ else
+ {
+ m_selectOnReleaseEvent = true;
+ m_pLastSelected->setSelected( true );
+ }
+ }
+ else if( ( e->state( ) & ShiftButton ) && oldCurrent && m_pLastSelected )
+ {
+ if( ( oldCurrent != m_pLastSelected ) &&
+ ( oldCurrent->parent( ) == m_pLastSelected->parent( ) ) )
+ {
+ specialAction = true;
+
+ // shift click, old current item has the same parent
+ // as the new selection. Select all items between the two
+ // items
+ if( m_pLastSelected->object( )->isSelectable( ) )
+ {
+ bool down = oldCurrent->itemPos( ) < m_pLastSelected->itemPos( );
+ QListViewItem* tmp;
+
+ if( down )
+ {
+ for( tmp = oldCurrent; tmp; tmp = tmp->nextSibling( ) )
+ {
+ tmp->setSelected( true );
+ emit objectChanged( (( PMTreeViewItem* ) tmp)->object( ),
+ PMCSelected, this );
+ if( tmp == m_pLastSelected )
+ break;
+ }
+ }
+ else
+ {
+ for( tmp = m_pLastSelected; tmp; tmp = tmp->nextSibling( ) )
+ {
+ tmp->setSelected( true );
+ emit objectChanged( (( PMTreeViewItem* ) tmp)->object( ),
+ PMCSelected, this );
+ if( tmp == oldCurrent )
+ break;
+ }
+ }
+ }
+ else
+ m_pLastSelected->setSelected( false );
+ }
+ }
+ }
+ if( !specialAction )
+ {
+ // no special action
+ // object is selected or deselected, no other objects are changed
+ if( m_itemSelected )
+ {
+ if( m_pLastSelected->object( )->isSelectable( ) )
+ emit objectChanged( m_pLastSelected->object( ), PMCSelected, this );
+ else
+ m_pLastSelected->setSelected( false );
+ }
+ else if( m_itemDeselected )
+ emit objectChanged( m_pLastSelected->object( ), PMCDeselected, this );
+ }
+ m_acceptSelect = false;
+}
+
+void PMTreeView::contentsMouseMoveEvent( QMouseEvent * e )
+{
+ m_itemSelected = false;
+ m_itemDeselected = false;
+ m_pLastSelected = 0;
+ m_selectionCleared = false;
+
+ m_event = true;
+ QListView::contentsMouseMoveEvent( e );
+ m_event = false;
+
+ // ignore all selections/deselections
+ if( m_itemSelected || m_itemDeselected )
+ m_pLastSelected->setSelected( m_pLastSelected->object( )->isSelected( ) );
+}
+
+void PMTreeView::viewportMousePressEvent( QMouseEvent* e )
+{
+ m_acceptSelect = true;
+ QListView::viewportMousePressEvent( e );
+ m_acceptSelect = false;
+
+ m_pressed = false;
+
+ QPoint p = e->pos( );
+
+ if( e->button( ) & RightButton )
+ {
+ if( m_pPart->factory( ) )
+ {
+ QPopupMenu* m =
+ ( QPopupMenu* ) m_pPart->factory( )->container( "treeViewPopup", m_pPart );
+ if( m )
+ m->exec( QCursor::pos( ) );
+ }
+ return;
+ }
+
+ PMTreeViewItem *item = ( PMTreeViewItem* )itemAt( p );
+ if( item )
+ {
+ // check if the root decoration was clicked
+ if( !( p.x( ) > header( )->cellPos( header( )->mapToActual( 0 ) ) +
+ treeStepSize( ) * ( item->depth( ) + ( rootIsDecorated( ) ? 1 : 0 ) )
+ + itemMargin( ) ||
+ p.x( ) < header( )->cellPos( header( )->mapToActual( 0 ) ) ) )
+ item = 0; // p is on the root decoration
+ }
+
+ if( item )
+ {
+ if( e->button( ) == LeftButton || e->button( ) == MidButton )
+ {
+ m_pressed = true;
+ m_pressedPos = e->pos( );
+ m_pressedItem = item;
+ return;
+ }
+ }
+}
+
+void PMTreeView::viewportMouseReleaseEvent( QMouseEvent* e )
+{
+ QListView::viewportMouseReleaseEvent( e );
+
+ if( !m_pressed )
+ return;
+
+ m_pressed = false;
+ m_pressedItem = 0L;
+
+ if( m_selectOnReleaseEvent )
+ {
+ if( m_pLastSelected )
+ {
+ m_acceptSelect = true;
+ clearSelection( );
+ m_pLastSelected->setSelected( true );
+ m_acceptSelect = false;
+
+ emit objectChanged( m_pLastSelected->object( ), PMCNewSelection, this );
+ }
+ }
+}
+
+void PMTreeView::viewportMouseMoveEvent( QMouseEvent *e )
+{
+ QListView::viewportMouseMoveEvent( e );
+
+ if( m_pressed && m_pressedItem )
+ {
+ int x = e->pos( ).x( );
+ int y = e->pos( ).y( );
+
+ //Is it time to start a drag?
+ if( abs( x - m_pressedPos.x( ) ) > KGlobalSettings::dndEventDelay( ) ||
+ abs( y - m_pressedPos.y( ) ) > KGlobalSettings::dndEventDelay( ) )
+ {
+ m_selectOnReleaseEvent = false;
+
+ // Calculate hotspot
+ QPoint hotspot;
+ PMObjectList sortedList = m_pPart->selectedObjects( );
+
+ // Do not handle more mouse move or mouse release events
+ m_pressed = false;
+
+ if( sortedList.count( ) > 0 )
+ {
+ PMObjectDrag* d = new PMObjectDrag( m_pPart, sortedList, viewport( ) );
+
+ hotspot.setX( m_pressedItem->pixmap( 0 )->width( ) / 2 );
+ hotspot.setY( m_pressedItem->pixmap( 0 )->height( ) / 2 );
+ if( sortedList.count( ) == 1 )
+ d->setPixmap( SmallIcon(
+ sortedList.first( )->pixmap( ) ), hotspot );
+ else
+ d->setPixmap( SmallIcon( "pmdrag" ) );
+
+ if( d->drag( ) )
+ {
+ kdDebug( PMArea ) << "Drag returned true\n";
+ if( !targetDisplaysPart( d->target( ) ) )
+ m_pPart->dragMoveSelectionTo( 0 );
+ }
+ }
+ }
+ }
+}
+
+void PMTreeView::viewportDragMoveEvent( QDragMoveEvent *e )
+{
+ bool accept = false;
+
+ if( m_pPart->isReadWrite( ) )
+ {
+ if( PMObjectDrag::canDecode( e, m_pPart ) )
+ {
+ PMTreeViewItem *item = ( PMTreeViewItem* ) itemAt( e->pos( ) );
+ PMObject* obj = 0;
+
+ if( !item )
+ {
+ accept = false;
+ /*
+ if( e->source( ) == viewport( ) )
+ {
+ if( m_pPart->scene( )->isSelected( ) )
+ accept = false;
+ else
+ accept = true;
+ }
+ else
+ accept = true;
+ obj = m_pPart->scene( );
+ */
+
+ m_pDragOverItem = 0L;
+ obj = 0;
+ }
+ else
+ {
+ obj = item->object( );
+ if( ( obj->isSelectable( ) &&
+ !obj->isSelected( ) ) || ( e->source( ) != viewport( ) ) )
+ {
+ accept = true;
+ setCurrentItem( item );
+ m_pDragOverItem = item;
+ }
+ else
+ {
+ accept = false;
+ m_pDragOverItem = 0L;
+ }
+ }
+
+ if( accept )
+ {
+ accept = false;
+ if( !obj->isReadOnly( ) )
+ accept = true;
+ if( obj->parent( ) )
+ if( !obj->parent( )->isReadOnly( ) )
+ accept = true;
+ }
+ }
+ else
+ accept = false;
+ }
+ else
+ accept = false;
+
+ if( accept )
+ e->acceptAction( );
+ else
+ e->ignore( );
+}
+
+void PMTreeView::viewportDragEnterEvent( QDragEnterEvent *e )
+{
+ m_pDragOverItem = 0L;
+
+ if( m_pPart->isReadWrite( ) )
+ e->accept( PMObjectDrag::canDecode( e, m_pPart ) );
+ else
+ e->ignore( );
+}
+
+void PMTreeView::viewportDragLeaveEvent( QDragLeaveEvent* )
+{
+ m_pDragOverItem = 0L;
+}
+
+void PMTreeView::viewportDropEvent( QDropEvent* e )
+{
+ PMObject* obj;
+
+ if( m_pPart->isReadWrite( ) )
+ {
+ if( m_pDragOverItem )
+ obj = m_pDragOverItem->object( );
+ else
+ obj = m_pPart->scene( );
+
+ if( PMObjectDrag::canDecode( e, m_pPart ) )
+ {
+ if( targetDisplaysPart( e->source( ) ) &&
+ ( e->action( ) == QDropEvent::Move ) )
+ {
+ if( m_pPart->dragMoveSelectionTo( obj ) )
+ e->acceptAction( );
+ else
+ e->ignore( );
+ }
+ else
+ {
+ if( m_pPart->drop( obj, e ) )
+ e->acceptAction( );
+ else
+ e->ignore( );
+ }
+ }
+ else
+ e->ignore( );
+ }
+ else
+ e->ignore( );
+
+ m_pDragOverItem = 0L;
+}
+
+void PMTreeView::focusOutEvent( QFocusEvent* e )
+{
+ QWidget::focusOutEvent( e );
+ m_pressed = false;
+ m_pressedItem = 0;
+}
+
+void PMTreeView::focusInEvent( QFocusEvent* e )
+{
+ QWidget::focusInEvent( e );
+ m_pressed = false;
+ m_pressedItem = 0;
+}
+
+void PMTreeView::keyPressEvent( QKeyEvent* e )
+{
+ QListViewItem* current = currentItem( );
+ QListViewItem* newSelection = 0;
+ bool accept = false;
+ bool deleteItem = false;
+ bool pasteItem = false;
+
+ if( current )
+ {
+ switch( e->key( ) )
+ {
+ case Qt::Key_Up:
+ newSelection = current->itemAbove( );
+ accept = true;
+ break;
+ case Qt::Key_Down:
+ newSelection = current->itemBelow( );
+ accept = true;
+ break;
+ case Qt::Key_Left:
+ newSelection = current->parent( );
+ accept = true;
+ break;
+ case Qt::Key_Right:
+ newSelection = current->firstChild( );
+ accept = true;
+ break;
+ case Qt::Key_Plus:
+ current->setOpen( true );
+ accept = true;
+ break;
+ case Qt::Key_Minus:
+ current->setOpen( false );
+ accept = true;
+ case Qt::Key_Delete:
+ deleteItem = true;
+ accept = true;
+ break;
+ case Qt::CTRL+Qt::Key_V:
+ case Qt::SHIFT+Qt::Key_Insert:
+ pasteItem = true;
+ accept = true;
+ break;
+ }
+ }
+
+ if( newSelection )
+ {
+ m_acceptSelect = true;
+ clearSelection( );
+ newSelection->setSelected( true );
+ setCurrentItem( newSelection );
+ ensureItemVisible( newSelection );
+ m_acceptSelect = false;
+
+ emit objectChanged( ( ( PMTreeViewItem* ) newSelection )->object( ),
+ PMCNewSelection, this );
+ }
+
+ if( deleteItem && m_pPart->isReadWrite( ) )
+ {
+ m_pPart->slotEditDelete( );
+ m_pPart->setModified( true );
+ }
+
+ if( pasteItem && m_pPart->isReadWrite( ) )
+ {
+ m_pPart->slotEditPaste( );
+ m_pPart->setModified( true );
+ }
+
+ if( accept )
+ e->accept( );
+ else
+ e->ignore( );
+ QWidget::keyPressEvent( e );
+}
+
+bool PMTreeView::targetDisplaysPart( QWidget* target )
+{
+ bool result = false;
+ if( !target ) // another application
+ result = false;
+ else if( target == viewport( ) ) // self
+ result = true;
+ else
+ {
+ // Widget may be a view port
+ // find the tree view
+ QWidget* t = target;
+ while( t && !t->isA( "PMTreeView" ) )
+ t = t->parentWidget( );
+ if( t )
+ if( ( ( PMTreeView* ) t )->part( ) == m_pPart )
+ result = true;
+ }
+ return result;
+}
+
+QString PMTreeViewFactory::description( ) const
+{
+ return i18n( "Object Tree" );
+}
+
+#include "pmtreeview.moc"
diff --git a/kpovmodeler/pmtreeview.h b/kpovmodeler/pmtreeview.h
new file mode 100644
index 00000000..24f6f33f
--- /dev/null
+++ b/kpovmodeler/pmtreeview.h
@@ -0,0 +1,182 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTREEVIEW_H
+#define PMTREEVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qlistview.h>
+#include "pmobject.h"
+#include "pmviewbase.h"
+#include "pmviewfactory.h"
+
+class PMTreeViewItem;
+class PMPart;
+
+/**
+ * Wrapper class for the treeview/dock widget
+ */
+class PMTreeViewWidget : public PMViewBase
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMTreeViewWidget( PMPart* pare, QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual QString viewType( ) const { return QString( "treeview" ); }
+ /** */
+ virtual QString description( ) const;
+};
+
+/**
+ * Widget that displays the scene as tree view
+ */
+class PMTreeView : public QListView
+{
+ Q_OBJECT
+ friend class PMTreeViewItem;
+public:
+ /**
+ * Creates a PMTreeView with parent and name that displays the
+ * document doc
+ */
+ PMTreeView( PMPart* part, QWidget* parent = 0, const char* name = 0 );
+ /**
+ * Deletes the PMTreeView
+ */
+ ~PMTreeView( );
+
+ /**
+ * Returns true PMTreeViewItem::setSelected should be accepted
+ */
+ bool acceptSelect( ) const { return m_acceptSelect; }
+ /**
+ * Returns the connected part
+ */
+ PMPart* part( ) const { return m_pPart; }
+
+public slots:
+ /**
+ * Called when an object is changed.
+ * @see PMPart::objectChanged( ) */
+ void slotObjectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Refreshes the whole csg tree
+ */
+ void slotRefresh( );
+ /**
+ * Clears all data
+ */
+ void slotClear( );
+
+signals:
+ /**
+ * Emitted, when an object is selected or deselected
+ */
+ void objectChanged( PMObject* obj, const int mode, QObject* sender );
+ /**
+ * Emitted in the destructor
+ */
+ void destroyed( PMTreeView* v );
+
+protected:
+ void contentsMousePressEvent( QMouseEvent * e );
+ void contentsMouseMoveEvent( QMouseEvent * e );
+ void itemSelected( PMTreeViewItem* item, bool selected );
+
+ void viewportMousePressEvent( QMouseEvent * e );
+ void viewportMouseReleaseEvent( QMouseEvent* e );
+ void viewportMouseMoveEvent( QMouseEvent* e );
+
+ void viewportDragMoveEvent( QDragMoveEvent *e );
+ void viewportDragEnterEvent( QDragEnterEvent *e );
+ void viewportDragLeaveEvent( QDragLeaveEvent* e );
+ void viewportDropEvent( QDropEvent* e );
+
+ void focusOutEvent( QFocusEvent* e );
+ void focusInEvent( QFocusEvent* e );
+
+ void keyPressEvent( QKeyEvent* e );
+
+private:
+ /**
+ * Adds child items of item to the tree view
+ */
+ void addChildItems( PMTreeViewItem* item );
+ /**
+ * Returns the ListViewItem connected with the PMObject obj
+ */
+ PMTreeViewItem* findObject( const PMObject* obj );
+ /**
+ * Selects the item. Expands the tree if necessary
+ */
+ void selectItem( QListViewItem* item );
+ /**
+ * Returns true if the drop target is a tree view for the same part
+ */
+ bool targetDisplaysPart( QWidget* target );
+
+ /**
+ * the displayed document
+ */
+ PMPart* m_pPart;
+
+ /**
+ * the selected items
+ */
+// QPtrList<PMTreeViewItem> m_selectedItems;
+ PMTreeViewItem* m_pLastSelected;
+ bool m_itemSelected;
+ bool m_itemDeselected;
+ bool m_selectionCleared;
+ bool m_event;
+ bool m_acceptSelect;
+ bool m_selectOnReleaseEvent;
+
+ PMTreeViewItem* m_pDragOverItem;
+// QStringList m_lstDropFormats;
+
+ // for drag and drop, copied from KonqBaseListViewWidget
+ bool m_pressed;
+ QPoint m_pressedPos;
+ PMTreeViewItem* m_pressedItem;
+};
+
+/**
+ * Factory class for the tree view
+ */
+class PMTreeViewFactory : public PMViewTypeFactory
+{
+public:
+ PMTreeViewFactory( ) { }
+ virtual QString viewType( ) const { return QString( "treeview" ); }
+ virtual QString description( ) const;
+ virtual QString iconName( ) const { return QString( "pmtreeview" ); }
+ virtual PMViewBase* newInstance( QWidget* parent, PMPart* part ) const
+ {
+ return new PMTreeViewWidget( part, parent );
+ }
+};
+
+#endif
diff --git a/kpovmodeler/pmtreeviewitem.cpp b/kpovmodeler/pmtreeviewitem.cpp
new file mode 100644
index 00000000..72562f78
--- /dev/null
+++ b/kpovmodeler/pmtreeviewitem.cpp
@@ -0,0 +1,117 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtreeviewitem.h"
+#include "pmobject.h"
+#include <kiconloader.h>
+
+#include "pmtreeview.h"
+#include "pmfactory.h"
+#include "pmtexturemap.h"
+
+PMTreeViewItem::PMTreeViewItem( PMObject* object, QListView* parent )
+ : QListViewItem( parent )
+{
+ m_pObject = object;
+ setDescriptions( );
+ initSelection( );
+}
+
+PMTreeViewItem::PMTreeViewItem( PMObject* object, QListViewItem* parent )
+ : QListViewItem( parent )
+{
+ m_pObject = object;
+ setDescriptions( );
+ initSelection( );
+}
+
+PMTreeViewItem::PMTreeViewItem( PMObject* object, QListView* parent,
+ QListViewItem* after )
+ : QListViewItem( parent, after )
+{
+ m_pObject = object;
+ setDescriptions( );
+ initSelection( );
+}
+
+PMTreeViewItem::PMTreeViewItem( PMObject* object, QListViewItem* parent,
+ QListViewItem* after )
+ : QListViewItem( parent, after )
+{
+ m_pObject = object;
+ setDescriptions( );
+ initSelection( );
+}
+
+void PMTreeViewItem::setDescriptions( )
+{
+ QString text;
+ setPixmap( 0, SmallIcon( m_pObject->pixmap( ), PMFactory::instance( ) ) );
+
+ if( m_pObject->canHaveName( ) )
+ {
+ text = m_pObject->name( );
+ if( text.isEmpty( ) )
+ text = m_pObject->description( );
+ }
+ else
+ text = m_pObject->description( );
+
+ if( m_pObject->parent( ) )
+ {
+ if( m_pObject->parent( )->isA( "TextureMapBase" ) )
+ {
+ PMTextureMapBase* tm = ( PMTextureMapBase* ) m_pObject->parent( );
+ if( m_pObject->type( ) == tm->mapType( ) )
+ text = QString( "[%1] " ).arg( tm->mapValue( m_pObject ), 4, 'f', 2 ) + text;
+ }
+ }
+ setText( 0, text );
+}
+
+QString PMTreeViewItem::key( int, bool ) const
+{
+ QString result;
+ if( m_pObject->parent( ) )
+ result.sprintf( "%06i", m_pObject->parent( )->findChild( m_pObject ) );
+ else
+ result = "000000";
+ return result;
+}
+
+void PMTreeViewItem::setSelected( bool select )
+{
+ bool ws = isSelected( );
+ PMTreeView* treeview = ( PMTreeView* ) listView( );
+
+ // ignore selections during a move event
+ if( treeview->acceptSelect( ) )
+ {
+ QListViewItem::setSelected( select );
+
+ if( ws != isSelected( ) )
+ treeview->itemSelected( this, isSelected( ) );
+ }
+}
+
+void PMTreeViewItem::initSelection( )
+{
+ QListViewItem::setSelected( m_pObject->isSelected( ) );
+// if( m_pObject->isSelected( ) )
+// repaint( );
+}
diff --git a/kpovmodeler/pmtreeviewitem.h b/kpovmodeler/pmtreeviewitem.h
new file mode 100644
index 00000000..499e2d16
--- /dev/null
+++ b/kpovmodeler/pmtreeviewitem.h
@@ -0,0 +1,88 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTREEVIEWITEM_H
+#define PMTREEVIEWITEM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qlistview.h>
+class PMObject;
+
+/**
+ * QListViewItem for a @ref PMObject
+ *
+ * Each PMListViewItem is connected to a PMObject.
+ */
+class PMTreeViewItem : public QListViewItem
+{
+public:
+ /**
+ * Constructs a new top-level list view item in the QListView parent.
+ */
+ PMTreeViewItem( PMObject* object, QListView* parent );
+ /**
+ * Constructs a new list view item which is a child of parent and
+ * first in the parent's list of children.
+ */
+ PMTreeViewItem( PMObject* object, QListViewItem* parent );
+ /**
+ * Constructs a list view item which is a child of parent
+ * and is after after in the parent's list of children.
+ */
+ PMTreeViewItem( PMObject* object, QListView* parent, QListViewItem* after );
+ /**
+ * Constructs a list view item which is a child of parent
+ * and is after after in the parent's list of children.
+ */
+ PMTreeViewItem( PMObject* object, QListViewItem* parent,
+ QListViewItem* after );
+ /**
+ * Returns the connected @ref PMObject
+ */
+ PMObject* object( ) const { return m_pObject; }
+ /**
+ * Returns a key that can be used for sorting, here the index in the
+ * parents list of children
+ */
+ virtual QString key( int column, bool ascending ) const;
+ /**
+ * Returns a pointer to the parent item
+ */
+ PMTreeViewItem* parent( )
+ {
+ return ( PMTreeViewItem* ) QListViewItem::parent( );
+ }
+ void setSelected( bool select );
+
+ /**
+ * Sets the text and pixmap
+ */
+ void setDescriptions( );
+private:
+ /**
+ * Initializes the selection at creation
+ */
+ void initSelection( );
+ PMObject* m_pObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmtriangle.cpp b/kpovmodeler/pmtriangle.cpp
new file mode 100644
index 00000000..3cae7e37
--- /dev/null
+++ b/kpovmodeler/pmtriangle.cpp
@@ -0,0 +1,621 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtriangle.h"
+#include "pmtriangleedit.h"
+
+#include "pmxmlhelper.h"
+#include "pmmemento.h"
+#include "pmviewstructure.h"
+#include "pm3dcontrolpoint.h"
+#include "pmvectorcontrolpoint.h"
+
+#include <klocale.h>
+
+const PMVector point0Default = PMVector( -1.0, 0.0, 0.0 );
+const PMVector point1Default = PMVector( 1.0, 0.0, 0.0 );
+const PMVector point2Default = PMVector( 0.0, 0.0, 1.0 );
+const PMVector normal0Default = PMVector( 0.0, 1.0, 0.0 );
+const PMVector normal1Default = PMVector( 0.0, 1.0, 0.0 );
+const PMVector normal2Default = PMVector( 0.0, 1.0, 0.0 );
+const PMVector uvVector0Default = PMVector( 0.0, 0.0 );
+const PMVector uvVector1Default = PMVector( 1.0, 0.0 );
+const PMVector uvVector2Default = PMVector( 0.5, 1.0 );
+
+PMDefinePropertyClass( PMTriangle, PMTriangleProperty );
+
+class PMPointProperty : public PMPropertyBase
+{
+public:
+ PMPointProperty( ) : PMPropertyBase( "points", PMVariant::Vector )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ if( index < 0 || index > 2 )
+ kdError( PMArea ) << "Illegal index in PMTriangle::PointProperty::setIndex" << endl;
+ else
+ m_index = index;
+ }
+ virtual int size( PMObject* /*object*/, int /*dimension*/ ) const
+ {
+ return 3;
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& v )
+ {
+ PMTriangle* p = ( PMTriangle* ) obj;
+ p->setPoint( m_index, v.vectorData( ) );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ const PMTriangle* p = ( const PMTriangle* ) obj;
+ return PMVariant( p->point( m_index ) );
+ }
+
+private:
+ int m_index;
+};
+
+class PMNormalProperty : public PMPropertyBase
+{
+public:
+ PMNormalProperty( ) : PMPropertyBase( "normals", PMVariant::Vector )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ if( index < 0 || index > 2 )
+ kdError( PMArea ) << "Illegal index in PMTriangle::NormalProperty::setIndex" << endl;
+ else
+ m_index = index;
+ }
+ virtual int size( PMObject* /*object*/, int /*dimension*/ ) const
+ {
+ return 3;
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& v )
+ {
+ PMTriangle* p = ( PMTriangle* ) obj;
+ p->setNormal( m_index, v.vectorData( ) );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ const PMTriangle* p = ( const PMTriangle* ) obj;
+ return PMVariant( p->normal( m_index ) );
+ }
+
+private:
+ int m_index;
+};
+
+class PMUVVectorProperty : public PMPropertyBase
+{
+public:
+ PMUVVectorProperty( )
+ : PMPropertyBase( "uvVectors", PMVariant::Vector )
+ {
+ m_index = 0;
+ }
+ virtual int dimensions( ) const { return 1; }
+ virtual void setIndex( int /*dimension*/, int index )
+ {
+ if( index < 0 || index > 2 )
+ kdError( PMArea ) << "Illegal index in PMTriangle::UVVectorProperty::setIndex" << endl;
+ else
+ m_index = index;
+ }
+ virtual int size( PMObject* /*object*/, int /*dimension*/ ) const
+ {
+ return 2;
+ }
+protected:
+ virtual bool setProtected( PMObject* obj, const PMVariant& v )
+ {
+ PMTriangle* p = ( PMTriangle* ) obj;
+ p->setUVVector( m_index, v.vectorData( ) );
+ return true;
+ }
+ virtual PMVariant getProtected( const PMObject* obj )
+ {
+ const PMTriangle* p = ( const PMTriangle* ) obj;
+ return PMVariant( p->uvVector( m_index ) );
+ }
+
+private:
+ int m_index;
+};
+
+PMMetaObject* PMTriangle::s_pMetaObject = 0;
+PMObject* createNewTriangle( PMPart* part )
+{
+ return new PMTriangle( part );
+}
+PMViewStructure* PMTriangle::s_pDefaultViewStructure = 0;
+
+PMTriangle::PMTriangle( PMPart* part )
+ : Base( part )
+{
+ m_point[0] = point0Default;
+ m_point[1] = point1Default;
+ m_point[2] = point2Default;
+ m_normal[0] = normal0Default;
+ m_normal[1] = normal1Default;
+ m_normal[2] = normal2Default;
+ m_smooth = false;
+ m_uvVector[0] = uvVector0Default;
+ m_uvVector[1] = uvVector1Default;
+ m_uvVector[2] = uvVector2Default;
+ m_uvEnabled = false;
+}
+
+PMTriangle::PMTriangle( const PMTriangle& t )
+ : Base( t )
+{
+ int i;
+ for( i = 0; i < 3; i++ )
+ {
+ m_point[i] = t.m_point[i];
+ m_normal[i] = t.m_normal[i];
+ m_uvVector[i] = t.m_uvVector[i];
+ }
+ m_smooth = t.m_smooth;
+ m_uvEnabled = t.m_uvEnabled;
+}
+
+PMTriangle::~PMTriangle( )
+{
+}
+
+QString PMTriangle::description( ) const
+{
+ if( m_smooth )
+ return i18n( "smooth triangle" );
+ return i18n( "triangle" );
+}
+
+void PMTriangle::serialize( QDomElement& e, QDomDocument& doc ) const
+{
+ e.setAttribute( "point0", m_point[0].serializeXML( ) );
+ e.setAttribute( "point1", m_point[1].serializeXML( ) );
+ e.setAttribute( "point2", m_point[2].serializeXML( ) );
+ e.setAttribute( "normal0", m_normal[0].serializeXML( ) );
+ e.setAttribute( "normal1", m_normal[1].serializeXML( ) );
+ e.setAttribute( "normal2", m_normal[2].serializeXML( ) );
+ e.setAttribute( "smooth", m_smooth );
+ e.setAttribute( "uvVector0", m_uvVector[0].serializeXML( ) );
+ e.setAttribute( "uvVector1", m_uvVector[1].serializeXML( ) );
+ e.setAttribute( "uvVector2", m_uvVector[2].serializeXML( ) );
+ e.setAttribute( "uvEnabled", m_uvEnabled );
+ Base::serialize( e, doc );
+}
+
+void PMTriangle::readAttributes( const PMXMLHelper& h )
+{
+ m_point[0] = h.vectorAttribute( "point0", point0Default );
+ m_point[1] = h.vectorAttribute( "point1", point1Default );
+ m_point[2] = h.vectorAttribute( "point2", point2Default );
+ m_normal[0] = h.vectorAttribute( "normal0", normal0Default );
+ m_normal[1] = h.vectorAttribute( "normal1", normal1Default );
+ m_normal[2] = h.vectorAttribute( "normal2", normal2Default );
+ m_smooth = h.boolAttribute( "smooth", false );
+ m_uvVector[0] = h.vectorAttribute( "uvVector0", uvVector0Default );
+ m_uvVector[1] = h.vectorAttribute( "uvVector1", uvVector1Default );
+ m_uvVector[2] = h.vectorAttribute( "uvVector2", uvVector2Default );
+ m_uvEnabled = h.boolAttribute( "uvEnabled", m_uvEnabled );
+ Base::readAttributes( h );
+}
+
+PMMetaObject* PMTriangle::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Triangle", Base::metaObject( ),
+ createNewTriangle );
+ s_pMetaObject->addProperty(
+ new PMTriangleProperty( "smooth", &PMTriangle::setSmoothTriangle,
+ &PMTriangle::isSmoothTriangle ) );
+ s_pMetaObject->addProperty( new PMPointProperty( ) );
+ s_pMetaObject->addProperty( new PMNormalProperty( ) );
+ s_pMetaObject->addProperty( new PMUVVectorProperty( ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMTriangle::setPoint( int i, const PMVector& p )
+{
+ if( ( i >= 0 ) && ( i <= 2 ) )
+ {
+ if( p != m_point[i] )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMPoint0ID + i, m_point[i] );
+ m_point[i] = p;
+ m_point[i].resize( 3 );
+ setViewStructureChanged( );
+ }
+ }
+ else
+ kdError( PMArea ) << "Wrong index in PMTriangle::setPoint\n";
+}
+
+PMVector PMTriangle::point( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 2 ) )
+ return m_point[i];
+ else
+ kdError( PMArea ) << "Wrong index in PMTriangle::point\n";
+ return PMVector( 0.0, 0.0, 0.0 );
+}
+
+void PMTriangle::setNormal( int i, const PMVector& p )
+{
+ if( ( i >= 0 ) && ( i <= 2 ) )
+ {
+ if( p != m_normal[i] )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMNormal0ID + i, m_normal[i] );
+ m_normal[i] = p;
+ m_normal[i].resize( 3 );
+ setViewStructureChanged( );
+ }
+ }
+ else
+ kdError( PMArea ) << "Wrong index in PMTriangle::setNormal\n";
+}
+
+PMVector PMTriangle::normal( int i ) const
+{
+ if( ( i >= 0 ) && ( i <= 2 ) )
+ return m_normal[i];
+ else
+ kdError( PMArea ) << "Wrong index in PMTriangle::normal\n";
+ return PMVector( 0.0, 0.0, 0.0 );
+}
+
+void PMTriangle::setSmoothTriangle( bool on )
+{
+ if( on != m_smooth )
+ {
+ if( m_pMemento )
+ {
+ m_pMemento->addData( s_pMetaObject, PMSmoothID, m_smooth );
+ m_pMemento->setDescriptionChanged( );
+ }
+ m_smooth = on;
+ setViewStructureChanged( );
+ }
+}
+
+PMVector PMTriangle::uvVector( int i ) const
+{
+ if( i >= 0 && i < 3 )
+ return m_uvVector[i];
+ else
+ kdError( PMArea ) << "Wrong index in PMTriangle::uvVector\n";
+ return PMVector( 0.0, 0.0 );
+}
+
+void PMTriangle::setUVVector( int i, const PMVector& v )
+{
+ if( i >= 0 && i < 3 )
+ {
+ if( v != m_uvVector[i] )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUVVector0ID + i, m_uvVector[i] );
+ m_uvVector[i] = v;
+ m_uvVector[i].resize( 2 );
+ }
+ }
+ else
+ kdError( PMArea ) << "Wrong index in PMTriangle::setNormal\n";
+}
+
+void PMTriangle::enableUV( bool yes )
+{
+ if( yes != m_uvEnabled )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMUVEnabledID, m_uvEnabled );
+ m_uvEnabled = yes;
+ }
+}
+
+PMDialogEditBase* PMTriangle::editWidget( QWidget* parent ) const
+{
+ return new PMTriangleEdit( parent );
+}
+
+void PMTriangle::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMPoint0ID:
+ setPoint( 0, data->vectorData( ) );
+ break;
+ case PMPoint1ID:
+ setPoint( 1, data->vectorData( ) );
+ break;
+ case PMPoint2ID:
+ setPoint( 2, data->vectorData( ) );
+ break;
+ case PMNormal0ID:
+ setNormal( 0, data->vectorData( ) );
+ break;
+ case PMNormal1ID:
+ setNormal( 1, data->vectorData( ) );
+ break;
+ case PMNormal2ID:
+ setNormal( 2, data->vectorData( ) );
+ break;
+ case PMSmoothID:
+ setSmoothTriangle( data->boolData( ) );
+ break;
+ case PMUVVector0ID:
+ setUVVector( 0, data->vectorData( ) );
+ break;
+ case PMUVVector1ID:
+ setUVVector( 1, data->vectorData( ) );
+ break;
+ case PMUVVector2ID:
+ setUVVector( 2, data->vectorData( ) );
+ break;
+ case PMUVEnabledID:
+ enableUV( data->boolData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMTriangle::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
+
+
+bool PMTriangle::isDefault( )
+{
+ if( ( m_point[0] == point0Default )
+ && ( m_point[1] == point1Default )
+ && ( m_point[2] == point2Default ) )
+ return true;
+ return false;
+}
+
+void PMTriangle::createViewStructure( )
+{
+ if( !m_pViewStructure )
+ {
+ m_pViewStructure = new PMViewStructure( defaultViewStructure( ) );
+ m_pViewStructure->points( ).detach( );
+ }
+
+ PMPointArray& points = m_pViewStructure->points( );
+
+ points[0] = m_point[0];
+ points[1] = m_point[1];
+ points[2] = m_point[2];
+}
+
+PMViewStructure* PMTriangle::defaultViewStructure( ) const
+{
+ if( !s_pDefaultViewStructure )
+ {
+ s_pDefaultViewStructure = new PMViewStructure( 3, 3 );
+ PMPointArray& points = s_pDefaultViewStructure->points( );
+ PMLineArray& lines = s_pDefaultViewStructure->lines( );
+
+ points[0] = point0Default;
+ points[1] = point1Default;
+ points[2] = point2Default;
+
+ lines[0] = PMLine( 0, 1 );
+ lines[1] = PMLine( 1, 2 );
+ lines[2] = PMLine( 0, 2 );
+ }
+ return s_pDefaultViewStructure;
+}
+
+void PMTriangle::controlPoints( PMControlPointList& list )
+{
+ PM3DControlPoint* cp;
+
+ cp = new PM3DControlPoint( m_point[0], PMPoint0ID,
+ i18n( "Point 1" ) );
+ list.append( cp );
+ if( m_smooth )
+ list.append( new PMVectorControlPoint( cp, m_normal[0], PMNormal0ID,
+ i18n( "Normal 1" ) ) );
+
+ cp = new PM3DControlPoint( m_point[1], PMPoint1ID,
+ i18n( "Point 2" ) );
+ list.append( cp );
+ if( m_smooth )
+ list.append( new PMVectorControlPoint( cp, m_normal[1], PMNormal1ID,
+ i18n( "Normal 2" ) ) );
+
+ cp = new PM3DControlPoint( m_point[2], PMPoint2ID,
+ i18n( "Point 3" ) );
+ list.append( cp );
+ if( m_smooth )
+ list.append( new PMVectorControlPoint( cp, m_normal[2], PMNormal2ID,
+ i18n( "Normal 3" ) ) );
+}
+
+void PMTriangle::controlPointsChanged( PMControlPointList& list )
+{
+ PMControlPoint* p;
+ PMVector p0, p1, p2;
+ PMVector n0, n1, n2;
+ double normalDirection = 1.0;
+ PMVector triangleNormal;
+ bool validNormal = false;
+ double d;
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMPoint0ID:
+ p0 = ( ( PM3DControlPoint* ) p )->point( );
+ break;
+ case PMPoint1ID:
+ p1 = ( ( PM3DControlPoint* ) p )->point( );
+ break;
+ case PMPoint2ID:
+ p2 = ( ( PM3DControlPoint* ) p )->point( );
+ break;
+ case PMNormal0ID:
+ n0 = ( ( PMVectorControlPoint* ) p )->vector( );
+ break;
+ case PMNormal1ID:
+ n1 = ( ( PMVectorControlPoint* ) p )->vector( );
+ break;
+ case PMNormal2ID:
+ n2 = ( ( PMVectorControlPoint* ) p )->vector( );
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( m_smooth )
+ {
+ triangleNormal = PMVector::cross( m_point[1] - m_point[0],
+ m_point[2] - m_point[0] );
+ normalDirection = PMVector::dot( triangleNormal, m_normal[0] );
+ if( approxZero( normalDirection ) )
+ normalDirection = PMVector::dot( triangleNormal, m_normal[1] );
+ if( approxZero( normalDirection ) )
+ normalDirection = PMVector::dot( triangleNormal, m_normal[2] );
+ if( normalDirection < 0 )
+ triangleNormal = -triangleNormal;
+ if( !approxZero( triangleNormal.abs( ) ) )
+ {
+ validNormal = true;
+ triangleNormal /= triangleNormal.abs( );
+ }
+ }
+
+ for( p = list.first( ); p; p = list.next( ) )
+ {
+ if( p->changed( ) )
+ {
+ switch( p->id( ) )
+ {
+ case PMPoint0ID:
+ if( !( p0.approxEqual( p1 ) || p0.approxEqual( p2 ) ) )
+ setPoint( 0, p0 );
+ else
+ ( ( PM3DControlPoint* ) p )->setPoint( m_point[0] );
+ break;
+ case PMPoint1ID:
+ if( !( p1.approxEqual( p0 ) || p1.approxEqual( p2 ) ) )
+ setPoint( 1, p1 );
+ else
+ ( ( PM3DControlPoint* ) p )->setPoint( m_point[1] );
+ break;
+ case PMPoint2ID:
+ if( !( p2.approxEqual( p0 ) || p2.approxEqual( p1 ) ) )
+ setPoint( 2, p2 );
+ else
+ ( ( PM3DControlPoint* ) p )->setPoint( m_point[2] );
+ break;
+
+ case PMNormal0ID:
+ if( validNormal )
+ {
+ d = PMVector::dot( triangleNormal, n0 );
+ if( d > 0 )
+ setNormal( 0, n0 );
+ else
+ {
+ setNormal( 0, n0 - ( d - 1e-5 ) * triangleNormal );
+ ( ( PMVectorControlPoint* ) p )->setVector( m_normal[0] );
+ }
+ }
+ else
+ ( ( PMVectorControlPoint* ) p )->setVector( m_normal[0] );
+ break;
+ case PMNormal1ID:
+ if( validNormal )
+ {
+ d = PMVector::dot( triangleNormal, n1 );
+ if( d > 0 )
+ setNormal( 1, n1 );
+ else
+ {
+ setNormal( 1, n1 - ( d - 1e-5 ) * triangleNormal );
+ ( ( PMVectorControlPoint* ) p )->setVector( m_normal[1] );
+ }
+ }
+ else
+ ( ( PMVectorControlPoint* ) p )->setVector( m_normal[1] );
+ break;
+ case PMNormal2ID:
+ if( validNormal )
+ {
+ d = PMVector::dot( triangleNormal, n2 );
+ if( d > 0 )
+ setNormal( 2, n2 );
+ else
+ {
+ setNormal( 2, n2 - ( d - 1e-5 ) * triangleNormal );
+ ( ( PMVectorControlPoint* ) p )->setVector( m_normal[2] );
+ }
+ }
+ else
+ ( ( PMVectorControlPoint* ) p )->setVector( m_normal[2] );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMTriangle::controlPointsChanged\n";
+ break;
+ }
+ }
+ }
+}
+
+void PMTriangle::cleanUp( ) const
+{
+ if( s_pDefaultViewStructure )
+ delete s_pDefaultViewStructure;
+ s_pDefaultViewStructure = 0;
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
diff --git a/kpovmodeler/pmtriangle.h b/kpovmodeler/pmtriangle.h
new file mode 100644
index 00000000..e2309c79
--- /dev/null
+++ b/kpovmodeler/pmtriangle.h
@@ -0,0 +1,158 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTRIANGLE_H
+#define PMTRIANGLE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmgraphicalobject.h"
+#include "pmvector.h"
+
+class PMViewStructure;
+
+/**
+ * Class for povray triangles.
+ */
+
+class PMTriangle : public PMGraphicalObject
+{
+ typedef PMGraphicalObject Base;
+public:
+ /**
+ * Creates an empty PMTriangle
+ */
+ PMTriangle( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMTriangle( const PMTriangle& t );
+ /**
+ * deletes the PMTriangle
+ */
+ virtual ~PMTriangle( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMTriangle( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+ /**
+ * Returns a new @ref PMTriangleEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmtriangle" ); }
+
+ /**
+ * Returns true if the triangle is a smooth triangle
+ */
+ bool isSmoothTriangle( ) const { return m_smooth; }
+ /**
+ * Enables/disables the normal vectors
+ */
+ void setSmoothTriangle( bool on );
+
+ /**
+ * Returns the point with index i
+ */
+ PMVector point( int i ) const;
+ /**
+ * Sets the point with index i
+ */
+ void setPoint( int i, const PMVector& p );
+ /**
+ * Returns the normal vector with index i
+ */
+ PMVector normal( int i ) const;
+ /**
+ * Sets the mormal vector with index i
+ */
+ void setNormal( int i, const PMVector& n );
+
+ /**
+ * Returns the uv vector with index i
+ */
+ PMVector uvVector( int i ) const;
+ /**
+ * Sets the uv vector with index i
+ */
+ void setUVVector( int i, const PMVector& v );
+ /**
+ * Return true if triangle has uv vectors
+ */
+ bool isUVEnabled( ) const { return m_uvEnabled; }
+ /**
+ * Enables/disable the uv vectors
+ */
+ void enableUV( bool yes );
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+ /** */
+ virtual void controlPoints( PMControlPointList& list );
+ /** */
+ virtual void controlPointsChanged( PMControlPointList& list );
+ /** */
+ virtual void cleanUp( ) const;
+
+protected:
+ /** */
+ virtual bool isDefault( );
+ /** */
+ virtual void createViewStructure( );
+ /** */
+ virtual PMViewStructure* defaultViewStructure( ) const;
+
+protected:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMTriangleMementoID { PMPoint0ID, PMPoint1ID, PMPoint2ID,
+ PMNormal0ID, PMNormal1ID, PMNormal2ID,
+ PMSmoothID,
+ PMUVVector0ID, PMUVVector1ID, PMUVVector2ID,
+ PMUVEnabledID };
+ PMVector m_point[3];
+ PMVector m_normal[3];
+ PMVector m_uvVector[3];
+ bool m_smooth;
+ bool m_uvEnabled;
+
+ /**
+ * The default view structure. It can be shared between triangles
+ */
+ static PMViewStructure* s_pDefaultViewStructure;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmtriangleedit.cpp b/kpovmodeler/pmtriangleedit.cpp
new file mode 100644
index 00000000..7b225aa8
--- /dev/null
+++ b/kpovmodeler/pmtriangleedit.cpp
@@ -0,0 +1,273 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmtriangleedit.h"
+#include "pmtriangle.h"
+#include "pmvectoredit.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+PMTriangleEdit::PMTriangleEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMTriangleEdit::createTopWidgets( )
+{
+ Base::createTopWidgets( );
+
+ int i;
+
+ QHBoxLayout *hl = new QHBoxLayout( topLayout( ) );
+ m_pSmooth = new QCheckBox( i18n( "Smooth" ), this );
+ hl->addWidget( m_pSmooth );
+ connect( m_pSmooth, SIGNAL( toggled( bool ) ),
+ SLOT( slotSmoothChecked( bool ) ) );
+
+ m_pUVEnabled = new QCheckBox( i18n( "UV vectors" ), this );
+ hl->addWidget( m_pUVEnabled );
+ connect( m_pUVEnabled, SIGNAL( toggled( bool ) ),
+ SLOT( slotUVVectorsChecked( bool ) ) );
+
+ QGridLayout* gl = new QGridLayout( topLayout( ), 9, 2 );
+
+ for( i = 0; i < 3; i++ )
+ {
+ m_pPoint[i] = new PMVectorEdit( "x", "y", "z", this );
+ gl->addWidget( new QLabel( i18n( "Point %1:" ).arg( i+1 ), this ),
+ i * 3, 0 );
+ gl->addWidget( m_pPoint[i], i * 3, 1 );
+ connect( m_pPoint[i], SIGNAL( dataChanged( ) ),
+ SIGNAL( dataChanged( ) ) );
+
+ m_pNormal[i] = new PMVectorEdit( "x", "y", "z", this );
+ m_pNormalLabel[i] = new QLabel( i18n( "Normal %1:" ).arg( i+1 ), this );
+ gl->addWidget( m_pNormalLabel[i], i * 3 + 1, 0 );
+ gl->addWidget( m_pNormal[i], i * 3 + 1, 1 );
+ connect( m_pNormal[i], SIGNAL( dataChanged( ) ),
+ SIGNAL( dataChanged( ) ) );
+
+ m_pUVVector[i] = new PMVectorEdit( "u", "v", this );
+ m_pUVVectorLabel[i] = new QLabel( i18n( "UV vector %1:" ).arg( i+1 ), this );
+ gl->addWidget( m_pUVVectorLabel[i], i * 3 + 2, 0 );
+ gl->addWidget( m_pUVVector[i], i * 3 + 2, 1 );
+ connect( m_pUVVector[i], SIGNAL( dataChanged( ) ),
+ SIGNAL( dataChanged( ) ) );
+ }
+ hl = new QHBoxLayout( topLayout( ) );
+ m_pMirror = new QPushButton( i18n( "Invert Normal Vectors" ), this );
+ hl->addWidget( m_pMirror );
+ hl->addStretch( 1 );
+ connect( m_pMirror, SIGNAL( clicked( ) ), SLOT( slotInvertNormals( ) ) );
+}
+
+void PMTriangleEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Triangle" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMTriangle* ) o;
+ bool smooth = m_pDisplayedObject->isSmoothTriangle( );
+ bool uvVector = m_pDisplayedObject->isUVEnabled( );
+ int i;
+
+ for( i = 0; i < 3; i++ )
+ {
+ m_pPoint[i]->setVector( m_pDisplayedObject->point( i ) );
+ m_pPoint[i]->setReadOnly( readOnly );
+
+ m_pNormal[i]->setVector( m_pDisplayedObject->normal( i ) );
+ m_pNormal[i]->setReadOnly( readOnly );
+
+ m_pUVVector[i]->setVector( m_pDisplayedObject->uvVector( i ) );
+ m_pUVVector[i]->setReadOnly( readOnly );
+
+ m_pSmooth->setChecked( smooth );
+ if( smooth )
+ {
+ m_pNormal[i]->show( );
+ m_pNormalLabel[i]->show( );
+ m_pMirror->show( );
+ }
+ else
+ {
+ m_pNormal[i]->hide( );
+ m_pNormalLabel[i]->hide( );
+ m_pMirror->hide( );
+ }
+
+ m_pUVEnabled->setChecked( uvVector );
+ if( uvVector )
+ {
+ m_pUVVector[i]->show( );
+ m_pUVVectorLabel[i]->show( );
+ }
+ else
+ {
+ m_pUVVector[i]->hide( );
+ m_pUVVectorLabel[i]->hide( );
+ }
+
+ emit sizeChanged( );
+ }
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMTriangleEdit: Can't display object\n";
+}
+
+void PMTriangleEdit::slotSmoothChecked( bool on )
+{
+ int i;
+ for( i = 0; i < 3; i++ )
+ {
+ if( on )
+ {
+ m_pNormal[i]->show( );
+ m_pNormalLabel[i]->show( );
+ m_pMirror->show( );
+ }
+ else
+ {
+ m_pNormal[i]->hide( );
+ m_pNormalLabel[i]->hide( );
+ m_pMirror->hide( );
+ }
+ }
+ emit sizeChanged( );
+ emit dataChanged( );
+}
+
+void PMTriangleEdit::slotUVVectorsChecked( bool on )
+{
+ int i;
+ for( i = 0; i < 3; ++i )
+ {
+ if( on )
+ {
+ m_pUVVector[i]->show( );
+ m_pUVVectorLabel[i]->show( );
+ }
+ else
+ {
+ m_pUVVector[i]->hide( );
+ m_pUVVectorLabel[i]->hide( );
+ }
+ }
+ emit sizeChanged( );
+ emit dataChanged( );
+}
+
+void PMTriangleEdit::slotInvertNormals( )
+{
+ int i;
+ for( i = 0; i < 3; i++ )
+ if( !m_pNormal[i]->isDataValid( ) )
+ return;
+
+ for( i = 0; i < 3; i++ )
+ m_pNormal[i]->setVector( -( m_pNormal[i]->vector( ) ) );
+}
+
+void PMTriangleEdit::saveContents( )
+{
+ int i;
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ for( i = 0; i < 3; i++ )
+ m_pDisplayedObject->setPoint( i, m_pPoint[i]->vector( ) );
+
+ if( m_pSmooth->isChecked( ) )
+ {
+ m_pDisplayedObject->setSmoothTriangle( true );
+ for( i = 0; i < 3; i++ )
+ m_pDisplayedObject->setNormal( i, m_pNormal[i]->vector( ) );
+ }
+ else
+ m_pDisplayedObject->setSmoothTriangle( false );
+
+ if( m_pUVEnabled->isChecked( ) )
+ {
+ m_pDisplayedObject->enableUV( true );
+ for( i = 0; i < 3; ++i )
+ m_pDisplayedObject->setUVVector( i, m_pUVVector[i]->vector( ) );
+ }
+ else
+ m_pDisplayedObject->enableUV( false );
+ }
+}
+
+bool PMTriangleEdit::isDataValid( )
+{
+ int i;
+ for( i = 0; i < 3; i++ )
+ if( !m_pPoint[i]->isDataValid( ) )
+ return false;
+
+ PMVector p0 = m_pPoint[0]->vector( ),
+ p1 = m_pPoint[1]->vector( ),
+ p2 = m_pPoint[2]->vector( );
+
+ if( p0.approxEqual( p1 ) || p1.approxEqual( p2 ) || p0.approxEqual( p2 ) )
+ {
+ KMessageBox::error( this, i18n( "Please enter a valid triangle." ),
+ i18n( "Error" ) );
+ return false;
+ }
+
+ if( m_pSmooth->isChecked( ) )
+ {
+ for( i = 0; i < 3; i++ )
+ if( !m_pNormal[i]->isDataValid( ) )
+ return false;
+
+ PMVector n0 = m_pNormal[0]->vector( ),
+ n1 = m_pNormal[1]->vector( ),
+ n2 = m_pNormal[2]->vector( );
+ PMVector tn = PMVector::cross( p1 - p0, p2 - p0 );
+ double c0 = PMVector::dot( tn, n0 ),
+ c1 = PMVector::dot( tn, n1 ),
+ c2 = PMVector::dot( tn, n2 );
+ if( ( ( c0 * c1 ) < 0 ) || ( ( c0 * c2 ) < 0 ) )
+ {
+ KMessageBox::error( this, i18n( "All normal vectors have to point"
+ " to the same side of the triangle." ),
+ i18n( "Error" ) );
+ return false;
+ }
+ }
+
+ if( m_pUVEnabled->isChecked( ) )
+ {
+ for( i = 0; i < 3; ++i )
+ if( !m_pUVVector[i]->isDataValid( ) )
+ return false;
+ }
+
+ return Base::isDataValid( );
+}
+
+#include "pmtriangleedit.moc"
diff --git a/kpovmodeler/pmtriangleedit.h b/kpovmodeler/pmtriangleedit.h
new file mode 100644
index 00000000..821ad68d
--- /dev/null
+++ b/kpovmodeler/pmtriangleedit.h
@@ -0,0 +1,77 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMTRIANGLEEDIT_H
+#define PMTRIANGLEEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmgraphicalobjectedit.h"
+
+class PMTriangle;
+class PMVectorEdit;
+class QCheckBox;
+class QLabel;
+class QPushButton;
+
+/**
+ * Dialog edit class for @ref PMTriangle
+ */
+class PMTriangleEdit : public PMGraphicalObjectEdit
+{
+ Q_OBJECT
+ typedef PMGraphicalObjectEdit Base;
+public:
+ /**
+ * Creates a PMTriangleEdit with parent and name
+ */
+ PMTriangleEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+private slots:
+ void slotSmoothChecked( bool on );
+ void slotUVVectorsChecked( bool on );
+ void slotInvertNormals( );
+
+private:
+ PMTriangle* m_pDisplayedObject;
+ PMVectorEdit* m_pPoint[3];
+ PMVectorEdit* m_pNormal[3];
+ QLabel* m_pNormalLabel[3];
+ QCheckBox* m_pSmooth;
+ QLabel* m_pUVVectorLabel[3];
+ PMVectorEdit* m_pUVVector[3];
+ QCheckBox* m_pUVEnabled;
+ QPushButton* m_pMirror;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmtruetypecache.cpp b/kpovmodeler/pmtruetypecache.cpp
new file mode 100644
index 00000000..9aa28d89
--- /dev/null
+++ b/kpovmodeler/pmtruetypecache.cpp
@@ -0,0 +1,395 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmtruetypecache.h"
+#include "pmdebug.h"
+
+//***********************************************************************
+// Part with freetype support
+//***********************************************************************
+
+#ifdef HAVE_FREETYPE
+#define PMFREETYPEDEBUG
+
+PMTrueTypeCache* PMTrueTypeCache::s_pInstance = 0;
+KStaticDeleter<PMTrueTypeCache> PMTrueTypeCache::s_staticDeleter;
+
+PMTrueTypeCache::PMTrueTypeCache( )
+ : m_cache( 10, 17, true )
+{
+ bool error = FT_Init_FreeType( &m_library );
+ if( error )
+ kdError( PMArea ) << "Failed to initialize the freetype library\n";
+
+#ifdef PMFREETYPEDEBUG
+ else
+ kdDebug( PMArea ) << "Freetype 2 initialized\n";
+#endif
+
+ m_cache.setAutoDelete( true );
+}
+
+PMTrueTypeCache::~PMTrueTypeCache( )
+{
+ m_cache.clear( );
+ if( m_library )
+ FT_Done_FreeType( m_library );
+}
+
+PMTrueTypeFont* PMTrueTypeCache::lookUp( const QString& file )
+{
+ if( !m_library )
+ return 0;
+ if( file.isEmpty( ) )
+ return 0;
+
+ PMTrueTypeFont* f = m_cache.find( file );
+ if( !f )
+ {
+ FT_Face face;
+ FT_New_Face( m_library, file.latin1( ), 0, &face );
+ f = new PMTrueTypeFont( m_library, face );
+
+#ifdef PMFREETYPEDEBUG
+ if( face )
+ kdDebug( PMArea ) << "Successfully opened font " << file << endl;
+
+ if( f->isValid( ) )
+ m_cache.insert( file, f, 1 );
+ else
+ m_cache.insert( file, f, 0 );
+#endif
+ }
+
+ if( f->isValid( ) )
+ return f;
+
+ return 0;
+}
+
+PMTrueTypeFont* PMTrueTypeCache::font( const QString& file )
+{
+ if( !s_pInstance )
+ s_staticDeleter.setObject( s_pInstance, new PMTrueTypeCache( ) );
+
+ return s_pInstance->lookUp( file );
+}
+
+PMTrueTypeFont::PMTrueTypeFont( FT_Library lib, FT_Face face )
+ : m_cache( 100, 127 )
+{
+ m_library = lib;
+ m_face = face;
+ m_valid = false;
+ m_validChecked = false;
+ m_useKerning = false;
+ if( m_face )
+ {
+ m_useKerning = FT_HAS_KERNING( m_face );
+ // find the correct encoding
+ int i;
+ bool found = false;
+ for( i = 0; ( i < m_face->num_charmaps ) && !found; i++ )
+ if( m_face->charmaps[i]->platform_id == 3 ) // microsoft encodings
+ FT_Set_Charmap( m_face, m_face->charmaps[i] );
+ for( i = 0; ( i < m_face->num_charmaps ) && !found; i++ )
+ if( m_face->charmaps[i]->platform_id == 1 ) // mac encodings
+ FT_Set_Charmap( m_face, m_face->charmaps[i] );
+ }
+
+ m_cache.setAutoDelete( true );
+}
+
+PMTrueTypeFont::~PMTrueTypeFont( )
+{
+ if( m_face )
+ FT_Done_Face( m_face );
+ m_cache.clear( );
+}
+
+bool PMTrueTypeFont::isValid( )
+{
+ if( !m_validChecked )
+ {
+ if( !m_face )
+ m_valid = false;
+ else
+ m_valid = m_face->face_flags & FT_FACE_FLAG_SCALABLE;
+
+#ifdef PMFREETYPEDEBUG
+ if( m_valid )
+ kdDebug( PMArea ) << "Font: " << m_face->family_name
+ << " style " << m_face->style_name
+ << " units_per_EM " << m_face->units_per_EM
+ << " height " << m_face->height << endl;
+#endif
+
+ m_validChecked = true;
+ }
+
+ return m_valid;
+}
+
+PMTrueTypeOutline* PMTrueTypeFont::outline( QChar c )
+{
+ PMTrueTypeOutline* ol = 0;
+
+ if( isValid( ) )
+ {
+ QString str( c );
+ ol = m_cache.find( str );
+ if( !ol )
+ {
+ FT_UInt glyphIndex = findGlyphIndex( c );
+
+ bool error = !glyphIndex;
+ FT_Glyph glyph = 0;
+
+ if( !error )
+ error = FT_Load_Glyph( m_face, glyphIndex,
+ FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE );
+ if( !error )
+ error = FT_Get_Glyph( m_face->glyph, &glyph );
+
+#ifdef PMFREETYPEDEBUG
+ if( error )
+ kdDebug( PMArea ) << "Failed to load glyph for " << c.latin1( ) << "\n";
+ else
+ {
+ FT_Glyph_Metrics* m = &( m_face->glyph->metrics );
+ kdDebug( PMArea ) << "Glyph w: " << m->width << " h: " << m->height
+ << " hbx: " << m->horiBearingX << " hby: " << m->horiBearingY
+ << " ha: " << m->horiAdvance << endl;
+ }
+#endif
+
+ if( !error && glyph && ( glyph->format == ft_glyph_format_outline ) )
+ {
+ FT_OutlineGlyph outlineGlyph = ( FT_OutlineGlyph ) glyph;
+ ol = new PMTrueTypeOutline( outlineGlyph, m_face );
+ }
+
+ if( glyph )
+ FT_Done_Glyph( glyph );
+ if( ol )
+ m_cache.insert( str, ol );
+ }
+ }
+
+ return ol;
+}
+
+double PMTrueTypeFont::kerning( QChar c1, QChar c2 )
+{
+ double k = 0.0;
+ if( m_useKerning && !c1.isNull( ) && !c2.isNull( ) )
+ {
+ FT_UInt gi1 = findGlyphIndex( c1 );
+ FT_UInt gi2 = findGlyphIndex( c2 );
+ if( gi1 && gi2 )
+ {
+ FT_Vector delta;
+ FT_Get_Kerning( m_face, gi1, gi2, ft_kerning_unscaled, &delta );
+ k = ( double ) delta.x / ( double ) m_face->units_per_EM;
+ }
+ }
+
+ return k;
+}
+
+FT_UInt PMTrueTypeFont::findGlyphIndex( QChar c )
+{
+ FT_UInt glyphIndex = 0;
+
+ if( m_face )
+ {
+ // glyphIndex = FT_Get_Char_Index( m_face, c.unicode( ) );
+ // if( !glyphIndex )
+ char ch = c.latin1( );
+ if( !ch )
+ ch = '?';
+ glyphIndex = FT_Get_Char_Index( m_face, ch );
+ }
+ return glyphIndex;
+}
+
+PMTrueTypeOutline::PMTrueTypeOutline( FT_OutlineGlyph glyph, FT_Face face )
+{
+ int n = 0, p = 0, si;
+ FT_Outline* ol = &( glyph->outline );
+
+ PMVector v[4];
+ bool onPoint[4] = { false, false, false, false };
+ bool cubic[4] = { false, false, false, false };
+
+ double dfh = ( double ) face->units_per_EM;
+ double horiBearing = ( double ) face->glyph->metrics.horiBearingX / dfh;
+
+ m_segments = 0;
+ m_contours = ol->n_contours;
+ m_advance = ( double ) face->glyph->metrics.horiAdvance / dfh;
+
+#ifdef PMFREETYPEDEBUG
+
+ /**
+ kdDebug( PMArea ) << "New outline:\n";
+ int dn, dp = 0;
+ for( dn = 0; dn < m_contours; dn++ )
+ {
+ kdDebug( PMArea ) << " Contour " << dn << ":\n";
+ for( ; dp <= ol->contours[dn]; dp++ )
+ {
+ kdDebug( PMArea ) << " <" << ol->points[dp].x << ", "
+ << ol->points[dp].y << ">, "
+ << ( ( ol->tags[dp] & 1 ) == 1 ) << " "
+ << ( ( ol->tags[dp] & 2 ) == 2 ) << endl;
+ }
+ }
+ */
+
+#endif
+
+ for( n = 0; n < m_contours; n++ )
+ {
+ PMSegmentList os;
+ PMSplineSegment s;
+ bool segmentCreated = false;
+ bool quadricSpecialCase = false;
+ bool contourEnd = false;
+ int firstPoint = p;
+
+ si = 0;
+
+ for( ; !contourEnd; p++, si++ )
+ {
+ segmentCreated = false;
+ quadricSpecialCase = false;
+
+ // last point = first point
+ if( p > ol->contours[n] )
+ {
+ p = firstPoint;
+ contourEnd = true;
+ }
+
+ // scale the point
+ v[si] = PMVector( ( double ) ol->points[p].x / dfh - horiBearing,
+ ( double ) ol->points[p].y / dfh );
+ // point type
+ onPoint[si] = ( ( ol->tags[p] & 1 ) == 1 );
+ cubic[si] = ( ( ol->tags[p] & 2 ) == 2 );
+
+ if( onPoint[si] )
+ {
+ switch( si )
+ {
+ case 0:
+ break;
+ case 1:
+ // line
+ s.calculateLinear( v[0], v[1] );
+ segmentCreated = true;
+ break;
+ case 2:
+ // quadric bezier
+ s.calculateQuadricBezier( v[0], v[1], v[2] );
+ segmentCreated = true;
+ break;
+ case 3:
+ // cubic bezier
+ s.calculateBezier( v[0], v[1], v[2], v[3] );
+ segmentCreated = true;
+ break;
+ default:
+ kdError( PMArea ) << "Glyph outline seems incorrect. No on point.\n";
+ si = 0;
+ break;
+ }
+ }
+ else if( ( si == 2 ) && ( !cubic[si] ) )
+ {
+ // two quadric off points
+ // add an on point between them
+ v[3] = v[2];
+ onPoint[3] = onPoint[2];
+ cubic[3] = cubic[2];
+ v[2] = ( v[1] + v[3] ) / 2.0;
+ onPoint[2] = true;
+
+ s.calculateQuadricBezier( v[0], v[1], v[2] );
+ segmentCreated = true;
+ quadricSpecialCase = true;
+ }
+
+ if( segmentCreated )
+ {
+ os.append( s );
+ v[0] = v[si];
+ onPoint[0] = true;
+ si = 0;
+
+ if( quadricSpecialCase )
+ {
+ v[1] = v[3];
+ onPoint[1] = onPoint[3];
+ cubic[1] = onPoint[3];
+ si++;
+ }
+ }
+ }
+
+ m_outline.append( os );
+ m_segments += os.count( );
+ p = ol->contours[n] + 1;
+ }
+}
+
+#else //!HAVE_FREETYPE
+
+//***********************************************************************
+// Part without freetype support
+//***********************************************************************
+
+PMTrueTypeCache::PMTrueTypeCache( )
+{
+}
+
+PMTrueTypeFont* PMTrueTypeCache::font( const QString& )
+{
+ return 0;
+}
+
+PMTrueTypeFont::PMTrueTypeFont( )
+{
+}
+
+bool PMTrueTypeFont::isValid( )
+{
+ return false;
+}
+
+PMTrueTypeOutline* PMTrueTypeFont::outline( QChar )
+{
+ return 0;
+}
+
+double PMTrueTypeFont::kerning( QChar, QChar )
+{
+ return 0;
+}
+
+#endif //HAVE_FREETYPE
diff --git a/kpovmodeler/pmtruetypecache.h b/kpovmodeler/pmtruetypecache.h
new file mode 100644
index 00000000..b305cb1c
--- /dev/null
+++ b/kpovmodeler/pmtruetypecache.h
@@ -0,0 +1,194 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMTRUETYPECACHE_H
+#define PMTRUETYPECACHE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmsplinesegment.h"
+
+#include <qcache.h>
+#include <kstaticdeleter.h>
+
+#ifdef HAVE_FREETYPE
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include FT_OUTLINE_H
+#endif
+
+class PMTrueTypeFont;
+
+/**
+ * Cache for truetype fonts
+ */
+class PMTrueTypeCache
+{
+public:
+ /**
+ * Returns a pointer to the font with file name "file" or 0, if the
+ * font does not exist or is no truetype font
+ *
+ * Returns 0 if freetype is not available.
+ */
+ static PMTrueTypeFont* font( const QString& file );
+
+#ifdef HAVE_FREETYPE
+
+ /**
+ * Destructor
+ */
+ ~PMTrueTypeCache( );
+
+private:
+ static PMTrueTypeCache* s_pInstance;
+ static KStaticDeleter<PMTrueTypeCache> s_staticDeleter;
+
+ /**
+ * Lookup function
+ */
+ PMTrueTypeFont* lookUp( const QString& file );
+
+ QCache<PMTrueTypeFont> m_cache;
+ FT_Library m_library;
+
+#endif //HAVE_FREETYPE
+
+private:
+ /**
+ * Standard constructor
+ */
+ PMTrueTypeCache( );
+};
+
+/**
+ * Class that represents a truetype character outline
+ */
+class PMTrueTypeOutline
+{
+public:
+#ifdef HAVE_FREETYPE
+ /**
+ * Constructor that generates the outline for the glyph.
+ * The outline is scaled to match the font height.
+ */
+ PMTrueTypeOutline( FT_OutlineGlyph glyph, FT_Face face );
+#else
+ /**
+ * Standard constructor.
+ *
+ * Don't use this constructor. It is only added as dummy if freetype
+ * is not installed.
+ */
+ PMTrueTypeOutline( )
+ {
+ m_contours = 0;
+ m_segments = 0;
+ m_advance = 0;
+ }
+#endif
+ /**
+ * Returns the outline
+ */
+ const PMSegmentListList& outline( ) const { return m_outline; }
+ /**
+ * Returns the number of contours
+ */
+ int contours( ) const { return m_contours; }
+ /**
+ * Returns the sum of the number of segments for all contours
+ */
+ int segments( ) const { return m_segments; }
+ /**
+ * Returns the offset for the next character
+ */
+ double advance( ) const { return m_advance; }
+
+ PMSegmentListList m_outline;
+ int m_contours;
+ int m_segments;
+ double m_advance;
+};
+
+/**
+ * Class that represents a truetype font.
+ *
+ * This class caches the glyph outlines.
+ */
+class PMTrueTypeFont
+{
+public:
+ /**
+ * Returns the outline for the character
+ *
+ * Returns 0 if there is no glyph for the character or the font is
+ * not a valid, scalable true type font.
+ */
+ PMTrueTypeOutline* outline( QChar c );
+ /**
+ * Returns true if the font is a valid, scalable true type font
+ */
+ bool isValid( );
+ /**
+ * Returns the kerning offset for the two characters
+ */
+ double kerning( QChar c1, QChar c2 );
+
+#ifdef HAVE_FREETYPE
+
+public:
+ /**
+ * Creates a true type font
+ */
+ PMTrueTypeFont( FT_Library lib, FT_Face face );
+ /**
+ * Deletes the true type font
+ */
+ ~PMTrueTypeFont( );
+
+private:
+ FT_UInt findGlyphIndex( QChar c );
+
+ FT_Library m_library;
+ FT_Face m_face;
+
+ bool m_valid;
+ bool m_validChecked;
+ bool m_useKerning;
+
+ QCache<PMTrueTypeOutline> m_cache;
+
+#else //!HAVE_FREETYPE
+
+public:
+ /**
+ * Standard constructor.
+ *
+ * Don't use this constructor. It is only added as dummy if freetype
+ * is not installed.
+ */
+ PMTrueTypeFont( );
+
+#endif //HAVE_FREETYPE
+
+};
+
+#endif
diff --git a/kpovmodeler/pmunknownview.cpp b/kpovmodeler/pmunknownview.cpp
new file mode 100644
index 00000000..b6067c02
--- /dev/null
+++ b/kpovmodeler/pmunknownview.cpp
@@ -0,0 +1,37 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmunknownview.h"
+#include <klocale.h>
+#include <qlayout.h>
+
+PMUnknownView::PMUnknownView( const QString& viewType,
+ QWidget* parent, const char* name )
+ : PMViewBase( parent, name )
+{
+ QHBoxLayout* hl = new QHBoxLayout( this );
+ QLabel* l;
+ l = new QLabel( i18n( "Unknown view type \"%1\"" ).arg( viewType ), this );
+ l->setAlignment( Qt::AlignCenter );
+ hl->addWidget( l );
+ m_viewType = viewType;
+}
+
+QString PMUnknownView::description( ) const
+{
+ return i18n( "Unknown" );
+}
diff --git a/kpovmodeler/pmunknownview.h b/kpovmodeler/pmunknownview.h
new file mode 100644
index 00000000..b8921dd6
--- /dev/null
+++ b/kpovmodeler/pmunknownview.h
@@ -0,0 +1,47 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMUNKNOWNVIEW_H
+#define PMUNKNOWNVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qlabel.h>
+#include "pmviewbase.h"
+
+/**
+ * Helper view for unknown view types
+ */
+class PMUnknownView : public PMViewBase
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMUnknownView( const QString& viewType, QWidget* parent,
+ const char* name = 0 );
+ /** */
+ virtual QString viewType( ) const { return m_viewType; }
+ /** */
+ virtual QString description( ) const;
+private:
+ QString m_viewType;
+};
+
+#endif
diff --git a/kpovmodeler/pmvalue.h b/kpovmodeler/pmvalue.h
new file mode 100644
index 00000000..3d2ecb02
--- /dev/null
+++ b/kpovmodeler/pmvalue.h
@@ -0,0 +1,102 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMVALUE_H
+#define PMVALUE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmvector.h"
+
+enum PMValueType { PMVFloat, PMVVector, PMVColor };
+
+/**
+ * Helper class for parsing numeric expressions because wo don't know
+ * at begin of an expression, which type it is.
+ *
+ * Colors are stored as 5D vectors.
+ */
+
+class PMValue
+{
+public:
+ /**
+ * Creates a PMValue with type PMVFloat and value 0.0
+ */
+ PMValue( ) : m_v( 0 ) { m_d = 0.0; m_type = PMVFloat; }
+ /**
+ * Copy constructor
+ */
+ PMValue( const PMValue& v )
+ {
+ m_type = v.m_type;
+ m_d = v.m_d;
+ m_v = v.m_v;
+ }
+ /**
+ * Returns the type of the value.
+ * Values can be PMVFloat, PMVVector, PMVColor
+ */
+ PMValueType type( ) const { return m_type; }
+
+ /**
+ * Sets the float value and sets the type to PMVFloat
+ */
+ void setFloat( const double d ) { m_d = d; m_type = PMVFloat; }
+ /**
+ * Sets the vector value and sets the type to PMVVector
+ */
+ void setVector( const PMVector& v ) { m_v = v; m_type = PMVVector; }
+ /**
+ * Sets the color value and sets the type to PMVColor
+ */
+ void setColor( const PMVector& v ) { m_v = v; m_type = PMVColor; }
+
+ /**
+ * Returns the float value
+ */
+ double floatValue( ) const { return m_d; }
+ /**
+ * Returns the vector value
+ */
+ PMVector vector( ) const { return m_v; }
+ /**
+ * Returns the color value
+ */
+ PMVector color( ) const { return m_v; }
+ /**
+ * Assigns v to the value
+ */
+ PMValue& operator= ( const PMValue& v )
+ {
+ m_type = v.m_type;
+ m_d = v.m_d;
+ m_v = v.m_v;
+ return *this;
+ }
+
+private:
+ PMValueType m_type;
+ double m_d;
+ PMVector m_v;
+};
+
+#endif
diff --git a/kpovmodeler/pmvariant.cpp b/kpovmodeler/pmvariant.cpp
new file mode 100644
index 00000000..d6b5384c
--- /dev/null
+++ b/kpovmodeler/pmvariant.cpp
@@ -0,0 +1,920 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmvariant.h"
+
+#include <qstring.h>
+#include "pmcolor.h"
+#include "pmvector.h"
+#include "pmdebug.h"
+
+inline const char* dcopTypeName( const PMVariant& ) { return "PMVariant"; }
+
+PMVariant::PMVariant( )
+{
+ m_dataType = PMVariant::None;
+ m_pData = 0;
+}
+
+PMVariant::PMVariant( int data )
+{
+ m_dataType = PMVariant::Integer;
+ m_pData = new int( data );
+}
+
+PMVariant::PMVariant( unsigned int data )
+{
+ m_dataType = PMVariant::Unsigned;
+ m_pData = new unsigned( data );
+}
+
+PMVariant::PMVariant( double data )
+{
+ m_dataType = PMVariant::Double;
+ m_pData = new double( data );
+}
+
+
+PMVariant::PMVariant( bool data )
+{
+ m_dataType = PMVariant::Bool;
+ m_pData = new bool( data );
+}
+
+PMVariant::PMVariant( PMThreeState data )
+{
+ m_dataType = PMVariant::ThreeState;
+ m_pData = new PMThreeState( data );
+}
+
+
+PMVariant::PMVariant( const QString& data )
+{
+ m_dataType = PMVariant::String;
+ m_pData = new QString( data );
+}
+
+PMVariant::PMVariant( const PMVector& data )
+{
+ m_dataType = PMVariant::Vector;
+ m_pData = new PMVector( data );
+}
+
+PMVariant::PMVariant( const PMColor& data )
+{
+ m_dataType = PMVariant::Color;
+ m_pData = new PMColor( data );
+}
+
+PMVariant::PMVariant( PMObject* obj )
+{
+ m_dataType = PMVariant::ObjectPointer;
+ m_pData = ( void* ) obj;
+}
+
+PMVariant::PMVariant( const PMVariant& v )
+{
+ m_pData = 0;
+ m_dataType = PMVariant::None;
+
+ switch( v.m_dataType )
+ {
+ case PMVariant::Integer:
+ setInt( *( ( int* ) v.m_pData ) );
+ break;
+ case PMVariant::Unsigned:
+ setUnsigned( *( ( unsigned* ) v.m_pData ) );
+ break;
+ case PMVariant::Double:
+ setDouble( *( ( double* ) v.m_pData ) );
+ break;
+ case PMVariant::Bool:
+ setBool( *( ( bool* ) v.m_pData ) );
+ break;
+ case PMVariant::ThreeState:
+ setThreeState( *( ( PMThreeState* ) v.m_pData ) );
+ break;
+ case PMVariant::String:
+ setString( *( ( QString* ) v.m_pData ) );
+ break;
+ case PMVariant::Vector:
+ setVector( *( ( PMVector* ) v.m_pData ) );
+ break;
+ case PMVariant::Color:
+ setColor( *( ( PMColor* ) v.m_pData ) );
+ break;
+ case PMVariant::ObjectPointer:
+ setObject( ( PMObject* ) v.m_pData );
+ break;
+ case PMVariant::None:
+ break;
+ }
+}
+
+PMVariant& PMVariant::operator= ( const PMVariant& v )
+{
+ switch( v.m_dataType )
+ {
+ case PMVariant::Integer:
+ setInt( *( ( int* ) v.m_pData ) );
+ break;
+ case PMVariant::Unsigned:
+ setUnsigned( *( ( unsigned* ) v.m_pData ) );
+ break;
+ case PMVariant::Double:
+ setDouble( *( ( double* ) v.m_pData ) );
+ break;
+ case PMVariant::Bool:
+ setBool( *( ( bool* ) v.m_pData ) );
+ break;
+ case PMVariant::ThreeState:
+ setThreeState( *( ( PMThreeState* ) v.m_pData ) );
+ break;
+ case PMVariant::String:
+ setString( *( ( QString* ) v.m_pData ) );
+ break;
+ case PMVariant::Vector:
+ setVector( *( ( PMVector* ) v.m_pData ) );
+ break;
+ case PMVariant::Color:
+ setColor( *( ( PMColor* ) v.m_pData ) );
+ break;
+ case PMVariant::ObjectPointer:
+ setObject( ( PMObject* ) v.m_pData );
+ break;
+ case PMVariant::None:
+ break;
+ }
+
+ return *this;
+}
+
+PMVariant::~PMVariant( )
+{
+ clear( );
+}
+
+void PMVariant::clear( )
+{
+ switch( m_dataType )
+ {
+ case PMVariant::Integer:
+ delete( ( int* ) m_pData );
+ break;
+ case PMVariant::Unsigned:
+ delete( ( unsigned* ) m_pData );
+ break;
+ case PMVariant::Double:
+ delete( ( double* ) m_pData );
+ break;
+ case PMVariant::Bool:
+ delete( ( bool* ) m_pData );
+ break;
+ case PMVariant::ThreeState:
+ delete( ( PMThreeState* ) m_pData );
+ break;
+ case PMVariant::String:
+ delete( ( QString* ) m_pData );
+ break;
+ case PMVariant::Vector:
+ delete( ( PMVector* ) m_pData );
+ break;
+ case PMVariant::Color:
+ delete( ( PMColor* ) m_pData );
+ break;
+ case PMVariant::ObjectPointer:
+ // delete nothing
+ break;
+ case PMVariant::None:
+ break;
+ }
+
+ m_dataType = PMVariant::None;
+ m_pData = 0;
+}
+
+void PMVariant::setInt( const int data )
+{
+ if( m_dataType != PMVariant::Integer )
+ {
+ clear( );
+ m_pData = new int( data );
+ m_dataType = PMVariant::Integer;
+ }
+ else
+ *( ( int* ) m_pData ) = data;
+}
+
+void PMVariant::setUnsigned( const unsigned int data )
+{
+ if( m_dataType != PMVariant::Unsigned )
+ {
+ clear( );
+ m_pData = new unsigned( data );
+ m_dataType = PMVariant::Unsigned;
+ }
+ else
+ *( ( unsigned* ) m_pData ) = data;
+}
+
+void PMVariant::setDouble( const double data )
+{
+ if( m_dataType != PMVariant::Double )
+ {
+ clear( );
+ m_pData = new double( data );
+ m_dataType = PMVariant::Double;
+ }
+ else
+ *( ( double* ) m_pData ) = data;
+}
+
+void PMVariant::setBool( const bool data )
+{
+ if( m_dataType != PMVariant::Bool )
+ {
+ clear( );
+ m_pData = new bool( data );
+ m_dataType = PMVariant::Bool;
+ }
+ else
+ *( ( bool* ) m_pData ) = data;
+}
+
+void PMVariant::setThreeState( const PMThreeState data )
+{
+ if( m_dataType != PMVariant::ThreeState )
+ {
+ clear( );
+ m_pData = new PMThreeState( data );
+ m_dataType = PMVariant::ThreeState;
+ }
+ else
+ *( ( PMThreeState* ) m_pData ) = data;
+}
+
+void PMVariant::setString( const QString& data )
+{
+ if( m_dataType != PMVariant::String )
+ {
+ clear( );
+ m_pData = new QString( data );
+ m_dataType = PMVariant::String;
+ }
+ else
+ *( ( QString* ) m_pData ) = data;
+}
+
+void PMVariant::setVector( const PMVector& data )
+{
+ if( m_dataType != PMVariant::Vector )
+ {
+ clear( );
+ m_pData = new PMVector( data );
+ m_dataType = PMVariant::Vector;
+ }
+ else
+ *( ( PMVector* ) m_pData ) = data;
+}
+
+void PMVariant::setColor( const PMColor& data )
+{
+ if( m_dataType != PMVariant::Color )
+ {
+ clear( );
+ m_pData = new PMColor( data );
+ m_dataType = PMVariant::Color;
+ }
+ else
+ *( ( PMColor* ) m_pData ) = data;
+}
+
+void PMVariant::setObject( PMObject* obj )
+{
+ if( m_dataType != PMVariant::ObjectPointer )
+ {
+ clear( );
+ m_pData = obj;
+ m_dataType = PMVariant::ObjectPointer;
+ }
+ else
+ m_pData = obj;
+}
+
+int PMVariant::intData( ) const
+{
+ if( m_dataType == PMVariant::Integer )
+ return *( ( int* ) m_pData );
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return 0;
+}
+
+int PMVariant::unsignedData( ) const
+{
+ if( m_dataType == PMVariant::Unsigned )
+ return *( ( unsigned* ) m_pData );
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return 0;
+}
+
+double PMVariant::doubleData( ) const
+{
+ if( m_dataType == PMVariant::Double )
+ return *( ( double* ) m_pData );
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return 0;
+}
+
+bool PMVariant::boolData( ) const
+{
+ if( m_dataType == PMVariant::Bool )
+ return *( ( bool* ) m_pData );
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return false;
+}
+
+PMThreeState PMVariant::threeStateData( ) const
+{
+ if( m_dataType == PMVariant::ThreeState )
+ return *( ( PMThreeState* ) m_pData );
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return PMUnspecified;
+}
+
+QString PMVariant::stringData( ) const
+{
+ if( m_dataType == PMVariant::String )
+ return *( ( QString* ) m_pData );
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return QString::null;
+}
+
+PMVector PMVariant::vectorData( ) const
+{
+ if( m_dataType == PMVariant::Vector )
+ return *( ( PMVector* ) m_pData );
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return PMVector( );
+}
+
+PMColor PMVariant::colorData( ) const
+{
+ if( m_dataType == PMVariant::Color )
+ return *( ( PMColor* ) m_pData );
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return PMColor( );
+}
+
+PMObject* PMVariant::objectData( ) const
+{
+ if( m_dataType == PMVariant::ObjectPointer )
+ return ( PMObject* ) m_pData;
+ kdError( PMArea ) << "Wrong type in PMVariant get function\n";
+ return 0;
+}
+
+bool PMVariant::convertTo( PMVariant::PMVariantDataType t )
+{
+ bool success = true;
+
+ switch( m_dataType )
+ {
+ case PMVariant::Integer:
+ {
+ int data = *( ( int* ) m_pData );
+
+ switch( t )
+ {
+ case PMVariant::Integer:
+ break;
+ case PMVariant::Unsigned:
+ setUnsigned( ( unsigned ) data );
+ break;
+ case PMVariant::Double:
+ setDouble( ( double ) data );
+ break;
+ case PMVariant::Bool:
+ setBool( ( bool ) data );
+ break;
+ case PMVariant::ThreeState:
+ success = false;
+ break;
+ case PMVariant::String:
+ {
+ QString tmp;
+ tmp.setNum( data );
+ setString( tmp );
+ break;
+ }
+ case PMVariant::Vector:
+ success = false;
+ break;
+ case PMVariant::Color:
+ success = false;
+ break;
+ case PMVariant::ObjectPointer:
+ success = false;
+ break;
+ case PMVariant::None:
+ success = false;
+ break;
+ }
+ break;
+ }
+
+ case PMVariant::Unsigned:
+ {
+ unsigned data = *( ( unsigned* ) m_pData );
+
+ switch( t )
+ {
+ case PMVariant::Integer:
+ setUnsigned( ( int ) data );
+ break;
+ case PMVariant::Unsigned:
+ break;
+ case PMVariant::Double:
+ setDouble( ( double ) data );
+ break;
+ case PMVariant::Bool:
+ setBool( ( bool ) data );
+ break;
+ case PMVariant::ThreeState:
+ success = false;
+ break;
+ case PMVariant::String:
+ {
+ QString tmp;
+ tmp.setNum( data );
+ setString( tmp );
+ break;
+ }
+ case PMVariant::Vector:
+ success = false;
+ break;
+ case PMVariant::Color:
+ success = false;
+ break;
+ case PMVariant::ObjectPointer:
+ success = false;
+ break;
+ case PMVariant::None:
+ success = false;
+ break;
+ }
+ break;
+ }
+
+ case PMVariant::Double:
+ {
+ double data = *( ( double* ) m_pData );
+
+ switch( t )
+ {
+ case PMVariant::Integer:
+ setInt( ( int ) data );
+ break;
+ case PMVariant::Unsigned:
+ setUnsigned( ( unsigned ) data );
+ break;
+ case PMVariant::Double:
+ break;
+ case PMVariant::Bool:
+ setBool( ( bool ) data );
+ break;
+ case PMVariant::ThreeState:
+ success = false;
+ break;
+ case PMVariant::String:
+ {
+ QString tmp;
+ tmp.setNum( data );
+ setString( tmp );
+ break;
+ }
+ case PMVariant::Vector:
+ success = false;
+ break;
+ case PMVariant::Color:
+ success = false;
+ break;
+ case PMVariant::ObjectPointer:
+ success = false;
+ break;
+ case PMVariant::None:
+ success = false;
+ break;
+ }
+ break;
+ }
+
+ case PMVariant::Bool:
+ {
+ bool data = *( ( bool* ) m_pData );
+
+ switch( t )
+ {
+ case PMVariant::Integer:
+ setInt( ( int ) data );
+ break;
+ case PMVariant::Unsigned:
+ setUnsigned( ( unsigned ) data );
+ break;
+ case PMVariant::Double:
+ setDouble( ( double ) data );
+ break;
+ case PMVariant::Bool:
+ break;
+ case PMVariant::ThreeState:
+ if( data )
+ setThreeState( PMTrue );
+ else
+ setThreeState( PMFalse );
+ break;
+ case PMVariant::String:
+ if( data )
+ setString( QString( "true" ) );
+ else
+ setString( QString( "false" ) );
+ break;
+ case PMVariant::Vector:
+ success = false;
+ break;
+ case PMVariant::Color:
+ success = false;
+ break;
+ case PMVariant::ObjectPointer:
+ success = false;
+ break;
+ case PMVariant::None:
+ success = false;
+ break;
+ }
+ break;
+ }
+
+ case PMVariant::ThreeState:
+ {
+ PMThreeState data = *( ( PMThreeState* ) m_pData );
+
+ switch( t )
+ {
+ case PMVariant::Integer:
+ success = false;
+ break;
+ case PMVariant::Unsigned:
+ success = false;
+ break;
+ case PMVariant::Double:
+ success = false;
+ break;
+ case PMVariant::Bool:
+ if( data == PMTrue )
+ setBool( true );
+ else if( data == PMFalse )
+ setBool( false );
+ else
+ success = false;
+ break;
+ case PMVariant::ThreeState:
+ break;
+ case PMVariant::String:
+ if( data == PMTrue )
+ setString( QString( "true" ) );
+ else if( data == PMFalse )
+ setString( QString( "false" ) );
+ else
+ setString( QString( "unspecified" ) );
+ break;
+ case PMVariant::Vector:
+ success = false;
+ break;
+ case PMVariant::Color:
+ success = false;
+ break;
+ case PMVariant::ObjectPointer:
+ success = false;
+ break;
+ case PMVariant::None:
+ success = false;
+ break;
+ }
+ break;
+ }
+
+ case PMVariant::String:
+ {
+ QString data = *( ( QString* ) m_pData );
+
+ switch( t )
+ {
+ case PMVariant::Integer:
+ {
+ int i = data.toInt( &success );
+ if( success )
+ setInt( i );
+ break;
+ }
+ case PMVariant::Unsigned:
+ {
+ unsigned u = data.toUInt( &success );
+ if( success )
+ setUnsigned( u );
+ break;
+ }
+ case PMVariant::Double:
+ {
+ double d = data.toDouble( &success );
+ if( success )
+ setDouble( d );
+ break;
+ }
+ case PMVariant::Bool:
+ if( data == "true" || data == "on" || data == "yes" )
+ setBool( true );
+ else if( data == "false" || data == "off" || data == "no" )
+ setBool( false );
+ else
+ success = false;
+ break;
+ case PMVariant::ThreeState:
+ if( data == "true" || data == "on" || data == "yes" )
+ setThreeState( PMTrue );
+ else if( data == "false" || data == "off" || data == "no" )
+ setThreeState( PMFalse );
+ else if( data == "unspecified" )
+ setThreeState( PMUnspecified );
+ else
+ success = false;
+ break;
+ case PMVariant::String:
+ break;
+ case PMVariant::Vector:
+ success = false;
+ break;
+ case PMVariant::Color:
+ success = false;
+ break;
+ case PMVariant::ObjectPointer:
+ success = false;
+ break;
+ case PMVariant::None:
+ success = false;
+ break;
+ }
+ break;
+ }
+
+ case PMVariant::Vector:
+ {
+ switch( t )
+ {
+ case PMVariant::Vector:
+ break;
+ case PMVariant::Color:
+ {
+ PMVector v = *( ( PMVector* ) m_pData );
+ if( v.size( ) == 5 )
+ setColor( v );
+ else
+ success = false;
+ break;
+ }
+ default:
+ success = false;
+ break;
+ }
+ break;
+ }
+
+ case PMVariant::Color:
+ {
+ switch( t )
+ {
+ case PMVariant::Vector:
+ {
+ PMColor c = *( ( PMColor* ) m_pData );
+ PMVector v( 5 );
+ v[0] = c.red( );
+ v[1] = c.green( );
+ v[2] = c.blue( );
+ v[3] = c.filter( );
+ v[4] = c.transmit( );
+ setVector( v );
+ break;
+ }
+ case PMVariant::Color:
+ break;
+ default:
+ success = false;
+ break;
+ }
+ break;
+ }
+
+ case PMVariant::ObjectPointer:
+ success = ( t == PMVariant::ObjectPointer );
+ break;
+
+ case PMVariant::None:
+ success = ( t == PMVariant::None );
+ break;
+ }
+
+ return success;
+}
+
+QString PMVariant::asString( ) const
+{
+ QString tmp;
+
+ switch( m_dataType )
+ {
+ case PMVariant::Integer:
+ {
+ int data = *( ( int* ) m_pData );
+
+ tmp.setNum( data );
+ break;
+ }
+ case PMVariant::Unsigned:
+ {
+ unsigned data = *( ( unsigned* ) m_pData );
+
+ tmp.setNum( data );
+ break;
+ }
+ case PMVariant::Double:
+ {
+ double data = *( ( double* ) m_pData );
+
+ tmp.setNum( data );
+ break;
+ }
+ case PMVariant::Bool:
+ {
+ bool data = *( ( bool* ) m_pData );
+
+ if( data )
+ tmp = "true";
+ else
+ tmp = "false";
+ break;
+ }
+ case PMVariant::ThreeState:
+ {
+ PMThreeState data = *( ( PMThreeState* ) m_pData );
+
+ if( data == PMTrue )
+ tmp = "true";
+ else if( data == PMFalse )
+ tmp = "false";
+ else
+ tmp = "unspecified";
+ break;
+ }
+ case PMVariant::String:
+ {
+ tmp = *( ( QString* ) m_pData );
+ break;
+ }
+ case PMVariant::Vector:
+ {
+ PMVector v = *( ( PMVector* ) m_pData );
+ tmp = v.serializeXML( );
+ break;
+ }
+
+ case PMVariant::Color:
+ {
+ PMColor c = *( ( PMColor* ) m_pData );
+ tmp = c.serializeXML( );
+ break;
+ }
+
+ case PMVariant::ObjectPointer:
+ tmp = "<object_pointer>";
+ break;
+
+ case PMVariant::None:
+ tmp = "<none>";
+ break;
+
+ default:
+ tmp = "<unknown>";
+ break;
+ }
+
+ return tmp;
+}
+
+bool PMVariant::fromString( const PMVariant::PMVariantDataType t, const QString& value )
+{
+ bool success;
+
+ switch( t )
+ {
+ case PMVariant::Integer:
+ {
+ int i = value.toInt( &success );
+ if( success )
+ setInt( i );
+ break;
+ }
+ case PMVariant::Unsigned:
+ {
+ unsigned u = value.toUInt( &success );
+ if( success )
+ setUnsigned( u );
+ break;
+ }
+ case PMVariant::Double:
+ {
+ double d = value.toDouble( &success );
+ if( success )
+ setDouble( d );
+ break;
+ }
+ case PMVariant::Bool:
+ success = true;
+ if( value == "true" || value == "on" || value == "yes" )
+ setBool( true );
+ else if( value == "false" || value == "off" || value == "no" )
+ setBool( false );
+ else
+ success = false;
+ break;
+ case PMVariant::ThreeState:
+ success = true; // Assume success, set to false if we fail.
+ if( value == "true" || value == "on" || value == "yes" )
+ setThreeState( PMTrue );
+ else if( value == "false" || value == "off" || value == "no" )
+ setThreeState( PMFalse );
+ else if( value == "unspecified" )
+ setThreeState( PMUnspecified );
+ else
+ success = false;
+ break;
+ case PMVariant::String:
+ setString( value );
+ success = true;
+ break;
+ case PMVariant::Vector:
+ {
+ PMVector v;
+ v.loadXML( value );
+ setVector( v );
+ success = true;
+ break;
+ }
+ case PMVariant::Color:
+ {
+ PMColor c;
+ c.loadXML( value );
+ setColor( c );
+ success = true;
+ break;
+ }
+ default:
+ success = false;
+ }
+ return success;
+}
+
+QDataStream& operator<<( QDataStream& stream, const PMVariant& value )
+{
+ stream << (Q_INT8)value.dataType( );
+ stream << value.asString( );
+
+ return stream;
+}
+
+QDataStream& operator>>( QDataStream& stream, PMVariant& value )
+{
+ Q_INT8 type;
+ PMVariant::PMVariantDataType dataType;
+ QString str;
+
+ stream >> type;
+ dataType = (PMVariant::PMVariantDataType)type;
+
+ stream >> str;
+
+ value.fromString(dataType, str);
+
+ return stream;
+}
diff --git a/kpovmodeler/pmvariant.h b/kpovmodeler/pmvariant.h
new file mode 100644
index 00000000..01519a01
--- /dev/null
+++ b/kpovmodeler/pmvariant.h
@@ -0,0 +1,221 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMVARIANT_H
+#define PMVARIANT_H
+
+#include <qstring.h>
+#include "pmcolor.h"
+#include "pmvector.h"
+#include "pmthreestate.h"
+
+class PMObject;
+
+/**
+ * Variant class for KPovModeler.
+ *
+ * Can store and convert: int, unsigned int, double, bool,
+ * PMThreeState, QString, PMVector, PMColor, PMObject*.
+ *
+ * Enums are stored as QString.
+ *
+ * The variant can store one type at a time. You can try to convert
+ * the type with the convertTo* methods. These will return bool on success.
+ * If the variant could not be converted, the old type and value
+ * did not change.
+ */
+
+class PMVariant
+{
+public:
+ /**
+ * Type of stored data
+ */
+ enum PMVariantDataType { Integer, Unsigned, Double, Bool,
+ ThreeState, String, Vector, Color,
+ ObjectPointer, None };
+ /**
+ * Creates an empty variant object
+ */
+ PMVariant( );
+ /**
+ * Stores an integer
+ */
+ PMVariant( int data );
+ /**
+ * Stores an unsigned integer
+ */
+ PMVariant( unsigned int data );
+ /**
+ * Stores a double
+ */
+ PMVariant( double data );
+ /**
+ * Stores a boolean
+ */
+ PMVariant( bool data );
+ /**
+ * Stores a @ref PMThreeState
+ */
+ PMVariant( PMThreeState data );
+ /**
+ * Stores a string
+ */
+ PMVariant( const QString& data );
+ /**
+ * Stores a @ref PMVector
+ */
+ PMVariant( const PMVector& data );
+ /**
+ * Stores a @ref PMColor
+ */
+ PMVariant( const PMColor& data );
+ /**
+ * Stores a pointer to a PMObject
+ */
+ PMVariant( PMObject* obj );
+ /**
+ * Copy constructor
+ */
+ PMVariant( const PMVariant& v );
+ /**
+ * Deletes the variant
+ */
+ ~PMVariant( );
+
+ /**
+ * Assignment operator
+ */
+ PMVariant& operator= ( const PMVariant& v );
+
+ /**
+ * Returns true if no data is stored
+ */
+ bool isNull( ) const { return !m_pData; }
+
+ /**
+ * Sets the integer value
+ */
+ void setInt( int data );
+ /**
+ * Sets the unsigned value
+ */
+ void setUnsigned( unsigned int data );
+ /**
+ * Sets the double value
+ */
+ void setDouble( double data );
+ /**
+ * Sets the boolean value
+ */
+ void setBool( bool data );
+ /**
+ * Sets the PMThreeState value
+ */
+ void setThreeState( PMThreeState data );
+ /**
+ * Sets the string data
+ */
+ void setString( const QString& data );
+ /**
+ * Sets the vector data
+ */
+ void setVector( const PMVector& data );
+ /**
+ * Sets the color data
+ */
+ void setColor( const PMColor& data );
+ /**
+ * Sets the object pointer
+ */
+ void setObject( PMObject* o );
+
+ /**
+ * Returns the integer value. Data type has to be Integer!
+ */
+ int intData( ) const;
+ /**
+ * Returns the unsigned value. Data type has to be Unsigned!
+ */
+ int unsignedData( ) const;
+ /**
+ * Returns the double value. Data type has to be Double!
+ */
+ double doubleData( ) const;
+ /**
+ * Returns the boolean value. Data type has to be Bool!
+ */
+ bool boolData( ) const;
+ /**
+ * Returns the PMThreeState value. Data type has to be ThreeState!
+ */
+ PMThreeState threeStateData( ) const;
+ /**
+ * Returns the string data. Data type has to be String!
+ */
+ QString stringData( ) const;
+ /**
+ * Returns the vector data. Data type has to be Vector!
+ */
+ PMVector vectorData( ) const;
+ /**
+ * Returns the color data. Data type has to be Color!
+ */
+ PMColor colorData( ) const;
+ /**
+ * Returns the object pointer. Data type has to be ObjectPointer!
+ */
+ PMObject* objectData( ) const;
+
+ /**
+ * Converts the variant to an integer. Returns true if possible
+ */
+ bool convertTo( PMVariantDataType t );
+
+ /**
+ * Returns the type of the stored data
+ */
+ PMVariantDataType dataType( ) const { return m_dataType; }
+
+ /**
+ * Returns the value of the stored data in string format
+ */
+ QString asString( ) const;
+ /**
+ * Sets the value of the variant based on the string
+ */
+ bool fromString( const PMVariant::PMVariantDataType t, const QString& value );
+private:
+ void clear( );
+
+ /**
+ * a pointer to the stored data
+ */
+ void* m_pData;
+ /**
+ * Type of the data
+ */
+ PMVariantDataType m_dataType;
+};
+
+// Streaming operators for PMVariant
+QDataStream& operator<<( QDataStream& stream, const PMVariant& value );
+QDataStream& operator>>( QDataStream& stream, PMVariant& value );
+
+
+#endif
diff --git a/kpovmodeler/pmvector.cpp b/kpovmodeler/pmvector.cpp
new file mode 100644
index 00000000..035f0d2b
--- /dev/null
+++ b/kpovmodeler/pmvector.cpp
@@ -0,0 +1,593 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmvector.h"
+#include "pmmath.h"
+#include "pmmatrix.h"
+#include "pmdebug.h"
+
+#include <qtextstream.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+double PMVector::s_dummy = 0;
+
+double& PMVector::operator[] ( int index )
+{
+ if( ( index >= 0 ) && ( index < ( signed ) m_size ) )
+ return m_coord[index];
+ kdError( PMArea ) << "Bad index in PMVector operator []\n";
+ return s_dummy;
+}
+
+const double& PMVector::operator[] ( int index ) const
+{
+ if( ( index >= 0 ) && ( index < ( signed ) m_size ) )
+ return m_coord[index];
+ kdError( PMArea ) << "Bad index in PMVector operator []\n";
+ return s_dummy;
+}
+
+void PMVector::allocateMemory( unsigned int size )
+{
+ m_size = size;
+
+ if( m_size == 0 )
+ m_coord = 0;
+ else
+ m_coord = ( double* ) malloc( sizeof( double ) * m_size );
+}
+
+PMVector::PMVector( const PMVector& v )
+{
+ unsigned int i;
+ allocateMemory( v.m_size );
+
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] = v.m_coord[i];
+}
+
+PMVector::PMVector( )
+{
+ unsigned int i;
+
+ allocateMemory( 3 );
+
+ for( i = 0; i < 3; i++ )
+ m_coord[i] = 0.0;
+}
+
+PMVector::PMVector( unsigned int s )
+{
+ unsigned int i;
+
+ allocateMemory( s );
+
+ for( i = 0; i < s; i++ )
+ m_coord[i] = 0.0;
+}
+
+PMVector::PMVector( const double x, const double y )
+{
+ allocateMemory( 2 );
+
+ m_coord[0] = x;
+ m_coord[1] = y;
+}
+
+PMVector::PMVector( const double x, const double y, const double z )
+{
+ allocateMemory( 3 );
+
+ m_coord[0] = x;
+ m_coord[1] = y;
+ m_coord[2] = z;
+}
+
+PMVector::PMVector( const double x, const double y, const double z,
+ const double t )
+{
+ allocateMemory( 4 );
+
+ m_coord[0] = x;
+ m_coord[1] = y;
+ m_coord[2] = z;
+ m_coord[3] = t;
+}
+
+PMVector::~PMVector( )
+{
+ if( m_coord )
+ free( m_coord );
+}
+
+
+void PMVector::resize( unsigned int s )
+{
+ unsigned int i;
+
+ if( s != m_size )
+ {
+ m_coord = ( double* ) realloc( m_coord, sizeof( double ) * s );
+
+ for( i = m_size; i < s; i++ )
+ m_coord[i] = 0.0;
+
+ if( m_coord )
+ m_size = s;
+ else
+ m_size = 0; // possibly out of memory
+ }
+}
+
+void PMVector::transform( const PMMatrix& m )
+{
+ (*this) = m * (*this);
+}
+
+PMVector& PMVector::operator= ( const PMVector& p )
+{
+ unsigned int i;
+
+ resize( p.m_size );
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] = p[i];
+ return *this;
+}
+
+PMVector& PMVector::operator= ( const double d )
+{
+ unsigned int i;
+
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] = d;
+ return *this;
+}
+
+PMVector& PMVector::operator*= ( const PMVector& p )
+{
+ unsigned int i;
+
+ if( m_size != p.m_size )
+ resize( p.m_size );
+
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] *= p[i];
+
+ return *this;
+}
+
+PMVector& PMVector::operator/= ( const PMVector& p )
+{
+ unsigned int i;
+
+ if( m_size > p.m_size )
+ {
+ kdError( PMArea ) << "Vector p is too small in PMVector& PMVector::operator/= ( const PMVector& p )\n";
+ }
+ else
+ {
+ for( i = 0; i < m_size; i++ )
+ {
+ if( approxZero( p[i] ) )
+ kdError( PMArea ) << "Division by zero in PMVector::operator/= " << "\n";
+ else
+ m_coord[i] *= p[i];
+ }
+ }
+
+ return *this;
+}
+
+PMVector& PMVector::operator*= ( double d )
+{
+ unsigned int i;
+
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] *= d;
+
+ return *this;
+}
+
+PMVector& PMVector::operator/= ( double d )
+{
+ if( approxZero( d ) )
+ {
+ kdError( PMArea ) << "Division by zero in PMVector::operator/= " << "\n";
+ }
+ else
+ {
+ unsigned int i;
+
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] /= d;
+ }
+
+ return *this;
+}
+
+PMVector& PMVector::operator+= ( double d )
+{
+ unsigned int i;
+
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] += d;
+
+ return *this;
+}
+
+PMVector& PMVector::operator-= ( double d )
+{
+ unsigned int i;
+
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] -= d;
+
+ return *this;
+}
+
+PMVector& PMVector::operator+= ( const PMVector& p )
+{
+ unsigned int i;
+
+ if( m_size < p.m_size )
+ resize( p.m_size );
+
+ for( i = 0; i < p.m_size; i++ )
+ m_coord[i] += p[i];
+
+ return *this;
+}
+
+PMVector& PMVector::operator-= ( const PMVector& p )
+{
+ unsigned int i;
+
+ if( m_size < p.m_size )
+ resize( p.m_size );
+
+ for( i = 0; i < m_size; i++ )
+ m_coord[i] -= p[i];
+
+ return *this;
+}
+
+PMVector operator- ( const PMVector& p )
+{
+ PMVector result( p.m_size );
+ unsigned int i;
+
+ for( i = 0; i < p.m_size; i++ )
+ result[i] = -p[i];
+
+ return result;
+}
+
+PMVector operator+ ( const PMVector& p1, const PMVector& p2 )
+{
+ PMVector result( p1 );
+ result += p2;
+
+ return result;
+}
+
+PMVector operator- ( const PMVector& p1, const PMVector& p2 )
+{
+ PMVector result( p1 );
+ result -= p2;
+
+ return result;
+}
+
+PMVector operator* ( const PMVector& p, const double d )
+{
+ PMVector result( p.m_size );
+ unsigned int i;
+
+ for( i = 0; i < p.m_size; i++ )
+ result[i] = p[i] * d;
+
+ return result;
+}
+
+PMVector operator/ ( const PMVector& p, const double d )
+{
+ PMVector result( p.m_size );
+ unsigned int i;
+
+ if( approxZero( d ) )
+ kdError( PMArea ) << "Division by zero in PMVector::operator/ ( PMVector& p, double d ) " << "\n";
+ else
+ for( i = 0; i < p.m_size; i++ )
+ result[i] = p[i] / d;
+
+ return result;
+}
+
+PMVector operator+ ( const PMVector& p, const double d )
+{
+ PMVector result( p.m_size );
+ unsigned int i;
+
+ for( i = 0; i < p.m_size; i++ )
+ result[i] = p[i] + d;
+
+ return result;
+}
+
+PMVector operator- ( const PMVector& p, const double d )
+{
+ PMVector result( p.m_size );
+ unsigned int i;
+
+ for( i = 0; i < p.m_size; i++ )
+ result[i] = p[i] - d;
+
+ return result;
+}
+
+PMVector operator* ( const double d, const PMVector& p )
+{
+ PMVector result( p.m_size );
+ unsigned int i;
+
+ for( i = 0; i < p.m_size; i++ )
+ result[i] = p[i] * d;
+
+ return result;
+}
+
+PMVector operator* ( const PMMatrix& m, const PMVector& p )
+{
+ PMVector result( 3 );
+ int c, i;
+ // for homogenous coordinates
+ double u;
+
+ if( p.m_size != 3 )
+ kdError( PMArea ) << "Vector has not size 3 in PMVector operator* ( const PMVector& p, const PMMatrix& m ) \n";
+ else
+ {
+ for( c=0; c<3; c++ )
+ {
+ result[c] = 0.0;
+ for( i=0; i<4; i++ )
+ result[c] += m[i][c] * ( i<3 ? p[i] : 1.0 );
+ }
+
+ u = 0.0;
+ for( i=0; i<4; i++ )
+ u += m[i][3] * ( i<3 ? p[i] : 1.0 );
+ if( !approxZero( u ) )
+ for( i=0; i<3; i++ )
+ result[i] /= u;
+ }
+
+ return result;
+}
+
+PMVector operator* ( const PMVector& p1, const PMVector& p2 )
+{
+ PMVector result( p1 );
+ result *= p2;
+
+ return result;
+}
+
+PMVector operator/ ( const PMVector& p1, const PMVector& p2 )
+{
+ PMVector result( p1 );
+ result /= p2;
+
+ return result;
+}
+
+bool PMVector::operator== ( const PMVector& p ) const
+{
+ unsigned int i;
+ if( m_size != p.m_size )
+ return false;
+ if( m_size == 0 )
+ return true;
+
+ for( i = 0; i < m_size; i++ )
+ if( p.m_coord[i] != m_coord[i] )
+ return false;
+ return true;
+}
+
+bool PMVector::approxEqual( const PMVector& p, double epsilon ) const
+{
+ unsigned int i;
+ if( m_size != p.m_size )
+ return false;
+ if( m_size == 0 )
+ return true;
+
+ for( i = 0; i < m_size; i++ )
+ if( ! approx( p.m_coord[i], m_coord[i], epsilon ) )
+ return false;
+ return true;
+}
+
+bool PMVector::operator!= ( const PMVector& p ) const
+{
+ return !( *this == p );
+}
+
+
+PMVector PMVector::cross( const PMVector& v1, const PMVector& v2 )
+{
+ PMVector result;
+ if( ( v1.size( ) == 3 ) && ( v2.size( ) == 3 ) )
+ {
+ result[0] = v1[1]*v2[2] - v1[2]*v2[1];
+ result[1] = v1[2]*v2[0] - v1[0]*v2[2];
+ result[2] = v1[0]*v2[1] - v1[1]*v2[0];
+ }
+ else
+ kdError( PMArea ) << "Wrong sizes in PMVector::cross( )\n";
+
+ return result;
+}
+
+double PMVector::dot( const PMVector& v1, const PMVector& v2 )
+{
+ double result = 0.0;
+ unsigned int i;
+
+ if( v1.size( ) == v2.size( ) )
+ {
+ for( i = 0; i < v1.size( ); i++ )
+ result += v1[i] * v2[i];
+ }
+ else
+ kdError( PMArea ) << "Wrong sizes in PMVector::dot( )\n";
+
+ return result;
+}
+
+double PMVector::angle( const PMVector& v1, const PMVector& v2 )
+{
+ PMVector cr;
+ double s, c, n;
+ double a = 0;
+ int i;
+
+ if( ( v1.size( ) == 3 ) && ( v2.size( ) == 3 ) )
+ {
+ n = v1.abs( ) * v2.abs( );
+
+ if( approxZero( n ) )
+ a = 0;
+ else
+ {
+ cr = cross( v1, v2 );
+ s = cr.abs( ) / n;
+
+ c = 0;
+ for( i = 0; i < 3; i++ )
+ c += v1[i] * v2[i];
+
+ c = c / n;
+
+ a = pmatan( s, c );
+ }
+ }
+ else
+ kdError( PMArea ) << "Wrong sizes in PMVector::angle( )\n";
+
+ return a;
+}
+
+double PMVector::abs( ) const
+{
+ unsigned int i;
+ double a = 0.0;
+
+ for( i = 0; i < m_size; i++ )
+ a += m_coord[i] * m_coord[i];
+
+ return sqrt( a );
+}
+
+PMVector PMVector::orthogonal( ) const
+{
+ PMVector result;
+ double l, rl;
+
+ l = abs( );
+ if( approxZero( l ) )
+ {
+ kdError( PMArea ) << "Can't calculate an orthogonal vector from a null vector\n";
+ return PMVector( 1, 0, 0 );
+ }
+
+ result = cross( (*this) / l, PMVector( 0, 0, 1 ) );
+ rl = result.abs( );
+ if( rl < 0.001 )
+ {
+ result = cross( (*this) / l, PMVector( 1, 0, 0 ) );
+ rl = result.abs( );
+ }
+ return result / rl;
+}
+
+QString PMVector::serialize( ) const
+{
+ QString result;
+ QTextStream str( &result, IO_WriteOnly );
+ unsigned int i;
+
+ if( m_size > 0 )
+ {
+ str << '<';
+ for( i = 0; i < m_size; i++ )
+ {
+ if( i > 0 )
+ str << ", ";
+ str << m_coord[i];
+ }
+ str << '>';
+ }
+ else
+ kdError( PMArea ) << "Can't serialize a vector with size 0\n";
+
+ return result;
+}
+
+QString PMVector::serializeXML( ) const
+{
+ QString result;
+ QTextStream str( &result, IO_WriteOnly );
+ unsigned int i;
+
+ if( m_size > 0 )
+ {
+ for( i = 0; i < m_size; i++ )
+ {
+ if( i > 0 )
+ str << ' ';
+ str << m_coord[i];
+ }
+ }
+ else
+ kdError( PMArea ) << "Can't serialize a vector with size 0\n";
+
+ return result;
+}
+
+bool PMVector::loadXML( const QString& str )
+{
+ int i;
+ int size = str.contains( ' ' ) + 1;
+ QString tmp( str );
+ QTextStream s( &tmp, IO_ReadOnly );
+ QString val;
+ bool ok;
+
+ resize( size );
+ for( i = 0; i < size; i++ )
+ {
+ s >> val;
+ m_coord[i] = val.toDouble( &ok );
+ if( !ok )
+ return false;
+ }
+ return true;
+}
diff --git a/kpovmodeler/pmvector.h b/kpovmodeler/pmvector.h
new file mode 100644
index 00000000..6794d02a
--- /dev/null
+++ b/kpovmodeler/pmvector.h
@@ -0,0 +1,275 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMVECTOR_H
+#define PMVECTOR_H
+
+#include <qmemarray.h>
+#include <qstring.h>
+
+class PMMatrix;
+
+/**
+ * Class for vectors with variable size
+ */
+class PMVector
+{
+public:
+ /**
+ * Creates a vector with size s. All values are set to 0
+ */
+ PMVector( unsigned int s );
+ /**
+ * Creates a vector with size 3. All values are set to 0
+ */
+ PMVector( );
+ /**
+ * Creates a vector with coordinates [x,y]
+ */
+ PMVector( const double x, const double y );
+ /**
+ * Creates a vector with coordinates [x,y,z]
+ */
+ PMVector( const double x, const double y, const double z );
+ /**
+ * Creates a vector with coordinates [x,y,z,t]
+ */
+ PMVector( const double x, const double y, const double z, const double t );
+ /**
+ * Copy constructor. Creates a deep copy.
+ */
+ PMVector( const PMVector& v );
+ /**
+ * Deletes the vector
+ */
+ ~PMVector( );
+
+ /**
+ * Returns the size of the vector
+ */
+ unsigned int size( ) const { return m_size; }
+ /**
+ * Resizes the vector. New elements are initialized with 0
+ */
+ void resize( unsigned int size );
+ /**
+ * Returns a reference to a coordinate, 0:x, 1:y, 2:z
+ */
+ double& operator[] ( int index );
+ /**
+ * Returns a reference to a coordinate, 0:x, 1:y, 2:z
+ */
+ const double& operator[] ( int index ) const;
+
+ /**
+ * Returns the x coordinate
+ */
+ double x( ) const { return (*this)[0]; }
+ /**
+ * Returns the y coordinate
+ */
+ double y( ) const { return (*this)[1]; }
+ /**
+ * Returns the z coordinate
+ */
+ double z( ) const { return (*this)[2]; }
+ /**
+ * Returns the t coordinate
+ */
+ double t( ) const { return (*this)[3]; }
+
+ /**
+ * Sets the x coordinate
+ */
+ void setX( const double d ) { (*this)[0] = d; }
+ /**
+ * Sets the y coordinate
+ */
+ void setY( const double d ) { (*this)[1] = d; }
+ /**
+ * Sets the z coordinate
+ */
+ void setZ( const double d ) { (*this)[2] = d; }
+ /**
+ * Sets the x coordinate
+ */
+ void setT( const double d ) { (*this)[3] = d; }
+
+ /**
+ * Transforms the point with the matrix m. Same as p = m * p
+ *
+ * size must be 3!
+ */
+ void transform( const PMMatrix& m );
+
+ /**
+ * Assigns p to the vector. Resizes the vector if necessary.
+ */
+ PMVector& operator= ( const PMVector& p );
+ /**
+ * Sets all values to d
+ */
+ PMVector& operator= ( const double d );
+
+ /**
+ * Multiplies all coordinates with d
+ */
+ PMVector& operator*= ( double d );
+ /**
+ * Divides all coordinates through d
+ */
+ PMVector& operator/= ( double d );
+ /**
+ * Adds d to all coordinates
+ */
+ PMVector& operator+= ( double d );
+ /**
+ * Subtracts d from all coordinates
+ */
+ PMVector& operator-= ( double d );
+
+ /**
+ * Multiplies the vectors (<x1*x2, y1*y2, z1*z2> ...)
+ */
+ PMVector& operator*= ( const PMVector& p );
+ /**
+ * Divides the vectors (<x1/x2, y1/y2, z1/z2> ...)
+ */
+ PMVector& operator/= ( const PMVector& p );
+
+ /**
+ * Adds p to the point.
+ */
+ PMVector& operator+= ( const PMVector& p );
+ /**
+ * Subtracts p from the point.
+ */
+ PMVector& operator-= ( const PMVector& p );
+
+ /**
+ * Returns a point with negated coordinates
+ */
+ friend PMVector operator- ( const PMVector& p );
+ /**
+ * Adds the two points
+ */
+ friend PMVector operator+ ( const PMVector& p1, const PMVector& p2 );
+ /**
+ * Subtracts p2 from p1
+ */
+ friend PMVector operator- ( const PMVector& p1, const PMVector& p2 );
+
+ /**
+ * Multiplies all coordinates with d
+ */
+ friend PMVector operator* ( const PMVector& p, const double d );
+ /**
+ * Divides all coordinates by d
+ */
+ friend PMVector operator/ ( const PMVector& p, const double d );
+ /**
+ * Adds d to all coordinates
+ */
+ friend PMVector operator+ ( const PMVector& p, const double d );
+ /**
+ * Subtracts d from all coordinates
+ */
+ friend PMVector operator- ( const PMVector& p, const double d );
+
+ /**
+ * Multiplies all coordinates with d
+ */
+ friend PMVector operator* ( const double d, const PMVector& p );
+ /**
+ * Multiplies the vectors (<x1*x2, y1*y2, z1*z2> ...)
+ */
+ friend PMVector operator* ( const PMVector& p1, const PMVector& p2 );
+ /**
+ * Divides the vectors (<x1/x2, y1/y2, z1/z2> ...)
+ */
+ friend PMVector operator/ ( const PMVector& p1, const PMVector& p2 );
+ /**
+ * Transforms the point p with the matrix m
+ * @see transform
+ */
+ friend PMVector operator* ( const PMMatrix& m, const PMVector& p );
+
+ /**
+ * Returns true if the vectors have the same size and values
+ */
+ bool operator== ( const PMVector& p ) const;
+ /**
+ * Returns false if the vectors have the same size and values
+ */
+ bool operator!= ( const PMVector& p ) const;
+
+ /**
+ * Returns true if the vectors have the same size and values
+ */
+ bool approxEqual( const PMVector& p, double epsilon = 1e-6 ) const;
+
+ /**
+ * Returns the cross product of v1 and v2
+ *
+ * Size of v1 and v2 has to be 3!
+ */
+ static PMVector cross( const PMVector& v1, const PMVector& v2 );
+ /**
+ * Returns the dot product of v1 and v2
+ */
+ static double dot( const PMVector& v1, const PMVector& v2 );
+
+ /**
+ * Returns the angle between v1 and v2
+ *
+ * Size of v1 and v2 has to be 3!
+ */
+ static double angle( const PMVector& v1, const PMVector& v2 );
+
+ /**
+ * Returns the length of the vector
+ */
+ double abs( ) const;
+
+ /**
+ * Returns a normalized vector that is orthogonal to this vector
+ */
+ PMVector orthogonal( ) const;
+
+ /**
+ * Returns a string for serialization
+ */
+ QString serialize( ) const;
+ /**
+ * Returns a string for xml output
+ */
+ QString serializeXML( ) const;
+ /**
+ * loads the vector data from the xml string
+ */
+ bool loadXML( const QString& str );
+private:
+ void allocateMemory( unsigned int size );
+
+ double* m_coord;
+ static double s_dummy;
+ unsigned int m_size;
+};
+
+#endif
diff --git a/kpovmodeler/pmvectorcontrolpoint.cpp b/kpovmodeler/pmvectorcontrolpoint.cpp
new file mode 100644
index 00000000..0a14d0b8
--- /dev/null
+++ b/kpovmodeler/pmvectorcontrolpoint.cpp
@@ -0,0 +1,89 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmvectorcontrolpoint.h"
+#include "pmmath.h"
+#include <math.h>
+
+PMVectorControlPoint::PMVectorControlPoint( PMControlPoint* base,
+ const PMVector& v, int id,
+ const QString& description,
+ bool extraLine, bool normalize )
+ : PMControlPoint( id, description )
+{
+ m_vector = v;
+ m_pBasePoint = base;
+ m_extraLine = extraLine;
+ m_normalize = normalize;
+}
+
+PMVectorControlPoint::PMVectorControlPoint( const PMVector& base,
+ const PMVector& v, int id,
+ const QString& description,
+ bool extraLine, bool normalize )
+ : PMControlPoint( id, description )
+{
+ m_vector = v;
+ m_constBasePoint = base;
+ m_pBasePoint = 0;
+ m_extraLine = extraLine;
+ m_normalize = normalize;
+}
+
+PMVector PMVectorControlPoint::position( ) const
+{
+ return basePoint( ) + m_vector;
+}
+
+PMVector PMVectorControlPoint::basePoint( ) const
+{
+ if( m_pBasePoint )
+ return m_pBasePoint->position( );
+ return m_constBasePoint;
+}
+
+void PMVectorControlPoint::graphicalChangeStarted( )
+{
+ m_originalVector = m_vector;
+}
+
+void PMVectorControlPoint::graphicalChange( const PMVector& startPoint,
+ const PMVector& /*viewNormal*/,
+ const PMVector& endPoint )
+{
+ double d;
+
+ m_vector = m_originalVector + endPoint - startPoint;
+ if( m_normalize )
+ {
+ d = m_vector.abs( );
+ if( approxZero( d ) )
+ m_vector = m_originalVector;
+ else
+ m_vector /= d;
+ }
+}
+
+void PMVectorControlPoint::snapToGrid( )
+{
+ int i;
+ double d = moveGrid( );
+ if( !approxZero( d ) )
+ for( i = 0; i < 3; i++ )
+ m_vector[i] = rint( m_vector[i] / d ) * d;
+ setChanged( );
+}
diff --git a/kpovmodeler/pmvectorcontrolpoint.h b/kpovmodeler/pmvectorcontrolpoint.h
new file mode 100644
index 00000000..92713bc6
--- /dev/null
+++ b/kpovmodeler/pmvectorcontrolpoint.h
@@ -0,0 +1,101 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMVECTORCONTROLPOINT_H
+#define PMVECTORCONTROLPOINT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "pmcontrolpoint.h"
+
+/**
+ * Class for vector like control points
+ */
+class PMVectorControlPoint : public PMControlPoint
+{
+public:
+ /**
+ * Creates a PMVectorControlPoint with id.
+ *
+ * The base point of the vector is given by the control point location.
+ */
+ PMVectorControlPoint( PMControlPoint* location, const PMVector& v,
+ int id, const QString& description,
+ bool extraLine = true, bool normalize = false );
+ /**
+ * Creates a PMVectorControlPoint with id.
+ *
+ * The base point of the vector is given by the vector p.
+ */
+ PMVectorControlPoint( const PMVector& location, const PMVector& v,
+ int id, const QString& description,
+ bool extraLine = true, bool normalize = false );
+ /**
+ * Deletes the PMVectorControlPoint
+ */
+ virtual ~PMVectorControlPoint( ) { };
+
+ /** */
+ virtual PMVector position( ) const;
+ /**
+ * Returns the base point
+ */
+ PMVector basePoint( ) const;
+
+ /**
+ * Sets the vector
+ */
+ void setVector( PMVector newVector ) { m_vector = newVector; }
+ /**
+ * returns the vector
+ */
+ PMVector vector( ) const { return m_vector; }
+
+ /** */
+ virtual bool hasExtraLine( ) const { return m_extraLine; }
+ /**
+ * Returns the start point of the extra line
+ */
+ virtual PMVector extraLineStart( ) const { return basePoint( ); }
+ /**
+ * Returns the end point of the extra line
+ */
+ virtual PMVector extraLineEnd( ) const { return position( ); }
+
+ /** */
+ virtual void snapToGrid( );
+
+protected:
+ /** */
+ virtual void graphicalChangeStarted( );
+ /** */
+ virtual void graphicalChange( const PMVector& startPoint,
+ const PMVector& viewNormal,
+ const PMVector& endPoint );
+private:
+ PMVector m_vector, m_originalVector;
+ PMControlPoint* m_pBasePoint;
+ PMVector m_constBasePoint;
+ bool m_extraLine;
+ bool m_normalize;
+};
+
+#endif
diff --git a/kpovmodeler/pmvectoredit.cpp b/kpovmodeler/pmvectoredit.cpp
new file mode 100644
index 00000000..7264f8f3
--- /dev/null
+++ b/kpovmodeler/pmvectoredit.cpp
@@ -0,0 +1,235 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmvectoredit.h"
+#include "pmdebug.h"
+#include <qstring.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <kdialog.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+
+PMVectorEdit::PMVectorEdit( const QString& descriptionX,
+ const QString& descriptionY,
+ QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ unsigned int i;
+ QHBoxLayout* layout;
+ QLabel* label;
+
+ m_edits.resize( 2 );
+ for( i = 0; i < 2; i++ )
+ {
+ m_edits.insert( i, new QLineEdit( this ) );
+ connect( m_edits[i], SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotTextChanged( const QString& ) ) );
+ }
+
+ layout = new QHBoxLayout( this );
+
+ if( !descriptionX.isEmpty( ) )
+ {
+ label = new QLabel( descriptionX, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[0] );
+ layout->addSpacing( KDialog::spacingHint( ) );
+
+ if( !descriptionY.isEmpty( ) )
+ {
+ label = new QLabel( descriptionY, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[1] );
+}
+
+PMVectorEdit::PMVectorEdit( const QString& descriptionX,
+ const QString& descriptionY,
+ const QString& descriptionZ,
+ QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ unsigned int i;
+ QHBoxLayout* layout;
+ QLabel* label;
+
+ m_edits.resize( 3 );
+ for( i = 0; i < 3; i++ )
+ {
+ m_edits.insert( i, new QLineEdit( this ) );
+ connect( m_edits[i], SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotTextChanged( const QString& ) ) );
+ }
+
+ layout = new QHBoxLayout( this );
+
+ if( !descriptionX.isEmpty( ) )
+ {
+ label = new QLabel( descriptionX, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[0] );
+ layout->addSpacing( KDialog::spacingHint( ) );
+
+ if( !descriptionY.isEmpty( ) )
+ {
+ label = new QLabel( descriptionY, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[1] );
+ layout->addSpacing( KDialog::spacingHint( ) );
+
+ if( !descriptionZ.isEmpty( ) )
+ {
+ label = new QLabel( descriptionZ, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[2] );
+}
+
+PMVectorEdit::PMVectorEdit( const QString& descriptionA,
+ const QString& descriptionB,
+ const QString& descriptionC,
+ const QString& descriptionD,
+ QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ unsigned int i;
+ QHBoxLayout* layout;
+ QLabel* label;
+
+ m_edits.resize( 4 );
+ for( i = 0; i < 4; i++ )
+ {
+ m_edits.insert( i, new QLineEdit( this ) );
+ connect( m_edits[i], SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotTextChanged( const QString& ) ) );
+ }
+
+ layout = new QHBoxLayout( this );
+
+ if( !descriptionA.isEmpty( ) )
+ {
+ label = new QLabel( descriptionA, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[0] );
+ layout->addSpacing( KDialog::spacingHint( ) );
+
+ if( !descriptionB.isEmpty( ) )
+ {
+ label = new QLabel( descriptionB, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[1] );
+ layout->addSpacing( KDialog::spacingHint( ) );
+
+ if( !descriptionC.isEmpty( ) )
+ {
+ label = new QLabel( descriptionC, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[2] );
+ layout->addSpacing( KDialog::spacingHint( ) );
+
+ if( !descriptionD.isEmpty( ) )
+ {
+ label = new QLabel( descriptionD, this );
+ layout->addWidget( label );
+ layout->addSpacing( KDialog::spacingHint( ) );
+ }
+ layout->addWidget( m_edits[3] );
+}
+
+void PMVectorEdit::setVector( const PMVector& v, int precision )
+{
+ unsigned int i;
+ QString str;
+
+ if( v.size( ) != m_edits.size( ) )
+ kdError( PMArea ) << "Vector has wrong size in PMVectorEdit::setVector\n";
+
+ for( i = 0; ( i < m_edits.size( ) ) && ( i < v.size( ) ); i++ )
+ {
+ str.setNum( v[i], 'g', precision );
+ m_edits[i]->setText( str );
+ }
+}
+
+PMVector PMVectorEdit::vector( ) const
+{
+ PMVector result( m_edits.size( ) );
+ unsigned int i;
+
+ for( i = 0; i < m_edits.size( ); i++ )
+ result[i] = m_edits[i]->text( ).toDouble( );
+
+ return result;
+}
+
+bool PMVectorEdit::isDataValid( )
+{
+ bool ok = true;
+ unsigned int i;
+
+ for( i = 0; ( i < m_edits.size( ) ) && ok; i++ )
+ {
+ m_edits[i]->text( ).toDouble( &ok );
+ if( !ok )
+ {
+ KMessageBox::error( this, i18n( "Please enter a valid float value!" ),
+ i18n( "Error" ) );
+ m_edits[i]->setFocus( );
+ m_edits[i]->selectAll( );
+ }
+ }
+
+ return ok;
+}
+
+void PMVectorEdit::slotTextChanged( const QString& )
+{
+ emit dataChanged( );
+}
+
+void PMVectorEdit::setReadOnly( bool yes )
+{
+ unsigned int i;
+ for( i = 0; ( i < m_edits.size( ) ); i++ )
+ m_edits[i]->setReadOnly( yes );
+}
+
+void PMVectorEdit::setEnabled( bool yes )
+{
+ unsigned int i;
+ for( i = 0; ( i < m_edits.size( ) ); i++ )
+ m_edits[i]->setEnabled( yes );
+}
+
+#include "pmvectoredit.moc"
diff --git a/kpovmodeler/pmvectoredit.h b/kpovmodeler/pmvectoredit.h
new file mode 100644
index 00000000..8be64ebe
--- /dev/null
+++ b/kpovmodeler/pmvectoredit.h
@@ -0,0 +1,100 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMVECTOREDIT_H
+#define PMVECTOREDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qptrvector.h>
+#include <qlineedit.h>
+#include "pmvector.h"
+
+/**
+ * Edit widget for @ref PMVector
+ */
+class PMVectorEdit : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates an edit widget for 2D vectors.
+ *
+ * The labels shown are descriptionX and descriptionY
+ */
+ PMVectorEdit( const QString& descriptionX,
+ const QString& descriptionY,
+ QWidget* parent, const char* name = 0 );
+ /**
+ * Creates an edit widget for 3D vectors.
+ *
+ * The labels shown are descriptionX, descriptionY and descriptionZ
+ */
+ PMVectorEdit( const QString& descriptionX,
+ const QString& descriptionY, const QString& descriptionZ,
+ QWidget* parent, const char* name = 0 );
+ /**
+ * Creates an edit widget for 4D vectors.
+ *
+ * The labels shown are descriptionA, descriptionB, descriptionC
+ * and description D
+ */
+ PMVectorEdit( const QString& descriptionA, const QString& descriptionB,
+ const QString& descriptionC, const QString& descriptionD,
+ QWidget* parent, const char* name = 0 );
+
+ /**
+ * Sets the displayed vector
+ */
+ void setVector( const PMVector& v, int precision = 5 );
+ /**
+ * Returns the displayed vector
+ */
+ PMVector vector( ) const;
+
+ /**
+ * Returns true if the text for each coordinate is a valid
+ * float value. Otherwise an error message is shown.
+ */
+ bool isDataValid( );
+
+ /**
+ * Enables or disables read only mode
+ */
+ void setReadOnly( bool yes = true );
+ /**
+ * Reimplemented from QWidget
+ */
+ virtual void setEnabled( bool yes );
+signals:
+ /**
+ * Emitted when one of the coordinates is changed
+ */
+ void dataChanged( );
+
+protected slots:
+ void slotTextChanged( const QString& );
+private:
+ QPtrVector<QLineEdit> m_edits;
+};
+
+#endif
diff --git a/kpovmodeler/pmvectorlistedit.cpp b/kpovmodeler/pmvectorlistedit.cpp
new file mode 100644
index 00000000..224c6b69
--- /dev/null
+++ b/kpovmodeler/pmvectorlistedit.cpp
@@ -0,0 +1,357 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmvectorlistedit.h"
+#include "pmdebug.h"
+
+#include <qheader.h>
+#include <qapplication.h>
+#include <qpalette.h>
+#include <qpainter.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+const int c_columnWidth = 65;
+
+
+/*
+PMTableItem::PMTableItem( QTable* table )
+ : QTableItem( table, QTableItem::OnTyping, QString( "" ) )
+{
+ m_readOnly = false;
+}
+
+void PMTableItem::paint( QPainter* p, const QColorGroup& cg,
+ const QRect& cr, bool selected )
+{
+ p->fillRect( 0, 0, cr.width( ), cr.height( ),
+ selected ? cg.brush( QColorGroup::Highlight )
+ : ( m_readOnly ? cg.brush( QColorGroup::Background ) :
+ cg.brush( QColorGroup::Base ) ) );
+
+ int w = cr.width( );
+ int h = cr.height( );
+
+ int x = 0;
+
+ if( selected )
+ p->setPen( cg.highlightedText( ) );
+ else
+ p->setPen( cg.text( ) );
+ p->drawText( x + 2, 0, w - x - 4, h,
+ wordWrap( ) ? ( alignment( ) | WordBreak ) : alignment( ), text( ) );
+}
+*/
+
+PMVectorListEdit::PMVectorListEdit( QWidget* parent, const char* name )
+ : QTable( 1, 3, parent, name )
+{
+ init( 3 );
+
+ QHeader* header = horizontalHeader( );
+ header->setLabel( 0, "x" );
+ header->setLabel( 1, "y" );
+ header->setLabel( 2, "z" );
+}
+
+PMVectorListEdit::PMVectorListEdit( const QString& c1, const QString& c2,
+ const QString& c3, const QString& c4,
+ QWidget* parent, const char* name )
+ : QTable( 1, 4, parent, name )
+{
+ init( 4 );
+
+ QHeader* header = horizontalHeader( );
+ header->setLabel( 0, c1 );
+ header->setLabel( 1, c2 );
+ header->setLabel( 2, c3 );
+ header->setLabel( 3, c4 );
+}
+
+PMVectorListEdit::PMVectorListEdit( const QString& c1, const QString& c2,
+ const QString& c3, QWidget* parent,
+ const char* name )
+ : QTable( 1, 3, parent, name )
+{
+ init( 3 );
+
+ QHeader* header = horizontalHeader( );
+ header->setLabel( 0, c1 );
+ header->setLabel( 1, c2 );
+ header->setLabel( 2, c3 );
+}
+
+PMVectorListEdit::PMVectorListEdit( const QString& c1, const QString& c2,
+ QWidget* parent, const char* name )
+ : QTable( 1, 2, parent, name )
+{
+ init( 2 );
+
+ QHeader* header = horizontalHeader( );
+ header->setLabel( 0, c1 );
+ header->setLabel( 1, c2 );
+}
+
+void PMVectorListEdit::init( int dimensions )
+{
+ int i;
+
+ m_dimension = dimensions;
+ m_size = 0;
+
+ horizontalHeader( )->setResizeEnabled( false );
+ verticalHeader( )->setResizeEnabled( false );
+
+ setSelectionMode( QTable::MultiRow );
+ for( i = 0; i < m_dimension; ++i )
+ setColumnStretchable( i, true );
+ connect( this, SIGNAL( valueChanged( int, int ) ),
+ SLOT( slotTextChanged( int, int ) ) );
+ setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
+}
+
+void PMVectorListEdit::setVectors( const QValueList<PMVector>& l,
+ bool resize, int prec )
+{
+ QValueList<PMVector>::ConstIterator it;
+ int r, nl = 0;
+
+ for( r = 0; r < ( signed ) m_links.size( ); ++r )
+ if( m_links[r] >= 0 )
+ ++nl;
+
+ if( nl == 0 && resize )
+ setSize( l.size( ) );
+
+ for( r = 0, it = l.begin( ); it != l.end( ) && r < m_size; ++r )
+ {
+ if( m_disabled[r] )
+ {
+ if( !isReadOnly( ) )
+ setRowReadOnly( r, true );
+ }
+ else
+ {
+ setVector( r, *it, prec );
+ if( !isReadOnly( ) )
+ setRowReadOnly( r, false );
+ if( m_links[r] >= 0 )
+ setVector( m_links[r], *it, prec );
+ ++it;
+ }
+ }
+ if( it != l.end( ) )
+ kdError( PMArea ) << "Wrong size of vector list in PMVectorListEdit::setVectors" << endl;
+}
+
+QValueList<PMVector> PMVectorListEdit::vectors( ) const
+{
+ QValueList<PMVector> l;
+ int i;
+
+ for( i = 0; i < m_size; ++i )
+ if( !m_disabled[i] )
+ l.append( vector( i ) );
+
+ return l;
+}
+
+void PMVectorListEdit::setVector( int r, const PMVector& v, int precision )
+{
+ if( r < 0 || r >= m_size )
+ {
+ kdError( PMArea ) << "Wrong vector index in PMVectorListEdit::setVector"
+ << endl;
+ return;
+ }
+
+ bool sb = signalsBlocked( );
+ blockSignals( true );
+
+ int i;
+ QString str;
+
+ for( i = 0; i < m_dimension && i <= ( signed ) v.size( ); ++i )
+ {
+ str.setNum( v[i], 'g', precision );
+ setText( r, i, str );
+ }
+
+ blockSignals( sb );
+}
+
+PMVector PMVectorListEdit::vector( int r ) const
+{
+ PMVector v( m_dimension );
+
+ if( r < 0 || r >= m_size )
+ {
+ kdError( PMArea ) << "Wrong vector index in PMVectorListEdit::vector"
+ << endl;
+ return v;
+ }
+
+ int i;
+ for( i = 0; i < m_dimension; ++i )
+ v[i] = text( r, i ).toDouble( );
+ return v;
+}
+
+void PMVectorListEdit::setSize( int s )
+{
+ if( s < 0 || s == m_size )
+ return;
+
+ setNumRows( s );
+ int i;
+ QHeader* h = verticalHeader( );
+ QString str;
+
+ for( i = 0; i < s; ++i )
+ {
+ setRowStretchable( i, true );
+ setRowReadOnly( i, false );
+
+ str.setNum( i + 1 );
+ h->setLabel( i, str );
+ }
+ m_links.fill( -1, s );
+ m_disabled.fill( false, s );
+ m_size = s;
+ updateGeometry( );
+}
+
+void PMVectorListEdit::setLink( int p1, int p2 )
+{
+ if( p1 < 0 || p1 >= m_size || p2 >= m_size )
+ return;
+
+ QHeader* h = verticalHeader( );
+ QString str;
+
+ // remove old link
+ if( m_links[p1] >= 0 )
+ {
+ str.setNum( m_links[p1] + 1 );
+ h->setLabel( m_links[p1], str );
+ if( !isReadOnly( ) )
+ setRowReadOnly( m_links[p1], false );
+ m_disabled[m_links[p1]] = false;
+ }
+
+ if( p2 >= 0 )
+ {
+ m_disabled[p2] = true;
+ str = QString( "%1 (=%2)" ).arg( p2 + 1 ).arg( p1 + 1 );
+ h->setLabel( p2, str );
+ if( !isReadOnly( ) )
+ setRowReadOnly( p2, true );
+ }
+
+ m_links[p1] = p2;
+}
+
+void PMVectorListEdit::clearLinks( )
+{
+ int i;
+ for( i = 0; i < ( signed ) m_links.size( ); ++i )
+ if( m_links[i] >= 0 )
+ setLink( i, -1 );
+}
+
+bool PMVectorListEdit::isSelected( int i ) const
+{
+ return isRowSelected( i );
+}
+
+void PMVectorListEdit::select( int i )
+{
+ selectRow( i );
+}
+
+void PMVectorListEdit::select( int i, int j )
+{
+ QTableSelection sel( i, 0, j, m_dimension - 1 );
+ addSelection( sel );
+
+}
+
+bool PMVectorListEdit::isDataValid( )
+{
+ int r, i;
+ bool valid = true;
+ double d;
+
+ for( r = 0; r < m_size && valid; ++r )
+ {
+ if( !m_disabled[r] )
+ {
+ for( i = 0; i < m_dimension && valid; ++i )
+ {
+ d = text( r, i ).toDouble( &valid );
+ if( !valid )
+ {
+ setCurrentCell( r, i );
+ KMessageBox::error( this, i18n( "Please enter a valid float value!" ),
+ i18n( "Error" ) );
+ }
+ }
+ }
+ }
+ return valid;
+}
+
+QSize PMVectorListEdit::sizeHint( ) const
+{
+ return QSize( c_columnWidth * m_dimension + frameWidth( ) * 2,
+ frameWidth( ) * 2 + horizontalHeader( )->height( )
+ + verticalHeader( )->sizeHint( ).height( ) );
+}
+
+void PMVectorListEdit::slotTextChanged( int, int )
+{
+ emit dataChanged( );
+}
+
+void PMVectorListEdit::blockSelectionUpdates( bool block )
+{
+ setUpdatesEnabled( !block );
+ verticalHeader( )->setUpdatesEnabled( !block );
+ horizontalHeader( )->setUpdatesEnabled( !block );
+ if( !block )
+ {
+ updateContents( );
+ verticalHeader( )->update( );
+ horizontalHeader( )->update( );
+ }
+}
+
+bool PMVectorListEdit::eventFilter( QObject* o, QEvent* e )
+{
+ if( e->type( ) == QEvent::Wheel && parent( ) )
+ return QApplication::sendEvent( parent( ), e );
+ if( e->type( ) == QEvent::MouseButtonPress
+ && ( ( QMouseEvent* ) e )->button( ) == RightButton )
+ {
+ bool b = QTable::eventFilter( o, e );
+ emit showContextMenu( );
+ return b;
+ }
+ return QTable::eventFilter( o, e );
+}
+
+#include "pmvectorlistedit.moc"
diff --git a/kpovmodeler/pmvectorlistedit.h b/kpovmodeler/pmvectorlistedit.h
new file mode 100644
index 00000000..f8ecb938
--- /dev/null
+++ b/kpovmodeler/pmvectorlistedit.h
@@ -0,0 +1,174 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMVECTORLISTEDIT_H
+#define PMVECTORLISTEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qtable.h>
+#include <qvaluelist.h>
+#include <qmemarray.h>
+
+#include "pmvector.h"
+
+/*
+const int c_pmTableRTTI = 14352;
+
+class PMTableItem : public QTableItem
+{
+public:
+ PMTableItem( QTable* table );
+
+ virtual void paint( QPainter* p, const QColorGroup& cg,
+ const QRect& cr, bool selected );
+
+ int rtti( ) const { return c_pmTableRTTI; }
+
+ void setReadOnly( bool r ) { m_readOnly = r; }
+ bool isReadOnly( ) const { return m_readOnly; }
+
+private:
+ bool m_readOnly;
+};
+*/
+
+
+/**
+ * Widget that displays a list of vectors, based on @ref QTable.
+ */
+class PMVectorListEdit : public QTable
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor for 3d vectors (x, y, z)
+ */
+ PMVectorListEdit( QWidget* parent, const char* name = 0 );
+ /**
+ * Constructor for 3d vectors
+ */
+ PMVectorListEdit( const QString& c1, const QString& c2, const QString& c3,
+ QWidget* parent, const char* name = 0 );
+ /**
+ * Constructor for 2d vectors
+ */
+ PMVectorListEdit( const QString& c1, const QString& c2,
+ QWidget* parent, const char* name = 0 );
+
+ /**
+ * Constructor for 4d vectors
+ */
+ PMVectorListEdit( const QString& c1, const QString& c2, const QString& c3,
+ const QString& c4, QWidget* parent, const char* name = 0 );
+ /**
+ * Sets and displays the vectors. The widget will automatically
+ * resize if no link is set and resize is true.
+ */
+ void setVectors( const QValueList<PMVector>& v, bool resize = false,
+ int precision = 5 );
+ /**
+ * Returns the vectors
+ */
+ QValueList<PMVector> vectors( ) const;
+ /**
+ * Sets the i-th vector
+ */
+ void setVector( int i, const PMVector& v, int precision = 5 );
+ /**
+ * Returns the i-th vector
+ */
+ PMVector vector( int i ) const;
+ /**
+ * Sets the number of vectors
+ */
+ void setSize( int s );
+ /**
+ * Returns the number of vectors
+ */
+ int size( ) const { return m_size; }
+
+ /**
+ * Adds a linked point. The point p2 will be disabled and synchronized
+ * with p1.
+ *
+ * Call this method before displaying vectors and remove the point
+ * p2 from the vector list before you call @ref setVectors( ).
+ * The list returned by @ref vectors( ) will not return this point.
+ *
+ * Set p2 to -1 to remove a link.
+ */
+ void setLink( int p1, int p2 );
+ /**
+ * Removes all links. The widget is not updated. You have to resize
+ * the widget and redisplay the points.
+ */
+ void clearLinks( );
+
+ /**
+ * Returns the selection status of vector i
+ */
+ bool isSelected( int i ) const;
+ /**
+ * Selects vector i
+ */
+ void select( int i );
+ /**
+ * Selects vector i to j
+ */
+ void select( int i, int j );
+ /**
+ * Blocks/unblocks selection updates. If block is false, the
+ * selection is repainted.
+ */
+ void blockSelectionUpdates( bool block );
+
+ /**
+ * Returns true if the edited data is valid.
+ */
+ bool isDataValid( );
+
+ /** */
+ virtual QSize sizeHint( ) const;
+ /** */
+ bool eventFilter( QObject* o, QEvent* e );
+
+protected slots:
+ void slotTextChanged( int, int );
+
+signals:
+ /**
+ * Emitted when the used edits a field
+ */
+ void dataChanged( );
+ /**
+ * Emitted after a right mouse button click
+ */
+ void showContextMenu( );
+private:
+ void init( int dimensions );
+
+ int m_dimension, m_size;
+ QMemArray<int> m_links;
+ QMemArray<bool> m_disabled;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmview.cpp b/kpovmodeler/pmview.cpp
new file mode 100644
index 00000000..fe9f32d4
--- /dev/null
+++ b/kpovmodeler/pmview.cpp
@@ -0,0 +1,108 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include <qprinter.h>
+#include <qpainter.h>
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <kconfig.h>
+#include <kdialog.h>
+#include <klocale.h>
+
+#include <stdio.h>
+
+// application specific includes
+#include "pmview.h"
+#include "pmpart.h"
+#include "pmtreeview.h"
+#include "pmdialogview.h"
+#include "pmglview.h"
+
+PMView::PMView( PMPart* part, QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ setBackgroundMode( PaletteBase );
+
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ m_pMainSplitter = new QSplitter( Qt::Horizontal, this, "MainSplitter" );
+ m_pTreeEditSplitter = new QSplitter( Qt::Vertical, m_pMainSplitter,
+ "TreeEditSplitter" );
+
+
+ m_pTreeView = new PMTreeView( part, m_pTreeEditSplitter, "TreeView" );
+ m_pTreeView->show( );
+
+ m_pDialogView = new PMDialogView( part, m_pTreeEditSplitter, "EditView" );
+ m_pDialogView->show( );
+
+
+ QWidget* glArea = new QWidget( m_pMainSplitter, "GLArea" );
+ glArea->show( );
+ PMGLView* gl;
+
+ QGridLayout* topLayout = new QGridLayout( glArea, 2, 2, 1, 1 );
+ gl = new PMGLView( part, PMGLView::PMViewPosZ, glArea );
+ topLayout->addWidget( gl, 0, 0 );
+ gl = new PMGLView( part, PMGLView::PMViewPosX, glArea );
+ topLayout->addWidget( gl, 0, 1 );
+ gl = new PMGLView( part, PMGLView::PMViewNegY, glArea );
+ topLayout->addWidget( gl, 1, 0 );
+ gl = new PMGLView( part, PMGLView::PMViewCamera, glArea );
+ topLayout->addWidget( gl, 1, 1 );
+
+ m_pMainSplitter->show( );
+
+ layout->addWidget( m_pMainSplitter );
+ layout->activate( );
+
+ m_pPart = part;
+}
+
+PMView::~PMView( )
+{
+}
+
+void PMView::print( QPrinter* pPrinter )
+{
+ QPainter printpainter;
+ printpainter.begin( pPrinter );
+
+ // TODO: add your printing code here
+
+ printpainter.end( );
+}
+
+void PMView::saveConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+
+ cfg->writeEntry( "MainSplitter", m_pMainSplitter->sizes( ) );
+ cfg->writeEntry( "TreeEditSplitter", m_pTreeEditSplitter->sizes( ) );
+}
+
+void PMView::restoreConfig( KConfig* cfg )
+{
+ cfg->setGroup( "Appearance" );
+
+ m_pMainSplitter->setSizes( cfg->readIntListEntry( "MainSplitter" ) );
+ m_pTreeEditSplitter->setSizes( cfg->readIntListEntry( "TreeEditSplitter" ) );
+}
+
+
+#include "pmview.moc"
diff --git a/kpovmodeler/pmview.h b/kpovmodeler/pmview.h
new file mode 100644
index 00000000..8a216663
--- /dev/null
+++ b/kpovmodeler/pmview.h
@@ -0,0 +1,76 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMVIEW_H
+#define PMVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// include files for Qt
+#include <qwidget.h>
+
+class PMTreeView;
+class PMDialogView;
+class PMPart;
+class QSplitter;
+class KConfig;
+
+/**
+ * The PMView class provides the view widget for the PMPart document class.
+ */
+class PMView : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor for the main view
+ */
+ PMView( PMPart* part, QWidget* parent = 0, const char* name = 0 );
+ /**
+ * Destructor for the main view
+ */
+ ~PMView( );
+
+ /**
+ * returns a pointer to the part
+ */
+ PMPart* part( ) const { return m_pPart; }
+
+ /**
+ * contains the implementation for printing functionality TODO*/
+ void print( QPrinter* pPrinter );
+ /**
+ * saves settings
+ */
+ void saveConfig( KConfig* cfg );
+ /**
+ * loads settings
+ */
+ void restoreConfig( KConfig* cfg );
+private:
+ PMTreeView* m_pTreeView;
+ PMPart* m_pPart;
+ PMDialogView* m_pDialogView;
+ QSplitter* m_pMainSplitter;
+ QSplitter* m_pTreeEditSplitter;
+};
+
+#endif
diff --git a/kpovmodeler/pmviewbase.cpp b/kpovmodeler/pmviewbase.cpp
new file mode 100644
index 00000000..44c239ef
--- /dev/null
+++ b/kpovmodeler/pmviewbase.cpp
@@ -0,0 +1,20 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmviewbase.h"
+
+#include "pmviewbase.moc"
diff --git a/kpovmodeler/pmviewbase.h b/kpovmodeler/pmviewbase.h
new file mode 100644
index 00000000..cce59922
--- /dev/null
+++ b/kpovmodeler/pmviewbase.h
@@ -0,0 +1,128 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMVIEWBASE_H
+#define PMVIEWBASE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qstring.h>
+
+class QDomElement;
+
+/**
+ * This class stores the view configuration for one view.
+ *
+ * Reimplement this class for each view type that has to store
+ * additional values.
+ *
+ * Created, loaded from and saved to the xml config by the corresponding
+ * @ref PMViewTypeFactory factory class.
+ */
+class PMViewOptions
+{
+public:
+ /**
+ * Returns a deep copy
+ */
+ virtual PMViewOptions* copy( ) const = 0;
+ /**
+ * Returns the identifier for the view type. Has to be equal
+ * to @ref PMViewBase::viewType for the corresponding view type.
+ */
+ virtual QString viewType( ) const = 0;
+ /**
+ * Loads the data from the xml element
+ */
+ virtual void loadData( QDomElement& e ) = 0;
+ /**
+ * Saves the data from to xml element
+ */
+ virtual void saveData( QDomElement& e ) = 0;
+};
+
+/**
+ * Base class for configuration widgets for view types
+ * for the layout settings dialog page
+ */
+class PMViewOptionsWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMViewOptionsWidget( QWidget* parent, const char* name = 0 )
+ : QWidget( parent, name )
+ {
+ }
+
+signals:
+ /**
+ * Emitted when the view type description has changed
+ */
+ void viewTypeDescriptionChanged( );
+};
+
+/**
+ * Interface for views.
+ *
+ * Each view type has to implement this interface. Handles the
+ * config loading and saving
+ */
+class PMViewBase : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ PMViewBase( QWidget* parent, const char* name = 0, WFlags f = 0 )
+ : QWidget( parent, name, f )
+ {
+ }
+ /**
+ * Returns the identifier for the view type. Has to be unique
+ * for all view types.
+ */
+ virtual QString viewType( ) const = 0;
+ /**
+ * Returns a i18n'ed description
+ */
+ virtual QString description( ) const = 0;
+ /**
+ * Restores the view configuration
+ *
+ * Reimplement this function if the view type has to
+ * restore additional values.
+ * @see PMViewOptions
+ */
+ virtual void restoreViewConfig( PMViewOptions* ) { }
+ /**
+ * Saves the view configuration
+ *
+ * Reimplement this function if the view type has to
+ * restore additional values.
+ * @see PMViewOptions
+ */
+ virtual void saveViewConfig( PMViewOptions* ) const { }
+};
+
+#endif
diff --git a/kpovmodeler/pmviewfactory.cpp b/kpovmodeler/pmviewfactory.cpp
new file mode 100644
index 00000000..58e566cc
--- /dev/null
+++ b/kpovmodeler/pmviewfactory.cpp
@@ -0,0 +1,94 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmviewfactory.h"
+#include "pmglview.h"
+#include "pmtreeview.h"
+#include "pmdialogview.h"
+#include "pmdebug.h"
+#include "pmviewbase.h"
+#include "pmglview.h"
+#include "pmtreeview.h"
+#include "pmdialogview.h"
+#include "pmlibrarybrowser.h"
+
+#include <klocale.h>
+
+PMViewFactory* PMViewFactory::s_pInstance = 0;
+KStaticDeleter<PMViewFactory> PMViewFactory::s_staticDeleter;
+
+PMViewFactory::PMViewFactory( )
+{
+ m_viewTypes.setAutoDelete( true );
+ addViewType( new PMTreeViewFactory( ) );
+ addViewType( new PMDialogViewFactory( ) );
+ addViewType( new PMGLViewFactory( ) );
+ addViewType( new PMLibraryBrowserViewFactory( ) );
+}
+
+PMViewFactory::~PMViewFactory( )
+{
+ m_viewTypes.clear( );
+}
+
+PMViewFactory* PMViewFactory::theFactory( )
+{
+ if( !s_pInstance )
+ s_staticDeleter.setObject( s_pInstance, new PMViewFactory( ) );
+ return s_pInstance;
+}
+
+void PMViewFactory::addViewType( PMViewTypeFactory* vt )
+{
+ if( vt )
+ {
+ m_viewTypes.append( vt );
+ m_dict.insert( vt->viewType( ), vt );
+ }
+}
+
+PMViewBase* PMViewFactory::newViewInstance( const QString& viewType,
+ QWidget* parent, PMPart* part ) const
+{
+ PMViewTypeFactory* f = m_dict.find( viewType );
+ if( f )
+ return f->newInstance( parent, part );
+
+ kdError( PMArea ) << "Unknown view type \"" << viewType << "\"" << endl;
+ return 0;
+}
+
+PMViewOptions* PMViewFactory::newOptionsInstance( const QString& viewType ) const
+{
+ PMViewTypeFactory* f = m_dict.find( viewType );
+ if( f )
+ return f->newOptionsInstance( );
+
+ kdError( PMArea ) << "Unknown view type \"" << viewType << "\"" << endl;
+ return 0;
+}
+
+PMViewTypeFactory* PMViewFactory::viewFactory( const QString& viewType ) const
+{
+ return m_dict.find( viewType );
+}
+
+const QPtrList<PMViewTypeFactory>& PMViewFactory::viewTypes( ) const
+{
+ return m_viewTypes;
+}
+
diff --git a/kpovmodeler/pmviewfactory.h b/kpovmodeler/pmviewfactory.h
new file mode 100644
index 00000000..b24814cf
--- /dev/null
+++ b/kpovmodeler/pmviewfactory.h
@@ -0,0 +1,145 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMVIEWFACTORY_H
+#define PMVIEWFACTORY_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qptrlist.h>
+#include <qdict.h>
+#include <kstaticdeleter.h>
+
+class PMViewBase;
+class QWidget;
+class PMPart;
+class QDomElement;
+class PMViewOptions;
+class PMViewOptionsWidget;
+
+/**
+ * Factory and description class for one view type
+ * @see PMViewFactory
+ */
+class PMViewTypeFactory
+{
+public:
+ /**
+ * Default constructor
+ */
+ PMViewTypeFactory( ) { }
+ /**
+ * Destructor
+ */
+ virtual ~PMViewTypeFactory( ) { }
+ /**
+ * Returns the id for the view type. Choose an unique name.
+ */
+ virtual QString viewType( ) const = 0;
+ /**
+ * Returns a i18n'ed description for the view type
+ */
+ virtual QString description( ) const = 0;
+ /**
+ * Returns a i18n'ed description for the view type, dependent
+ * on the options. Calls the method above by default.
+ */
+ virtual QString description( PMViewOptions* ) const
+ {
+ return description( );
+ }
+ /**
+ * Returns the icon name for the view
+ */
+ virtual QString iconName( ) const = 0;
+ /**
+ * Returns a new view instance
+ */
+ virtual PMViewBase* newInstance( QWidget* parent, PMPart* part ) const = 0;
+ /**
+ * Creates a config object for the view type.
+ * If the view doesn't have special attributes, the function returns 0;
+ */
+ virtual PMViewOptions* newOptionsInstance( ) const { return 0; }
+ /**
+ * Creates a widget to configure the custom options
+ */
+ virtual PMViewOptionsWidget* newOptionsWidget( QWidget*, PMViewOptions* )
+ {
+ return 0;
+ }
+};
+
+
+/**
+ * Factory class for KPovModeler views.
+ *
+ * Plugins can add new view types by adding new
+ * @ref PMViewTypeFactory objects.
+ */
+class PMViewFactory
+{
+public:
+ /**
+ * Destructor
+ */
+ ~PMViewFactory( );
+ /**
+ * Returns the factory instance
+ */
+ static PMViewFactory* theFactory( );
+
+ /**
+ * Adds a new view type
+ *
+ * The factory becomes the owner of the object
+ */
+ void addViewType( PMViewTypeFactory* vt );
+ /**
+ * Returns a new view of type viewType if available
+ */
+ PMViewBase* newViewInstance( const QString& viewType,
+ QWidget* parent, PMPart* part ) const;
+ /**
+ * Returns a new view option instance for the given view type
+ */
+ PMViewOptions* newOptionsInstance( const QString& viewType ) const;
+ /**
+ * Returns the factory for the given view type
+ */
+ PMViewTypeFactory* viewFactory( const QString& viewType ) const;
+ /**
+ * Returns the list of available view types
+ */
+ const QPtrList<PMViewTypeFactory>& viewTypes( ) const;
+private:
+ /**
+ * Constructor
+ */
+ PMViewFactory( );
+
+ QPtrList<PMViewTypeFactory> m_viewTypes;
+ QDict<PMViewTypeFactory> m_dict;
+
+ static PMViewFactory* s_pInstance;
+ static KStaticDeleter<PMViewFactory> s_staticDeleter;
+};
+
+#endif
diff --git a/kpovmodeler/pmviewlayoutmanager.cpp b/kpovmodeler/pmviewlayoutmanager.cpp
new file mode 100644
index 00000000..593eed27
--- /dev/null
+++ b/kpovmodeler/pmviewlayoutmanager.cpp
@@ -0,0 +1,935 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmviewlayoutmanager.h"
+#include "pmdockwidget_private.h"
+
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include <kfilterdev.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+
+#include <qfile.h>
+#include <qdom.h>
+#include <qwidgetlist.h>
+#include <qlistbox.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include "pmshell.h"
+#include "pmdebug.h"
+#include "pmviewfactory.h"
+
+PMViewLayoutManager* PMViewLayoutManager::s_pInstance = 0;
+KStaticDeleter<PMViewLayoutManager> PMViewLayoutManager::s_staticDeleter;
+
+
+//================ PMViewLayoutEntry ====================
+
+PMViewLayoutEntry::PMViewLayoutEntry( )
+{
+ m_viewType = "treeview";
+ m_dockPosition = PMDockWidget::DockRight;
+ m_columnWidth = 33;
+ m_height = 50;
+ m_floatingWidth = 400;
+ m_floatingHeight = 400;
+ m_floatingPositionX = 200;
+ m_floatingPositionY = 200;
+ m_pCustomOptions = 0;
+}
+
+PMViewLayoutEntry::PMViewLayoutEntry( const PMViewLayoutEntry& e )
+{
+ m_viewType = e.m_viewType;
+ m_dockPosition = e.m_dockPosition;
+ m_columnWidth = e.m_columnWidth;
+ m_height = e.m_height;
+ m_floatingWidth = e.m_floatingWidth;
+ m_floatingHeight = e.m_floatingHeight;
+ m_floatingPositionX = e.m_floatingPositionX;
+ m_floatingPositionY = e.m_floatingPositionY;
+ if( e.m_pCustomOptions )
+ m_pCustomOptions = e.m_pCustomOptions->copy( );
+ else
+ m_pCustomOptions = 0;
+}
+
+PMViewLayoutEntry::~PMViewLayoutEntry( )
+{
+ if( m_pCustomOptions )
+ delete m_pCustomOptions;
+}
+
+void PMViewLayoutEntry::loadData( QDomElement& e )
+{
+ QString s;
+ bool ok;
+
+ // Read the view type
+ s = e.tagName( );
+ m_viewType = s;
+
+ // Read dock position
+ s = e.attribute( "position", "Right" );
+ if( s == "Right" ) m_dockPosition = PMDockWidget::DockRight;
+ else if( s == "Bottom" ) m_dockPosition = PMDockWidget::DockBottom;
+ else if( s == "Center" ) m_dockPosition = PMDockWidget::DockCenter;
+ else if( s == "None" ) m_dockPosition = PMDockWidget::DockNone;
+
+ // Read the column width
+ s = e.attribute( "columnWidth", "33" );
+ m_columnWidth = s.toInt( &ok );
+ if( !ok ) m_columnWidth = 33;
+
+ // and view height
+ s = e.attribute( "height", "50" );
+ m_height = s.toInt( &ok );
+ if( !ok ) m_height = 50;
+
+ s = e.attribute( "floatingHeight", "400" );
+ m_floatingHeight = s.toInt( &ok );
+ if( !ok ) m_floatingHeight = 400;
+ s = e.attribute( "floatingWidth", "400" );
+ m_floatingWidth = s.toInt( &ok );
+ if( !ok ) m_floatingWidth = 400;
+
+ s = e.attribute( "floatingPosX", "200" );
+ m_floatingPositionX = s.toInt( &ok );
+ if( !ok ) m_floatingPositionX = 200;
+ s = e.attribute( "floatingPosY", "200" );
+ m_floatingPositionY = s.toInt( &ok );
+ if( !ok ) m_floatingPositionY = 200;
+
+ // Load custom options
+ if( m_pCustomOptions )
+ delete m_pCustomOptions;
+ m_pCustomOptions =
+ PMViewFactory::theFactory( )->newOptionsInstance( m_viewType );
+ if( m_pCustomOptions )
+ m_pCustomOptions->loadData( e );
+}
+
+void PMViewLayoutEntry::saveData( QDomElement& e ) const
+{
+ QString s;
+ e.setTagName( m_viewType );
+ switch( m_dockPosition )
+ {
+ case PMDockWidget::DockRight:
+ e.setAttribute( "position", "Right" );
+ break;
+ case PMDockWidget::DockBottom:
+ e.setAttribute( "position", "Bottom" );
+ break;
+ case PMDockWidget::DockCenter:
+ e.setAttribute( "position", "Center" );
+ break;
+ case PMDockWidget::DockNone:
+ e.setAttribute( "position", "None" );
+ break;
+ default:
+ kdError( PMArea ) << i18n( "Unknown dock position." )
+ << endl;
+ break;
+ }
+ s.setNum( m_columnWidth );
+ e.setAttribute( "columnWidth", s );
+ s.setNum( m_height );
+ e.setAttribute( "height", s );
+ s.setNum( m_floatingHeight );
+ e.setAttribute( "floatingHeight", s );
+ s.setNum( m_floatingWidth );
+ e.setAttribute( "floatingWidth", s );
+ s.setNum( m_floatingPositionX );
+ e.setAttribute( "floatingPosX", s );
+ s.setNum( m_floatingPositionY );
+ e.setAttribute( "floatingPosY", s );
+
+ // save custom options
+ if( m_pCustomOptions )
+ m_pCustomOptions->saveData( e );
+}
+
+void PMViewLayoutEntry::setViewType( const QString& v )
+{
+ m_viewType = v;
+}
+
+void PMViewLayoutEntry::setDockPosition( PMDockWidget::DockPosition i )
+{
+ m_dockPosition = i;
+}
+
+void PMViewLayoutEntry::setColumnWidth( int i )
+{
+ m_columnWidth = i;
+ if( i < 1 )
+ m_columnWidth = 1;
+}
+
+void PMViewLayoutEntry::setHeight( int i )
+{
+ m_height = i;
+ if( i < 1 )
+ m_height = 1;
+}
+
+const QString PMViewLayoutEntry::viewTypeAsString( )
+{
+ PMViewTypeFactory* f = PMViewFactory::theFactory( )->viewFactory( m_viewType );
+ if( f )
+ {
+ if( m_pCustomOptions )
+ return f->description( m_pCustomOptions );
+ else
+ return f->description( );
+ }
+
+ kdError( PMArea ) << i18n( "Unknown view type." )<< endl;
+ return i18n( "Unknown" );
+}
+
+const QString PMViewLayoutEntry::dockPositionAsString( )
+{
+ switch( m_dockPosition )
+ {
+ case PMDockWidget::DockRight:
+ return i18n( "New Column" );
+ case PMDockWidget::DockBottom:
+ return i18n( "Below" );
+ case PMDockWidget::DockCenter:
+ return i18n( "Tabbed" );
+ case PMDockWidget::DockNone:
+ return i18n( "Floating" );
+ default:
+ kdError( PMArea ) << i18n( "Unknown dock position." )
+ << endl;
+ return i18n( "unknown" );
+ }
+}
+
+void PMViewLayoutEntry::setCustomOptions( PMViewOptions* o )
+{
+ if( m_pCustomOptions && m_pCustomOptions != o )
+ delete m_pCustomOptions;
+ m_pCustomOptions = o;
+}
+
+//================== PMViewLayout ======================
+
+PMViewLayout::PMViewLayout( )
+{
+ m_entries.clear( );
+}
+
+PMViewLayout::PMViewLayout( const PMViewLayout& vl )
+{
+ m_entries = vl.m_entries;
+ m_name = vl.m_name;
+}
+
+PMViewLayout& PMViewLayout::operator = ( const PMViewLayout& vl )
+{
+ m_entries = vl.m_entries;
+ m_name = vl.m_name;
+ return *this;
+}
+
+void PMViewLayout::loadData( QDomElement& e )
+{
+ m_entries.clear( );
+ m_name = e.attribute( "name", "unnamed" );
+
+ QDomNode m = e.firstChild( );
+ while( !m.isNull( ) )
+ {
+ if( m.isElement( ) )
+ {
+ QDomElement me = m.toElement( );
+ PMViewLayoutEntry vle;
+
+ vle.loadData( me );
+ m_entries.append( vle );
+ }
+ m = m.nextSibling( );
+ }
+ normalize( );
+}
+
+void PMViewLayout::saveData( QDomElement& e, QDomDocument& doc ) const
+{
+ QValueList< PMViewLayoutEntry>::const_iterator it;
+
+ e.setAttribute( "name", m_name );
+ for( it = m_entries.begin( ); it != m_entries.end( ) ; ++it )
+ {
+ QDomElement a;
+ a = doc.createElement( "unknown" );
+ ( *it ).saveData( a );
+ e.appendChild( a );
+ }
+}
+
+void PMViewLayout::setName( const QString& n )
+{
+ m_name = n;
+}
+
+void PMViewLayout::addEntry( const PMViewLayoutEntry& e, int index )
+{
+ if( index == -1 )
+ m_entries.append( e );
+ else
+ m_entries.insert( m_entries.at( index ), 1, e );
+}
+
+void PMViewLayout::removeEntry( int index )
+{
+ m_entries.remove( m_entries.at( index ) );
+}
+
+void PMViewLayout::displayLayout( PMShell* shell )
+{
+ PMDockWidget* lastWidget = 0;
+ QValueList< PMViewLayoutEntry>::const_iterator it;
+ bool isViewSet = false;
+ int lastWidth = 0, width = 100;
+ int lastHeight = 0, height = 100;
+
+ for( it = m_entries.begin( ); it != m_entries.end( ) ; ++it )
+ {
+ PMDockWidget* dock = shell->createView( ( *it ).viewType( ),
+ ( *it ).customOptions( ),
+ false );
+ // Dock the widget
+ if( ( *it ).dockPosition( ) == PMDockWidget::DockNone )
+ {
+ // the specified target is the desktop
+ dock->manualDock( 0, PMDockWidget::DockDesktop, 50,
+ QPoint( ( *it ).floatingPositionX( ),
+ ( *it ).floatingPositionY( ) ) );
+ dock->resize( ( *it ).floatingWidth( ), ( *it ).floatingHeight( ) );
+ dock->show( );
+ }
+ else
+ {
+ // the first dockwidget is not docked but placed on all the window
+ // through setView( )
+ if( !isViewSet )
+ {
+ shell->setView( dock );
+ isViewSet = true;
+ lastWidget = dock;
+ }
+ else
+ {
+ switch( ( *it ).dockPosition( ) )
+ {
+ case PMDockWidget::DockRight:
+ dock->manualDock( lastWidget, ( *it ).dockPosition( ),
+ lastWidth * 100 / width );
+
+ width -= lastWidth;
+ if( width < 1 ) width = 1;
+ height = 100;
+ lastWidget = dock;
+ break;
+ case PMDockWidget::DockBottom:
+ dock->manualDock( lastWidget, ( *it ).dockPosition( ),
+ lastHeight * 100 / height );
+ height -= lastHeight;
+ if( height < 1 ) height = 1;
+ lastWidget = dock;
+ break;
+ case PMDockWidget::DockCenter:
+ dock->manualDock( lastWidget, ( *it ).dockPosition( ), 100 );
+ break;
+ default:
+ dock->manualDock( 0, PMDockWidget::DockDesktop, 100 );
+ break;
+ }
+ }
+
+ switch( ( *it ).dockPosition( ) )
+ {
+ case PMDockWidget::DockRight:
+ lastWidth = ( *it ).columnWidth( );
+ lastHeight = ( *it ).height( );
+ break;
+ case PMDockWidget::DockBottom:
+ lastHeight = ( *it ).height( );
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void PMViewLayout::normalize( )
+{
+ iterator it;
+ int sumColWidth = 0;
+
+ it = m_entries.begin( );
+ // the first entry has to be a new column
+ if( it != m_entries.end( ) )
+ if( ( *it ).dockPosition( ) != PMDockWidget::DockRight )
+ ( *it ).setDockPosition( PMDockWidget::DockRight );
+
+ // find negative or zero widths and heights
+ for( it = m_entries.begin( ); it != m_entries.end( ); ++it )
+ {
+ if( ( *it ).columnWidth( ) < 1 )
+ ( *it ).setColumnWidth( 1 );
+ if( ( *it ).height( ) < 1 )
+ ( *it ).setHeight( 1 );
+ }
+
+ // normalize the column widths
+ for( it = m_entries.begin( ); it != m_entries.end( ); ++it )
+ if( ( *it ).dockPosition( ) == PMDockWidget::DockRight )
+ sumColWidth += ( *it ).columnWidth( );
+ if( sumColWidth == 0 )
+ sumColWidth = 1;
+
+ for( it = m_entries.begin( ); it != m_entries.end( ); ++it )
+ {
+ if( ( *it ).dockPosition( ) == PMDockWidget::DockRight )
+ {
+ ( *it ).setColumnWidth( ( int ) ( ( *it ).columnWidth( ) * 100.0
+ / sumColWidth + 0.5 ) );
+ // normalize each column
+ iterator it2 = it;
+ int height = ( *it ).height( );
+
+ for( it2++; it2 != m_entries.end( ) &&
+ ( *it2 ).dockPosition( ) != PMDockWidget::DockRight; ++it2 )
+ if( ( *it2 ).dockPosition( ) == PMDockWidget::DockBottom )
+ height += ( *it2 ).height( );
+ if( height == 0 )
+ height = 1;
+ ( *it ).setHeight( ( int ) ( ( *it ).height( ) * 100.0
+ / height + 0.5 ) );
+ it2 = it;
+ for( it2++; it2 != m_entries.end( ) &&
+ ( *it2 ).dockPosition( ) != PMDockWidget::DockRight; ++it2 )
+ if( ( *it2 ).dockPosition( ) == PMDockWidget::DockBottom )
+ ( *it2 ).setHeight( ( int ) ( ( *it2 ).height( ) * 100.0
+ / height + 0.5 ) );
+ }
+ }
+}
+
+PMViewLayout PMViewLayout::extractViewLayout( PMShell* shell )
+{
+ PMViewLayout layout;
+
+ QValueList< QValueList< PMViewLayoutEntry > > cols;
+ cols.append( QValueList< PMViewLayoutEntry >( ) );
+
+ // find docked widgets
+ recursiveExtractColumns( cols, cols.begin( ), 100,
+ shell->centralWidget( ) );
+
+ QValueListIterator< QValueList< PMViewLayoutEntry > > cit;
+ QValueListIterator< PMViewLayoutEntry > eit;
+
+ for( cit = cols.begin( ); cit != cols.end( ); ++cit )
+ for( eit = ( *cit ).begin( ); eit != ( *cit ).end( ); ++eit )
+ layout.addEntry( *eit );
+
+ // find floating widgets
+ QPtrList<PMDockWidget> list;
+ shell->manager( )->findFloatingWidgets( list );
+ QPtrListIterator<PMDockWidget> it( list );
+
+ for( ; it.current( ); ++it )
+ {
+ kdDebug( PMArea ) << it.current( ) << " " << it.current( )->isVisible( ) << endl;
+ QWidget* w = it.current( )->getWidget( );
+ if( w )
+ {
+ bool invalid = false;
+ PMViewLayoutEntry e;
+ e.setDockPosition( PMDockWidget::DockNone );
+ QPoint p = it.current( )->pos( );
+ e.setFloatingPositionX( p.x( ) );
+ e.setFloatingPositionY( p.y( ) );
+ e.setFloatingWidth( it.current( )->width( ) );
+ e.setFloatingHeight( it.current( )->height( ) );
+
+ if( w->inherits( "PMViewBase" ) )
+ {
+ PMViewBase* v = ( PMViewBase* ) w;
+ e.setViewType( v->viewType( ) );
+ PMViewOptions* vo =
+ PMViewFactory::theFactory( )->newOptionsInstance( v->viewType( ) );
+ if( vo )
+ {
+ v->saveViewConfig( vo );
+ e.setCustomOptions( vo );
+ }
+ }
+ else
+ invalid = true;
+
+ if( !invalid )
+ layout.addEntry( e );
+ }
+ }
+
+ return layout;
+}
+
+void PMViewLayout::recursiveExtractColumns(
+ QValueList< QValueList< PMViewLayoutEntry > >& cols,
+ QValueList< QValueList< PMViewLayoutEntry > >::iterator cit,
+ int width, QWidget* widget )
+{
+ if( !widget )
+ return;
+
+ if( widget->inherits( "PMDockWidget" ) )
+ {
+ PMDockWidget* dw = ( PMDockWidget* ) widget;
+ QWidget* w = dw->getWidget( );
+ if( w )
+ {
+ bool colStart = true;
+ if( w->inherits( "PMDockSplitter" ) )
+ {
+ PMDockSplitter* sp = ( PMDockSplitter* ) w;
+ if( sp->splitterOrientation( ) == Qt::Vertical )
+ {
+ colStart = false;
+ // vertical splitter, split up the current column
+ int w1 = ( int ) ( width * 0.01 * sp->separatorPos( ) + 0.5 );
+ int w2 = width - w1;
+ if( w1 == 0 ) w1++;
+ if( w2 == 0 ) w2++;
+
+ QValueList< QValueList< PMViewLayoutEntry > >::iterator cit1
+ = cols.insert( cit, QValueList< PMViewLayoutEntry >( ) );
+
+ recursiveExtractColumns( cols, cit1, w1, sp->getFirst( ) );
+ recursiveExtractColumns( cols, cit, w2, sp->getLast( ) );
+ }
+ }
+ if( colStart )
+ {
+ // widget is a view, a horizontal splitter or a tab widget
+ // a new column starts
+ PMViewLayoutEntry e;
+ e.setColumnWidth( width );
+ ( *cit ).append( e );
+ recursiveExtractOneColumn( *cit, ( *cit ).begin( ), 100, dw );
+ }
+ }
+ }
+}
+
+void PMViewLayout::recursiveExtractOneColumn(
+ QValueList< PMViewLayoutEntry >& entries,
+ QValueList< PMViewLayoutEntry >::iterator eit,
+ int height, QWidget* widget )
+{
+ if( !widget )
+ return;
+
+ if( widget->inherits( "PMDockWidget" ) )
+ {
+ PMDockWidget* dw = ( PMDockWidget* ) widget;
+ QWidget* w = dw->getWidget( );
+ if( w )
+ {
+ if( w->inherits( "PMDockSplitter" ) )
+ {
+ PMDockSplitter* sp = ( PMDockSplitter* ) w;
+ // splitter, split up the current column
+ int h1 = ( int ) ( height * 0.01 * sp->separatorPos( ) + 0.5 );
+ int h2 = height - h1;
+ if( h1 == 0 ) h1++;
+ if( h2 == 0 ) h2++;
+
+ ( *eit ).setHeight( h1 );
+ ( *eit ).setDockPosition( PMDockWidget::DockRight );
+
+ PMViewLayoutEntry e;
+ e.setHeight( h2 );
+ e.setDockPosition( PMDockWidget::DockBottom );
+ QValueList< PMViewLayoutEntry >::iterator eit1 = eit;
+ eit1 = entries.insert( ++eit1, e );
+
+ recursiveExtractOneColumn( entries, eit, h1, sp->getFirst( ) );
+ recursiveExtractOneColumn( entries, eit1, h2, sp->getLast( ) );
+ }
+ else if( w->inherits( "PMDockTabGroup" ) )
+ {
+ PMDockTabGroup* g = ( PMDockTabGroup* ) w;
+ int num = g->count( );
+ QWidget* tw;
+ int i;
+ for( i = 0; i < num; i++ )
+ {
+ tw = g->page( i );
+ if( i == 0 )
+ recursiveExtractOneColumn( entries, eit, height, tw );
+ else
+ {
+ PMViewLayoutEntry e;
+ e.setHeight( height );
+ e.setDockPosition( PMDockWidget::DockCenter );
+
+ eit++;
+ eit = entries.insert( eit, e );
+ recursiveExtractOneColumn( entries, eit, height, tw );
+ }
+ }
+ }
+ else
+ {
+ // a kpovmodeler view???
+ if( w->inherits( "PMViewBase" ) )
+ {
+ PMViewBase* v = ( PMViewBase* ) w;
+ ( *eit ).setViewType( v->viewType( ) );
+ PMViewOptions* vo =
+ PMViewFactory::theFactory( )->newOptionsInstance( v->viewType( ) );
+ if( vo )
+ {
+ v->saveViewConfig( vo );
+ ( *eit ).setCustomOptions( vo );
+ }
+ }
+ }
+ }
+ }
+}
+
+//=============== PMViewLayoutManager ===================
+
+PMViewLayoutManager::PMViewLayoutManager( )
+{
+ m_layoutsLoaded = false;
+ m_layoutDisplayed = false;
+ loadData( );
+}
+
+PMViewLayoutManager::~PMViewLayoutManager( )
+{
+}
+
+void PMViewLayoutManager::setDefaultLayout( const QString& name )
+{
+ m_defaultLayout = name;
+}
+
+QStringList PMViewLayoutManager::availableLayouts( )
+{
+ QStringList result;
+ QValueListIterator<PMViewLayout> it;
+
+ for( it = m_layouts.begin( ); it != m_layouts.end( ); ++it )
+ result.push_back( ( *it ).name( ) );
+
+ return result;
+}
+
+void PMViewLayoutManager::loadData( )
+{
+ if( m_layoutsLoaded )
+ m_layouts.clear( );
+
+ m_layoutsLoaded = true;
+
+ QString fileName = locate( "data", "kpovmodeler/viewlayouts.xml" );
+ if( fileName.isEmpty( ) )
+ {
+ // Generate a default layout
+ // I have a feeling this shouldn't be here but hey, it works for now
+ // TODO Must find a way to move this cleanly to PMShell
+ PMViewLayout a;
+ a.setName( i18n( "Default" ) );
+ PMViewLayoutEntry p;
+ p.setViewType( "treeview" );
+ p.setDockPosition( PMDockWidget::DockRight );
+ p.setHeight( 50 );
+ p.setColumnWidth( 33 );
+ a.addEntry( p );
+ p.setViewType( "dialogview" );
+ p.setDockPosition( PMDockWidget::DockBottom );
+ p.setHeight( 50 );
+ a.addEntry( p );
+ p.setViewType( "glview" );
+ p.setCustomOptions( new PMGLViewOptions( PMGLView::PMViewPosX ) );
+ p.setDockPosition( PMDockWidget::DockRight );
+ p.setHeight( 50 );
+ p.setColumnWidth( 33 );
+ a.addEntry( p );
+ p.setCustomOptions( new PMGLViewOptions( PMGLView::PMViewNegY ) );
+ p.setDockPosition( PMDockWidget::DockBottom );
+ p.setHeight( 50 );
+ a.addEntry( p );
+ p.setCustomOptions( new PMGLViewOptions( PMGLView::PMViewPosZ ) );
+ p.setDockPosition( PMDockWidget::DockRight );
+ p.setHeight( 50 );
+ p.setColumnWidth( 33 );
+ a.addEntry( p );
+ p.setCustomOptions( new PMGLViewOptions( PMGLView::PMViewCamera ) );
+ p.setDockPosition( PMDockWidget::DockBottom );
+ p.setHeight( 50 );
+ a.addEntry( p );
+
+ m_layouts.append( a );
+ m_defaultLayout = a.name( );
+
+ return;
+ }
+
+ QFile file( fileName );
+ if( !file.open( IO_ReadOnly ) )
+ {
+ kdError( PMArea ) << i18n( "Could not open the view layouts file." )
+ << endl;
+ return;
+ }
+
+ QDomDocument doc( "VIEWLAYOUTS" );
+ doc.setContent( &file );
+
+ QDomElement e = doc.documentElement( );
+ m_defaultLayout = e.attribute( "default", "empty" );
+
+ QDomNode c = e.firstChild( );
+
+ QString str;
+
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ PMViewLayout v;
+ v.loadData( ce );
+ m_layouts.append( v );
+ }
+ c = c.nextSibling( );
+ }
+}
+
+void PMViewLayoutManager::saveData( )
+{
+ QString fileName = locateLocal( "data", "kpovmodeler/viewlayouts.xml" );
+ if( fileName.isEmpty( ) )
+ {
+ kdError( PMArea ) << i18n( "View layouts not found." ) << endl;
+ return;
+ }
+ QFile file( fileName );
+ if( !file.open( IO_WriteOnly ) )
+ {
+ kdError( PMArea ) << i18n( "Could not open the view layouts file." )
+ << endl;
+ return;
+ }
+ QDomDocument doc( "VIEWLAYOUTS" );
+ QDomElement e = doc.createElement( "viewlist" );
+ e.setAttribute( "default", m_defaultLayout );
+
+ QValueListIterator<PMViewLayout> it;
+
+ for( it = m_layouts.begin( ); it != m_layouts.end( ); ++it )
+ {
+ QDomElement l;
+
+ l = doc.createElement( "viewlayout" );
+ ( *it ).saveData( l, doc );
+ e.appendChild( l );
+ }
+ doc.appendChild( e );
+ QTextStream str( &file );
+ str.setEncoding( QTextStream::UnicodeUTF8 );
+ str << doc.toString( );
+ file.close( );
+}
+
+PMViewLayoutManager* PMViewLayoutManager::theManager( )
+{
+ if( !s_pInstance )
+ s_staticDeleter.setObject( s_pInstance, new PMViewLayoutManager( ) );
+ return s_pInstance;
+}
+
+void PMViewLayoutManager::displayLayout( const QString& name, PMShell* shell )
+{
+ PMViewLayout* v_layout = findLayout( name );
+
+ if( v_layout )
+ {
+ // Destroy the existing dock widgets
+ if( m_layoutDisplayed )
+ {
+ QWidgetList lst;
+
+ if( shell->centralWidget( ) )
+ shell->manager( )->findChildDockWidget( shell->centralWidget( ), lst );
+ while( lst.first( ) )
+ {
+ ( ( PMDockWidget* )lst.first( ) )->undock( );
+ ( ( PMDockWidget* )lst.first( ) )->close( );
+ lst.remove( );
+ }
+
+ QPtrList<PMDockWidget> flist;
+ shell->manager( )->findFloatingWidgets( flist );
+ while( flist.first( ) )
+ {
+ flist.first( )->undock( );
+ flist.first( )->close( );
+ flist.remove( );
+ }
+ }
+ // Create the new layout
+ v_layout->displayLayout( shell );
+ m_layoutDisplayed = true;
+ }
+}
+
+void PMViewLayoutManager::displayDefaultLayout( PMShell* shell )
+{
+ displayLayout( m_defaultLayout, shell );
+}
+
+PMViewLayout* PMViewLayoutManager::findLayout( const QString& name )
+{
+ QValueListIterator<PMViewLayout> it;
+ for( it = m_layouts.begin( ); it != m_layouts.end( ) &&
+ ( *it ).name( ) != name; ++it );
+
+ if( it == m_layouts.end( ) )
+ return 0;
+ return &( *it );
+}
+
+void PMViewLayoutManager::fillPopupMenu( KPopupMenu* pMenu )
+{
+ QStringList lst = availableLayouts( );
+ QStringList::ConstIterator it = lst.begin( );
+
+ pMenu->clear( );
+ if( it != lst.end( ) )
+ {
+ for( ; it != lst.end( ); ++it )
+ pMenu->insertItem( ( *it ) );
+ }
+}
+
+void PMViewLayoutManager::addLayout( const QString& name )
+{
+ PMViewLayout a;
+
+ if( m_layouts.isEmpty( ) )
+ m_defaultLayout = name;
+ a.setName( name );
+ m_layouts.append( a );
+}
+
+void PMViewLayoutManager::removeLayout( const QString& name )
+{
+ QValueListIterator<PMViewLayout> it;
+ for( it = m_layouts.begin( ); it != m_layouts.end( ) &&
+ ( *it ).name( ) != name; ++it );
+
+ if( it != m_layouts.end( ) )
+ m_layouts.remove( it );
+}
+
+
+PMSaveViewLayoutDialog::PMSaveViewLayoutDialog( PMShell* parent,
+ const char* name )
+ : KDialogBase( parent, name, true, i18n( "Save View Layout" ),
+ KDialogBase::Ok | KDialogBase::Cancel )
+{
+ m_pShell = parent;
+
+ setButtonOK( KStdGuiItem::save() );
+ enableButtonOK( false );
+
+ QWidget* w = new QWidget( this );
+ QVBoxLayout* vl = new QVBoxLayout( w, 0, KDialog::spacingHint( ) );
+
+ QLabel* l = new QLabel( i18n( "Enter view layout name:" ), w );
+ vl->addWidget( l );
+
+ m_pLayoutName = new QLineEdit( w );
+ vl->addWidget( m_pLayoutName );
+ connect( m_pLayoutName, SIGNAL( textChanged( const QString& ) ),
+ SLOT( slotNameChanged( const QString& ) ) );
+
+ QListBox* lb = new QListBox( w );
+ vl->addWidget( lb );
+ connect( lb, SIGNAL( highlighted( const QString& ) ),
+ SLOT( slotNameSelected( const QString& ) ) );
+ lb->insertStringList( PMViewLayoutManager::theManager( )
+ ->availableLayouts( ) );
+
+ setMainWidget( w );
+ setInitialSize( QSize( 300, 200 ) );
+}
+
+PMSaveViewLayoutDialog::~PMSaveViewLayoutDialog( )
+{
+}
+
+void PMSaveViewLayoutDialog::slotOk( )
+{
+ QString name = m_pLayoutName->text( );
+
+ PMViewLayoutManager* m = PMViewLayoutManager::theManager( );
+ PMViewLayout* layout = m->findLayout( name );
+
+ PMViewLayout newLayout = PMViewLayout::extractViewLayout( m_pShell );
+ newLayout.setName( name );
+
+ if( layout )
+ *layout = newLayout;
+ else
+ m->addLayout( newLayout );
+
+ m->saveData( );
+
+ KDialogBase::slotOk( );
+}
+
+void PMSaveViewLayoutDialog::slotNameChanged( const QString& s )
+{
+ enableButtonOK( !s.isEmpty( ) );
+}
+
+void PMSaveViewLayoutDialog::slotNameSelected( const QString& s )
+{
+ m_pLayoutName->setText( s );
+}
+
+#include "pmviewlayoutmanager.moc"
diff --git a/kpovmodeler/pmviewlayoutmanager.h b/kpovmodeler/pmviewlayoutmanager.h
new file mode 100644
index 00000000..c0246c5d
--- /dev/null
+++ b/kpovmodeler/pmviewlayoutmanager.h
@@ -0,0 +1,306 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+ copyright : (C) 2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMVIEWLAYOUTMANAGER_H
+#define PMVIEWLAYOUTMANAGER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstring.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+#include <kstaticdeleter.h>
+
+#include <kdialogbase.h>
+
+#include "pmdockwidget.h"
+#include "pmviewbase.h"
+
+class KConfig;
+class QDomElement;
+class QLineEdit;
+class PMShell;
+
+/**
+ * Class used internally by @ref PMViewLayout
+ *
+ * This class maintains all the information needed to create a docked view.
+ */
+class PMViewLayoutEntry
+{
+public:
+ /**
+ * Constructor
+ */
+ PMViewLayoutEntry( );
+ /**
+ * Copy constructor
+ */
+ PMViewLayoutEntry( const PMViewLayoutEntry& e );
+ /**
+ * Destructor
+ */
+ ~PMViewLayoutEntry( );
+
+ QString viewType( ) const { return m_viewType; }
+ void setViewType( const QString& vt );
+
+ PMDockWidget::DockPosition dockPosition( ) const { return m_dockPosition; }
+ void setDockPosition( PMDockWidget::DockPosition i );
+
+ int columnWidth( ) const { return m_columnWidth; }
+ void setColumnWidth( int i );
+
+ int height( ) const { return m_height; }
+ void setHeight( int i );
+
+ int floatingHeight( ) const { return m_floatingHeight; }
+ void setFloatingHeight( int h ) { m_floatingHeight = h; }
+
+ int floatingWidth( ) const { return m_floatingWidth; }
+ void setFloatingWidth( int w ) { m_floatingWidth = w; }
+
+ int floatingPositionX( ) const { return m_floatingPositionX; }
+ void setFloatingPositionX( int p ) { m_floatingPositionX = p; }
+ int floatingPositionY( ) const { return m_floatingPositionY; }
+ void setFloatingPositionY( int p ) { m_floatingPositionY = p; }
+
+ void loadData( QDomElement& e );
+ void saveData( QDomElement& e ) const;
+
+ PMViewOptions* customOptions( ) const { return m_pCustomOptions; }
+ void setCustomOptions( PMViewOptions* o );
+
+ const QString dockPositionAsString( );
+ const QString viewTypeAsString( );
+
+private:
+ QString m_viewType;
+ PMDockWidget::DockPosition m_dockPosition;
+ int m_columnWidth;
+ int m_height;
+ int m_floatingWidth;
+ int m_floatingHeight;
+ int m_floatingPositionX;
+ int m_floatingPositionY;
+ PMViewOptions* m_pCustomOptions;
+};
+
+/**
+ * Class used internally by @ref PMViewLayoutManager
+ *
+ * This class maintains a named layout. It basically stores all views
+ * associated with that layout.
+ */
+class PMViewLayout
+{
+public:
+ typedef QValueList< PMViewLayoutEntry >::iterator iterator;
+ /**
+ * Constructor
+ */
+ PMViewLayout( );
+ /**
+ * Copy constructor
+ */
+ PMViewLayout( const PMViewLayout& vl );
+ /**
+ * Destructor
+ */
+ ~PMViewLayout( ) { }
+
+ /**
+ * Assignment operator
+ */
+ PMViewLayout& operator = ( const PMViewLayout& vl );
+
+ QString name( ) const { return m_name; }
+
+ void loadData( QDomElement& e );
+
+ void saveData( QDomElement& e, QDomDocument& doc ) const;
+ /**
+ * Destroy all dock widgets in PMShell and create the new ones
+ */
+ void displayLayout( PMShell* shell );
+ /**
+ * Sets the name of the layout
+ */
+ void setName( const QString& n );
+ /**
+ *
+ * Add a new entry to the layout. By default it adds the entry at the end
+ * of the list. If a position is given it adds the entry at the indicated
+ * position
+ */
+ void addEntry( const PMViewLayoutEntry& e, int index = -1 );
+ /**
+ * Removes the entry at the given position
+ */
+ void removeEntry( int index );
+ /**
+ * Returns an iterator to the first entry
+ */
+ iterator begin( ) { return m_entries.begin( ); }
+ /**
+ * Returns an iterator to the last entry
+ */
+ iterator end( ) { return m_entries.end( ); }
+ /**
+ * Returns an iterator to the n-th entry
+ */
+ iterator at( int i ) { return m_entries.at( i ); }
+ /**
+ * Returns the entry at the given position
+ */
+ PMViewLayoutEntry& operator[]( int index ) { return m_entries[ index ]; }
+ /**
+ * Normalizes the column width and view heights
+ */
+ void normalize( );
+
+ /**
+ * Extracts the view layout from the current window
+ */
+ static PMViewLayout extractViewLayout( PMShell* shell );
+private:
+ static void recursiveExtractColumns(
+ QValueList< QValueList< PMViewLayoutEntry > >& cols,
+ QValueList< QValueList< PMViewLayoutEntry > >::iterator cit,
+ int width, QWidget* widget );
+
+ static void recursiveExtractOneColumn(
+ QValueList< PMViewLayoutEntry >& entries,
+ QValueList< PMViewLayoutEntry >::iterator eit,
+ int height, QWidget* widget );
+
+ QString m_name;
+ QValueList< PMViewLayoutEntry > m_entries;
+};
+
+/**
+ * Singleton that contains the view layouts available.
+ *
+ * It interacts with @ref PMShell to create the view layouts.
+ * The class maintains a list of layouts as well as the name of the default
+ * layout. The layouts are stored in a XML file caled viewlayouts.xml.
+ */
+class PMViewLayoutManager
+{
+public:
+ /**
+ * Destructor
+ */
+ ~PMViewLayoutManager( );
+ /**
+ * Returns the manager instance (singleton)
+ */
+ static PMViewLayoutManager* theManager( );
+
+ /**
+ * Returns the list of available view layouts
+ */
+ QStringList availableLayouts( );
+ /**
+ * Sets the default layout
+ */
+ void setDefaultLayout( const QString& name );
+ /**
+ * Returns the default layout
+ */
+ QString defaultLayout( ) const { return m_defaultLayout; }
+ /**
+ * Destroy all dock widgets in PMShell and create the new ones
+ */
+ void displayLayout( const QString& name, PMShell* shell );
+ /**
+ * Displays the layout indicated as default
+ */
+ void displayDefaultLayout( PMShell* shell );
+ /**
+ * Loads all layouts from the configuration file
+ */
+ void loadData( );
+ /**
+ * Saves the current layout collection to the configuration file
+ */
+ void saveData( );
+ /**
+ * Add a new empty layout
+ */
+ void addLayout( const QString& name );
+ /**
+ * Add a new layout
+ */
+ void addLayout( const PMViewLayout& l ) { m_layouts.append( l ); }
+ /**
+ * Remove a layout
+ */
+ void removeLayout( const QString& name );
+ /**
+ * Get a known layout
+ */
+ PMViewLayout* findLayout( const QString& name );
+ /**
+ * Returns the list of available layouts
+ */
+ QValueList<PMViewLayout> layouts( ) { return m_layouts; }
+ /**
+ * Sets the list of available layouts
+ */
+ void setLayouts( const QValueList<PMViewLayout>& l ) { m_layouts = l; }
+ /**
+ * Fill the available layouts menu
+ */
+ void fillPopupMenu( KPopupMenu* pMenu );
+private:
+ /**
+ * Constructor
+ */
+ PMViewLayoutManager( );
+
+ bool m_layoutsLoaded;
+ bool m_layoutDisplayed;
+ QString m_defaultLayout;
+ QValueList< PMViewLayout > m_layouts;
+
+ static PMViewLayoutManager* s_pInstance;
+ static KStaticDeleter<PMViewLayoutManager> s_staticDeleter;
+};
+
+
+class PMSaveViewLayoutDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ PMSaveViewLayoutDialog( PMShell* parent, const char* name = 0 );
+ ~PMSaveViewLayoutDialog( );
+protected slots:
+ virtual void slotOk( );
+ void slotNameChanged( const QString& );
+ void slotNameSelected( const QString& );
+private:
+ QLineEdit* m_pLayoutName;
+ PMShell* m_pShell;
+};
+
+#endif
diff --git a/kpovmodeler/pmviewstructure.cpp b/kpovmodeler/pmviewstructure.cpp
new file mode 100644
index 00000000..966df90b
--- /dev/null
+++ b/kpovmodeler/pmviewstructure.cpp
@@ -0,0 +1,127 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmviewstructure.h"
+
+/*
+void PMViewStructure::render( )
+{
+ glVertexPointer( 3, GL_DOUBLE, sizeof( PMVector ), points.data( ) );
+ glDrawElements( GL_LINES, lines.size( ) * 2,
+ GL_UNSIGNED_INT, lines.data( ) );
+}
+*/
+
+PMViewStructure::PMViewStructure( )
+{
+ m_parameterKey = -1;
+}
+
+PMViewStructure::PMViewStructure( unsigned int n, unsigned int l, unsigned int f )
+{
+ m_points.resize( n );
+ m_lines.resize( l );
+ m_faces.resize( f );
+ m_parameterKey = -1;
+}
+
+PMViewStructure::PMViewStructure( const PMViewStructure& vs )
+{
+ m_points = vs.m_points;
+ m_lines = vs.m_lines;
+ m_faces = vs.m_faces;
+ m_parameterKey = vs.m_parameterKey;
+}
+
+PMViewStructure::PMViewStructure( const PMViewStructure* vs )
+{
+ m_points = vs->m_points;
+ m_lines = vs->m_lines;
+ m_faces = vs->m_faces;
+ m_parameterKey = vs->m_parameterKey;
+}
+
+PMViewStructure& PMViewStructure::operator = ( const PMViewStructure& vs )
+{
+ m_lines = vs.m_lines;
+ m_points = vs.m_points;
+ m_faces = vs.m_faces;
+
+ return *this;
+}
+
+bool PMViewStructure::operator == ( const PMViewStructure& vs ) const
+{
+ return ( ( m_lines.data( ) == vs.m_lines.data( ) )
+ && ( m_points.data( ) == vs.m_points.data( ) )
+ && ( m_faces == vs.m_faces ) );
+}
+
+bool PMViewStructure::operator != ( const PMViewStructure& vs ) const
+{
+ return ( ( m_lines.data( ) != vs.m_lines.data( ) )
+ || ( m_points.data( ) != vs.m_points.data( ) )
+ || !( m_faces == vs.m_faces ) );
+}
+
+
+PMBoundingBox::PMBoundingBox( const PMVector& min, const PMVector& max )
+{
+ m_bValid = true;
+ m_min = min;
+ m_max = max;
+}
+
+PMBoundingBox::PMBoundingBox( )
+{
+ m_bValid = false;
+ m_min = PMVector( 0.0, 0.0, 0.0 );
+ m_max = PMVector( 0.0, 0.0, 0.0 );
+}
+
+void PMBoundingBox::mergeWith( const PMBoundingBox& box )
+{
+ if( m_bValid )
+ {
+ if( box.m_bValid )
+ {
+ if( box.m_min.x( ) < m_min.x( ) )
+ m_min.setX( box.m_min.x( ) );
+ if( box.m_min.y( ) < m_min.y( ) )
+ m_min.setY( box.m_min.y( ) );
+ if( box.m_min.z( ) < m_min.z( ) )
+ m_min.setZ( box.m_min.z( ) );
+
+ if( box.m_max.x( ) > m_max.x( ) )
+ m_max.setX( box.m_max.x( ) );
+ if( box.m_max.y( ) > m_max.y( ) )
+ m_max.setY( box.m_max.y( ) );
+ if( box.m_max.z( ) > m_max.z( ) )
+ m_max.setZ( box.m_max.z( ) );
+ }
+ }
+ else
+ {
+ if( box.m_bValid )
+ {
+ m_bValid = true;
+ m_max = box.m_max;
+ m_min = box.m_min;
+ }
+ }
+}
diff --git a/kpovmodeler/pmviewstructure.h b/kpovmodeler/pmviewstructure.h
new file mode 100644
index 00000000..5356466b
--- /dev/null
+++ b/kpovmodeler/pmviewstructure.h
@@ -0,0 +1,222 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMVIEWSTRUCTURE_H
+#define PMVIEWSTRUCTURE_H
+
+#include "pmface.h"
+#include "pmpoint.h"
+#include "pmline.h"
+#include "pmmatrix.h"
+#include "pmobject.h"
+#include "pmvector.h"
+
+/**
+ * Represents the view structure (points, lines, faces) of an object
+ *
+ * Faces are not implemented yet but are needed later to calculate the view
+ * structure of csg objects
+ */
+
+class PMViewStructure
+{
+ friend class PMObject;
+public:
+ /**
+ * Creates an empty view structure
+ */
+ PMViewStructure( );
+ /**
+ * Creates a view structure with n points, l lines and f faces.
+ */
+ PMViewStructure( unsigned int n, unsigned int l, unsigned int f = 0 );
+ /**
+ * Creates a copy of the view structure. m_points, m_lines and m_faces are shared
+ */
+ PMViewStructure( const PMViewStructure& vs );
+ /**
+ * Creates a copy of the view structure. m_points, m_lines anf m_faces are shared
+ */
+ PMViewStructure( const PMViewStructure* vs );
+
+ /**
+ * Returns a reference to the array of points
+ */
+ PMPointArray& points( ) { return m_points; }
+ /**
+ * Returns a reference to the array of lines
+ */
+ PMLineArray& lines( ) { return m_lines; }
+ /**
+ * Returns a refrence to the array of faces
+ */
+ PMFaceArray& faces( ) { return m_faces; }
+ /**
+ * Returns the parameter key
+ */
+ int parameterKey( ) const { return m_parameterKey; }
+ /**
+ * Sets the parameter key
+ */
+ void setParameterKey( int k ) { m_parameterKey = k; }
+
+ /**
+ * Assigns the view structure to this view structure.
+ * The points and lines are shared
+ */
+ PMViewStructure& operator = ( const PMViewStructure& vs );
+ /**
+ * Returns true if the view structures share the same points and lines
+ */
+ bool operator == ( const PMViewStructure& vs ) const;
+ /**
+ * Returns false if the view structures share the same points and lines
+ */
+ bool operator != ( const PMViewStructure& vs ) const;
+protected:
+ /**
+ * Not transformed points, can be shared between PMObjects
+ * of the same type. m_points.data( ) can be used as vertex array.
+ *
+ * Optimized for fast rendering.
+ */
+ PMPointArray m_points;
+ /**
+ * Lines to display. m_lines.data( ) can be used by glDrawElements.
+ *
+ * Optimized for fast rendering.
+ */
+ PMLineArray m_lines;
+ /**
+ * Faces to display.
+ */
+ PMFaceArray m_faces;
+ /**
+ * View structure parameter key.
+ *
+ * Each class can have parameters that modifies the number of lines and
+ * points of a view structure (detail level).
+ *
+ * The framework determines if the view structure is up to date by
+ * comparing the key with the parameter key of the corresponding class.
+ */
+ int m_parameterKey;
+};
+
+/**
+ * Class for bounding boxes of PMObjects
+ */
+class PMBoundingBox
+{
+public:
+ /**
+ * Creates a bounding box with min and max vectors
+ */
+ PMBoundingBox( const PMVector& min, const PMVector& max );
+ /**
+ * Creates an invalid bounding box. @ref PMObject::boundingBox() returns
+ * an invalid bounding box, if the object has none.
+ */
+ PMBoundingBox( );
+
+ /**
+ * Returns the minimum coordinates
+ */
+ PMVector min( ) const { return m_min; }
+ /**
+ * Returns the maximum coordinates
+ */
+ PMVector max( ) const { return m_max; }
+ /**
+ * Returns the minumum x coordinate
+ */
+ double minX( ) const { return m_min.x( ); }
+ /**
+ * Returns the minumum y coordinate
+ */
+ double minY( ) const { return m_min.y( ); }
+ /**
+ * Returns the minumum z coordinate
+ */
+ double minZ( ) const { return m_min.z( ); }
+ /**
+ * Returns the maximum x coordinate
+ */
+ double maxX( ) const { return m_max.x( ); }
+ /**
+ * Returns the maximum y coordinate
+ */
+ double maxY( ) const { return m_max.y( ); }
+ /**
+ * Returns the maximum z coordinate
+ */
+ double maxZ( ) const { return m_max.z( ); }
+ /**
+ * Sets the minimum coordinates
+ */
+ void setMin( const PMVector& min ) { m_min = min; }
+ /**
+ * Sets the maximum coordinates
+ */
+ void setMax( const PMVector& max ) { m_max = max; }
+ /**
+ * Sets the minimum x coordinate
+ */
+ void setMinX( const double c ) { m_min.setX( c ); }
+ /**
+ * Sets the minimum y coordinate
+ */
+ void setMinY( const double c ) { m_min.setY( c ); }
+ /**
+ * Sets the minimum z coordinate
+ */
+ void setMinZ( const double c ) { m_min.setZ( c ); }
+ /**
+ * Sets the maximum x coordinate
+ */
+ void setMaxX( const double c ) { m_max.setX( c ); }
+ /**
+ * Sets the maximum y coordinate
+ */
+ void setMaxY( const double c ) { m_max.setY( c ); }
+ /**
+ * Sets the maximum z coordinate
+ */
+ void setMaxZ( const double c ) { m_max.setZ( c ); }
+
+ /**
+ * Returns true, if the bounding box is valid
+ */
+ bool isValid( ) const { return m_bValid; }
+ /**
+ * Sets the valid flag to v
+ */
+ void setValid( bool v ) { m_bValid = v; }
+
+ /**
+ * Merges the two bounding boxes
+ */
+ void mergeWith( const PMBoundingBox& box );
+
+private:
+ bool m_bValid;
+ PMVector m_min, m_max;
+};
+
+#endif
diff --git a/kpovmodeler/pmwarp.cpp b/kpovmodeler/pmwarp.cpp
new file mode 100644
index 00000000..76d58cf3
--- /dev/null
+++ b/kpovmodeler/pmwarp.cpp
@@ -0,0 +1,548 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmxmlhelper.h"
+#include "pmvector.h"
+#include "pmwarp.h"
+#include "pmwarpedit.h"
+#include "pmmemento.h"
+#include "pmenumproperty.h"
+
+#include <klocale.h>
+
+const PMVector directionDefault = PMVector( 1.0, 0.0, 0.0 );
+const PMVector offsetDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector flipDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector locationDefault = PMVector( 0.0, 0.0, 0.0 );
+const double radiusDefault = 0;
+const double strengthDefault = 0;
+const double falloffDefault = 0;
+const bool inverseDefault = false;
+const PMVector repeatDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector turbulenceDefault = PMVector( 0.0, 0.0, 0.0 );
+const PMVector valueVectorDefault = PMVector( 0.0, 0.0, 0.0 );
+const int octavesDefault = 6;
+const double omegaDefault = 0.5;
+const double lambdaDefault = 2.0;
+const PMVector orientationDefault = PMVector( 0.0, 0.0, 1.0 );
+const double distExpDefault = 0.0;
+const double majorRadiusDefault = 1.0;
+
+PMDefinePropertyClass( PMWarp, PMWarpProperty );
+PMDefineEnumPropertyClass( PMWarp, PMWarp::PMWarpType, PMWarpTypeProperty );
+
+PMMetaObject* PMWarp::s_pMetaObject = 0;
+PMObject* createNewWarp( PMPart* part )
+{
+ return new PMWarp( part );
+}
+
+PMWarp::PMWarp( PMPart* part )
+ : Base( part )
+{
+ m_warpType = PMWarp::Repeat;
+ m_direction = directionDefault;
+ m_offset = offsetDefault;
+ m_flip = flipDefault;
+ m_location = locationDefault;
+ m_radius = radiusDefault;
+ m_strength = strengthDefault;
+ m_falloff = falloffDefault;
+ m_inverse = inverseDefault;
+ m_repeat = repeatDefault;
+ m_turbulence = turbulenceDefault;
+ m_valueVector = valueVectorDefault;
+ m_octaves = octavesDefault;
+ m_omega = omegaDefault;
+ m_lambda = lambdaDefault;
+ m_orientation = orientationDefault;
+ m_distExp = distExpDefault;
+ m_majorRadius = majorRadiusDefault;
+}
+
+PMWarp::PMWarp( const PMWarp& w )
+ : Base( w )
+{
+ m_warpType = w.m_warpType;
+ m_direction = w.m_direction;
+ m_offset = w.m_offset;
+ m_flip = w.m_flip;
+ m_location = w.m_location;
+ m_radius = w.m_radius;
+ m_strength = w.m_strength;
+ m_falloff = w.m_falloff;
+ m_inverse = w.m_inverse;
+ m_repeat = w.m_repeat;
+ m_turbulence = w.m_turbulence;
+ m_valueVector = w.m_valueVector;
+ m_octaves = w.m_octaves;
+ m_omega = w.m_omega;
+ m_lambda = w.m_lambda;
+ m_orientation = w.m_orientation;
+ m_distExp = w.m_distExp;
+ m_majorRadius = w.m_majorRadius;
+}
+
+PMWarp::~PMWarp( )
+{
+}
+
+QString PMWarp::description( ) const
+{
+ return i18n( "warp" );
+}
+
+void PMWarp::serialize( QDomElement& e, QDomDocument& /*doc*/ ) const
+{
+ bool mapping = false;
+
+ switch( m_warpType )
+ {
+ case PMWarp::Repeat:
+ e.setAttribute( "warp_type", "repeat");
+ e.setAttribute( "direction", m_direction.serializeXML( ) );
+ e.setAttribute( "offset", m_offset.serializeXML( ) );
+ e.setAttribute( "flip", m_flip.serializeXML( ) );
+ break;
+ case PMWarp::BlackHole:
+ e.setAttribute( "warp_type", "black hole");
+ e.setAttribute( "location", m_location.serializeXML( ) );
+ e.setAttribute( "radius", m_radius );
+ e.setAttribute( "strength", m_strength );
+ e.setAttribute( "falloff", m_falloff );
+ e.setAttribute( "inverse", m_inverse );
+ e.setAttribute( "repeat", m_repeat.serializeXML( ) );
+ e.setAttribute( "turbulence", m_turbulence.serializeXML( ) );
+ break;
+ case PMWarp::Turbulence:
+ e.setAttribute( "warp_type", "turbulence");
+ e.setAttribute( "turbulence", m_valueVector.serializeXML( ) );
+ e.setAttribute( "octaves", m_octaves );
+ e.setAttribute( "omega", m_omega );
+ e.setAttribute( "lambda", m_lambda );
+ break;
+ case PMWarp::Cylindrical:
+ mapping = true;
+ e.setAttribute( "warp_type", "cylindrical" );
+ break;
+ case PMWarp::Spherical:
+ mapping = true;
+ e.setAttribute( "warp_type", "spherical" );
+ break;
+ case PMWarp::Toroidal:
+ mapping = true;
+ e.setAttribute( "warp_type", "toroidal" );
+ e.setAttribute( "major_radius", m_majorRadius );
+ break;
+ case PMWarp::Planar:
+ mapping = true;
+ e.setAttribute( "warp_type", "planar" );
+ break;
+ }
+
+ if ( mapping )
+ {
+ e.setAttribute( "orientation", m_orientation.serializeXML( ) );
+ e.setAttribute( "dist_exp", m_distExp );
+ }
+}
+
+void PMWarp::readAttributes( const PMXMLHelper& h )
+{
+ bool mapping = false;
+ QString str = h.stringAttribute( "warp_type", "repeat" );
+
+ if( str == "repeat" )
+ {
+ m_warpType = PMWarp::Repeat;
+ m_direction = h.vectorAttribute( "direction", directionDefault );
+ m_offset = h.vectorAttribute( "offset", offsetDefault );
+ m_flip = h.vectorAttribute( "flip", flipDefault );
+ }
+ else if( str == "black hole" )
+ {
+ m_warpType = PMWarp::BlackHole;
+ m_location = h.vectorAttribute( "location", locationDefault );
+ m_radius = h.doubleAttribute( "radius", radiusDefault );
+ m_strength = h.doubleAttribute( "strength", strengthDefault );
+ m_falloff = h.doubleAttribute( "falloff", falloffDefault );
+ m_inverse = h.boolAttribute( "inverse", inverseDefault );
+ m_repeat = h.vectorAttribute( "repeat", repeatDefault );
+ m_turbulence = h.vectorAttribute( "turbulence", turbulenceDefault );
+ }
+ else if( str == "turbulence" )
+ {
+ m_warpType = PMWarp::Turbulence;
+ m_valueVector = h.vectorAttribute( "turbulence", valueVectorDefault );
+ m_octaves = h.intAttribute( "octaves", octavesDefault );
+ m_omega = h.doubleAttribute( "omega", omegaDefault );
+ m_lambda = h.doubleAttribute( "lambda", lambdaDefault );
+ }
+ else if( str == "cylindrical" )
+ {
+ mapping = true;
+ m_warpType = PMWarp::Cylindrical;
+ }
+ else if( str == "spherical" )
+ {
+ mapping = true;
+ m_warpType = PMWarp::Spherical;
+ }
+ else if( str == "toroidal" )
+ {
+ mapping = true;
+ m_warpType = PMWarp::Toroidal;
+ m_majorRadius = h.doubleAttribute( "major_radius", majorRadiusDefault );
+ }
+ else if( str == "planar" )
+ {
+ mapping = true;
+ m_warpType = PMWarp::Planar;
+ }
+
+ if( mapping )
+ {
+ m_orientation = h.vectorAttribute( "orientation", orientationDefault );
+ m_distExp = h.doubleAttribute( "dist_exp", distExpDefault );
+ }
+}
+
+PMMetaObject* PMWarp::metaObject( ) const
+{
+ if( !s_pMetaObject )
+ {
+ s_pMetaObject = new PMMetaObject( "Warp", Base::metaObject( ),
+ createNewWarp );
+
+ PMWarpTypeProperty* p = new PMWarpTypeProperty(
+ "warpType", &PMWarp::setWarpType, &PMWarp::warpType );
+ p->addEnumValue( "Repeat", Repeat );
+ p->addEnumValue( "BlackHole", BlackHole );
+ p->addEnumValue( "Turbulence", Turbulence );
+ p->addEnumValue( "Cylindrical", Cylindrical );
+ p->addEnumValue( "Spherical", Spherical );
+ p->addEnumValue( "Toroidal", Toroidal );
+ p->addEnumValue( "Planar", Planar );
+ s_pMetaObject->addProperty( p );
+
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "direction", &PMWarp::setDirection, &PMWarp::direction ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "offset", &PMWarp::setOffset, &PMWarp::offset ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "flip", &PMWarp::setFlip, &PMWarp::flip ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "location", &PMWarp::setLocation, &PMWarp::location ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "radius", &PMWarp::setRadius, &PMWarp::radius ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "strength", &PMWarp::setStrength, &PMWarp::strength ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "falloff", &PMWarp::setFalloff, &PMWarp::falloff ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "inverse", &PMWarp::setInverse, &PMWarp::inverse ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "repeat", &PMWarp::setRepeat, &PMWarp::repeat ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "turbulence", &PMWarp::setTurbulence, &PMWarp::turbulence ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "valueVector", &PMWarp::setValueVector, &PMWarp::valueVector ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "octaves", &PMWarp::setOctaves, &PMWarp::octaves ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "omega", &PMWarp::setOmega, &PMWarp::omega ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "lambda", &PMWarp::setLambda, &PMWarp::lambda ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "orientation", &PMWarp::setOrientation, &PMWarp::orientation ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "dist_exp", &PMWarp::setDistExp, &PMWarp::distExp ) );
+ s_pMetaObject->addProperty(
+ new PMWarpProperty( "major_radius", &PMWarp::setMajorRadius, &PMWarp::majorRadius ) );
+ }
+ return s_pMetaObject;
+}
+
+void PMWarp::cleanUp( ) const
+{
+ if( s_pMetaObject )
+ {
+ delete s_pMetaObject;
+ s_pMetaObject = 0;
+ }
+ Base::cleanUp( );
+}
+
+void PMWarp::setWarpType( PMWarpType c )
+{
+ if( c != m_warpType )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMWarpTypeID, m_warpType );
+ m_warpType = c;
+ }
+}
+
+void PMWarp::setDirection( const PMVector& c )
+{
+ if( c != m_direction )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDirectionID, m_direction );
+ m_direction = c;
+ }
+}
+
+void PMWarp::setOffset( const PMVector& c )
+{
+ if( c != m_offset )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOffsetID, m_offset );
+ m_offset = c;
+ }
+}
+
+void PMWarp::setFlip( const PMVector& c )
+{
+ if( c != m_flip )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFlipID, m_flip );
+ m_flip = c;
+ }
+}
+
+void PMWarp::setLocation( const PMVector& c )
+{
+ if( c != m_location )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLocationID, m_location );
+ m_location = c;
+ }
+}
+
+void PMWarp::setRadius( const double c )
+{
+ if( c != m_radius )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRadiusID, m_radius );
+ m_radius = c;
+ }
+}
+
+void PMWarp::setStrength( const double c )
+{
+ if( c != m_strength )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMStrengthID, m_strength );
+ m_strength = c;
+ }
+}
+
+void PMWarp::setFalloff( const double c )
+{
+ if( c != m_falloff )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMFalloffID, m_falloff );
+ m_falloff = c;
+ }
+}
+
+void PMWarp::setInverse( const bool c )
+{
+ if( c != m_inverse )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMInverseID, m_inverse );
+ m_inverse = c;
+ }
+}
+
+void PMWarp::setRepeat( const PMVector& c )
+{
+ if( c != m_repeat )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMRepeatID, m_repeat );
+ m_repeat = c;
+ }
+}
+
+void PMWarp::setTurbulence( const PMVector& c )
+{
+ if( c != m_turbulence )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMTurbulenceID, m_turbulence );
+ m_turbulence = c;
+ }
+}
+
+void PMWarp::setValueVector( const PMVector& c )
+{
+ if( c != m_valueVector )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMValueVectorID, m_valueVector );
+ m_valueVector = c;
+ }
+}
+
+void PMWarp::setOctaves( const int c )
+{
+ if( c != m_octaves )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOctavesID, m_octaves );
+ m_octaves = c;
+ }
+}
+
+void PMWarp::setOmega( const double c )
+{
+ if( c != m_omega )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOmegaID, m_omega );
+ m_omega = c;
+ }
+}
+
+void PMWarp::setLambda( const double c )
+{
+ if( c != m_lambda )
+ {
+ if( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMLambdaID, m_lambda );
+ m_lambda = c;
+ }
+}
+
+void PMWarp::setOrientation( const PMVector& v )
+{
+ if ( v != m_orientation )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMOrientationID, m_orientation );
+ m_orientation = v;
+ }
+}
+
+void PMWarp::setDistExp( const double c )
+{
+ if ( c != m_distExp )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMDistExpID, m_distExp );
+ m_distExp = c;
+ }
+}
+
+void PMWarp::setMajorRadius( const double c )
+{
+ if ( c != m_majorRadius )
+ {
+ if ( m_pMemento )
+ m_pMemento->addData( s_pMetaObject, PMMajorRadiusID, m_majorRadius );
+ m_majorRadius = c;
+ }
+}
+
+PMDialogEditBase* PMWarp::editWidget( QWidget* parent ) const
+{
+ return new PMWarpEdit( parent );
+}
+
+void PMWarp::restoreMemento( PMMemento* s )
+{
+ PMMementoDataIterator it( s );
+ PMMementoData* data;
+
+ for( ; it.current( ); ++it )
+ {
+ data = it.current( );
+ if( data->objectType( ) == s_pMetaObject )
+ {
+ switch( data->valueID( ) )
+ {
+ case PMWarpTypeID:
+ setWarpType( ( PMWarpType )data->intData( ) );
+ break;
+ case PMDirectionID:
+ setDirection( data->vectorData( ) );
+ break;
+ case PMOffsetID:
+ setOffset( data->vectorData( ) );
+ break;
+ case PMFlipID:
+ setFlip( data->vectorData( ) );
+ break;
+ case PMLocationID:
+ setLocation( data->vectorData( ) );
+ break;
+ case PMRadiusID:
+ setRadius( data->doubleData( ) );
+ break;
+ case PMStrengthID:
+ setStrength( data->doubleData( ) );
+ break;
+ case PMFalloffID:
+ setFalloff( data->doubleData( ) );
+ break;
+ case PMInverseID:
+ setInverse( data->boolData( ) );
+ break;
+ case PMRepeatID:
+ setRepeat( data->vectorData( ) );
+ break;
+ case PMTurbulenceID:
+ setTurbulence( data->vectorData( ) );
+ break;
+ case PMValueVectorID:
+ setValueVector( data->vectorData( ) );
+ break;
+ case PMOctavesID:
+ setOctaves( data->intData( ) );
+ break;
+ case PMOmegaID:
+ setOmega( data->doubleData( ) );
+ break;
+ case PMLambdaID:
+ setLambda( data->doubleData( ) );
+ break;
+ case PMOrientationID:
+ setOrientation( data->vectorData( ) );
+ break;
+ case PMDistExpID:
+ setDistExp( data->doubleData( ) );
+ break;
+ case PMMajorRadiusID:
+ setMajorRadius( data->doubleData( ) );
+ break;
+ default:
+ kdError( PMArea ) << "Wrong ID in PMWarp::restoreMemento\n";
+ break;
+ }
+ }
+ }
+ Base::restoreMemento( s );
+}
diff --git a/kpovmodeler/pmwarp.h b/kpovmodeler/pmwarp.h
new file mode 100644
index 00000000..a6ed213b
--- /dev/null
+++ b/kpovmodeler/pmwarp.h
@@ -0,0 +1,162 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMWARP_H
+#define PMWARP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmobject.h"
+
+/**
+ * Class for Repeat Warps
+ */
+
+class PMWarp : public PMObject
+{
+ typedef PMObject Base;
+public:
+ enum PMWarpType { Repeat, BlackHole, Turbulence,
+ Cylindrical, Spherical, Toroidal, Planar };
+
+ /**
+ * Creates a PMWarp
+ */
+ PMWarp( PMPart* part );
+ /**
+ * Copy constructor
+ */
+ PMWarp( const PMWarp& w );
+ /**
+ * deletes the PMWarp
+ */
+ virtual ~PMWarp( );
+
+ /** */
+ virtual PMObject* copy( ) const { return new PMWarp( *this ); }
+ /** */
+ virtual QString description( ) const;
+
+ /** */
+ virtual PMMetaObject* metaObject( ) const;
+ /** */
+ virtual void cleanUp( ) const;
+
+ /** */
+ virtual void serialize( QDomElement& e, QDomDocument& doc ) const;
+ /** */
+ virtual void readAttributes( const PMXMLHelper& h );
+
+ /**
+ * Returns a new @ref PMWarpEdit
+ */
+ virtual PMDialogEditBase* editWidget( QWidget* parent ) const;
+ /**
+ * Returns the name of the pixmap that is displayed in the tree view
+ * and dialog view
+ */
+ virtual QString pixmap( ) const { return QString( "pmwarp" ); }
+
+ PMWarpType warpType( ) const { return m_warpType; }
+ void setWarpType( PMWarpType c );
+
+ PMVector direction( ) const { return m_direction; }
+ void setDirection( const PMVector& c );
+ PMVector offset( ) const { return m_offset; }
+ void setOffset( const PMVector& c );
+ PMVector flip( ) const { return m_flip; }
+ void setFlip( const PMVector& c );
+
+ PMVector location( ) const { return m_location; }
+ void setLocation( const PMVector& v );
+ double radius( ) const { return m_radius; }
+ void setRadius( double c );
+ double strength( ) const { return m_strength; }
+ void setStrength( double c );
+ double falloff( ) const { return m_falloff; }
+ void setFalloff( double c );
+ bool inverse( ) const { return m_inverse; }
+ void setInverse( bool c );
+ PMVector repeat( ) const { return m_repeat; }
+ void setRepeat( const PMVector& v );
+ PMVector turbulence( ) const { return m_turbulence; }
+ void setTurbulence( const PMVector& v );
+
+ PMVector valueVector( ) const { return m_valueVector; }
+ void setValueVector( const PMVector& v );
+ int octaves( ) const { return m_octaves; }
+ void setOctaves( int c );
+ double omega( ) const { return m_omega; }
+ void setOmega( double c );
+ double lambda( ) const { return m_lambda; }
+ void setLambda( double c );
+
+ PMVector orientation( ) const { return m_orientation;}
+ void setOrientation( const PMVector& v );
+ double distExp( ) const { return m_distExp; }
+ void setDistExp( double c );
+ double majorRadius( ) const { return m_majorRadius; }
+ void setMajorRadius( double c );
+
+
+ /** */
+ virtual void restoreMemento( PMMemento* s );
+private:
+ /**
+ * IDs for @ref PMMementoData
+ */
+ enum PMWarpMementoID { PMWarpTypeID, PMDirectionID, PMOffsetID, PMFlipID,
+ PMLocationID, PMRadiusID, PMStrengthID, PMFalloffID,
+ PMInverseID, PMRepeatID, PMTurbulenceID,
+ PMValueVectorID, PMOctavesID, PMOmegaID, PMLambdaID,
+ PMOrientationID, PMDistExpID, PMMajorRadiusID };
+
+ PMWarpType m_warpType;
+
+ // Repeat variables
+ PMVector m_direction;
+ PMVector m_offset;
+ PMVector m_flip;
+
+ // Black Hole variables
+ PMVector m_location;
+ double m_radius;
+ double m_strength;
+ double m_falloff;
+ bool m_inverse;
+ PMVector m_repeat;
+ PMVector m_turbulence;
+
+ // Turbulence variables
+ PMVector m_valueVector;
+ int m_octaves;
+ double m_omega;
+ double m_lambda;
+
+ // Mapping variables
+ PMVector m_orientation;
+ double m_distExp;
+ double m_majorRadius;
+
+ static PMMetaObject* s_pMetaObject;
+};
+
+#endif
diff --git a/kpovmodeler/pmwarpedit.cpp b/kpovmodeler/pmwarpedit.cpp
new file mode 100644
index 00000000..99c620dd
--- /dev/null
+++ b/kpovmodeler/pmwarpedit.cpp
@@ -0,0 +1,407 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#include "pmwarpedit.h"
+#include "pmwarp.h"
+#include "pmvectoredit.h"
+#include "pmlineedits.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+#include <kdialog.h>
+
+
+PMWarpEdit::PMWarpEdit( QWidget* parent, const char* name )
+ : Base( parent, name )
+{
+ m_pDisplayedObject = 0;
+}
+
+void PMWarpEdit::createTopWidgets( )
+{
+ QHBoxLayout* hl;
+ QVBoxLayout* vl;
+ QGridLayout* gl;
+
+ Base::createTopWidgets( );
+
+ QLabel* label = new QLabel( i18n( "Warp type:" ), this );
+ m_pWarpTypeEdit = new QComboBox( false, this );
+ m_pWarpTypeEdit->insertItem( i18n( "Repeat" ) );
+ m_pWarpTypeEdit->insertItem( i18n( "Black Hole" ) );
+ m_pWarpTypeEdit->insertItem( i18n( "Turbulence" ) );
+ m_pWarpTypeEdit->insertItem( i18n( "Cylindrical" ) );
+ m_pWarpTypeEdit->insertItem( i18n( "Spherical" ) );
+ m_pWarpTypeEdit->insertItem( i18n( "Toroidal" ) );
+ m_pWarpTypeEdit->insertItem( i18n( "Planar" ) );
+ hl = new QHBoxLayout( topLayout( ) );
+ hl->addWidget( label );
+ hl->addWidget( m_pWarpTypeEdit );
+ hl->addStretch( 1 );
+
+ /* Repeat Warp Objects */
+ m_pRepeatWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pRepeatWidget, 0, KDialog::spacingHint( ) );
+ gl = new QGridLayout( vl, 3, 2 );
+ m_pDirectionLabel = new QLabel( i18n( "Direction:" ), m_pRepeatWidget );
+ m_pDirectionEdit = new PMVectorEdit( "x", "y", "z", m_pRepeatWidget );
+ gl->addWidget( m_pDirectionLabel, 0, 0 );
+ gl->addWidget( m_pDirectionEdit, 0, 1 );
+ m_pOffsetLabel = new QLabel( i18n( "Offset:" ), m_pRepeatWidget );
+ m_pOffsetEdit = new PMVectorEdit( "x", "y", "z", m_pRepeatWidget );
+ gl->addWidget( m_pOffsetLabel, 1, 0 );
+ gl->addWidget( m_pOffsetEdit, 1, 1 );
+ m_pFlipLabel = new QLabel( i18n( "Flip:" ), m_pRepeatWidget );
+ m_pFlipEdit = new PMVectorEdit( "x", "y", "z", m_pRepeatWidget );
+ gl->addWidget( m_pFlipLabel, 2, 0 );
+ gl->addWidget( m_pFlipEdit, 2, 1 );
+
+ /* Black Hole Warp Objects */
+ m_pBlackHoleWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pBlackHoleWidget, 0, KDialog::spacingHint( ) );
+ m_pLocationLabel = new QLabel( i18n( "Location:" ), m_pBlackHoleWidget );
+ m_pLocationEdit = new PMVectorEdit( "x", "y", "z", m_pBlackHoleWidget );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( m_pLocationLabel );
+ hl->addWidget( m_pLocationEdit );
+ m_pRadiusLabel = new QLabel( i18n( "Radius:" ), m_pBlackHoleWidget );
+ m_pRadiusEdit = new PMFloatEdit( m_pBlackHoleWidget );
+ m_pStrengthLabel = new QLabel( i18n( "Strength:" ), m_pBlackHoleWidget );
+ m_pStrengthEdit = new PMFloatEdit( m_pBlackHoleWidget );
+ m_pFalloffLabel = new QLabel( i18n( "Falloff:" ), m_pBlackHoleWidget );
+ m_pFalloffEdit = new PMFloatEdit( m_pBlackHoleWidget );
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 3, 2 );
+ gl->addWidget( m_pRadiusLabel, 0, 0 );
+ gl->addWidget( m_pRadiusEdit, 0, 1 );
+ gl->addWidget( m_pStrengthLabel, 1, 0 );
+ gl->addWidget( m_pStrengthEdit, 1, 1 );
+ gl->addWidget( m_pFalloffLabel, 2, 0 );
+ gl->addWidget( m_pFalloffEdit, 2, 1 );
+ hl->addStretch( 1 );
+
+ m_pRepeatLabel = new QLabel( i18n( "Repeat:" ), m_pBlackHoleWidget );
+ m_pRepeatEdit = new PMVectorEdit( "x", "y", "z", m_pBlackHoleWidget );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( m_pRepeatLabel );
+ hl->addWidget( m_pRepeatEdit );
+ m_pTurbulenceLabel = new QLabel( i18n( "Turbulence:" ), m_pBlackHoleWidget );
+ m_pTurbulenceEdit = new PMVectorEdit( "x", "y", "z", m_pBlackHoleWidget );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( m_pTurbulenceLabel );
+ hl->addWidget( m_pTurbulenceEdit );
+ m_pInverseEdit = new QCheckBox( i18n( "Inverse" ), m_pBlackHoleWidget );
+ vl->addWidget( m_pInverseEdit );
+
+ /* Turbulence Warp Objects */
+ m_pTurbulenceWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pTurbulenceWidget, 0, KDialog::spacingHint( ) );
+ m_pValueVectorLabel = new QLabel( i18n( "Value:" ), m_pTurbulenceWidget );
+ m_pValueVectorEdit = new PMVectorEdit( "x", "y", "z", m_pTurbulenceWidget );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( m_pValueVectorLabel );
+ hl->addWidget( m_pValueVectorEdit );
+
+ hl = new QHBoxLayout( vl );
+ gl = new QGridLayout( hl, 3, 2 );
+ m_pOctavesLabel = new QLabel( i18n( "Octaves:" ), m_pTurbulenceWidget );
+ m_pOctavesEdit = new PMIntEdit( m_pTurbulenceWidget );
+ gl->addWidget( m_pOctavesLabel, 0, 0 );
+ gl->addWidget( m_pOctavesEdit, 0, 1 );
+ m_pOmegaLabel = new QLabel( i18n( "Omega:" ), m_pTurbulenceWidget );
+ m_pOmegaEdit = new PMFloatEdit( m_pTurbulenceWidget );
+ gl->addWidget( m_pOmegaLabel, 1, 0 );
+ gl->addWidget( m_pOmegaEdit, 1, 1 );
+ m_pLambdaLabel = new QLabel( i18n( "Lambda:" ), m_pTurbulenceWidget );
+ m_pLambdaEdit = new PMFloatEdit( m_pTurbulenceWidget );
+ gl->addWidget( m_pLambdaLabel, 2, 0 );
+ gl->addWidget( m_pLambdaEdit, 2, 1 );
+ hl->addStretch( 1 );
+
+ /* Mapping Warp Objects */
+ m_pMappingWidget = new QWidget( this );
+ vl = new QVBoxLayout( m_pMappingWidget, 0, KDialog::spacingHint( ) );
+ label = new QLabel( i18n( "Orientation:" ), m_pMappingWidget );
+ m_pOrientationEdit = new PMVectorEdit( "x", "y", "z", m_pMappingWidget );
+ hl = new QHBoxLayout( vl );
+ hl->addWidget( label );
+ hl->addWidget( m_pOrientationEdit );
+
+ gl = new QGridLayout( vl, 2, 2 );
+ label = new QLabel( i18n( "Distance exponent:" ), m_pMappingWidget );
+ m_pDistExpEdit = new PMFloatEdit( m_pMappingWidget );
+ gl->addWidget( label, 0, 0 );
+ gl->addWidget( m_pDistExpEdit, 0, 1 );
+ m_pMajorRadiusLabel = new QLabel( i18n( "Major radius:" ), m_pMappingWidget );
+ m_pMajorRadiusEdit = new PMFloatEdit( m_pMappingWidget );
+ gl->addWidget( m_pMajorRadiusLabel, 1, 0 );
+ gl->addWidget( m_pMajorRadiusEdit, 1, 1 );
+
+ vl = new QVBoxLayout( topLayout( ) );
+ vl->addSpacing( 0 );
+ vl->addWidget( m_pRepeatWidget );
+ vl->addWidget( m_pBlackHoleWidget );
+ vl->addWidget( m_pTurbulenceWidget );
+ vl->addWidget( m_pMappingWidget );
+
+ connect( m_pWarpTypeEdit, SIGNAL( activated( int ) ), SLOT( slotComboChanged( int ) ) );
+ connect( m_pDirectionEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOffsetEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFlipEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pLocationEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRadiusEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pStrengthEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pFalloffEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pInverseEdit, SIGNAL( clicked( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pRepeatEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pTurbulenceEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pValueVectorEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOctavesEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOmegaEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pLambdaEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pOrientationEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pDistExpEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+ connect( m_pMajorRadiusEdit, SIGNAL( dataChanged( ) ), SIGNAL( dataChanged( ) ) );
+}
+
+void PMWarpEdit::displayObject( PMObject* o )
+{
+ if( o->isA( "Warp" ) )
+ {
+ bool readOnly = o->isReadOnly( );
+ m_pDisplayedObject = ( PMWarp* ) o;
+
+ switch( m_pDisplayedObject->warpType( ) )
+ {
+ case PMWarp::Repeat:
+ m_pWarpTypeEdit->setCurrentItem( 0 );
+ slotComboChanged( 0 );
+ break;
+ case PMWarp::BlackHole:
+ m_pWarpTypeEdit->setCurrentItem( 1 );
+ slotComboChanged( 1 );
+ break;
+ case PMWarp::Turbulence:
+ m_pWarpTypeEdit->setCurrentItem( 2 );
+ slotComboChanged( 2 );
+ break;
+ case PMWarp::Cylindrical:
+ m_pWarpTypeEdit->setCurrentItem( 3 );
+ slotComboChanged( 3 );
+ break;
+ case PMWarp::Spherical:
+ m_pWarpTypeEdit->setCurrentItem( 4 );
+ slotComboChanged( 4 );
+ break;
+ case PMWarp::Toroidal:
+ m_pWarpTypeEdit->setCurrentItem( 5 );
+ slotComboChanged( 5 );
+ break;
+ case PMWarp::Planar:
+ m_pWarpTypeEdit->setCurrentItem( 6 );
+ slotComboChanged( 6 );
+ break;
+ }
+ m_pDirectionEdit->setVector( m_pDisplayedObject->direction( ) );
+ m_pDirectionEdit->setReadOnly( readOnly );
+ m_pOffsetEdit->setVector( m_pDisplayedObject->offset( ) );
+ m_pOffsetEdit->setReadOnly( readOnly );
+ m_pFlipEdit->setVector( m_pDisplayedObject->flip( ) );
+ m_pFlipEdit->setReadOnly( readOnly );
+ m_pLocationEdit->setVector( m_pDisplayedObject->location( ) );
+ m_pLocationEdit->setReadOnly( readOnly );
+ m_pRadiusEdit->setValue( m_pDisplayedObject->radius( ) );
+ m_pRadiusEdit->setReadOnly( readOnly );
+ m_pStrengthEdit->setValue( m_pDisplayedObject->strength( ) );
+ m_pStrengthEdit->setReadOnly( readOnly );
+ m_pFalloffEdit->setValue( m_pDisplayedObject->falloff( ) );
+ m_pFalloffEdit->setReadOnly( readOnly );
+ m_pInverseEdit->setChecked( m_pDisplayedObject->inverse( ) );
+ m_pInverseEdit->setEnabled( !readOnly );
+ m_pRepeatEdit->setVector( m_pDisplayedObject->repeat( ) );
+ m_pRepeatEdit->setReadOnly( readOnly );
+ m_pTurbulenceEdit->setVector( m_pDisplayedObject->turbulence( ) );
+ m_pTurbulenceEdit->setReadOnly( readOnly );
+ m_pValueVectorEdit->setVector( m_pDisplayedObject->valueVector( ) );
+ m_pValueVectorEdit->setReadOnly( readOnly );
+ m_pOctavesEdit->setValue( m_pDisplayedObject->octaves( ) );
+ m_pOctavesEdit->setReadOnly( readOnly );
+ m_pOmegaEdit->setValue( m_pDisplayedObject->omega( ) );
+ m_pOmegaEdit->setReadOnly( readOnly );
+ m_pLambdaEdit->setValue( m_pDisplayedObject->lambda( ) );
+ m_pLambdaEdit->setReadOnly( readOnly );
+ m_pOrientationEdit->setVector( m_pDisplayedObject->orientation( ) );
+ m_pOrientationEdit->setReadOnly( readOnly );
+ m_pDistExpEdit->setValue( m_pDisplayedObject->distExp( ) );
+ m_pDistExpEdit->setReadOnly( readOnly );
+ m_pMajorRadiusEdit->setValue( m_pDisplayedObject->majorRadius( ) );
+ m_pMajorRadiusEdit->setReadOnly( readOnly );
+
+ Base::displayObject( o );
+ }
+ else
+ kdError( PMArea ) << "PMWarpEdit: Can't display object\n";
+}
+
+void PMWarpEdit::saveContents( )
+{
+ bool mapping = false;
+
+ if( m_pDisplayedObject )
+ {
+ Base::saveContents( );
+ switch( m_pWarpTypeEdit->currentItem( ) )
+ {
+ case 0:
+ m_pDisplayedObject->setWarpType( PMWarp::Repeat );
+ m_pDisplayedObject->setDirection( m_pDirectionEdit->vector( ) );
+ m_pDisplayedObject->setOffset( m_pOffsetEdit->vector( ) );
+ m_pDisplayedObject->setFlip( m_pOffsetEdit->vector( ) );
+ break;
+ case 1:
+ m_pDisplayedObject->setWarpType( PMWarp::BlackHole );
+ m_pDisplayedObject->setLocation( m_pLocationEdit->vector( ) );
+ m_pDisplayedObject->setRadius( m_pRadiusEdit->value( ) );
+ m_pDisplayedObject->setStrength( m_pStrengthEdit->value( ) );
+ m_pDisplayedObject->setFalloff( m_pFalloffEdit->value( ) );
+ m_pDisplayedObject->setInverse( m_pInverseEdit->isChecked( ) );
+ m_pDisplayedObject->setRepeat( m_pRepeatEdit->vector( ) );
+ m_pDisplayedObject->setTurbulence( m_pTurbulenceEdit->vector( ) );
+ break;
+ case 2:
+ m_pDisplayedObject->setWarpType( PMWarp::Turbulence );
+ m_pDisplayedObject->setValueVector( m_pValueVectorEdit->vector( ) );
+ m_pDisplayedObject->setOctaves( m_pOctavesEdit->value( ) );
+ m_pDisplayedObject->setOmega( m_pOmegaEdit->value( ) );
+ m_pDisplayedObject->setLambda( m_pLambdaEdit->value( ) );
+ break;
+ case 3:
+ m_pDisplayedObject->setWarpType( PMWarp::Cylindrical );
+ mapping = true;
+ break;
+ case 4:
+ m_pDisplayedObject->setWarpType( PMWarp::Spherical );
+ mapping = true;
+ break;
+ case 5:
+ m_pDisplayedObject->setWarpType( PMWarp::Toroidal );
+ m_pDisplayedObject->setMajorRadius( m_pMajorRadiusEdit->value( ) );
+ mapping = true;
+ break;
+ case 6:
+ m_pDisplayedObject->setWarpType( PMWarp::Planar );
+ mapping = true;
+ break;
+ }
+
+ if( mapping )
+ {
+ m_pDisplayedObject->setOrientation( m_pOrientationEdit->vector( ) );
+ m_pDisplayedObject->setDistExp( m_pDistExpEdit->value( ) );
+ }
+ }
+}
+
+bool PMWarpEdit::isDataValid( )
+{
+ double x,y,z;
+
+ switch( m_pWarpTypeEdit->currentItem( ) )
+ {
+ case 0:
+ if( !m_pDirectionEdit->isDataValid( ) ||
+ !m_pOffsetEdit->isDataValid( ) ||
+ !m_pFlipEdit->isDataValid( ) )
+ return false;
+ // The direction vector can only have one non-zero component
+ x = m_pDirectionEdit->vector( ).x( );
+ y = m_pDirectionEdit->vector( ).y( );
+ z = m_pDirectionEdit->vector( ).z( );
+ if( ( x && ( y || z ) ) || ( y && ( x || z )) || ( z && ( x || y ) ) )
+ return false;
+ break;
+ case 1:
+ break;
+ case 2:
+ if( !m_pOctavesEdit->isDataValid( ) ||
+ m_pOctavesEdit->value( ) < 1 ||
+ m_pOctavesEdit->value( ) > 10 )
+ return false;
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ if( !m_pOrientationEdit->isDataValid( ) ||
+ !m_pDistExpEdit->isDataValid( ) ||
+ !m_pMajorRadiusEdit->isDataValid( ) )
+ return false;
+ break;
+ }
+ return Base::isDataValid( );
+}
+
+void PMWarpEdit::slotComboChanged( int c )
+{
+ switch ( c )
+ {
+ case 0:
+ m_pRepeatWidget->show( );
+ m_pBlackHoleWidget->hide( );
+ m_pTurbulenceWidget->hide( );
+ m_pMappingWidget->hide( );
+ break;
+ case 1:
+ m_pRepeatWidget->hide( );
+ m_pBlackHoleWidget->show( );
+ m_pTurbulenceWidget->hide( );
+ m_pMappingWidget->hide( );
+ break;
+ case 2:
+ m_pRepeatWidget->hide( );
+ m_pBlackHoleWidget->hide( );
+ m_pTurbulenceWidget->show( );
+ m_pMappingWidget->hide( );
+ break;
+ case 3:
+ case 4:
+ case 6:
+ m_pRepeatWidget->hide( );
+ m_pBlackHoleWidget->hide( );
+ m_pTurbulenceWidget->hide( );
+ m_pMappingWidget->show( );
+ m_pMajorRadiusLabel->hide( );
+ m_pMajorRadiusEdit->hide( );
+ break;
+ case 5:
+ m_pRepeatWidget->hide( );
+ m_pBlackHoleWidget->hide( );
+ m_pTurbulenceWidget->hide( );
+ m_pMappingWidget->show( );
+ m_pMajorRadiusLabel->show( );
+ m_pMajorRadiusEdit->show( );
+ break;
+ }
+ emit dataChanged( );
+ emit sizeChanged( );
+}
+
+#include "pmwarpedit.moc"
diff --git a/kpovmodeler/pmwarpedit.h b/kpovmodeler/pmwarpedit.h
new file mode 100644
index 00000000..1140e3e6
--- /dev/null
+++ b/kpovmodeler/pmwarpedit.h
@@ -0,0 +1,110 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2001 by Luis Carvalho
+ email : lpassos@mail.telepac.pt
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+
+#ifndef PMWARPEDIT_H
+#define PMWARPEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmdialogeditbase.h"
+
+class PMWarp;
+class PMVectorEdit;
+class PMIntEdit;
+class PMFloatEdit;
+class QComboBox;
+class QCheckBox;
+class QLabel;
+
+/**
+ * Dialog edit class for @ref PMWarp.
+ */
+class PMWarpEdit : public PMDialogEditBase
+{
+ Q_OBJECT
+ typedef PMDialogEditBase Base;
+public:
+ /**
+ * Creates a PMWarpEdit with parent and name
+ */
+ PMWarpEdit( QWidget* parent, const char* name = 0 );
+
+ /** */
+ virtual void displayObject( PMObject* o );
+
+ /** */
+ virtual bool isDataValid( );
+protected:
+ /** */
+ virtual void createTopWidgets( );
+ /** */
+ virtual void saveContents( );
+
+protected slots:
+ /** */
+ void slotComboChanged( int c );
+
+private:
+ PMWarp* m_pDisplayedObject;
+ QComboBox* m_pWarpTypeEdit;
+ PMVectorEdit* m_pDirectionEdit;
+ QLabel* m_pDirectionLabel;
+ PMVectorEdit* m_pOffsetEdit;
+ QLabel* m_pOffsetLabel;
+ PMVectorEdit* m_pFlipEdit;
+ QLabel* m_pFlipLabel;
+
+ PMVectorEdit* m_pLocationEdit;
+ QLabel* m_pLocationLabel;
+ PMFloatEdit* m_pRadiusEdit;
+ QLabel* m_pRadiusLabel;
+ PMFloatEdit* m_pStrengthEdit;
+ QLabel* m_pStrengthLabel;
+ PMFloatEdit* m_pFalloffEdit;
+ QLabel* m_pFalloffLabel;
+ QCheckBox* m_pInverseEdit;
+ PMVectorEdit* m_pRepeatEdit;
+ QLabel* m_pRepeatLabel;
+ PMVectorEdit* m_pTurbulenceEdit;
+ QLabel* m_pTurbulenceLabel;
+
+ PMVectorEdit* m_pValueVectorEdit;
+ QLabel* m_pValueVectorLabel;
+ PMIntEdit* m_pOctavesEdit;
+ QLabel* m_pOctavesLabel;
+ PMFloatEdit* m_pOmegaEdit;
+ QLabel* m_pOmegaLabel;
+ PMFloatEdit* m_pLambdaEdit;
+ QLabel* m_pLambdaLabel;
+
+ PMVectorEdit* m_pOrientationEdit;
+ PMFloatEdit* m_pDistExpEdit;
+ PMFloatEdit* m_pMajorRadiusEdit;
+ QLabel* m_pMajorRadiusLabel;
+
+ QWidget* m_pRepeatWidget;
+ QWidget* m_pBlackHoleWidget;
+ QWidget* m_pTurbulenceWidget;
+ QWidget* m_pMappingWidget;
+};
+
+
+#endif
diff --git a/kpovmodeler/pmxmlhelper.cpp b/kpovmodeler/pmxmlhelper.cpp
new file mode 100644
index 00000000..bbb3c32c
--- /dev/null
+++ b/kpovmodeler/pmxmlhelper.cpp
@@ -0,0 +1,160 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmxmlhelper.h"
+
+PMXMLHelper::PMXMLHelper( const QDomElement& e, PMPart* p, PMParser* par,
+ int majorDocumentFormat, int minorDocumentFormat )
+{
+ m_e = e;
+ m_pPart = p;
+ m_pParser = par;
+ m_major = majorDocumentFormat;
+ m_minor = minorDocumentFormat;
+}
+
+bool PMXMLHelper::hasAttribute( const QString& name ) const
+{
+ return m_e.hasAttribute( name );
+}
+
+int PMXMLHelper::intAttribute( const QString& name, int def ) const
+{
+ QString str = m_e.attribute( name );
+ bool ok;
+ int res;
+
+ if( str.isNull( ) )
+ return def;
+ res = str.toInt( &ok );
+ if( ok )
+ return res;
+ return def;
+}
+
+double PMXMLHelper::doubleAttribute( const QString& name, double def ) const
+{
+ QString str = m_e.attribute( name );
+ bool ok;
+ double res;
+
+ if( str.isNull( ) )
+ return def;
+ res = str.toDouble( &ok );
+ if( ok )
+ return res;
+ return def;
+}
+
+bool PMXMLHelper::boolAttribute( const QString& name, bool def ) const
+{
+ QString str = m_e.attribute( name );
+ bool ok;
+ int res;
+
+ if( str.isNull( ) )
+ return def;
+ res = str.toInt( &ok );
+ if( ok )
+ return ( res != 0 );
+ return def;
+}
+
+PMThreeState PMXMLHelper::threeStateAttribute( const QString& name ) const
+{
+ QString str = m_e.attribute( name );
+ bool ok;
+ int res;
+
+ if( str.isNull( ) )
+ return PMUnspecified;
+ res = str.toInt( &ok );
+ if( ok )
+ {
+ if( res == 0 )
+ return PMFalse;
+ else
+ return PMTrue;
+ }
+ return PMUnspecified;
+}
+
+QString PMXMLHelper::stringAttribute( const QString& name, const QString& def ) const
+{
+ return m_e.attribute( name, def );
+}
+
+PMVector PMXMLHelper::vectorAttribute( const QString& name, const PMVector& def ) const
+{
+ QString str = m_e.attribute( name );
+
+ if( str.isNull( ) )
+ return def;
+ else
+ {
+ PMVector v;
+ if( v.loadXML( str ) )
+ return v;
+ }
+ return def;
+}
+
+PMMatrix PMXMLHelper::matrixAttribute( const QString& name, const PMMatrix& def ) const
+{
+ QString str = m_e.attribute( name );
+
+ if( str.isNull( ) )
+ return def;
+ else
+ {
+ PMMatrix m;
+ if( m.loadXML( str ) )
+ return m;
+ }
+ return def;
+}
+
+PMColor PMXMLHelper::colorAttribute( const QString& name, const PMColor& def ) const
+{
+ QString str = m_e.attribute( name );
+
+ if( str.isNull( ) )
+ return def;
+ else
+ {
+ PMColor c;
+ if( c.loadXML( str ) )
+ return c;
+ }
+ return def;
+}
+
+QDomElement PMXMLHelper::extraData( ) const
+{
+ QDomNode c = m_e.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ if( ce.tagName( ) == "extra_data" )
+ return ce;
+ }
+ c = c.nextSibling( );
+ }
+ return QDomElement( );
+}
diff --git a/kpovmodeler/pmxmlhelper.h b/kpovmodeler/pmxmlhelper.h
new file mode 100644
index 00000000..25ae6947
--- /dev/null
+++ b/kpovmodeler/pmxmlhelper.h
@@ -0,0 +1,121 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMXMLHELPER_H
+#define PMXMLHELPER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qdom.h>
+#include <qstring.h>
+
+#include "pmobject.h"
+#include "pmcolor.h"
+#include "pmvector.h"
+#include "pmmatrix.h"
+
+class PMPart;
+class PMParser;
+
+/**
+ * Class for reading attributes out of a @ref QDomElement
+ */
+class PMXMLHelper
+{
+public:
+ /**
+ * Creates a PMXMLHelper for the QDomElement& e
+ */
+ PMXMLHelper( const QDomElement& e, PMPart* p, PMParser* par,
+ int majorDocumentFormat, int minorDocumentFormat );
+ /**
+ * Returns the QDomElement
+ */
+ QDomElement element( ) const { return m_e; }
+
+ /**
+ * Returns true if the element contains the attribute
+ */
+ bool hasAttribute( const QString& name ) const;
+ /**
+ * Reads an integer attribute
+ */
+ int intAttribute( const QString& name, int def ) const;
+ /**
+ * Reads a double attribute
+ */
+ double doubleAttribute( const QString& name, double def ) const;
+ /**
+ * Reads a bool attribute
+ */
+ bool boolAttribute( const QString& name, bool def ) const;
+ /**
+ * Reads a PMThreeState attribute
+ */
+ PMThreeState threeStateAttribute( const QString& name ) const;
+ /**
+ * Reads a string attribute
+ */
+ QString stringAttribute( const QString& name, const QString& def ) const;
+ /**
+ * Reads a vector attribute
+ */
+ PMVector vectorAttribute( const QString& name, const PMVector& def ) const;
+ /**
+ * Reads a matrix attribute
+ */
+ PMMatrix matrixAttribute( const QString& name, const PMMatrix& def ) const;
+ /**
+ * Reads a color attribute
+ */
+ PMColor colorAttribute( const QString& name, const PMColor& def ) const;
+
+ /**
+ * Returns the "extra_data" child element or a null element, if there
+ * is no child element with tag name "extra_data"
+ */
+ QDomElement extraData( ) const;
+
+ /**
+ * Returns a pointer to the part
+ */
+ PMPart* part( ) const { return m_pPart; }
+ /**
+ * Returns a pointer to the parser
+ */
+ PMParser* parser( ) const { return m_pParser; }
+ /**
+ * Returns the documents major format number
+ */
+ int majorDocumentFormat( ) const { return m_major; }
+ /**
+ * Returns the documents minor format number
+ */
+ int minorDocumentFormat( ) const { return m_minor; }
+
+private:
+ QDomElement m_e;
+ PMPart* m_pPart;
+ PMParser* m_pParser;
+ int m_major;
+ int m_minor;
+};
+
+#endif
diff --git a/kpovmodeler/pmxmlparser.cpp b/kpovmodeler/pmxmlparser.cpp
new file mode 100644
index 00000000..520b19c0
--- /dev/null
+++ b/kpovmodeler/pmxmlparser.cpp
@@ -0,0 +1,177 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#include "pmxmlparser.h"
+
+#include <qbuffer.h>
+#include <klocale.h>
+
+#include "pmpart.h"
+#include "pmscene.h"
+#include "pmxmlhelper.h"
+#include "pmprototypemanager.h"
+#include "pmdocumentformat.h"
+#include "pmdebug.h"
+
+PMXMLParser::PMXMLParser( PMPart* part, QIODevice* dev )
+ : PMParser( part, dev )
+{
+ init( );
+}
+
+PMXMLParser::PMXMLParser( PMPart* part, const QByteArray& array )
+ : PMParser( part, array )
+{
+ init( );
+}
+
+void PMXMLParser::init( )
+{
+ m_pDoc = 0;
+ m_majorDocumentFormat = 1;
+ m_minorDocumentFormat = 0;
+}
+
+PMXMLParser::~PMXMLParser( )
+{
+ if( m_pDoc )
+ delete m_pDoc;
+}
+
+bool PMXMLParser::initDocument( )
+{
+ if( !m_pDoc )
+ {
+ m_pDoc = new QDomDocument( "KPOVMODELER" );
+ if( m_pDoc->setContent( m_pDevice ) )
+ return true;
+ else
+ {
+ printError( i18n( "Could not load the documents data!" ) );
+ setFatalError( );
+ return false;
+ }
+ }
+ return true;
+}
+
+void PMXMLParser::topParse( )
+{
+ if( initDocument( ) )
+ {
+ QDomElement e = m_pDoc->documentElement( );
+ // read the format number
+ // assume 1.0 on error
+ QString fstring = e.attribute( "majorFormat", "1" );
+ bool ok = true;
+ int format = fstring.toInt( &ok );
+ if( !ok || ( format < 1 ) )
+ format = 1;
+ m_majorDocumentFormat = format;
+
+ fstring = e.attribute( "minorFormat", "0" );
+ ok = true;
+ format = fstring.toInt( &ok );
+ if( !ok || ( format < 0 ) )
+ format = 0;
+ m_minorDocumentFormat = format;
+
+ if( ( m_majorDocumentFormat > c_majorDocumentFormat )
+ || ( m_majorDocumentFormat == c_majorDocumentFormat )
+ && ( m_minorDocumentFormat > c_minorDocumentFormat ) )
+ printWarning( i18n( "This document was created with a newer version of KPovModeler. "
+ "The whole document may not be loaded correctly." ) );
+
+ if( e.tagName( ) == "objects" )
+ {
+ parseChildObjects( e, 0 );
+ }
+ else if( e.tagName( ) == "scene" )
+ {
+ PMScene* scene = new PMScene( m_pPart );
+ insertChild( scene, 0 );
+ PMXMLHelper hlp( e, m_pPart, this,
+ m_majorDocumentFormat, m_minorDocumentFormat );
+ scene->readAttributes( hlp );
+ parseChildObjects( e, scene );
+ }
+ else
+ {
+ printError( i18n( "Wrong top level tag" ) );
+ setFatalError( );
+ }
+ }
+}
+
+void PMXMLParser::parseChildObjects( QDomElement& e, PMObject* parent )
+{
+ QDomNode c = e.firstChild( );
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ PMPrototypeManager* m = m_pPart->prototypeManager( );
+ PMObject* obj = m->newObject( m->className( ce.tagName( ) ) );
+ if( obj )
+ {
+ PMXMLHelper hlp( ce, m_pPart, this,
+ m_majorDocumentFormat, m_minorDocumentFormat );
+ obj->readAttributes( hlp );
+ if( insertChild( obj, parent ) )
+ {
+ parseChildObjects( ce, obj );
+
+ if( obj->isA( "Declare" ) )
+ checkID( ( PMDeclare* ) obj );
+ }
+ else
+ delete obj;
+ }
+ else if( ce.tagName( ) != "extra_data" )
+ printError( i18n( "Unknown object %1" ).arg( ce.tagName( ) ) );
+ }
+ c = c.nextSibling( );
+ }
+}
+
+
+void PMXMLParser::quickParse( QStringList& list )
+{
+ if( initDocument( ) )
+ {
+ QDomElement e = m_pDoc->documentElement( );
+ if( ( e.tagName( ) == "objects" ) || ( e.tagName( ) == "scene" ) )
+ {
+ QDomNode c = e.firstChild( );
+
+ while( !c.isNull( ) )
+ {
+ if( c.isElement( ) )
+ {
+ QDomElement ce = c.toElement( );
+ QString type = m_pPart->prototypeManager( )->className( ce.tagName( ) );
+ if( !type.isNull( ) )
+ list.append( type );
+ }
+ c = c.nextSibling( );
+ }
+ }
+ else
+ printError( i18n( "Wrong top level tag" ) );
+ }
+}
diff --git a/kpovmodeler/pmxmlparser.h b/kpovmodeler/pmxmlparser.h
new file mode 100644
index 00000000..ca311048
--- /dev/null
+++ b/kpovmodeler/pmxmlparser.h
@@ -0,0 +1,84 @@
+//-*-C++-*-
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2002 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#ifndef PMXMLPARSER_H
+#define PMXMLPARSER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pmparser.h"
+
+/**
+ * Parser that parses kpovmodeler xml code
+ */
+class PMXMLParser : public PMParser
+{
+public:
+ /**
+ * Parser that parses the device
+ */
+ PMXMLParser( PMPart* part, QIODevice* device );
+ /**
+ * Parser that parses the byte array
+ */
+ PMXMLParser( PMPart* part, const QByteArray& array );
+ /**
+ * Deletes the parser
+ */
+ virtual ~PMXMLParser( );
+
+ /**
+ * Quickly scans the top level objects. Appends all top level object
+ * types to the list.
+ */
+ virtual void quickParse( QStringList& list );
+ /**
+ * Returns true, if the parser can quickly scan the top level objects.
+ */
+ virtual bool canQuickParse( ) const { return true; }
+protected:
+ /**
+ * Top level parse function
+ */
+ virtual void topParse( );
+
+private:
+ /**
+ * Inializes the parser
+ */
+ void init( );
+ /**
+ * Initializes the QDomDocument. Returns true if successful.
+ */
+ bool initDocument( );
+
+ /**
+ * Looks for child objects, parses them and appends them to the parent
+ * object. If parent is 0, all objects are appended to the result list.
+ */
+ void parseChildObjects( QDomElement& e, PMObject* parent );
+
+ QDomDocument* m_pDoc;
+ int m_majorDocumentFormat;
+ int m_minorDocumentFormat;
+};
+
+
+#endif
diff --git a/kpovmodeler/povraydocmap.xml b/kpovmodeler/povraydocmap.xml
new file mode 100644
index 00000000..1981abe1
--- /dev/null
+++ b/kpovmodeler/povraydocmap.xml
@@ -0,0 +1,174 @@
+<!DOCTYPE DOCMAP>
+<map>
+ <version number="3.1" index="povuser.htm">
+ <item className="Comment" target="pov159.htm"/>
+ <item className="Declare" target="pov190.htm"/>
+
+ <item className="Translate" target="pov217.htm"/>
+ <item className="Scale" target="pov218.htm"/>
+ <item className="Rotate" target="pov219.htm"/>
+ <item className="PovrayMatrix" target="pov220.htm"/>
+
+ <item className="Camera" target="pov224.htm"/>
+
+ <item className="ObjectLink" target="pov236.htm"/>
+ <item className="Blob" target="pov238.htm"/>
+ <item className="BlobSphere" target="pov238.htm"/>
+ <item className="BlobCylinder" target="pov238.htm"/>
+ <item className="Box" target="pov239.htm"/>
+ <item className="Cone" target="pov240.htm"/>
+ <item className="Cylinder" target="pov241.htm"/>
+ <item className="HeightField" target="pov242.htm"/>
+ <item className="JuliaFractal" target="pov243.htm"/>
+ <item className="Lathe" target="pov244.htm"/>
+ <item className="Prism" target="pov245.htm"/>
+ <item className="Sphere" target="pov246.htm"/>
+ <item className="SuperquadricEllipsoid" target="pov247.htm"/>
+ <item className="SurfaceOfRevolution" target="pov248.htm"/>
+ <item className="Text" target="pov249.htm"/>
+ <item className="Torus" target="pov250.htm"/>
+
+ <item className="BicubicPatch" target="pov252.htm"/>
+ <item className="Disc" target="pov253.htm"/>
+ <item className="Mesh" target="pov254.htm"/>
+ <item className="Polygon" target="pov255.htm"/>
+ <item className="Triangle" target="pov256.htm"/>
+
+ <item className="Plane" target="pov258.htm"/>
+ <item className="Polynom" target="pov259.htm"/>
+
+ <item className="Csg" target="pov261.htm"/>
+
+ <item className="Light" target="pov267.htm"/>
+
+ <item className="ClippedBy" target="pov278.htm"/>
+ <item className="BoundedBy" target="pov279.htm"/>
+ <item className="Material" target="pov280.htm"/>
+
+ <item className="Interior" target="pov285.htm"/>
+
+ <item className="Texture" target="pov292.htm"/>
+ <item className="Pigment" target="pov293.htm"/>
+ <item className="SolidColor" target="pov294.htm"/>
+ <item className="ColorList" target="pov295.htm"/>
+ <item className="ColorMap" target="pov296.htm"/>
+ <item className="PigmentMap" target="pov297.htm"/>
+ <item className="PigmentList" target="pov297.htm"/>
+ <item className="ImageMap" target="pov298.htm"/>
+ <item className="QuickColor" target="pov299.htm"/>
+
+ <item className="Normal" target="pov300.htm"/>
+ <item className="SlopeMap" target="pov301.htm"/>
+ <item className="Slope" target="pov301.htm"/>
+ <item className="NormalMap" target="pov302.htm"/>
+ <item className="NormalList" target="pov302.htm"/>
+ <item className="BumpMap" target="pov303.htm"/>
+
+ <item className="Finish" target="pov304.htm"/>
+
+ <item className="TextureMap" target="pov312.htm"/>
+ <item className="TextureList" target="pov312.htm"/>
+ <item className="MaterialMap" target="pov314.htm"/>
+ <item className="Pattern" target="pov316.htm"/>
+ <item className="BlendMapModifiers" target="pov348.htm"/>
+ <item className="Warp" target="pov354.htm"/>
+
+ <item className="Media" target="pov356.htm"/>
+ <item className="Density" target="pov362.htm"/>
+ <item className="DensityList" target="pov365.htm"/>
+ <item className="DensityMap" target="pov365.htm"/>
+
+ <item className="Background" target="pov369.htm"/>
+ <item className="Fog" target="pov370.htm"/>
+ <item className="SkySphere" target="pov371.htm"/>
+ <item className="Rainbow" target="pov372.htm"/>
+
+ <item className="GlobalSettings" target="pov373.htm"/>
+ </version>
+
+ <version number="3.5" index="index.html">
+ <item className="Comment" target="povdoc_157.html#target_530"/>
+ <item className="Declare" target="povdoc_167.html#target_662"/>
+
+ <item className="Translate" target="povdoc_175.html#target_702"/>
+ <item className="Scale" target="povdoc_175.html#target_703"/>
+ <item className="Rotate" target="povdoc_175.html#target_704"/>
+ <item className="PovrayMatrix" target="povdoc_175.html#target_705"/>
+
+ <item className="Camera" target="povdoc_180.html#target_713"/>
+
+ <item className="ObjectLink" target="pov236.htm"/>
+ <item className="Blob" target="povdoc_187.html#target_752"/>
+ <item className="BlobSphere" target="pov238.htm"/>
+ <item className="BlobCylinder" target="pov238.htm"/>
+ <item className="Box" target="povdoc_187.html#target_765"/>
+ <item className="Cone" target="povdoc_187.html#target_766"/>
+ <item className="Cylinder" target="povdoc_187.html#target_767"/>
+ <item className="HeightField" target="povdoc_187.html#target_768"/>
+ <item className="JuliaFractal" target="povdoc_187.html#target_775"/>
+ <item className="Lathe" target="povdoc_187.html#target_800"/>
+ <item className="Prism" target="povdoc_187.html#target_807"/>
+ <item className="Sphere" target="povdoc_187.html#target_812"/>
+ <item className="SuperquadricEllipsoid" target="povdoc_187.html#target_816"/>
+ <item className="SurfaceOfRevolution" target="povdoc_187.html#target_818"/>
+ <item className="Text" target="povdoc_187.html#target_822"/>
+ <item className="Torus" target="povdoc_187.html#target_824"/>
+
+ <item className="BicubicPatch" target="povdoc_188.html#target_828"/>
+ <item className="Disc" target="povdoc_188.html#target_835"/>
+ <item className="Mesh" target="povdoc_188.html#target_837"/>
+ <item className="Polygon" target="povdoc_188.html#target_848"/>
+ <item className="Triangle" target="povdoc_188.html#target_849"/>
+
+ <item className="Plane" target="povdoc_189.html#target_852"/>
+ <item className="Polynom" target="povdoc_189.html#target_853"/>
+
+ <item className="Csg" target="povdoc_192.html#target_905"/>
+
+ <item className="Light" target="povdoc_193.html#target_914"/>
+
+ <item className="ClippedBy" target="povdoc_195.html#target_970"/>
+ <item className="BoundedBy" target="povdoc_195.html#target_971"/>
+ <item className="Material" target="povdoc_195.html#target_972"/>
+
+ <item className="Interior" target="povdoc_196.html#target_980"/>
+
+ <item className="Texture" target="povdoc_205.html#target_1000"/>
+ <item className="Pigment" target="povdoc_206.html#target_1002"/>
+ <item className="SolidColor" target="povdoc_206.html#target_1003"/>
+ <item className="ColorList" target="povdoc_206.html#target_1004"/>
+ <item className="ColorMap" target="povdoc_206.html#target_1005"/>
+ <item className="PigmentMap" target="povdoc_206.html#target_1007"/>
+ <item className="PigmentList" target="povdoc_206.html#target_1007"/>
+ <item className="ImageMap" target="povdoc_206.html#target_1009"/>
+ <item className="QuickColor" target="povdoc_206.html#target_1019"/>
+
+ <item className="Normal" target="povdoc_207.html#target_1021"/>
+ <item className="SlopeMap" target="povdoc_207.html#target_1022"/>
+ <item className="Slope" target="povdoc_207.html#target_1022"/>
+ <item className="NormalMap" target="povdoc_207.html#target_1025"/>
+ <item className="NormalList" target="povdoc_207.html#target_1025"/>
+ <item className="BumpMap" target="povdoc_207.html#target_1027"/>
+
+ <item className="Finish" target="povdoc_208.html#target_1035"/>
+
+ <item className="TextureMap" target="povdoc_210.html#target_1071"/>
+ <item className="TextureList" target="povdoc_210.html#target_1071"/>
+ <item className="MaterialMap" target="povdoc_210.html#target_1077"/>
+ <item className="Pattern" target="povdoc_216.html#target_1089"/>
+ <item className="BlendMapModifiers" target="povdoc_217.html#target_1143"/>
+ <item className="Warp" target="povdoc_217.html#target_1155"/>
+
+ <item className="Media" target="povdoc_218.html#target_1185"/>
+ <item className="Density" target="povdoc_221.html#target_1202"/>
+ <item className="DensityList" target="povdoc_221.html#target_1206"/>
+ <item className="DensityMap" target="povdoc_221.html#target_1206"/>
+
+ <item className="Background" target="povdoc_224.html#target_1211"/>
+ <item className="Fog" target="povdoc_225.html#target_1212"/>
+ <item className="SkySphere" target="povdoc_226.html#target_1220"/>
+ <item className="Rainbow" target="povdoc_227.html#target_1222"/>
+
+ <item className="GlobalSettings" target="povdoc_234.html#target_1265"/>
+ </version>
+</map>
diff --git a/kpovmodeler/questionmark.png b/kpovmodeler/questionmark.png
new file mode 100644
index 00000000..19eb62d8
--- /dev/null
+++ b/kpovmodeler/questionmark.png
Binary files differ
diff --git a/kpovmodeler/version.h b/kpovmodeler/version.h
new file mode 100644
index 00000000..1fbc1f0c
--- /dev/null
+++ b/kpovmodeler/version.h
@@ -0,0 +1,18 @@
+/*
+**************************************************************************
+ description
+ --------------------
+ copyright : (C) 2000-2003 by Andreas Zehender
+ email : zehender@kde.org
+**************************************************************************
+
+**************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+**************************************************************************/
+
+#define KPOVMODELER_VERSION "1.1.3"